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

Taking Sammy to the SPA

On February 25, 2013, in JavaScript, Sammy.js, by admin

Web applications are now expected to be as responsive and immersive as desktop applications. In my opinion, Single Page Applications or SPAs are where the web is going and many sites you are already familiar, with such as Gmail, are already there. However writing an application on the web poses some unique concerns. Being on the web, users will expect the forward and back button to work and to be able to bookmark pages. Having a SPA poses some problems since everything is done on a single page. So how do you provide support for back and forward buttons and support for bookmarks? Enter Sammy.js

Benefits of using Sammy.js

  • Bookmarking a “page” in your SPA
  • Forward and back button still work as expected
  • Avoiding Postbacks/Minimal Network traffic, because this is a single page there is no need for the browser to reload the page each time you navigate, so almost all computation is done client side providing a significant speed boost.
  • Avoiding session, because we have actual URLs there is no need for your application to remember where you are, eliminating the need to store the users current state in session or something similar which can be a problem in traditional AJAX sites.

The heart of Sammy.js is allowing you to define routes in your JavaScript very similar to how you set up routes in MVC. The first step is to set up the base route. This is what will be fired when no other route is defined. In order for Sammy to work you must setup the routes right after the DOM is fully loaded before you have any other actions in you JavaScript.

(function ($) { 
    var app = $.sammy('#MainSection', function () { 
        this.get('#/', function (context) {
            DoSomethingHere();
        }); 
    });  

    $(function () { 
        app.run('#/');
    });
})(jQuery);

Above I am defining the main content area of my SPA as MainSection. You can also explicitly define the main content area (see below), but you can just use the short hand as shown above to keep things simple.

this.element_selector = '#MainSection';

After defining the main content area I am defining my default route. So whenever the users navigates to a URL matching www.myapp.com/, www.myapp.com/# or www.myapp.com/default.html/# it will call the DoSomethingHere() method. After defining the default route you must initialize the application. If you do not initialize the application by calling app.run() then the routing engine will not take over and none of your routes will work.

Now let’s try for a little more complex route. I want a URL that will show employees. So I am going to define a route that looks like www.myapp.com/default.html#/Employees. We are going to declare this route right below the default route in the example above.

this.get('#/Employees', function (context) {
   ShowEmployees();
 });

So anytime someone navigates to the URL above it will run the ShowEmployees functions. If you have any experience with the MVC framework this should look very familiar to you. Now if we wanted to continue along those lines and wanted to view a specific employee based on that employee’s ID then we can use the following pattern www.myapp.com/default.html#/Employees/5 and define a route to match.

 this.get('#/Employees/:id', function (context) {
    LoadEmployee(this.params['id']);
 });

The :id tells the routing engine to expect a variable after the ending slash. To access this variable you just call this.params[] and give the name of the variable in quotes and you are ready to use it. So now that we have the routes down how do we actually use it? You simply add an anchor tag to your site that matches a route. The below example shows how you would add a link to view employee number 5:

   <a href="#/Employees/5" >John Doe </a>

When the user clicks the link above, the page life cycle looks something this:

  1. Page navigates to the # anchor on the page (doesn’t actually exist) loads DOM
  2. Sammy.js recognizes the pattern from your defined routes
  3. Your method LoadEmployee gets fired, where you change the main content to display information about John Doe.
    1. Presumably you are making an AJAX call to pull employee data back via JSON, or if you are using an HTML5 compatible site, you can load all your employee data when the user first lands on your site and store everything in local storage. There are pros and cons to each method, but that is out of scope for this post.
  4. After LoadEmployees returns the rest of your JavaScript on the page fires. For example, if you are using JQuery this is when the document.ready function would fire.
  5. Display the rendered page to the user.

In summary, by using Sammy.js you can create and define routes in your single page applications that will allow users to navigate as they normally would on the web without the extra overhead of continuously posting back to the server.

This is cross posted at TCSC.com

Tagged with:  
RVP

I am speaking at the Microsoft Visions Conference

On February 25, 2013, in Azure, HTML5, Speaking, by admin

Mark your calendars now for the Microsoft Visions Conference scheduled on February 20, 2013.

I will be giving a presentation on HTML5 and Azure and how you can leverage the Azure platform to quickly build your HTML5 website using Azure table storage.

There is something for everyone, whether you are a developer, business analyst, or even an executive. This event will be held at the Microsoft office in in Glen Allen, VA.

The Microsoft Visions Conference is sponsored by TCSC, go ahead and register today!

Tagged with: