Está en la página 1de 43

Ajax Architecture

Relevance, LLC
Table of Contents
Ajax Architecture................................................................................................................................................1
License and Usage..................................................................................................................................2
Agenda....................................................................................................................................................3
What's Wrong With the Web?................................................................................................................3
What is Ajax?..........................................................................................................................................4
A Bit More Detail, Please.......................................................................................................................4
Ajax is a Client-Tier State of Mind.........................................................................................................5
What is Ajax For? -- Some Examples.....................................................................................................5
Position 1: This Sh** Ain't New!...........................................................................................................6
Position 2: Holy Nth Tier, Batman!........................................................................................................7
The New Client Tier...............................................................................................................................7
Both Positions are Right!........................................................................................................................8
Message to Conservative Managers........................................................................................................8
Message to Progressive Managers..........................................................................................................9
A Pragmatic Start....................................................................................................................................9
The Zip Code Example.........................................................................................................................10
Zip Code Step 1: Plain Old Web..........................................................................................................10
Zip Code Step 2: Add DOM Ids...........................................................................................................11
Zip Code Step 3a: Add XHR................................................................................................................12
Zip Code Step 3b: Bind Event Handler................................................................................................12
Zip Code Step 4: Add XHR Callback...................................................................................................13
Where Are We?.....................................................................................................................................13
Time To Get Some Tools......................................................................................................................14
Why Firefox?........................................................................................................................................14
The JavaScript Shell.............................................................................................................................15
JavaScript Shell in Action.....................................................................................................................16
Firebug..................................................................................................................................................17
Firebug in Action..................................................................................................................................18
Web Developer Toolbar........................................................................................................................19
Web Developer Toolbar in Action........................................................................................................20
Prototype...............................................................................................................................................20
Zip Code Step 5: $ Method...................................................................................................................21
Zip Code Step 6: Event.observe............................................................................................................21
Zip Code Step 7: Ajax.Request.............................................................................................................22
Zip Code Step 8: Error Handling..........................................................................................................22
Zip Code Step 9: Progress Indicator.....................................................................................................24
Scriptaculous.........................................................................................................................................25
Zip Code Step 10: Fade Effect..............................................................................................................25
Zip Code Step 11: Autocomplete..........................................................................................................26
Zip Code Step 12: Autocomplete is Mostly CSS.................................................................................27
Architectural Decisions.........................................................................................................................28
What to Send on the Wire?...................................................................................................................28
Setting innerHTML/View-Centric Ajax...............................................................................................29
Polling with View-Centric Ajax...........................................................................................................29
View-Centric Polling: Lessons Learned...............................................................................................30
JavaScript eval/Code-Centric Ajax.......................................................................................................30
JSON (etc.) / Model-Centric Ajax........................................................................................................31
Polling with Model Centric Ajax..........................................................................................................31
What Library to Use?............................................................................................................................32
Prototype's Role....................................................................................................................................33

i
Table of Contents
Ajax Architecture
Scriptaculous's Role..............................................................................................................................34
Dojo: A Full Stack................................................................................................................................35
Avoiding Ajax Pitfalls..........................................................................................................................36
The Back Button Issue..........................................................................................................................37
Back Button Solutions..........................................................................................................................38
Bookmarking........................................................................................................................................38
Bookmarking Solution..........................................................................................................................39
Link to this Page (local.google.com)....................................................................................................40
References.............................................................................................................................................40
Projects Cited.........................................................................................................................................40

ii
Ajax Architecture

A Relevance/Codecite Presentation
Copyright 2005 Relevance, LLC
Ajax applications have unique architectural challenges and opportunities. This presentation will show you
how to take advantage of the Ajax's strengths, and work around its quirks.

We'll start with an overview of Ajax, and then dive right into an extended example where we add Ajax to an
existing web application. Along the way we'll cover several tools that we use to aid in Ajax development:

• The JavaScript Shell


• Firebug
• The Web Developer's Toolbar

We'll also look at two popular JavaScript Ajax libraries: Prototype and Scriptaculous.

With the example application under our belts, we'll move to a discussion of Ajax architectural questions,
including:

• How do I selecting an Ajax library?


• What format data should my Ajax calls use: XML, JSON, HTML, or other?
• How do I handle the back button and deep linking in Ajax?

