Web Programming Step by Step, 2nd Edition
Lecture 21: Ajax
Reading: 12.1 - 12.2
Except where otherwise noted, the contents of this document are
Copyright 2012 Marty Stepp, Jessica Miller, and Victoria Kirst.
All rights reserved.
Any redistribution, reproduction, transmission, or storage of part
or all of the contents in any form is prohibited without the author's
expressed written permission.
Synchronous web communication
- synchronous: user must wait while new pages load
-
the typical communication pattern used in web pages (click, wait, refresh)
-
web application: a dynamic web site that mimics the feel of a desktop app
-
Ajax: Asynchronous JavaScript and XML
- not a programming language; a particular way of using JavaScript
- downloads data from a server in the background
- allows dynamically updating a page without making the user wait
- avoids the "click-wait-refresh" pattern
-
examples: UW's CSE 14x Diff Tool, Practice-It;
Google Suggest
Asynchronous web communication
- asynchronous: user can keep interacting with page while data loads
-
communication pattern made possible by Ajax
- JavaScript includes an
XMLHttpRequest
object that can fetch files from a web server
- supported in IE5+, Safari, Firefox, Opera, Chrome, etc. (with minor compatibilities)
- it can do this asynchronously (in the background, transparent to user)
- the contents of the fetched file can be put into current web page using the DOM
- sounds great!...
- ... but it is clunky to use, and has various browser incompatibilities
- Prototype provides a better wrapper for Ajax, so we will use that instead
A typical Ajax request
- user clicks, invoking an event handler
- handler's code creates an
XMLHttpRequest
object
XMLHttpRequest
object requests page from server
- server retrieves appropriate data, sends it back
XMLHttpRequest
fires an event when data arrives
- this is often called a callback
- you can attach a handler function to this event
- your callback event handler processes the data and displays it
An aside: Creating a new anonymous object
var name = {
fieldName: value,
...
fieldName: value
};
var pt = {
x: 4,
y: 3,
distanceFromOrigin: function() {
return Math.sqrt(this.x * this.x + this.y * this.y);
}
};
alert(pt.x + ", " + pt.y + ", dist=" + pt.distanceFromOrigin());
- in JavaScript, you can create a new object without creating a class
- the object can have methods (function properties) that refer to itself as
this
Prototype's Ajax model
new Ajax.Request("url", {
option : value,
option : value,
...
option : value
});
- construct a Prototype
Ajax.Request
object to request a page from a server using Ajax
- constructor accepts 2 parameters:
- the URL to fetch, as a String,
-
a set of options, as a set of key : value pairs in
{}
braces
(an anonymous JS object)
- hides icky details of the raw
XMLHttpRequest
; works well in all browsers
Prototype Ajax
option |
description |
method
|
how to fetch the request from the server (default "post" )
|
asynchronous
|
should request be sent asynchronously in the background? (default true )
|
parameters
|
query parameters to pass to the server, if any (as a string or object)
|
onSuccess
|
event: request completed successfully
|
onFailure
|
event: request was unsuccessful
|
onException
|
event: request has a syntax error, security error, etc.
|
others: contentType , encoding ,
requestHeaders ; events: onCreate , onComplete ,
on### (for HTTP error code ###)
|
Prototype Ajax example
new Ajax.Request("foo/bar/mydata.txt", {
method: "get",
onSuccess: myAjaxSuccessFunction
});
...
function myAjaxSuccessFunction(ajax) {
do something with ajax.responseText
;
}
- attach an event handler function to the request's
onSuccess
event
- the handler takes an Ajax response object as a parameter, which we'll name
ajax
Ajax response object's properties
property |
description |
status
|
the request's HTTP result code (200 = OK, etc.)
|
statusText
|
HTTP status code text
|
responseText
|
the entire text of the fetched file, as a string
|
responseXML ,
responseJSON
|
the entire contents of the fetched file, in other formats (seen later)
|
function myAjaxSuccessFunction(ajax) {
alert(ajax.responseText);
}
- most commonly used property is
responseText
, to access the fetched text content
Handling Ajax errors
new Ajax.Request("url", {
method: "get",
onSuccess: functionName,
onFailure: ajaxFailure,
onException: ajaxFailure
});
...
function ajaxFailure(ajax, exception) {
alert("Error making Ajax request:" +
"\n\nServer status:\n" + ajax.status + " " + ajax.statusText +
"\n\nServer response text:\n" + ajax.responseText);
if (exception) {
throw exception;
}
}
- for user's (and developer's) benefit, show an error message if a request fails
Debugging Ajax code
- Firebug Net tab (or Chrome's Network tab) shows each request, parameters, response, errors
- expand a request with + and look at Response tab to see Ajax result
- check Console tab for any errors that are thrown by requests
Passing query parameters to a request
new Ajax.Request("lookup_account.php", {
method: "get",
parameters: {name: "Ed Smith", age: 29, password: "abcdef"},
onFailure: ajaxFailure,
onException: ajaxFailure
});
...
- don't concatenate the parameters onto the URL yourself with
"?" +
...
- won't properly URL-encode the parameters
- won't work for POST requests
- query parameters are passed as a
parameters
object, {}
braces with name : value pairs
- (the above is equivalent to:
"name=Ed+Smith&age=29&password=abcdef"
)
Creating a POST
request
new Ajax.Request("url", {
method: "post",
parameters: {name: value, name: value, ..., name: value},
onSuccess: functionName,
onFailure: functionName,
onException: functionName
});
method
should be changed to "post"
(or omitted; post
is default)
XMLHttpRequest
security restrictions
- Ajax must be run on a web page stored on a web server
- (cannot be run from a web page stored on your hard drive)
- Ajax can only fetch files from the same server that the page is on
http://www.foo.com/a/b/c.html
can only fetch fromwww.foo.com
Prototype's Ajax Updater
new Ajax.Updater("id", "url", {
method: "get"
});
Ajax.Updater
fetches a file and injects its content into an element as innerHTML
- this is a common Ajax use case: "go fetch this page/file, and put its contents into an element on the page"
- could do this with
Ajax.Request
, but Ajax.Updater
saves you some typing and work
- additional (1st) parameter specifies the
id
of element to inject into
onSuccess
handler not needed (but onFailure
, onException
handlers may still be useful)
Ajax.Updater options
new Ajax.Updater({success: "id", failure: "id"}, "url", {
method: "get",
insertion: "top"
});
- instead of passing a single id, you can pass an object with a
success
and/or failure
id
- the
success
element will be filled if the request succeeds
- the
failure
element (if provided) will be filled if the request fails
insertion
parameter specifies where in the element to insert the text (top, bottom, before, after)
PeriodicalUpdater
new Ajax.PeriodicalUpdater("id", "url", {
frequency: seconds,
name: value, ...
});
Ajax.PeriodicalUpdater
repeatedly fetches a file at a given interval and injects its content into an element as innerHTML
onSuccess
handler not needed (but onFailure
, onException
handlers may still be useful)
- same options as in
Ajax.Updater
can be passed
Ajax.Responders
Ajax.Responders.register({
onEvent: functionName,
onEvent: functionName,
...
});
- sets up a default handler for a given kind of event for all Ajax requests
- can be useful for attaching a common failure/exception handler to all requests in one place