Memories Sample App

The Memories Sample App:

  • Demonstrates typical asynchronous Yahoo! Mail API programming with callbacks.
  • Uses the setData and getData API to remember a user's name and the date when it first 'met' the user.

Try It Out

See Quick Start to learn how to get the full source for this example, install it, and run it in Yahoo! Mail.

config.xml

This config.xml tells Yahoo! Mail to load the app's views/main.html in a dialog when the user clicks on the app's icon.

  1. <?xml version="1.0"?>
  2. <openmail_app_config version="3">
  3. <name>Memories</name>
  4. <description>Memories sample app illustrates persistent per-user storage.</description>
  5. <data/>
  6. <events>
  7. <click>
  8. <action>
  9. <launch>
  10. <view>main.html</view>
  11. <target_zone>dialog</target_zone>
  12. <title>Memories Sample App</title>
  13. <height>400</height>
  14. </launch>
  15. </action>
  16. </click>
  17. </events>
  18. </openmail_app_config>
  19.  
<?xml version="1.0"?>
<openmail_app_config version="3">
  <name>Memories</name>
  <description>Memories sample app illustrates persistent per-user storage.</description>
  <data/>
  <events>
    <click>
      <action>
        <launch>
          <view>main.html</view>
          <target_zone>dialog</target_zone>
          <title>Memories Sample App</title>
          <height>400</height>
        </launch>
      </action>
    </click>
  </events>
</openmail_app_config>
 

views/main.html

This app's one and only view is called main.html to match the value in the config xml above.

  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
  2. <html>
  3. <head>
  4. <title>Memories</title>
  5. <script src="http://mail.yimg.com/nq/om/api/1.1.19/om-min.js"></script>
  6. <script src="/yahoo/mail/assets/memories.js"></script>
  7. </head>
  8.  
  9. <body onload="onLoadFx()">
  10. <!-- We"ll talk to the user by appending text to this div. -->
  11. <div id="message"><p>I think I might have met you before, let me see. . .</p></div>
  12.  
  13. <!-- By default, this div isn"t displayed. If we"ve never met the user,
  14. display it so that they can submit their name. -->
  15. <div id="meet" style="display:none">
  16. <p>What"s your name?</p>
  17. <input id="name"/><button onclick="onJustMet()">Submit</button>
  18. </div>
  19.  
  20. <!--Another div that isn"t displayed by default. We"ll display it if we"ve
  21. met the user before, to give them the option of being forgotten. -->
  22. <p/>
  23. <button id="forget" style="display:none" onclick="onForget()">Forget About Me</button>
  24. </body>
  25. </html>
  26.  
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
       <head>
       <title>Memories</title>
       <script src="http://mail.yimg.com/nq/om/api/1.1.19/om-min.js"></script>
       <script src="/yahoo/mail/assets/memories.js"></script>
       </head>
 
<body onload="onLoadFx()">
    <!-- We"ll talk to the user by appending text to this div. -->
    <div id="message"><p>I think I might have met you before, let me see. . .</p></div>
 
    <!-- By default, this div isn"t displayed. If we"ve never met the user,
    display it so that they can submit their name. -->
    <div id="meet" style="display:none">
        <p>What"s your name?</p>
        <input id="name"/><button onclick="onJustMet()">Submit</button>
    </div>
 
    <!--Another div that isn"t displayed by default. We"ll display it if we"ve
    met the user before, to give them the option of being forgotten. -->
    <p/>
    <button id="forget" style="display:none" onclick="onForget()">Forget About Me</button>
</body>
</html>
 

assets/memories.js

The main view runs code on launch to query by key for the user's name and time they first met. The keys and values are persisted in per-user-per-app storage, which means that the data is specific to this user and this application. Our getData API can be used to retrieve data by key from the per-app-per-user persistent store.

