December 27th, 2007

Widgets the YUI Way

12 comments on 1229 words

Why are there so many lightbox implementations? Why are there numerous “versions” of widgets? Do you know which fork is the latest and greatest? Probably not, and for good reason. The current system sucks.

Over the past few days I’ve been studying the YUI library and it’s accompanying ecosystem. It’s truly a well oiled machine. But besides being developed by a web giant, what makes it tick? There are numerous things I’ve come to conclude, and it shines a light on why widget efforts by Prototype developers et al have largely failed.

The public face

  • Documentation: This is the most obvious one, but the one we get wrong 90% of the time. If you’ve written a widget, you have intimate knowledge of it’s inner workings and how to use it, knowledge your audience doesn’t have. We make the assumption that consumers will understand our products on the same level we do. This isn’t the case. Even YUI beta code has full documentation and a host of examples.

  • Centralization: If you want a YUI calendar control, where is the first place you look? On the YUI site. If you search Google for YUI, you get the official YUI calendar and also a collection of blog post showing some cool tricks and general usage of the official control. If you want to learn how to use the YUI Calendar control, where is the first place you look? The YUI site. It’s all organized and centralized.

  • Standardization: Everything is standardized. Everything from how articles are written and structured to the release cycles and code conventions. Take a look at the Drag and Drop landing page and then the Dom Collection landing page. Notice the clear and concise explanation of what the component is. Also note the bullet points for quickly navigating a page, the “Getting Started” headers, the cheat sheets and the examples—It’s extremely helpful. Don’t forget about YUI Theatre either.

