Cover | Table of Contents | Colophon
XMLHttpRequest, a JavaScript object with an application programming interface (API) that can connect with a server using the HyperText Transfer Protocol (HTTP). A lot of the Ajax magic is propelled by this piece of code, which all the major browsers (such as Mozilla Firefox, Internet Explorer 6, Safari 1.3 and 2.0, and Opera 7.6) support. The asynchronous part of Ajax derives from this object’s characteristics.
XMLHttpRequest object can handle the server response in standard XML format as well as plain text.select lists, textareas, text fields, and radio buttons that submit their own data and talk to servers behind the scenes. However, bear in mind that Ajax-powered widgets should be first and foremost usable, and always avoid confusing and irritating web users.
XMLHttpRequest object, which allows JavaScript to fetch bits of server data while the user is happily playing with the rest of your application. This object has its own API, which we will summarize in this introduction.XMLHttpRequest object’s methods include open( ), send( ), and abort( ).
onreadystatechange
readyState changes.
readyState
0 means uninitialized, open( ) has not yet been called; 1 means loading, send( ) has not been called; 2 means loaded, send( ) has been called, and headers/status are available; 3 means interactive, responseText holds partial data; 4 means completed.
responseText
string
XMLHttpRequest. However, continuing with the tradition established by IE 5.0, recent vintages of Internet Explorer implement the software as an ActiveX object named
Microsoft.XMLHTTP or
Msxml2.XMLHTTP.Microsoft.XMLHTTP and Msxml2.XMLHTTP refer to different versions of software components that are a part of Microsoft XML Core Services (MSXML). Here’s what our contributing IE expert says on this matter:Microsoft.XMLHTTP, the ActiveXObject wrapper will try to initialize the last known good version of the object that has this program (or “prog”) ID. This object, in theory, could be MSXML 1.0, but almost no one these days has that version because it has been updated via Windows Update, IE 6, or another means. MSXML 1.0 was very short-lived. If you use MSXML2.XMLHTTP, that signifies to the wrapper to use at least MSXML 2.0 libraries. Most developers do not need to use a specific version of MSXML, such as MSXML2.XMLHTTP.4.0 or MSXML2.XMLHTTP.5.0.”ActiveX and XMLHttpRequest objects simply as “request objects” throughout this book, because they have very similar functionality. ActiveX-related request objects, and then properly initialize the object.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/1999/REC-html401-19991224/strict.dtd">
<html>
<head>
<script type="text/javascript" src="/parkerriver/js/hack2.js"></script>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Send a data tidbit</title>
</head>
<body>
<h3>A Few Facts About Yourself...</h3>
<form action="javascript:void%200" onsubmit="sendData( );return false">
<p>First name: <input type="text" name="firstname" size="20"> </p>
<p>Last name: <input type="text" name="lastname" size="20"> </p>
<p>Gender: <input type="text" name="gender" size="2"> </p>
<p>Country of origin: <input type="text" name="country" size="20"> </p>
<p><button type="submit">Send Data</button></p>
</form>
</body>
</html>
XMLHttpRequest object, then import that file into every web page that needs it. At the very least, this ensures that any necessary changes regarding how the code sets up the request object have to be made only in this file, as opposed to every JavaScript file that uses Ajax-style requests.XMLHttpRequest can then import this file in the following way:<script type="text/javascript" src="js/http_request.js"></script>
var request = null;
/* Wrapper function for constructing a request object.
Parameters:
reqType: The HTTP request type, such as GET or POST.
url: The URL of the server program.
asynch: Whether to send the request asynchronously or not.
respHandle: The name of the function that will handle the response.
Any fifth parameters, represented as arguments[4], are the data a
POST request is designed to send. */
function httpRequest(reqType,url,asynch,respHandle){
//Mozilla-based browsers
if(window.XMLHttpRequest){
request = new XMLHttpRequest( );
} else if (window.ActiveXObject){
request=new ActiveXObject("Msxml2.XMLHTTP");
if (! request){
request=new ActiveXObject("Microsoft.XMLHTTP");
}
}
//very unlikely, but we test for a null request
//if neither ActiveXObject was initialized
if(request) {
//if the reqType parameter is POST, then the
//5th argument to the function is the POSTed data
if(reqType.toLowerCase( ) != "post") {
initReq(reqType,url,asynch,respHandle);
} else {
//the POSTed data
var args = arguments[4];
if(args != null && args.length > 0){
initReq(reqType,url,asynch,respHandle,args);
}
}
} else {
alert("Your browser does not permit the use of all "+
"of this application's features!");
}
}
/* Initialize a request object that is already constructed */
function initReq(reqType,url,bool,respHandle){
try{
/* Specify the function that will handle the HTTP response */
request.onreadystatechange=respHandle;
request.open(reqType,url,bool);
//if the reqType parameter is POST, then the
//5th argument to the function is the POSTed data
if(reqType.toLowerCase( ) == "post") {
request.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded; charset=UTF-8");
request.send(arguments[4]);
} else {
request.send(null);
}
<?xml
version="1.0" encoding="UTF-8"?>), followed by a root element and zero or more child elements. An example is:<?xml version="1.0" encoding="UTF-8"?> <gps> <gpsMaker>Garmin</gpsMaker> <gpsDevice> Forerunner 301 </gpsDevice> </gps>
gps is the root element, and gpsMaker and gpsDevice are child elements. responseXML. This object is a DOM Document object that your Ajax application can use. Here’s an example:function handleResponse( ){
if(request.readyState == 4){
if(request.status == 200){
var doc = request.responseXML;
...
}request.responseText. This hack asks the user to choose a stock symbol, and the server returns the stock price for display. The code handles the return value as a string.<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/1999/REC-html401-19991224/strict.dtd">
<html>
<head>
<script type="text/javascript" src="js/hack9.js"></script>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Choose a stock</title>
</head>
<body>
<h3>Stock prices</h3>
<form action="javascript:void%200" onsubmit=
"getStockPrice(this.stSymbol.value);return false">
<p>Enter stock symbol: <input type="text" name=
"stSymbol" size="4"><span id="stPrice"></span></p>
<p><button type="submit">Get Stock Price</button></p>
</form>
</body>
</html>
span element to the right of the text field.
string (as discussed in the last hack) or some other object. JavaScript is usually pretty smart about converting values to number types without your intervention, but still, you don’t want your application to multiply an innocent investor’s share quantity by undefined or some other weird data the server returns!
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/1999/REC-html401-19991224/strict.dtd">
<html>
<head>
<script type="text/javascript" src="/parkerriver/js/hack4.js">
</script>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Tally your stocks</title>
</head>
<body>
<h3>Your total Stock Holdings</h3>
<form action="javascript:void%200" onsubmit=
"getStockPrice(this.stSymbol.value,this.numShares.value);return false">
<p>Enter stock symbol: <input type="text" name="stSymbol" size="4">
<span id="stPrice"></span></p>
<p>Enter share amount: <input type="text" name="numShares" size="10"></p>
<p><button type="submit">Get Total Value</button></p>
<div id="msgDisplay"></div>
</form>
</body>
</html>
{)})"hello"
[1,2,3,4]
true, false, or null
http://www.json.org for further details.Object literal in JavaScript. As an example, here is what the information requested of the user in “Use the Request Object to POST Data to the Server” [Hack #2] looks like in JSON format:{
firstname:"Bruce",
lastname:"Perry",
gender:"M",
country:"USA"
}
open( ) method with the request object, your code uses a different host address than the address from which the user downloaded the web page. The request object throws an exception in this case when you try to call its open( ) method. XMLHttpRequest object (discussed at the beginning of this chapter), you know that the
request.status property equates to an HTTP response status code sent from the server. This is an important value to check before your page does anything cool with the HTTP response. 200 (the request went through okay), 404 (the requested file or URL path was not found), or 500 (internal server error). Server response header) or the content type of the response (the Content-Type header). This hack requests the user to enter a URL in a text field. When the user tabs out of or clicks outside of the text field, the browser displays various HTTP response headers. As usual with Ajax, this happens without a page refresh.Content-Type, Date, Server, and Content-Length.<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/1999/REC-html401-19991224/strict.dtd">
<html>
<head>
<script type="text/javascript" src="js/hack7.js"></script>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>view response headers</title>
<link rel="stylesheet" type="text/css" href="/parkerriver/css/hacks.css" />
</head>
<body onload="document.forms[0].url.value=urlFragment">
<h3>Find out the HTTP response headers when you "GET" a Web page</h3>
<form action="javascript:void%200">
<p>Enter a URL:
<input type="text" name="url" size="20" onblur="getAllHeaders(this.value)">
<span class="message">::press tab when finished editing the
field::</span></p>
<div id="msgDisplay"></div>
</form>
</body>
</html>select tag listing the styles the users can choose for the display of the results and a text field containing a partial URL they can complete and submit to a server.<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/1999/REC-html401-19991224/strict.dtd">
<html>
<head>
<script type="text/javascript" src="js/hack8.js"></script>
<script type="text/javascript">
function setSpan( ){
document.getElementById("instr").onmouseover=function( ){
this.style.backgroundColor='yellow';};
document.getElementById("instr").onmouseout=function( ){
this.style.backgroundColor='white';};
}
</script>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>view response headers</title>
<link rel="stylesheet" type="text/css" href="/parkerriver/css/hacks.css" />
</head>
<body onload="document.forms[0].url.value=urlFragment;setSpan( )">
<h3>Find out the HTTP response headers when you "GET" a Web page</h3>
<h4>Choose the style for your message</h4>
<form action="javascript:void%200">
<p>
<select name="_style">
<option label="Loud" value="loud" selected>Loud</option>
<option label="Fancy" value="fancy">Fancy</option>
<option label="Cosmopolitan" value="cosmo">Cosmopolitan</option>
<option label="Plain" value="plain">Plain</option>
</select>
</p>
<p>Enter a URL: <input type="text" name="url" size="20" onblur=
"getAllHeaders(this.value,this.form._style.value)">var request;
var urlFragment="http://localhost:8080/";
var st;
function getAllHeaders(url,styl){
if(url){
st=styl;
httpRequest("GET",url,true);
}
}
/* Set one or more CSS style attributes on a DOM element
CSS2Properties Object.
Parameters:
stType stands for a style name, as in 'plain,''fancy,''loud,' or 'cosmo'.
stylObj is the HTML element's style property, as in div.style. */
function setStyle(stType,stylObj){
switch(stType){
case 'plain' :
stylObj.maxWidth="80%";
stylObj.border="thin solid black";
stylObj.padding="5%";
stylObj.textShadow="none";
stylObj.fontFamily="Arial, serif";
stylObj.fontSize="0.9em";
stylObj.backgroundColor="yellow"; break;
case 'loud' :
stylObj.maxWidth="80%";
stylObj.border="thin solid black";
stylObj.padding="5%";
stylObj.fontFamily="Impact, serif";
stylObj.fontSize="1.4em";
stylObj.textShadow="0 0 2.0em black";
stylObj.backgroundColor="rgb(181,77,79)"; break;
case 'fancy' :
stylObj.maxWidth="80%";
stylObj.border="thin solid black";
stylObj.padding="5%";
stylObj.fontFamily="Herculanum, Verdana, serif";
stylObj.fontSize="1.2em";
stylObj.fontStyle="oblique";
stylObj.textShadow="0.2em 0.2em grey";
stylObj.color="rgb(21,49,110)";
stylObj.backgroundColor="rgb(234,197,49)"; break;
case 'cosmo' :
stylObj.maxWidth="80%";
stylObj.border="thin solid black";
stylObj.padding="1%";
stylObj.fontFamily="Papyrus, serif";
stylObj.fontSize="0.9em";
stylObj.textShadow="0 0 0.5em black";
stylObj.color="aqua";
stylObj.backgroundColor="teal"; break;
default :
alert('default');
}
}
//event handler for XMLHttpRequest
function handleResponse( ){
try{
if(request.readyState == 4){
if(request.status == 200){
/* All headers received as a single string */
var headers = request.getAllResponseHeaders( );
var div = document.getElementById("msgDisplay");
if(st){
setStyle(st,div.style);
} else {
setStyle("plain",div.style);
}
div.innerHTML="<pre>"+headers+"</pre>";
select lists, and then submitting the forms by clicking a button. The purpose of these forms is to upload user- or client-related data to a server component, which then implements a task such as logging the user into an application. XMLHttpRequest, and how to dynamically generate the content of display widgets from server data.
textarea. The application code waits for the text widget’s
onblur event to occur, then uses the request object to send just the data from that field or textarea. In many applications, this technique is preferable to requiring the user to click a Submit button, then sending all of the form’s values to the server in a big clump. It is also much snappier in terms of the application’s responsiveness. For example, an online quiz or teaching application can fetch and display the correct answer to a question as soon as the user has moved away from the field, instead of requiring the user to click a button and refresh the page just to see specific answers. Real-time language translation is another possible application for this user-interface behavior.
textarea. The application code waits for the text widget’s
onblur event to occur, then uses the request object to send just the data from that field or textarea. In many applications, this technique is preferable to requiring the user to click a Submit button, then sending all of the form’s values to the server in a big clump. It is also much snappier in terms of the application’s responsiveness. For example, an online quiz or teaching application can fetch and display the correct answer to a question as soon as the user has moved away from the field, instead of requiring the user to click a button and refresh the page just to see specific answers. Real-time language translation is another possible application for this user-interface behavior.onblur event is triggered when a web form control such as a text field loses the keyboard focus, which is typically caused by the user pressing the Tab key or clicking outside of the field. You can also use the onkeypress, onkeydown, or
onkeyup event handlers to respond to user interaction with a text widget.textarea. textarea.textarea or text field values to a server component behind the scenes. textarea.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="js/hacks_2_1.js"></script>
<link rel="stylesheet" type="text/css" href="/css/hacks.css" />
<title>Submit your information</title>
</head>
<body>
<h3>Get stats from textareas and textfields using Ajax</h3>
<form action="javascript:void%200" >
<table border="0"><tr>
<td>Enter a few words for submitting to our server:
select list directly to a server program using the request object, rather than requiring the user to click a button and send the entire form. This gives the application greater responsiveness and increases efficiency by sending discrete values rather than clumps of information.select list. The select element looks like this in the HTML code that underlies the web page:<select name="_state" multiple="multiple" size="4">
select list (because the user presses the Tab key or clicks elsewhere on the page), the code defined by the element’s onblur event handler executes. (This code is shown in an upcoming section.) The size=4 part indicates that four state names can be displayed at a time in the select list. Figure 2-4 shows the page loaded into the Safari browser.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="js/hacks_2_4.js"></script>
<link rel="stylesheet" type="text/css" href="/css/hacks.css" />
<title>Alter select lists</title>
</head>
<body>
<h3>Create or Alter a Select List</h3>
<form action="javascript:void%200" >
<table border="0">
<tr><td>Choose one or more states: </td><td>
<select name="_state" multiple="multiple" size="4">
<option value="al">Alabama</option>
<option value="ak">Alaska</option>
<option value="az">Arizona</option>
<option value="ar">Arkansas</option>
<option value="ca">California</option>
<option value="co">Colorado</option>
<option value="ct">Connecticut</option>
<option value="de">Delaware</option>
<option value="dc">District of Columbia</option>
<option value="fl">Florida</option>
<option value="ga">Georgia</option>
<option value="hi">Hawaii</option>
<!—snipped...-->
</select></td></tr>
<tr><td>select list has a choice for hardware platform, such as Apple or HP, which generates (when the user makes a choice) a second list of related operating systems, and so on. Ajax can shine in these situations where the user interface can automatically be customized for the browser user, as well as where the content for the select list must come from a server.select list. However, the choices for the new list would have to be hardcoded into the JavaScript. Ultimately, this content for new lists will change, creating an awkward situation in which developers have to constantly add persistent lists to an existing JavaScript file. Without being able to store these values in a sensible location such as a database or other persistent store, this application model becomes unwieldy.
select list above the radio buttons because that code appears in the previous hack:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="js/hacks_2_4.js"></script>
<link rel="stylesheet" type="text/css" href="/css/hacks.css" />
<title>Alter select lists</title>
</head>
<body>
<h3>Create or Alter a Select List</h3>
<form action="javascript:void%200" >
<table border="0">
<tr><td>Choose one or more states: </td>
<td><select name="_state" multiple="multiple" size="4">
<option value="al">Alabama</option>
<!—more options... -->
</select></td></tr>
<tr><td><span id="select_info" class="message">
The server reports that you have chosen the following abbreviatedselect element used in “Submit Selection-List Values to the Server Without a Round Trip” [Hack #14]. As part of the customer-registration process, you ask what state your customers live in (for sales-tax purposes, say). However, you want to be able register customers from other countries too, because your product can now be distributed overseas. You do not want to include every country on earth in the select list, though, both for geo-political reasons (countries frequently change, as in the case of the former Yugoslavia) and because the select list would be too big to fit nicely on the page. Thus, you want your users to be able to choose (when applicable) a continent, making a selection that adds a subset of select options to the page. Your application will pass the name of the selected continent to the server program and query the server for the specific countries associated with that continent.select list of continents. When the user makes a selection, the names of the countries within that continent are derived from the server and automatically added to an existing select list, without the page being refreshed. Figure 2-8 shows the web page for this hack, which is based on the previous hack containing the select list of U.S. states.
select list. This action triggers the onclick event for the select element. Here is the HTML code for the page:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="js/hacks2_6.js"></script>
<link rel="stylesheet" type="text/css" href="/css/hacks.css" />
<title>Alter select lists</title>
</head>
<body>
<h3>Add Entries to a Select List</h3>
<form action="javascript:void%200">
<table border="0">
<tr><td>Add your country: <select id="cts" name="_continents">
<option value="southam">South America</option>
<option value="euro">Europe</option>
</select></td></tr><tr><td>Choose one or more states: </td>
<td> <select id="sts" name="_state" multiple="multiple" size="4">
<option value="al">Alabama</option>
<option value="ak">Alaska</option>
<option value="az">Arizona</option>
<option value="ar">Arkansas</option>
<option value="ca">California</option>
<option value="co">Colorado</option>
<option value="ct">Connecticut</option>
<option value="de">Delaware</option>
<option value="dc">District of Columbia</option>
<option value="fl">Florida</option>
<option value="ga">Georgia</option>
<option value="hi">Hawaii</option>
<!--snipped here...-->
</select></td></tr>
</table>
</form>
</body>
</html>
XMLHttpRequest object to send the sport choices and handle the server’s response, and it uses DOM programming and CSS to display the poll results. Here is the HTML code for the page:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="js/hacks2_5.js"></script>
<link rel="stylesheet" type="text/css" href="/css/hacks2_5.css" />
<title>submit checkbox values</title>
</head>
<body>
<h3>Choose your favorite sports</h3>
<h4>Team sport</h4>
<form id="team" action="javascript:void%200" method="get">
<div id="team_d" class="team">
<input type="checkbox" name="team_sports" id=
"baseball" value="baseball" /> Baseball <br />
<input type="checkbox" name="team_sports" id=
"soccer" value="soccer" /> Soccer <br />
<input type="checkbox" name="team_sports" id=
"football" value="football" /> Football <br />
<input type="checkbox" name="team_sports" id=
"basketball" value="basketball" /> Basketball <br />
<input type="checkbox" name="team_sports" id=
"lacrosse" value="lacrosse" />Lacrosse <br />
<input type="checkbox" name="team_sports" id=
"hockey" value="hockey" /> Hockey <br />
<input type="checkbox" name="team_sports" id=
"tennis" value="tennis" /> Tennis <br />
</div>
</form>
<div id="team_poll" class="poll">
<span id="t_title" class="p_title"></span>
<span id="t_results" class="p_results"></span></div>
<h4>Individual sport</h4>
<form id="ind" action="javascript:void%200" method="get">
<div id="ind_d" class="ind">
<input type="checkbox" name="individual_sports" id=
"cycling" value="cycling" /> Cycling <br />
<input type="checkbox" name="individual_sports" id=
"running" value="running" /> Running <br />
<input type="checkbox" name="individual_sports" id=
"swimming" value="swimming" /> Swimming <br />
<input type="checkbox" name="individual_sports" id=
"nordic_skiing" value="nordic_skiing" />Nordic Skiing <br />
<input type="checkbox" name="individual_sports" id=
"inline_skating" value="inline_skating" />Inline Skating <br />
<inpu