One of the major changes taking place in the 5.4 branch is the choice
between explicit initialization and unobtrusive initialization.

Tapestry has traditionally used explicit initialization:
- render and element, with a specific id
- generate "parameters" object that describes the behavior, and references
that id
- import a JavaScript library that provides a T5.initializers function
- Invoke that function with the parameters object when the page loads

With 5.4, we're leveraging unobtrusive initialization. In this style,
specific elements have special class names (or, increasingly, data-
attributes).  A module is imported that provides a document-level event
handler for events (both DOM events, and custom events) that originate in
such elements.

Sometimes groups of data-attributes work together, for example in 5.4,
validation now looks something like this:

<input ... data-validate="true" data-optionality="required"
data-required-message="You most provide a user name."/>

What's nice about this approach is that, when new content is added to the
page via Ajax or DHTML, the underlying validation behavior is instantly in
place ... no wait of any kind for initialization, and no processing time
spent performing the initialization. Likewise, if content is removed from
the DOM, there's no possibility (even in IE) of memory leaks from cycles
between JavaScript objects and closures, and DOM objects.

A nice note about this is that even elements that are rendered entirely on
the client (perhaps using Backbone, as with my main client projects) can
now pretty easily participate in validation, just by providing the right
data- attributes.  At some point, we'll need to create a dictionary of
these different attributes and how they related to each other!

This unobtrusive, attribute-driven, approach works great on things that are
rendered entirely the server side. As I'm recoding more sophisticated
components, such as the Palette, I'm hitting components that want to do
some rendering or setup on the client. Even here, there's room for explicit
or unobtrusive.

To accomplish unobtrusive, we could do a scan when the page loads for
elements; for instance, the Palette component could render a
data-component-type="core/Palette" attribute, and code inside the
core/palette module could locate such elements and wire them up.

The challenge there is that, on an Ajax update, we need to scan the newly
added content and the DOM does not directly provide a way to do that.
However, the Zone component (and other things that act like a Zone) emit
custom events before and after updating the DOM.  So we could do one scan
on initial page load, and an additional scan, just on updated zone content,
whenever a zone does in fact update.

The advantage here is moving away from Tapestry-generated unique ids, and
all the confusion associated with them.

Has anyone else pursued the unobstrusive/scanning approach (outside of
Tapestry)?

Currently, the work I'm doing on Palette leaves it in the explicit
initialization camp. The trade-off for me is the expense of lots of
document scans looking for elements to initialize; I'm sure a larger app
with many big custom components could end up spending a lot of cycles doing
just that after every dynamic update. However, the appeal of going "id
free" is compelling.


-- 
Howard M. Lewis Ship

Creator of Apache Tapestry

The source for Tapestry training, mentoring and support. Contact me to
learn how I can get you up and productive in Tapestry fast!

(971) 678-5210
http://howardlewisship.com

Reply via email to