Prior exposure to Ajax and JavaScript is useful but not required.

Ajax Architecture 1
License and Usage
This presentation is Copyright 2005-6, Relevance LLC. You may use any code you find here, subject to the
terms below. If you want to deliver this presentation, please send email to contact@relevancellc.com for
permission and details.

Sample code associated with this presentation is Copyright (c) 2005-6 Relevance, LLC
(www.relevancellc.com), unless otherwise marked. Code citations from other projects are subject to the
license(s) appropriate to those projects. You are responsible for complying with licenses for code you use.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of
the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Ajax Architecture (Slide 1 of 69) 2


Agenda
• What is Ajax?
• What is Ajax For?
• Ajax Quick Start
• Tools and Toolkits
• Architectural Decisions
• Avoiding Pitfalls

What's Wrong With the Web?


• Page Transitions!
♦ apparently excellent for sharing physics research
♦ not particularly convenient to interaction
• Wish: Interaction Centered on Use Case
♦ rich interactivity
♦ rapid response

Ajax Architecture (Slide 2 of 69) 3


What is Ajax?
• Asynchronous JavaScript and XML
♦ async invocation breaks pages (good!)
♦ javascript enables rich interaction
♦ XML enables models (and MVC)
• Coined by Jesse James Garrett

A Bit More Detail, Please


• Standards-Based Presentation
♦ XHTML
♦ CSS
• Dynamic Display and Interaction
♦ Document Object Model
• Data Interchange and Manipulation
♦ XML and XSLT
• Asynchronous Invocation
♦ XMLHttpRequest
• JavaScript to Tie it All Together

Ajax Architecture (Slide 4 of 69) 4


Ajax is a Client-Tier State of Mind

What is Ajax For? -- Some Examples


• Validation
• Active Search
• Dynamic Forms
• Input Suggestions
• Panning Image Data
• Organizing and Navigating Data
• Parallel Activities

Ajax Architecture (Slide 6 of 69) 5


Position 1: This Sh** Ain't New!
• Those Examples Are Just JavaScript!
♦ no async
♦ no XML
• Async Is Not New, Anyway
• Neither is XML

Ajax Architecture (Slide 8 of 69) 6


Position 2: Holy Nth Tier, Batman!

The New Client Tier


• New MVC Layer (In-Browser Client)
• New Dominant Language (JavaScript)
• New Remoting Plumbing (Async, aka XHR)
• Think How Long It Took Us To Absorb the Middle Tier!

Ajax Architecture (Slide 9 of 69) 7


Both Positions are Right!
• Depends on How You Do It

Message to Conservative Managers


We're using proven technology: XML, HttpRequests, and JavaScript.

Ajax Architecture (Slide 11 of 69) 8


Message to Progressive Managers
Ajax is the Revolution, and we're all on board.

A Pragmatic Start
• Add Ajax on the Edges
• Stay Degradable
• Wait for MVC Frameworks to Mature

Ajax Architecture (Slide 13 of 69) 9


The Zip Code Example
• Goal: Update City, State Without Page Transition

Zip Code Step 1: Plain Old Web


<h1>Junk Mail Registration Form</h1>
<form action="register" method="post">
<table>
<tr>
<td>Name</td>
<td><input name="name" type="text"/></td>
</tr>
<tr>
<td>Address</td>
<td><input name="address" type="text"/></td>
</tr>
<tr>
<td>City</td>
<td><input name="city" type="text"/></td>
</tr>
<tr>
<td>State</td>
<td><input name="state" type="text"/></td>
</tr>
<tr>
<td>Zip</td>
<td><input name="zip" type="text"/></td>
</tr>
<tr>
<td>&nbsp;</td>

Ajax Architecture (Slide 15 of 69) 10


<td><input type="submit"/></td>
</tr>
</table>
</form>

--app/views/zip/zip1.rhtml in Rails Exploration Application

Zip Code Step 2: Add DOM Ids


<tr>
<td>Zip</td>
<td><input id="zip" name="zip" type="text"/></td>
</tr>
<tr>
<td>City</td>
<td><input id="city" name="city" type="text"/></td>
</tr>
<tr>
<td>State</td>
<td><input id="state" name="state" type="text"/></td>
</tr>

--app/views/zip/zip2.rhtml in Rails Exploration Application

