Ajax Fundamentals – Part 2

Index | Part 1 | Part 2 | Part 3 | Part 4 | Part 5

2. Ajax Communication

2.1. Handling the Server Response

The XMLHttpRequest object is used to receive the sever response. Two methods are used, namely responseText and responseXML. The responseText method returns text and the responseXML returns an object that can be parsed as a DOM object.

The responseText is limited however its functionality can be enriched when combining it with the innerHTML property. This is a simple method of including dynamic content within the page. The following code is a selected code extract from an example supplied by Foundations of Ajax.


function startRequest()
{
    createXMLHttpRequest();
    xmlHttp.onreadystatechange = handleStateChange;
    xmlHttp.open("GET", "innerHTML.xml", true);
    xmlHttp.send(null);
}
function handleStateChange()
{
    if(xmlHttp.readyState == 4)
    {
        if(xmlHttp.status == 200)
        {
            document.getElementById("results").innerHTML =                 xmlHttp.responseText;
        }
    }
}
</script>
</head>
  <body>
    <form action="#">
      <input type="button" value="Search for Today's Activities" onclick="startRequest();"/>
    </form>
<div id="results"></div>
</body>
</html>

The above example refers to “innerHTML.xml”. This is a document that contains HTML tags that define an HTML table. When handleStateChange executes, an HTML table is embedded between within ‘results’ div tags and a table will be displayed.The innerHTML property is not a standard therefore not all browsers offer the same support. Microsoft Internet Explorer restricts innerHTML property to read only on certain elements. Using the W3C DOM is the preferred method for manipulating the web page. In order to use the W3C DOM the script needs to extract specific data from the server’s response. Selecting data from XML is far simpler than finding the data in plain text. The script can use responseXML to receive a response in XML format.The responseXML method returns an XML object that meets the W3C DOM specification. This standard is supported by most modern browsers. Using the API provided by DOM, the script can traverse the XML document. The following code shows an example of this.


function showArtistAlbums(artist)
{
    var artistname = artist;
    var xmlDoc = req.responseXML;// req is an XMLHttpRequest object
    var node = xmlDoc.getElementsByTagName(artistname)[0];
    var albums = node.getElementsByTagName("album");
    var result = artistname;

    for(var i = 0; i < albums.length; i++)
    {
        result = result + "\n * " + albums&#91;i&#93;.                         childNodes&#91;0&#93;.nodeValue;// Retrieves the text value
    }
}

&#91;/sourcecode&#93;

The objective of Ajax is to modify only relevant parts of a web page without refreshing the entire page.   This eases the load on the web server and provides a better user experience.   Performing these ‘precision updates' is possible by making use of the W3C DOM. <a href="http://www.amazon.com/Foundations-Ajax-Foundation-Ryan-Asleson/dp/1590595823/ref=pd_bbs_sr_1?ie=UTF8&amp;s=books&amp;qid=1207069447&amp;sr=8-1" target="_blank">Foundations of Ajax</a> gives a good example of dynamically appending rows to an HTML table.   A Sample of the code is shown below.   Note that the tbody tag is used, in this case the tbody element has an ID equal to "resultsBody".



function addTableRow(address, price, comments)
{
    var row = document.createElement("tr");
       var cell = createCellWithText(address);
       row.appendChild(cell);
       cell = createCellWithText(price);
       row.appendChild(cell);
       cell = createCellWithText(comments);
       row.appendChild(cell);
       document.getElementById("resultsBody").appendChild(row);
}
function createCellWithText(text)
{
       var cell = document.createElement("td");
       var textNode = document.createTextNode(text);
       cell.appendChild(textNode);
       return cell;
}

2.2. Parsing Parameters in the Request

In order for the server to filter and customise the response, the browser needs to send parameters with the request. A script can include parameters using a scheme that is similar to the ‘GET’ and ‘POST’ techniques used by Hypertext Transfer Protocol (HTTP).

