Asynchronous page updating with Prototype

AJAXLet’s face it– page pizzazz, facilitated by JavaScript magic, is all the rage these days (along with disco dancing). And for good reason! Not only do various JavaScript libraries, like Prototype, assist in building slick effects and enable asynchronous behavior, but they also begin to shift the burden of resources towards the client.

For instance, rather than building a data-full page on the server, which could take resources (like processing power, memory, time, etc), by properly leveraging Ajax techniques, some subset of the page can be built in the server side and then other portions can be updated (resulting in smaller data transmissions between the client and the server), based upon events on the client side. Don’t get me wrong, the server side is still doing a lot of work– just not all at the same time. In fact, the server will be handling more requests, but those requests will be smaller.

In this age of Aquarius, there’s no shortage of JavaScript libraries available for facilitating Ajax (among other things, man). One contender is the aforementioned Prototpye. Prototype makes asynchronous page updating a cinch– for example, imagine an on-demand search system that searches various websites for specific items. When a user goes to their specific search page, rather than loading all the results during the page load (which can take a bit) an asynchronous call is made during a specific event to load the individual items.

AJAXWhen a page loads an initial table-like structure describes the search item’s facets. Yet, after the entire page is loaded, the magic happens.

First, to capture the page load event, you need to leverage Prototype’s document.observe call. This takes an event type and a function to call. The function that will be called will then leverage Ajax to call a server side resource to display the items found.

Accordingly, the event code looks like this:

document.observe("dom:loaded", getSearchResults());

The function getSearchResults is fairly simple, man. It uses Prototype’s Ajax.Updater function to do essentially two things: first, it invokes a specific URL and second, it can replace the contents of a specific DOM element with what’s returned from the URL. Accordingly, you’ve got to build a specific URL– which usually involves leveraging parameters– in my case, I’ve got to supply an id and a zipcode.

function getSearchResults() {
  var baseUrl = "${createLink(controller:'search', action:'getSearchResults')}" ;
  var pars = "searchid=${search.id}&zipcode=${search.account.zipCode}";

  new Ajax.Updater("searchresults", baseUrl, {
            method: "get",
            parameters: pars
  });
}

As you can see, the variable baseUrl is built leveraging Groovy’s copasetic Grails framework– a URL is built to the ’search’ controller type and the specific action invoked is the ‘getSearchResults’ one. What’s more, specific parameters are passed in as a String type. Note, this is URL is as unRESTful as it can get!

Lastly, the Ajax.Updater function is invoked, which takes three parameters– the id of a DOM element, a URL, and a series of options (in my case, they specify the HTTP method (i.e. GET, POST) and the parameters to bind to the URL).

The first parameter is the name of the id corresponding to the DOM element which needs replacing– in my case, I have a div whose id is “searchresults” like so:

<fieldset>
 <legend>Here's what we've found</legend>
 <ul>
  <div id="searchresults">
  (fetching search results....)
  </div>
 </ul>
</fieldset>

There is some server-side logic, which only displays this bit of HTML if the search is actually found– i.e. the fieldset is wrapped by a Grails GSP tag like so:

<g:if test="${search.found == true}">
...
</g:if>

AJAXConsequently, when a page loads and if that specific search has been found, a new table-like structure is displayed.

The details of the server-side’s hip handling of the getSearchResults call is not necessarily relevant at this point, suffice to say, this resource returns formatted text– it could return JSON, XML, etc– in my case, it just returns plain old HTML; in fact, it turns an unordered list. That way, no parsing is required– keep in mind my short cut does introduce a level of fog into the idea of separation of concerns, baby.

Putting it all together the work flow functions as follows:
AJAX

  1. The page loads and prototype’s “dom:loaded” event fires
  2. The getSearchResults function is called
  3. The getSearchResults function invokes Ajax.Updater, which asynchronously invokes and HTTP GET on a local URL
  4. This URL returns a snippet of HTML that is inserted into the DOM element whose id is “searchresults” without a page refresh

Prototype makes this trippin’ process quite easy– in fact, you don’t even need to use all that much of the library– in this case, two aspects were utilized– document.observe and Ajax.Updater. And the beauty, of course, of leveraging Ajax, in this case, is that the initial page load is quite fast as the amount of data is small. After the page is loaded, another call is made, which does increase the number of hits on the server, but these hits are smaller in nature, thus reducing the load. Asynchronous page updating with Prototype is a cinch, baby!

Related odds and ends
 

One Response to “Asynchronous page updating with Prototype”

  1. on 28 Sep 2008 at 8:07 pm Kyle Lahnakoski

    Interesting, your example of using search and smaller requests is quite opposite to my particular domain of “search”.

    I do not know what you experience is with your web server(s), but I find the web server latency the biggest drag: It seems that I can deliver pages an order of magnitude larger without impacting the total download time. I thought that is why GWT merges all the images into one, which I doubt is smaller, but does reduce the number of (high-latency) requests to the server.

    My search domain is only in the few-thousands: I deliver the whole inventory to the client { visibility: hidden; display: none }, and have the client perform search, or filter. I have not noticed the initial load being slow, but once the page is loaded, the user can search of filter that inventory with snappy responsiveness; much more pleasant than a request/response introduced by going back to the server.

    Furthermore, allowing the server to accept these “smaller” requests from an AJAX app, demands I have something on the server side that can accept those requests under the right context, or at the very minimum with the right authentication, which I find messy. But maybe I am doing all this web programming stuff wrong.

Trackback this Post | Feed on comments to this Post

Leave a Reply