Document Actions
12/16/2005
CPS Ajaxification, round #1

In my last blurg I said I would select some toolkit out there to compare the result, but after some mails exchanged on Z3 mailing list ( Ajax in Zope 3 Thread), I agreed with what Benji York and Gary Poster said in this subject:

"I'm very interested in coming up with a one or more relatively simple server-side proposals to make Ajax stuff easier, but I think the Ajax stuff (and even the whole JavaScript world) is too immature to settle on one client-side implementation. Therefore we should concentrate on doing things that help most or all of the JS toolkits be more usable with Z3."

So I have started the work over CPS with Scriptaculous, focusing on uses cases and when doable, on the server-side infrastructure.

CPS Use case #1: CPSDocument AJAX form controller with graceful degradation

The first use case in CPS is to embed existing forms used to change document fields. The Javascript needs to let the user validate a form, that is sent asynchronously through an XMLHttpRequest object, to get direct feedback.

The feedback is then used on client-side to either:

  • Update the form on errors, to point out the fields that are not correct;
  • tell the user changes where made, optionnaly changes the page title when the user has change the title, and eventually redirect the user.

Since this is an ajaxification of existing server side Z2 infrastructure, it was very hard, even overkill to start doing server-side work, so for this use case I have just added a bit of code on server side to make it work, without trying to do a clean infrastructure.

The constraints are:

  • Graceful degradation: if JavaScript is not available, the form has to work as usual
  • If the user tries to send a file in the form, the classic form will be used
  • Use Object Oriented approach (OO)
  • Use Test-driven development approach (TDD)

Graceful degradation

This is one of the most interesting thing to work on: make the pages still work when Javascript is unavailable, so CPS stays compliant with all accessibility levels.

This is simply done by an unobtrusive way of doing thing: when initialized, the Javascript code hook itslef to the form, degrading its action and its submit buttons.

TDD and OO

The OO approach is very easy under Scriptaculous, wich is built on the top of Prototype. So this is as easy as Mochikit, and I would say, as easy a coding some classes in Python !

The TDD approach is very simple too: Scriptaculous comes with a unittest framework that provides usual tools you would find under Python (assertXXX methods, test fixtures, etc.). Doing TDD in Javascript come in two parts: browser-side testing and server-side testing when AJAx is involved.

browser-side testing

browser-side testing is done by creating a simple HTML file that contains all use cases to be tested, wich is the HTML environnement where the JS has to evolve, and the test object itself with all tests. When the HTML file is called, all test are called and you can even display feedback with green divs and red divs a la selenium.

Try CPSDocument Js Test here, it should fail on some testunder Firefox, maybe more on Safari, and even more under Konqueror :) (old version).

server-side testing

I won't discuss this part in that blurg, but to cover the whole code, we need to validate the code that generates AJAX answers as well.

Conclusion

CPS now has a nice AJAX form validation that will be available in the next releases, and wich is still beeing worked out in a branch at this time.

This was quite simple to do, thanks to the nice, smart js toolkit, and thanks to the scriptaculous community out there, that helped me out on some small problems

I didn't talk about two things yet:

  • Server-side infrastructure
  • Test automation

Server-side infrastructure

The next use case fits better for presenting how AJAX helpers can be done on Zope side: drag'n'drop in folderish objects.

Test automation

In my next blurg I will explain how to automate this tests and add them in a Zope environment, to be able to call them in a Python test suite, try out several browser types, and get feedback about it.

-- footnotes

tries to send a file: You cannot send file with Javascript (security hole) unless you use some iframe artifact.

Posted by Tarek Ziadé @ 12/16/2005 09:59 AM. - Categories: AJAX, cps, web, zope, zope3 -  0 comments
12/06/2005
Choosing a Javascript library for Zope

Choosing a Javascript library for Zope

Background

What's AJAX ?

(If you know it, you should skip this section)

Wikipedia says:

Asynchronous JavaScript and XML, or Ajax, is a web development technique for
creating interactive web applications using a combination of:

  - XHTML (or HTML) and CSS for marking up and styling information
  - The Document Object Model manipulated through JavaScript to dynamically
    display and interact with the information presented
  - The XMLHttpRequest object to exchange data asynchronously with the web
    server. (XML is commonly used, although any format will work, including
    preformatted HTML, plain text, JSON and even EBML)

Like DHTML, LAMP, or SPA, Ajax is not a technology in itself, but a term
that refers to the use of a group of technologies together. In fact,
derivative/composite technologies based substantially upon Ajax, such as
AFLAX, are already appearing.

