yui (advanced)
DESCRIPTION
Discussion on a few concepts in deeper detail on YUI with the Yahoo! Maktoob team in JordanTRANSCRIPT
Saurabh Sahni YDN Developer, Hacker, Evangelist
YUI (ADVANCED)
Jai SanthoshYDN Engineer, Hacker, Frontend Guy
Yahoo!
What We’re Going to Cover
• Why YUI?
• Modularity
• YUI Infrastructure
• YUI Loader – Deep dive
• Extensibility– Native and Artificial Code Structuring
• YUI is Open!
http://yuilibrary.com/
What We’re Going to Cover
• Why YUI?
• Modularity
• YUI Infrastructure
• YUI Loader – Deep dive
• Extensibility– Native and Artificial Code Structuring
• YUI is Open!
Good Architecture!!
What’s in Smart Software?
• Reliability
• Maintainability
• Compatibility
• Extensibility
What We’re Going to Cover
• Why YUI?
• Modularity
• YUI Infrastructure
• YUI Loader – Deep dive
• Extensibility– Native and Artificial Code Structuring
• YUI is Open!
Javascript Modules
// yuiblog.com/blog/2007/06/12/module-pattern
myLibrary.fizzbuzz = (function () {var myPrivateVar = "Fizz";
return {fizzbuzz: myPrivateVar + "buzz";
};})();
YUIModules
// fizzbuzz.js
YUI.add("fizzbuzz", function(Y) {
// Private variablevar myPrivateVar = "fizz";
// Export as public varaibleY.fizzbuzz = myPrivateVar + "buzz";
})
YUIModules
// DOMYUI().use("node", function (Y) {......});
// Calendar widgetYUI().use("calendar", function (Y) {......});
// YQL clientYUI().use("yql", function (Y) {......});
What We’re Going to Cover
• Why YUI?
• Modularity
• YUI Infrastructure
• YUI Loader – Deep dive
• Extensibility– Native and Artificial Code Structuring
• YUI is Open!
YUI Infrastructure• Attribute
• Base
• EventTarget
• Plugin
http://yuilibrary.com/yui/infrastructure/
YUI Infrastructure• Attribute
• Base
• EventTarget
• Plugin
http://yuilibrary.com/yui/infrastructure/
Y.Attribute// http://yuilibrary.com/yui/docs/attribute/#configurationYUI().use("attribute", function(Y) {
function MyClass(userValues) { // Use addAttrs, to setup default attributes for // your class, and mixing in user provided initial values var attributeConfig = { attrA : { // ... Configuration for attribute "attrA" ... }, attrB : { // ... Configuration for attribute "attrB" ... } }; this.addAttrs(attributeConfig, userValues);
};
Y.augment(MyClass, Y.Attribute);});
YUI Infrastructure• Attribute
• Base
• EventTarget
• Plugin
http://yuilibrary.com/yui/infrastructure/
Y.Base// http://yuilibrary.com/yui/docs/base/YUI().use("base", function(Y) { function MyClass(config) { // Invoke Base constructor, passing through arguments MyClass.superclass.constructor.apply(this, arguments); }
// Used to identify instances of this classMyClass.NAME = "myClass";
// "Associative Array", used to define the set of attributes
// added by this class.MyClass.ATTRS = { A : { // Attribute "A" configuration },
B : { // Attribute "B" configuration }};...
Y.Base...Y.extend(MyClass, Y.Base, { // Prototype methods for your new class // Tasks MyClass needs to perform during // the init() lifecycle phase initializer : function(cfg) { this._wrapper = Y.Node.create('<div
class="yui-wrapper"></div>'); },
// Tasks MyClass needs to perform during // the destroy() lifecycle phase destructor : function() { Y.Event.purgeElement(this._wrapper);
this._wrapper.get("parentNode").removeChild(this._wrapper);
this._wrapper = null; }
});});
YUI Infrastructure• Attribute
• Base
• EventTarget
• Plugin
http://yuilibrary.com/yui/infrastructure/
Y.EventTarget// http://yuilibrary.com/yui/docs/event-custom/YUI().use('event-custom', function (Y) { // EventTarget is available and ready for use.
// Add implementation code here.});
// Subscription callbacks receive fire() argumentsY.on('birthday', function (name, birthdate) { var age = new Date().getFullYear() - birthdate.getFullYear(); alert('Happy ' + age + ', ' + name + '!');});
// Fire EventsY.fire('birthday', { name: '"Uncle" Walt Whitman', birthdate: new Date(1819, 4, 31)});
YUI Infrastructure• Attribute
• Base
• EventTarget
• Plugin
http://yuilibrary.com/yui/infrastructure/
Y.Plugin// http://yuilibrary.com/yui/docs/event-custom/YUI().use('plugin', function (Y) {
// This AnchorPlugin is designed to be added to Node instances
function AnchorPlugin(config) { // Hold onto the host instance (a Node in this
case), this._node = config.host;}
// When plugged into a node instance, the plugin will be // available on the "anchors" property.AnchorPlugin.NS = "anchors";
AnchorPlugin.prototype = { disable: function() { var node = this._node; var anchors = node.queryAll("a"); anchors.addClass("disabled"); anchors.setAttribute("disabled", true); }};...
Y.Plugin...var container = Y.one("div.actions");
container.plug(AnchorPlugin);
container.anchors.disable();
container.unplug("anchors");
});
What We’re Going to Cover
• Why YUI?
• Modularity
• YUI Infrastructure
• YUI Loader – Deep dive
• Extensibility– Native and Artificial Code Structuring
• YUI is Open!
• Async loading
• Dynamic dependency resolution
• On-demand module loading
• CSS support
• ... and more
YUI Loader
YUI Loader{
combine: true,comboUrl: 'http://yui.yahooapis.com/combo?',baseUrl: '3.4.1/build',modules: { },groups: {
ymaps: { combine: true, base: '/ajaxapi-4/modules/', comboBase: 'http://l.yimg.com/zz/combo?', root: 'a/lib/map/v4/4.0.0.579/modules/', modules: { }, patterns: {
'gallery-': {}}
}},
...
YUI Loader – Module Options
• type• path• fullpath• requires• optional
• use• after• lang• condition
YUI Loader – Module Options
• type• path• fullpath• requires• optional
• use• after• lang• condition
YUI Loadermodules: {
...
'ymaps-core': { path: 'ymaps-core/ymaps-core-min.js', requires: ['event'] }, 'ymaps-config': { path: 'ymaps-config/ymaps-config-min.js', requires: ['ymaps-core', 'intl'], lang: ['en-US', 'en-GB', 'es-ES', 'es-MX', 'es-US', 'fr-FR', 'fr-CA', 'it-IT', 'de-DE'] }, 'jQuery': { fullpath: 'http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js' },
...
}
YUI Loader – Module Options
• type• path• fullpath• requires• optional
• use• after• lang• condition
YUI Loadermodules: {
...
'ymaps-stack': {use: ['node', 'event', 'event-custom']
}, 'gallery-graphics-vml': {
path: 'gallery-graphics-vml/gallery-graphics-vml-min.js', condition: {
test: function (Y) {var canvas =
document.createElement('canvas');return (!
document.implementation.hasFeature('http://www.w3.org/TR/SVG11/feature#BasicStructure', '1.1') && (!canvas || !canvas.getContext || !canvas.getContext('2d')));
},trigger: 'gallery-graphics',ua: 'ie',when: 'instead',
}
...}
YUI Loader – Applying Config
• Instance Config
• YUI_config
• YUI.GlobalConfig
• YUI.applyConfig
YUI Loader – Applying Config
...
YUI({ debug: true, combine: true, comboBase: 'http://mydomain.com/combo?', root: 'yui3/'}).use('node', function (Y) { // ...});
• Instance Config
YUI Loader – Applying Config
...
YUI_config = { debug: true, combine: true, comboBase: 'http://mydomain.com/combo?', root: 'yui3/'};
• YUI_config
YUI Loader – Applying Config
...
YUI.GlobalConfig = { debug: true, combine: true, comboBase: 'http://mydomain.com/combo?', root: 'yui3/'};
• YUI.GlobalConfig
YUI Loader – Applying Config
...
YUI.applyConfig({ debug: true, combine: true});YUI.applyConfig({ comboBase: 'http://mydomain.com/combo?', root: 'yui3/'});
• YUI.applyConfig
What We’re Going to Cover
• Why YUI?
• Modularity
• YUI Infrastructure
• YUI Loader – Deep dive
• Extensibility– Native and Artificial Code Structuring
• YUI is Open!
Good Extensibility=
Good Code Structure
• Pseudo-classical
• Prototypal
• Augmentation (Class A + Class B)
• Plugins
• Class extensions (mixins)
• MVC
Class Structure Strategies
Artificial
Native• Pseudo-classical
• Prototypal
• Augmentation
• Plugins
• Class extensions
• MVC
Class structure strategies
Native
Class structure strategies
• Pseudo-classical
• Prototypal
Pseudo-classical(Old school)
Pseudo-classical
function SubClass() { // constructor}
SubClass.prototype = new SuperClass();
SubClass.prototype.someProperty = "booga!";SubClass.prototype.someMethod = function () { ... };...
SubClass.someStaticMethod = function () { ... };...
Y.extend = function (SubClass, SuperClass, proto, static);
function SubClass() { // constructor}
Y.extend(SubClass, SuperClass);
SubClass.prototype.someProperty = "booga!";SubClass.prototype.someMethod = function () { ... };...
SubClass.someStaticMethod = function () { ... };...
Y.extend = function (SubClass, SuperClass, proto, static)
Pseudo-classical
function SubClass() { // constructor}
Y.extend(SubClass, SuperClass, { someProperty: "booga!", someMethod : function () { ... }, ...});
SubClass.someStaticMethod = function () { ... };...
Y.extend = function (SubClass, SuperClass, proto, static)
Pseudo-classical
function SubClass() { // constructor}
Y.extend(SubClass, SuperClass, { someProperty: "booga!", someMethod : function () { ... }, ...}, { someStaticMethod: function () { ... }, ...});
Y.extend = function (SubClass, SuperClass, proto, static)
Pseudo-classical
Y.SubClass = Y.extend( function() { // constructor }, /* extends */ SuperClass, { // Instance members someProperty: "booga!", someMethod : function () { ... } }, { // Static members someStaticMethod: function () { ... } });
Y.extend = function (SubClass, SuperClass, proto, static)
Pseudo-classical
Y.extend() PROs
• Creates a “clean” subclass relationship
• no YUI class requirement
• Preserves instanceof
• SubClass.superclass (not super, but close)
• Control superclass constructor execution
Y.extend() CONs
• No multiple inheritance
• Manual constructor chaining required
• Constructor chaining is awkward
• Constructor chaining may be costly
• No multiple inheritance
• Manual constructor chaining required
• Constructor chaining is awkward
• Constructor chaining may be costly
function SubClass() { // Chain superclass constructor SubClass.superclass.constructor.apply(this, arguments); // My constructor stuff ...}
AWKWARDCOSTLY?
Y.extend() CONs
To sum up
• Good for basic class inheritance
• If you can extend Y.Base, there are more options
Prototypal
Prototypal
Y.extend = function(SubClass, SuperClass,...) { var superProto = SuperClass.prototype, subProto = Y.Object(superProto);
SubClass.prototype = subProto; ...
Y.extend = function(SubClass, SuperClass,...) { var superProto = SuperClass.prototype, subProto = Y.Object(superProto);
SubClass.prototype = subProto; ...
Prototypal
Y.Object = (function () {
function F() {} return function (obj) { F.prototype = obj; return new F(); };
})();
Prototypal
// Old and bustedSubClass.prototype = new SuperClass();
Constructor
SuperClass
Prototype{}
Constructor
SubClass
Prototype
f(n)Constructor
SuperClass
Prototype
f(n)
{}
Constructor
new
f(n)
Prototype{}
BAD
Prototypal
EMPTY Constructor
(anon)
Y.Object = (function () { function F() {} return function (obj) { F.prototype = obj;’
return new F(); };})();
Constructor
SuperClass
Prototype
Constructor
SubClass
Prototype
f(n)
new
f(n)
{}Prototype
{}Prototype{} {}
Prototype
EMPTY Constructor
(anon)
Prototype
f(n)
{}
EMPTY Constructor
f(n)
Prototypal
Y.Object = (function () { function F() {} return function (obj) { F.prototype = obj; return new F(); };})();
Any Object
EMPTY Constructor
(anon)f(n)
New Object{} {}
Prototype
EMPTY Constructor
(anon)f(n)
Prototype
{}
Prototypal
Factory constructor
function Set() { var that = (this instanceof Set) ? this : Y.Object(Set.prototype); // use that instead of this [].push.apply(that._items, arguments); return that;}
function Set() { var that = (this instanceof Set) ? this : Y.Object(Set.prototype); // use that instead of this [].push.apply(that._items, arguments); return that;}
var set = new Set(‘a’,’b’);
Factory constructor
function Set() { var that = (this instanceof Set) ? this : Y.Object(Set.prototype); // use that instead of this [].push.apply(that._items, arguments); return that;}
var set = new Set(‘a’,’b’);
set instanceof Set; // true
Factory constructor
function Set() { var that = (this instanceof Set) ? this : Y.Object(Set.prototype); // use that instead of this [].push.apply(that._items, arguments); return that;}
var set = Set(‘a’,’b’); // <-- OOPS! I forgot 'new'!
Factory constructor
function Set() { var that = (this instanceof Set) ? this : Y.Object(Set.prototype); // use that instead of this [].push.apply(that._items, arguments); return that;}
var set = Set(‘a’,’b’);
set instanceof Set; // true
Factory constructor
Y.Object() PROs
• Avoids copying a lot of properties
• Can be used to make factory constructors
• Can be used to store original values for revert
• Any object can be the prototype
• Avoids class explosion
Y.Object() CONs
• No multiple inheritance
• Factory constructor can promote sloppiness
• Can’t use hasOwnProperty in for/in loops
To sum up
• Useful for some internal logic patterns
• Not a good fit for most web app problems
• Common use suggests need for a constructor
To sum up
var account1 = Y.Object(accountProto);account1.id = 1234;account1.holder = 'John Q. Consumer';
var account2 = Y.Object(accountProto);account2.id = 1235;account2.holder = 'Jane B. Investor';
• Useful for some internal logic patterns
• Not a good fit for most web app problems
• Common use suggests need for a constructor
To sum up
var account1 = Y.Object(accountProto);account1.id = 1234;account1.holder = 'John Q. Consumer';
var account2 = Y.Object(accountProto);account2.id = 1235;account2.holder = 'Jane B. Investor';
CONSTRUCTOR
• Useful for some internal logic patterns
• Not a good fit for most web app problems
• Common use suggests need for a constructor
To sum up
function Account(id, holder) { this.id = id; this.holder = holder;}
var account1 = new Account(1234, 'John Q. Consumer');var account2 = new Account(1235, 'Jane B. Invester');
• Useful for some internal logic patterns
• Not a good fit for most web app problems
• Common use suggests need for a constructor
Class structure strategies
Native✓ Pseudo-classical
✓ Prototypal
Artificial
• Augmentation
• Plugins
• Class extensions
• MVC
Augmentation
A C
B
Augmentation
Y.ModelList = Y.extend( function () { /* constructor */ ModeList.superclass.constructor.apply(this, arguments); },
Y.Base,
{ /* prototype */ }, { /* static */ }); Y.augment(Y.ModelList, Y.ArrayList);
Y.augment = function (to, from, force, whitelist, config)
Y.ModelList = Y.extend( function () { /* constructor */ ModeList.superclass.constructor.apply(this, arguments); },
Y.Base,
{ /* prototype */ }, { /* static */ }); Y.augment(Y.ModelList, Y.ArrayList);
Y.augment = function (to, from, force, whitelist, config)
Augmentation
Y.ModelList = Y.extend( function () { /* constructor */ ModeList.superclass.constructor.apply(this, arguments); },
Y.Base,
{ /* prototype */ }, { /* static */ }); Y.augment(Y.ModelList, Y.ArrayList);
Y.augment = function (to, from, force, whitelist, config)
Augmentation
list
ModelList
Prototype
Constructor
create
init
each
item
Y.augment(Y.ModelList, Y.ArrayList);
var list = new Y.ModelList({ ... });
list.each(function (item) { ... });
ModelList
Prototype
Constructor
create
init
ArrayList
Prototype
each
item
Constructor
each
item
Prototype
create
init
each
itemPrototype
new
Constructor
augment
Augmentation
list
item
each
ArrayList
Prototype
each
item
Constructor
Y.augment(Y.ModelList, Y.ArrayList);
var list = new Y.ModelList({ ... });
list.each(function (item) { ... });
ModelList
Prototype
Constructor
create
init
Prototype
each
item
each
Constructoreach 1. Copy
2. Construct
3. Execute
each
Augmentation
Y.augment(Y.HistoryBase, Y.EventTarget, null, null, { emitFacade : true, prefix : 'history', preventable: false, queueable : true});
Y.augment = function (to, from, force, whitelist, config)
Augmentation
Y.augment() PROs
• Defers constructor overhead
• Can augment with multiple classes
• Supports class or instance augmentation
• No YUI class requirement
Y.augment() CONs
• First augmented method call is costly
• instanceof is false for augmenting classes
• Consumes more memory
• Limited control of constructor invocation
To sum up
• Use it to simulate lazy multiple inheritance
• Y.Base-based classes should use class extensions
• Beware the diamond problem
• Weigh the importance of constructor deferral
To sum up
• Use it to simulate lazy multiple inheritance
• Y.Base-based classes should use class extensions
• Beware the diamond problem
• Weigh the importance of constructor deferral
Y.SubClass = Y.extend( function () { Y.SuperClass.apply(this, arguments); Y.EventTarget.apply(this, { /* config */ }); }, Y.SuperClass, // <-- one "official" extention class Y.mix({ /* prototype */ }, Y.EventTarget.prototype), { /* static */ });
Plugins
Aa a aa
Pluginsvar overlay = new Y.Overlay({ ... });
overlay.plug(Y.Plugin.Drag);
overlay.dd.set('lock', true);
overlay.unplug('dd');
var overlay = new Y.Overlay({ ... });
overlay.plug(Y.Plugin.Drag);
overlay.dd.set('lock', true);
overlay.unplug('dd');
Overlay
Attributes
x
y
Constructor
Overlay
ATTRS
x
y
Constructoroverlay
Attributes
x
y
Constructor
Plugins
overlay
Attributes
x
y
var overlay = new Y.Overlay({ ... });
overlay.plug(Y.Plugin.Drag);
overlay.dd.set('lock', true);
overlay.unplug('dd');
Overlay
ATTRS
x
y
Constructor
Plugin.Drag
Attributes
lock
Constructor
Plugin.Drag
ATTRS
lock
Constructor
overlay.ddAttributes
lock Constructordd
Plugins
var overlay = new Y.Overlay({ ... });
overlay.plug(Y.Plugin.Drag);
overlay.dd.set('lock', true);
overlay.unplug('dd');
Overlay
ATTRS
x
y
Constructor
Plugin.Drag
ATTRS
lock
Constructor
overlay
Attributes
x
y
overlay.ddAttributes
lock
dd
Plugins
var overlay = new Y.Overlay({ ... });
overlay.plug(Y.Plugin.Drag);
overlay.dd.set('lock', true);
overlay.unplug('dd');
Overlay
ATTRS
x
y
Constructor
Plugin.Drag
ATTRS
lock
Constructor
overlay
Attributes
x
y
overlay.ddAttributes
lock
dd
Plugins
The requirements
• Y.Plugin.Host (free in Y.Base, or add with Y.augment)
Host class
Plugin class
• Static NS property
That’s it
Plugins (instance)
Y.Plugin.Host.prototype.plug = function (Plugin, config) { ... if (Plugin && Plugin.NS) { config.host = this; this[Plugin.NS] = new Plugin(config); }};
Plugins (instance)
Y.Plugin.Host.prototype.plug = function (Plugin, config) { ... if (Plugin && Plugin.NS) { config.host = this; this[Plugin.NS] = new Plugin(config); }};
overlay.dd.set('lock', true);
overlay.unplug('dd');
The contract
SHOULD✓ Expect an object
constructor argument with ‘host’ property
✓ Provide namespaced API✓ Modify core behavior via
events or AOP
MAYSHOULD✓ Expect an object
constructor argument with ‘host’ property
The contract
✓ Provide namespaced API✓ Modify core behavior via
events or AOP
MAY
MUST✓ Remove all traces when
unplugged
SHOULD✓ Expect an object
constructor argument with ‘host’ property
The contract
✓ Provide namespaced API✓ Modify core behavior via
events or AOP
MAY
MUST✓ Remove all traces when
unplugged
MUST NOT✓ Modify host directly other
than add the namespace
SHOULD✓ Expect an object
constructor argument with ‘host’ property
The contract
Plugins (class)
Y.Plugin.Host.plug(Y.Overlay, Y.Plugin.Drag, { handles: ['.yui3-widget-hd']});
var overlay = new Y.Overlay({ ... });
overlay.dd.set('lock', true);
Plugin PROs
• Avoids method/property naming collisions
• Preserves host behavior when unplug()ed
• Plug classes or instances
• Generic plugins can work for multiple host types
• Works on Nodes
Plugin CONs
• Fragments API
• Plugin contract to restore host can add code weight
• Difficult to manage competing plugins
• plug() could use a little sugar
To sum up
• Flexible
• Better in smaller numbers
• Class Plugins vs Augmentation?
• Free with Y.Base-based classes and Y.Nodes
(have I mentioned that you should use Y.Base?)
Class Extensions
A C
B
Y.Base
Class extensionsY.extend = function (SubClass, SuperClass, proto, static)
Y.SubClass = Y.extend(
{ someProperty: ‘booga!’, someMethod : function () { ... } }, {
function() { SubClass.superclass.constructor.apply(this, arguments); },
/* extends */ Y.Base
NAME: ‘subsub’,
[], // <-- class extensions!
/* NAME */ ‘subsub’,
Y.Base.create = function(NAME, SuperClass, ext, proto, static)
ATTRS: { ... } });
Class extensionsY.Base.create = function(NAME, SuperClass, ext, proto, static)
Y.LineSeries = Y.Base.create('lineSeries', Y.CartesianSeries, [ Y.Lines ],
{ /* Glue Y.Lines APIs to Y.CartesianSeries APIs */ });
Y.Base.create = function(NAME, SuperClass, ext, proto, static)
Y.LineSeries = Y.Base.create('lineSeries', Y.CartesianSeries, [ Y.Lines ],
{ /* Glue Y.Lines APIs to Y.CartesianSeries APIs */ });
Y.ComboSeries = Y.Base.create('comboSeries', Y.CartesianSeries, [ Y.Fills, Y.Lines, Y.Plots ],
{ /* Glue Y.Fills etc APIs to Y.CartesianSeries APIs */ }, { ATTRS: { ... } });
Class extensions
Y.Base.create = function(NAME, SuperClass, ext, proto, static)
Y.LineSeries = Y.Base.create('lineSeries', Y.CartesianSeries, [ Y.Lines ],
{ /* Glue Y.Lines APIs to Y.CartesianSeries APIs */ });
Y.ComboSeries = Y.Base.create('comboSeries', Y.CartesianSeries, [ Y.Fills, Y.Lines, Y.Plots ],
{ /* Glue Y.Fills etc APIs to Y.CartesianSeries APIs */ }, { ATTRS: { ... } });
Class extensions
LineSeries
Y.LineSeries = Y.Base.create('lineSeries', Y.CartesianSeries, [ Y.Lines ], { ... });
var series = new Y.LineSeries({ ... });
LinesConstructor
ConstructorConstructor
Prototype
ATTRS
ATTRS
Prototype
CartesianConstructor
ATTRS
Prototype
Constructor Constructor
Class extensions
LineSeries
Prototype
ATTRS
ConstructorConstructor
Constructor
Constructor
ATTRS
Y.LineSeries = Y.Base.create('lineSeries', Y.CartesianSeries, [ Y.Lines ], { ... });
var series = new Y.LineSeries({ ... });
LinesConstructor
ATTRS
Prototype
CartesianConstructor
ATTRS
Prototype
CartesianConstructor
ATTRS
Prototype
direction
type
LinesConstructor
ATTRS
Prototype
type
Class extensions
LineSeries
Y.LineSeries = Y.Base.create('lineSeries', Y.CartesianSeries, [ Y.Lines ], { ... });
var series = new Y.LineSeries({ ... });
Prototype
Constructor
ATTRS
CartesianConstructor
ATTRS
Prototype
direction
type
LinesConstructor
ATTRS
Prototype
typedirection
type
type
+styles
Class extensions
LinesConstructor
ATTRS
Prototype
type
LinesConstructor
Prototype
ATTRS
drawLines
LineSeries
Y.LineSeries = Y.Base.create('lineSeries', Y.CartesianSeries, [ Y.Lines ], { ... });
var series = new Y.LineSeries({ ... });
Prototype
Constructor
CartesianConstructor
ATTRS
Prototype
direction
type
ATTRS
direction
type
stylesATTRS
Prototype
CartesianConstructor
ATTRS
Prototype
draw
Class extensions
LinesConstructor
Prototype
ATTRS
drawLines
LineSeries
Y.LineSeries = Y.Base.create('lineSeries', Y.CartesianSeries, [ Y.Lines ], { ... });
var series = new Y.LineSeries({ ... });
Constructor
ATTRS
Prototype
CartesianConstructor
ATTRS
Prototype
draw
Prototype
drawPrototype
drawdrawLines
drawSeries
Class extensions
LinesConstructor
Prototype
ATTRS
drawLines
LineSeries
Y.LineSeries = Y.Base.create('lineSeries', Y.CartesianSeries, [ Y.Lines ], { ... });
var series = new Y.LineSeries({ ... });
Constructor
ATTRS
CartesianConstructor
ATTRS
Prototype
draw
Prototype
initializer
Prototype
initializerinitializer
initializer
initializer
initializer
Class extensions
Y.LineSeries = Y.Base.create('lineSeries', Y.CartesianSeries, [ Y.Lines ], { ... });
var series = new Y.LineSeries({ ... });
1. Constructors are called
2. Attributes are set
3. initializers are called
Class extensions
Two types of extensions
• Class decoration
• Core functionality
Add feature APIs and Attributes
Satisfy abstract class implementation
Y.Base.create = function(NAME, SuperClass, ext, proto, static)
Y.Overlay = Y.Base.create('overlay', Y.Widget, [ Y.WidgetStdMod, Y.WidgetPosition, Y.WidgetStack, Y.WidgetPosition, Y.WidgetPositionConstrain]);
Class extensions
Y.Base.mix = function(Class, ext)
Y.Slider = Y.Base.create('slider', Y.SliderBase,[Y.SliderValueRange]);
Y.Base.mix(Y.Slider, [Y.ClickableRail]);
Class extensions
Extensions PROs
• Promotes code reuse across environments
• Feature APIs are added to the prototype
• Can be used to mimic MVC breakdown
Extensions CONs
• Requires Y.Base
• Initialization overhead
• Class definition only (no instance feature additions)
• Does not work on Nodes
• Increased potential for accidental name collisions
Extension vs Plugin
• Extensions can be used to contribute core behavior
• Extensions modify the class prototype, plugins are always namespaced
• Feature extension constructors are always executed, plugin constructors on plug()
• Feature APIs/attributes on the prototype vs class plugins in namespace is a stylistic choice
What We’re Going to Cover
• Why YUI?
• Modularity
• YUI Infrastructure
• YUI Loader – Deep dive
• Extensibility– Native and Artificial Code Structuring
• YUI is Open!
YUI is Open!!
• Open Source
• Open CDN
• Open Hours
• Open Communication
• Open Development
• Open Documentation
References
• http://yuilibrary.com/
• Images from Google, Flickr
• http://www.youtube.com/yuilibrary
• Inheritance Patterns by @ls_n
Questions?
• Slides at http://slideshare.net/jaisanth
• Twitter: @jaisanth
• IRC freenode: #yui
THANK YOU!