HTTP ‘GET’ and ‘POST’ is common practice. Using ‘GET’ the parameters are included as part of the URL. The parameter list is a name-value pair. This list is appended to the URL by using a question mark [?] and then listing the parameters with the names and values. An ampersand [&] is used to separate the parameters. The parameters are visible in the URL displayed by the browser. Standard server side environments give ease of access to these parameters in the URL. As with ‘GET’, the ‘POST’ method passes the parameters as name-value pairs. The ‘POST’ method embeds the parameter string within the request body thus the parameters are not visible in the URL displayed by the browser.

The benefit of the using ‘GET’ is that users can bookmark pages. This is a desired effect in many standard (non-Ajax) web applications, however it is not always appropriate when using Ajax. The ‘GET’ method restricts the length of the queries, this restriction is dependant on the browser. For these reasons, the ‘POST’ method is most often used when implementing Ajax functionality.

The XMLHttpRequest object differs from HTTP when specifying the method to be used. HTTP uses the HTML form element to specify the ‘GET’ or ‘POST’ method. Using XMLHttpRequest object the script specifies the method when calling the XMLHttpRequest objects open method. The XMLHttpRequest objects open method is shown in Appendix A and a description of using this method is given shortly.

When passing parameters to the server the script needs to build a query string in the correct format e.g.?name1=value1&name2=value2 etc. In traditional applications the browser encodes the form data automatically. When using the XMLHttpRequestObject the script must encode the request parameters. The escape function is built into JavaScript. This function replaces any character that cannot be part of a URL with %HH where HH is the hexadecimal code. Often a timestamp is added as an additional parameter to the query string. This prevents the browser from caching and reusing the results of a request.

In order for a script to send a request using the ‘GET’ method, the script must append the query string to the ‘bare’ URL. The script passes this construct (URL + query string) to the XMLHttpRequest’s open method. The script may send through null as a parameter in the XMLHttpRequest’s send method. Using ‘POST’, the script will not append the query string to the URL used in the XMLHttpRequest’s open method. It will send the query string through as a parameter of the XMLHttpRequest’s send method. Once again the ‘GET’ method exposes the parameters in the URL displayed by the browser and the ‘POST’ method embeds the parameters in the request body. This is shown in the following examples extracted from OpenJS.

Using ‘GET’


// Using the ‘GET’ method
var url = "get_data.php";
var params = "lorem=ipsum&name=binny";
http.open("GET", url+"?"+params, true);
http.onreadystatechange = function()
{   //Call a function when the state changes.
    if(http.readyState == 4 && http.status == 200)
   {
        alert(http.responseText);
   }
}
http.send(null);

Using ‘POST’


var url = "get_data.php";
var params = "lorem=ipsum&name=binny";
http.open("POST", url, true);

//Send the proper header information along with the request
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.setRequestHeader("Content-length", params.length);
http.setRequestHeader("Connection", "close");

http.onreadystatechange = function()
{//Call a function when the state changes.
    if(http.readyState == 4 && http.status == 200)
    {
        alert(http.responseText);
    }
}
http.send(params);

As can be seen in the example, header information needs to be included when using the ‘POST’ method. setRequestHeader(“Content-type”, “application/x-www-form-urlencoded”) informs the server that data is being sent in the format of a form submission. setRequestHeader(“Content-length”, params.length) specifies (in bytes) the length of the post. setRequestHeader(“Connection”, “close”) instructs the server to close the connection after receiving the amount of data specified in the ‘content-length’ header.Using Ajax allows a developer to process larger amounts of data on the client side. Ajax enables a developer to implement the model-view-controller pattern with the model being manipulated within the browser. This technique leads to complex data structures being created on the browser side. These data structures may need to be submitted to the server. When sending complex data structures it is recommended that the data is sent as an XML document. This can be done in a similar way to sending a query string using the ‘POST’ method. Using string concatenation is the most browser neutral method of creating XML documents. Many web developers view this approach as cumbersome. A growing community of developers feel that XML is overly verbose. This has led to the development of JavaScript Object Notation.

2.3. JavaScript Object Notation

