Seaside Ajaxification

Add the following 15 lines of Javascript to your Seaside application — and you’ll get a full blown Ajax web application for free:

$(document.body).observe("click", function (event) {
   var element = Event.element(event);
   var extractor = /<body[^>]*>((.|\s)*)<\/body>/;
   if (!element.href) element = element.up("a");
   if (element && element.href) {
       new Ajax.Request(element.href, {
           method: "get",
           requestHeaders: [ "X-Requested-With", "" ],
           onSuccess: function (transport) {
               document.body.innerHTML = 
                  extractor.exec(transport.responseText)[1];
           }
   	});
   	Event.stop(event);
   }
}.bindAsEventListener());

The script uses functionality provided by the Prototype Javascript framework. The script registers a click handler on the body of the DOM tree. The first few lines check if the clicked element is an anchor or within one. Then the anchor node is asked for its URL element.href and an Ajax request is instantiated. The last step of the event handler stops the event processing Event.stop(event);, so that the default action of the web browser is vetoed. We have to carefully tweak some options of the Ajax request: We use a GET request, as Prototype does a POST by default. Then we have to make Seaside think that we do a "full request", as we actually want to do a full request with callback processing and a rendering phase. Finally the onSuccess: handler extracts the body from the response and injects it into the current DOM tree.

That’s all that is needed to turn any Seaside application into a full blown Ajax application. People might argue that I am cheating here: I am still doing a full request, I just do it asynchronously in the background using XMLHttpRequest. This gives only a marginal speed improvement (the same amount of data is transfered), but looks much smoother than doing a full request. For example, the page does not scroll to the top and is replaced without the usual flickering a full request does. Best of it, the script works well, even if you have other manually crafted Ajax actions in your code. Furthermore it supports the use of call: and answer:, something that was not easily possible before.

Of course there are some quirks that the presented script does not solve, however all these things can be easily added. For example, it does not currently update the <head> and it does not evaluate load scripts that might come with the response. Furthermore, forms are currently not ajaxified automatically, something that can be done by observing the Javascript submit event. A major annoyance of the script is, that you loose the ability to use the back button of the web browser. The URL always stays the same. But again, this problem can be easily solved. The idea is to add the _k key as a fragment to the URL and observe potential changes in window.location. That’s something for another post.

Posted by Lukas Renggli at 24 October 2008, 8:08 pm with tags seaside, javascript, prototype link