Ajax Basics: The Purpose of Ajax
Ajax Basics: The Purpose of Ajax
Ajax Basics: The Purpose of Ajax
In this lesson of the Ajax tutorial, you will learn... 1. 2. 3. 4. The Purpose of Ajax. How Ajax Works. How to create cross-browser Ajax. How to send data using Head, Get and Post.
The term AJAX is a pseudo-acronym for "Asynchronous JavaScript And XML," (see footnote) but is now used much more broadly to cover all methods of communicating with a server using JavaScript. As we will see, Ajax (see footnote) is not always asynchronous and does not always involve XML.
(AjaxBasics/Demos/EmployeeAdmin.jsp)
2. When the user chooses an employee, the server returns a new page (FIRST REFRESH)
3. The user can then edit the employee data (e.g, change "Andrew" to "Andy") and submit
the form. The server then returns the new page (SECOND REFRESH).
(AjaxBasics/Demos/EditEmployee.jsp)
4. To get back to the employee list to begin the process of modifying another employee's data, the user would have to click on the "Employee List" link (THIRD REFRESH).
1. Like with the traditional method, the Ajax application shows a list of employees to pick
from. (AjaxBasics/Solutions/EmployeeAdmin.html)
2. When the user chooses an employee, the page doesn't reload. Instead, an Ajax call to the
server is made, the server returns the HTML form and JavaScript is used to display the
3. The user can then edit the form fields. Each time a changed form field loses focus the
change is sent to the server with Ajax, the server-side code updates the data in the database and sends back the updated list of employees to the browser. JavaScript is again
4. The employee list is updated to reflect the changes made. Notice "Andrew" has been
changed to "Andy" in the list. A message is displayed letting the user know that the
All this is accomplished without having to do even one complete refresh. This is the major benefit of Ajax.
Code Explanation This code attempts to create an XMLHttpRequest object using the XMLHttpRequest() constructor. If it succeeds, it writes out "Using XMLHttpRequest Object" to the body of the page. If it fails, it writes out "XMLHttp cannot be created!"
= = = = = = =
var i; for (i=0; i < ieXmlHttpVersions.length; i++) { try { var xmlhttp = new ActiveXObject(ieXmlHttpVersions[i]); document.getElementById("Content").innerHTML="<h1>Using " + ieXmlHttpVersions[i] + "</h1>"; break; } catch (exc) { alert(ieXmlHttpVersions[i] + " not supported."); } } if (typeof xmlhttp == "undefined") document.getElementById("Content").innerHTML="<h1>XMLHttp cannot be created!</h1>"; } </script> </head> <body> <a href="javascript:Start()">Start</a> <div id="Content"></div> </body> </html>
Code Explanation This code creates an array containing the names of all the different versions of Microsoft's XMLHttp ActiveX control, starting with the most recent. It then loops through the array and uses the first available control to create an xmlhttp object. As soon as it finds one, it writes out the version being used to the body of the page. If none of the versions is supported, it writes out "XMLHttp cannot be created!"
So, now that we have an XMLHttpRequest object created, what do we do with it? We use it to make HTTP requests. To do so, we initialize the object with the open() method, which takes three arguments. XMLHttpRequest open() Method Arguments Method Description Request Type String. Usually POST, GET, or HEAD URL String. The URL receiving the request. Boolean. Whether the request should be made asynchronously (true) or Asynchronous synchronously (false). A typical open() method call is shown below.
xmlhttp.open("GET","Demo.xml",true);
Request Types
Although the HTTP specification identifies several methods of HTTP requests (see footnote), the most commonly supported (and used) methods are GET, POST and HEAD. HEAD The HEAD method is the least commonly used of the three; however, for simple requests, it can be all you need. It simply returns the meta-information contained in the HTTP headers. The call would look like this:
xmlhttp.open("HEAD","Demo.jsp",true);
The GET method is used to send information to the server as part of the URL. The server returns the same header information that the HEAD method returns, but it also returns the body of the message (i.e, the content of the page). Any name-value pairs to be processed by the receiving page should be passed along the querystring. The call would look like this:
xmlhttp.open("GET","Demo.jsp?FirstName=Nat&LastName=Dunn",true);
The response would be the same as the response shown for the HEAD method followed by the message body, which would typically be plain text, HTML or XML. Again, the XMLHttpRequest request is sent as follows:
xmlhttp.send(null);
POST The POST method is used to send information as an enclosed entity. The call would look like this:
xmlhttp.open("POST","Demo.jsp",true);
The response header is somewhat different in that it specifies that the returned content is not cacheable. Like with GET, the message body would typically be plain text, HTML or XML. The XMLHttpRequest request is sent as follows:
xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded;"); xmlhttp.send("FirstName=Nat&LastName=Dunn");
As you can see, with POST, we first need to set the content type to "application/x-www-formurlencoded;". This tells the server to expect form data. In the send method, we include namevalue pairs. These name-value pairs are available to the receiving page for processing. Nothing can be sent in this manner with the HEAD and GET methods, which is why null was passed in the previous examples. We'll see later that we can also send data in other formats, such as raw XML, using the POST method.
The xmlhttp object's readyState property holds the current state of the response. There are five possible states (0-4), which are described below. Values of the readyState Property State Description 0 uninitialized 1 loading 2 loaded 3 interactive 4 complete This use of an inline function may be new to you. In JavaScript, functions are first-class objects and can be assigned to variables or properties of other objects. We could also create a named function and assign that function to xmlhttp.onreadystatechange. The following sample file illustrates how the readystatechange event is handled.
Code Explanation The output will look something like this. The actual ready states returned will depend on your
setup. In practice, before doing anything with the xmlhttp response data, we want to make sure the readyState is complete (4), so we put a condition inside our function to check for this:
xmlhttp.onreadystatechange=function() { if (xmlhttp.readyState==4) { //Do something here } }
Now we're ready to do something with the data returned. Before looking at an example, let's take a look at the properties and methods of the xmlhttp object, so we know what's available to us. XMLHttpRequest Object Properties Property Description onreadystatechange Specifies the callback function to be triggered when the ready state changes. readyState Holds the state of the response. responseText Holds the message body as a string. responseXML Holds the message body as an XML object. status Holds the status code returned from the server (e.g, 200 for success, 404 for
XMLHttpRequest Object Properties Description page not found, etc.). statusText Holds the status text returned from the server. XMLHttpRequest Object Methods Method Description abort() Aborts the xmlhttp request. getAllResponseHeaders() Retrieves the values of all the HTTP headers as a string. getResponseHeader(header) Retrieves the value of the specified HTTP header as a string. open(Method,URL,Async) Initializes the XMLHttpRequest object. send(postData) Sends the HTTP request to the server. setRequestHeader(header,value) Specifies the name and value of an HTTP header. Property A common application is to check the status property to make sure that the request was successful and then to output the message body to a div on the HTML page. The following sample file demonstrates this.
Code Explanation This page simply "copies" the response text (xmlhttp.responseText) and "pastes" it into the "Content" div on the page.
In this exercise, you will modify the code from the last demonstration to send data using the POST method. You will need to use the setRequestHeader() method to alert the server to expect form data. 1. Open AjaxBasics/Exercises/UsingXMLHttpRequest-Post.html in your editor. 2. Modify the code to make the request using the POST method shown earlier. 3. Test your solution in a browser.
Write out all the response headers to the end of the same "Content" div. Where is the solution?
In this exercise, you will create a mini-application for displaying and updating employee records. The server-side files are already created and much of the JavaScript is written for you. You will have to finish the Ajax portions of the code. 1. Open AjaxBasics/Exercises/EmployeeList.jsp in your editor and review the code. This page returns a list of the employees as links. When the links are clicked, the GetEmployeeForm() function is called with EmployeeForm.jsp and the EmployeeID as passed parameters. The first generated list item is shown below:
2. <li> 3. <a href="javascript:void(0)" 4. onclick="GetEmployeeForm('EmployeeForm.jsp',1)">Nancy Davolio</a> </li>
5. Open AjaxBasics/Exercises/EmployeeForm.jsp in your editor and review the code. This page returns a form filled out with the data of the employee whose id was passed in over the querystring. To see this, in your browser navigate to AjaxBasics/Exercises/EmployeeForm.jsp?eid=1. The returned code is shown below:
6. <h2>Edit Employee</h2> 7. <form onsubmit="return false"> 8. <table> 9. <tr> 10. <td>First Name:</td> 11. <td> 12. <input type="text" name="FirstName" value="Nancy" onchange="UpdateEmployee('EditEmployee.jsp','FirstName',this.value,1);" /> 13. </td> 14. </tr> 15. <tr> 16. <td>Last Name:</td> 17. <td> 18. <input type="text" name="LastName" value="Davolio" onchange="UpdateEmployee('EditEmployee.jsp','LastName',this.value,1);"/> 19. </td> 20. </tr> 21. <tr> 22. <td>Title:</td> 23. <td> 24. <input type="text" name="Title" value="Sales Representative" onchange="UpdateEmployee('EditEmployee.jsp','Title',this.value,1);"/> 25. </td> 26. </tr> 27. <tr> 28. <td>Extension:</td> 29. <td> 30. <input type="text" name="Extension" value="5467" onchange="UpdateEmployee('EditEmployee.jsp','Extension',this.value,1);" /> 31. </td> 32. </tr> 33. </table> </form>
34. Open AjaxBasics/Exercises/EditEmployee.jsp in your editor and review the code. This page updates the database and redirects to EmployeeForm.jsp so that the form gets returned. 35. Open AjaxBasics/Exercises/Scripts/Ajax.js in your editor and review the code. This page just contains the function for creating the XMLHttpRequest object. The function is called createXHR(). 36. Open AjaxBasics/Exercises/EmployeeAdmin.html for editing. This is where you'll do your work. 1. In the GetEmployeeList() function where the comment is: open an XMLHttpRequest using the POST method. Use the passed in URL. When the state of the request changes, call the Display() method. Send the request. 2. In the Display() function: Set the innerHTML property of OutputDiv to the responseText of the returned xmlhttp object. Test your solution to this piece by opening AjaxBasics/Exercises/EmployeeAdmin.html in your browser. You should see a list of the employees. If you do not, check your GetEmployeeList() and Display() functions. 3. In the GetEmployeeForm() function: Open an XMLHttpRequest using the POST method. Use the passed in URL. Make sure to pass in the EmployeeID as "eid" on the querystring. When the state of the request changes, call the Display() method. Send the request.
4. In the UpdateEmployee() function: Open an XMLHttpRequest using the POST method. Use the passed in URL. Make sure to pass in the EmployeeID as "eid", the field being changed as "field" and the new field value as "value" on the querystring. When the state of the request changes, call the EmployeeUpdated() method. Send the request.
OutputDiv = document.getElementById("FormDiv"); OutputDiv.innerHTML="Loading..."; /* Open an XMLHttpRequest using the POST method. Use the passed in URL. Make sure to pass in the EmployeeID as "eid" on the querystring. When the state of the request changes, call the Display() method. Send the request. */
function UpdateEmployee(URL,FIELD,VALUE,EID) { /* Open an XMLHttpRequest using the POST method. Use the passed in URL. Make sure to pass in the EmployeeID as "eid", the field being changed as "field" and the new field value as "value" on the querystring. When the state of the request changes, call the EmployeeUpdated() method. Send the request. */ } function EmployeeUpdated() { if (xmlhttp.readyState==4 && xmlhttp.status==200) { var MessageDiv = document.getElementById("MessageDiv"); if (xmlhttp.responseText.indexOf("Failed") == 0) { MessageDiv.className = "Warning"; MessageDiv.innerHTML=xmlhttp.responseText; } else { MessageDiv.innerHTML="Updated!"; FadeElem(MessageDiv,255,255,0,255,255,255); setTimeout(function() { GetEmployeeList('EmployeeList.jsp') },"1000"); //Call to GetEmployeeList is delayed to give the database a chance to update. } } } window.onload = function() { GetEmployeeList("EmployeeList.jsp"); } </script> </head> <body> <h1>Employee Administration</h1> <p>Click employee name to modify.</p> <div id="EmployeeList"></div> <div id="FormDiv"></div> <div id="MessageDiv"></div>
</body> </html>