Ajax Architecture (Slide 16 of 69) 11


Zip Code Step 3a: Add XHR
<script type="text/javascript">
var xhr;
function checkzip(zip) {
xhr = new XMLHttpRequest();
xhr.open("GET", "checkzip?zip=" + zip)
xhr.send(null);
}
</script>

--app/views/zip/zip3.rhtml in Rails Exploration Application

Zip Code Step 3b: Bind Event Handler


<tr>
<td>Zip</td>
<td><input id="zip" name="zip" type="text" onchange="checkzip(this.value)"/></td>
</tr>

--app/views/zip/zip3.rhtml in Rails Exploration Application

Ajax Architecture (Slide 18 of 69) 12


Zip Code Step 4: Add XHR Callback
function updatezip() {
if (xhr.readyState == 4) {
var data = xhr.responseXML;
document.getElementById("city").value = data.getElementsByTagName("city")[0].textContent;
document.getElementById("state").value = data.getElementsByTagName("state")[0].textContent;
}
}
function checkzip(zip) {
xhr = new XMLHttpRequest();
xhr.onreadystatechange = updatezip;
xhr.open("GET", "checkzip?zip=" + zip, true)
xhr.send(null);
}

--app/views/zip/zip4.rhtml in Rails Exploration Application

Where Are We?


• City/State Update Works
• Much To Improve
♦ lots of boilerplate code
♦ doesn't work cross-browser (oops!)
♦ view and controller entangled
♦ no error handling
♦ no status

Ajax Architecture (Slide 20 of 69) 13


Time To Get Some Tools
• These Are Our Primary Tools
♦ many other good options exist
♦ do your homework
• Tools
♦ Firefox
♦ JavaScript Shell
♦ Firebug
♦ Web Developer Toolbar
• Libraries
♦ Prototype, Scriptaculous

Why Firefox?
• As Good In Most Ways
• Better In Some
• Plugin Community is Compelling

Ajax Architecture (Slide 22 of 69) 14


The JavaScript Shell
• Installs as Bookmarklet
• Console-Like Shell Against Current Browser Window

Ajax Architecture (Slide 24 of 69) 15


JavaScript Shell in Action

Ajax Architecture (Slide 25 of 69) 16


Firebug
• Firefox Plugin
• Better Error Reporting Than JavaScript Console
• Inspect DOM Elements
• Excellent Logging of Ajax Traffic

Ajax Architecture (Slide 26 of 69) 17


Firebug in Action

Ajax Architecture (Slide 27 of 69) 18


Web Developer Toolbar
• Tons of Handy Goodies
• Personal Ajax Favorites
♦ CSS:Edit CSS
♦ Information: View JavaScript
♦ Information: Display *
♦ View Source: View Generated Source

Ajax Architecture (Slide 28 of 69) 19


Web Developer Toolbar in Action

Prototype
• Core Support for Dynamic Web Apps
• Used by Scriptaculous and Rico
• Driven and Inspired by Ruby on Rails
• Simple and Elegant

Ajax Architecture (Slide 29 of 69) 20


Zip Code Step 5: $ Method
$("city").value = data.getElementsByTagName("city")[0].textContent;
$("state").value = data.getElementsByTagName("state")[0].textContent;

--app/views/zip/zip5.rhtml in Rails Exploration Application

Zip Code Step 6: Event.observe


• Decouples Event Handling From Markup

Event.observe(window, "load", function() {


Event.observe("zip", "change", function() {
checkzip($("zip").value);
})
})

--app/views/zip/zip6.rhtml in Rails Exploration Application

Ajax Architecture (Slide 31 of 69) 21


Zip Code Step 7: Ajax.Request
• Works Cross-Browser

function updatezip(request) {
var data = request.responseXML;
$("city").value = data.getElementsByTagName("city")[0].textContent;
$("state").value = data.getElementsByTagName("state")[0].textContent;
}
function checkzip(zip) {
new Ajax.Request("checkzip", {
method: "get",
parameters: "zip=" + zip,
onSuccess: updatezip
});
}

--app/views/zip/zip7.rhtml in Rails Exploration Application

Zip Code Step 8: Error Handling


• Add Error With Insertion.After
• Remove Error With Element.remove

