Net Tuts Plus - Building Persist Ant Sticky Notes With Local Storage

  • Upload
    alexl

  • View
    219

  • Download
    0

Embed Size (px)

Citation preview

  • 8/8/2019 Net Tuts Plus - Building Persist Ant Sticky Notes With Local Storage

    1/12

    Andrew Burgess on Aug 10th 2010 with 18 comments

    Tutorial Details

    Topic: JavaScript, HTML5 APIsDifficulty: IntermediateEstimated Completion Time: 45 minutes

    ing Persistant Sticky Notes with Local Storage | Nettuts+ http://net.tutsplus.com/tutorials/html-css-techniques/building-pers

    2 8/10/2010

  • 8/8/2019 Net Tuts Plus - Building Persist Ant Sticky Notes With Local Storage

    2/12

    HTML5 local storage is like cookies on steroids; its incredibly simple to use and yet still so powerful. In thistutorial, Ill show you how to create sticky notes functionality, that allows your users to take persistent noteswhile browsing your site.

    Because of the dynamic nature of this project, there isnt really much to code in the way of regular old semanticmarkup. Well just simulate a web page by putting together some filler content:

    view plaincopy to clipboardprint?

    1.

    2. 3. 4. HTML 5 complete5. 6. 7.

    10.11.12.

    ing Persistant Sticky Notes with Local Storage | Nettuts+ http://net.tutsplus.com/tutorials/html-css-techniques/building-pers

    2 8/10/2010

  • 8/8/2019 Net Tuts Plus - Building Persist Ant Sticky Notes With Local Storage

    3/12

    13. 14. Sample Article Title15. 16.

    Lorem ipsum dolor. . .

    17.18. 19.

    Copyright 2010 Andrew Burgess

    20.

    21. 22.23. 24. 25. 26. 27. 28. 29.30.31.

    There are a few important things to notice here: were including two CSS files: the first one is the simple stylingfor the page, which weve called default.css. Then, weve got a special CSS files for styles relating to oursticky notes; its called stickies.css, and as you can see, it lives in the stickies folder. At the bottom, wereincluding four scripts:

    jQuery, from Googles CDNJQuery UI, from Googles CDNJSON2, from Douglas CrockfordOur own stickies.js, which lives in the stickies directory

    Then, weve got an empty script tag that well use to start the engine a bit later.

    And thats it for HTML!

    The contents ofdefault.css is incredibly simple:

    view plaincopy to clipboardprint?

    body {1.margin:0;2.padding:0;3.background:#ccc;4.font:14px/1.5 "Helvetica Neue", Helvetica, Arial, san-serif;5.

    }6.article, footer, header { display: block; }7.article {8.

    width:880px;9.background:#fff;10.

    ing Persistant Sticky Notes with Local Storage | Nettuts+ http://net.tutsplus.com/tutorials/html-css-techniques/building-pers

    2 8/10/2010

  • 8/8/2019 Net Tuts Plus - Building Persist Ant Sticky Notes With Local Storage

    4/12

    margin:auto;11.padding:40px;12.

    }13.article header {14.

    color:#474747;15.border-bottom:1px solid #47474716.

    }17.article footer {18.

    font-size:90%;19.color:#ccc;20.

    }21.

    Thats it; now, theres the CSS from stickies.css to look after but we dont have that markup yet. So letsstart some JavaScript, and when thats done, well look at the CSS for the sticky notes.

    Heres the skeleton for our JavaScript application:

    view plaincopy to clipboardprint?

    var STICKIES = (function () {1.var initStickies = function () {},2.

    openStickies = function () {},3.createSticky = function (data) {},4.deleteSticky = function (id) {},5.saveSticky = function () {},6.markUnsaved = function () {};7.

    8. return {9.open : openStickies,10.init : initStickies11.

    };12.}());13.

    Weve got a few interesting techniques going on here. First is the self-involking function: it might look likewere assigning a function to the variable STICKIES, but if you look closely at the end of the function, youllsee that were running it right away. As a hintto remind us that this isnt a normal functionwere wrappingthe entire function in parentheses. So, STICKIES isnt a function, its the returned value from that function,which is an object, in this case.

    That brings us to the next technique: closure. Notice that of the six functions we create, only two of them areexposed to the user (really, only one is necessary for the usage were planning; if we wanted to build supportfor creating notes into your website, we could expose the createSticky and deleteSticky). Even though theself-involking function finishes executing before we even use the methods, well be able to use the otherfunctions that weve defined.

    Okay, lets move on to the content of these function.

    ing Persistant Sticky Notes with Local Storage | Nettuts+ http://net.tutsplus.com/tutorials/html-css-techniques/building-pers

    2 8/10/2010

  • 8/8/2019 Net Tuts Plus - Building Persist Ant Sticky Notes With Local Storage

    5/12

    Well start by looking at the initStickies function:

    view plaincopy to clipboardprint?

    var initStickies = function initStickies() {1. $("", {2.text : "+",3."class" : "add-sticky",4.click : function () { createSticky(); }5.

    }).prependTo(document.body);6.initStickies = null;7.

    },8.

    This is pretty simple. Well be using jQuery to create elements quite a bit, and were using some special syntaxin v. 1.4: thats passing an object literal with the specs for the element as a second parameter to the jQueryfunction. Here, were creating a button to create a new note. That mean we need a new div; were setting the

    text to + and giving it a class add-sticky; then, were setting a click handler to call the createStickymethod (its important to call createSticky from inside a function, and not have the click handler call directlyto createSticky; this is because createSticky can take a single parameter, and we dont want that to be theevent object). Finally, were prepending this div to the body. We end by setting initStickies to null; yes,were essentially getting rid of the function that were running. This assures us that this function will only be runonce; we dont want the user of our API to inadvertantly add multiple add note buttons to page.

    Lets move on to the next method, openStickies:

    view plaincopy to clipboardprint?

    openStickies = function openStickies() {1.initStickies && initStickies();2.for (var i = 0; i < localStorage.length; i++) {3.

    createSticky(JSON.parse(localStorage.getItem(localStorage.key(i))));4.}5.

    },6.

    We start by running initStickies but whats with the fancy syntax? Well, youre probably familiar with&& operator: the boolean AND operator. Youd usually use it to check multiple conditions in an if-statement.Heres what it actually does: it evaluates the first expression, and if that comes out true, it will go on to evaluatethe second expression. In this case, ifinitStickies has not been set to null yet, well run the function. Thisavoids the error that would come from trying to run a null variable as a function.

    Next, were looping over each item in localStorage. Heres what we do in that for-loop (from inside to outside):

    localStorage.key() is a great function that returns the key name oflocalStorage value; it takes anumber as a paramter. Its a great way to loop over each item in localStorage.Once we have the key for a stored item, we can pass it to localStorage.getItem() to get its value.

    ing Persistant Sticky Notes with Local Storage | Nettuts+ http://net.tutsplus.com/tutorials/html-css-techniques/building-pers

    2 8/10/2010

  • 8/8/2019 Net Tuts Plus - Building Persist Ant Sticky Notes With Local Storage

    6/12

    Then, we pass that value to JSON.parse(); this comes from Crockfords library. Because were storing afew values for each note, were using JSON.stringify() on the other end to turn an object into a JSONstring, which we store. Here, were converting it from a string back into an object.Finally, we pass that object to createSticky(), which turns it back into a sticky note.

    Now, lets look at that createSticky method.

    view plaincopy to clipboardprint?

    createSticky = function createSticky(data) {1.data = data || { id : +new Date(), top : "40px", left : "40px", text : "Note Here" }2.

    3.return $("", {4.

    "class" : "sticky",5.'id' : data.id6.})7.

    .prepend($("", { "class" : "sticky-header"} )8..append($("", {9.

    "class" : "status-sticky",10.click : saveSticky11.

    }))12..append($("", {13.

    "class" : "close-sticky",14.text : "trash",15.click : function () { deleteSticky($(this).parents(".sticky").attr("id")); }16.

    }))17.)18.

    .append($("", {19.html : data.text,20.contentEditable : true,21."class" : "sticky-content",22.keypress : markUnsaved23.

    }))24..draggable({25.

    handle : "div.sticky-header",26.stack : ".sticky",27.start : markUnsaved,28.stop : saveSticky29.

    })30..css({31.

    position: "absolute",32."top" : data.top,33."left": data.left34.

    })35..focusout(saveSticky)36..appendTo(document.body);37.

    },38.

    Yes, its long, but its not going to be too hard. First, notice that this function takes a data object; as we just saw

    ing Persistant Sticky Notes with Local Storage | Nettuts+ http://net.tutsplus.com/tutorials/html-css-techniques/building-pers

    2 8/10/2010

  • 8/8/2019 Net Tuts Plus - Building Persist Ant Sticky Notes With Local Storage

    7/12

    in openStickies, were passing the stored data to this function. However, if we arent passing in any data (i.e.,were creating a brand new note), well create the default note object. Since all notes have to be created at onepoint, all notes will start with this configuration. Notice that for the note id, were using +new Date(); thatprepended unary plus operator converts the date we get from new date to a number, so this statement results ina number representing the number of milliseconds since January 1, 1970. Obviously, this number will becontinually changing, so its a great way to uniquely identify each note.

    The rest of the function is a long string of chained jQuery methods. Before we go through this, notice that werereturning the result. If we exposed this method to developers using our mirco-API, it would return a referenceto the sticky note div element.

    So, heres whats going on:

    First, we create the div that is the shell of the sticky note. Using that helpful jQuery 1.4 syntax, we give ita class of sticky and the id from the data object.

    Then, we prepend a div to that one; this div gets a class sticky-header. div.sticky-header then getstwo spans appended to it. The first, span.sticky-status , gets a click handler that calls the saveStickyfunction. However, thats actually a hidden feature: this span will display the status of the sticky: savedor unsaved. There will be a few ways the sticky saves its data to localStorage; its possible that the userwill think that clicking unsaved will save the note, so well provide them with that functionality. Thesecond span, span.close-sticky , will be the delete button: when the user clicks it, well remove thesticky from localStorage, via the deleteSticky method. We pass that method the note id.

    Next, were appending another div to the main div.sticky; notice that we set the html property todata.text; when we save the notes text, were using jQuerys html() method, because using text()gets rid of line-breaks. We also set contentEditable:true on this div, because its the content of thenote. As such, it also gets the class sticky-content. Finally, when a key is pressed on this div (meaningthe user is changing the content), we want to mark it as unsaved, so well call that function (which wellmake soon).

    Now, were using the jQuery UI draggable feature to make our sticky note moveable. In our parameterobject, were using the handle property to make our notes only movable from the header bar. The stackproperty is a selector for the draggable elements to want to stack; by setting this, the currently draggednote will always come to the top. Finally, when we start dragging the note, we want to mark it asunsaved (because we have to save its coordinates, too), and when we stop dragging, well save thatsticky.

    ing Persistant Sticky Notes with Local Storage | Nettuts+ http://net.tutsplus.com/tutorials/html-css-techniques/building-pers

    2 8/10/2010

  • 8/8/2019 Net Tuts Plus - Building Persist Ant Sticky Notes With Local Storage

    8/12

    Next, were setting some styles for our div.sticky; we position it absolutely, and then set its top and leftvalues to the ones in the data object. This way, the note will keep its position as well as its content whenwe refresh the page.

    Finally, well set an event handler for when we focusout of the sticky (essentially, click outside it afterclicking inside it): we want to save the sticky. Lastly, well append it to the body. For reference, heresthe html structure that we should have generated:

    view plaincopy to clipboardprint?

    1. 2. 3. trash4. 5. 6.

    Note Here7. 8.9.

    And thats our createSticky function.

    Now we have the deleteSticky function; its really simple:

    view plaincopy to clipboardprint?

    deleteSticky = function deleteSticky(id) {1.

    localStorage.removeItem("sticky-" + id);2. $("#" + id).fadeOut(200, function () { $(this).remove(); });3.},4.

    As you recall, the deleteSticky function takes the id of a note as its parameter.localStorage.removeItem() is the method of the hour: we pass it the key to a locally-stored value to removethat key-value pair (Notice that when we store the note data, were prepending sticky- to the id). Then, wefind the element with the given id, fade it our, and remove it. Note deleted!

    Second-to-last might be the most important method today: saveSticky: this is the glue that makes it all work.

    view plaincopy to clipboardprint?

    saveSticky = function saveSticky() {1.var that = $(this), sticky = (that.hasClass("sticky-status") || that.hasClass("sticky-

    content")) ? that.parents('div.sticky'): that,2.

    obj = {3.id : sticky.attr("id"),4.top : sticky.css("top"),5.

    ing Persistant Sticky Notes with Local Storage | Nettuts+ http://net.tutsplus.com/tutorials/html-css-techniques/building-pers

    2 8/10/2010

  • 8/8/2019 Net Tuts Plus - Building Persist Ant Sticky Notes With Local Storage

    9/12

    left: sticky.css("left"),6.text: sticky.children(".sticky-content").html()7.

    }8.localStorage.setItem("sticky-" + obj.id, JSON.stringify(obj));9.sticky.find(".sticky-status").text("saved");10.

    },11.

    The first line is a bit of resolution: there are three different elements we can call this function from. First, well

    jQuerify this into that; then, if the element has either the sticky-status or sticky-content classes, wellget the parent div.sticky; if it doesnt have either of those classes, then its div.sticky itself, so well justuse that.

    Then, we need to get the values we want to store. As you can see, were getting the id, offset from the top andleft, and the html of the child .sticky-content; remember, were using html() instead oftext() because wewant to keep the line breaks. Then, we use localStorage.setItem to store the data. Remember, it takes twoparameters: the key and the value to store. Since localStorage only stores strings, we use JSON.stringify()to convert the object to a string.

    Lastly, change the sticky status to saved.

    Weve got one last function, which is just a helper function:

    view plaincopy to clipboardprint?

    markUnsaved = function markUnsaved() {1.var that = $(this), sticky = that.hasClass("sticky-content") ? that.parents("div.sticky") : that;2.sticky.find(".sticky-status").text("unsaved");3.

    }4.

    Again, we have to start by resolving the reference to div.sticky; once we do, we can simply find the statusspan and set the text to unsaved.

    Believe it or not, thats all the JavaScript.

    Now that we know what our sticky note markup is, we can style it. Its pretty simple; but look it over, and Illmake a few comments at the end:

    view plaincopy to clipboardprint?

    :focus {1.outline:0;2.

    }3..add-sticky {4.

    cursor: default;5.position:absolute;6.

    ing Persistant Sticky Notes with Local Storage | Nettuts+ http://net.tutsplus.com/tutorials/html-css-techniques/building-pers

    2 8/10/2010

  • 8/8/2019 Net Tuts Plus - Building Persist Ant Sticky Notes With Local Storage

    10/12

    top:1px;7.left:1px;8.font-size:200%;9.background:#000;10.color:#fff;11.border:2px solid #fff;12.border-radius:40px;13.-webkit-border-radius:40px;14.

    -moz-border-radius:40px;15.text-align:center;16.line-height:25px;17.width:30px;18.height:30px;19.

    }20..add-sticky:hover {21.

    background: #474747;22.}23..sticky {24.

    width:300px;25.

    background:#fdfdbe;26.box-shadow:3px 3px 10px rgba(0,0,0,0.45);27.-webkit-box-shadow:3px 3px 10px rgba(0,0,0,0.45);28.-moz-box-shadow:3px 3px 10px rgba(0,0,0,0.45);29.

    }30..sticky-content {31.

    min-height:150px;32.border-left:3px double rgba(238, 150, 122, .75);33.margin-left:30px;34.padding:5px;35.

    }36.

    .sticky-header {37.padding:5px;38.background:#f3f3f3;39.border-bottom:2px solid #fefefe;40.box-shadow:0 3px 5px rgba(0,0,0,0.25);41.-webkit-box-shadow:0 3px 5px rgba(0,0,0,0.25);42.-moz-box-shadow:0 3px 5px rgba(0,0,0,0.25);43.

    }44..sticky-status {45.

    color:#ccc;46.padding:5px;47.

    }48. .close-sticky {49.background:#474747;50.float:rightright;51.cursor:default;52.color:#ececec;53.padding:1px 5px;54.border-radius:20px;55.-webkit-border-radius:20px;56.-moz-border-radius:20px;57.

    }58.

    ing Persistant Sticky Notes with Local Storage | Nettuts+ http://net.tutsplus.com/tutorials/html-css-techniques/building-pers

    12 8/10/2010

  • 8/8/2019 Net Tuts Plus - Building Persist Ant Sticky Notes With Local Storage

    11/12

    There are a few points of interest here:

    Some browsers put an outline around elements with contenteditable=true when youre editing thecontent. We dont want that, so were getting rid of it with our :focus declaration.The Add Sticky button is positioned in the upper-left corner; it looks vaguely similar to the AddDashboard Widget in Mac OS X.Were using the border-radius and box-shadow CSS3 properties (and their appropriate vendor-prefix

    incarnations).Were also using rgba() for our shadow colours. It takes four parameters: the red, greed, and bluecolours, and the alpha (transparency) value.

    Other than that, its just your standard CSS. Heres what a styled note should look like:

    Now that weve made our API, its time to get it started; we can do that from the extra empty script tag in ourindex.html file:

    STICKIES.open();1.

    Well, were done! Heres the final product in action:

    ing Persistant Sticky Notes with Local Storage | Nettuts+ http://net.tutsplus.com/tutorials/html-css-techniques/building-pers

    12 8/10/2010

  • 8/8/2019 Net Tuts Plus - Building Persist Ant Sticky Notes With Local Storage

    12/12

    Thats all Ive got for today; how do you plan to use HTML5 local storage to spice up your web projects? Letme know in the comments!

    ing Persistant Sticky Notes with Local Storage | Nettuts+ http://net.tutsplus.com/tutorials/html-css-techniques/building-pers