In part one of “Ajaxifying the web, the easy way” I placed much emphasis on how the url can be used to run your javascript. We are going to push the idea further by allowing our links to take parameters. In PHP, Node.js, ASP.NET and in just about any backend technology, the use of parameters is common for retrieving content. I also mentioned in the previous article that it is important to simulate how content is retrieved without AJAX. The reason for this is because it will become easier to create highly reusable scripts if you follow this idea, furthermore it will be easier to create versions of your content which don’t rely on javascript (as it is kind of what we are supposed to be simulating after all). So lets start creating…

2.Create a tool to help handle more complex ajax requests through your URLs. This technique can also be used with the newer but less supported pushState API, instead of using window.location.hash

In the previous article we used javascript native window‘s object property, location.hash, to find out the hash url currently active. This time we are instead gonna call a wrapper function which contains window.location.hash.

I highly recommend wrapping code that you intend to enhance in every javascript project. In this case, by wrapping window.location.hash in a function, we will be able to analyze the returned value and parse it in any way we wish, to return something even more useful. This means for example that we can have urls such as “http://mydomain.com/#myRequestName/parameter1=value/parameter2=value2” translated into an object where the key or main value is “myRequestName” and its parameters are “parameter1,” and “parameter2.” If you are wondering how this will work we are pretty much going to cut our hash value into pieces and then extract these pieces using a couple of basic javascript methods.

1
<a href="http://www.domain.com/#bio/name=Andres/getContactInfo=true/">Andres</a>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
doSomethingAccordingToHashValue(hashContent){
     console.log(hashContent);//View the content returned by our tool
}

window.addEventListener('hashchange',function(){
  //Triggered when hash changed.
  //You may want to use a library like jquery to listen for the hash change to support older versions of IE


  //var valueInHash = window.location.hash;
  //If above link was to be clicked window.location.hash would return
'http://www.domain.com/#bio/name=Andres/getContactInfo=true/'
  var hashContents = getHashContents();//Our new wrapper to replace window.location.hash
  //At this point the getHashContents() won't return anything since we have yet to create the function

  doSomethingAccordingToHashValue(hashContents);
});

Not much above has changed from our code in part I of the tutorial. As you can see the only things we have really changed are the link which now has a unique format to allow us to pass parameters, and our use of window.location.hash which has been commented out and replaced by the function getHashContents().

So now with our new function wrapper getHashContents() we need to create this function and its functionality. This will be a core tool for what we intend to do ultimately.

a. We mentioned the wrapper will let us extend functionality with ease. So lets start by allowing the function to not just grab the window.location.hash, but to also allow us to pass any url in the same format to it. This will make this function work as our special url decoder, whether the urls come from the url bar or whether we pass our own.

1
2
3
4
5
6
7
8
9
10
11
12
13
/*Our function with a parameter to allow us to pass url strings if and when needed */
function getHashContents(hashString){
  if(typeof hashString === "undefined")hashString = window.location.hash;
        //The above if statement will check if we are passing a string otherwise it will just go ahead and get the string from the url bar instead(the typeof keyword is very useful by the way)

  hashString = hashString.substr(1);
        //Using substr above we remove the "#" symbol from the returned string as it serves no purpose for us

        console.log(hashString)
        return hashString;
        //If the url is http://www.domain.com/#bio/name=Andres/getContactInfo=true/ this will return bio/name=Andres/getContactInfo=true/
        //Our tool is obviously not complete, but getting closer
}

b. Lets separate our main value/key/request name, from its parameters. Lets grab that knife and begin splitting.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function getHashContents(hashString){
  if(typeof hashString === "undefined")hashString = window.location.hash;

  hashString = hashString.substr(1);
        /*Comments for the above code removed to keep explanations concise. Modifications added are below*/

        //At this point our hashString is now bio/name=Andres/getContactInfo=true/
       
        hashStringArr = hashString.split('/');
        //In our hashString value you can see that only "/" separates our main value parameters, so we will cut these into an array using javascript's split method.
       
        console.log(hashStringArr);//This time we are outputting hashStringArr instead to the console

        //return hashString;
        return hashStringArr;
        //If the url is http://www.domain.com/#bio/name=Andres/getContactInfo=true/ this will return the split array ['bio','name=Andres','getContactInfo=true']
        //Once again our tool is obviously not complete, but getting closer
}

c. Lets keep cutting and rearranging so our main value is truly separate from its parameters.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
function getHashContents(hashString){
  if(typeof hashString === "undefined")hashString = window.location.hash;

  hashString = hashString.substr(1);
        //Comments for previous code have been removed to keep explanations concise.

        //At this point our hashString is now bio/name=Andres/getContactInfo=true/
        /*New modifications added are below*/
        hashStringArr = hashString.split('/');
        //Our hashStringArr is ['bio','name=Andres','getContactInfo=true'] so lets keep processing it.

        lnk = hashStringArr.shift();
        //The first value in the hashStringArr is our main value
        //Lets use unshift to get this, the first value

  params = hashStringArr.splice(0,hashStringArr.length);
        //We now use hashStringArr.length to know the amount of values we need to splice through.
        //Params now does not include the main value which means we have separated our main value from its parameters
       
       
        console.log({
            lnk : lnk,
            params : params
        });
         //This time we are returning an object to the console.  
         //Now our tool as you can see is coming closer to life, however the params are still in a format that is not very useful.

        return {
            lnk : lnk,
            params : params
        }
        //Since the function returns an object we can use it as a tool to this way
        //getHashContents().lnk or getHashContents().params
        //But as mentioned in the comment above getting the params in this format is not very useful.  
        //The goal is to be able to use the params like getHashContents().params.name to get the parameter.
        //Our parameters need to be an associative array, (object in javascript) to be truly versatile.
}

