YUI 3: Lighter, Faster, Easier to Use

Share this article

In August of 2008, the Yahoo User Interface team released the first preview release of YUI 3, a complete rewrite of YUI from the ground up (the first beta release of which is due out some time next week!).

Why would they rewrite an already useful and mature library, you might ask? Well, as YUI 2 matured, the manner in which it was built also evolved.

As a result, parts of YUI that were present from the beginning were coded in an entirely different way from parts that were added later on. The result was that the library contained inconsistencies – both in the internal mechanics and the API. So, the team decided that they’d bring the library back to basics and rebuild it from the ground up. Their plan was to apply the experience they gained from the past three years of working on YUI and build a library that was lighter, faster, and easier to use. Finally, in an effort to make the library as flexible as possible, YUI 3 introduces an all new plugin architecture that allows you to add your own functionality to nodes and widgets. We’ll see one such plugin in action a little later. First, let’s see what’s new in YUI 3.

Goodbye YAHOO, hello YUI

The first bit you’ll notice when looking at YUI 3 code examples is the new global object name that it uses. The old YAHOO global object has been replaced with the new YUI global object. It was renamed for a couple of reasons: user feedback suggested that some companies disliked having the Yahoo name in their code; but more importantly, it allows older versions of YUI to coexist with YUI 3 by virtue of having a different variable name.

