YUI 3 Introduction


kenjiru.ro@gmail.com

Overview

  • Loader
  • Modules
  • DOM manipulation
  • Event system
  • Component infrastructure
    • Y.Base
    • Attributes
    • Plugins
  • Widgets

What is YUI 3

  • YUI stands for Yahoo User Interface Library
  • JavaScript library that simplifies development
  • First release in 2006
  • Developed by Yahoo engineers



Checkout yuilibrary.com

The Seed File

Seed file:

  • YUI core
  • Loader
  • metadata for additional YUI modules

Include the YUI seed file in your HTML:
<script src="http://yui.yahooapis.com/3.10.1/build/yui/yui-min.js"></script>

More Seed Files

The Base Seed file:
  • YUI core
  • the Get utility
  • no Loader, no metadata
<script src="http://yui.yahooapis.com/3.10.1/build/yui-base/yui-base-min.js"></script>
The Core Seed file:
  • YUI core
  • the smallest seed file
  • not capable of dynamically loading other modules
<script src="http://yui.yahooapis.com/3.10.1/build/yui-core/yui-core-min.js"></script>

The Loader

Loader:
  • loads JavaScript and CSS files
  • can load external modules
  • resolves dependencies automatically
  • loads files asynchronous (default) or synchronous


Using modules

Using a module:
YUI().use('node', function(Y) {
  Y.one('#myDiv').set('text', 'Foo');
});
The workflow:
  • create a new YUI instance calling YUI()
  • call use() on the new YUI instance
    • loads any necessary modules
    • attaches them to the YUI instance
    • executes the modules
  • executes our callback method

More Use Cases

Using multiple modules:
YUI().use('node', 'anim', function(Y) {
  Y.one('#myDiv').set('text', 'Foo');
  new Y.anim({ node: '#mySpan', to: {opacity: 0} });
});
Attach modules to an existing instance:
YUI().use('calendar', function (Y) {
  // the 'calendar' module is available here
  Y.use('autocomplete', function () {
    // both 'calendar' and 'autocomplete' modules are now available
  });
});

Defining a Module

The general pattern:

YUI.add('foo', function(Y) {
  var privateProperty = 'something';
  function privateMethod() {
  };

  Y.foo = {
    privateProperty : 'private',
    privateMethod : function() { 
    }
  };
}, '0.1', { requires: ['node'] });

Advantages:

  • helps structuring the code
  • encapsulates private code

DOM Manipulation

Y.Node is the interface for DOM operations:
  • wraps the basic DOM API 
  • handles cross browser issues
  • provides convenient methods for 
    • managing CSS classes
    • setting or animating styles
    • subscribing to events
    • updating or dynamically loading content
    • and a lot more
  • the API is very similar to jQuery

Y.node

Getting a node:

var node = Y.one('#main'); // Node instance
var spans = Y.all('span'); // NodeList instance
var specialSpan = spans.one('#special');
var selectedSpans = spans.all('.selected');

Creating nodes and modifying content:

var div = Y.Node.create('<div id="main"><i>Foo</i></div>');
Y.one('#foo').setHTML('<b>Foo</b>');
Y.one('#bar').append('<span>bar</span>');
Accessing node properties:
var imgNode = Y.one('#preview');
imgNode.set('title', 'Small thumbnail..');
var src = imgNode.get('src');

Y.NodeList

Working with collections of nodes:

var spans = Y.all('#main span');

// NodeLists host most Node methods for simple iterative operations
spans.removeClass('highlight');
spans.setAttribute('foo', 'bar');

// or call each() to do more work on each Node
spans.each(function (span) {
    span.transition({ opacity: 0 }, function () {
        // ...
    });
});

Event System

  • provides APIs for browser's DOM event system
  • fixes events that behave differently across browsers
  • synthetic event system supplies entirely new DOM events
  • the user can create custom events

Basic examples:
Y.on('click', function(e) {
  // handle the event
}, '#myNode', context);
myButton.on('click', function(e) {
  // handle the event
}, context);

The Event Object

button.on('click', function (e) {
  this.get('id'); // Node instance, the button being clicked
  e.target.get('id'); // Node instance

  // Stop the event's default behavior
  e.preventDefault();
  // Stop the event from bubbling up the DOM tree
  e.stopPropagation();
});

Detaching subscription:

var sub = button.on('click', handleClick);
sub.detach(); // unbinds the event

button.detach('click', handleClick); // alternative for unbinding

Event Delegation

Advantages:

  • one event subscription handles multiple elements
  • the filtering logic is build-in as a CSS selector
// delegated subscription for all button clicks from inside the node
node.delegate('click', function() {
  this.get('id'); // now this refers to the button that was clicked
}, 'button, input[type=button]');

