Last Updated:

How to write an AJAX Application

Two years ago, AJAX was a curiosity (and the word AJAX itself had not yet been invented). Web applications whose pages are updated on the fly are now the order of the day. On the contrary, without AJAX, it is difficult to imagine some services.

How did regular web applications work? As a rule, the browser responded to the event (clicking on a link or clicking on a button) by sending a request to the server. When a response came from the server, the entire content of the page was completely updated.

One of the problems was that when the content of the page is updated, the Web application enters a new state. Of the previous state information, only the data transmitted in the request is stored. The more accurate information about the previous state of the system is required, the more data needs to be sent in the request.

Another disadvantage is the need to forward duplicate data sets to the client after each event. For example, if the user made a mistake when filling out the form, then instead of a short error message, you have to download the form and all the information entered earlier.

Modern browsers that support W3C DOM standards allow you to take your web application to the next level.

The pattern of interaction remains almost the same. That's just sends a request and receives a response from the server now the script on the client side, and instead of updating the entire page - only part of it is updated (instead of updating, other actions can be taken, for example, the next request is sent).

The web application is distributed, and part of the logic is on the client side, and part is on the server side. Such applications are called the term "AJAX Applications" (the abbreviation stands for Asynchronous Javascript And Xml Applications).

XMLHTTPRequest Object

For asynchronous client-to-server requests, a special object called XMLHTTPRequest is used on the browser side.

Let's list the methods and properties of the object that will be used below:

  • XMLHTTPRequest.open("method", "URL", async, "uname", "pswd") - creates a request to the server.
    • method - type of request, for example, GET
    • URL - The URL of the request, such as http://localhost/file.xml
    • async - if True, then an asynchronous request will be used, that is, the script will continue to execute after the request is sent. Otherwise, the script will wait for a response from the server by freezing the UI.
    • uname, pswd - login and password for simple web authorization.
  • XMLHTTPRequest.send("content") - sends a request to the server. The content value can be the data for the POST request or an empty string.
  • XMLHTTPRequest.onreadystatechange - an event handler that fires on each change in the state of the object. Object states can be as follows:
    • 0 - before the request is sent (uninitialized)
    • 1 - object initialized (loading)
    • 2 - received a response from the server (loaded)
    • 3 - connection to the server actively (interactive)
    • 4 - object has completed its work (complete)
  • XMLHTTPRequest.responseText - Returns the data received from the server as a string.
  • XMLHTTPRequest.responseXML - If the server response came in the form of valid XML, returns an XML DOM object.
  • XMLHTTPRequest.status - Returns the status of the HTTP response as a number. For example, a 404 if the requested page was not found on the server.

Let's consider the use of the object on the example of a simple AJAX-application.

Searchable SELECT field

Suppose we have a table that has about a million records. The user needs to select only one record from the table (one-to-many implementation). User selection is just one step in filling out a large web form.

Naturally, in order for the user to be able to select the desired record from a million, some means of searching for this very record are needed. For example, a simple text search by name.

In a traditional web application, for this purpose, you would have to use a separate page and save the rest of the form data in the user's session, or divide the process of filling out the form into several stages. An AJAX application does not need an additional page.

The record selection will be implemented by using two elements of the Web Form. The first element is a text box where the user enters a keyword. It is sent to the server, and the server returns only those rows from the table that satisfy the search criteria. The server response (in the form of a list) is placed in the SELECT field, in which the user will make the final choice. Therefore, when you submit the entire form to the server, the selected value in the SELECT field will appear as the ID of the record from a large table.

In HTML, it might look like this:

<input type="text"
   onkeyup="lookup(this.value, 'id_select', 
   'http://localhost/cgi-bin/xmlhttp.cgi')" />	
<select id="id_select" name="id_select">
<option selected="selected" value=""></option>
</select>

On any KeyUp event (button squeeze) in the text field, the lookup function ('text', 'id-selecta', 'url') is called.

function lookup(text, select_id, url) {
        // Get the XMLHTTPRequest object
        if(!this.http){
            this.http = get_http();
            this.working = false;
        }
        // Request
        if (!this.working && this.http) {
            varhttp = this.http;
            // If there are less than three in the text field
            // characters - do nothing
            if (text.length <3 ) return;
//add encoded text
                //in the request URL
            url = url + "?text="+encodeURIComponent(text);
      //create a request
            this.http.open("GET", url, true);
            //attach a handler function to the request
            //events
            this.http.onreadystatechange = function() {
// 4 - data is ready for processing
                if (http.readyState == 4) {
                    fill(select_id, http.responseText);
                    this.working = false;
                  }else{
                     // data in the process of receiving,
                     // you can amuse the user
                     //messages
                     // WAIT FOR REPLY
                  }
            }
            this.working = true;
            this.http.send(null);
        }
        if(!this.http){
              alert('Error creating XMLHTTP object!')
        }
    }

As you can see, in the beginning we get an XMLHTTP object using the get_http() function. The search text is then encoded in the URL style and a GET request to the server is generated. The URL of the request in this case will look something like this: http://localhost/cgi-bin/xmlhttp.cgi?text=...

The script on the server, having received the value text, makes a search in the table and sends the result to the client. In the event handler of the XMLHTTP object, when data from the server is received and ready for use, the fill('select_id', 'data') function is called, which populates the SELECT list with the retrieved data.

The get_http() function is a cross-browser implementation of retrieving an XMLHTTP object (each browser produces it differently). Its implementation with comments you can easily find on the Internet, this is, so to speak, an example from the textbook.

function get_http(){
    var xmlhttp;
    /*@cc_on
    @if (@_jscript_version >= 5)
        try {
            xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try {
                xmlhttp = new 
                ActiveXObject("Microsoft.XMLHTTP");
            } catch (E) {
                xmlhttp = false;
            }
        }
    @else
        xmlhttp = false;
    @end @*/
    if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
        try {
            xmlhttp = new XMLHttpRequest();
        } catch (e) {
            xmlhttp = false;
        }
    }
    return xmlhttp;
}

The fill() function receives as input the value of the ID parameter of the SELECT list to be populated, and the data itself obtained from the server.

For simplicity, suppose that we get the data from the server in the form of a table, the fields of which are separated by the tab character 't', and the rows - by the line break 'n':

id1	t	name1	n
id2	t	name2	n
...

Based on the contents of this table, we will populate the SELECT field with OPTION elements.

function fill (select_id, data){
     // SELECT field into a variable as an object
     var select = document.getElementById(select_id);
     // clear SELECT
     select.options.length = 0;
     // if there is no data, do nothing else
     if(data.length == 0) return;
     // in array arr - rows of the received table
     vararr = data.split('n');
     // for each line
     for(var i in arr){
         // in the array val - the fields of the resulting table
         val = arr[i].split('t');
         // add a new OPTION object to our SELECT
         select.options[select.options.length]=
         new Option(val[1], val[0], false, false);
     }
}

Ready. Now, for any web form application, we can implement a similar selection of a value from a multi-million dollar list, which for the user will look like a read of keystrokes. In a local network, the choice is almost instantaneous. In the event of an unstable or low-speed connection to the server, it is also necessary to notify the user that the download of data from the server has not yet been completed. It is also useful to provide means for responding to a disconnection.