Adam howitt Duo Consulting 7/7/20061223PN How to Design a large AJAX Application Introduction I'll cover the process I have developed in the course of implementing two AJAX applications as a developer for Duo Consulting in Chicago. This approach has made it easier for me to work with the design team, produce estimates for this type of project and communicate what is involved each step of the way to the project managers for scheduling purposes Background experimenting with AJAX requests to handle tasks that really shouldnt trigger sun I re-designed WalkJog Run to utilize the Google maps API over a year ago and beg complete page request. Shortly after that one of our clients, Chicago Park District wanted to redesign their seasonal registration application to maximize the number of people who could register for their seasonal programs and make it easier for people to use the site. After a detailed discovery phase we proposed an AJAX browser interface to make it simpler to drilldown through their online offerings and ultimately to locate a program and register. Inspired by the iPod menu concept, we developed and built ar applicationwhich served 3000 orders in the first 3 minutes of summer registration Since then I worked on a second application which sits on top of the custom CMs we implement for clients to allow them to generate Microsoft Word proposals to send to clients from the data that drives the website without cutting and pasting. This application was built on the prototype AJAX library but uses the same design principles Why use AJAX? AJAX isn't just a new buzzword or a cream cleanser from Procter& Gamble. It's a great leap forward(and a small step back) for usability. Like flash, when it is used correctly and appropriately it can dramatically enhance the user experience by making web applications respond faster and make interactions less jarring than having a page reload AJAX also offers a performance benefit for your web server since you begin serving smaller chunks of pages instead of complete pages every time. For Cold Fusion this also means only the business logic pertaining to the requested chunk needs to be recalculated instead of the logic for a whole page so your application server will get some relief. Ihttp://www.duoconsulting.com/ http://www.walkiogrun.net shttp://www.google.com/apis/maps/ http://duoconsulting.com/experience/chicago-park-district-registration/index.cfm http://programs.chicagoparkdistrictcom/programbrowserl http://www.duocms.com httpgeneratorduodesign.com:sElecttheproposalgeneratoronceyouhaveloggedinwiththeusername demo(@duoconsulting com and password demo 1/8
Adam Howitt Duo Consulting 7/7/2006 12:23 PM How to Design a large AJAX Application Introduction I’ll cover the process I have developed in the course of implementing two AJAX applications as a developer for Duo Consulting 1 in Chicago. This approach has made it easier for me to work with the design team, produce estimates for this type of project and communicate what is involved each step of the way to the project managers for scheduling purposes. Background I re-designed WalkJogRun 2 to utilize the Google maps API 3 over a year ago and begun experimenting with AJAX requests to handle tasks that really shouldn’t trigger a complete page request. Shortly after that one of our clients, Chicago Park District4 , wanted to redesign their seasonal registration application to maximize the number of people who could register for their seasonal programs and make it easier for people to use the site. After a detailed discovery phase we proposed an AJAX “browser interface” to make it simpler to drilldown through their online offerings and ultimately to locate a program and register. Inspired by the iPod menu concept, we developed and built an application5 which served 3000 orders in the first 3 minutes of summer registration. Since then I worked on a second application which sits on top of the custom CMS6 we implement for clients to allow them to generate Microsoft Word proposals7 to send to clients from the data that drives the website without cutting and pasting. This application was built on the prototype AJAX library but uses the same design principles. Why use AJAX? AJAX isn’t just a new buzzword or a cream cleanser from Procter & Gamble. It’s a great leap forward (and a small step back) for usability. Like flash, when it is used correctly and appropriately it can dramatically enhance the user experience by making web applications respond faster and make interactions less jarring than having a page reload. AJAX also offers a performance benefit for your web server since you begin serving smaller chunks of pages instead of complete pages every time. For ColdFusion this also means only the business logic pertaining to the requested chunk needs to be recalculated instead of the logic for a whole page so your application server will get some relief. 1 http://www.duoconsulting.com/ 2 http://www.walkjogrun.net 3 http://www.google.com/apis/maps/ 4 http://duoconsulting.com/experience/chicago-park-district-registration/index.cfm 5 http://programs.chicagoparkdistrict.com/programBrowser/ 6 http://www.duocms.com 7 http://generator.duodesign.com : Select the proposal generator once you have logged in with the username demo@duoconsulting.com and password demo 1/8
Adam howitt o Consulter 7/720061223PM sign Work from a mockup you can doodle on. Draw on the mockup to identify discreet sections of the applications and label them. Do panels interact or are they isolated? If there is a relationship between an interaction in one panel and the display of information draw it with arrows and callouts. This helps to communicate the logical breakdown of the application with other developers. An example marked up mockup for the Chicago Park District program browser application might look like this chicago park district home events grams in the news parks facilites Program Registration Summer 2006 Session June 19-August 27 Online registration is now open! Walk in registration opens 04/22/2006 9: 00 AM Find Programs Program Groups pI Clubs and Game Program Search Results Wishlist 891011:127 Why create D Only show programs available for online registration(highlighted Aquatic Exercise- Ages: 60 8 Ove estriction: None Sign in to your account (Il 0619 747,6001 ender: Co-Rec Create one now 19/2006·8/27/2006 skill Level: open to All Available slots: I w Shopping Cart anticipant Firstname Lastname (Add to Cart D)(cancel Your cart is empty ase Fee!丰0.00 In the example I have numbered the interactions on the mockup for the sake of space but these correspond to the following interactions 1. selectltem(panel 3. selectltem(panel) 4. selectltem(panel) /8
Adam Howitt Duo Consulting 7/7/2006 12:23 PM Design Work from a mockup you can doodle on. Draw on the mockup to identify discreet sections of the applications and label them. Do panels interact or are they isolated? If there is a relationship between an interaction in one panel and the display of information, draw it with arrows and callouts. This helps to communicate the logical breakdown of the application with other developers. An example marked up mockup for the Chicago Park District program browser application might look like this: 5 1 11 12 9 8 6 7 2 4 3 10 In the example I have numbered the interactions on the mockup for the sake of space but these correspond to the following interactions: 1. selectItem(panel) 2. selectItem(panel) 3. selectItem(panel) 4. selectItem(panel) 2/8
Duo Consulting 7/7/20061223PN 5. getHelp(helptopic) 6. view ProgramDetails(activity code) 7. save Towishlist(activity code) 8. check Availability(activity code) 9. addTocart(activity code, participant) 10. cancelRegistration(activity code) 11. load WishlistScreen(mode) 12. load WishlistScreen(mode) Obviously, there are huge gaps in this model. Ideally you would take each colored section of the diagram and model each of the states(screens )and continue labeling Interactions Identify each interaction(a function) and work out the parameters required to allow the function to work as an isolated item. Functions should be able to perform their task without going beyond global variables and the argument scope in most cases. Create a text file and group the function specifications based on the discreet areas of the application e.g. cart, wishlist, account, help. Add JavaScript comments to describe the interaction and include any pseudo code to describe the steps for a function where there are important validation tests, lookups or steps to be performed Are there any panels of the site which have related Java Script functions that are repeated? Whether an undefined number of repeats or a defined number it is preferred to build a JavaScript object. This reduces code duplication, provides variables local to each instance and generally makes things easier. Prefix functions that act on a specific instance of a panel with the name of the panel e.g. Cart: function deleteltemO Look at the interactions which fetch remote data(make an AJAX call). Think about each in turn and make a decision whether each request must be unique(e.g. get user cart)or whether the information doesnt change at all (e.g. get help panel). Update the comments for each function making a remote call to explain that it is remote and indicate if it is unique or not Next, consider the types of remote call you are making. Is the complete result sent back from the remote page as rendered hTmL (rendered result) which can be inserted directly into a destination panel or will the result contain JavaScript variables, XML or a custom structured result(functional result) to be processed in a specific way? An example of rendered result is that a help file chunk can be simply rendered in a given Div element so it is sent back as HTML; a functional result example would be a remote address lookup function where you send an address and receive back a complex object to be inspected which then updates various fields on a form. Add a comment to each AJAX call to say whether the result is rendered or functional Now is probably a good time to walk through your design with another programmer and the designer to make sure you understood the designer's intentions and make sure that your approach isn't missing some obvious efficiencies. An example design document for 3/8
Adam Howitt Duo Consulting 7/7/2006 12:23 PM 5. getHelp(helptopic) 6. viewProgramDetails(activity_code) 7. saveToWishlist(activity_code) 8. checkAvailability(activity_code) 9. addToCart(activity_code,participant) 10. cancelRegistration(activity_code) 11. loadWishlistScreen(mode) 12. loadWishlistScreen(mode) Obviously, there are huge gaps in this model. Ideally you would take each colored section of the diagram and model each of the states (screens) and continue labeling interactions. Identify each interaction (a function) and work out the parameters required to allow the function to work as an isolated item. Functions should be able to perform their task without going beyond global variables and the argument scope in most cases. Create a text file and group the function specifications based on the discreet areas of the application e.g. cart, wishlist, account, help. Add JavaScript comments to describe the interaction and include any pseudo code to describe the steps for a function where there are important validation tests, lookups or steps to be performed. Are there any panels of the site which have related JavaScript functions that are repeated? Whether an undefined number of repeats or a defined number it is preferred to build a JavaScript object. This reduces code duplication, provides variables local to each instance and generally makes things easier. Prefix functions that act on a specific instance of a panel with the name of the panel e.g. Cart:function deleteItem() Look at the interactions which fetch remote data (make an AJAX call). Think about each in turn and make a decision whether each request must be unique (e.g. get user cart) or whether the information doesn’t change at all (e.g. get help panel). Update the comments for each function making a remote call to explain that it is remote and indicate if it is unique or not. Next, consider the types of remote call you are making. Is the complete result sent back from the remote page as rendered HTML (rendered result) which can be inserted directly into a destination panel or will the result contain JavaScript variables, XML or a custom structured result (functional result) to be processed in a specific way? An example of a rendered result is that a help file chunk can be simply rendered in a given DIV element so it is sent back as HTML; a functional result example would be a remote address lookup function where you send an address and receive back a complex object to be inspected which then updates various fields on a form. Add a comment to each AJAX call to say whether the result is rendered or functional. Now is probably a good time to walk through your design with another programmer and the designer to make sure you understood the designer’s intentions and make sure that your approach isn’t missing some obvious efficiencies. An example design document for 3/8
Adam howitt Duo Consulting 77/20061223PM the subset of functionality described in the earlier Chicago Park District mockup might look something like this program Browser. txt /Search Panels SearchPanel: selectItem(panel) / if panel is between 1 and 3 retrieve the contents of the next panel (getResults) else retrieve the program listing * SearchPanel: getResults(target panel, filter) /* based on the given filter make a non-unique rendered x call to grab the contents of the panel and place it in the target panel * //Help getHelp(help topic)t / make non-unique rendered AJAX call to grab the help text for help topic and place it in the elp div 7/Program Search Result riew ProgramDetails(activity code)( / expand the hidden divs for the panel labeled with the activity code and check availability * saveToWishlist(activity code / make a unique functional AJAX call to return a result ndicate is the item already in the cart is the cart full 4/8
Adam Howitt Duo Consulting 7/7/2006 12:23 PM the subset of functionality described in the earlier Chicago Park District mockup might look something like this: programBrowser.txt //Search Panels SearchPanel:selectItem(panel) { /* if panel is between 1 and 3 retrieve the contents of the next panel (getResults), else retrieve the program listing */ } SearchPanel:getResults(target_panel,filter) { /* based on the given filter make a non-unique rendered AJAX call to grab the contents of the panel and place it in the target_panel */ } //Help getHelp(help_topic) { /* make non-unique rendered AJAX call to grab the help text for help_topic and place it in the help div */ } //Program Search Result viewProgramDetails(activity_code) { /* expand the hidden divs for the panel labeled with the activity_code and check availability */ } saveToWishlist(activity_code) { /* make a unique functional AJAX call to return a result to indicate - is the user logged in - is the item already in the cart - is the cart full 4/8
Adam howitt o Consulter 7/720061223PM Pass the result to handlesaveToWishlist( */ checkAvailability(activity code)( / make a unique functional AJAX call to return a result to indicate if there is available inventory and pass the result to andlecheckAvailability()*/ handle CheckAvailability(result)t /* if none available set inventory to zero and change the class and text of the inventory box to indicate that the item is sold out, else update the inventory box to the returned value * adaToCart(activity code, participant) cancelRegistration(activity code) t / hide the more info div for the activity code * loadwishlistscreen(mode) / make a non-unique rendered AJAx call to retrieve the content matching the the wishlist div accordingly handlesaveTowishlist(result / based on the result either refresh the wishlist panel to reflect date the wishlist p 5/8
Adam Howitt Duo Consulting 7/7/2006 12:23 PM Pass the result to handleSaveToWishlist() */ } checkAvailability(activity_code) { /* make a unique functional AJAX call to return a result to indicate if there is available inventory and pass the result to handleCheckAvailability() */ } handleCheckAvailability(result) { /* if none available set inventory to zero and change the class and text of the inventory box to indicate that the item is sold out, else update the inventory box to the returned value */ } addToCart(activity_code,participant) { /* skipped for brevity... */ } cancelRegistration(activity_code) { /* hide the more info div for the activity_code */ } //Wishlist loadWishlistScreen(mode) { /* make a non-unique rendered AJAX call to retrieve the content matching the mode passed in and update the wishlist div accordingly */ } handleSaveToWishlist(result) { /* based on the result either -refresh the wishlist panel to reflect the new item -update the wishlist panel with an error message */ 5/8