Implementing AJAX Features

Implementing AJAX Features
Dr.NaveenBansal Profile Pic
Published Date:25-10-2017
Your Website URL(Optional)
8644ch13FINAL.qxd 1/30/08 2:43 PM Page 399 CHAPTER 13 Implementing AJAX Features In this chapter we’ll enhance our fully functional shopping cart using the technology that made web development headlines in 2005. This technology is called AJAX, and it allows you to make your web applications easier and more pleasant to use for your visitors. Although AJAX isn’t a huge subject, at least compared to other programming fields, it doesn’t have a trivial learning curve either. We’re going to be here with you the whole way, but you should know there are several AJAX books on the market, including two written specifically for PHP developers: AJAX and PHP: Building Responsive Web Applications (Cristian Darie, Bogdan Brinzarea, Filip Chereches-Tosa, and Mihai Bucica, Packt Publishing, 2006.) and Beginning AJAX with PHP: From Novice to Professional (Lee Babin. Apress, 2006.). In this chapter we’ll take you through a very concise AJAX tutorial, and then we’ll update TShirtShop to • Allow adding new products to the shopping cart without completely reloading the web page when the Add to Cart buttons are clicked. This way, clicking an Add to Cart button will update the shopping cart much faster, without freezing the web page while the action happens. • Improve the responsiveness of the shopping cart actions, such as changing the product quantity, removing products, or saving them to the “Save for later” section. Admittedly, these might not seem like huge feature improvements. However, they’re the kind of nice touches that improve a user’s experience on your site, and they can differentiate a modern web site from one that feels like it was created in the last century. AJAX Quick Start The great advantage AJAX can bring to a web application is that it improves the responsiveness of the application. Responsiveness is a term we use when speaking about how fast an applica- tion responds to a user’s request. In the world of web development, this includes the time it takes for a web site (the server) to respond to a clicked link or to update a page with new data. The term AJAX was coined by Jesse James Garrett ( in 2005 as an acronym for Asynchronous JavaScript and XML. What’s in a name? If you say “not much,” we agree, at least in this case. AJAX is a programming technique that uses JavaScript on the client side to make background server calls and retrieve additional data as needed, updating certain portions of the web page without causing full page reloads. AJAX is often cited in the context of Web 2.0 ( as being one of the technologies that allows 399 1/30/08 2:43 PM Page 400 400 CHAPTER 13 ■ IMPLEMENTING AJAX FEATURES for creating next-generation web sites, which provide a friendly environment that facilitates online information sharing and collaboration. Technically, the only “new” thing about AJAX is the name. The technologies required to create AJAX web applications have been around for a while. To perform asynchronous server calls (send server requests in the background), we use the XMLHttpRequest object of JavaScript (together with a few other lesser-known techniques). To update the visitor’s page in response to the data retrieved from the server, we use the Document Object Model (DOM) eventually together with Cascading Style Sheets (CSS) for a modern presentation layer. And to encode the information passed back and forth from the server, XML (the format implied by the AJAX acronym) or other data formats can be used, with a popular alternative to XML being JavaScript Object Model (JSON). We’ll discuss each of these shortly, but first we’ll show a visual represen- tation of how an AJAX-enabled web page works. See Figure 13-1. Client requests a PHP page Server executes the PHP page and builds an HTML response The server sends a response containing HTML and JavaScript User Web Client Web Server JavaScript code makes invisible call to server Server replies by sending the data JavaScript updates the web page using this data Figure 13-1. Asynchronous server call using AJAX JavaScript JavaScript is a programming language supported by all modern web browsers, which makes it ideal for implementing various features at the client (web browser) level. JavaScript code can be included in (or referenced from) HTML pages, and it can execute when the page loads or when certain events on the page happen (such as a button being clicked). Some of the first uses of JavaScript were to add (more or less) useful graphical effects to web pages (remember the falling snow and the flying bats?), but in the meantime both the language and the skills (and tastes) of the people using it have improved. Although familiarity with JavaScript will certainly help you, we’ll teach you everything you need to improve your shop. For a comprehensive JavaScript reference, you should check out JavaScript: The Definitive Guide (David Flangan. O’Reilly, 2006.) or check one of the several free tutorials on the Web, such as those at these URLs: • • • • 1/30/08 2:43 PM Page 401 CHAPTER 13 ■ IMPLEMENTING AJAX FEATURES 401 DOM The DOM is an application programming interface (API) that allows for reading and manipu- lating hierarchical structures such as HTML and XML documents. Most languages contain a DOM component; in the context of AJAX programming, the DOM interface of JavaScript allows you to read, parse, alter, and create HTML elements of the web page. More often than not, after receiving the server response to the asynchronous call you’ve made, you’ll want to modify the page accordingly to inform the visitor of the results. JavaScript provides the default document object that is a DOM representation of the cur- rent page. For example, you can use document.write() to add content to the body element of the page, and you can use document.getElementById() to get an element of the page. For example, take the following piece of code that edits the content of the div element named cart-summary: document.getElementById("cart-summary").innerHTML = response; ■Caution There’s one obvious detail you must always keep in mind when modifying the contents of a page using JavaScript: clients that don’t support JavaScript won’t benefit from the new features. The important features of the web site must not rely on JavaScript being enabled; in other words, the implemen- tations must be degradable. A particular case of visitors that don’t execute JavaScript code is web spiders, such as those from Google, Yahoo, or MSN, indexing your web site. You must not display any important con- tent using JavaScript because it would be completely invisible to web spiders, which is not something you can typically afford when you run an online business. To learn more about the DOM, we recommend you check out the following resources: • (a DOM tutorial) • (a DOM tutorial) • (a useful and entertaining DOM game) • (a DOM reference) XMLHttpRequest XMLHttpRequest is the object you can use from your JavaScript code to make asynchronous HTTP server requests. This allows you to initiate HTTP requests and receive responses from the server in the background, without requiring the user to submit the page to the server. Typically, when the response is received from the server, the DOM is used to alter the page accordingly. This allows you to implement responsive functionality and visual effects backed with live data from the server, without the user experiencing significant visual interruptions. This is AJAX. XMLHttpRequest was implemented by Microsoft in 1999 as an ActiveX object in Internet Explorer, and it eventually became the de facto standard for all browsers, with it being supported as a native object by all modern web browsers except Internet Explorer 6. 1/30/08 2:43 PM Page 402 402 CHAPTER 13 ■ IMPLEMENTING AJAX FEATURES Let’s see how XMLHttpRequest works. You need to learn how to create the object, how to initialize it by setting the appropriate parameters, how to start the server request, and how to read the results. Creating the XMLHttpRequest Object In Internet Explorer 6 and older, XMLHttpRequest is implemented as an ActiveX control, and you create it like this: xmlHttp = new ActiveXObject("Microsoft.XMLHttp"); In Internet Explorer 7 and other web browsers—including Firefox, Opera, and Safari— XMLHttpRequest is a native object, so you create instances of it like this: xmlHttp = new XMLHttpRequest(); To create XMLHttpRequest objects for all browsers, we’ll use the following JavaScript func- tion, which creates an XMLHttpRequest instance by using the native object if available or the Microsoft.XMLHttp ActiveX control for visitors who use Internet Explorer 6 or older: // Creates an XMLHttpRequest instance function createXmlHttpRequestObject() // xmlHttp will store the reference to the XMLHttpRequest object var xmlHttp; // Try to instantiate the native XMLHttpRequest object try // Create an XMLHttpRequest object xmlHttp = new XMLHttpRequest(); catch(e) // Assume IE6 or older try xmlHttp = new ActiveXObject("Microsoft.XMLHttp"); catch(e) // Return the created object or display an error message if (xmlHttp) alert("Error creating the XMLHttpRequest object."); else return xmlHttp; 1/30/08 2:43 PM Page 403 CHAPTER 13 ■ IMPLEMENTING AJAX FEATURES 403 ■Note Microsoft.XMLHttp is the oldest version of the ActiveX XMLHttp library, but the library comes in many more flavors and versions than you could imagine. Each piece of Microsoft software, including Internet Explorer and MDAC, has shipped with new versions of this ActiveX control, each with its own name. In our code we’ll implement a technique that automatically detects the latest XMLHttp version installed on a user machine, but only if it is using Internet Explorer 6 or older. Otherwise, the native XMLHttpRequest object is still used. createXmlHttpRequestObject() uses the JavaScript try-catch construct, which is a powerful exception-handling technique that was initially implemented in object-oriented programming (OOP) languages and now is also supported by PHP 5. An exception is an object that represents an error that has happened in your code at runtime. Exceptions can be caught and dealt with, in which case they don’t block the execution of the code when they are raised. ■Note An exception propagates through the call stack of your program, from the place it was raised up to the environment on which it runs. The call stack is the list of methods being executed. So if a function A() calls a function B() that at its turn calls a function C(), then the call stack will be formed from all three methods. If an exception happens in C(), you can handle it using a try-catch block in function C() before the exception is passed out of the function. If the exception isn’t caught and handled in C(), it propagates to B(), and so on. The final layer is the web browser, which may display an unpleasant error message to your visitor, depending on how it’s configured. Using the try-catch syntax, you can catch the exception and handle it locally so that the error won’t be propagated to the user’s browser. The try-catch syntax is as follows: try // Code that might generate an exception catch (e) // Execution is passed to this block when an exception is thrown in the try block // (exception details are available through the e parameter) If an error happens while executing the code inside the try block, the execution is passed immediately to the catch block. If no error happens inside the try block, then the code in the catch block never executes. The way you handle each exception depends very much on the situation at hand. Some- times you will simply ignore the error; other times you will flag it somehow in the code, or you will display an error message to your visitor. In our particular case, when we want to create an XMLHttpRequest object, we will first try to create the object as if it were a native browser object, like this: 1/30/08 2:43 PM Page 404 404 CHAPTER 13 ■ IMPLEMENTING AJAX FEATURES // Try to instantiate the native XMLHttpRequest object try // Create an XMLHttpRequest object xmlHttp = new XMLHttpRequest(); Internet Explorer 7, Firefox, Opera, Safari, and other browsers will execute this piece of code just fine, and no error will be generated, because XMLHttpRequest is supported natively. However, Internet Explorer 6 and its older versions won’t recognize the XMLHttpRequest object, an exception will be generated, and the execution will be passed to the catch block. For Inter- net Explorer 6 and older versions, the XMLHttpRequest object needs to be created as an ActiveX control: catch(e) // Assume IE6 or older try xmlHttp = new ActiveXObject("Microsoft.XMLHttp"); catch(e) There are more techniques for creating the XMLHttpRequest object. For example, another technique is to use a JavaScript feature called object detection. This feature allows you to check whether a particular object is supported by the browser, and it works like this: if (window.XMLHttpRequest) xmlHttp = new XMLHttpRequest(); At the end of createXmlHttpRequestObject, we test that xmlHttp contains a valid XMLHttpRequest instance: // Return the created object or display an error message if (xmlHttp) alert("Error creating the XMLHttpRequest object."); else return xmlHttp; Here we used the reverse effect of JavaScript’s object detection feature, which says that JavaScript will evaluate a valid object instance, such as xmlHttp, to true. The negation of this expression—xmlHttp—returns true if xmlHttp is false, null, or undefined. (In JavaScript, undefined is a special “value” that is automatically assigned to a variable or object that has not been assigned a value.) 1/30/08 2:43 PM Page 405 CHAPTER 13 ■ IMPLEMENTING AJAX FEATURES 405 Using XMLHttpRequest Once the XMLHttpRequest object has been created, you can start using it to initiate synchronous or asynchronous server requests. Table 13-1 describes the public methods and properties of this object. Table 13-1. The XMLHttpRequest API Method/Property Description abort Stops the current request getAllResponseHeaders() Returns the response headers as a string getResponseHeader("headerLabel") Returns a single response header as a string open("method", "URL", asyncFlag, Initializes the request parameters "userName", "password") send(content) Performs the HTTP request setRequestHeader("label", "value") Sets an HTTP request header onreadystatechange Sets the callback function that handles request state changes readyState Returns the status of the request: 0 = uninitialized 1 = loading 2 = loaded 3 = interactive 4 = complete responseText Returns the server response as a string responseXml Returns the server response as an XML document that can be manipulated using JavaScript’s DOM functions status Returns the status code of the request statusText Returns the status message of the request The methods you will use with every server request are open() and send(). The open() method configures the request without sending it. It has two required parameters and a few optional ones. The first parameter specifies the method used to send data to the server page; the usual values are GET and POST. The second parameter is URL, which specifies where you want to send the request. The URL can be complete or relative. If the URL doesn’t specify a resource accessible via HTTP, the first parameter is ignored. The third parameter of open(), called async, specifies whether the request should be handled asynchronously. true means that your code processing carries on after send() returns without waiting for a response from the server; false means the script waits for a response before continuing processing. To enable asynchronous processing (which is the heart of the AJAX mechanism), you will need to set async to true and handle the onreadystatechange event to process the response from the server. After configuring the connection with open(), you execute it using send(). When making aGET request, you send the parameters using the URL query string, as in http://localhost/ajax/ test.php?param1=x¶m2=y. This server request passes two parameters to the server—a parame- ter called param1 with the value x and a parameter called param2 with the value y: 1/30/08 2:43 PM Page 406 406 CHAPTER 13 ■ IMPLEMENTING AJAX FEATURES // Call the server to execute the server-side operation"GET", "http://localhost/ajax/test.php?param1=x¶m2=y", true); xmlHttp.onreadystatechange = handleRequestStateChange; xmlHttp.send(null); When using POST, you send the query string as a parameter of the send() method, instead of joining it on to the base URL, like this: // Call the server page to execute the server-side operation"POST", "http://localhost/ajax/test.php", true); xmlHttp.onreadystatechange = handleRequestStateChange; xmlHttp.send("param1=x¶m2=y"); The two code samples should have the same effect. In practice, there are a few differences between POST and GET that you should know about: • Using GET can help with debugging because you can simulate GET requests with a web browser, so you can easily see with your own eyes what your server script generates. • POST is required when sending large blocks of data, which cannot be handled by GET. • GET is meant to be used for retrieving data from the server, while POST is meant to sub- mit changes. In the real world, it’s good to obey these rules; otherwise, strange things can happen. For example, search engines send GET requests to read data from the Web, but they never post any data. If you use GET to submit changes and a search engine becomes aware of the address of the server script, that search engine could start modi- fying your data—and you certainly don’t want that The minimal implementation of a function named process() that makes asynchronous server calls using GET looks like this: function process() // Call the server to execute the server-side operation"GET", "server_script.php", true); xmlHttp.onreadystatechange = handleRequestStateChange; xmlHttp.send(null); This implementation has the following potential problems: • process() may be executed even if xmlHttp doesn’t contain a valid XMLHttpRequest instance. This may happen if, for example, the user’s browser doesn’t support XMLHttpRequest. This would cause an unhandled exception to happen. Our other efforts to handle errors don’t help very much if we aren’t consistent and do something about the process function as well. • process() isn’t protected against other kinds of errors that could happen. For example, as you will see later in this chapter, some browsers will generate a security exception if they don’t like the server you want to access with the XMLHttpRequest object. 1/30/08 2:43 PM Page 407 CHAPTER 13 ■ IMPLEMENTING AJAX FEATURES 407 A better version of process() looks like this: // Performs a server request and assigns a callback function function process() // Continue only if xmlHttp isn't void if (xmlHttp) // Try to connect to the server try // Initiate server request"GET", "server_script.php", true); xmlHttp.onreadystatechange = handleRequestStateChange; xmlHttp.send(null); // Display an error in case of failure catch (e) alert("Can't connect to server:\n" + e.toString()); If xmlHttp is null (or false), we don’t display yet another error message, because we assume such a message was already displayed by the createXmlHttpRequestObject function. We make sure to signal any other connection problems, though. Handling the Server Response When making an asynchronous request, such as in the code snippets presented earlier, the execution of xmlHttp.send() doesn’t freeze waiting for the server response; instead, the JavaScript code continues executing. The process() function shown earlier defines a function named handleRequestStateChange() as the callback method that should handle request state changes. The readyState property can have one the following values representing the possible states of the request: 0 = uninitialized 1 = loading 2 = loaded 3 = interactive 4 = complete Usually the handleRequestStateChange() method is called multiple times, when the request enters a new stage, but you can’t rely on the web browser to raise the readystatechange event for all the mentioned states except state 4, which signals the request has completed. The names of the states are self-explanatory except for state 3. The interactive state is an intermediate state when the response has been partially received. In our AJAX applications we will use only the complete state, which marks that a response has been fully received from the server. 1/30/08 2:43 PM Page 408 408 CHAPTER 13 ■ IMPLEMENTING AJAX FEATURES The following code snippet shows the typical implementation of handleRequestStateChange and highlights the portion where you actually get to read the response from the server: // Function executed when the state of the request changes function handleRequestStateChange() // Continue if the process is completed if (xmlHttp.readyState == 4) // Continue only if HTTP status is "OK" if (xmlHttp.status == 200) // Retrieve the response response = xmlHttp.responseText; // Do something with the response // ... Before attempting to read the received data, we also verify that the response status code is 200. Sending such a code indicates the status of the request is part of the HTTP protocol, and 200 is the status code that specifies that the request completed successfully. Other popu- lar HTTP status codes are 404, which indicates that the requested resource couldn’t be found, and 500, which indicates a server error. Once again we can use try-catch blocks to handle errors that could happen while initiat- ing a connection to the server or while reading the response from the server. An improved version of the handleRequestStateChange() function looks like this: // Function executed when the state of the request changes function handleRequestStateChange() // Continue if the process is completed if (xmlHttp.readyState == 4) // Continue only if HTTP status is "OK" if (xmlHttp.status == 200) try // Retrieve the response response = xmlHttp.responseText; // Do something with the response // ... catch(e) // Display error message alert("Error reading the response: " + e.toString()); 1/30/08 2:43 PM Page 409 CHAPTER 13 ■ IMPLEMENTING AJAX FEATURES 409 else // Display status message alert("There was a problem retrieving the data:\n" + xmlHttp.statusText); In practice, we will be displaying more user-friendly error messages. Moreover, whenever possible, we’ll make our code degradable so that when an error happens inside the JavaScript code, the functionality is instead performed using a typical form submit. Let’s see how. Writing Degradable Code Ideally, a modern web application should use AJAX to enhance existing features whenever possible, while keeping the web site functional even when JavaScript isn’t available. In our particular case, we want to let our visitors add products to their shopping carts and edit their shopping carts even if they have JavaScript disabled or if their web browser doesn’t support JavaScript. When a visitor clicks the Add to Cart button, we first try to make a background AJAX call to add the product to the visitor’s cart and update the cart summary box accordingly. If an error happens when trying to make the call or if JavaScript is disabled, we submit the form to the server and add the product to the visitor’s cart in a non-AJAX fashion. This way, we’ll offer a better web experience to most of our users, while permitting the others to use our store as well. This is easier to implement than it sounds. Take a look at the following code, which repre- sents the AJAXified “Save for later” and Remove links in the shopping cart. a href="" onclick="return executeCartAction(this);"Save for later/a a href="obj-mCartProductsi.remove" onclick="return executeCartAction(this);"Remove/a In both cases, a JavaScript function is executed as a result of the click event. If that function returns false, the link isn’t followed anymore. If the function returns true or it’s not executed at all, the link is followed, and the shopping cart gets modified using in a non-AJAX fashion. The Add to Cart buttons are handled similarly, except in this case the JavaScript function is called when submitting the form: onsubmit="return addProductToCart(this);" Figure 13-2 describes what happens when a visitor clicks an Add to Cart button. The process is similar to that of updating shopping cart items, which we’ll also implement in this chapter. As you can see, no matter whether the visitor has JavaScript or not, the same end result is achieved. The difference lies in the responsiveness; in the AJAX scenario the user doesn’t have to wait a few seconds for the page to reload. 1/30/08 2:43 PM Page 410 410 CHAPTER 13 ■ IMPLEMENTING AJAX FEATURES ) Figure 13-2. Degradable AJAX feature AJAX Scenario JavaScript code in the When the server’s response web page calls the is received, the user page Yes server page asynchronously is updated to reflect the The user to inform it of the user action shopping cart changes   receives a   User clicks new page Add to Cart User has that reflects button JavaScript that the enabled product has Traditional Scenario been added Default Joe Happy Joe to the cart Form is submitted to server No8644ch13FINAL.qxd 1/30/08 2:43 PM Page 411 CHAPTER 13 ■ IMPLEMENTING AJAX FEATURES 411 Is AJAX Always Suitable? We end the theoretical part of the chapter with a warning: AJAX can improve your visitors’ experi- ence with your web site, but it can also worsen it when used inappropriately. Usually, AJAX is best used in addition to the traditional web development paradigms, rather than changing or replac- ing them. For example, unless your application has really special requirements, it’s wise to let your users navigate your content using good old hyperlinks. Web browsers have a long history of dealing with content navigation, and web users have a long history of using browsers’ naviga- tional features. AJAX can bring the following benefits to your projects: • It makes it possible to create better and more responsive web applications. • It encourages the development of patterns and frameworks that help developers avoid reinventing the wheel when performing common tasks. • It makes use of existing technologies and features supported by all modern web browsers. • It makes use of many existing developer skills. The following are potential problems with AJAX: • It’s unavailable to some users: JavaScript can be disabled at the client side, which makes the AJAX features nonfunctional. • It’s easy to use AJAX for the wrong purposes: Increased awareness of usability, accessibil- ity, web standards, and search engine optimization will help you make better decisions when designing and implementing web sites. • It can make your content invisible to search engines: Search engines cannot index con- tent dynamically generated by JavaScript in an AJAX application, because they don’t execute any JavaScript code when indexing the web site. If search engine optimization is important for your web site, you shouldn’t use AJAX for content delivery and naviga- tion. In our case, we don’t want search engines to index the shopping cart page or the cart summary box, so we’re not affected by this limitation. • It can cause impaired browser bookmarking and page navigation: Typically AJAX appli- cations run inside a web page whose URL doesn’t change in response to user actions, in which case you can bookmark only the entry page. The Back and Forward buttons in browsers don’t produce the same result as with classic web sites, unless your AJAX application is specifically programmed to do so. To enable AJAX page bookmarking and the Back and Forward browser buttons, you can use frameworks such as Really Simple History by Brad Neuberg ( README.html). This framework enables bookmarking by dynamically adding page anchors using your JavaScript code, such as in You also need to create supporting code that loads and saves the state of your applica- tion through the anchor parameter. However, supporting bookmaking and navigation this way adds a significant level of complexity to your code that increases the chances of errors and browser compatibility problems. 1/30/08 2:43 PM Page 412 412 CHAPTER 13 ■ IMPLEMENTING AJAX FEATURES With these warnings out of the way, it’s time to start updating TShirtShop with the new AJAX features. Creating the AJAX Shopping Cart We’ll AJAXify the shopping cart in two steps. First we’ll implement the AJAX features to the Add to Cart buttons, which update the shopping cart and the cart summary box without reloading the page. Then we’ll enhance the shopping cart page. Figure 13-3 shows the shopping cart summary box while being updated after clicking an Add to Cart button. Note the “Updating...” text that shows up in the cart summary box to indi- cate the cart is being updated. Figure 13-4 shows the shopping cart while removing a product. Figure 13-3. Adding a product to the cart 1/30/08 2:43 PM Page 413 CHAPTER 13 ■ IMPLEMENTING AJAX FEATURES 413 Figure 13-4. Updating the shopping cart Enhancing the Add to Cart Feature with AJAX You saw in Figure 13-2 what we’re about to create here. The implementation is relatively simple. You’ll update the product.tpl and products_list.tpl templates to call a JavaScript function named addProductToCart() when an Add to Cart button is clicked to submit the form. Then you’ll create ajax.js, a rather large JavaScript file that contains all the code required to support the new client functionality. It contains the following functions: • createXmlHttpRequestObject() creates the XMLHttpRequest object. • handleError(message) displays the error messages generated by the other functions or degrades to classical non-AJAX behavior, depending on the value of a variable named showErrors. • addProductToCart() is called from the HTML page to add a product to the cart. • handleAddProductToCart() is the callback function for the Add to Cart server calls. • postAddProductToCartProcess() reads the Add to Cart server response and updates the cart summary box. You’ll also update your project in various places to utilize or support the new features. Let’s go through the exercise that follows, and we’ll discuss the process in more detail afterward. 1/30/08 2:43 PM Page 414 414 CHAPTER 13 ■ IMPLEMENTING AJAX FEATURES Exercise: Adding Products Quicker 1. Open presentation\templates\product.tpl, add the highlighted code, and modify the name of the input element to add_to_cart: The Add to Cart form form class="add-product-form" target="_self" method="post" action="obj-mProduct.link_to_add_product" onsubmit="return addProductToCart(this);" Generate the list of attribute values p class="attributes" Parse the list of attributes and attribute values section name=k loop=obj-mProduct.attributes ... /section /p Add the submit button and close the form p input type="submit" name="add_to_cart" value="Add to Cart" / /p /form 2. Open presentation\templates\products_list.tpl, and modify it as shown here: The Add to Cart form form class="add-product-form" target="_self" method="post" action="obj-mProductsk.link_to_add_product" onsubmit="return addProductToCart(this);" Generate the list of attribute values p class="attributes" Parse the list of attributes and attribute values section name=l loop=obj-mProductsk.attributes ... /section /p Add the submit button and close the form p input type="submit" name="add_to_cart" value="Add to Cart" / 1/30/08 2:43 PM Page 415 CHAPTER 13 ■ IMPLEMENTING AJAX FEATURES 415 /p /form 3. Create a new folder in your project’s root folder (tshirtshop) named scripts, add a new file named ajax.js in it, and type the following code: // Holds an instance of XMLHttpRequest var xmlHttp = createXmlHttpRequestObject(); // Display error messages (true) or degrade to non-AJAX behavior (false) var showErrors = true; // Contains the link or form clicked or submitted by the visitor var actionObject = ''; // Creates an XMLHttpRequest instance function createXmlHttpRequestObject() // Will store the XMLHttpRequest object var xmlHttp; // Create the XMLHttpRequest object try // Try to create native XMLHttpRequest object xmlHttp = new XMLHttpRequest(); catch(e) // Assume IE6 or older var XmlHttpVersions = new Array( "MSXML2.XMLHTTP.6.0", "MSXML2.XMLHTTP.5.0", "MSXML2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"); // Try every id until one works for (i = 0; i XmlHttpVersions.length && xmlHttp; i++) try // Try to create XMLHttpRequest object xmlHttp = new ActiveXObject(XmlHttpVersionsi); catch (e) // Ignore potential error 1/30/08 2:43 PM Page 416 416 CHAPTER 13 ■ IMPLEMENTING AJAX FEATURES // If the XMLHttpRequest object was created successfully, return it if (xmlHttp) return xmlHttp; // If an error happened, pass it to handleError else handleError("Error creating the XMLHttpRequest object."); // Displays an the error message or degrades to non-AJAX behavior function handleError(message) // Ignore errors if showErrors is false if (showErrors) // Display error message alert("Error encountered: \n" + message); return false; // Fall back to non-AJAX behavior else if (actionObject.tagName) return true; // Fall back to non-AJAX behavior by following the link else if (actionObject.tagName == 'A') window.location = actionObject.href; // Fall back to non-AJAX behavior by submitting the form else if (actionObject.tagName == 'FORM') actionObject.submit(); // Adds a product to the shopping cart function addProductToCart(form) // Display "Updating" message document.getElementById('updating').style.visibility = 'visible'; // Degrade to classical form submit if XMLHttpRequest is not available if (xmlHttp) return true; 1/30/08 2:43 PM Page 417 CHAPTER 13 ■ IMPLEMENTING AJAX FEATURES 417 // Create the URL we open asynchronously request = form.action + '&AjaxRequest'; params = ''; // obtain selected attributes formSelects = form.getElementsByTagName('SELECT'); if (formSelects) for (i = 0; i formSelects.length; i++) params += '&' + + '='; selected_index = formSelectsi.selectedIndex; params += encodeURIComponent(formSelectsiselected_index.text); // Try to connect to the server try // Continue only if the XMLHttpRequest object isn't busy if (xmlHttp.readyState == 4 xmlHttp.readyState == 0) // Make a server request to validate the extracted data"POST", request, true); xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xmlHttp.onreadystatechange = addToCartStateChange; xmlHttp.send(params); catch (e) // Handle error handleError(e.toString()); // Stop classical form submit if AJAX action succeeded return false; // Function that retrieves the HTTP response function addToCartStateChange() // When readyState is 4, we also read the server response if (xmlHttp.readyState == 4) // Continue only if HTTP status is "OK" 1/30/08 2:43 PM Page 418 418 CHAPTER 13 ■ IMPLEMENTING AJAX FEATURES if (xmlHttp.status == 200) try updateCartSummary(); catch (e) handleError(e.toString()); else handleError(xmlHttp.statusText); // Process server's response function updateCartSummary() // Read the response response = xmlHttp.responseText; // Server error? if (response.indexOf("ERRNO") = 0 response.indexOf("error") = 0) handleError(response); else // Extract the contents of the cart_summary div element var cartSummaryRegEx = /div class="box" id="cart-summary"➥ (\s\S)\/div/m; matches = cartSummaryRegEx.exec(response); response = matches1; // Update the cart summary box and hide the Loading message document.getElementById("cart-summary").innerHTML = response; // Hide the "Updating..." message document.getElementById('updating').style.visibility = 'hidden'; 4. Open presentation\templates\store_front.tpl, and add a reference to your JavaScript file, ajax.js: html head

Advise: Why You Wasting Money in Costly SEO Tools, Use World's Best Free SEO Tool Ubersuggest.