As well as the global object being renamed, its usage is based on a fundamentally different principle than in 2.x. For starters, it’s no longer a static object but rather a function that, when executed, returns an instance of itself. Now, every execution of YUI returns a self-contained environment where the version of the library and the version of all of its loaded components can run without interfering with any other instance of YUI on the page. By extension this also means that multiple versions of the library can coexist on the same page, by instantiating different versions of the YUI object. The example below illustrates this principle:

 
YUI().use('dd-drop', 'anim', function(Y) {
   // Y.DD is available
   // Y.Anim is available
}

Here, YUI() is executed, which returns an instance of the library from which the use method is executed. A minimum of two parameters are required: the library components, then the callback to run once everything is done loading. In our above example, the first two parameters passed to use are the names of the library components that are to be loaded. The final parameter is our callback function, which receives an object (named Y in the example) – this is an instance of the library containing all of the loaded components. So, like the comments in the example above, the drag and drop component can be found at Y.DD, and the animation component can be found at Y.Anim.

A Cleaner, More Succinct Coding Style

One of the main concerns the team had was to ensure consistent internal mechanics and a consistent API across all YUI components. So YUI 3 now has a new hierarchy of classes that allow exactly that. The Attribute class, for example, provides get and set methods, initial configuration support, and attribute change events to classes that inherit it. There’s also a Base class that inherits from Attribute and provides some out-of-the-box object oriented functionality, like initializer and destructor methods for all classes that inherit from it. Finally, they’ve built a Widget class that inherits from Base and provides common functionality normally used by widgets, such as a render method – a common Model-View-Controller structure for managing the widget’s rendering – and support for common widget attributes. It also provides plugin registration and activation support.

Another problem YUI 3 overcomes is when your script needs to load a heavy piece of the library for only one or two functions contained within it. For example, in YUI 2 you’d have to include the entire Connection Utility (weighing 38KB, 12KB when minified) just to do some XMLHttpRequest calls. YUI 3 solves this problem by splitting up functionality into smaller submodules. That way, there’s no need to pull down the entire utility just to make XMLHttpRequest calls. In YUI 3 you can make an XMLHttpRequest call by only pulling down the IO Utility’s io-base module, weighing a mere 19KB (4KB minified). In fact, the entire IO Utility weighs 29KB (7KB minified) and is much more feature-rich than its predecessor. For example, it’s now possible to make cross-domain or XDomainRequest calls with the io-xdr submodule.

Selecting and Chaining

YUI 2 introduced a selector engine, but it did so a little late in the library’s life. As a result, the whole library is built around old-school element fetching techniques. In other words, you either passed an element’s id or the element itself whenever a reference was needed, and that was about it. With YUI 3, however, the selector engine is built right into the very core of the library. It permeates every part of it so that you can pass CSS selector strings virtually anywhere an element reference is needed. As well as constructors, that also includes setting up event handlers and working with utilities. Here’s an example, which makes the first element with the class author draggable:

var dd = new Y.DD.Drag({
   node: '.author'
});

Whenever YUI 3 has no logical value to return, it tries to make the method chainable. Here’s an example of that in action:

Y.get('.author').setStyle('cursor', 'move');

Here, we referred to the first element with the class name author and set a cursor style on it.

Nodes and Event Façades

YUI 3 introduces a new abstraction layer for the DOM with the Node Utility. Rather than return a reference to a DOM element, YUI 3 returns Nodes and NodeLists, which greatly simplify DOM interaction. That’s because Nodes include all the functionality you need in order to interact with them, rather than having to go to separate functions. What’s more, the methods that are exposed by a Node take care of browser normalization whenever it’s needed so the experience of working with them is as painless as possible. Here’s what you’d have to write in YUI 2 in order to add a class name to an element:

YAHOO.util.Dom.addClass("navProducts", "selected");

In YUI 3 this becomes:

Y.get("#navProducts").addClass("selected");

In fact, if the node was already in hand, say in a variable named navProducts, then you’d simply be able to do this:

navProducts.addClass("selected");

YUI 3 simplified the interaction with the DOM, and has also normalized event management using the idea of an event façade. Every event listener receives an event façade that takes care of all the browser normalization. So, for example, where in YUI 2 you needed the following code in order to “prevent default”:

YAHOO.util.Event.on("navProducts", "click", YUI2callback(e) { 
 e = e || event;
 YAHOO.util.Event.preventDefault(e);
});

Now all you need to do is:

navProducts.on("click", YUI3callback(e) { 
 e.preventDefault();
});

What’s more, this behavior extends over to purely custom events as well, so even these receive event façades that allow them to prevent default and stop propagation.

Next: let’s put some of these new methods into practice.

Show Me the Money!

I’ve built a simple example page demonstrating how easy and powerful YUI 3 is to use. To save space here in the article, I’ll avoid showing you all the markup and code, but you can view the full source on the example page.

The first task I do is load up an instance of YUI with the Animation Utility, Slider Widget, MenuNav Node Plugin, and Drag & Drop Utilities. YUI goes and fetches the necessary files and their dependencies from the Yahoo servers. It then returns an instance of YUI with the loaded components to the callback function, which receives it in the variable named Y:

YUI().use('anim', 'slider', 'node-menunav', 'dd-drag', function (Y) { ...

Next, I create a simple animation to bounce the page’s contents into view. In order to do this, I instantiate a new Animation object. I pass it a reference to the element with the id main and tell it to animate the top value to 0 from wherever it currently is (right now it’s at -1000px, as specified in the example page’s markup). I also specify that the animation should take three seconds and that it should use the elasticOut easing method. Once the object is instantiated, it’s just a simple case of running it with the run method:

  
/*  
* Bounce-in Anim  
*/  
var anim = new Y.Anim({  
 node: '#main',  
 to: {  
     top: 0  
 },  
 duration: 3,  
 easing: Y.Easing.elasticOut  
 });  
anim.run();  

Next, I set up a Slider object in order to let users adjust the page’s base font size. YUI’s fonts CSS (included in the example page) sets the page’s base font size to 13 pixels. It does this by setting the font-size value on the body element, from which all other font sizes are calculated. This is what we’re going to manipulate in order to change the whole page’s font sizes.

I grab a node reference for the body element, which will be used later in conjunction with the slider. Then I create a slider widget. I set the minimum value to 13 and the maximum to 28 because I want the font size to stay within these values. I then make sure the slider’s rail size is 100 pixels wide. Finally, I set the slider’s thumb image (which is loaded directly off Yahoo’s hosted servers):

/*  
* Font Size Slider  
*/  
 var body = Y.get('body');  
 var slider = new Y.Slider({  
   min: 13,  
   max: 28,  
   railSize: '100px',  
   thumbImage:  
   'http://yui.yahooapis.com/3.0.0pr2/build/  
   slider/assets/skins/sam/thumb-classic-x.png'  
   });

Once the slider is instantiated, it’s just a simple matter of rendering it. I do this by calling the slider’s render method with the class name of the element I want it rendered in. The slider widget will render in the first element in the DOM that matches that class name:

slider.render('.horiz_slider');

The only task left to do now is to wire up the slider so that it actually adjusts the page’s font size. This I do by hooking into its after event. YUI 3 has standard on and after events you can hook into to make event handling like this much easier than in the prior version. Now, whenever the valueChange event is fired, our body element’s fontStyle value is changed:

slider.after('valueChange', function (e) {  
 body.setStyle('fontSize', e.newVal + 'px');  
});

I’ve also set up a navigation menu. Once the page’s content is ready I plug the MenuNav Node Plugin into the nav node. It then automatically sets up a navigation menu based on the markup that it finds – as simple as that! Here’s the code:

/*  
* MenuNav  
*/  
Y.on('contentready', function () {  
 this.plug(  
   Y.plugin.NodeMenuNav,  
     {mouseOutHideDelay: 1});  
}, '#nav');

Finally, I make the picture of yours truly draggable by simply instantiating a new drag and drop object and passing it a reference to my picture’s class name. As soon as the object is created, the image is draggable. As an added touch, I change the mouse cursor when it hovers over the image so that it’s apparent that the image is draggable:

/*  
* Drag and Drop  
*/  
 var dd = new Y.DD.Drag({  
   node: '.author'  
 });  
 
 Y.get('.author').setStyle('cursor', 'move');  
});
Summary

So, as you can see, YUI 3 is a completely different animal than its predecessor. Along with a new syntax, you gain a faster, lighter, easier, and more flexible library – ready to take on your most ambitious web projects.

Seeing this was a primer, we’ve barely scratched the surface of what’s possible with YUI 3. For more reading, check out the YUI 3.x Preview Release 2 page, Satyen Desai’s presentation on YUI 3, and the YUI 3 forum.

Frequently Asked Questions about YUI 3

What are the new features in YUI 3?

YUI 3 introduces a host of new features designed to make web development easier and more efficient. These include a new event system that allows for more flexible event handling, a new module system that simplifies the process of loading and using modules, and a new attribute system that provides a consistent API for working with object properties. Additionally, YUI 3 includes a number of new utilities and widgets, such as Node and NodeList for DOM manipulation, IO for Ajax requests, and Widget for creating reusable UI components.

How do I create a YUI 3 module?

Creating a YUI 3 module involves defining a new module using the YUI.add() method, specifying the module’s dependencies, and then implementing the module’s functionality. The module’s dependencies are specified as an array of module names, and the module’s functionality is implemented as a function that receives the YUI instance as an argument. This function is where you define your module’s methods and properties.

How does the new event system in YUI 3 work?

The new event system in YUI 3 is based on the concept of event targets and event handlers. An event target is an object that can emit events, and an event handler is a function that responds to those events. You can create an event target by extending the EventTarget class, and you can attach event handlers to an event target using the on() method. This system allows for a high degree of flexibility in how events are handled.

What is the purpose of the attribute system in YUI 3?

The attribute system in YUI 3 provides a consistent API for working with object properties. It allows you to define attributes with a specific set of characteristics, such as whether they’re read-only or write-only, whether they have a default value, and whether they should trigger a change event when their value is modified. This system makes it easier to create objects with a well-defined interface.

How do I use the IO utility in YUI 3 for Ajax requests?

The IO utility in YUI 3 provides a simple and consistent API for making Ajax requests. You can use the io() method to send a request, specifying the URL, the request method (GET or POST), and any data to be sent with the request. The io() method returns a transaction object, which you can use to handle the response.

How do I use the Node and NodeList utilities in YUI 3 for DOM manipulation?

The Node and NodeList utilities in YUI 3 provide a simple and consistent API for manipulating the DOM. You can use the Y.one() method to get a reference to a single DOM element, and the Y.all() method to get a NodeList representing a collection of elements. These methods return Node and NodeList instances, which provide a host of methods for manipulating the elements they represent.

How do I use the Widget utility in YUI 3 to create reusable UI components?

The Widget utility in YUI 3 provides a framework for creating reusable UI components. A widget is essentially a visual component that encapsulates a specific piece of functionality. You can create a widget by extending the Widget class and implementing the methods and properties that define your widget’s behavior and appearance.

How do I load and use modules in YUI 3?

Loading and using modules in YUI 3 is done using the YUI().use() method. This method takes as arguments the names of the modules to load, and a callback function to execute once the modules are loaded. The callback function receives a YUI instance as an argument, which provides access to the loaded modules.

How do I handle errors in YUI 3?

Error handling in YUI 3 is done using the Y.error() method. This method throws an error with a specified message, and optionally logs the error and halts the execution of the current code block. You can catch and handle errors thrown by Y.error() using a try/catch block.

How do I extend classes in YUI 3?

Class extension in YUI 3 is done using the Y.extend() method. This method takes as arguments the constructor of the class to create, the constructor of the class to extend, and an object containing the methods and properties to add to the new class. The new class inherits all the methods and properties of the class it extends, and adds or overrides them with the methods and properties specified in the third argument.

Ara PehlivanianAra Pehlivanian
View Author

Ara has been working on the Web since 1997. He's been a freelancer, a webmaster, and most recently, a front-end architect and practice lead for Nurun, a global interactive communications agency. Ara's experience comes from having worked on every aspect of web development throughout his career, but he's now following his passion for web standards-based front-end development.

Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week