(full definition here: What's AJAX ?)

In other words, AJAX allows a developer to make calls to the server from the loaded page with Javascript, and change the page based on the server's answer without having to do a complete page reload.

Since the publishing machinery is not involved, a asynchronous round-trip is very fast and allow big ergonomics improvments. This is due to the fact that asyncrhonous calls are made over server methods that just quickly renders the needed datas, in opposition to a regular call that calculates and renders a full page.

Why should we care of AJAX in Zope applications ?

AJAX isn't just the latest buzz word out there you can show up in your applications (the come-here-we-have-some effect), AJAX is not this latest and coolest technological thing all hype developers should know about.

AJAX is not the web UI silver bullet either.

AJAX is just a tool that let you focus on something that often get lost, when creating a web applications: people.

I believe this is the main reason of AJAX success: developers are able to greatly enhance their users experience with a few drops of Javascript.

Examples of use cases:

  • A select box value is changed, the values of a second one are reloaded.
  • Direct edition of page parts (see CPSWiki for instance)
  • Content panel that changes on user actions
  • Forms are checked before actually sent (see CPSMailAccess email editor)
  • etc..

People can argue there are a lot of caveats on this (for example, using the 'back' button of the navigator can brake it) but it improves so much the flexibility of a web application and make web app as reactive as desktop apps.

A recent Ajax Survey shows us that AJAX is used in real applications everywhere. Even if the amount of developers that have answered this survey is not big, it also brings a good idea on what tools are actually used to do AJAX.

Zope is not apart from the main web developpers stream, and can use any AJAX library out there. AJAX libraries have different approaches, explained in the next section.

Different libraries approaches

There are several kind of libraries available to work with AJAX:

  • Low-level client-side frameworks (LLF)
  • Client-side Application frameworks (CSF)
  • Server-side Javascript generation frameworks (SSF)
  • XForm approach framework (XFF)
  • Other frameworks

Low-level client-side frameworks

Low-level Javascript libraries provide a simple piping to access the server by wrapping XMLHTTPRequest objects and let the developper perfom DOM manipulation with the server's answer.

Most of these libraries are a thin layer that provides a portable API for these actions, and other utilies like:

  • XPath query APIs
  • XSLT APIs
  • etc.

Example of such libraries are: Sarissa, XHConn, LibXMLHttpRequest (non GPL), etc.

Here's a small example of a simple AJAX call in Sarissa:

Sarissa.updateContentFromURI = function(sFromUrl, oTargetElement, xsltproc) {
    try{
        oTargetElement.style.cursor = "wait";
        var xmlhttp = new XMLHttpRequest();
        xmlhttp.open("GET", sFromUrl);
        function sarissa_dhtml_loadHandler() {
            if (xmlhttp.readyState == 4) {
                oTargetElement.style.cursor = "auto";
                Sarissa.updateContentFromNode(xmlhttp.responseXML, oTargetElement, xsltproc);
            };
        };
        xmlhttp.onreadystatechange = sarissa_dhtml_loadHandler;
        xmlhttp.send(null);
        oTargetElement.style.cursor = "auto";
    }
    catch(e){
        oTargetElement.style.cursor = "auto";
        throw e;
    };
};

Sarissa takes care of all portability aspects to allow this code to work under most navigators that implements Javascript. These simple libraries provide a quick and simple way to use asynchronous calls on a web view.

Google has also released its XSLT/XPath JavaScript engine as an open source project: AJAXSLT

Client-side application frameworks

Most of the time, client-side application frameworks provide the same features than Low-level client-side frameworks, but also brings a higher level, component-oriented, set of APIs.

These APIs let the developer work on client-side like he or she would do in a desktop app with a classical GUI toolkit. The style and the amount of javascript code produced are very dependent on the library, and the developer is quite driven by the toolkit.

For example, toolkits like Prototype provides a object-oriented way to work in Javascript, and therefore changes a lot how Javascript is used in a web application and its importance in the architecture.

This example show how to create a class hierarchy with Prototype:

function Manager () {
    this.reports = [];
}
Manager.prototype = new Employee;

function WorkerBee () {
    this.projects = [];
}
WorkerBee.prototype = new Employee;

function SalesPerson () {
  this.dept = "sales";
  this.quota = 100;
}
SalesPerson.prototype = new WorkerBee;

etc...

Some toolkits also provide very high level functionnalities that let the developper implement common AJAX use cases in a few lines. OpenRico, which is built on the top of Prototype, is one of those.

For example, adding a nice fade effect in OpenRico is done with a single command:

new Effect.FadeTo('fadeMe',
                  .2, // 20% opacity
                  500, // 500ms (1/2 second)
                  10, // 10 steps
                  {complete:function() {setStatus('done fading element.',
                   1500);}} );

Complex use cases, like live grids, can be provided as well. See OpenRico live grid demo

Client-side application frameworks also provide other developper tools like:

  • Unit-testing framework integration, like ECMAUnit or Test.Simple
  • Debuggers
  • Different protocol for client-server dialogs (XML, JSON)

The learning curve involved by these frameworks worth it, as they bring to Javascript what we have in Python.

  • Javascript? huh! I don't want to use it
  • What if you can actually use object oriented programming in it ?
  • I always get thousands of errors in a few lines of Javascript
  • What if you can debug it ?
  • Is there any pop corn left ?

Server-side Javascript generation frameworks

Server-side Javascript generation is generally based on the no-javascript-skills-needed paradigm: the developper creates code on server side, using the server's language using specific APIs, or a specific model. The framework then automatically generates the right HTML and Javascript elements and sends them to the client. Sometime this generation is made on client sied with a javascript engine.

CrackAjax is one of those for Python, and let the developper create AJAX views:

import crackajax
import cherrypy
import ituneslib

class iTunesAjaxPage(crackajax.AjaxPage):

    @crackajax.clientside
    def do_search():
        update_list(search_songs(document.getElementById("searchbox").value))

    @crackajax.serverside
    def get_all_songs(self):
        return [self.SONGS]

    @crackajax.serverside
    def search_songs(self, query):
        query = query.lower()
        return [filter(lambda s: self.does_song_match(query, s),
                self.SONGS)]

crackajax.init("jsolait")
cherrypy.root = iTunesAjaxPage(ituneslib.Library("Library.xml"), "")
cherrypy.server.start()

The serverside decorator tags the methods to become an XML-RPC call, and the clientside automatically convert Python code into client-side javascript, using Python-to-JScript .NET compiler.

There are also less radical approaches, where the framework provides APIs to describe the javascript that needs to be created, using for example a descriptive langage that covers explicit behaviors. (see Azax approach).

XForm approach frameworks

Section to be completed (see FormFaces)

Other frameworks

They are many other hybrid approaches that mixes server-side and client-side, or approaches that provides even lower-level mecanisms.

They are not detailed here because they are often tighted to a particular web framework or don't bring more features that what we would have in other types.

Choosing a library

For CPS , and moreover for Zope-based applications, an AJAX library has to be taken in CSF category or SSF, since all functionalities available in LLF exists in CSF. The next sections provide a very quick review on existing libraries.

SSF Libraries

CrackAjax

Pros:
  • straight-forward: a server side approach, like CrackAjax or Azax, provides a straight-forward tool to add Ajax features in a web application, by hiding the Javascript layers from the developer with techniques that can be compared to Template MetaProgramming, and providing a meta langage or a set of APIs in the web application native language.
Cons:
  • not so hidden: as you can see in this CrackAjax example, the code written in Python is very similar to what you would have done in Javascript. Furthermore, it's a bit of magic since the given Python code cannot be unit tested howsoever (the 'document' variable does not exists on Python side)

Azax

Pros:
  • clean architecture: Sometime the SSF approach is also meant to drive the developper to cleary separate the Controller and the Interface. For example Azax xml templates provides a way to separate the behavior of a page and the UI, example of separation: Azax page behavior / Azax page template
  • includes a link to mochikit, allowing hybrid behaviors

Cons:

  • one more layer: This clean separation can be done straight forward in Javascript, without adding a layer, but describing behaviors in XML can also be seen as more portable and readable, because the code could work without Javascript, wich is just the last layer This approach is very similar to what XUL has in XBL Events, but this is a bit of Not Invented Here.

CSF Libraries

A quite complete survey at OSA foundation is available and EDevil's blog has a nice library list.

A library for CPS

In the next blurg, I will try to see wich library fits the best for CPS by:

  • Suming up the use cases that already need to be covered, in both Zope 2 and Zope 3.
  • Selecting the 10 best libs out there
  • Trying out all use cases with each toolkit to compare.

And please don't hesitate to react on this blurg, if you want to give more precisions or corrections on some toolkits, or if you have opinions, comments. These will be integrated on the page.

Thanks to Paul Everitt, for for pointing out some mistakes on this entry, and for pointing out the XForm approach, that will be completed soon.

Posted by Tarek Ziadé @ 12/06/2005 11:09 AM. - Categories: cps, rich_client, web, zope, zope3 -  0 comments
Last modified: 01/25/2005 06:15 PM

Nuxeo Bloggers: Log in!
Nuxeo - Indesko - Nuxeo 5 Project
All content is copyrighted by their author.
CPSSkins is Copyright © 2003-2006 by Jean-Marc Orliaguet. | CPS is Copyright © 2002-2006 by Nuxeo SAS.