JavaScript Object Notation (JSON) is a lightweight data-interchange format. JSON is a subset of standard JavaScript. The JSON website explains that “JSON is a text format that is completely language independent but uses conventions that are familiar to programmers of the C-family of languages, including C, C++, C#, Java, JavaScript, Perl, Python, and many others. These properties make JSON an ideal data-interchange language”. Douglas Crockford (JSON inventor and architect at Yahoo! Inc.) describes JSON as being ‘The Fat Free Alternative to XML’.

JSON has four simple types: strings, numbers, booleans, and null. It is built on two structures:

  • A collection of name/value pairs. In various languages, this is realized as an object, record, struct, dictionary, hash table, keyed list, or associative array
  • An ordered list of values. In most languages, this is realized as an array, vector, list, or sequence

As explained by Developer.com, “Each instance of a JSON document describes one object with nested objects, arrays, strings, numbers, boolean values, or null values”. This example from Developer.com provides a comparison of XML and JSON:

XML


<?xml version='1.0' encoding='UTF-8'?>
<card>
   <fullname>Sean Kelly</fullname>
   <org>SK Consulting</org>
   <emailaddrs>
      <address type='work'>kelly@seankelly.biz</address>
      <address type='home' pref='1'>kelly@seankelly.tv</address>
   </emailaddrs>
   <telephones>
      <tel type='work' pref='1'>+1 214 555 1212</tel>
      <tel type='fax'>+1 214 555 1213</tel>
      <tel type='mobile'>+1 214 555 1214</tel>
   </telephones>
   <addresses>
      <address type='work' format='us'>1234 Main St
         Springfield, TX 78080-1216</address>
      <address type='home' format='us'>5678 Main St
         Springfield, TX 78080-1316</address>
   </addresses>
   <urls>
      <address type='work'>http://seankelly.biz/</address>
      <address type='home'>http://seankelly.tv/</address>
   </urls>
</card>

JSON


{
   "fullname": "Sean Kelly",
   "org": "SK Consulting",
   "emailaddrs": [
      {"type": "work", "value": "kelly@seankelly.biz"},
      {"type": "home", "pref": 1, "value": "kelly@seankelly.tv"}
   ],
    "telephones": [
      {"type": "work", "pref": 1, "value": "+1 214 555 1212"},
      {"type": "fax", "value": "+1 214 555 1213"},
      {"type": "mobile", "value": "+1 214 555 1214"}
   ],
   "addresses": [
      {"type": "work", "format": "us",
       "value": "1234 Main StnSpringfield, TX 78080-1216"},
      {"type": "home", "format": "us",
       "value": "5678 Main StnSpringfield, TX 78080-1316"}
   ],
    "urls": [
      {"type": "work", "value": "http://seankelly.biz/"},
      {"type": "home", "value": "http://seankelly.tv/"}
   ]
}

XML is far more verbose than JSON. The real benefits of JSON come from the parsing. JSON object properties can be accessed using standard do notation. This simplifies the data processing for the developer. Below is sample code showing dot notation:


var employee = {
              "firstName" : John
            , "lastName" : Doe
            , "employeeNumber" : 123
            , "title" : "Accountant"
            }
// Use the object’s properties
var lastName = employee.lastName;      //Access the last name
var title = employee.title;           //Access the title
employee.employeeNumber = 456;       //Change the employee number

In general, JSON is used as default and XML is only used when there is a good reason.

Index | Part 1 | Part 2 | Part 3 | Part 4 | Part 5

Advertisements

6 thoughts on “Ajax Fundamentals – Part 2

  1. Pingback: Ajax Fundamentals - Part 1 « Daryn’s Blog

  2. Pingback: Ajax Fundamentals - About & Index « Daryn’s Blog

  3. Pingback: Ajax Fundamentals - Part 3 « Project Entropy

  4. Pingback: Ajax Fundamentals - Part 4 « Project Entropy

  5. I lately came across your blog and have been reading along. I thought I would leave my first remark. I dont know what to say except that I have relished reading. Solid blog. I will keep visiting this blog very often.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s