jQuery AJAX
AJAX (Asynchronous JavaScript and XML) is a JavaScript-based communication technique between the client (browsers) and the server (web servers) that can be used with other technologies like jQuery, JavaScript, HTML5, and CSS3 to create faster, dynamic, user-friendly, and highly interactive web sites. Conventional web applications are synchronous, which means when users submit a form or send a request for information, they have to wait for the server to complete the process and send the information back to the browser. When the information is received by the browser, the complete page is refreshed with the updated information. In the case of web applications developed using AJAX, while users are working on a web page, data entered by the user or request for the new information is sent to the server seamlessly without any interruption in the workflow. When data is returned from the web server, only a portion of the web page is updated with the new information. Figure 9-1 displays the request and response flow between the client and the server in a conventional web application.
Figure 9-1. Request and response model of a conventional web application
Figure 9-2 displays the request and response flow between the client and the server via jQuery AJAX APIs and the AJAX engine in a web application.
Figure 9-2. Request and response model of the web application using AJAX
The advantages of using AJAX are:
The following are some examples of the web applications using AJAX:
jQuery AJAX methods make the code simpler and the web applications more interactive and dynamic. This chapter covers recipes that use jQuery AJAX-related methods and events to simplify the implementation of AJAX calls and processing of the returned data on the client (browser) side. It covers requesting and receiving the data in the following five formats—plain text, HTML, XML, JSON, and Script.
Since Chrome and Safari browsers have stricter security policies related to accessing local resources and different versions of Internet Explorer behave differently for AJAX calls, it’s best to test all the recipes in this chapter using the Firefox browser. In order to test on other browsers, deploy the code on a web server and then test them. Refer to the Appendix C for deploying web applications on Apache Tomcat and IIS.
You can monitor the content of the request, request header, response, and response header by opening the network tab of the browser’s developer tool or console.
9-1. Using jQuery AJAX API Calls to Get Plain Text Data from the Server
Problem
You want to use jQuery API calls to get plain text data from the server.
Solution
The following is the most commonly used syntax for making a jQuery AJAX API call:
$.ajax(settingsMapObject)
where, settingsMapObject is
{
type: "GET",
url: "requestUrl",
dataType: "text", // html, xml, json
success: successCallbackFunction,
error: errorCallbackFunction
}
function successCallbackFunction(returnedData, status) { ... }
function errorCallbackFunction(request, status, errorMsg) { ... }
The available settings of an AJAX API call are outlined next.
The type Setting
type sets the type of the request (GET or POST) you are making to the server. Communication between clients and servers uses HTTP (Hypertext Transfer Protocol) by initiating requests from clients and getting back responses from servers. GET and POST are two commonly used request methods.
<a href="http://domainName/resource?param1=paramVal1¶m2=paramVal2">
<form method="POST" action="resourceURL">
<!-- Data entry fields HTML form elements -->
</form>
The url Setting
url sets the URL to which you are sending the request and expecting the response back. It can be relative to the current page or an absolute URL path. The URL can be either an absolute or relative path. Generally, the URL contains the resource name, which programmatically gets the data from some source (such as a database, file, business logic, and so on) and sends it back to the client (browser). Since writing server-side code is out of the scope of this book, all the recipes in this chapter use data files to provide the response content to the browser.
If the current page and this URL have different domain names, the browser will throw an error about the cross-domain security. If you want to force a cross-domain request, set the crossDomain setting to true in the ajax() method.
The dataType Setting
The dataType setting sets the type of the data you are expecting back from the server. If it is not specified, the dataType from the Content-type in the response header will be used. The data type of the returnedData (the parameter in the success callback function) will be set as the specified data type.
The following are the commonly used data types:
The success Setting
The success setting specifies which event handler (callback function) to execute when data is returned successfully from the server.
The error Setting
error specifies which event handler (callback function) to execute when there is an error while sending the request or upon getting the response back.
Other ajax() Settings
Some of the other less frequently used settings of the ajax() method include:
Using the ajax() Method
Listing 9-1 demonstrates the use of the jQuery ajax() method to get text from the server and Listing 9-2 shows the employees.txt file.
Listing 9-1. Using the ajax() method to make an AJAX call to the server
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="scripts/jquery-2.1.0.min.js"></script>
<style>
div {
border:3px double green;
width: 300px;
background-color: lightcyan;
}
table {
border:0px;
}
td {
padding-right: 10px;
padding-left: 10px;
}
.header {
font-weight: bold;
background-color: lightgray;
}
.evenRow {
background-color: lightyellow;
}
.oddRow {
background-color: lightblue;
}
.errMsg {
background-color: orange;
color: white;
font-weight: bold;
width: 600px;
}
</style>
<script>
function processData(returnedData, status) {
$("#ajaxStatusMessage").append("Status: " + status + "<br>");
var records = returnedData.split(" ");
for (var i=0; i<records.length; i++) {
var fields = records[i].split(",");
$("#tblEmployee").append("<tr><td>" + fields[0] +
"</td><td>" + fields[1] +
"</td><td>" + fields[2] + "</td></tr>");
}
$("tr").eq(0).addClass("header");
$("tr:even:gt(0)").addClass("evenRow");
$("tr:odd").addClass("oddRow");
}
function reportError(request, status, errorMsg) {
$("#ajaxStatusMessage").append("Status: " + status + "<br>Error Message: " + errorMsg);
$("#ajaxStatusMessage").addClass("errMsg");
}
$(function () {
$.ajax({
type: "GET",
url: "employees.txt",
dataType: "text",
success: processData,
error: reportError
});
});
</script>
</head>
<body>
<table id="tblEmployee"></table><br>
<div id="ajaxStatusMessage"></div>
</body>
</html>
Listing 9-2. Content of the employees.txt file
Employee Name, Department, Salary
Jane Smith, Marketing, $95000
John Smith, Technology, $90000
Brian Adam, Sales, $72000
Mary Jones, Support, $60000
Michael Jefferson, Technology, $85000
How It Works
The HTML file with the AJAX call that’s loading a local file (for example, file:///C:/myWebApp/ajax.htm) can be viewed only in Firefox. Browsers like Chrome, Internet Explorer, and Safari have more restrictive default security features and they don’t permit local files to be loaded. To test with these browsers, you need to deploy the web application on a web server. Refer to the Appendix C for deploying a web application on Apache Tomcat and IIS.
In this code, after the DOM is ready, the following code is executed:
$.ajax({
type: "GET",
url: "employees.txt",
dataType: "text",
success: processData,
error: reportError
});
The jQuery ajax() method is executed with the following settings:
$.ajax() returns a jqXHR (jQuery XMLHttpRequest) object. jqXHR extends the browser’s native XMLHttpRequest object’s functionalities by adding properties and APIs to it. The .ajax() method call sets its properties and then returns it. It manages all the aspects of the request and the response, including a request header, data being sent to the server, callback function names, the status of the request, the response header from the server, and the data returned from the server. This object is also passed as an argument to most of the callback functions, such as success and error callback functions.
The ajax() method execution sends the request to the server asynchronously—the program execution doesn’t wait for the response to come back. When a response is received from the server, depending on the status, either processData or reportError is executed.
If there is a successful response, the processData() function is called. It executes the following code:
$("#ajaxStatusMessage").append("Status: " + status + "<br>");
var records = returnedData.split(" ");
for (var i=0; i<records.length; i++) {
var fields = records[i].split(",");
$("#tblEmployee").append("<tr><td>" + fields[0] +
"</td><td>" + fields[1] +
"</td><td>" + fields[2] + "</td></tr>");
}
$("tr").eq(0).addClass("header");
$("tr:even:gt(0)").addClass("evenRow");
$("tr:odd").addClass("oddRow");
The returnedData argument contains data from the response. $("#ajaxStatusMessage").append("Status: " + status + "<br>") appends the status message to the div tag with the ajaxStatusMessage ID.
var records = returnedData.split(" ") creates an array of records by splitting the returned data using a newline character as a delimiter. If you want to see the content of the records array, you can add the following line to your code, after the records variable is set:
console.dir(records)
console.dir(objName) displays the content of the specified object objName in the browser’s console. Figure 9-3 displays the content of the records array in the Firefox browser.
Figure 9-3. Content of the records array
for (var i=0; i<records.length; i++) { ... } iterates over the each record specified in Figure 9-3.
var fields = records[i].split(",") creates an array of fields by splitting each record using , as a delimiter. If you want to see the content of the fields array, you can add the following line to your code, after the fields variable is set: console.dir(fields). Figure 9-4 displays the content of the fields array for the third element in the browser console.
Figure 9-4. Content of the records array
$("#tblEmployee").append("<tr><td>" + fields[0] + "</td><td>" + fields[1] + "</td><td>" + fields[2] + "</td></tr>") builds the <tr> record for the table using elements from the fields array and appends it to the <table> with the ID tblEmployee.
After all the records are built and appended to the table, the following code is executed to set the CSS properties:
Note that in this code, HTML and CSS are added using JavaScript on the client (browser) side. In a conventional web application, HTML and CSS are specified on the server side.
Figure 9-5 displays the page after data is returned from the server and after the HTML tags and CSS classes are added to the returned data.
Figure 9-5. Data has been returned and formatted using HTML and CSS
If there is an error sending the request or receiving the response, the reportError() callback function is executed. It has the following arguments—request (which contains information about the request), status (which in this case is “error”), and errorMsg (which contains details about the error).
In order to simulate an error, make a small change in the code in the Listing 9-1. Update the value of the url to employeeY.txt (for example) and view the page in the browser. Due to the error in the request, the error callback function will be executed and an error message will be displayed, as shown in the Figure 9-6.
Figure 9-6. An error message is displayed
About the Convenience Methods
jQuery has provided some convenience (shorthand) methods that you can be use in place of using the ajax() method. For this recipe, you can replace the ajax() method call with the following convenience method:
$.get("employees.txt", processData, "text");
The following is the syntax for the .get() convenience method:
$.get(url, data, successCallbackFunction, dataType)
where data is the data you want to send to the server. In the current recipe, it is null and hence there is no need to pass it. successCallbackFunction is the callback function, and its called when there’s a successful response from the server. The data, successCallbackFunction, and dataType arguments are optional. You can handle error conditions by setting the global error handler using $(document).ajaxError(errorHandler). These are covered in Recipes 9-9 and 9-10.
Handling Runtime Errors
JavaScript runtime errors are not reported in the Firefox console log if the error is in the callback functions. In order to catch the runtime error, use JavaScript exception handling statement try {...} catch (error) {...}. Refer to Appendix D for details about implementing exception handling in your code.
9-2. Using jQuery AJAX API Calls to Get HTML Text from the Server
Problem
You want to use jQuery API calls to get HTML text from the server. This functionality can be used to get HTML code from various sources in order to display a complete view in a single HTML file.
Solution
Refer to Recipe 9-1 for the syntax for making a jQuery AJAX call. Listings 9-3 and 9-4 provide the changes to the code in Recipe 9-1 needed to demonstrate the use of the jQuery AJAX API ajax() method in order to get HTML content from the server. Listing 9-5 shows the employees.htm file.
Listing 9-3. Using the ajax() method to get HTML data: changes to the callback function of the success event
function processData(returnedData, status) {
$("#ajaxStatusMessage").append("Status: " + status + "<br>");
$("#tblEmployee").append(returnedData);
}
Listing 9-4. Using the ajax() method to get HTML data: changes to the ajax() call
$.ajax({
type: "GET",
url: "employees.htm",
dataType: "html",
success: processData,
error: reportError
});
Listing 9-5. Content of the employees.htm file
<table>
<tr class="header"><td>Employee Name</td><td>Department</td><td>Salary</td></tr>
<tr class="oddRow"><td>Jane Smith</td><td>Marketing</td><td>$95000</td></tr>
<tr class="evenRow"><td>John Smith</td><td>Technology</td><td>$90000</td></tr>
<tr class="oddRow"><td>Brian Adam</td><td>Sales</td><td>$72000</td></tr>
<tr class="evenRow"><td>Mary Jones</td><td>Support</td><td>$60000</td></tr>
<tr class="oddRow"><td>Michael Jefferson</td><td>Technology</td><td>$85000</td></tr>
</table>
How It Works
After the DOM is ready, the following code is executed:
$.ajax({
type: "GET",
url: "employees.htm",
dataType: "html",
success: processData,
error: reportError
});
The jQuery ajax() method is executed with the following settings:
The ajax() method execution sends the request to the server asynchronously. When a response is received from the server, depending on the status, the processData or reportError callback function is executed.
If there is a successful response, the processData() function will be called, and it will execute the following code:
$("#ajaxStatusMessage").append("Status: " + status + "<br>");
$("#tblEmployee").append(returnedData);
$("#ajaxStatusMessage").append("Status: " + status + "<br>") appends the status message to the div tag with the ajaxStatusMessage ID.
$("#tblEmployee").append(returnedData) appends the returned HTML data to the <table> with the tblEmployee ID.
Figure 9-5 displays the page after the data is returned from the server and appended to the <table> tag. Figure 9-6 displays the error message when an error occurs when sending the request to the server or when receiving the response from the server.
For this recipe, you can replace the ajax() method call using the following convenience method:
$.get("employees.htm", processData, "html");
There is another convenience method called load() that attaches the HTML data directly to the specified selector:
$("#tblEmployee").load("employee.htm");
In this case, you don’t have to define a success callback function like processData. The following is the syntax to use the load() method:
load(url, data, completeCallbackFunction)
load(url, data, function(returnedData, status) {...})
where data is the data you want to send to the server. In the current recipe, it is null and hence there is no need to pass it. completeCallbackFunction is the callback function that’s executed upon completing the request. returnedData is the data returned from the server and status is the status of the request and the response. data and completeCallbackFunction are optional arguments.
9-3. Using jQuery AJAX API Calls to Get Data in XML Format from the Server
Problem
You want to use jQuery API calls to get data in XML format from the server.
Solution
Refer to Recipe 9-1 for the syntax of making a jQuery AJAX call. Listings 9-6 and 9-7 shows the changes to the code in Recipe 9-1 needed to demonstrate the use of the jQuery AJAX API ajax() method to get employees data in the XML format from the server. Listing 9-8 shows the employees.xml file.
Listing 9-6. Using the ajax() method to get XML data: changes to the callback function for the success event
function processData(returnedData, status) {
$("#ajaxStatusMessage").append("Status: " + status + "<br>");
var tableRecord="";
$("#tblEmployee").append("<tr><td>Employee Name</td><td>Department</td><td>Salary</td>");
$(returnedData).find('employee').each(function(){
$("#tblEmployee").append(
"<tr><td>" + $(this).find("employeeName").text() +
"</td><td>" + $(this).find("department").text() +
"</td><td>" + $(this).find("salary").text() + "</td></tr>");
});
$("tr").eq(0).addClass("header");
$("tr:even:gt(0)").addClass("evenRow");
$("tr:odd").addClass("oddRow");
}
Listing 9-7. Using the ajax() method to get XML data: changes in the ajax() call
$.ajax({
type: "GET",
url: "employees.xml",
dataType: "xml",
success: processData,
error: reportError
});
Listing 9-8. Content of the employees.xml file
<employees>
<employee>
<employeeName>Jane Smith</employeeName>
<department>Marketing</department>
<salary>$95000</salary>
</employee>
<employee>
<employeeName>John Smith</employeeName>
<department>Technology</department>
<salary>$90000</salary>
</employee>
<employee>
<employeeName>Brian Adam</employeeName>
<department>Sales</department>
<salary>$72000</salary>
</employee>
<employee>
<employeeName>Mary Jones</employeeName>
<department>Support</department>
<salary>$60000</salary>
</employee>
<employee>
<employeeName>Michael Jefferson</employeeName>
<department>Technology</department>
<salary>$85000</salary>
</employee>
</employees>
How It Works
After the DOM is ready, the following code is executed:
$.ajax({
type: "GET",
url: "employees.xml",
dataType: "xml",
success: processData,
error: reportError
});
The jQuery ajax() method is executed with the following settings:
The ajax() method execution sends the request to the server asynchronously. When a response is received from the server, depending on the status, the processData or reportError callback function is executed.
If there is a successful response, the processData() function will be executed, which will in turn execute the following code:
$("#ajaxStatusMessage").append("Status: " + status + "<br>");
var tableRecord="";
$("#tblEmployee").append("<tr><td>Employee Name</td><td>Department</td><td>Salary</td>");
$(returnedData).find('employee').each(function(){
$("#tblEmployee").append(
"<tr><td>" + $(this).find("employeeName").text() +
"</td><td>" + $(this).find("department").text() +
"</td><td>" + $(this).find("salary").text() + "</td></tr>");
});
$("tr").eq(0).addClass("header");
$("tr:even:gt(0)").addClass("evenRow");
$("tr:odd").addClass("oddRow");
Note the following items about this code example:
Figure 9-5 displays the page after the data is returned from the server and appended to the <table> tag. Figure 9-6 displays the error message if an error occurs while sending the request to the server or while receiving the response from the server.
For this recipe, you can replace the ajax() method call with the following convenience method:
$.get("employees.xml", processData, "xml");
9-4. Using jQuery AJAX API Calls to Get Data in the JSON Format from the Server
Problem
You want to use jQuery API calls to get data in the JSON format from the server.
Solution
Refer to Recipe 9-1 for the syntax of making a jQuery AJAX call. Listings 9-9 and 9-10 provide the changes to the code in Recipe 9-1 to demonstrate the use of the jQuery AJAX API ajax() method to get the employees data in the JSON format from the server. Listing 9-11 shows the employees.json file.
Listing 9-9. Using the ajax() method to get JSON data: changes to the callback function for the success event
function processData(returnedData, status) {
$("#ajaxStatusMessage").append("Status: " + status + "<br>");
console.dir(returnedData);
var tableRecord="";
$("#tblEmployee").append("<tr><td>Employee Name</td><td>Department</td><td>Salary</td>");
for (var i=0; i < returnedData.employees.length; i++) {
var employee = returnedData.employees[i];
$("#tblEmployee").append("<tr><td>" + employee.employeeName +
"</td><td>" + employee.department +
"</td><td>" + employee.salary + "</td></tr>");
}
$("tr").eq(0).addClass("header");
$("tr:even:gt(0)").addClass("evenRow");
$("tr:odd").addClass("oddRow");
}
Listing 9-10. Using the ajax() method to get JSON data: changes to the callback function for the success event
$.ajax({
type: "GET",
url: "employees.json",
dataType: "json",
success: processData,
error: reportError
});
Listing 9-11. Content of the employees.json file
{
"employees":
[
{"employeeName":"Jane Smith", "department":"Marketing", "salary":"$95000"},
{"employeeName":"John Smith", "department":"Technology", "salary":"$90000"},
{"employeeName":"Brian Adam", "department":"Sales", "salary":"$72000"},
{"employeeName":"Mary Jones", "department":"Support", "salary":"$60000"},
{"employeeName":"Michael Jefferson", "department":"Technology", "salary":"$85000"}
]
}
How It Works
After the DOM is ready, the following code is executed:
$.ajax({
type: "GET",
url: "employees.json",
dataType: "json",
success: processData,
error: reportError
});
The jQuery ajax() method is executed with the following settings:
ajax() method execution sends the request to the server asynchronously. When a response is received from the server, depending on the status, the processData or reportError callback function is executed.
If there is a successful response, processData() function will be executed, which will in turn execute the following code:
$("#ajaxStatusMessage").append("Status: " + status + "<br>");
console.dir(returnedData);
var tableRecord="";
$("#tblEmployee").append("<tr><td>Employee Name</td><td>Department</td><td>Salary</td>");
for (var i=0; i < returnedData.employees.length; i++) {
var employee = returnedData.employees[i];
$("#tblEmployee").append("<tr><td>" + employee.employeeName +
"</td><td>" + employee.department +
"</td><td>" + employee.salary + "</td></tr>");
}
$("tr").eq(0).addClass("header");
$("tr:even:gt(0)").addClass("evenRow");
$("tr:odd").addClass("oddRow");
Where:
var jsonObj = $.parseJSON(returnedData);
var jsonString = JSON.stringify(jsonObj);
Figure 9-7. Structure of the returned JSON data
Figure 9-5 displays the page after the data is returned from the server and appended to the <table> tag. Figure 9-6 displays the error message if an error occurs while the request is being sent or the response is being received.
Convenience Methods
For this recipe, you can replace the ajax() method call with the following convenience method:
$.get("employees.json", processData, "json");
You can also use another convenience method that’s available specifically for the JSON data type:
$.getJSON("employees.json", processData);
The following is the syntax to use the getJSON() method:
$.getJSON( url, data, successCallbackFunction)
where data is the data you want to send to the server and successCallbackFunction is the function that’s executed if the response is received successfully. data and successCallbackFunction are optional arguments.
9-5. Using jQuery AJAX API Calls to Get the Script from the Server
Problem
You want to use jQuery API calls to get the script from the server. This feature is useful when the JavaScript logic is dependent on the user interaction or on certain criteria that’s known at runtime. Instead of adding complex JavaScript code to the HTML file, the server can deliver the script to the browser at runtime.
Solution
Refer to Recipe 9-1 for the syntax of making a jQuery AJAX call. Listings 9-12 and 9-13 provide the changes to the code in Recipe 9-1 to demonstrate the use of the jQuery AJAX API ajax() method to get the script from the server. Listing 9-11 provides the content of the employees.json file. In the success callback function, another AJAX call is made by using the convenience method $.getScript(), which gets the JavaScript code from the server and executes it. Listing 9-14 shows the JavaScript code in the employees.js file.
Listing 9-12. Using the ajax() method to get JSON data and getScript() to get JavaScript code: changes to the callback function for the success event
function processData(returnedData, status) {
$("#ajaxStatusMessage").append("Status: " + status + "<br>");
var tableRecord="";
$("#tblEmployee").append("<tr><td>Employee Name</td><td>Department</td><td>Salary</td>");
for (var i=0; i < returnedData.employees.length; i++) {
var employee = returnedData.employees[i];
$("#tblEmployee").append("<tr><td>" + employee.employeeName +
"</td><td>" + employee.department +
"</td><td>" + employee.salary + "</td></tr>");
}
$.getScript("employees.js");
}
Listing 9-13. Using the ajax() method to get JSON data and getScript() to get the JavaScript code: changes to the ajax() call
$.ajax({
type: "GET",
url: "employees.json",
dataType: "json",
success: processData,
error: reportError
});
Listing 9-14. Content of the employees.js file
$("tr").eq(0).addClass("header");
$("tr:even:gt(0)").addClass("evenRow");
$("tr:odd").addClass("oddRow");
How It Works
Refer to Recipe 9-4 for the ajax() call code explanation for the JSON dataType and for the success callback function. In the processData() success callback function, another AJAX call gets the script by using the $.getScript("employees.js") code. The getScript method gets the JavaScript code from the server and executes it.
Figure 9-5 displays the page after the data is returned from the server and appended to the <table> tag. Figure 9-6 displays an error message if an error occurs when sending the request or when receiving the response.
9-6. Sending Data to the Server Using a GET Request Method
Problem
You want to use jQuery API calls to send data to the server so that the server can send the information back, based on the data received with the request.
Solution
The following is syntax to send data to the server using the GET request method:
$.ajax(settingsMapObject)
where, settingsMapObject is
{
type: "GET",
url: "requestUrl",
data: "param1=paramValue1& param2=paramValue2&...",
dataType: "text", // html, xml, json
success: successCallbackFunction,
error: errorCallbackFunction
}
function successCallbackFunction(returnedData, status) { ... }
function errorCallbackFunction(request, status, errorMsg) { ... }
The data is the data to be sent to the server. Its value can be either a string in the querystring format, such as "param1=paramValue1¶m2=paramValue2,...", or the map object in the key/value pairs form {param1:'paramValue1', param2:'paramValue2', ...}. If any parameter has multiple values, the same parameter name can be specified multiple times with the different parameter values. While sending the request to the server, the URL gets converted to requestUrl?param1=paramValue1& param2=paramValue2&...
If the data you want to send to the server is contained in form fields, you can use jQuery helper function serialize() to convert the form’s elements value to the query string format. Listing 9-15 provides an example to send form data to the server in the querystring format. Since server side coding to filter the data, based on the passed value, is out of the scope of this chapter, this recipe will get the response back from a file instead of from a processing resource (web service) on the server side. Listing 9-11 provides the content of the employees.json file.
Listing 9-15. Using the ajax() method to make an AJAX call with data using the GET request method
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="scripts/jquery-2.1.0.min.js"></script>
<style>
div {
border:3px double green;
width: 500px;
background-color: lightcyan;
}
form {
border:3px double green;
width: 400px;
padding: 20px;
background-color: lightyellow;
}
table {
border:0px;
}
td {
padding-right: 10px;
padding-left: 10px;
}
label {
float:left;
display:block;
width: 250px;
font-weight: bold;
}
.header {
font-weight: bold;
background-color: lightgray;
}
.evenRow {
background-color: lightyellow;
}
.oddRow {
background-color: lightblue;
}
.errMsg {
background-color: orange;
color: white;
font-weight: bold;
width: 600px;
}
</style>
<script>
function processData(returnedData, status) {
$("#ajaxStatusMessage").append("Status: " + status + " <br>");
var tableRecord="";
var enteredDepartment = $("#txtDepartment").val().toLowerCase().trim();
var enteredSalary = 0;
if ($("#txtSalary").val() != "") {
enteredSalary = parseFloat($("#txtSalary").val());
}
$("#tblEmployee").append("<tr><td>Employee Name</td><td>Department</td><td>Salary</td>");
for (var i=0; i < returnedData.employees.length; i++) {
var employee = returnedData.employees[i];
var salary = parseFloat(employee.salary.replace("$",""));
var department = employee.department.toLowerCase().trim();
// Filter records
if (salary >=enteredSalary && (enteredDepartment == "" || enteredDepartment == department)) {
$("#tblEmployee").append("<tr><td>" + employee.employeeName +
"</td><td>" + employee.department +
"</td><td>" + employee.salary + "</td></tr>");
}
}
$("tr").eq(0).addClass("header");
$("tr:even:gt(0)").addClass("evenRow");
$("tr:odd").addClass("oddRow");
}
function reportError(request, status, errorMsg) {
$("#ajaxStatusMessage").append("Status: " + status + "<br>Error Message: " + errorMsg);
$("#ajaxStatusMessage").addClass("errMsg");
}
$(function () {
$("#btnSubmit").click( function (eventObj) {
eventObj.preventDefault();
$.ajax({
type: "GET",
url: "employees.json",
data: $("form").serialize(),
dataType: "json",
success: processData,
error: reportError
});
$("#ajaxStatusMessage").append("Parameter Sent to the server: " + $("form").serialize() + "<br>");
});
});
</script>
</head>
<body>
<h4>Employee Search Criteria:</h4>
<form id="frmSearch">
<label for="txtDepartment">Department Name:</label>
<input type="text" id="txtDepartment" name="txtDepartment"><br>
<label for="txtSalary">Salary (greater than or equal to):</label>
<input type="text" id="txtSalary" name="txtSalary"><br><br>
<button id="btnSubmit">Submit</button>
</form><br><br>
<div id="ajaxStatusMessage"></div><br>
Search Result:
<table id="tblEmployee"></table><br><br>
</body>
</html>
How It Works
In this example, filtering is done at the client side in the JavaScript code. In the real-world application, filtering logic is implemented on the server side to reduce the network traffic between the server and the browser. Since server side coding is out of the scope of this book, this example uses client-side filtering.
Most of the code in these listings is explained in Recipe 9-4. The following are the only differences:
If you want to send data from few elements only instead of sending all data entry form fields, you can use the following syntax:
$(selector).serialize()
If you want to convert data from an object or an array into a querystring format, you can use the helper function $.param(objName). For example,
var mapObj = {employeeName: "John Smith", department: "Technology"};
can be converted to a querystring by using:
var querystring = $.param(mapObj)
The value of the querystring will be:
employeeName=John+Smith&department=Technology
Figure 9-8 displays the initial page when displayed in the browser.
Figure 9-8. Displaying the initial page
Figure 9-9 displays the page when the Department name is Technology, the Salary is 85,000, and the Submit button is clicked.
Figure 9-9. Displaying the search result
9-7. Sending Form Data to the Server Using a POST Request Method
Problem
You want to use jQuery API calls to send data to the server so that server can process the data and/or save it.
Solution
The following is syntax to send form data to the server using the POST request method:
$.ajax(settingsMapObject)
where, settingsMapObject is
{
type: "POST",
url: "requestUrl",
data: $(form).serializeArray(),
dataType: "text",
success: successCallbackFunction,
error: errorCallbackFunction
}
function successCallbackFunction(returnedData, status) { ... }
function errorCallbackFunction(request, status, errorMsg) { ... }
If the data you want to send to the server is contained in form fields, you can use jQuery helper function serializeArray() to convert the form’s elements’ values to an array of names and values, as so:
[ {name: "formFieldName1", value: "formFieldValue1"},
{name: "formFieldName2", value: "formFieldValue2"},
.....]
Name/value pairs are sent in the HTTP message body for the POST request method. GET requests have length restrictions where as POST requests have no data length restrictions. POST requests are more secure than the GET method because name value pairs cannot be cached, bookmarked, saved in the browser history, or logged in the server logs. Listing 9-16 demonstrates the use of the POST request method and the use of the jQuery method serializeArray() to get the form’s data to be sent to the server. Listing 9-17 displays the content of the file createNewEmployee.json. In real-world applications, the request is sent to the processing resource (web service) on the server side. An appropriate status, based on the processing result, is sent back as a response.
Listing 9-16. Using the ajax() method to send form data using the POST request method
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="scripts/jquery-2.1.0.min.js"></script>
<style>
div {
border:3px double green;
width: 400px;
background-color: lightcyan;
padding: 10px;
}
form {
border:3px double green;
width: 400px;
padding: 20px;
background-color: lightyellow;
}
table {
border:0px;
}
td {
padding-right: 10px;
padding-left: 10px;
}
label {
float:left;
display:block;
width: 175px;
font-weight: bold;
}
.header {
font-weight: bold;
background-color: lightgray;
}
.evenRow {
background-color: lightyellow;
}
.oddRow {
background-color: lightblue;
}
.errMsg {
background-color: orange;
color: white;
font-weight: bold;
width: 400px;
}
</style>
<script>
function processData(returnedData, status) {
$("#ajaxStatusMessage").append("Status: " + status + "<br>");
if (returnedData.processingStatus == "Successful") {
$("#processingResult").append("New employee record is created successfully.");
} else {
$("#processingResult").append("Failed to create new employee record.");
$("#processingResult").addClass("errMsg");
}
}
function reportError(request, status, errorMsg) {
$("#ajaxStatusMessage").append("Status: " + status + "<br>Error Message: " + errorMsg);
$("#ajaxStatusMessage").addClass("errMsg");
}
$(function () {
$("#btnCreateNew").click( function (eventObj) {
eventObj.preventDefault();
$.ajax({
type: "POST",
url: "createNewEmployee.json",
data: $("form").serializeArray(),
dataType: "json",
success: processData,
error: reportError
});
var fields = "";
$.each( $("form").serializeArray(), function( i, field ) {
fields += "[Key: " + field.name + " Value: " + field.value + "]<br>";
});
$("#ajaxStatusMessage").append("Data Sent to the server: <br>" + fields + "<br>");
});
});
</script>
</head>
<body>
<h4>New Employee:</h4>
<form id="frmSearch">
<label for="txtEmployeeName">Employee's Name:</label>
<input type="text" id="txtEmployeeName" name="txtEmployeeName"><br>
<label for="txtDepartment">Department Name:</label>
<input type="text" id="txtDepartment" name="txtDepartment"><br>
<label for="txtSalary">Salary (greater than):</label>
<input type="text" id="txtSalary" name="txtSalary"><br><br>
<button id="btnCreateNew">Create New Employee Record</button>
</form><br><br>
<div id="ajaxStatusMessage"></div><br>
Processing Result:
<div id="processingResult"></div><br><br><br>
</body>
</html>
Listing 9-17. Content of the createNewEmployee.json file
{"processingStatus": "Successful"}
How It Works
If Create New Employee Record is clicked after the DOM is created, the following code is executed:
eventObj.preventDefault();
$.ajax({
type: "POST",
url: "createNewEmployee.json",
data: $("form").serializeArray(),
dataType: "json",
success: processData,
error: reportError
});
var fields = "";
$.each( $("form").serializeArray(), function( i, field ) {
fields += "[Key: " + field.name + " Value: " + field.value + "]<br>";
});
$("#ajaxStatusMessage").append("Data Sent to the server: <br>" + fields + "<br>");
Where:
If you want to send data from a few elements only instead of sending all the data-entry form fields, you can use the following syntax:
$(selector).serializeArray()
If you want to convert data from an object or an array into a querystring format, you can use the helper function $.param(objName). For example:
var mapObj = {employeeName: "John Smith", department: "Technology"};
can be converted to a querystring by using:
var querystring = $.param(mapObj)
The value of the querystring will be:
employeeName=John+Smith&department=Technology
You can use any of the jQuery helper functions—$.param(mapObj), $.param(arrayObj), $(selector).serialize(), and $(selector).serializeArray()—to set the data in the ajax() method for the GET and POST request methods.
$.each( $("form").serializeArray(), function( i, field ) {
fields += "[Key: " + field.name + " Value: " + field.value + "]<br>";
});
$("#ajaxStatusMessage").append("Data Sent to the server: <br>" + fields + "<br>");
This code iterates over the name/value pairs in the array, sets the fields variable with the pairs values, and displays it on the page.
When there is a successful response from the server, the processData() callback function is executed with the following code:
$("#ajaxStatusMessage").append("Status: " + status + "<br>");
if (returnedData.processingStatus == "Successful") {
$("#processingResult").append("New employee record is created successfully.");
} else {
$("#processingResult").append("Failed to create new employee record.");
("#processingResult").addClass("errMsg");
}
Where:
Figure 9-10 displays the initial page when displayed in the browser.
Figure 9-10. Displaying the initial page
Figure 9-11 displays the page after new employee’s information is entered and the Create New Employee Record button is clicked.
Figure 9-11. Displaying the data sent to the server and the successful response back from the server
For this recipe, you can replace the ajax() method call with the following convenience method:
$.post("createNewEmployee.json",
$("form").serializeArray(),
processData,
"json");
The following is the syntax for the post() convenience method:
$.post(url, data, successCallbackFunction, dataType)
where data is the data you want to send to the server. successCallbackFunction is the callback function that will be called when there’s a successful response from the server. The data, successCallbackFunction, and dataType arguments are optional. You can handle error conditions by setting the global error handler using ajaxError(errorHandler). These are covered in Recipes 9-9 and 9-10.
9-8. Using AJAX Events at the Request Level
Problem
You want to know how to use AJAX events at the request level.
Solution
The following is the list of events that you can handle at various stages of the AJAX request and response process. These events are triggered in the order specified in the following list:
For example, the following callback function (event handler) can be used to set the value of the URL based on the outcome of some processing logic:
$.ajax({
....
beforeSend: function(jqXHR, settings) {
// Processing logic
settings.url = "/process.asmx";
}
});
$.ajax({
....
dataFilter: function(returnedData, dataType) {
// Processing logic to update returnedData
var updatedData = returnedData;
return(updatedData);
}
});
success: [function1, function2, ...]
In the callback function of this event, you process the returned data from the server. Some examples are:
$.ajax({
....
success: function(returnedData, status, jqXHR) {
// Processing logic
$(selector).append(returnedData);
}
});
In the callback function of this event, you can display a message to the user with the user-friendly error message or retry the AJAX call if timeout occurred.
$.ajax({
....
error: function(jqXHR, status, errorMessage) {
// Display error message
$(selector).append("Status: " + status + " Error Message: " + errorMessage);
}
});
In the callback function of this event, you can display the progress bar as 100% completed to indicate that the request has completed successfully or has failed.
$.ajax({
....
complete: function(jqXHR, status) {
// Display message
$(selector).append("Processing completed with the status: " + status);
}
});
If you want to list an object’s properties and values, you can use the console.dir(objName) statement. This will display an object’s content in the browser.
You will use all of these request-level events in Recipe 9-10.
9-9. Using AJAX Events at the Global Level
Problem
You want to know how to use AJAX events at the global level.
Solution
The following is the list of global AJAX events that you can use at various stages of AJAX request and response process in the document. Callback functions for these events are at the document (web page) level. By default, global event handler are called for all AJAX requests on the page. To prevent execution of these global event handlers, you can set global options as false in the ajax() method:
$.ajax({
....
global: false;
});
$(document).on("ajaxStart", startCallbackFunction)
or
$(document). ajaxStart(startCallbackFunction)
$(document).on("ajaxSend", sendCallbackFunction)
or
$(document). ajaxSend(sendCallbackFunction)
$(document).on("ajaxSuccess", successCallbackFunction)
or
$(document). ajaxSuccess(succesCallbackFunction)
$(document).on("ajaxError", errorCallbackFunction)
or
$(document). ajaxError(errorCallbackFunction)
$(document).on("ajaxComplete", completeCallbackFunction)
or
$(document). ajaxComplete(completeCallbackFunction)
$(document).on("ajaxStop", stopCallbackFunction)
or
$(document). ajaxStop(stopCallbackFunction)
If you want to list an object’s properties and their values, you can use console.dir(objName). This will display an object’s content in the browser.
You will use all of these request-level events in Recipe 9-10.
9-10. Order of AJAX Events at the Request and Global Levels
Problem
You want to know the order in which AJAX events are triggered during the lifecycle of an AJAX request.
Solution
Listing 9-18 demonstrates the order of AJAX events triggering. It shows all the global and request-level events that are triggered for a successful AJAX request as well as for a failed AJAX request. This code listing has event handlers (with arguments) for all AJAX events triggered at the document and request levels. Listing 9-19 shows the testMessage.txt file.
Listing 9-18. The order of triggering AJAX events
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="scripts/jquery-2.1.0.min.js"></script>
<script>
// Global AJAX events callbacks
function ajaxSuccessCallback(eventObj, jqXHR, settingsObj) {
$("#status").append("Global event - ajaxSuccess.<br>");
}
function ajaxSendCallback(eventObj, jqXHR, settingsObj) {
$("#status").append("Global event - ajaxSend.<br>");
}
function ajaxStartCallback(eventObj) {
$("#status").append("Global event - ajaxStart.<br>");
}
function ajaxStopCallback(eventObj) {
$("#status").append("Global event - ajaxStop.<br>");
}
function ajaxErrorCallback(eventObj, jqXHR, settingsObj) {
$("#status").append("Global event - ajaxError.<br>");
}
function ajaxCompleteCallback(eventObj, jqXHR, settingsObj) {
$("#status").append("Global event - ajaxComplete.<br>");
}
// AJAX events callbacks at the request level
function requestBeforeSendCallback(jqXHR, settingsObj) {
$("#status").append("Request event - beforeSend.<br>");
}
function requestCompleteCallback(jqXHR, status) {
$("#status").append("Request event - complete.<br>");
}
function requestDataFilterCallback(returnedData, dataType) {
$("#status").append("Request event - dataFilter.<br>");
}
function requestErrorCallback(jqXHR, status, errorMessage) {
$("#status").append("Request event - error.<br>");
}
function requestSuccessCallback(returnedData, status, jqXHR) {
$("#status").append("Request event - success.<br>");
}
$(function () {
$(document).on("ajaxSend", ajaxSendCallback);
$(document).on("ajaxSuccess", ajaxSuccessCallback);
$(document).on("ajaxError", ajaxErrorCallback);
$(document).on("ajaxComplete", ajaxCompleteCallback);
$(document).on("ajaxStart", ajaxStartCallback);
$(document).on("ajaxStop", ajaxStopCallback);
$("#btnSuccess").click(function () {
$("#status").empty();
$.ajax(
{
type: "GET",
url: "testMessage.txt",
beforeSend: requestBeforeSendCallback,
complete: requestCompleteCallback,
dataFilter: requestDataFilterCallback,
error: requestErrorCallback,
success: requestSuccessCallback,
data: null,
dataType: "text"
});
});
$("#btnFailed").click(function () {
$("#status").empty();
$.ajax(
{
type: "GET",
url: "incorrect.txt",
beforeSend: requestBeforeSendCallback,
complete: requestCompleteCallback,
dataFilter: requestDataFilterCallback,
error: requestErrorCallback,
success: requestSuccessCallback,
data: null,
dataType: "text" //script: execute response as a script.
});
});
});
</script>
</head>
<body>
<button id="btnSuccess">Start Successful Ajax Call</button>
<button id="btnFailed">Start Unsuccessful Ajax Call</button><br><br>
<div id="status"></div>
</body>
</html>
Listing 9-19. Content of the testMessage.txt file
Test Message
How It Works
After the DOM is created, event handlers for all global-level AJAX events are registered by using the following code:
$(document).on("ajaxSend", ajaxSendCallback);
$(document).on("ajaxSuccess", ajaxSuccessCallback);
$(document).on("ajaxError", ajaxErrorCallback);
$(document).on("ajaxComplete", ajaxCompleteCallback);
$(document).on("ajaxStart", ajaxStartCallback);
$(document).on("ajaxStop", ajaxStopCallback);
When the Start Successful Ajax Call button is clicked, the following AJAX code is executed to register request-level event handlers for the events—beforeSend, complete, dataFilter, error, and success.
$.ajax(
{
type: "GET",
url: "testMessage.txt",
beforeSend: requestBeforeSendCallback,
complete: requestCompleteCallback,
dataFilter: requestDataFilterCallback,
error: requestErrorCallback,
success: requestSuccessCallback,
data: null,
dataType: "text"
});
When the Start Unsuccessful Ajax Call button is clicked, the following AJAX code is executed to register request-level event handlers for the beforeSend, complete, dataFilter, error, and success events. The only difference in this case is the URL setting, which uses a filename that doesn’t exist. This is to simulate an error condition.
$.ajax(
{
type: "GET",
url: " incorrect.txt",
beforeSend: requestBeforeSendCallback,
complete: requestCompleteCallback,
dataFilter: requestDataFilterCallback,
error: requestErrorCallback,
success: requestSuccessCallback,
data: null,
dataType: "text"
});
In all the registered event handlers, the div tag with the ID status is set to display the message with the name of the event handler being executed using the code. For example, $("#status").append("Request event - success.<br>").
Figure 9-12 displays the list of event handlers that are executed when the user clicks the Start Successful Ajax Call button.
Figure 9-12. Displaying a list of events that occurred during a successful AJAX request
Figure 9-13 displays the list of event handlers that are executed when the user clicks the Start Unsuccessful Ajax Call button.
Figure 9-13. Displaying a list of events that occurred during a successful AJAX request
Figures 9-14 displays a flowchart of an AJAX events chain for a successful and a failed AJAX request.
Figure 9-14. Flowchart of events triggered during successful and failed AJAX requests
Summary
This chapter covered topics related to jQuery AJAX methods and events. You learned:
18.191.29.22