2 Copyright (c) 2009, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
8 YUI.add('event-custom-base', function(Y) {
11 * Custom event engine, DOM event listener abstraction layer, synthetic DOM
13 * @module event-custom
23 * Custom event engine, DOM event listener abstraction layer, synthetic DOM
25 * @module event-custom
26 * @submodule event-custom-base
31 * Allows for the insertion of methods that are executed before or after
43 * Cache of objects touched by the utility
50 * Execute the supplied method before the specified function
52 * @param fn {Function} the function to execute
53 * @param obj the object hosting the method to displace
54 * @param sFn {string} the name of the method to displace
55 * @param c The execution context for fn
56 * @return {string} handle for the subscription
59 before: function(fn, obj, sFn, c) {
62 a = [fn, c].concat(Y.Array(arguments, 4, true));
63 f = Y.rbind.apply(Y, a);
66 return this._inject(BEFORE, f, obj, sFn);
70 * Execute the supplied method after the specified function
72 * @param fn {Function} the function to execute
73 * @param obj the object hosting the method to displace
74 * @param sFn {string} the name of the method to displace
75 * @param c The execution context for fn
76 * @return {string} handle for the subscription
79 after: function(fn, obj, sFn, c) {
82 a = [fn, c].concat(Y.Array(arguments, 4, true));
83 f = Y.rbind.apply(Y, a);
86 return this._inject(AFTER, f, obj, sFn);
90 * Execute the supplied method after the specified function
92 * @param when {string} before or after
93 * @param fn {Function} the function to execute
94 * @param obj the object hosting the method to displace
95 * @param sFn {string} the name of the method to displace
96 * @param c The execution context for fn
97 * @return {string} handle for the subscription
101 _inject: function(when, fn, obj, sFn) {
104 var id = Y.stamp(obj), o, sid;
106 if (! this.objs[id]) {
107 // create a map entry for the obj if it doesn't exist
114 // create a map entry for the method if it doesn't exist
115 o[sFn] = new Y.Do.Method(obj, sFn);
117 // re-route the method to our wrapper
120 return o[sFn].exec.apply(o[sFn], arguments);
125 sid = id + Y.stamp(fn) + sFn;
127 // register the callback
128 o[sFn].register(sid, fn, when);
130 return new Y.EventHandle(o[sFn], sid);
135 * Detach a before or after subscription
137 * @param handle {string} the subscription handle
139 detach: function(handle) {
147 _unload: function(e, me) {
152 //////////////////////////////////////////////////////////////////////////
155 * Wrapper for a displaced method with aop enabled
158 * @param obj The object to operate on
159 * @param sFn The name of the method to displace
161 Y.Do.Method = function(obj, sFn) {
163 this.methodName = sFn;
164 this.method = obj[sFn];
170 * Register a aop subscriber
172 * @param sid {string} the subscriber id
173 * @param fn {Function} the function to execute
174 * @param when {string} when to execute the function
176 Y.Do.Method.prototype.register = function (sid, fn, when) {
178 this.after[sid] = fn;
180 this.before[sid] = fn;
185 * Unregister a aop subscriber
187 * @param sid {string} the subscriber id
188 * @param fn {Function} the function to execute
189 * @param when {string} when to execute the function
191 Y.Do.Method.prototype._delete = function (sid) {
192 delete this.before[sid];
193 delete this.after[sid];
197 * Execute the wrapped method
200 Y.Do.Method.prototype.exec = function () {
202 var args = Y.Array(arguments, 0, true),
210 if (bf.hasOwnProperty(i)) {
211 ret = bf[i].apply(this.obj, args);
213 switch (ret.constructor) {
230 ret = this.method.apply(this.obj, args);
233 // execute after methods.
235 if (af.hasOwnProperty(i)) {
236 newRet = af[i].apply(this.obj, args);
237 // Stop processing if a Halt object is returned
238 if (newRet && newRet.constructor == Y.Do.Halt) {
239 return newRet.retVal;
240 // Check for a new return value
241 } else if (newRet && newRet.constructor == Y.Do.AlterReturn) {
242 ret = newRet.newRetVal;
250 //////////////////////////////////////////////////////////////////////////
254 * Return an AlterArgs object when you want to change the arguments that
255 * were passed into the function. An example would be a service that scrubs
256 * out illegal characters prior to executing the core business logic.
257 * @class Do.AlterArgs
259 Y.Do.AlterArgs = function(msg, newArgs) {
261 this.newArgs = newArgs;
265 * Return an AlterReturn object when you want to change the result returned
266 * from the core method to the caller
267 * @class Do.AlterReturn
269 Y.Do.AlterReturn = function(msg, newRetVal) {
271 this.newRetVal = newRetVal;
275 * Return a Halt object when you want to terminate the execution
276 * of all subsequent subscribers as well as the wrapped method
277 * if it has not exectued yet.
280 Y.Do.Halt = function(msg, retVal) {
282 this.retVal = retVal;
286 * Return a Prevent object when you want to prevent the wrapped function
287 * from executing, but want the remaining listeners to execute
290 Y.Do.Prevent = function(msg) {
295 * Return an Error object when you want to terminate the execution
296 * of all subsequent method calls.
298 * @deprecated use Y.Do.Halt or Y.Do.Prevent
300 Y.Do.Error = Y.Do.Halt;
302 //////////////////////////////////////////////////////////////////////////
304 // Y["Event"] && Y.Event.addListener(window, "unload", Y.Do._unload, Y.Do);
309 * Custom event engine, DOM event listener abstraction layer, synthetic DOM
311 * @module event-custom
312 * @submodule event-custom-base
316 * Return value from all subscribe operations
319 * @param evt {CustomEvent} the custom event
320 * @param sub {Subscriber} the subscriber
323 // var onsubscribeType = "_event:onsub",
349 Y.EventHandle = function(evt, sub) {
358 * The subscriber object
364 Y.EventHandle.prototype = {
367 * Detaches this subscriber
371 var evt = this.evt, i;
373 if (Y.Lang.isArray(evt)) {
374 for (i=0; i<evt.length; i++) {
378 evt._delete(this.sub);
385 * The CustomEvent class lets you define events for your application
386 * that can be subscribed to by one or more independent component.
388 * @param {String} type The type of event, which is passed to the callback
389 * when the event fires
390 * @param o configuration object
394 Y.CustomEvent = function(type, o) {
396 // if (arguments.length > 2) {
397 // this.log('CustomEvent context and silent are now in the config', 'warn', 'Event');
402 this.id = Y.stamp(this);
405 * The type of event, returned to subscribers when the event fires
412 * The context the the event will fire from by default. Defaults to the YUI
419 this.logSystem = (type == YUI_LOG);
422 * If 0, this event does not broadcast. If 1, the YUI instance is notified
423 * every time this event fires. If 2, the YUI instance and the YUI global
424 * (if event is enabled on the global) are notified every time this event
426 * @property broadcast
429 // this.broadcast = 0;
432 * By default all custom events are logged in the debug build, set silent
433 * to true to disable debug outpu for this event.
437 this.silent = this.logSystem;
440 * Specifies whether this event should be queued when the host is actively
441 * processing an event. This will effect exectution order of the callbacks
442 * for the various events.
447 // this.queuable = false;
450 * The subscribers to this event
451 * @property subscribers
454 this.subscribers = {};
457 * 'After' subscribers
464 * This event has fired if true
470 // this.fired = false;
473 * An array containing the arguments the custom event
474 * was last fired with.
475 * @property firedWith
481 * This event should only fire one time if true, and if
482 * it has fired, any new subscribers should be notified
489 // this.fireOnce = false;
492 * Flag for stopPropagation that is modified during fire()
493 * 1 means to stop propagation to bubble targets. 2 means
494 * to also stop additional subscribers on this target.
501 * Flag for preventDefault that is modified during fire().
502 * if it is not 0, the default behavior for this event
503 * @property prevented
506 // this.prevented = 0;
509 * Specifies the host for this custom event. This is used
510 * to enable event bubbling
517 * The default function to execute after event listeners
518 * have fire, but only if the default action was not
520 * @property defaultFn
523 // this.defaultFn = null;
526 * The function to execute if a subscriber calls
527 * stopPropagation or stopImmediatePropagation
528 * @property stoppedFn
531 // this.stoppedFn = null;
534 * The function to execute if a subscriber calls
536 * @property preventedFn
539 // this.preventedFn = null;
542 * Specifies whether or not this event's default function
543 * can be cancelled by a subscriber by executing preventDefault()
544 * on the event facade
545 * @property preventable
549 this.preventable = true;
552 * Specifies whether or not a subscriber can stop the event propagation
553 * via stopPropagation(), stopImmediatePropagation(), or halt()
561 * Supports multiple options for listener signatures in order to
563 * @property signature
567 this.signature = YUI3_SIGNATURE;
569 // this.hasSubscribers = false;
571 // this.hasAfters = false;
574 * If set to true, the custom event will deliver an EventFacade object
575 * that is similar to a DOM event object.
576 * @property emitFacade
580 // this.emitFacade = false;
582 this.applyConfig(o, true);
584 // this.log("Creating " + this.type);
588 Y.CustomEvent.prototype = {
591 * Apply configuration properties. Only applies the CONFIG whitelist
592 * @method applyConfig
593 * @param o hash of properties to apply
594 * @param force {boolean} if true, properties that exist on the event
595 * will be overwritten.
597 applyConfig: function(o, force) {
599 Y.mix(this, o, force, CONFIGS);
603 _on: function(fn, context, args, when) {
606 this.log("Invalid callback for CE: " + this.type);
609 var s = new Y.Subscriber(fn, context, args, when);
611 if (this.fireOnce && this.fired) {
612 Y.later(0, this, Y.bind(this._notify, this, s, this.firedWith));
616 this.afters[s.id] = s;
617 this.hasAfters = true;
619 this.subscribers[s.id] = s;
620 this.hasSubscribers = true;
623 return new Y.EventHandle(this, s);
628 * Listen for this event
630 * @param {Function} fn The function to execute
631 * @return {EventHandle|EventTarget} unsubscribe handle or a
632 * chainable event target depending on the 'chain' config.
635 subscribe: function(fn, context) {
636 var a = (arguments.length > 2) ? Y.Array(arguments, 2, true): null;
637 return this._on(fn, context, a, true);
641 * Listen for this event
643 * @param {Function} fn The function to execute
644 * @return {EventHandle|EventTarget} unsubscribe handle or a
645 * chainable event target depending on the 'chain' config.
647 on: function(fn, context) {
648 var a = (arguments.length > 2) ? Y.Array(arguments, 2, true): null;
649 return this._on(fn, context, a, true);
653 * Listen for this event after the normal subscribers have been notified and
654 * the default behavior has been applied. If a normal subscriber prevents the
655 * default behavior, it also prevents after listeners from firing.
657 * @param {Function} fn The function to execute
658 * @return {EventHandle|EventTarget} unsubscribe handle or a
659 * chainable event target depending on the 'chain' config.
661 after: function(fn, context) {
662 var a = (arguments.length > 2) ? Y.Array(arguments, 2, true): null;
663 return this._on(fn, context, a, AFTER);
669 * @param {Function} fn The subscribed function to remove, if not supplied
670 * all will be removed
671 * @param {Object} context The context object passed to subscribe.
672 * @return {int|EventTarget} returns a chainable event target
673 * or the number of subscribers unsubscribed.
675 detach: function(fn, context) {
676 // unsubscribe handle
677 if (fn && fn.detach) {
681 var found = 0, subs = this.subscribers, i, s;
684 if (subs.hasOwnProperty(i)) {
686 if (s && (!fn || fn === s.fn)) {
698 * @method unsubscribe
699 * @param {Function} fn The subscribed function to remove, if not supplied
700 * all will be removed
701 * @param {Object} context The context object passed to subscribe.
702 * @return {boolean|EventTarget} returns a chainable event target
703 * or a boolean for legacy detach support.
704 * @deprecated use detach
706 unsubscribe: function() {
707 return this.detach.apply(this, arguments);
712 * Notify a single subscriber
714 * @param s {Subscriber} the subscriber
715 * @param args {Array} the arguments array to apply to the listener
718 _notify: function(s, args, ef) {
720 this.log(this.type + "->" + "sub: " + s.id);
724 ret = s.notify(args, this);
726 if (false === ret || this.stopped > 1) {
727 this.log(this.type + " cancelled by subscriber");
735 * Logger abstraction to centralize the application of the silent flag
737 * @param msg {string} message to log
738 * @param cat {string} log category
740 log: function(msg, cat) {
746 * Notifies the subscribers. The callback functions will be executed
747 * from the context specified when the event was created, and with the
748 * following parameters:
750 * <li>The type of event</li>
751 * <li>All of the arguments fire() was executed with as an array</li>
752 * <li>The custom object (if any) that was passed into the subscribe()
756 * @param {Object*} arguments an arbitrary set of parameters to pass to
758 * @return {boolean} false if one of the subscribers returned false,
763 if (this.fireOnce && this.fired) {
764 this.log('fireOnce event: ' + this.type + ' already fired');
768 var args = Y.Array(arguments, 0, true);
771 this.firedWith = args;
773 if (this.emitFacade) {
774 return this.fireComplex(args);
776 return this.fireSimple(args);
781 fireSimple: function(args) {
782 if (this.hasSubscribers || this.hasAfters) {
783 this._procSubs(Y.merge(this.subscribers, this.afters), args);
785 this._broadcast(args);
786 return this.stopped ? false : true;
789 // Requires the event-custom-complex module for full funcitonality.
790 fireComplex: function(args) {
791 args[0] = args[0] || {};
792 return this.fireSimple(args);
795 _procSubs: function(subs, args, ef) {
798 if (subs.hasOwnProperty(i)) {
801 if (false === this._notify(s, args, ef)) {
804 if (this.stopped == 2) {
814 _broadcast: function(args) {
815 if (!this.stopped && this.broadcast) {
817 var a = Y.Array(args);
818 a.unshift(this.type);
820 if (this.host !== Y) {
824 if (this.broadcast == 2) {
825 Y.Global.fire.apply(Y.Global, a);
831 * Removes all listeners
832 * @method unsubscribeAll
833 * @return {int} The number of listeners unsubscribed
834 * @deprecated use detachAll
836 unsubscribeAll: function() {
837 return this.detachAll.apply(this, arguments);
841 * Removes all listeners
843 * @return {int} The number of listeners unsubscribed
845 detachAll: function() {
846 return this.detach();
851 * @param subscriber object
854 _delete: function(s) {
858 delete this.subscribers[s.id];
859 delete this.afters[s.id];
864 /////////////////////////////////////////////////////////////////////
867 * Stores the subscriber information to be used when the event fires.
868 * @param {Function} fn The wrapped function to execute
869 * @param {Object} context The value of the keyword 'this' in the listener
870 * @param {Array} args* 0..n additional arguments to supply the listener
875 Y.Subscriber = function(fn, context, args) {
878 * The callback that will be execute when the event fires
879 * This is wrapped by Y.rbind if obj was supplied.
886 * Optional 'this' keyword for the listener
890 this.context = context;
893 * Unique subscriber id
897 this.id = Y.stamp(this);
900 * Additional arguments to propagate to the subscriber
907 * Custom events for a given fire transaction.
909 * @type {EventTarget}
915 Y.Subscriber.prototype = {
917 _notify: function(c, args, ce) {
918 var a = this.args, ret;
919 switch (ce.signature) {
921 ret = this.fn.call(c, ce.type, args, c);
924 ret = this.fn.call(c, args[0] || null, c);
929 a = (a) ? args.concat(a) : args;
930 ret = this.fn.apply(c, a);
932 ret = this.fn.call(c);
940 * Executes the subscriber.
942 * @param args {Array} Arguments array for the subscriber
943 * @param ce {CustomEvent} The custom event that sent the notification
945 notify: function(args, ce) {
946 var c = this.context,
950 c = (ce.contextFn) ? ce.contextFn() : ce.context;
953 // only catch errors if we will not re-throw them.
954 if (Y.config.throwFail) {
955 ret = this._notify(c, args, ce);
958 ret = this._notify(c, args, ce);
960 Y.error(this + ' failed: ' + e.message, e);
968 * Returns true if the fn and obj match this objects properties.
969 * Used by the unsubscribe method to match the right subscriber.
972 * @param {Function} fn the function to execute
973 * @param {Object} context optional 'this' keyword for the listener
974 * @return {boolean} true if the supplied arguments match this
975 * subscriber's signature.
977 contains: function(fn, context) {
979 return ((this.fn == fn) && this.context == context);
981 return (this.fn == fn);
988 * Custom event engine, DOM event listener abstraction layer, synthetic DOM
990 * @module event-custom
991 * @submodule event-custom-base
996 * EventTarget provides the implementation for any object to
997 * publish, subscribe and fire to custom events, and also
998 * alows other EventTargets to target the object with events
999 * sourced from the other object.
1000 * EventTarget is designed to be used with Y.augment to wrap
1001 * EventCustom in an interface that allows events to be listened to
1002 * and fired by name. This makes it possible for implementing code to
1003 * subscribe to an event that either has not been created yet, or will
1004 * not be created at all.
1005 * @class EventTarget
1006 * @param opts a configuration object
1007 * @config emitFacade {boolean} if true, all events will emit event
1008 * facade payloads by default (default false)
1009 * @config prefix {string} the prefix to apply to non-prefixed event names
1010 * @config chain {boolean} if true, on/after/detach return the host to allow
1011 * chaining, otherwise they return an EventHandle (default false)
1015 PREFIX_DELIMITER = ':',
1016 CATEGORY_DELIMITER = '|',
1017 AFTER_PREFIX = '~AFTER~',
1020 * If the instance has a prefix attribute and the
1021 * event type is not prefixed, the instance prefix is
1022 * applied to the supplied type.
1026 _getType = Y.cached(function(type, pre) {
1028 if (!pre || !L.isString(type) || type.indexOf(PREFIX_DELIMITER) > -1) {
1032 return pre + PREFIX_DELIMITER + type;
1036 * Returns an array with the detach key (if provided),
1037 * and the prefixed event name from _getType
1038 * Y.on('detachcategory, menu:click', fn)
1039 * @method _parseType
1042 _parseType = Y.cached(function(type, pre) {
1044 var t = type, detachcategory, after, i;
1046 if (!L.isString(t)) {
1050 i = t.indexOf(AFTER_PREFIX);
1054 t = t.substr(AFTER_PREFIX.length);
1057 i = t.indexOf(CATEGORY_DELIMITER);
1060 detachcategory = t.substr(0, (i));
1067 // detach category, full type with instance prefix, is this an after listener, short type
1068 return [detachcategory, (pre) ? _getType(t, pre) : t, after, t];
1071 ET = function(opts) {
1074 var o = (L.isObject(opts)) ? opts : {};
1076 this._yuievt = this._yuievt || {
1086 chain: ('chain' in o) ? o.chain : Y.config.chain,
1089 context: o.context || this,
1091 emitFacade: o.emitFacade,
1092 fireOnce: o.fireOnce,
1093 queuable: o.queuable,
1094 broadcast: o.broadcast,
1095 bubbles: ('bubbles' in o) ? o.bubbles : true
1105 * Subscribe to a custom event hosted by this object
1107 * @param type {string} The type of the event
1108 * @param fn {Function} The callback
1109 * @return the event target or a detach handle per 'chain' config
1111 on: function(type, fn, context, x) {
1113 var parts = _parseType(type, this._yuievt.config.prefix), f, c, args, ret, ce,
1114 detachcategory, handle, store = Y.Env.evt.handles, after, adapt, shorttype,
1115 Node = Y.Node, n, domevent;
1117 if (L.isObject(type)) {
1119 if (L.isFunction(type)) {
1120 return Y.Do.before.apply(Y.Do, arguments);
1125 args = Y.Array(arguments, 0, true);
1127 after = type._after;
1130 Y.each(type, function(v, k) {
1133 f = v.fn || ((Y.Lang.isFunction(v)) ? v : f);
1137 args[0] = (after) ? AFTER_PREFIX + k : k;
1141 ret[k] = this.on.apply(this, args);
1145 return (this._yuievt.chain) ? this : new Y.EventHandle(ret);
1149 detachcategory = parts[0];
1151 shorttype = parts[3];
1153 // extra redirection so we catch adaptor events too. take a look at this.
1154 if (Node && (this instanceof Node) && (shorttype in Node.DOM_EVENTS)) {
1155 args = Y.Array(arguments, 0, true);
1156 args.splice(2, 0, Node.getDOMNode(this));
1157 return Y.on.apply(Y, args);
1162 if (this instanceof YUI) {
1164 adapt = Y.Env.evt.plugins[type];
1165 args = Y.Array(arguments, 0, true);
1166 args[0] = shorttype;
1171 if (n instanceof Y.NodeList) {
1172 n = Y.NodeList.getDOMNodes(n);
1173 } else if (n instanceof Node) {
1174 n = Node.getDOMNode(n);
1177 domevent = (shorttype in Node.DOM_EVENTS);
1179 // Captures both DOM events and event plugins.
1185 // check for the existance of an event adaptor
1187 handle = adapt.on.apply(Y, args);
1188 } else if ((!type) || domevent) {
1189 handle = Y.Event._attach(args);
1195 ce = this._yuievt.events[type] || this.publish(type);
1196 handle = ce._on(fn, context, (arguments.length > 3) ? Y.Array(arguments, 3, true) : null, (after) ? 'after' : true);
1199 if (detachcategory) {
1200 store[detachcategory] = store[detachcategory] || {};
1201 store[detachcategory][type] = store[detachcategory][type] || [];
1202 store[detachcategory][type].push(handle);
1205 return (this._yuievt.chain) ? this : handle;
1210 * subscribe to an event
1212 * @deprecated use on
1214 subscribe: function() {
1215 return this.on.apply(this, arguments);
1219 * Detach one or more listeners the from the specified event
1221 * @param type {string|Object} Either the handle to the subscriber or the
1222 * type of event. If the type
1223 * is not specified, it will attempt to remove
1224 * the listener from all hosted events.
1225 * @param fn {Function} The subscribed function to unsubscribe, if not
1226 * supplied, all subscribers will be removed.
1227 * @param context {Object} The custom object passed to subscribe. This is
1228 * optional, but if supplied will be used to
1229 * disambiguate multiple listeners that are the same
1230 * (e.g., you subscribe many object using a function
1231 * that lives on the prototype)
1232 * @return {EventTarget} the host
1234 detach: function(type, fn, context) {
1235 var evts = this._yuievt.events, i, ret,
1236 Node = Y.Node, isNode = (this instanceof Node);
1238 // detachAll disabled on the Y instance.
1239 if (!type && (this !== Y)) {
1241 if (evts.hasOwnProperty(i)) {
1242 ret = evts[i].detach(fn, context);
1247 Y.Event.purgeElement(Node.getDOMNode(this));
1253 var parts = _parseType(type, this._yuievt.config.prefix),
1254 detachcategory = L.isArray(parts) ? parts[0] : null,
1255 shorttype = (parts) ? parts[3] : null,
1256 handle, adapt, store = Y.Env.evt.handles, cat, args,
1259 keyDetacher = function(lcat, ltype) {
1260 var handles = lcat[ltype];
1262 while (handles.length) {
1263 handle = handles.pop();
1269 if (detachcategory) {
1271 cat = store[detachcategory];
1276 keyDetacher(cat, type);
1279 if (cat.hasOwnProperty(i)) {
1280 keyDetacher(cat, i);
1285 return (this._yuievt.chain) ? this : true;
1288 // If this is an event handle, use it to detach
1289 } else if (L.isObject(type) && type.detach) {
1290 ret = type.detach();
1291 return (this._yuievt.chain) ? this : ret;
1292 // extra redirection so we catch adaptor events too. take a look at this.
1293 } else if (isNode && ((!shorttype) || (shorttype in Node.DOM_EVENTS))) {
1294 args = Y.Array(arguments, 0, true);
1295 args[2] = Node.getDOMNode(this);
1296 return Y.detach.apply(Y, args);
1299 adapt = Y.Env.evt.plugins[shorttype];
1301 // The YUI instance handles DOM events and adaptors
1302 if (this instanceof YUI) {
1303 args = Y.Array(arguments, 0, true);
1304 // use the adaptor specific detach code if
1305 if (adapt && adapt.detach) {
1306 return adapt.detach.apply(Y, args);
1308 } else if (!type || (!adapt && Node && (type in Node.DOM_EVENTS))) {
1310 return Y.Event.detach.apply(Y.Event, args);
1316 ret = ce.detach(fn, context);
1319 return (this._yuievt.chain) ? this : ret;
1324 * @method unsubscribe
1325 * @deprecated use detach
1327 unsubscribe: function() {
1328 return this.detach.apply(this, arguments);
1332 * Removes all listeners from the specified event. If the event type
1333 * is not specified, all listeners from all hosted custom events will
1336 * @param type {string} The type, or name of the event
1338 detachAll: function(type) {
1339 return this.detach(type);
1343 * Removes all listeners from the specified event. If the event type
1344 * is not specified, all listeners from all hosted custom events will
1346 * @method unsubscribeAll
1347 * @param type {string} The type, or name of the event
1348 * @deprecated use detachAll
1350 unsubscribeAll: function() {
1351 return this.detachAll.apply(this, arguments);
1355 * Creates a new custom event of the specified type. If a custom event
1356 * by that name already exists, it will not be re-created. In either
1357 * case the custom event is returned.
1361 * @param type {string} the type, or name of the event
1362 * @param opts {object} optional config params. Valid properties are:
1366 * 'broadcast': whether or not the YUI instance and YUI global are notified when the event is fired (false)
1369 * 'bubbles': whether or not this event bubbles (true)
1372 * 'context': the default execution context for the listeners (this)
1375 * 'defaultFn': the default function to execute when this event fires if preventDefault was not called
1378 * 'emitFacade': whether or not this event emits a facade (false)
1381 * 'prefix': the prefix for this targets events, e.g., 'menu' in 'menu:click'
1384 * 'fireOnce': if an event is configured to fire once, new subscribers after
1385 * the fire will be notified immediately.
1388 * 'preventable': whether or not preventDefault() has an effect (true)
1391 * 'preventedFn': a function that is executed when preventDefault is called
1394 * 'queuable': whether or not this event can be queued during bubbling (false)
1397 * 'silent': if silent is true, debug messages are not provided for this event.
1400 * 'stoppedFn': a function that is executed when stopPropagation is called
1403 * 'type': the event type (valid option if not provided as the first parameter to publish)
1407 * @return {Event.Custom} the custom event
1410 publish: function(type, opts) {
1411 var events, ce, ret, pre = this._yuievt.config.prefix;
1413 type = (pre) ? _getType(type, pre) : type;
1416 if (L.isObject(type)) {
1418 Y.each(type, function(v, k) {
1419 ret[k] = this.publish(k, v || opts);
1425 events = this._yuievt.events;
1429 // ce.log("publish applying new config to published event: '"+type+"' exists", 'info', 'event');
1431 ce.applyConfig(opts, true);
1435 ce = new Y.CustomEvent(type, (opts) ? Y.mix(opts, this._yuievt.defaults) : this._yuievt.defaults);
1439 // make sure we turn the broadcast flag off if this
1440 // event was published as a result of bubbling
1441 // if (opts instanceof Y.CustomEvent) {
1442 // events[type].broadcast = false;
1445 return events[type];
1449 * Registers another EventTarget as a bubble target. Bubble order
1450 * is determined by the order registered. Multiple targets can
1453 * @param o {EventTarget} the target to add
1455 addTarget: function(o) {
1456 this._yuievt.targets[Y.stamp(o)] = o;
1457 this._yuievt.hasTargets = true;
1461 * Removes a bubble target
1462 * @method removeTarget
1463 * @param o {EventTarget} the target to remove
1465 removeTarget: function(o) {
1466 delete this._yuievt.targets[Y.stamp(o)];
1470 * Fire a custom event by name. The callback functions will be executed
1471 * from the context specified when the event was created, and with the
1472 * following parameters.
1474 * If the custom event object hasn't been created, then the event hasn't
1475 * been published and it has no subscribers. For performance sake, we
1476 * immediate exit in this case. This means the event won't bubble, so
1477 * if the intention is that a bubble target be notified, the event must
1478 * be published on this object first.
1480 * The first argument is the event type, and any additional arguments are
1481 * passed to the listeners as parameters. If the first of these is an
1482 * object literal, and the event is configured to emit an event facade,
1483 * that object is mixed into the event facade and the facade is provided
1484 * in place of the original object.
1487 * @param type {String|Object} The type of the event, or an object that contains
1488 * a 'type' property.
1489 * @param arguments {Object*} an arbitrary set of parameters to pass to
1490 * the handler. If the first of these is an object literal and the event is
1491 * configured to emit an event facade, the event facade will replace that
1492 * parameter after the properties the object literal contains are copied to
1494 * @return {Event.Target} the event host
1497 fire: function(type) {
1499 var typeIncluded = L.isString(type),
1500 t = (typeIncluded) ? type : (type && type.type),
1501 ce, a, ret, pre=this._yuievt.config.prefix;
1503 t = (pre) ? _getType(t, pre) : t;
1504 ce = this.getEvent(t, true);
1506 // this event has not been published or subscribed to
1509 if (this._yuievt.hasTargets) {
1510 a = (typeIncluded) ? arguments : Y.Array(arguments, 0, true).unshift(t);
1511 return this.bubble(null, a, this);
1514 // otherwise there is nothing to be done
1519 a = Y.Array(arguments, (typeIncluded) ? 1 : 0, true);
1520 ret = ce.fire.apply(ce, a);
1522 // clear target for next fire()
1526 return (this._yuievt.chain) ? this : ret;
1530 * Returns the custom event of the provided type has been created, a
1531 * falsy value otherwise
1533 * @param type {string} the type, or name of the event
1534 * @param prefixed {string} if true, the type is prefixed already
1535 * @return {Event.Custom} the custom event or null
1537 getEvent: function(type, prefixed) {
1540 pre = this._yuievt.config.prefix;
1541 type = (pre) ? _getType(type, pre) : type;
1543 e = this._yuievt.events;
1544 return (e && type in e) ? e[type] : null;
1548 * Subscribe to a custom event hosted by this object. The
1549 * supplied callback will execute after any listeners add
1550 * via the subscribe method, and after the default function,
1551 * if configured for the event, has executed.
1553 * @param type {string} The type of the event
1554 * @param fn {Function} The callback
1555 * @return the event target or a detach handle per 'chain' config
1557 after: function(type, fn) {
1559 var a = Y.Array(arguments, 0, true);
1561 switch (L.type(type)) {
1563 return Y.Do.after.apply(Y.Do, arguments);
1568 a[0] = AFTER_PREFIX + type;
1571 return this.on.apply(this, a);
1576 * Executes the callback before a DOM event, custom event
1577 * or method. If the first argument is a function, it
1578 * is assumed the target is a method. For DOM and custom
1579 * events, this is an alias for Y.on.
1581 * For DOM and custom events:
1582 * type, callback, context, 0-n arguments
1585 * callback, object (method host), methodName, context, 0-n arguments
1588 * @return detach handle
1589 * @deprecated use the on method
1591 before: function() {
1592 return this.on.apply(this, arguments);
1599 // make Y an event target
1600 Y.mix(Y, ET.prototype, false, false, {
1606 YUI.Env.globalEvents = YUI.Env.globalEvents || new ET();
1609 * Hosts YUI page level events. This is where events bubble to
1610 * when the broadcast config is set to 2. This property is
1611 * only available if the custom event module is loaded.
1616 Y.Global = YUI.Env.globalEvents;
1618 // @TODO implement a global namespace function on Y.Global?
1624 * <code>YUI</code>'s <code>on</code> method is a unified interface for subscribing to
1625 * most events exposed by YUI. This includes custom events, DOM events, and
1626 * function events. <code>detach</code> is also provided to remove listeners
1627 * serviced by this function.
1629 * The signature that <code>on</code> accepts varies depending on the type
1630 * of event being consumed. Refer to the specific methods that will
1631 * service a specific request for additional information about subscribing
1632 * to that type of event.
1635 * <li>Custom events. These events are defined by various
1636 * modules in the library. This type of event is delegated to
1637 * <code>EventTarget</code>'s <code>on</code> method.
1639 * <li>The type of the event</li>
1640 * <li>The callback to execute</li>
1641 * <li>An optional context object</li>
1642 * <li>0..n additional arguments to supply the callback.</li>
1645 * <code>Y.on('domready', function() { // start work });</code>
1647 * <li>DOM events. These are moments reported by the browser related
1648 * to browser functionality and user interaction.
1649 * This type of event is delegated to <code>Event</code>'s
1650 * <code>attach</code> method.
1652 * <li>The type of the event</li>
1653 * <li>The callback to execute</li>
1654 * <li>The specification for the Node(s) to attach the listener
1655 * to. This can be a selector, collections, or Node/Element
1657 * <li>An optional context object</li>
1658 * <li>0..n additional arguments to supply the callback.</li>
1661 * <code>Y.on('click', function(e) { // something was clicked }, '#someelement');</code>
1663 * <li>Function events. These events can be used to react before or after a
1664 * function is executed. This type of event is delegated to <code>Event.Do</code>'s
1665 * <code>before</code> method.
1667 * <li>The callback to execute</li>
1668 * <li>The object that has the function that will be listened for.</li>
1669 * <li>The name of the function to listen for.</li>
1670 * <li>An optional context object</li>
1671 * <li>0..n additional arguments to supply the callback.</li>
1673 * Example <code>Y.on(function(arg1, arg2, etc) { // obj.methodname was executed }, obj 'methodname');</code>
1677 * <code>on</code> corresponds to the moment before any default behavior of
1678 * the event. <code>after</code> works the same way, but these listeners
1679 * execute after the event's default behavior. <code>before</code> is an
1680 * alias for <code>on</code>.
1683 * @param type** event type (this parameter does not apply for function events)
1684 * @param fn the callback
1685 * @param target** a descriptor for the target (applies to custom events only).
1686 * For function events, this is the object that contains the function to
1688 * @param extra** 0..n Extra information a particular event may need. These
1689 * will be documented with the event. In the case of function events, this
1690 * is the name of the function to execute on the host. In the case of
1691 * delegate listeners, this is the event delegation specification.
1692 * @param context optionally change the value of 'this' in the callback
1693 * @param args* 0..n additional arguments to pass to the callback.
1694 * @return the event target or a detach handle per 'chain' config
1699 * after() is a unified interface for subscribing to
1700 * most events exposed by YUI. This includes custom events,
1701 * DOM events, and AOP events. This works the same way as
1702 * the on() function, only it operates after any default
1703 * behavior for the event has executed. @see <code>on</code> for more
1706 * @param type event type (this parameter does not apply for function events)
1707 * @param fn the callback
1708 * @param target a descriptor for the target (applies to custom events only).
1709 * For function events, this is the object that contains the function to
1711 * @param extra 0..n Extra information a particular event may need. These
1712 * will be documented with the event. In the case of function events, this
1713 * is the name of the function to execute on the host. In the case of
1714 * delegate listeners, this is the event delegation specification.
1715 * @param context optionally change the value of 'this' in the callback
1716 * @param args* 0..n additional arguments to pass to the callback.
1717 * @return the event target or a detach handle per 'chain' config
1722 }, '3.0.0' ,{requires:['oop']});