The callback passed to getData is _onGotData, so it will be invoked once the server has responded back with the query results. Assuming non-error response, it will contain the requested keys and their values. If they haven't been set, main.html prompts the user to enter their name and uses the setData API call to save the user's name and the current time.

  1. function onLoadFx() {
  2. messageDiv = document.getElementById("message");
  3.  
  4. // See if we know anything about this user. Try a data fetch.
  5. // The callback handler will catch the data.
  6. openmail.Application.getData(
  7. { keys:["name", "timeWeFirstMet"] }, _onGotData);
  8. }
  9.  
  10. // Async getData callback invoked once it has finished our query.
  11. function _onGotData(response) {
  12. // Check for problems in the response"s error structure.
  13. if(response.error && (response.error != YAHOO.openmail.ERR_NONE)) {
  14. messageDiv.innerHTML += "I'm having technical difficulties with my memory.<p/>" +
  15. "Try again later.<p/>";
  16. return;
  17. }
  18.  
  19. // Access and format the timestamp.
  20. var timeWeFirstMet = response.data.timeWeFirstMet;
  21.  
  22. // Do we have a timestamp for this user?
  23. if(!timeWeFirstMet) {
  24. messageDiv.innerHTML += "Either I've never met you before or I've forgotten " +
  25. "about you. You seem pretty cool, though.";
  26. document.getElementById("meet").style.display = "";
  27. } else {
  28. // We know when and who, so tell them about it.
  29. messageDiv.innerHTML += "<p/>I do remember you, " + response.data.name + "!";
  30. document.getElementById("forget").style.display = "";
  31.  
  32. // Format and display the timestamp for this user.
  33. var now = new Date().getTime();
  34. var MS_PER_DAY = 3600000 * 24;
  35. var daysKnown = Math.floor((now - timeWeFirstMet) / MS_PER_DAY);
  36. if(daysKnown < 1) {
  37. messageDiv.innerHTML += "<p>We met pretty recently.</p>";
  38. } else {
  39. messageDiv.innerHTML += "<p>I met you " + daysKnown + " days ago.</p>";
  40. }
  41. }
  42. }
  43.  
  44. // Handler for when the user submits their name.
  45. function onJustMet() {
  46. var who = document.getElementById("name").value;
  47. var now = new Date().getTime();
  48.  
  49. // Store the data into the user's storage area and register a callback.
  50. openmail.Application.setData( {
  51. keys: {
  52. "name" : who,
  53. "timeWeFirstMet" : now
  54. }
  55. }, _onSetDataResponse);
  56.  
  57. // Message the user.
  58. messageDiv.innerHTML += "<p>I'm trying to remember you for the next time we meet, "
  59. + who + "...</p>";
  60. // Hide the meet-and-greet dialog.
  61. document.getElementById("meet").style.display="none";
  62. }
  63.  
  64. // Handler for when the user clicks the "Forget About Me" button.
  65. function onForget() {
  66. // Hide the forget button and message the user
  67. document.getElementById("forget").style.display="none";
  68. messageDiv.innerHTML += "<p>I'm trying hard to forget you....</p>";
  69.  
  70. // Clear the timestamp for this user and register a callback handler.
  71. openmail.Application.setData( {
  72. keys: {
  73. timeWeFirstMet : ""
  74. }
  75. }, _onForgetResponse);
  76.  
  77. }
  78.  
  79. // Response handler for when we try and store the user's name and timestamp.
  80. function _onSetDataResponse(response) {
  81. if(response.error && (response.error != YAHOO.openmail.ERR_NONE)) {
  82. messageDiv.innerHTML += "<p> setData Storage for the timeWeFirstMet failed</p>";
  83. } else {
  84. messageDiv.innerHTML += "<p> Ok, I got you memorized!</p>";
  85. }
  86. }
  87.  
  88. // Response handler for when we try and null out the user's timestamp.
  89. function _onForgetResponse(response){
  90. if(response.error && (response.error != YAHOO.openmail.ERR_NONE)) {
  91. messageDiv.innerHTML += "<p> setData Storage for clearing timeWeFirstMet failed</p>";
  92. } else {
  93. messageDiv.innerHTML += "<p> Wow, I just totally forgot who you are.</p>";
  94. }
  95. }
  96.  
