Except where otherwise noted, the contents of this presentation are Copyright 2009 Marty Stepp and Jessica Miller.
XMLHttpRequest
Ajax: Asynchronous JavaScript and XML
XMLHttpRequest object can fetch files from a web server
XMLHttpRequest objectXMLHttpRequest object requests a document from a web serverXMLHttpRequest fires event to say that the data has arrived
XMLHttpRequest
XMLHttpRequest objectthe core JavaScript object that makes Ajax possible
abort, getAllResponseHeaders, getResponseHeader, open, send, setRequestHeader
onreadystatechange, readyState, responseText, responseXML, status, statusText
ActiveXObject instead
var ajax = new XMLHttpRequest();
ajax.open("GET", url, false);
ajax.send(null);
// at this point, the request will have returned with its data
do something with ajax.responseText;
send returns, the fetched text will be stored in request's responseText property
var ajax = new XMLHttpRequest();
ajax.onreadystatechange = functionName;
ajax.open("get", url, true);
ajax.send(null);
// don't process ajax.responseText here, but in your function
...
onreadystatechange eventtrue as third parameter to openreadyState propertyXMLHttpRequestreadyState property:
| State | Description |
|---|---|
| 0 | not initialized |
| 1 | set up |
| 2 | sent |
| 3 | in progress |
| 4 | complete |
readyState changes → onreadystatechange handler runsreadyState of 4 (complete)XMLHttpRequest template
var ajax = new XMLHttpRequest();
ajax.onreadystatechange = function() {
if (ajax.readyState == 4) { // 4 means request is finished
do something with ajax.responseText;
}
};
ajax.open("get", url, true);
ajax.send(null);
ajax)
var ajax = new XMLHttpRequest();
ajax.onreadystatechange = function() {
if (ajax.readyState == 4) {
if (ajax.status == 200) { // 200 means request succeeded
do something with ajax.responseText;
} else {
code to handle the error;
}
}
};
ajax.open("get", url, true);
ajax.send(null);
new Ajax.Request(
"url",
{
option : value,
option : value,
...
option : value
}
);
Ajax.Request object constructor accepts 2 parameters:
{} bracesonreadystatechange, etc.)Ajax.Request constructor:
method : how to fetch the request from the server (default "post")
parameters : query parameters to pass to the server, if any
asynchronous (default true),
contentType,
encoding,
requestHeaders
Ajax.Request object that you can handle:
onSuccess : request completed successfully
onFailure : request was unsuccessful
onCreate,
onComplete,
onException,
on### (handler for HTTP error code ###)
new Ajax.Request(
"url",
{
method: "get",
onSuccess: functionName
}
);
...
function functionName(ajax) {
do something with ajax.responseText;
}
onSuccess eventXMLHttpRequest object, ajax, as a parameter
new Ajax.Request(
"url",
{
method: "get",
onSuccess: functionName,
onFailure: ajaxFailure
}
);
...
function ajaxFailure(ajax) {
alert("Error making Ajax request:" +
"\n\nServer status:\n" + ajax.status + " " + ajax.statusText +
"\n\nServer response text:\n" + ajax.responseText);
}
POST request
new Ajax.Request(
"url",
{
method: "POST", // optional
parameters: { name: value, name: value, ..., name: value },
onSuccess: functionName,
onFailure: functionName
}
);
Ajax.Request can also be used to post data to a web servermethod should be changed to "post" (or omitted; post is default)parameters parameter, written between {} braces as name: value pairs
get request parameters can also be passed this way, if you like
new Ajax.Updater(
"id",
"url",
{
method: "get"
}
);
Ajax.Updater can be used if you want to fetch a file via Ajax and inject its text/HTML contents into an onscreen elementid of the element into which to inject the contentWhen writing Ajax programs, there are new kinds of bugs that are likely to appear.
responseText or responseXML has no properties.How do we find and fix such bugs?
XMLHttpRequest security restrictions
www.foo.com/a/b/c.html can only fetch from www.foo.comXMLHttpRequest
<... ...="..."></...>h1, img) and attributes (id/class on all elements, src/alt on img tag)<?xml version="1.0" encoding="UTF-8"?> <note> <to>Tove</to> <from>Jani</from> <subject>Reminder</subject> <message language="english"> Don't forget me this weekend! </message> </note>
note)to, from, subjectbook, title, author<bloop bleep="flibbetygibbet">quirkleblat</bloop>
new Ajax.Request(
"url",
{
method: "get",
onSuccess: functionName
}
);
...
function functionName(ajax) {
do something with ajax.responseXML;
}
ajax.responseText contains the XML data in plain textajax.responseXML is a pre-parsed DOM object representing the XML file as a tree (more useful)responseXML object, using DOM methods and propertiesAll of the DOM properties and methods we already know can be used on XML nodes:
firstChild, lastChild, childNodes, nextSibling, previousSibling, parentNodenodeName, nodeType, nodeValue, attributesappendChild, insertBefore, removeChild, replaceChildgetElementsByTagName, getAttribute, hasAttributes, hasChildNodes
<?xml version="1.0" encoding="UTF-8"?> <categories> <category>children</category> <category>computers</category> ... </categories>
<?xml version="1.0" encoding="UTF-8"?> <foo bloop="bleep"> <bar/> <baz><quux/></baz> <baz><xyzzy/></baz> </foo>
We can use DOM properties and methods on ajax.responseXML:
// zeroth element of array of length 1 var foo = ajax.responseXML.getElementsByTagName("foo")[0]; // same var bar = foo.getElementsByTagName("bar")[0]; // array of length 2 var all_bazzes = foo.getElementsByTagName("baz"); // string "bleep" var bloop = foo.getAttribute("bloop");
<?xml version="1.0" encoding="UTF-8"?> <foo bloop="bleep"> <bar/> <baz><quux/></baz> <baz><xyzzy/></baz> </foo>
We are reminded of some pitfalls of the DOM:
// works - XML prolog is removed from document tree var foo = ajax.responseXML.firstChild; // WRONG - just a text node with whitespace! var bar = foo.firstChild; // works var first_baz = foo.getElementsByTagName("baz")[0]; // WRONG - just a text node with whitespace! var second_baz = first_baz.nextSibling; // works - why? var xyzzy = second_baz.firstChild;
<?xml version="1.0" encoding="UTF-8"?> <bookstore> <book category="cooking"> <title lang="en">Everyday Italian</title> <author>Giada De Laurentiis</author> <year>2005</year><price>30.00</price> </book> <book category="computers"> <title lang="en">XQuery Kick Start</title> <author>James McGovern</author> <year>2003</year><price>49.99</price> </book> <book category="children"> <title lang="en">Harry Potter</title> <author>J K. Rowling</author> <year>2005</year><price>29.99</price> </book> <book category="computers"> <title lang="en">Learning XML</title> <author>Erik T. Ray</author> <year>2003</year><price>39.95</price> </book> </bookstore>
ids or classes to use to get specific nodesfirstChild/nextSibling properties are unreliablegetElementsByTagName:
node.getElementsByTagName("tagName")
"book", "subject", etc.)
node.getAttribute("attributeName")
category, lang)// make a paragraph for each book about computers var books = ajax.responseXML.getElementsByTagName("book"); for (var i = 0; i < books.length; i++) { var category = books[i].getAttribute("category"); if (category == "computers") { var title = books[i].getElementsByTagName("title")[0].firstChild.nodeValue; var author = books[i].getElementsByTagName("author")[0].firstChild.nodeValue; // make an XHTML <p> tag based on the book's XML data var p = document.createElement("p"); p.innerHTML = title + ", by " + author; document.body.appendChild(p); } }
ajax.responseTextresponseXML in Firebug