RVP

HTML5 Localstorage

On May 22, 2013, in HTML5, JavaScript, JQuery, by admin

One of my favorite features of the ‘new’ HTML5 spec is the use of local storage. Local storage is a persistent store in the user’s browser that can save key/value pairs without much overhead. This data is never transferred to the server, it only ever exists locally (hence the name), and can be used for any sort of data storage. There is an upper limit on the amount of data that you can store, and that is dependent on the browser.

Why would I want to use local storage?

As I mentioned before you can use it for any data storage. So there aren’t any real limitations on what you can store. However everything is stored in plain text, and is stored in the browser so you wouldn’t want to put sensitive information in there.

I tend to use local storage for static data that I know that I am going to use over and over again throughout an application, such as look up data. Local storage is very useful when creating single page applications (SPAs) because you can load the data into local storage and never have to go back to the server to grab it. And if this is a site that your users are going to be on a lot they won’t have to go back to the server the next time around to get it since the data is already stored in their browser.

Just a quick word about private browsing. You can still use local storage when in private browsing. However that data is only persistent during the private browsing session. If you stored things in local storage before going into private browsing those will not be available during the private session. Most applications won’t have to worry about this, just something interesting to note.

Usage

In the example below I am going to be using JQuery and a tool called Modernizr in order to make testing for local storage a little bit easier. Modernizr is a JavaScript file that will allow you to test for many different HTML5 and CSS3 features before you try to use them to allow you to fail gracefully. I highly recommend you check it out.

So let’s look at some code

function addLocalStorage(key, value) {
   if (Modernizr.localstorage) {
      localStorage[key] = value;
   }
   else {
      alert("No localstorage");
   }
}

This small function takes in two variables, and adds the value to local storage. As you can see there isn’t a whole lot here. And that is, one reason, why local storage is so nice, because it is so simple to use. As you can see in my if-statement I am testing to see that local storage exists before I try to use it. In actual production code I would have a fail-over to provide the same functionality in either case.

If I already know what I want my key to be I can also implicitly add the property to the localstorage variable. In the example below I am storing an array of different states into a variable named States in local storage.

 localstorage.States = [ 'Active, Inactive, Pending' ];

So where does this actually live. This is a screen shot from Chrome’s developer tools that shows what my local storage looks like
local storage in browser
You can see I have a Key/Value pair for Hello world, and an entry for my different states.

Now that we put things into local storage how do we get it out?

 function readLocalStorage(key) {
    if (Modernizr.localstorage) {
       return localStorage[key];
    }
    else { alert("No LocalStorage"); }
 }

Again, not a whole lot here. Just use the key to get things back out. You can also use the implicitly typed example (localstorage.States).

Summary

  • You can use local storage to quickly and easily store data in the user’s browser
  • Storage is persisted even after browser is closed.
  • Don’t store any sensitive information as everything is stored in plain text.
  • Don’t store volatile data so you don’t have to keep swapping out the information stored there.

This post is also posted over on my company’s blog. Go

Full Code listing

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title></title>
        <script src="scripts/jquery-1.9.0.js"></script>
        <script src="scripts/modernizr-2.6.2.js"></script>
 
 
        <script>
 
            $(document).ready(function () {
 
                $("#btnSave").click(function () {
 
                    var key = $("#txtKey").val();
                    var value = $("#txtValue").val();
 
                    addLocalStorage(key, value);
                    alert("Saved");
                    
                    $("#txtKey").val();
                    $("#txtValue").val();
 
                });
 
                $("#btnGetValue").click(function () {
                    var key = $("#txtKeyForRetrieve").val();
 
                    var value = readLocalStorage(key);
 
                    $("#storageValue").text(value);
 
                });
 
                function addLocalStorage(key, value) {
                    if (Modernizr.localstorage) {
                        localStorage[key] = value;
                    }
                    else {
                        alert("No localstorage");
                    }
                }
 
                function readLocalStorage(key) {
                    if (Modernizr.localstorage) {
                        return localStorage[key];
                    }
                    else { alert("No LocalStorage"); }
                }
            });
 
        </script>
    </head>
    <body>
 
        <section>
            <h2>Save to LocalStorage</h2>
            <p> Key: <br/>
                <input id="txtKey" type="text"/>
            </p>
            <p>
                Value: <br/>
                <input id="txtValue" type="text"/>
            </p>
            <br/>
            <input type="submit" value="Save" id="btnSave"/>
        </section>
 
        <section>
            <h2>Retrieve Localstorage</h2>
            <p> Key: <br/>
                <input id="txtKeyForRetrieve" type="text"/>
            </p>
 
            <div id="storageValue"></div>
                
            <input type="submit" value="Retrieve" id="btnGetValue"/>
        </section>
    </body>