<script type="text/javascript" src="/javascripts/prototype.js"></script>


<script type="text/javascript">
//codecite
function updatezip(request) {
var data = request.responseXML;
if (!data || !data.getElementsByTagName("city")[0]) {
badzip();
} else {
$("city").value = data.getElementsByTagName("city")[0].textContent;
$("state").value = data.getElementsByTagName("state")[0].textContent;
Element.remove("err");
}
}
function badzip() {
new Insertion.After("table", "<div id='err'>Zip Not Recognized</div>");
}
function checkzip(zip) {
new Ajax.Request("checkzip", {
method: "get",
parameters: "zip=" + zip,
onSuccess: updatezip,
onFailure: badzip
});

Ajax Architecture (Slide 33 of 69) 22


}
//codecite
Event.observe(window, "load", function() {
Event.observe("zip", "change", function() {
checkzip($("zip").value);
})
})
</script>
<h1>Junk Mail Registration Form</h1>
<form action="register" method="post">
<table id="table">
<tr>
<td>Name</td>
<td><input id="name" name="name" type="text"/></td>
</tr>
<tr>
<td>Address</td>
<td><input id="address" name="address" type="text"/></td>
</tr>
<tr>
<td>Zip</td>
<td><input id="zip" name="zip" type="text"/></td>
</tr>
<tr>
<td>City</td>
<td><input id="city" name="city" type="text"/></td>
</tr>
<tr>
<td>State</td>
<td><input id="state" name="state" type="text"/></td>
</tr>
<tr>
<td>&nbsp;</td>
<td><input type="submit"/></td>
</tr>
</table>
</form>

--app/views/zip/zip8.rhtml in Rails Exploration Application

Ajax Architecture (Slide 34 of 69) 23


Zip Code Step 9: Progress Indicator
• Show With Element.Show
• Hide With Element.Hide

function updatezip(request) {
var data = request.responseXML;
if (!data || !data.getElementsByTagName("city")[0]) {
badzip();
} else {
$("city").value = data.getElementsByTagName("city")[0].textContent;
$("state").value = data.getElementsByTagName("state")[0].textContent;
Element.remove("err");
}
}
function badzip() {
new Insertion.After("table", "<div id='err'>Zip Not Recognized</div>");
}
function checkzip(zip) {
Element.show("checking_zip");
new Ajax.Request("checkzip", {
method: "get",
parameters: "zip=" + zip,
onSuccess: updatezip,
onFailure: badzip,
onComplete: function() {
Element.hide("checking_zip");
}
});
}

--app/views/zip/zip9.rhtml in Rails Exploration Application

Ajax Architecture (Slide 35 of 69) 24


Scriptaculous
• GUI Library
• Builds on Prototype
• Effects
• Drag and Drop
• AutoComplete
• Slider

Zip Code Step 10: Fade Effect


function updatezip(request) {
var data = request.responseXML;
if (!data || !data.getElementsByTagName("city")[0]) {
badzip();
} else {
$("city").value = data.getElementsByTagName("city")[0].textContent;
$("state").value = data.getElementsByTagName("state")[0].textContent;
Effect.Fade("err");
}
}
function badzip() {
new Insertion.After("table", "<div id='err'>Zip Not Recognized</div>");
}
function checkzip(zip) {
Element.show("checking_zip");
new Ajax.Request("checkzip", {
method: "get",
parameters: "zip=" + zip,
onSuccess: updatezip,
onFailure: badzip,
onComplete: function() {
Effect.Fade("checking_zip");
}
});
}

Ajax Architecture (Slide 36 of 69) 25


--app/views/zip/zip10.rhtml in Rails Exploration Application

Zip Code Step 11: Autocomplete


function updatezip(request) {
var data = request.responseXML;
if (!data || !data.getElementsByTagName("city")[0]) {
badzip();
} else {
$("city").value = data.getElementsByTagName("city")[0].textContent;
$("state").value = data.getElementsByTagName("state")[0].textContent;
Effect.Fade("err");
}
}
function badzip() {
new Insertion.After("table", "<div id='err'>Zip Not Recognized</div>");
}
function checkzip(zip) {
Element.show("checking_zip");
new Ajax.Request("checkzip", {
method: "get",
parameters: "zip=" + zip,
onSuccess: updatezip,
onFailure: badzip,
onComplete: function() {
Effect.Fade("checking_zip");
}
});
}