function onLoadFx() {
    messageDiv = document.getElementById("message");
 
    // See if we know anything about this user. Try a data fetch.
    // The callback handler will catch the data.
    openmail.Application.getData( 
        { keys:["name", "timeWeFirstMet"] }, _onGotData);
}
 
// Async getData callback invoked once it has finished our query.
function _onGotData(response) {
    // Check for problems in the response"s error structure.
    if(response.error && (response.error != YAHOO.openmail.ERR_NONE)) {
        messageDiv.innerHTML += "I'm having technical difficulties with my memory.<p/>" +
                                "Try again later.<p/>";
        return;
    }
 
    // Access and format the timestamp.
    var timeWeFirstMet = response.data.timeWeFirstMet;
 
    // Do we have a timestamp for this user?
    if(!timeWeFirstMet) {
        messageDiv.innerHTML += "Either I've never met you before or I've forgotten " +
                                "about you. You seem pretty cool, though.";
        document.getElementById("meet").style.display = "";
    } else {
        // We know when and who, so tell them about it.
        messageDiv.innerHTML += "<p/>I do remember you, " + response.data.name + "!";
        document.getElementById("forget").style.display = "";
 
        // Format and display the timestamp for this user.
        var now = new Date().getTime();
        var MS_PER_DAY = 3600000 * 24;
        var daysKnown = Math.floor((now - timeWeFirstMet) / MS_PER_DAY);
        if(daysKnown < 1) {
            messageDiv.innerHTML += "<p>We met pretty recently.</p>";
        } else {
            messageDiv.innerHTML += "<p>I met you " + daysKnown + " days ago.</p>";
        }
    }
}
 
// Handler for when the user submits their name.
function onJustMet() {
    var who = document.getElementById("name").value;
    var now = new Date().getTime();
 
    // Store the data into the user's storage area and register a callback.
    openmail.Application.setData( {
        keys: {
            "name" : who,
            "timeWeFirstMet" : now
        }
    }, _onSetDataResponse);
 
    // Message the user.
    messageDiv.innerHTML += "<p>I'm trying to remember you for the next time we meet, "
                         + who + "...</p>";
    // Hide the meet-and-greet dialog.
    document.getElementById("meet").style.display="none";
}
 
// Handler for when the user clicks the "Forget About Me" button.
function onForget() {
    // Hide the forget button and message the user
    document.getElementById("forget").style.display="none";
    messageDiv.innerHTML += "<p>I'm trying hard to forget you....</p>";
 
    // Clear the timestamp for this user and register a callback handler.
    openmail.Application.setData( {
        keys: {
            timeWeFirstMet : ""
        }
    }, _onForgetResponse);
 
}
 
// Response handler for when we try and store the user's name and timestamp.
function _onSetDataResponse(response) {
    if(response.error && (response.error != YAHOO.openmail.ERR_NONE)) {
        messageDiv.innerHTML += "<p> setData Storage for the timeWeFirstMet failed</p>";
    } else {
        messageDiv.innerHTML += "<p> Ok, I got you memorized!</p>";
    }
}
 
// Response handler for when we try and null out the user's timestamp.
function _onForgetResponse(response){
    if(response.error && (response.error != YAHOO.openmail.ERR_NONE)) {
        messageDiv.innerHTML += "<p> setData Storage for clearing timeWeFirstMet failed</p>";
    } else {
        messageDiv.innerHTML += "<p> Wow, I just totally forgot who you are.</p>";
    }
}
 

Note that getData does not consider requested keys that have never been set to be an error. It will respond to such requests with the requested keys' values set to the empty string.