One time subscriptions:

Y.once('click', callback, '#myDiv');

node.once('click', callback);

The subscription will automatically be detached after the event fires.

Custom Events

this.fire('eventName', { foo : 'foo' });

// handling the event
myObject.on('eventName', function(e) {
  console.log(e.foo);
});

Advantages:

  • normalized API
  • subscribe as on and after
  • can have cancelable default behaviors
  • can bubble


Component Infrastructure

Consists of:

  • Y.Base
  • Y.Attribute
  • Y.Plugin
  • Y.Widget

Y.Base

  • low level class
  • Attribute and Event based
  • consistent init() and destroy() lifecycle
function MyClass(config) {
  // Invoke Base constructor, passing through arguments
  MyClass.superclass.constructor.apply(this, arguments);
}
MyClass.NAME = "myClass";
MyClass.ATTRS = {
  myAttribute : { }
};

Y.extend(MyClass, Y.Base, {
  // Prototype methods for your new class
  myMethod : function() { }
});

Y.Base.create

var MyClass = Y.Base.create('myClass', Y.Base, [], {
  initializer : function(config) {
    // initialization here
  },
  prototypeMethod : function() {
    this.set('foo', 'some value');
  },
  destructor : function() {
    // cleanup here
  }
}, {
  ATTRS : {
    foo : {}
  },
  staticMethod : function() {}
});

Attributes

  • get() and set() methods
  • getters, setters and validators
  • change events when attribute values change
  • read-only or write-once

Setting and getting attributes:
myObject.set('attrA', 6);

myobject.get('attrA');

Attribute configuration

this.addAttr("attrA", {
    value: 5,
    setter: function(val) {
        return Math.min(val, 10);
    },
    validator: function(val) {
        return Y.Lang.isNumber(val);
    }
});

this.addAttrs({
  attrA: {},
  attrB: {}
}, userValues);

More about attribute configuration.

Attribute Change Events

Custom Events, having the type: "[attributeName]Change"

myObject.on('enabledChange', function(event) {
  // Do something just before 'enabled' is about to be set
  var val = event.prevVal; // the current attribute value

  if (val < 10) {
    event.newVal = val + 10; // or set a new value
  } else {
    event.preventDefault(); // can prevent the set action
  }
});

myObject.after("nameChange", function (event) {
  // Do something after 'enabled' was set
});


Plugin

function AnchorPlugin(config) {
  this._node = config.host;
}

AnchorPlugin.NS = "anchors"

AnchorPlugin.prototype = {
    disable: function() {
        var node = this._node,
            anchors = node.queryAll("a");

        anchors.addClass("disabled");
        anchors.setAttribute("disabled", true);
    }
};

var container = Y.one("#myDiv");
container.plug(AnchorPlugin); // attach the plugin

container.anchors.disable(); // execute a method

Y.Plugin.Base

  • extends Y.Base (attributes, life cycle, custom events)
  • sets up host as an attribute
  • can listen for and react to events fired by the host
    • onHostEvent(),  afterHostEvent()
    • listeners are automaticaly cleaned up when unplugging
  • can inject logic before or after methods invoked on the host (using YUI 3 AOP)
    • beforeHostMethod(), afterHostMethod()
    • can prevent the default method from being executed

Y.Widget

  • the base class of all YUI 3 widgets
  • adds a render lifecycle
  • a common set of widget attributes
  • progressive enhancement
  • string localization

The Render Lifecycle

The renderer() method implementation:

renderer: function() {
  this.renderUI();
  this.bindUI();
  this.syncUI();
}

Rendered Markup:

  • boundingBox and contentBox attributes
  • BOUNDING_TEMPLATE and CONTENT_TEMPLATE prototype properties

Class names:

var class = this.getClassName("hidden"); // yui3-tooltip-hidden

Sample Widget

var Tooltip = Y.Base.create('tooltip', Y.Widget, [ ], {
  CONTENT_TEMPLATE : '<span></span>',
  renderUI : function() {
    var text = this.get('text');
    this.get('contentBox').set('text', text);
  },
  bindUI : function() {
    var targetNode = this.get('targetNode');
    targetNode.on('mouseover', this.show, this);
    targetNode.on('mouseout', this.hide, this);
  }
}, {
  ATTRS : {
    targetNode : null,
    text : { value : 'Default text' }
  }
});

HTML Output

Sample output:
<div id="yui_12" class="yui3-widget yui3-tooltip yui3-widget-positioned yui3-widget-stacked yui3-tooltip-hidden">
  <span id="yui_14" class="yui3-tooltip-content">Tooltip 4</span>
</div>


YUI 3 Introduction

By kenjiru

YUI 3 Introduction

Presentation of YUI 3

  • 1,319