Demistifying HTML5 history api (hash push)

There are a lot sites about html5 history api, but most of those sites dont even have a fully working example of how about this api works on the fly, many assumptions are being made on this very topic, but just a few examples worth spending time.

This is the main reason I will try to explain how the history api works:

First of all (and as far as I know) there are two main ways to push a state into the history:

1) by calling window.history.pushState(data, url, title).

2) by setting the window.location.hash property usually this approach is used in single page applications.

In this particular post I’m gonna cover the second option.

Let’s get started:

First things first, binding the popstate:

window.onpopstate = function(event) {
loadContent(window.location.hash, true);
};

/*
What?
=====
This basically wires up the built-in onpopstate event with this anonymous function
which calls our 'loadContent' function with the specified hash (remember the hash
is already on the url, because the back/forward button already placed it there,
and the second parameter is what I call 'isPoppingState' in this case (we're on
the onpopstate event) therefore we're indeed popping the state.
*/

You should place the code above inside the document ready.

Let’s address the missing loadContent function:

function loadContent(hash, isPoppingState) {
if(!isPoppingState) {
window.location.hash = hash;
}

showLoader(function() { processHash(hash, function() {
showPage();
});
});
}

/*
What?
=====
This will set the hash if we're not popping the state (remember setting the hash
is another way to PUSH a state, so if you're setting the hash don't call
`history.pushState`). Then it will call `showLoader` and wait for it's callback,
then it will process the hash and call `showPage` after the `processHash`
callback.
*/

Yes, now you have more missing functions, let’s code them:

function showLoader(done) {
    $('head title').html('Loading...');
    $('div#page').fadeOut(500, function() {
        if(done && typeof(done) === 'function') {
            done();
        }
    });
}

/*
What?
=====
Nevermind.
*/
function processHash(hash, done) {
    var title;
    var content;

    switch(hash) {
        case '':
        case '#index':
            title = Services.IndexService.GetData().Title;
            content = Services.IndexService.GetData().Content;
            break;
        case '#contact':
            title = Services.ContactService.GetData().Title;
            content = Services.ContactService.GetData().Content;
            break;
        default:
            title = 'Page not found!';
            break;
    }

    if(hash === '') {
        hash = '#index';
    }

    $('section:not(' + hash + ')').hide();
    $('section' + hash).show();
    $('head title').html(title);
    $('header h1').html(title);
    $('section' + hash + ' div.content').html(content);

    if(done && typeof(done) === 'function') {
        done();
    }
}

/*
What?
=====
This function will call the corresponding service and fetch the data, after that
it will display, update, hide elements accordingly, at the end it will invoke
its callback if applies.
Did you note the `hash === ''` part, this is just for handling the view since I
need to assume that an empty hash is the index part.
*/
function showPage() {
    $('div#loader').fadeOut(500, function() {
        $('div#page').fadeIn(500);
    });
}

/*
What?
=====
Nevermind.
*/

Okay, now it’s time to mock our services:

Add this to the top of your javascript.

var Services;

And this before any attempt to get data:

Services = new FakeServices();

Yes, you need the FakeServices object, don’t worry, here it is:

var FakeServices = function() {
    var indexService = function() {
        var getData = function() {
            return {
                Title: 'Index',
                Content: 'Welcome to my HTML5 Single Page Application
with History API via hashtag!'
            };
        };

        return {
            GetData: getData
        };
    };

    var contactService = function() {
        var getData = function() {
            return {
                Title: 'Contact',
                Content: 'You can contact me at
esteban[dot]murchio[at]gmail[dot]com.'
            };
        };

        return {
            GetData: getData
        };
    };

    return {
        IndexService: new indexService(),
        ContactService: new contactService()
    };
};

/*
What?
=====
Javascript objects ftw!
*/

If you would like to bind more ways to go back and forth in your history you could to this:

$('button.back').on('click', function() {
    history.back();
});

You might also want to use a global ajax error handler, this could be done like:

$(document).ajaxError(function(event, xhr) {    
    console.log(xhr.status + ': ' + xhr.statusText);
});

Here is the full example: 

http [colon] [slash] [slash] jsbin [dot] com [slash] akizej [slash] 7

How To: Use lambda expressions as method parameter

Today I would like to answer a question I’ve heard many times.

Let’s say you’re building a layered application, so you’d probably have at least three projects: Data, Services and Web. And you want a method in your services to support several selection options.

You might do something like this:

public class EntityService
{
    public ICollection FindByPredicate(Func<Entity, bool> predicate)
    {
        return _context.Entities.Where(predicate).ToList();
    }
}

Now you can do this:

var service = new EntityService();
var entities = service.FindByPredicate(q => q.Field == 1);

Remote Proxy Pattern

Well, the time came for the third specialization I’m going to write about the proxy pattern, in this case is the remote proxy pattern.

It’s role is to provide the client the functionality to interact with an object that it might not be in the client machine, this proxy will inherit from the same interface than the remote object, but it wont have it’s own implementation, it will simply call the remote object. In short, it’s like the web services, when we make a web reference the wsdl file will be created, but it won’t be able to perform any concrete action, because the real object, is somewhere else.

The example will be like this, we will pretend to have a remote service, think about a WCF service, or even a web service, and we’re going to make our method calls to invoke the methods on the proxy, in fact, the proxy’s job is to stand between the real object and the client, not only this kind of proxy, but all. So we’re showing something to the client, but he doesn’t know that we’re calling the real object inside our proxy.

Here is the example, it’s by far the easiest and shortest one about this series of examples about the proxy design pattern.

Step 1: Add a service reference to our project, in this case I’m going to use a public web service, so we right-click our project and select ‘Add Service Reference…’ then we paste this url (http://soatest.parasoft.com/calculator.wsdl), and name our service ‘CalculatorService’.
Thanks to the Parasoft crew for publishing the service.

Step 2: We will code our main method

using System;

namespace Structural.Proxy.Remote
{
    class Program
    {
        static void Main(string[] args)
        {
            CalculatorService.ICalculator calculator = new CalculatorService.CalculatorClient();

            Console.WriteLine(calculator.add(7.3f,6.2f));

            Console.ReadKey();
        }
    }
}

It’s important to mention that we’re coding against a proxy, then the proxy will call the real service operation.

Hope it helps.

Best regards,
Esteban.

Follow

Get every new post delivered to your Inbox.