Monday, September 26, 2011

Integrating YUI3 with Tapestry 5.2

I have become a fan of the YUI's patterns for modular architecture and the idea of executing JavaScript in a restricted "sandbox". Unfortunately, I haven't found many examples for integrating this pattern in Tapestry 5.2. The closest example for integrating YUI at the time was the tapx-yui module, but as the project is more related to YUI 2, I thought to give it a go and try to implement something for YUI 3 myself.

Step 1: importing YUI JavaScript modules and CSS
As far as I've understood, there are two ways for importing YUI modules:
  1. By importing (creating a script tag for) every YUI JavaScript asset that is required on a page.
  2. By importing the yui(-min).js asset and using the auto-loading feature.
As tapx-yui already had a great example on how to go about importing the assets one-by-one, I decided to focus on using the auto-loader approach. In the following example, I define the yui.js asset as a JavaScriptStack, which also contains 4 YUI CSS assets: cssreset, cssbase, cssfonts and cssgrids. No real reason to do so, the CSS assets could as well be auto-loaded.

In this case, all assets from the YUI build are expected to be stored under the src/main/webapp/yui directory.
The CoreYuiStack class needs to be contributed to the JavaScriptStackSource service:

Step 2: Creating a component that defines a YUI module
As soon as YUI libraries can be auto-loaded, we can start defining our own custom modules. Here is an example of a component that wraps the YUI Panel functionality. Not much augmentation here compared to the YUI's Panel, but the idea should be clear enough.

A new JavaScript namespace, appcore is defined, containing a component called Panel. The corresponding Tapestry component class looks like this:

After the component's body is rendered, we add an initialization call for passing configuration data to the new component. There is no special API here, just a simple code snippet rendered into the page body. There is some room for improvement here. Although we would very much like the initialization call to be wrapped in a sandbox, the dependency on a local variable called Y looks a bit iffy design-wise.
The YuiSupport service is responsible for wrapping the initialization calls into a YUI sandbox:

Step 3: Using the new component
The Panel component can now be used like any other Tapestry component:
The output should now contain a panel similar to this:

No comments:

Post a Comment