Sunday, September 25, 2011

Simplifying External TagLibs with Proxies

I am the proud author of the jQuery-UI-Widget Grails Plugin.   I built this plugin to enable Grails developers the ability to create jQuery-UI widgets without dealing with JavaScript directly.   This allows Grails developers to use the resources they are familiar with while still building cool, rich User Interface components.

This post isnt about my plugin.  Instead, its about how engineers can better utilize plugins like mine.  

One of the challenges I've faced when leading a team of developers is this... How can I enforce all components of a certain type are built the same way, especially when I dont control the construction of the component itself.  A non-abstract example of this issue is this... Developers on my team are all creating jQuery-UI AutoCompletes via the TagLib.  How do I ensure all the AutoComplete configuration properties are the same?

The answer is simple.  You require all instantiations of the component to go through your own code.  This is called the Proxy Pattern.  In practice, you create a wrapper that your developers call.  This wrapper is responsible for setting the standard configuration properties for the component and creating the component itself.  The ability to override or further customize the component can be easily implemented as well.

Lets look at an example using a custom Grails Tag and my jQuery-UI-Widget plugin.  I'm going to encapsulate the jQuery-UI AutoComplete in my own tag.

def myautocomplete = { attrs, body ->

 // grab the id
 def id = attrs.remove("id")

 // create a config to pass to taglib
 def acConfig = [:]
 // pass the id along to the config
 acConfig.id = id
 // throughput the widget config or create a new one
 acConfig.config = attrs.remove("config") ?: [:]
 // enforce the delay property 
 acConfig.config.delay = 200 
 // set the minLength property if not overridden by instance config
 acConfig.config.minLength = acConfig.minLength ?: 1 

 //call the jquery-ui taglib
 out << jqueryui.jquiAutoComplete(acConfig, body)

}

This Tag is a Proxy to the jQuery-UI TagLib's jquiAutoComplete tag. The config is passed along to the target tag after any defaults are set. Doing this allows me to enforce a standard for our application's jQuery-UI Widgets.




Thats is. The idea is pretty simple overall, but flexible enough to allow my team to build the Widgets we need for our application. I've applied this approach to jQuery-UI Widgets, YUI2 Widgets and DataTables.

Tuesday, September 6, 2011

Extending jQuery-UI Widgets

I recently needed to extend the jQuery-UI AutoComplete Widget for a few custom features. The act of extending the Widget was relatively easy, but its not the entire story. Simply extending the jQuery-UI Widget will cause you to lose native functionality. Here is what I'm talking about...

Say I want to extend the jQuery-UI Widget...
$.widget("ui.myAC", $.ui.autocomplete, {
    myMethod : function(){
    },
    myOverride : function(){
        self.myOverride()
    }
});

Doing this allows me to instantiate my custom widget...
$("#myInput").myAC({});

However... the following wont work.
$("#myInput").myAC("search", "%");

Calling the widgets public methods will fail. A little debugging shows me that jQuery-UI doesnt think that method exists. Hmm... I extended a jQuery-UI Widget, but I lost the native methods. Boo!

Since jQuery-UI Widget extension has changed recently, Google didnt provide me with an obvious answer. However, I kept stumbling upon this thing called a Bridge.

Lets try it...
$.widget.bridge("myAC", $.ui.myAC);

Woot! I now have access to the native methods. Now my custom widget is fully functional.

I could attempt to explain all the different things $.widget.bridge does for us, but I'd do a poor job. Here are some folks that have already explained it.
Eric Hynds
Alex Sexton