Ajax for ActionScripters
Jon Meyer
FlashForward 2006
This is a session to give you a flavor of what its like to write Ajax applications. You should be comfortable looking at code, since there will be plenty of JavaScript. The session is fairly introductory, though you should have some familiarity with terms like "CSS", "DOM" and "HTML". You'll learn the basic mechanisms that underlie all Ajax apps, rather than any specific Ajax toolkit or technology.
The notes and full code samples for the session are online at www.cybergrain.com/tech/flashforward.
What is "Ajax”?
Ajax is a label coined by Jesse Garrett of Adaptive Path to describe an approach to building "web 2.0” applications using Xml and JavaScript. There is no single "Ajax” technology. There are lots of Ajax apps: Outlook Web Access, Amazon, GMail, Google Maps, 37 Signals apps, Yahoo Mail… the list is growing.
Ajax is a good label to rally around, but it is really a misnomer – as Steffan Meschkat pointed out:
  1. Nearly all GUI applications are event driven and therefore the "asynchronous” is a given.
  2. If you want to create apps that run in a Web browser, JavaScript is the only game in town – this too is a given.
  3. XML – it turns out that the XML implementation in most browsers is slow and cumbersome – so most AJAX applications forgo XML and use JavaScript as a message interchange format (e.g. JSON – see www.json.org)
Why should you look at Ajax?
Uppers
  1. Ajax apps are built in JavaScript, the same language as Flash. Many of your scripting skills will transfer well to Ajax.
  2. At the end of the day, its all still about objects, properties, controls, layouts, images, and text – things you already know.
  3. The development tools are free – you just need a web browser and a text editor.
  4. Like Flash, there is a huge wealth of open source example code / forums out there to learn from.
  5. Even better, on most web pages you can do "View Source” to see how the page works.
  6. You can use "real” debuggers in both FireFox and IE (if you buy Visual Studio).
  7. Your apps will run in a web browser without needing the proprietary Macromedia sandbox.
  8. You get great HTML support :-) things like tables and flow layouts are really easy in Ajax apps.
 Downers
  1. Complex: Three intersecting standards (ECMA, HTML, CSS) instead of a single-vendor tool.
  2. Complex: Three or more different runtimes instead of just one Flash Player.
  3. Lack of tools - you have to do much more in a straight text editor. There is no visual designer like the Flash  IDE for Ajax.
  4. Debugging is slow and tedious.
  5. Hard to protect your investment (people can rip off your script and design elements).
  6. Have to give up some of the richness of Flash (e.g. no rotation, no masking).
Setting up Shop
The 3(.5) browsers
Most Ajax Apps target 3 main "second generation” browsers: FireFox 1.0, Safari, and IE6. All three support "XMLHttpRequest” which lets you call back to the server.
Opera is a forth browser with a very vocal user base. If you don't support Opera, you'll get a lot of email complaining about that fact.
Get FireFox
FireFox is indispensable:
  1. Best CSS implementation
  2. Lots of developer add-ons
  3. Start with FireFox and then move outwards.
  4. JavaScript console
  5. DOM inspector
  6. Web developer extension gives access to CSS info and more. See:
Get a Debugger
FireFox: , get the Venkman JavaScript Debugger  from:
Internet Explorer: you use Visual Studio. Add the following line to your JavaScript:
    
    debugger;
 
Then in IE open the Internet Options > Advanced tab, make sure that "Disable Script Debugging (Internet Explorer)” checkbox is not checked.
Then run the script and it should trap into the IE debugger, where you can single-step and set breakpoints.
Safari/Opera: I'm not aware of good debuggers for Safari/Opera. See "Consoles” below.
Other Tools
You will of course need an HTML editor, a CSS editor, an XML editor and a JavaScript code editor. Visual Studio, Dreamweaver, … it's a matter of preference. I use Visual Studio on my PC and vi on my Mac.
Cross Platform
With several different runtimes and three distinct standards (HTML, CSS, JavaScript), Ajax apps are complex to write.
Pay attention to complexity and cross-platform issues up front, rather than ignoring them until they catch you out.
With Flash, you can "hack-and-ship” because there is one runtime everywhere. With Ajax, you will need to do more engineering.
Cross-platform is unpleasant, but it needn't be a nightmare. Two general rules:
1. Develop a cross-platform library
Whenever you discover a difference between two platforms, write a JavaScript function that handles the difference, and add it to your cross-platform library. Then, always use your library version in your code. That way, if you find a third or forth browser that handles it differently, you just modify the one function in your cross-platform library.
2. Use function-sniffing rather than browser sniffing
Early on, people wrote complex "sniffers” to detect exactly which browser you were on, and then wrote big switch statements with cases for each browser.
These days, the trend is to test for exactly the function you want, e.g. here is part of my cross-platform library:
 