d. Using the same technique we have already used lets makes those parameters useful. We will loop through them and make those into objects.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
function getHashContents(hashString){
  if(typeof hashString === "undefined")hashString = window.location.hash;

  hashString = hashString.substr(1);
        //Comments for previous code have been removed to keep explanations concise. Modifications added are below

        //At this point our hashString is now bio/name=Andres/getContactInfo=true/
       
        hashStringArr = hashString.split('/');
        //Our hashStringArr is ['bio','name=Andres','getContactInfo=true'] so lets keep processing it.

        lnk = hashStringArr.shift();
  params = hashStringArr.splice(0,hashStringArr.length);
        //Our params are ['name=Andres','getContactInfo=true'];

        /*New modifications added below**/
        var pair= {};
        //The pair object is going to be our object container for our parameters.
        var paramsLn = params.length;//Stores count of how many parameters we have

        if(paramsLn > 0){//If we have parameters then lets fill our pair object with them
    for(var i = 0;i<paramsLn;i++){//Lets loop through our params array items
      var keyVal = params[i].split('=');//Just like we split our url lets split the params values based on the "=" sign.
                        //For example in the array value "name=Andres" we will get the array ['name','Andres'].  In that array then keyVal[0] is 'name', and keyVal[1] is 'Andres'

      pair[keyVal[0]] = keyVal[1];//Here we assign a new property to our pair object
    }
  }
       
        /*By this point we now have have all the data we need and can return an object with all the right data*/

        return {
            mainValue : lnk,
            parameters : pair
        }
        /*The object returned above would then be the same as
         {
            mainValue : 'bio',
            parameters : {
                name : 'Andres',
                getContactInfo : 'true'
            }
        }
       */

}

e. We have now completed our tool for analyzing our links. We can now use it on our Ajax calls.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//Our completed tool
function getHashContents(hashString){
  if(typeof hashString === "undefined")hashString = window.location.hash;

  hashString = hashString.substr(1);

        hashStringArr = hashString.split('/');
        lnk = hashStringArr.shift();
  params = hashStringArr.splice(0,hashStringArr.length);

        var pair= {};
        var paramsLn = params.length;//Stores count of how many parameters we have

        if(paramsLn > 0){
    for(var i = 0;i<paramsLn;i++){
      var keyVal = params[i].split('=');
                        pair[keyVal[0]] = keyVal[1];
    }
  }
       
   return {
      mainValue : lnk,
      parameters : pair
   }
}

With our tool ready, we could then have one small ajax script handling most if not all of our ajax based UI; a reason for which I find working this way scaleable. This works great for mobile apps where you want to create a native app like experience.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
doSomethingAccordingToHashValue(hashContent){
     console.log(hashContent);//View the object returned by our tool
     var scriptName = hashContent.mainValue;//This is passed to the url request in our ajax call
         myParameters = hashContent.parameters;//This is passed as the parameters in our ajax call

     /*This can be used to add a router script or to create an even more powerful framework
       We will just add an ajax call using jQuery to provide an idea as to how this may
       be used.
     */

     
     $.ajax({
       url : '/location/of/my/ajax/scripts/'+scriptName+'.php',
       dataType : 'json',
       data : myParameters,
       success : function(response){
           //We could pass this to a  templating engine, or a template generating script.
           //What you do with the data is up to you
       },
       error : function(response){
           //We need to handle what happens on every error
       }
     });
}

window.addEventListener('hashchange',function(){
  //Triggered when hash in url is changed changed.
  //You may want to use a library like jquery to listen for the hash change to support older versions of IE

  var hashContents = getHashContents();
  doSomethingAccordingToHashValue(hashContents);
});

So we have just now created a very simple script that can help us handle complex tasks. I have used the techniques above to write a small framework which grabs smarty like templates from the server along with data. This framework caches these templates and uses them when the connection is lost, or updates them if there is a connection. With that said on the next part of our tutorial I will show you how to extend upon what we have created, to have our script cache every request. I won’t go in detail into writing a whole caching framework with all the bells and whistles as that would be much beyond the scope of what I can cover in a few articles, however, it will be knowledge that can be applied to creating such a framework as well as just about anything where self updating objects can be used…Ajax or not

I hope you all enjoyed this tutorial. If you missed part one, you may find it here

Share this:

Share this page via Email Share this page via Stumble Upon Share this page via Digg this Share this page via Facebook Share this page via Twitter
If you enjoyed this post, make sure you subscribe to my RSS feed!

Comments RSS and TrackBack Identifier URI ?
Do you want to comment?

2 responses



Comment now!