Tapestry Training -- From The Source

Let me help you get your team up to speed in Tapestry ... fast. Visit howardlewisship.com for details on training, mentoring and support!

Saturday, November 07, 2009

Rethinking Tapestry's approach to JavaScript

I've been doing a lot of work for a client using the ExtJS library and that, combined with many other things I've been looking at, has started to shift my attitude to the correct approach to client-side JavaScript. Not a sea change, just a minor adjustment.

Until now, I've had the approach that the page should popup "complete" and that the JavaScript should only manipulate (or add to) the content already present. In most cases, such as adding validations to user input fields, that works fine: you write out the HTML for the field, remember the id for the field, then add JavaScript that adds event handlers to the field, finding it by its id.

However, for more complex cases, such as Tapestry's Palette component, I've been coding like its 2001 for too long.

The Palette component renders out two <select> elements, plus a number of <divs>, a few buttons, and a chunk of JavaScript to connect it all together. This means generating a lot of related ids on the server (to match against the generated HTML markup) and passing those down to the client.

It's effective but it reflects my relative naivete with JavaScript back in 2001. It's now so much easier to create a DOM structure on the client, using any of the major JavaScript libraries. That, in turn, makes it much more reasonable to just write out an empty <div> element with an id and install into that empty space all the markup for the component, generated on the client side. In fact, I envision a version of the Palette for Tapestry 5.2 that starts as a <select> configured for multiple selection and is converted on the fly to the familiar Palette component entirely on the client side ... which means that it could actually operate in a functional, if limited way, even if JavaScript is disabled in the client.

ExtJS includes a number of other ideas that are worth thinking about; I've been very impressed by the concept of a separate controller hierarchy on the client side (ExtJS calls these "components" as differentiated from the DOM nodes they create and manage). That's something that's ad-hoc and inconsistent in Tapestry's client-side library. I think embracing a similar, more structured approach could make it easier for Tapestry to embrace even more dynamic Ajax behavior.


Kalin Krustev said...

Howard, I have been using ExtJS with Tapestry for prototyping a complex business application since T5 was in alpha. But when the licensing of ExtJS changed, I needed to switch to another framework. Then I discovered SmartClient. Since then, I have been impressed many times by it's design and feature richness and I am currently using it in several projects, including ones not based on Tapestry.

I am planning to release a T5 component library based on SmartClient, when I feel my code is complete enough.

Feel free to get inspired by this framework too ;)

Gabriel Kastenbaum said...

Did you ee the closure library. It's a javascript library used by Google.
Some part of closure reminds me extjs (that I like a lot, too)
It seems that can generate a lot of html with that library.
For instance :

function sayHi() {
var newHeader = goog.dom.createDom('h1', {'style': 'background-color:#EEE'},
'Hello world!');
goog.dom.appendChild(document.body, newHeader);

And you have a new page with a [h1]hello world[/h1]

Maybe the licence used by closure could be friendlier than the one used by extjs. Maybe it could be a nice replacement

Piotrek said...

@Kalin have you published your code somewhere? even if it's incomplete. any url? i'm also thinking about using T5 with smartclient but i'm on the beginning of the way. however i found it a bit difficult to use those frameworks toogether, that's why i would like to see someone's else ideas