XPlatform.setSelection = function(textBox, startIndex, endIndex) {
if (textBox.setSelectionRange) {
        textBox.setSelectionRange(startIndex, endIndex);
    } else if (textBox.createTextRange) {
        var range = textBox.createTextRange();
        range.moveStart('character', startIndex);
        range.moveEnd('character', -textBox.value.length + endIndex);
        range.select();
    }
}
 
Notice that the function doesn't test for IE or FireFox – it works by testing for methods (setSelectionRange vs createTextRange) rather than browsers. Sometimes you have to test for specific browsers, but its good to be more general if you can.
Two Flavors of JavaScript
JavaScript is a flexible programming language – so different groups create their own patterns and paradigms for building larger apps in JavaScript. Two flavors predominate: Functional and Class-oriented.
Functional
Aim is to push JavaScript in the direction of Ruby/Python – lots of functions:
 
var Ajax = {
  getTransport: function() {
    return Try.these(
      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
      function() {return new ActiveXObject('Microsoft.XMLHTTP')},
      function() {return new XMLHttpRequest()}
    ) || false;
  }
}
Class-oriented    
Goal is to make JavaScript look more like Java and C#:
 
// Demo class
function Demo() {}
 
// Demo.toString method
Demo.prototype.toString = function() {
    return 'Demo' + this.name;
}
 
I have a blog post on performance metrics for these two approaches at www.cybergrain.com - search for "ajax perf” in the search box.
JavaScript Tools
Ajax is gaining popularity partly because there are dozens of Ajax JavaScript apps and toolkits on the web, and its usually fairly easy to copy/paste code into your app. The tools fall into two classes: libraries and frameworks. Libraries offer a relatively focused set of features. Frameworks throw in control frameworks and usually some kind of back-end story.
Libraries
Prototype (open source)
Site: http://prototype.conio.net  A functional JavaScript library, has classes for events, DOM manipulation, form helpers, position classes, string and array helpers. Has a strong Ruby flavor. Fairly light weight, not that much documentation, used by 37 signals / ruby on rails camp.
MochiKit (open source)
Site: www.mochikit.com. Another functional library, has functions for dom manipulation, color, datetime, string formatting, logging, and asynchronous messaging. Strong Python flavor. Lots of documentation.
Many others…
Look at www.ajaxian.com for more Ajax libraries. It's also not too hard to create a new library. If you are doing a big Ajax app, it's worth taking the time to develop your own libraries that have the functions and style you like. There's plenty of code to start from…
Frameworks
Atlas (commercial)
Site: http://atlas.asp.net. Microsoft's entry to the Ajax Framework universe. Has a relatively small set of well thought out controls and some nice features. A class-oriented framework, its still in early stages. It includes databinding and some Visual Studio integration. Requires ASP on the back end.
Backbase (commercial)
Site: www.backbase.com. Similar to Flex - has a set of extensions to XHTML called BXML, and a JavaScript runtime with controls and databinding. Backbase has "behaviors” that are associated with XHTML nodes. It also has a rich server-side story. Like Flex, it is not free. No Safari support yet.
BlueShoes (open source)
Site: www.blueshoes.org. A PHP framework but it has lots of JavaScript controls that can be used without PHP. Also has examples of how to use the controls. Fairly easy to script. No XML syntax for writing UI.
Dojo (open source)
Site: http://dojotoolkit.org. A class-oriented framework for creating controls and building Ajax apps. Includes a rich text editor. Gaining popularity.
Working with CSS/DOM
In Flash you get movie clips and properties. Ajax apps use DOM node, properties, attributes styles.
CSS
CSS is considered the "cool” way to design HTML pages. CSS can do a lot of the things that used to be done with HTML tables and single-pixel transparent GIF images. Personally, I'm not a huge fan of the CSS approach to  styles, but its better than no styling system.
CSS lets you specify collections of property values in a stylesheet, e.g.
 
    .normal {
        font-family: times;
        font-size: 12px;
        color: #222;
        margin: 1em;
    }
 
and then apply those styles to HTML:
 
    <p class=”normal”>Here is some normal text</p>
 
