Augmenting YUI3 Module Objects


In YUI 2 augmenting a library class is as simple as appending functions to the static object or modifying the prototype of a non-static object. Augmenting objects in YUI 3 is almost as easy, differing only in the augmentation having to be applied inside of a YUI().add() function. Although, augmenting objects is not difficult, it feels complicated until you become used to the YUI 3 way of coding. This article will cover how to augment the objects in the YUI 3 library.

To start, think about your application. Ask yourself, if you include a common set of YUI 3 modules on every page, or if each page uses a disparate set. If you include the same modules files on every page, then you can consolidate your augmentation into a single file (yui3-ext.js), otherwise, you may want to have a file for the augmentation of each module (yui3-node.ext.js, yui3-widget-ext.js, etc.). When you want to apply your augmented objects, the location of the code needs to be defined in YUI() function.

Example 1: Making Augmentation Code Available to YUI()

 // single augmentation file
YUI({
	combine: true,
	modules: {
		'yui3-ext': {
			fullpath: '/js/yui3-ext.js',
			requires: ['node', 'widget', 'cookie'],
			optional: [],
			supersedes: []
		}
	}
}).use('yui3-ext', function() {
	// your code
});

// or multiple augmentation files
YUI({
	combine: true,
	modules: {
		'yui3-node-ext': {
			fullpath: '/js/yui3-node-ext.js',
			requires: ['node'],
			optional: [],
			supersedes: []
		},
		
		'yui3-widget-ext': {
			fullpath: '/js/yui3-widget-ext.js',
			requires: ['widget'],
			optional: [],
			supersedes: []
		}
	}
}).use('yui3-node-ext', 'yui3-widget-ext', function() {
	// your code
});

The first half of Example 1 shows how to setup a single augmentation file, which in this case assumes the application uses node and widget on each page. The second half of Example 1 shows how to define a specific augmentation file for each YUI3 module. Notice in both cases, when call the YUI().use() function only the module augmentation file is called. It is safe to rely on YUI 3 to use the requires property to dynamically load the core modules, you do not have to explicitly call them.

For the rest of this article we will be focusing on how to include a single augmentation file, to be used throughout your project.

Example 2: YUI3-EXT.js

YUI().add('yui3-ext', function(Y) {
	Y.mix(Y.Node.prototype, {
		
		/**
		 * Fetches normalizes tagName.
		 * @method getTagName
		 * @return {String} The tagName.
		 * @public
		 */
		getTagName: function() {
			return this.get('tagName').toLowerCase();
		},
	
		/**
		 * Toggles the className for the provided element as a result of the boolean.
		 * @method toggleClass
		 * @param className {String} Required. The class name to apply.
		 * @param bool {Boolean} Optional. Specify class state, instead of toggle.
		 * @return {Boolean} The class was added.
		 * @public
		 */
		toggleClass: function(className, bool) {
			bool = LANG.isUndefined(bool) ? ! this.hasClass(className) : bool;
			this[bool ? 'addClass' : 'removeClass'](className);
			return bool;
		},
		
		...
	});
	
	Y.mix(Y.Widget.prototype, {
		
		/**
		 * Undisplays the widget.
		 * @method hide
		 * @public
		 */
		hide: function() {
			this.get('boundingBox').addClass('displayNode');
		},
		
		/**
		 * Displays the widget.
		 * @method show
		 * @public
		 */
		show: function() {
			this.get('boundingBox').removeClass('displayNode');
		},
		
		...
	});
	
	Y.mix(Y.Cookie, {
		myCookieFunction: function() {
			// do something,
		},
		
		...
	});
}, "@VERSION@", {requires: ['node', 'widget', 'cookie']});

Example 2 shows what should go inside of your augmentation JavaScript file. We register the name yui3-ext by calling YUI().add('yui3-ext', ...);. This is how YUI 3 knows to execute this function block if the yui3-ext package is included in a YUI().use() function. YUI 3 first looks to see if the module is defined in the module list, then it fetches the JavaScript file as necessary, and finally calls the appropriate YUI.add() function defined in the fetched file. Inside of the add function the prototype of Y.Node and Y.Widget is augmented to have additional functions, and additional functions are added to the static Y.Cookie object. This shows how to augment instantiatable objects versus static ones.

Now, in your code, any time the yui3-ext package is included all instances of Y.Node and Y.Widget, and the static Y.Cookie object will have additional functions.

Example 3: Using YUI3-EXT

YUI({
	combine: true,
	modules: {
		'yui3-ext': {
			fullpath: '/js/yui3-ext.js',
			requires: ['node', 'widget', 'cookie'],
			optional: [],
			supersedes: []
		}
	}
}).use('yui3-ext', 'slider', function(Y) {
	var node = Y.get('#myNodeId');
	node.toggleClass('myClass');
	
	var slider = new Y.Slider({});
	slider.hide();
	slider.show();
	
	Y.Cookie.myCookieFunction();
});

In Example 3 we see that each YUI 3 module is augmented, but that developers do not need to do anything special to access the augmentations. The augmentations are now part of the objects and even in the case of Y.Slider, which inherits from Y.Widget, we still find the augmented widget methods.

YUI Cookie Storage Engine


In the YUI Storage Utility article, we covered the new utility method added into YUI 2.8 for storing large amounts of data client-side using JavaScript. The utility uses a variety of engines to make this possible, and was written to be easily extensible, so developers can write and add their own engines. This article will walk through how to create a simple engine using browser cookies.

continue reading article…

YUI Storage Utility


YUI 2.8 came out last week while I was on vacation. There are many improvements, including a Storage Utility (by me) that allows developers to store large amounts of textual data client-side, regardless of whether the browser supports the proposed HTML 5 specification or not. The package does this by using one of three storage engines (HTML 5, Google Gears, or SWF), although each engine has its own limitations (see documentation). However, all engines implement the same Storage model, so they have the identical interface, regardless of their actual implementation.

Here is a visualization that describes how it works:

continue reading article…

Comparing Widget in Y2 Versus Y3


I have been wanting to do a YUI 2 versus YUI 3 comparison for some time, and it took a while to design a simple example that was complex enough to be meaningful. Anyway, for this comparison I wrote a simple CheckboxList widget, that renders a list of checkboxes and labels from a JSON object. Both versions will require only a DOM node to instantiate, they will include two custom events onCheck and onBeforeCheck, and they will have these public functions: 'clear', 'hide', 'render', 'serialize', 'show'. The 'hide' and 'show' methods will apply "display:none" and "display:block" to the root node, respectively. The 'clear' method will remove the content of the root node and then call 'hide'. The 'render' method will build the HTML from a JSON object and then call 'show'. Lastly, the 'serialize'

continue reading article…

Adding a Library Class to YUI 3


The upcoming release of YUI 3 is going to change the way we develop using the YUI framework. Instead of namespacing the library behind the 'YAHOO' object, as was done in YUI 2, in YUI 3 the library will be referenced in isolated functional contexts by calling "YUI().use". Thus developers need to modify their code to wrap everything that uses the YUI library with a "YUI().use" call.

continue reading article…