The code

  • Modularity: The code is extremely well structured. It’s not all or nothing. I’ve not been a fan of deep namespacing (e.g. YAHOO.widget.Menu), but in this context I think it’s important. It not only has utility, it creates a visual hierarchy with only small overhead. I definitely prefer common utilities such as $('foo) and baked in enumerations (augmenting native prototypes), but I’m fine with doing var menu = new YAHOO.widget.Menu("mymenu");.

  • Event Driven: This one was enlightening for me. Most of YUI’s widgets rely heavily on custom events to pass messages internally and externally. Notice how all of the “interesting moments”, both private and public are handled through events setup in a Menu’s initialization routine. None of them are directly invoked by another method.

  • Inline documentation: I debated whether this was important enough to warrant a bullet point (it was encompassed with the public api docs), but as I continued to study the code the inline API comments were indispensable. Whenever I wondered what an argument meant, I could see it documented a few lines above where I was scanning the code. Check out this snippet from YUI’s CustomEvent object.


    /**
     * Notifies the subscribers.  The callback functions will be executed
     * from the scope specified when the event was created, and with the 
     * following parameters:
     *   <ul>
     *   <li>The type of event</li>
     *   <li>All of the arguments fire() was executed with as an array</li>
     *   <li>The custom object (if any) that was passed into the subscribe() 
     *       method</li>
     *   </ul>
     * @method fire 
     * @param {Object*} arguments an arbitrary set of parameters to pass to 
     *                            the handler.
     * @return {boolean} false if one of the subscribers returned false, 
     *                   true otherwise
     */
    fire: function() {
     //...
   }
   //...

Notice the method signature for fire. At first glance it looks like it doesn’t take any arguments, but take a look at the signature in the documentation. Pretty nifty trick. Notice this line in the comments: @param {Object*} arguments. The * tells JsDoc Toolkit to treat the following word as an argument for the method. JsDoc Toolkit can do some really cool stuff and has made vast improvements since it’s inception as JSDoc. It also now speaks Prototype.

Summing up

We can learn a lot from YUI, it has some of the smartest minds in the industry working on it. I encourage you to have a look yourself, study it, and take note of their practices and apply them to your own ventures in the world of widgets.

Discussion

  1. Wreck Wreck said on December 28th

    You know one thing i wish Justin? Is that you would post more often, because enjoy reading your stuff.

    Good points you have made here, i think an organizational change is in order. I’m not a fan of deep namespacing either when doing things just for myself, however it really makes sense in this scenario.

    Thanks.

  2. Priit Tamboom Priit Tamboom said on December 28th

    YUI is nice (I’m using always their CSS framework), their widgets are well made and the very same time quite heavy in sizes.

    eh, in contrast, I just stumbled to your last December’s post “avoiding-bloat-in-widgets” :-) http://alternateidea.com/blog/articles/2006/12/4/avoiding-bloat-in-widgets

  3. Kim Kim said on December 28th

    FYI: The link to “Drag and Drop” and “DOM” points to the same place

  4. Justin Palmer Justin Palmer said on December 28th

    @Priit: I want to make sure people distinguish between file size and bloat. Bloat has little to no benefit for the majority of end users.

    @kim: Fixed. Thanks for the heads up.

  5. Mark Holton Mark Holton said on December 28th

    Great article… great piece of advice to study YUI, will do.

    ...so is there any movement towards a centralized location for Prototype-based widgets? That would be nice… i know YUI has it, likewise jQuery. Would be great if it was an additional ‘tab’ on the prototypejs.org site, perhaps maintained by the community.

    Thanks- :Mark

  6. Michael Michael said on December 28th

    Namespaces are a good thing that gives me freedom to name my objects as I please without worrying about conflicts and reserved words. I usually alias them like this for quicker access:

    
    // put your code in a closure to avoid creating global vars
    (function() {
    
    // alias the namespaces
    var Dom      = YAHOO.util.Dom;
    var Event    = YAHOO.util.Event;
    var Calendar = YAHOO.widget.Calendar;
    
    // create a calendar
    cal = new Calendar('someid');
    
    })();
    
  7. kangax kangax said on December 28th

    @Mark Holton

    We have released Scripteka some time ago exactly for such purpose – indexing all prototype-based extensions in one place. This is not an official repository but the prototype core team feels very positive about it.

    Best, kangax

  8. Gabriel K. Gabriel K. said on December 29th

    I deeply agree with you. When things are getting more or less quivalents, this is the kind of details that make the difference.

    Did you see ExtJS? What do you think about the 2.0 release? The example are impressives. Documentation is here. Centralisation. But… >500ko! Hum..

  9. Dustin Diaz Dustin Diaz said on December 30th

    Well this was a pleasant surprise of a post to catch near the new years. It’s fun that you’ve dug into YUI to get a good idea of what’s going on underneath. The documentation alone I felt was reason enough in its early stages once it went public. The fact that people mentioned that there would be too steep of a learning curve seemed a bit of a fussy excuse since everything you need to know is on the YUI website.

    I think the differences between bloat and filesize is that bloat is simply unnecessary components or making costly assumptions in your code. Filesize is what we all have to live with. If you want things to work in a wide array of browsers, then you have to drop in the code to make that work.

    Remember the page weight blog post? http://yuiblog.com/blog/2006/10/16/pageweight-yui0114/

    As long as we’re minifying, then gzipping our files, that should turn a 45k file into a 3k file. And if available, throw it on a cdn with edge caching, then you’re definitely good to go. It completely debunks the “library size” myth people always grump about.

  10. Erin Erin said on December 31st

    After that you could of course begin implementing widget analytics. Its quite easy for online/offline widgets by using tools from Clearspring. I know its swaying from the topic a tiny bit, but I followed this guide and then began using their a widget analytic tools at www.clearspring.com, specifically the analytic tools explained here http://www.clearspring.com/docs/reporting , to determine if my new design had an effect on use, and I was happy to say it did!

  11. codebrulee codebrulee said on December 31st

    I could not agree more with your point about being Event Driven. About a year ago, I was involved with making a web application that replaced a desktop app, and our decision to use events (we had to do it ourself due to our JS framework at the time not having it) to communicate with different components made all the difference, IMHO.

  12. Will Will said on January 12th

    Lets not get me started on documentation, or lack there of.

Sorry, comments are closed for this article.