410 likes | 542 Views
AJAX Chapters 10 & 12. Synchronous web communication. synchronous : user must wait while new pages load the typical communication pattern used in web pages ( click , wait, refresh ). Web applications and Ajax.
E N D
AJAX Chapters 10 & 12
Synchronous web communication • synchronous: user must wait while new pages load • the typical communication pattern used in web pages (click, wait, refresh)
Web applications and Ajax • web application: a web site that mimics the look, feel, and overall user experience of a desktop application • a web app presents a continuous user experience rather than disjoint pages • as much as possible, "feels" like a normal program to the user • examples of web apps • Gmail, Google Maps, Google Docs and Spreadsheets, Flickr, A9 • many web apps use Ajax to battle these problems of web pages: • slowness / lack of UI responsiveness • lack of user-friendliness • Harsh nature of "click-wait-refresh" pattern
What is Ajax? • 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 • aids in the creation of rich, user-friendly web sites • Term Ajax was coined by Jesse James Garrett of Adaptive Path in February 2005, when he was presenting the previously unnamed technology to a client • Ajax involves technologies that have existed for longtime such as HTML, JavaScript, CSS, the DOM and XML
Asynchronous web communication • asynchronous: user can keep interacting with page while data loads • communication pattern made possible by Ajax
Ajax • Ajax applications separateclient-side user interaction and server communication, and run themin parallel, making the delays of server-side processing more transparent to the user • uses JavaScript to send asynchronous requests to the server, then updates the page using the DOM (in the background, transparent to user) • XML and JSON are used to structure the data passed between the server and the client (seen later)
Core Ajax concepts • JavaScript includes an XMLHttpRequest object that can fetch files from a web server • Resides on the client • Is the layer between the client and the server that manages asynchronous requests in Ajax applications • Supported in IE7+, Safari, Firefox, Opera, Chrome, etc. (all major browsers) • the contents of the fetched file can be put into current web page using the DOM • NOTE: Ajax can fetch files from the same web server where your page is hosted. As a result, you need to upload your Ajax code to the server then test it.
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 • XMLHttpRequestfires an event when data arrives • this is often called a callback • you can attach a handlerfunctionto this event • 6) your callback event handler processes the data and displays it
Levels of using XMLHttpRequest • we'll learn to use Ajax in 4 steps: • synchronous, text-only (SJAT?) • asynchronous, text-only (AJAT?) • asynchronous w/ Prototype (AJAP?) • asynchronous w/ XML data (real Ajax)
XMLHttpRequest methods • the core JavaScript object that makes Ajax possible
1. Synchronous requests (bad) varajax = 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; • create the request object, open a connection, send the request • when send returns, the fetched text will be stored in request's responseText property • Why synchronous requests are bad • your code waits for the request to completely finish before proceeding • easier for you to program, but ... • the user's entire browser locks up until the download is completed • a terrible user experience (especially if the file is very large)
2. Asynchronous requests, basic idea varajax = new XMLHttpRequest(); ajax.onreadystatechange = functionName; ajax.open("get", url, true); ajax.send(null); // don't process ajax.responseText here, but in your function ... • attach an event handler to the request's onreadystatechange event. It will be called when request makes progress (i.e. changes): • Progress is monitored by the readyStateproperty • pass true as third parameter to open • readyStatechanges → onreadystatechange handler runs • usually we are only interested in readyState of 4 (complete) • function's code will be run when request is complete
Asynchronous XMLHttpRequest template varajax = 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); • most Ajax code uses an anonymous function as the event handler • useful to declare it as an inner anonymous function, because then it can access surrounding local variables (e.g. ajax)
Quick Example <body> <h1>Quick Ajax example</h1> <div> <input id="dumptext" type="text" size="50" value="digg.html" /> <button id ="button" >Fetch</button> </div> <div id="dumpdiv"></div> </div> </body> window.onload = function() { document.getElementById("button").onclick= run; }; function run( ) { varurl = document.getElementById("dumptext").value; vardumpTarget = document.getElementById("dumpdiv"); ajaxDump(url, dumpTarget); } function ajaxDump(url, dumpTarget) { varajax = new XMLHttpRequest(); ajax.onreadystatechange = function() { if (ajax.readyState == 4) { dumpTarget.innerHTML = ajax.responseText; } }; try { ajax.open("get", url, true); ajax.send(null); } catch (e if ("" + e).match(/denied/)) { alert("Ajax security error: cannot fetch " + url); } }
Checking for request errors varajax = 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); • web servers return status codes for requests (200 means Success) • you may wish to display a message or take action on a failed request
XMLHttpRequest Object: Summary Steps • Create an instance of the XMLHttpRequestobject • Use openmethod to set up the request, • ajax.open(method, url, async); • Method: “GET” or “POST” • urlis a string representation of URL • If async is set to false means the request is synchronous. Otherwise, it is asynchronous • After open, use sendmethod to initiate the request • ajax.send(data) • Data should be null for get request • Register a callback functionas the event handler for the XMLHttpRequest object’s onreadystatechangeevent • Whenever the request makes progress, event handler is called • Progress is monitored by the readyStateproperty, which has a value from 0 to 4 • value 4 indicates that the request is complete.
Exception handling XMLHttpRequest Object • An exception is an indication of a problem that occurs during a program’s execution • Exception handling enables you to create applications that can handle exceptions • try block : try followed by a block of code enclosed in curly braces ({}) • Encloses code that might cause an exception and code that should not execute if an exception occurs • When an exception occurs • try block terminates immediately • catch block catches (i.e., receives) and handles an exception • catch block : • catch followed by an exception parameter in parentheses and a block of code enclosed in curly braces • Exception parameter’s name • Enables the catch block to interact with a caught exception object, which contains name and message properties
<body> <h1>Mouse over a book for more information.</h1> <img id="cpphtp6" src = "resources/cpphtp6.jpg" alt="cpphtp6.html"/> <img id="iw3htp4" src = "resources/iw3htp4.jpg" alt="iw3htp4.html" /> <img id="jhtp7" src = "resources/jhtp7.jpg" alt="jhtp7.html" /> <img id="vbhtp3" src = "resources/vbhtp3.jpg" alt ="vbhtp3.html"/> <img id="vcsharphtp2" src = "resources/vcsharphtp2.jpg" alt="vcsharphtp2.html" /> <img id="chtp5" src = "resources/chtp5.jpg" alt = "chtp5.html" /> <div class = "box" id = "contentArea"> </div> </body> window.onload = function() { varmyimg= document.getElementsByTagName("img"); for (vari= 0; i < myimg.length; i++) { myimg[i].onmouseover = getContent; myimg[i].onmouseout = clearContent; } }; window.onload = function() { document.getElementById("cpphtp6").onmouseover = getContent; document.getElementById("cpphtp6").onmouseout = clearContent; document.getElementById("iw3htp4").onmouseover = getContent; document.getElementById("iw3htp4").onmouseout = clearContent; document.getElementById("jhtp7").onmouseover = getContent; document.getElementById("jhtp7").onmouseout = clearContent; document.getElementById("vbhtp3").onmouseover = getContent; document.getElementById("vbhtp3").onmouseout = clearContent; document.getElementById("vcsharphtp2").onmouseover = getContent; document.getElementById("vcsharphtp2").onmouseout = clearContent; document.getElementById("chtp5").onmouseover = getContent; document.getElementById("chtp5").onmouseout = clearContent; }; varasyncRequest; function getContent( ) { // attempt to create the XMLHttpRequest and make the request try { asyncRequest = new XMLHttpRequest(); // create request object // register event handler asyncRequest.onreadystatechange = stateChange; asyncRequest.open( 'GET', this.alt, true ); // prepare the request asyncRequest.send( null ); // send the request }// end try catch ( exception ) { alert( 'Request failed.' ); }// end catch } // end function getContent
function clearContent(){ document.getElementById( 'contentArea' ).innerHTML = ''; } // end function clearContent // displays the response data on the page function stateChange() { if ( asyncRequest.readyState == 4 && asyncRequest.status == 200 ){ document.getElementById( 'contentArea' ).innerHTML = asyncRequest.responseText; // places text in contentArea } // end if } // end function stateChange
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 URLto fetch, as a String, • a set of options, as an array of key : valuepairs in {} braces (an anonymous JS object) • hides icky details from the raw XMLHttpRequest; • works well in all browsers
Prototype Ajax options new Ajax.Request("http://www.example.com/foo/bar.txt", { method: "get", parameters: {name: "Ed Smith", age: 29}, // "name=Ed+Smith&age=29" ... } );
Prototype Ajax event options • new Ajax.Request("http://www.example.com/foo.php", • { • parameters: {password: "abcdef"}, // "password=abcdef" • onSuccess: mySuccessFunction • } • );
Basic Prototype Ajax template • new Ajax.Request( • "url", • { • method: "get", • onSuccess: functionName • } • ); • ... • function functionName(ajax) { • do something withajax.responseText; • } • most Ajax requests we'll do in this course are GET requests • attach a handler to the request's onSuccess event • the handler accepts the XMLHttpRequest object as a parameter, which we'll name ajax,
Ajax response object's properties • function handleRequest(ajax) { • alert(ajax.responseText); • } • most commonly used property is responseText, to access the fetched text content
Quick Example <body> <h1>Quick Ajax example</h1> <div> <input id="dumptext" type="text" size="50" value="digg.html" /> <button id ="button" >Fetch</button> </div> <div id="dumpdiv"></div> </div> </body> window.onload = function() { document.getElementById("button").onclick= run; }; function run( ) { varurl = document.getElementById("dumptext").value; vardumpTarget = document.getElementById("dumpdiv"); ajaxDump(url, dumpTarget); } function ajaxDump(url, dumpTarget) { varajax = new XMLHttpRequest(); ajax.onreadystatechange = function() { if (ajax.readyState == 4) { dumpTarget.innerHTML = ajax.responseText; } }; try { ajax.open("get", url, true); ajax.send(null); } catch (e if ("" + e).match(/denied/)) { alert("Ajax security error: cannot fetch " + url); } } document.observe('dom:loaded', function () { $('button').observe('click', run); }); function run() { new Ajax.Request( $("dumptext").value, { method: "get", onSuccess: ajaxDump} ); } function ajaxDump(ajax) { $("dumpdiv").innerHTML = ajax.responseText; }
XMLHttpRequest security restrictions • cannot be run from a web page stored on your hard drive • can only be run on a web page stored on a web server • can only fetch files from the same site that the page is on • http://www.foo.com/a/b/c.html can only connect to www.foo.com
Handling Ajax errors new Ajax.Request("url", { method: "get", onSuccess: functionName, onFailure: ajaxFailure, onException: ajaxFailure } ); ... function ajaxFailure(ajax, exception) { varmsg = "Error making Ajax request: \n\n "; if (exception) { msg += exception.message; } else { msg += "Server status:\n" + ajax.status + " " + ajax.statusText + "\n\nServer response text:\n" + ajax.responseText; } alert(msg); } • Error handler accept another optional parameter representing any exception. • for user's (and developer's) benefit, show an error message if a request fails • a good failure message shows the HTTP error code and status text
Ajax code bugs • When writing Ajax programs, there are new kinds of bugs that are likely to appear. • Nothing happens! • The responseText or responseXML has no properties. • The data isn't what I expect. • How do we find and fix such bugs?
Debugging Ajax code • Net tab shows each request, its parameters, response, any errors • expand a request with + and look at Response tab to see Ajax result
Creating a POST request new Ajax.Request("url", { method: "post", // optional parameters: { name: value, name: value, ..., name: value }, onSuccess: functionName, onFailure: functionName, onException: functionName } ); • method should be changed to "post" (or omitted; post is default) • any query parameters should be passed as a parameter • written between {}braces as a set of name : valuepairs (another anonymous object) • get request parameters can also be passed this way, if you like 32
Prototype's Ajax Updater new Ajax.Updater("id", "url", { method: "get" } ); • Ajax.Updaterfetchesa file and injects its content into an element as innerHTML • 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)
Quick Example <body> <h1>Quick Ajax example</h1> <div> <input id="dumptext" type="text" size="50" value="digg.html" /> <button id ="button" >Fetch</button> </div> <div id="dumpdiv"></div> </div> </body> document.observe('dom:loaded', function () { $('button').observe('click', run); }); function run() { new Ajax.Request( $("dumptext").value, { method: "get", onSuccess: ajaxDump} ); } new Ajax.Updater( "dumpdiv", $("dumptext").value, { method: "get" } ); function ajaxDump(ajax) { $("dumpdiv").innerHTML = ajax.responseText; }
Quick Example <body> <h1>Quick Ajax example</h1> <div> <input id="dumptext" type="text" size="50" value="digg.html" /> <button id ="button" >Fetch</button> </div> <div id="dumpdiv"></div> </div> </body> document.observe('dom:loaded', function () { $('button').observe('click', run); }); function run() { new Ajax.Updater( "dumpdiv", $("dumptext").value, { method: "get", onFailure: ajaxFailure, onException: ajaxFailure } ); } function ajaxFailure(ajax, exception) { varmsg = "Error making Ajax request: \n\n "; if (exception) { msg += exception.message; } else { msg += "Server status:\n" + ajax.status + " " + ajax.statusText + "\n\nServer response text:\n" + ajax.responseText; } alert(msg); }
PeriodicalUpdater new Ajax.PeriodicalUpdater("id", "url", { frequency: seconds, option: value, ... } ); • Ajax.PeriodicalUpdater repeatedly fetches a file at a given interval and injects its content into innerHTML of a container identified by “id” • onSuccess handler not needed (but onFailure, onException handlers may still be useful)
Another Example: Syn Vs Asyn <h1>transcript example</h1> <div> <button id ="load" >load notes</button> <button id ="displaytranscript" >display transcript</button> </div> <div id="output"></div> <div id="transcriptarea"></div> </div> window.onload = function() { $("load").onclick = loadClick; $("displaytranscript").onclick = displayTranscriptClickAsync; } function loadClick() { varajax = new XMLHttpRequest(); ajax.open("GET", "notes.txt", false); ajax.send(null); // at this point in the code, the web //request has completed $("output").innerHTML = ajax.responseText; }
Another Example: Syn Vs Asyn function displayTranscriptClickAsync() { new Ajax.Request( "transcript.txt", { method: "get", onSuccess: ajaxDump } ); } function ajaxDump(ajax) { // fetch the text var lines = ajax.responseText.split("\n"); // convert the lines of text into DOM items //in an unordered list varul = document.createElement("ul"); for (vari = 0; i < lines.length; i++) { varli = document.createElement("li"); li.innerHTML = lines[i]; ul.appendChild(li); } // place the list onto the page in the //transcriptarea div $("transcriptarea").appendChild(ul); } 39
XMLHttpRequestmore events varajax = new XMLHttpRequest(); ajax.onload = sucFunctionName; ajax.onerror = errorFunctionName; ajax.open("GET", url, true); ajax.send(); ... function sucFunctionName() { if (this.status == 200) {// 200 means request succeeded do something with this.responseText; } else { code to handle the error; } } function errorFunctionName(exception) {do something } • onloadevent handlercontains code to run when request is complete • inside your handler function, this will refer to the ajaxobject that you can access its properties • onerrorevent handler is passed the error/exception as a parameter • you can examine the error, and other properties, to determine what went wrong 40
XMLHttpRequestmore events varajax = new XMLHttpRequest(); ajax.onload = sucFunctionName; ajax.onerror = errorFunctionName; ajax.open("GET", url, true); ajax.send(); ... function sucFunctionName() { if (this.status == 200) { // 200 means request succeeded do something with this.responseText; } else { code to handle the error; } } function errorFunctionName(exception) { alert("Error making Ajax request:" + "\n\nServer status:\n" + this.status + " " + this.statusText + "\n\nServer response text:\n" + this.responseText); if (exception) { throw exception; } } 41