</html>
RVP

HTML5 Web Workers and AJAX

On February 25, 2013, in HTML5, JavaScript, JQuery, by admin

One of the new features in HTML5 allows asynchronous JavaScript operations to happen on the web freeing your UI thread to continue and not lock up the user providing a rich user experience. But how do you use AJAX along with the web workers to post data back to the server? This proves a little more difficult because we are limited to basic JavaScript calls. We can’t use jQuery from within the web worker, so we have to rely on our old friend the XMLHttpRequest.

First let’s start with the basics, calling a web worker. In order to call a web worker you must create a separate JavaScript file to hold all the logic. I have the following code in a JavaScript file named SavePerson.js

   self.addEventListener('message', function (e) {
 
    self.postMessage('Saved person: ' + e.data);
});

In the main body of my JS code I have the following code to call the worker.

var worker = new Worker('/scripts/SavePerson.js');
 
worker.addEventListener('message', function (e) {
    alert(e.data);
});
 
worker.postMessage('James Bond');

As you may have noticed in order to send messages back and forth both the caller and the worker are posting messages back and forth and are listening for the message event. The event contains one parameter ‘e’ which has a data property. This data property can be just simple text or JSON. The caller, in this example, is passing the text “James Bond” to the worker. The worker receives the message and simply prepends the text ‘Saved person: ’ in front of the message and posts that back to the calling thread, who then pops up that message in an alert box.

This is obviously a very simple example and will return almost immediately, with very little lag. So this isn’t something you would generally use web workers for. You would want to use them for long running processes. Something like saving or updating a record doesn’t require the user to wait before it is finished.

I am now going to update my web worker to actually make a call back to my .Net code to do my insert.

self.addEventListener('message', function (e) {
 
    var data = JSON.stringify(e.data);
    
    var req = new XMLHttpRequest();
 
    req.open('POST', '/myHandler.ashx?action=SavePerson', false);
 
    req.setRequestHeader('Content-Type', 'application/json;  charset=utf-8');
    req.onreadystatechange = function () {
        if (req.readyState == 4 && req.status == 200) {
            self.postMessage({ 'Error': 'No', 'Message': 'Save Successful' });
        }    
    }    
    req.send(data);
});

This is a more complex example, so let’s step through one line at a time for those not used to the old school method of making AJAX calls. The first line is the same as our first example where we are listening for the message event. We are then converting the JSON data passed in into a string so can post it back to the server. We then create a new XMLHttpRequest object and open it. This is a post method since we are sending data back to the server. I am posting back to a generic handler named myHandler.ashx, and passing a query string value that is telling my handler what action I wish to take.

The last parameter of the open method is whether or not you want this synchronous or not. Since I am in a web worker which is in a separate thread already from the main UI thread I can wait around for my AJAX call to come back. The next line tells the server that I will be sending JSON back to the server. We are then ready to setup our callback event for the readyStateChange event. The state changes a few times during this process so we must look for the complete state, which is HTTP status of 200 and a ready state of 4 which equates to loaded. Once we have received those codes, we post a message back to the parent saying that there were no errors and the save was successful. The last line is where the post actually happens when we tell the XMLHttpRequest to send the data.

Whew, that was a lot of work for something so simple as calling $.post(“/myhandler.asxh?action=SavePerson”, data, function(){}) in jQuery. This is why jQuery is such a nice tool. Under the hood jQuery is doing the same thing, and since this worker is in a separate thread there is no document.ready function, so we can never initialize the jQuery object. That is why you can’t use it in your workers.

Calling the worker is exactly the same as in the first example except I am sending and receiving a JSON object.

 var person = {     'Name': 'James Bond',
                    'Age': '32',           
                    'Bio': 'Redacted',
                };  

 var worker = new Worker('/scripts/SavePerson.js');
        
        worker.addEventListener('message', function (e) {            
            if (e.data.Error == 'No') {                
                DisplayInfoMessage(e.data.Message);             
            }
            else {                
                DisplayErrorMessage(e.data.Message);
            }            
        });

worker.postMessage(person);        

Summary

  • Web workers allow async JavaScript calls to free up your UI thread
  • You should only use them for long running processes
  • You can pass strings or JSON between worker and caller
  • You can’t use jQuery in your workers
Tagged with:  
RVP

Using Templates to Generate HTML from JSON

On February 25, 2013, in JavaScript, by admin

Instead of generating HTML inside of JavaScript by concatenating strings to form your display code you can use JSRender to apply templates to your JSON objects in order to greatly simplify your code.
As an example I am going to create a simple form that takes in some person information and uses JQuery and JSRender to display it back on the page.

