update: I posted a piece of annoated source code that demos some of what I describe here: jQuery Toggle Widget By Example
What’s a Widget?
The widget infrastructure was introduced by the jQuery-ui library. You can think of it as a class that’s tied to a dom object. $("#foo").my_widget(); would instantiate a new copy of the my_widget widget on the #foo DOM element. A key thing to note is that if you have a list of jQuery objects $("p").my_widget(), you’d get a separate instance of the widget for each item in that list. A widget is only attached to a single DOM element.
Why Widgets?
There are a few key reasons to use jQuery’s widgets for your interaction code.
- The biggest is that it provides the level of code organization that is very hard to maintain outside of a widget structure. It changes the code from being imperative (”do this, then that, then another thing, bind to click”) to declarative (”act like an expando thing”). This frees you up to define what “expando thing” means, while not cluttering or changing the outer layer of your app. No more multi-hundred line long
$(document).ready()blocks. - Instance variables inside the widget allows you to avoid having global lookup hashes, and similar code smells.
- Easy developer cooperation. You’re working with another guy, he’s in toggle.js, you’re in window.js, and you know that you’re not going to accidentally step on each other.
What we use Widgets for at Citrusbyte
The Small Time Stuff
- Our home-grown tab library (show/hide various divs, custom events & callbacks)
- Togglable on/off switches
- jQuery UI Built-in widgets for draggable, droppable, resizable, and the rest. Often as building blocks for
- Shared widgets between clients. It’s pretty often that we need to write a generic widget that gets added to our library of easy-to-modify code. Copy into new project, tweak, and deploy. Saves us time, and our clients money.
The Big Time Stuff
- 100% JS interfaces where elements have significant state, change views, with custom events. Look for our future case study regarding this particular client.
What’s a basic widget look like?
Key things to note:
- Widgets strings all start with `ui.` in their names. Don’t be fooled into thinking this is a namespace. It’s not. You’re required to use `ui.` there. I’m not sure of the design decision behind this, but you need to watch out for it.
- Methods with an underscore are private, _init() is a magic one that jQuery calls when you initialize things
- Methods without an underscore are public.
Calling Methods After you’ve init’d the widget
Multiple Widgets on a Single DOM Element
Accessing the element from the Widget
The my_widget variable contains a reference to the current scope. So you can call methods, and so on. I like making it an explicit variable, rather than the implicit `this` because then it doesn’t get clobbered by event handler callbacks.
The $my_widget variable is the DOM element that this widget instance is attached to. Just like any other jQuery DOM element, you can search for parents(), children(), appendTo(), toggle(), attach events like click(), hover(), and whatever else you need to do.
Composing Widgets
A fun trick is to have your widget initializer define further widgets it’s own element. Any given DOM element can have many attached widgets. So you can define your own widget, and use composition to build out it’s features.
For instance:
As far as the jQuery outside world is concerned, you have a widget that attaches all that functionality in a single call to $("#foo").my_widget(). The element just automatically becomes draggable, resizable, or any other custom widget behavior you implement.
The Options Hash
You can pass an arbitrary hash of values into a widget. These can include callbacks, strings, numbers, objects, or whatever else you have.
Default Options
You can set default options for your widget by simply having an options variable set. Any options passed in by the user will overwrite your defaults.
Inheritance
Inheritance in jQuery widgets isn’t quite as smart as real class-based languages or Javascript frameworks. What is happening is that it is starting with the parent widget (ui.world), and merging in the child widget’s hash of definitions (from ui.hello). Because there’s no true inheritance, there is no easily accessible way to call super. You can still do it by doing some gymnastics with $.ui.world.prototype if you need to call the super’s copy. You can easily form a chain of widgets, each inheriting from another.
We’ve used this when we’ve needed to build out a set of different kinds of widgets that all needed similar base functionality (like drag&drop, or right-click-menu, or similar).
This kind of base functionality is provided by the jQuery UI library in the mouse class

{ 1 trackback }
{ 0 comments… add one now }