CSS has some very powerful features. However, it is also very easy to build "spagetti” style sheets that even you won't understand.  Also, the differences between browsers mean that you end up spending a lot of resources working out CSS issues. IE6 in particular has a lot of differences that will catch you out.
Some tips:
  1. Design for FireFox first. Then generalize to the other browsers. FireFox has the most "standard” implementation of CSS, so if something works there its because the CSS is "correct”.
  2. CSS Zen Garden (www.csszengarden.com) has lots of examples of the same page designed with different CSS styles
  3. Get the CSS book "Cascading Style Sheets – The Definitive Guide” by Eric Meyer, O'Reilly. http://www.meyerweb.com/eric/books/css-tdg/
  4. It's best not to copy/modify a complete style sheet designed for another site. Usually you'll find it is better to build your own from scratch, so you understand all the pieces.
  5. Try to keep things simple. I prefer "classes” over other selector mechanisms, i.e. things like:
 
.myclass { color: red; margin: 10px; }
over :
div { color: red; margin: 10px; }
  1. Avoid long compound selector rules where possible:
 
div p < input { color: red; margin: 10px; }
Quirks Mode
It bites every CSS developer: Different browsers have different "quirks” – ways that they try to behave to be compatible with older versions of the browser.
If you specify the DOCTYPE at the top of your document you can turn off some of those quirks.
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
The result is much better consistency between browsers.
XHTML
Most Ajax apps use XHTML, which is HTML that is legal Xml (i.e. all attributes must be in quotes, all opening elements must be closed, etc.).
Here's the basic template for a well-formed XHTML document (for brevity in the rest of the examples I'll skip this template.).
 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >
    <body>
        Hello World
    </body>
</html>
 
Script Example 1: Setting Attributes
See: script1.html | xplat.js
Before you can set an attribute, you have to get the DOM object you want to modify. There are two common techniques for fetching elements from the DOM. Either use "this” in an event handler e.g.
 
    <div onmouseover=”doSomething(this);”></div>
Or give the HTML element an "ID” for use with document.getElementById, e.g.
 