Step 1: Get JSRender

You can find JSRender here from github.

Step 2: Reference the jsrender.js file in your page

    <script src="Script/jsrender.js" type="text/javascript"></script>

Step 3: Create your template

 <script id="PersonTemplate" type="text/x-jsrender">
    <div class="DataRow">
       <div class="Col">{{>FirstName}}</div>
       <div class="Col">{{>LastName}}</div>
       <div class="Col">{{>Suffix}}</div>
       <div class="Col">{{>Gender}}</div>  
    </div>
 </script>

Make sure you give your template an id, set its type to text/x-jsrender, and then declare the template inside of your document.ready function as shown below:

$.templates({
  PersonTemplate: "#PersonTemplate"
});

Step 4 : Fill your JSON Object.

In the example below I am storing all of my entries in the people object.  I am pulling the values from the html form, filling out my row, and adding it to the people object.


var people= [];

$("#btnSave").button().click(function () {
   var person = {
      "FirstName": $("#txtFirstName").val(),
      "LastName": $("#txtLastName").val(),
      "Suffix": $("#txtSuffix").val(),
      "Gender": $("#ddlGender").val()
   };

people.push(person);

Step 5: Apply the template

Applying the template is very simple; you just have to pass the data that you wish to render to the template function, which then gets output as HTML. In the below example I am appending the output to the SavedPeople div.

$("#SavedPeople").text("");
$("#SavedPeople").append($.render.PersonTemplate(people));

The results should look something similar to this:

Fully working example:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
   <title>JSON Templating Example</title>
   <style>
      .DataRow{
         position: relative;
         width: inherit;
         min-width: 650px;
         clear: both;
         margin: 10px;
         height: 1%;         
         overflow: hidden;
      }

      .FormRow{
         position: relative;
         width: inherit;
         min-width: 650px;
         clear: both;
         height: 15px;
         margin: 10px;
      }

      .Col{
         float: left;
         width: 25%;
         height: 100%;
      }

      .headerRow{
         font-size: 11px;         
         font-weight: bold;
         color: Black;
         background-color: #C0E0FF;         
         vertical-align: top;
         border: solid 1px #aaaaaa;
         padding: 5px;
      }

</style>

</head>

<body>

   <form id="form1" runat="server">
      <div>
         <fieldset> <legend>Person</legend>
             <div class="FormRow">
                <div class="Col">First Name</div>
                <div class="Col"> <input id="txtFirstName" type="text" /></div>
             </div>

             <div class="FormRow">
                <div class="Col">Last Name </div>
                <div class="Col"> <input id="txtLastName" type="text" /></div>
             </div>

             <div class="FormRow">
                <div class="Col">Suffix</div>
                <div class="Col"> <input id="txtSuffix" type="text" /></div>
             </div>

             <div class="FormRow">
                <div class="Col">Gender</div>
                <div class="Col">
                   <select id="ddlGender">
                      <option value="male">Male</option>
                      <option value="female">Female</option>

                   </select>
                </div>
             </div>

             <a href="#" id="btnSave">Save</a>

         </fieldset>

         <h2>Saved People</h2>
            <div class="DataRow headerRow">
                <div class="Col">First Name</div>
                <div class="Col">Last Name</div>
                <div class="Col">Suffix</div>
                <div class="Col">Gender</div>
            </div>
            
            <div id="SavedPeople">
                (No People)
            </div>
         </div>

  </form>

  <script src="Script/jquery-1.6.2.js" type="text/javascript"></script>
  <script src="Script/jquery-ui-1.8.18.js" type="text/javascript"></script>
  <script src="Script/jsrender.js" type="text/javascript"></script>
  
  <script>
     $(document).ready(function () {
        $.templates({
           PersonTemplate: "#PersonTemplate"
        });

        var people = [];

        $("#btnSave").button().click(function () {
           var person = {
             "FirstName": $("#txtFirstName").val(),
             "LastName": $("#txtLastName").val(),
             "Suffix": $("#txtSuffix").val(),
             "Gender": $("#ddlGender").val()
           };

           people.push(person);

           $("#SavedPeople").text("");
           $("#SavedPeople").append($.render.PersonTemplate(people));

        });
     });

  </script>

  <script id="PersonTemplate" type="text/x-jsrender">
     <div class="DataRow">
        <div class="Col">{{>FirstName}}</div>
        <div class="Col">{{>LastName}}</div>
        <div class="Col">
           {{if Suffix == ""}}
               
           {{else}}
              {{>Suffix}}
           {{/if}}
        </div>
        <div class="Col">{{>Gender}}</div>  
     </div>

  </script>


</body>
</html>

This post is cross posted at TCSC.com

Tagged with: