yui 3: events evolved
DESCRIPTION
An overview of some of the features in YUI 3's event system. Presented at YUIConf 2009.TRANSCRIPT
YUICONF 2009
yuilibrary: lsmith
github: lsmith
twitter: @ls_n
Luke Smith
Events Evolved
Monday, January 17, 2011
YUICONF 2009
<input type="button" onclick="doSomething();">
Monday, January 17, 2011
YUICONF 2009
<input type="button" onclick="doSomething();">
Monday, January 17, 2011
YUICONF 2009
<input type="button" onclick="doSomething();">
button.onclick = doSomething;
Monday, January 17, 2011
YUICONF 2009
button.onclick = doSomething;
<input type="button" onclick="doSomething();">
Monday, January 17, 2011
YUICONF 2009
button.onclick = doSomething;
<input type="button" onclick="doSomething();">
button.addEventListener('click', doSomething, false);
Monday, January 17, 2011
YUICONF 2009
button.addEventListener('click', doSomething, false);
<input type="button" onclick="doSomething();">
button.onclick = doSomething;
Monday, January 17, 2011
YUICONF 2009
button.addEventListener('click', doSomething, false);
<input type="button" onclick="doSomething();">
button.onclick = doSomething;
Monday, January 17, 2011
YUICONF 2009
if (button.addEventListener) { button.addEventListener('click', doSomething, false);} else if (button.attachEvent) { button.attachEvent('click', doSomething);} else { button.onclick = doSomething;}
Monday, January 17, 2011
YUICONF 2009
if (button.addEventListener) { button.addEventListener('click', doSomething, false);} else if (button.attachEvent) { button.attachEvent('click', doSomething);} else { button.onclick = doSomething;}
DUMB
Monday, January 17, 2011
YUICONF 2009
<input type="button" onclick="doSomething();">
button.onclick = doSomething;
button.addEventListener('click', doSomething, false);
if (button.addEventListener) { /* madness */ }
Monday, January 17, 2011
YUICONF 2009
if (button.addEventListener) { /* madness */ }
<input type="button" onclick="doSomething();">
button.onclick = doSomething;
button.addEventListener('click', doSomething, false);
addEvent(button, 'click', doSomething);
Monday, January 17, 2011
YUICONF 2009
function doSomething(e) { if (e && e.preventDefault) { e.preventDefault(); }
return false;}
Monday, January 17, 2011
YUICONF 2009
function doSomething(e) { if (e && e.preventDefault) { e.preventDefault(); }
return false;}
Monday, January 17, 2011
YUICONF 2009
We've been through this
function doSomething(e) { if (e && e.preventDefault) { e.preventDefault(); }
return false;}
Monday, January 17, 2011
YUICONF 2009
if (button.addEventListener) { /* madness */ }
<input type="button" onclick="doSomething();">
button.onclick = doSomething;
button.addEventListener('click', doSomething, false);
addEvent(button, 'click', doSomething);
Monday, January 17, 2011
YUICONF 2009
if (button.addEventListener) { /* madness */ }
<input type="button" onclick="doSomething();">
button.onclick = doSomething;
button.addEventListener('click', doSomething, false);
addEvent(button, 'click', doSomething);
Monday, January 17, 2011
YUICONF 2009
YAHOO.util.Event.on(button,'click',doSomething);
YUI 2
Monday, January 17, 2011
YUICONF 2009
YAHOO.util.Event.on(button,'click',doSomething);
YAHOO.util.Event.preventDefault(e);
YUI 2
Monday, January 17, 2011
YUICONF 2009
YAHOO.util.Event.on(button,'click',doSomething);
YAHOO.util.Event.preventDefault(e);
YUI 2
✓Normalized subscription
Monday, January 17, 2011
YUICONF 2009
YAHOO.util.Event.on(button,'click',doSomething);
YAHOO.util.Event.preventDefault(e);
YUI 2
✓Normalized subscription✓Normalized event handling
Monday, January 17, 2011
YUICONF 2009
YAHOO.util.Event.on(button,'click',doSomething);
YAHOO.util.Event.preventDefault(e);
YUI 2
✓Normalized subscription✓Normalized event handling✓DOM-like method names
Monday, January 17, 2011
YUICONF 2009
button.on('click', doSomething);
e.preventDefault();
YUI 3
Monday, January 17, 2011
YUICONF 2009
button.on('click', doSomething);
e.preventDefault();
YUI 3
✓Normalized subscription
Monday, January 17, 2011
YUICONF 2009
button.on('click', doSomething);
e.preventDefault();
YUI 3
✓Normalized subscription✓Normalized event handling
Monday, January 17, 2011
YUICONF 2009
button.on('click', doSomething);
e.preventDefault();
YUI 3
✓Normalized subscription✓Normalized event handling✓DOM-like method names
Monday, January 17, 2011
YUICONF 2009
button.on('click', doSomething);
e.preventDefault();
YUI 3
✓Normalized subscription✓Normalized event handling✓DOM-like method names✓DOM-like context
Monday, January 17, 2011
YUICONF 2009
button.on('click', doSomething);
e.preventDefault();
YUI 3
✓Normalized subscription✓Normalized event handling✓DOM-like method names✓DOM-like context✓Terse
Monday, January 17, 2011
YUICONF 2009
We give you the DOM
Monday, January 17, 2011
YUICONF 2009
We give you the DOM
... but it works
Monday, January 17, 2011
YUICONF 2009
You are here
Monday, January 17, 2011
YUICONF 2009
Custom Events
YUI 2
Monday, January 17, 2011
YUICONF 2009
this.myEvent = new YAHOO.util.CustomEvent("myEvent");
Custom Events
instance.myEvent.subscribe(doSomething);
YUI 2
this.myEvent.fire();
Monday, January 17, 2011
YUICONF 2009
Custom Events
YUI 2
instance.subscribe("myEvent",doSomething);
this.fireEvent("myEvent");
Monday, January 17, 2011
YUICONF 2009
Custom Events
instance.on("myEvent", doSomething);
YUI 3
this.fire("myEvent");
Monday, January 17, 2011
YUICONF 2009
this.publish("myEvent", config);
Custom Events
instance.on("myEvent", doSomething);
YUI 3
this.fire("myEvent");
Monday, January 17, 2011
YUICONF 2009
Y.extend( MyClass, Y.EventTarget );
Y.EventTarget
✓ Event API
Monday, January 17, 2011
YUICONF 2009
Y.extend( MyClass, Y.Base );
Y.EventTarget
✓ Event API
Y.Base
✓ Event API
✓ Attributes
✓ Plugins
Monday, January 17, 2011
YUICONF 2009
Y.extend( MyClass, Y.Widget );
Y.EventTarget
✓ Event API
Y.Base
✓ Event API
✓ Attributes
✓ Plugins
Y.Widget
✓ Event API
✓ Attributes
✓ Plugins
✓ UI Lifecycle
Monday, January 17, 2011
YUICONF 2009
Y.extend( MyClass, Y.Widget );
Y.EventTarget
✓ Event API
Y.Base
✓ Event API
✓ Attributes
✓ Plugins
Y.Widget
✓ Event API
✓ Attributes
✓ Plugins
✓ UI Lifecycle
Monday, January 17, 2011
YUICONF 2009
Y.extend( MyClass, Y.Base );
Y.EventTarget
✓ Event API
Y.Base
✓ Event API
✓ Attributes
✓ Plugins
Y.Widget
✓ Event API
✓ Attributes
✓ Plugins
✓ UI Lifecycle
Monday, January 17, 2011
YUICONF 2009
✓DOM events
✓Custom events
Normalized subscription
instance.on("myEvent", doSomething);
button.on("click", doSomething);
Monday, January 17, 2011
YUICONF 2009
✓DOM events
✓Custom events
subscriptionUnified
instance.on("myEvent", doSomething);
button.on("click", doSomething);
Monday, January 17, 2011
YUICONF 2009
DOM Events Module/App Events
Event API
Your App
Monday, January 17, 2011
YUICONF 2009
DOMCustom Events
Monday, January 17, 2011
YUICONF 2009
DOMCustom Events
Monday, January 17, 2011
YUICONF 2009
Custom Events more DOM like
✓Unify Subscription API
- Default behaviors
- Bubbling
Monday, January 17, 2011
YUICONF 2009
Custom Events more DOM like
✓Unify Subscription API
- Default behaviors
- Bubbling
foo.on(event, fn)
Monday, January 17, 2011
YUICONF 2009
Custom Events more DOM like
✓Unify Subscription API
- Default behaviors
- Bubblingthis.publish(...)
Monday, January 17, 2011
YUICONF 2009
Custom Events more DOM like
Default behaviors
Monday, January 17, 2011
YUICONF 2009
this.publish("myEvent", config);
Custom Events
YUI 3
instance.on("myEvent", doSomething);
this.fire("myEvent");
Monday, January 17, 2011
YUICONF 2009
this.publish("myEvent", config);
Custom Events
YUI 3
Monday, January 17, 2011
YUICONF 2009
initializer: function () {
this.publish("start", {
defaultFn: this._defStartFn
});
}
Default behaviors
this.publish( name, config );
Monday, January 17, 2011
YUICONF 2009
initializer: function () {
this.publish("start", {
defaultFn: this._defStartFn
});
}
Default behaviors
this.publish( name, config );
Monday, January 17, 2011
YUICONF 2009
Default behaviors
initializer: function () { ... },
_defStartFn: function (e) {
Y.log("started " + e.time);
this._disableControls();
this._getGoing(e.urgency);}
Monday, January 17, 2011
YUICONF 2009
e.timee.urgency
this.fire("start", payload);
Event payload
Monday, January 17, 2011
YUICONF 2009
e.timee.urgency
Event payload
this.fire("start", { time: new Date(), urgency: 'ASAP'});
Monday, January 17, 2011
YUICONF 2009
instance.on("start", doSomething);
this.fire("start");
Monday, January 17, 2011
YUICONF 2009
instance.on("start", doSomething);
this.fire("start"); execute subscribers
_defStartFn
prevented?end yes
no
Monday, January 17, 2011
YUICONF 2009
function doSomething(e) {
if (e.urgency === 'ASAP') {
e.preventDefault();
}
}
Behavior is preventableprevented?
Monday, January 17, 2011
YUICONF 2009
... but it doesn't have to be
initializer: function () {
this.publish("start", {
defaultFn: this._defStartFn,
preventable: false
});
}
Monday, January 17, 2011
YUICONF 2009
... but it doesn't have to be
initializer: function () {
this.publish("start", {
defaultFn: this._defStartFn,
preventedFn: this._prvStartFn
});
}
Monday, January 17, 2011
YUICONF 2009
Monday, January 17, 2011
YUICONF 2009
Dogfood (nom)
initializer: function () { this.publish("add", { defaultFn: this._defAddFn });
this.publish("flush", { defaultFn: this._defFlushFn });}
cache.js
Monday, January 17, 2011
YUICONF 2009
Dogfood (nom)
initializer: function () { this.publish(ENTRY, { defaultFn: this._defEntryFn });
this.publish(RESET, { defaultFn: this._defResetFn });}
console.js
Monday, January 17, 2011
YUICONF 2009
Dogfood (nom)
initializer: function () { this.publish("request", { defaultFn: Y.bind("_defRequestFn", this), queuable:true }); ...}
datasource.js
Monday, January 17, 2011
YUICONF 2009
Dogfood (nom)
initializer: function () { this.publish(EV_MOUSE_DOWN, { defaultFn: this._defMouseDownFn, bubbles: true }); ...}
drag.js
Monday, January 17, 2011
YUICONF 2009
Dogfood (nom)
initializer: function () { this.publish(SYNC, { defaultFn: this._defSyncFn }); this.publish(POSITION_THUMB, { defaultFn: this._defPositionThumbFn });}
slider.js
Monday, January 17, 2011
YUICONF 2009
Dogfood (nom)
this.publish({
execute: { defaultFn : this._defExecFn },
shift : { defaultFn : this._defShiftFn },
add : { defaultFn : this._defAddFn },
promote: { defaultFn : this._defPromoteFn },
remove : { defaultFn : this._defRemoveFn }
});
async-queue.js
Monday, January 17, 2011
YUICONF 2009
We love default behaviors
You should, too
Monday, January 17, 2011
YUICONF 2009
Custom Events more DOM like
✓Unify Subscription API
✓Default behaviors
- Bubbling
Monday, January 17, 2011
YUICONF 2009
Custom Events more DOM like
Bubbling
Monday, January 17, 2011
YUICONF 2009
Bubbling
initializer: function () {
this.publish("start", {
bubbles: true
});
this.addTarget(host);
}
Monday, January 17, 2011
YUICONF 2009
Bubbling
initializer: function () {
this.publish("start", {
broadcast: 1
});
}
Monday, January 17, 2011
YUICONF 2009
Bubbling
initializer: function () {
this.publish("start", {
bubbles: true,
stoppedFn: this._stopStartFn
});
}
Monday, January 17, 2011
YUICONF 2009
Event Delegation
<UL>
<li>one</li>
<li>two</li>
<li>three</li>
<li>four</li>
<li>five</li>
<li>six</li>
Y.all('li') .on('click', sayHi);
Monday, January 17, 2011
YUICONF 2009
Event Delegation
<UL>
<li>one</li>
<li>two</li>
<li>three</li>
<li>four</li>
<li>five</li>
<li>six</li>
Y.all('li') .on('click', sayHi);
6 subscriptions
Monday, January 17, 2011
YUICONF 2009
Event Delegation
Y.one('ul') .on('click', sayHi);
<UL>
<li>one</li>
<li>two</li>
<li>three</li>
<li>four</li>
<li>five</li>
<li>six</li>
Monday, January 17, 2011
YUICONF 2009
Event Delegation
Y.one('ul') .on('click', sayHi);
1 subscription
<UL>
<li>one</li>
<li>two</li>
<li>three</li>
<li>four</li>
<li>five</li>
<li>six</li>
Monday, January 17, 2011
YUICONF 2009
Event Delegation
Y.one('ul').delegate( 'click',sayHi,'li');
<UL>
<li>one</li>
<li>two</li>
<li>three</li>
<li>four</li>
<li>five</li>
<li>six</li>
Monday, January 17, 2011
YUICONF 2009
Event Delegation
Y.one('ul').delegate( 'click',sayHi,'li');
1 subscription
<UL>
<li>one</li>
<li>two</li>
<li>three</li>
<li>four</li>
<li>five</li>
<li>six</li>
Monday, January 17, 2011
YUICONF 2009
Event Delegation
instance1
instance2
instance3
instance4
instance5
instance6
instance1.on('start', sayHi);
instance2.on('start', sayHi);
instance3.on('start', sayHi);
instance4.on('start', sayHi);
instance5.on('start', sayHi);
instance6.on('start', sayHi);
Monday, January 17, 2011
YUICONF 2009
Event Delegation
instance1
instance2
instance3
instance4
instance5
instance6
instance1.on('start', sayHi);
instance2.on('start', sayHi);
instance3.on('start', sayHi);
instance4.on('start', sayHi);
instance5.on('start', sayHi);
instance6.on('start', sayHi);
6 subscriptions
Monday, January 17, 2011
YUICONF 2009
Event Delegation
ManagerClass
instance1
instance2
instance3
instance4
instance5
instance6
Mgr.on('foo:start', sayHi);
Monday, January 17, 2011
YUICONF 2009
Event Delegation
ManagerClass
instance1
instance2
instance3
instance4
instance5
instance6
Mgr.on('foo:start', sayHi);
1 subscription
Monday, January 17, 2011
YUICONF 2009
Event Delegation
ManagerClass
instance1
instance2
instance3
instance4
instance5
instance6
Mgr.on('foo:start', sayHi);
1 subscription
initializer: function () { this.addTarget( this.get("host"); );}
Monday, January 17, 2011
YUICONF 2009
Dogfood
var draggable = new Y.DD.Drag({ node: '#dragme'});
draggable.on('start', doSomething);
Drag and Drop
Monday, January 17, 2011
YUICONF 2009
Dogfood
var draggable = new Y.DD.Drag({ node: '#dragme'});
Y.DD.DDM.on('drag:start', doSomething);
Drag and Drop
Monday, January 17, 2011
YUICONF 2009
Dogfood
Y.on('yui:log', doSomething);
Y.Global.on('yui:log', doSomething);
Y.Global
Monday, January 17, 2011
YUICONF 2009
Custom Events more DOM like
✓Unify Subscription API
✓Default behaviors
✓Bubbling
Monday, January 17, 2011
YUICONF 2009
DOMCustom Events
Monday, January 17, 2011
YUICONF 2009
Above and beyond
Monday, January 17, 2011
YUICONF 2009
Above and beyond
- Subscription context override
Monday, January 17, 2011
YUICONF 2009
Above and beyond
- Subscription context override
- Subscription payload
Monday, January 17, 2011
YUICONF 2009
Above and beyond
- Subscription context override
- Subscription payload
- Easy event detach
Monday, January 17, 2011
YUICONF 2009
Above and beyond
- Subscription context override
- Subscription payload
- Easy event detach
- "After" subscriptions
Monday, January 17, 2011
YUICONF 2009
Above and beyond
- Subscription context override
- Subscription payload
- Easy event detach
- "After" subscriptions
- New DOM events
Monday, January 17, 2011
YUICONF 2009
instance.on("start", myObj.startHandler);
on()++
Monday, January 17, 2011
YUICONF 2009
on()++
instance.on("start", Y.bind(myObj.startHandler, myObj));
Monday, January 17, 2011
YUICONF 2009
on()++
instance.on("start", myObj.startHandler, myObj);
instance.on(event, handler, context);
Monday, January 17, 2011
YUICONF 2009
on()++
node.on("click", myObj.clickHandler, myObj);
instance.on(event, handler, context);node.on(event, handler, context);
Monday, January 17, 2011
YUICONF 2009
instance.on("start", myObj.startHandler);
on()++
Monday, January 17, 2011
YUICONF 2009
on()++
instance.on("start", Y.rbind(myObj.startHandler, myObj, 1, new Date(), { foo: "bar" }));
Monday, January 17, 2011
YUICONF 2009
on()++
instance.on("start", myObj.startHandler, myObj, 1, new Date(), { foo: "bar" });
instance.on(evt, fn, ctx, arg1, ...argN);node.on(evt, fn, ctx, arg1, ...argN);
Monday, January 17, 2011
YUICONF 2009
on()++
instance.on("start", myObj.startHandler, myObj, 1, new Date(), { foo: "bar" });
instance.on(evt, fn, ctx, arg1, ...argN);node.on(evt, fn, ctx, arg1, ...argN);
node.on(evt, fn, null, arg1, ...argN);
Monday, January 17, 2011
YUICONF 2009
Above and beyond
✓Subscription context override
✓Subscription payload
- Easy event detach
- "After" subscriptions
- New DOM events
Monday, January 17, 2011
YUICONF 2009
Above and beyond
✓Subscription context override
✓Subscription payload
- Easy event detach
- "After" subscriptions
- New DOM events
Monday, January 17, 2011
YUICONF 2009
button.detach("click", doSomething);
Handles and categories
Monday, January 17, 2011
YUICONF 2009
button.detach("click", doSomething);
Handles and categories
var sub = button.on("click", doSomething);sub.detach();
Monday, January 17, 2011
YUICONF 2009
button.detach("click", doSomething);
Handles and categories
var sub = button.on("click", doSomething);sub.detach();
button.on("my-cat|click", doSomething);button.detach("my-cat|click");
Monday, January 17, 2011
YUICONF 2009
button.detach("click", doSomething);
Handles and categories
var sub = button.on("click", doSomething);sub.detach();
widget.on("guid|xChange", handleXChange);widget.on("guid|yChange", handleYChange);widget.detach("guid|*");
Monday, January 17, 2011
YUICONF 2009
Above and beyond
✓Subscription context override
✓Subscription payload
✓Easy event detach
- "After" subscriptions
- New DOM events
Monday, January 17, 2011
YUICONF 2009
Above and beyond
✓Subscription context override
✓Subscription payload
✓Easy event detach
- "After" subscriptions
- New DOM events
Monday, January 17, 2011
YUICONF 2009
instance
event
_defEventFn
instance.on(event,handler)
Monday, January 17, 2011
YUICONF 2009
instance
event
_defEventFn
instance.on(event,handler)
instance.after(event,handler)
Monday, January 17, 2011
YUICONF 2009
this.after("attrChange", this._updateUI);
After moments
Y.Base
✓ Event API
✓ Attributes
✓ Plugins
Monday, January 17, 2011
YUICONF 2009
this.after("attrChange", this._updateUI);
After moments
Side effects of a state change
Y.Base
✓ Event API
✓ Attributes
✓ Plugins
Monday, January 17, 2011
YUICONF 2009
instance
event
_defEventFn
instance.on(event,handler)
instance.after(event,handler)
Monday, January 17, 2011
YUICONF 2009
instance
event
_defEventFn
instance.on(event,handler)
instance.after(event,handler)
State UNCHANGED
Monday, January 17, 2011
YUICONF 2009
instance
event
_defEventFn
instance.on(event,handler)
instance.after(event,handler)
State UNCHANGED
Change state
Monday, January 17, 2011
YUICONF 2009
instance
event
_defEventFn
instance.on(event,handler)
instance.after(event,handler)
State UNCHANGED
Change state
State CHANGED
Monday, January 17, 2011
YUICONF 2009
Monday, January 17, 2011
YUICONF 2009
Above and beyond
✓Subscription context override
✓Subscription payload
✓Easy event detach
✓ "After" subscriptions
- New DOM events
Monday, January 17, 2011
YUICONF 2009
Above and beyond
✓Subscription context override
✓Subscription payload
✓Easy event detach
✓ "After" subscriptions
- New DOM events
Monday, January 17, 2011
YUICONF 2009
Y.Env.evt.plugins.YOUR_EVENT =Y.Node.DOM_EVENTS.YOUR_EVENT = {
on: function (type, handler, ctx) {
}
}
DOM++
Monday, January 17, 2011
YUICONF 2009
Y.Env.evt.plugins.YOUR_EVENT =Y.Node.DOM_EVENTS.YOUR_EVENT = {
on: function (type, handler, ctx) {
}
}
DOM++
Monday, January 17, 2011
YUICONF 2009
Y.Env.evt.plugins.konami =Y.Node.DOM_EVENTS.konami = {
}
Konami
Monday, January 17, 2011
YUICONF 2009
Y.Env.evt.plugins.konami =Y.Node.DOM_EVENTS.konami = { on: function (type, fn, ctx) { var progress = {}, handlers = {}, keys = [38,38,40,40,37,39,37,39,66,65], ... node.on("keydown", _checkProgress);
return detachHandle;}
Konami
Monday, January 17, 2011
YUICONF 2009
node.on('konami', addUnicorns);
Using your event
Monday, January 17, 2011
YUICONF 2009
Above and beyond
✓Subscription context override
✓Subscription payload
✓Easy event detach
✓ "After" subscriptions
✓New DOM events
Monday, January 17, 2011
YUICONF 2009
Summary✓Unified subscription
✓Default behaviors
✓Bubbling
✓Context override
✓Subscription payload
✓Easy event detach
✓ "After" subscriptions
✓New DOM events
DOMCustom Events
Monday, January 17, 2011
YUICONF 2009
Rethink how you use events
Monday, January 17, 2011
YUICONF 2009
Rethink how you build your apps
Monday, January 17, 2011
YUICONF 2009
Image credit
http://www.redandgreen.org/R2Kphotos2.htm (revolution)http://www.vinylrecords.ch/B/BE/Beatles/http://www.flickr.com/photos/farewell_goodnight/214712018/http://www.flickr.com/photos/docman/2948845217/http://www.flickr.com/photos/yabanji/3175297773/http://www.flickr.com/photos/hueyatl/233553293/http://www.flickr.com/photos/dark_hylian/56050955/http://www.flickr.com/photos/techthis/3528776386/
Monday, January 17, 2011