Web Programming Step by Step

Chapter 10
Ajax and XML for Accessing Data

Except where otherwise noted, the contents of this presentation are Copyright 2009 Marty Stepp and Jessica Miller.

Valid XHTML 1.1 Valid CSS!

10.1: Ajax Concepts

Synchronous web communication (10.1)

synchronous communication

Web applications

What is Ajax?

Ajax bleach

Ajax: Asynchronous JavaScript and XML

Asynchronous web communication

synchronous communication

Quick Ajax example

Core Ajax concepts

A typical Ajax request

request
  1. user clicks, invoking event handler
  2. that handler's JS code creates an XMLHttpRequest object
  3. XMLHttpRequest object requests a document from a web server
  4. server retrieves appropriate data, sends it back
  5. XMLHttpRequest fires event to say that the data has arrived
    • this is often called a callback
    • you can attach a handler to be notified when the data has arrived
  6. your callback event handler processes the data and displays it

10.2: Using XMLHttpRequest

The XMLHttpRequest object

the core JavaScript object that makes Ajax possible

1. Synchronous requests (10.2.1)

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;

Why synchronous requests are bad

man looking at his watch

2. Asynchronous requests, basic idea (10.2.3)

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
...

The readyState property

Asynchronous 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);

Checking for request errors (10.2.2)

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);

Prototype's Ajax model (10.2.4)

new Ajax.Request(
	"url",
	{
		option : value,
		option : value,
		...
		option : value
	}
);

Prototype Ajax methods and properties

Prototype Ajax template

	new Ajax.Request(
		"url",
		{
			method: "get",
			onSuccess: functionName
		}
	);
	...

function functionName(ajax) {
	do something with ajax.responseText;
}

Handling Ajax errors w/ Prototype

	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);
}

Creating a POST request

new Ajax.Request(
	"url",
	{
		method: "POST",   // optional
		parameters: { name: value, name: value, ..., name: value },
		onSuccess: functionName,
		onFailure: functionName
	}
);

Prototype's Ajax Updater

	new Ajax.Updater(
		"id",
		"url",
		{
			method: "get"
		}
	);

Ajax code bugs (10.2.5)

When writing Ajax programs, there are new kinds of bugs that are likely to appear.

How do we find and fix such bugs?

Debugging Ajax code

Firebug Ajax

XMLHttpRequest security restrictions

Ajax security error

10.3: XML

What is XML?

An example XML file

<?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>

What tags are legal in XML?

Schemas

Uses of XML

Pros and cons of XML

Fetching XML using AJAX (template)

	new Ajax.Request(
		"url",
		{
			method: "get",
			onSuccess: functionName
		}
	);
	...

function functionName(ajax) {
	do something with ajax.responseXML;
}

Using XML data in a web page

Recall: Javascript XML (XHTML) DOM

All of the DOM properties and methods we already know can be used on XML nodes:

XML DOM tree structure

node tree
<?xml version="1.0" encoding="UTF-8"?>
<categories> 
  <category>children</category> 
  <category>computers</category> 
  ... 
</categories>

Analyzing a fetched XML file using DOM

<?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");

Recall: Pitfalls of the DOM

<?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;

Larger XML file example

<?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>

Navigating the node tree

Navigating node tree example

// 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);
	}
}

A historical interlude: why XHTML?

Why XML in AJAX?

Debugging responseXML in Firebug

Firebug Debug Ajax