<div id=”foo”>Some text</div>
This can be addressed in JavaScript using:
 
    var elem = document.getElementById("foo”);
Tip: be careful about how you treat references to DOM objects in your code, because there are memory leaks in ActiveX in IE. See http://jibbering.com/faq/faq_notes/closures.html#clMem
Once you have a DOM element, you can set attributes on it using setAttribute. Note that some attributes have different names on different browsers. E.g. "class” is "className” on IE. I use a cross-platform helper here:
 
// My cross-platform class
function XPlatform() { }
 
// detects Internet Explorer
XPlatform.isIE = document.all && window.ActiveXObject &&
    (navigator.userAgent.toLowerCase().indexOf('msie') > -1);
 
// Sets the 'class' of a DOM element
XPlatform.setClass = function setClass(element, val) {
    var attrName = (XPlatform.isIE ? 'className' : 'class');
    element.setAttribute(attrName, val);
}
Put the script above in a file "xplat.js”.
The method defines a cross-platform way of setting the class of an element. (The online xplat.js code has a getClass method).
The  follwing html code shows how to use xplat.js:
 
<html>
<head>
    <style>
        /* define a style called myClass */
        .myClass { color: red; }
    </style>
    <!-- include cross-platform code -->
    <script src="xplat.js"> </script>    
</head>
<body>
    <!-- define an element with onmouseover/out that calls setClassName -->
    <div onmouseover="XPlatform.setClass(this,'myClass');"
         onmouseout="XPlatform.setClass(this,'');" >
       Some text
    </div>
</body>
</html>
 
The result? When you mouse over the "Some text” on the page, it turns red.
Notice how the code mixes CSS, JavaScript, and HTML. It's clunky, but it works.
Example 2: Setting Styles
See: script2.html | xplat.js
In this example, we'll make buttons that change the width of an element by setting style attributes on the element.
First, we need a cross-platform way to set styles, which I'll add to xplat.js:
 
XPlatform.setStyle = function setStyle(element, styleAttribute, val) {
    if (element.style.setAttribute) {
        element.style.setAttribute(styleAttribute, val);
    } else {
        element.style[styleAttribute] = val;
    }
}
In the online xplat.js there is a very similar function for getting a style.
Here's an example using this code to set a style directly on an element:
 
<html>
<head>
    <script src="xplat.js">
    </script>
    <script>
        function makeBig() {
            // Get "foo”
            var elem = document.getElementById("foo");
            // Set the "width” style to 200 pixels
            XPlatform.setStyle(elem, 'width', '200px');
        }
        function makeSmall() {
            var elem = document.getElementById("foo");
            // Set the "width” style to 50 pixels
            XPlatform.setStyle(elem, 'width', '50px');
        }
    </script>
</head>
<body>
   <!-- define the "foo” element -->  
   <div id="foo"
        style="width:100px;height:100px;background-color:red">
      Hello
   </div>          
   <!-- buttons to make the rectangle big/small -->  
   <a href="#" onclick="makeBig(); return false;">make big</a> |
   <a href="#" onclick="makeSmall(); return false;">make small</a>
</body>
</html>
In this markup, notice:
  1. The element has an id 'foo', makeBig/makeSmall address foo via document.getElementById()
  2. We have attached style properties directly to the element using a style attribute. If you want to modify style attributes via script, it is best to set the styles directly on the element (I've had perf issues with some FireFox versions when I don't)
  3. The hyperlinks both have an onclick handler which returns false:
       <a href="#" onclick="makeBig(); return false;">
               This prevents the browser's default behavior for click from happening
A note on measurements
In Flash, you have _x, _y, _width, _height that both get and set the size and position of a movie clip.
In JavaScript? Its more complex – if you get the value of a style or attribute, you are returned the value that you set, which may be different from what the user sees after the CSS layout engine has run.
Input values are specified as styes in a style sheet or via the style attribute e.g.
 
    <div id=”foo” style=”width: 100px”>Hello world</div>
But to get actual the width of the item you need to use "offsetWidth” property of the item:
 
    document.getElementById("foo”).offsetWidth
Example 3: A Basic Animation
See: script3.html | xplat.js
Here is a JavaScript function animateBig(), which we can add just beneath makeBig(). It's like makeBig  except it animates the element's width over time:
    
    var w = 10;
    function animateBig() {
        if (w < 200) {
            w+= 10;
            var elem = document.getElementById("foo");
            XPlatform.setStyle(elem, 'width', w + 'px');
            // use setTimeout to call animateBig again in 50ms
            setTimeout('animateBig()', 50);
        }
      }
Here's a hyperlink button to invoke animateBig():
 
    <a href="#" onclick="w = 50; animateBig(); return false;">
        animate big
    </a>
 
Things to note:
  1. The script is using the variable 'w' to store the property value during animation.
  2. setTimeout creates a timer to call the function after a time delay.
  3. We concatenate the value w with the string 'px' to get a valid CSS scalar (CSS values have units, in this case the units are pixels).
More complex animations    
The code above illustrates the basic principles, but it has many shortcomings. Most Ajax apps use a JavaScript animation library, adding features to:
  1. Start, stop and cancel animations
  2. Play multiple animations at once
  3. Animate multiple properties of a single object
  4. Animate multiple properties of multiple objects
  5. Register event handlers for detecting when animations finish
  6. Detect frame rates and run animations in "real time”
Many Ajax toolkits come with animation support – hunt around for one you like. I wrote my own engine, which works in both Flash and  JavaScript: http://www.cybergrain.com/tech/anim/
Example 4: Setting Opacity
See: script4.html | xplat.js
Opera, Safari, IE and Safari all support opacity, though in different ways. So we'll extend our cross-platform library to handle opacity:
 
XPlatorm.setOpacity = function setOpacity(element, opacity) {
    if (element.filters) {
        try {
            element.filters.alpha.opacity = opacity * 100;
        } catch (e) { }
    } else if (element.style.MozOpacity !== (void 0)) {
        var val = parseFloat(opacity);
        if (val > .99) val = .99;
        element.style.MozOpacity = val;
    } else if (element.style.opacity !== (void 0))
        element.style.opacity=opacity;
}
Now we can create a page which uses setOpacity to hide/show an "overlay”, a translucent rectangle which appears in the top left corner of the page when you move your mouse there:
 
<html>
<head>
    <script src="xplat.js"></script>
    <style>
        /* use CSS to position, size and color the overlay */
        .overlay {
            position:absolute;
            top:0; left:0;
            width:100px; height:70px;
            padding-top:40px;
            background-color:red;
            text-align: center;
        }
    </style>
</head>
<body onload="XPlatform.setOpacity(document.getElementById('over'), 0)">
 
    <h1>Here is some text</h1>
  
    <!-- a div which uses the setOverlay method -->
    <div id="over" class="overlay"
         onmouseover="XPlatform.setOpacity(this, 0.5)"
         onmouseout="XPlatform.setOpacity(this, 0)">
      Overlay
    </div>
</body>
</html>
Here's what the  HTML page looks like - some text with a red translucent overlay:
 
        
Example 5: Creating a clock using DOM Manipulation
See: script5.html | xplat.js
Ajax applications often build new HTML elements on the fly. One easy and effective way to do this is to push HTML text into an Array object, and then use the DOM's innerHTML property to turn that HTML code into live DOM objects. This script, in clock.js, uses innerHTML to create a JavaScript clock:
 
// This method generates the HTML for a clock on the page
function updateClock() {
    // Get the time
    var time = new Date();
 
    // Now build the HTML for the clock in an array
    var arr = new Array();
    arr.push('<div class="clock">');
    arr.push('<span class="hour">');
    appendDigit(arr, time.getHours() % 12);
    arr.push('</span>:<span class="min">');
    appendDigit(arr, time.getMinutes());
    arr.push('</span>:<span class="sec">');
    appendDigit(arr, time.getSeconds());
    arr.push('</span></div>');
 
    // This sets the contents of "clockDiv” to be the HTML we
    // just built.
    document.getElementById("clockDiv").innerHTML = arr.join('');
    
    // Do it all again a second from now
    setTimeout('updateClock()', 1000);
}
 
// Append a single clock digit to the array
function appendDigit(arr, num) {
    var str = num + '';
    if (str.length == 1) str = '0' + str;
    arr.push(str);
}
Here's the HTML for hosting the clock, with some styles and a div called "clockDiv”:
 
<html>
<head>
    /* include the clock source code */
    <script src=”clock.js”></script>
    <style>
        /* clock styles */
        .clock { font-size: 48px; font-family: arial; color: red; }
        .hour { color: #444; }
        .min { color: #aaa; }
        .sec { color: #ccc; }
    </style>
</head>
<!-- N.B. onload calls updateClock() to initialize the clock on load -->
<body onload="updateClock()">
 
    <!-- this is the div that the clock appears within -->
    <div id="clockDiv"></div>
 
</body>
</html>
The final clock looks like this:
Example 6: XMLHttpRequest
See: script6.html | xplat.js
The essence of Ajax applications is that they call back to the server to load new data into the page, without forcing the user to navigate to a new page.
To do that, you need the XMLHttpRequest object. Once again, you need to think about cross-platform up front. Here is a very simple wrapper on XMLHttpRequest for doing cross platform HTTP GET requests:
 
XPlatform.httpGet = function httpGet(url) {
    var req;
    if (XPlatform.isIE) {
        req = new ActiveXObject('Microsoft.XMLHTTP');
    } else {
        req = new XMLHttpRequest();
    }
    req.open('GET', url, false);
    req.setRequestHeader('Cache-Control', 'no-cache');
    req.setRequestHeader('Expires', 'Fri, 30 Oct 1998 14:19:41 GMT');
    req.send(null);
    return req.responseText;
}
Below is an example HTML page that uses the function. We'll do something very simple – create a page with a "load" button on it. When you click on the load button, then the HTML for the page itself is fetched from the server using an HTTP GET, and displayed within the page.
 
<html>
    <head>
    <script src="xplat.js"></script>
 
 
    <script>
        // This calls httpGet to get the text for this document
        function loadDoc() {
            var txt = XPlatform.httpGet('example6.html');
            // Use regular expressions to replace HTML markup…
            txt = txt.replace(/</g, '&lt;');
            txt = txt.replace(/>/g, '&gt;');
            txt = txt.replace(/\n/g, '<br>');
            // Now set the contents of the 'text' element to
            // the text we retrieved
            document.getElementById('text').innerHTML = txt;
        }
    </script>
</head>
 
<body>
    <!-- here is a hyperlink which, when clicked, loads this doc -->
    <a href="#" onclick="loadDoc(); return false">load it</a>
 
     <!-- the div that the text is loaded into -->
    <div id="text"></div>
</body>
</html>
JSON
An increasing number of AJAX applications are using JSON rather than XML to send data between the front end and the back end. See http://www.crockford.com/JSON/. JSON is a very restricted subset of JavaScript.
The following document shows some JSON:
 
    {
    "firstName":"Jon",
    "zip":10013,
    "friends":[ "Kate","Myke","Toby" ],
    }
The cool thing about JSON is that, in JavaScript, you can use eval () to turn the JSON script into a graph of JavaScript objects. One of the implications of AJAX/JSON is that your backend becomes more of a service tier, and less of an HTML templating system.
Crunching
A typical non-trivial Ajax app may consist of 10,000-20,000 lines of JavaScript. That's a lot of code to load into the web browser! To shink code, most large Ajax projects emply some kind of "crunching" technology, which eliminates whitespace and may perform other code transformations. Do a search for "javascript cruncher" to find open source crunchers.
Final Remarks
These notes just touch the surface of all the things you can do in Ajax. I didn't discuss the back-end at all, though Ajax extensions are appearing for most back-end solutions. As you can see, Ajax apps integrate HTML, CSS and JavaScript. You end up needing to learn all three, but the results can be very rewarding.
Have fun!