Ajax Architecture (Slide 37 of 69) 26


--app/views/zip/zip11.rhtml in Rails Exploration Application

Zip Code Step 12: Autocomplete is Mostly CSS


div.auto_complete {
width: 350px;
background: #fff;
}
div.auto_complete ul {
border:1px solid #888;
margin:0;
padding:0;
width:100%;
list-style-type:none;
}
div.auto_complete ul li {
margin:0;
padding:3px;
}
div.auto_complete ul li.selected {
background-color: #ffb;
}
div.auto_complete ul strong.highlight {
color: #800;
margin:0;
padding:0;
}

--public/stylesheets/autocomplete.css in Rails Exploration Application

Ajax Architecture (Slide 38 of 69) 27


Architectural Decisions
• What to Send on the Wire
• Which Libraries to Use

What to Send on the Wire?


Wire Format Client Handling Implied Ajax Style
html set innerHTML view-centric
javascript eval response text code-centric
json parse JSON model-centric
xml parse (DOM or E4X) model-centric

Ajax Architecture (Slide 40 of 69) 28


Setting innerHTML/View-Centric Ajax
• Simplest Approach
• Lots of Library Support
• Easy to Add to Existing Web Content

Polling with View-Centric Ajax


new PeriodicalExecuter(function() {
new Ajax.Updater('items',
'http://localhost:3000/chat/retrieve_chats',
{asynchronous:true, evalScripts:false});
}, 10);

Ajax Architecture (Slide 42 of 69) 29


View-Centric Polling: Lessons Learned
• Ajax Starts with Async
♦ register a callback function
• Simplest Callback Just Sets innerHTML
♦ toolkits hide callback function for this case
♦ you just specify a DOM id
• No Need to Execute Script

JavaScript eval/Code-Centric Ajax


• Very Flexible and Powerful
• Demanding on Developers
♦ typically need to understand client and server coding
• Can Sometimes be Added to Existing Web Content

Ajax Architecture (Slide 44 of 69) 30


JSON (etc.) / Model-Centric Ajax
• Completely Rethink the Page
• Server Serves a Model
• Re-implement MVC Within the Browser
• Not an Incremental Approach!
• Enables Desktop-App-In-A-Browser

Polling with Model Centric Ajax


Event.observe(window, 'load', function() {
new Ajax.Request("<%= url_for(:action=>'retrieve_chats', :only_path=>false) %>",
{onSuccess: function(request) {updateList(request.responseText);}});
});
function updateList(text) {
var json = eval(text);
var frag = ""
json.each(function(line) {
frag += ("<li>" + line.ip + " sayeth " + line.message + "</li>");
});
$('items').innerHTML = frag;
}

--app/views/chat_json/chat.rhtml in Pragmatic Chat Sample Application

Ajax Architecture (Slide 46 of 69) 31


What Library to Use?
• Depends on What Features You Need

Ajax Architecture (Slide 48 of 69) 32


Prototype's Role

Ajax Architecture (Slide 49 of 69) 33


Scriptaculous's Role

Ajax Architecture (Slide 50 of 69) 34


Dojo: A Full Stack

Ajax Architecture (Slide 51 of 69) 35


Avoiding Ajax Pitfalls
• The Back Button
• Bookmarking
• Don't Reinvent the Wheel

Ajax Architecture (Slide 52 of 69) 36


The Back Button Issue
• Back Button Goes to Previous Page
• This May be Eons Ago in an Ajax App

Ajax Architecture (Slide 53 of 69) 37


Back Button Solutions
• Punt
♦ acceptable for "desktop apps"
• Hack the Back Button

Bookmarking
• Ajax Lets Users Get "Between" Pages
• Where Should Bookmarks Point?

Ajax Architecture (Slide 54 of 69) 38


Bookmarking Solution
• Manufacture Unique URL for each State
• Get the URL to the User Somehow
♦ update a "link to this page" on each ajax call
♦ hack the url in the location bar

Ajax Architecture (Slide 56 of 69) 39


Link to this Page (local.google.com)

References
Projects Cited
• Rails Exploration Application
• Pragmatic Chat Sample Application

Ajax Architecture (Slide 57 of 69) 40