src/cm/media/js/lib/yui/yui3.0.0/build/event-custom/event-custom-base-debug.js
changeset 0 40c8f766c9b8
equal deleted inserted replaced
-1:000000000000 0:40c8f766c9b8
       
     1 /*
       
     2 Copyright (c) 2009, Yahoo! Inc. All rights reserved.
       
     3 Code licensed under the BSD License:
       
     4 http://developer.yahoo.net/yui/license.txt
       
     5 version: 3.0.0
       
     6 build: 1549
       
     7 */
       
     8 YUI.add('event-custom-base', function(Y) {
       
     9 
       
    10 /**
       
    11  * Custom event engine, DOM event listener abstraction layer, synthetic DOM
       
    12  * events.
       
    13  * @module event-custom
       
    14  */
       
    15 
       
    16 Y.Env.evt = {
       
    17     handles: {},
       
    18     plugins: {}
       
    19 };
       
    20 
       
    21 
       
    22 /**
       
    23  * Custom event engine, DOM event listener abstraction layer, synthetic DOM 
       
    24  * events.
       
    25  * @module event-custom
       
    26  * @submodule event-custom-base
       
    27  */
       
    28 (function() {
       
    29 
       
    30 /**
       
    31  * Allows for the insertion of methods that are executed before or after
       
    32  * a specified method
       
    33  * @class Do
       
    34  * @static
       
    35  */
       
    36 
       
    37 var BEFORE = 0,
       
    38     AFTER = 1;
       
    39 
       
    40 Y.Do = {
       
    41 
       
    42     /**
       
    43      * Cache of objects touched by the utility
       
    44      * @property objs
       
    45      * @static
       
    46      */
       
    47     objs: {},
       
    48 
       
    49     /**
       
    50      * Execute the supplied method before the specified function
       
    51      * @method before
       
    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
       
    57      * @static
       
    58      */
       
    59     before: function(fn, obj, sFn, c) {
       
    60         // Y.log('Do before: ' + sFn, 'info', 'event');
       
    61         var f = fn, a;
       
    62         if (c) {
       
    63             a = [fn, c].concat(Y.Array(arguments, 4, true));
       
    64             f = Y.rbind.apply(Y, a);
       
    65         }
       
    66 
       
    67         return this._inject(BEFORE, f, obj, sFn);
       
    68     },
       
    69 
       
    70     /**
       
    71      * Execute the supplied method after the specified function
       
    72      * @method after
       
    73      * @param fn {Function} the function to execute
       
    74      * @param obj the object hosting the method to displace
       
    75      * @param sFn {string} the name of the method to displace
       
    76      * @param c The execution context for fn
       
    77      * @return {string} handle for the subscription
       
    78      * @static
       
    79      */
       
    80     after: function(fn, obj, sFn, c) {
       
    81         var f = fn, a;
       
    82         if (c) {
       
    83             a = [fn, c].concat(Y.Array(arguments, 4, true));
       
    84             f = Y.rbind.apply(Y, a);
       
    85         }
       
    86 
       
    87         return this._inject(AFTER, f, obj, sFn);
       
    88     },
       
    89 
       
    90     /**
       
    91      * Execute the supplied method after the specified function
       
    92      * @method _inject
       
    93      * @param when {string} before or after
       
    94      * @param fn {Function} the function to execute
       
    95      * @param obj the object hosting the method to displace
       
    96      * @param sFn {string} the name of the method to displace
       
    97      * @param c The execution context for fn
       
    98      * @return {string} handle for the subscription
       
    99      * @private
       
   100      * @static
       
   101      */
       
   102     _inject: function(when, fn, obj, sFn) {
       
   103 
       
   104         // object id
       
   105         var id = Y.stamp(obj), o, sid;
       
   106 
       
   107         if (! this.objs[id]) {
       
   108             // create a map entry for the obj if it doesn't exist
       
   109             this.objs[id] = {};
       
   110         }
       
   111 
       
   112         o = this.objs[id];
       
   113 
       
   114         if (! o[sFn]) {
       
   115             // create a map entry for the method if it doesn't exist
       
   116             o[sFn] = new Y.Do.Method(obj, sFn);
       
   117 
       
   118             // re-route the method to our wrapper
       
   119             obj[sFn] = 
       
   120                 function() {
       
   121                     return o[sFn].exec.apply(o[sFn], arguments);
       
   122                 };
       
   123         }
       
   124 
       
   125         // subscriber id
       
   126         sid = id + Y.stamp(fn) + sFn;
       
   127 
       
   128         // register the callback
       
   129         o[sFn].register(sid, fn, when);
       
   130 
       
   131         return new Y.EventHandle(o[sFn], sid);
       
   132 
       
   133     },
       
   134 
       
   135     /**
       
   136      * Detach a before or after subscription
       
   137      * @method detach
       
   138      * @param handle {string} the subscription handle
       
   139      */
       
   140     detach: function(handle) {
       
   141 
       
   142         if (handle.detach) {
       
   143             handle.detach();
       
   144         }
       
   145 
       
   146     },
       
   147 
       
   148     _unload: function(e, me) {
       
   149 
       
   150     }
       
   151 };
       
   152 
       
   153 //////////////////////////////////////////////////////////////////////////
       
   154 
       
   155 /**
       
   156  * Wrapper for a displaced method with aop enabled
       
   157  * @class Do.Method
       
   158  * @constructor
       
   159  * @param obj The object to operate on
       
   160  * @param sFn The name of the method to displace
       
   161  */
       
   162 Y.Do.Method = function(obj, sFn) {
       
   163     this.obj = obj;
       
   164     this.methodName = sFn;
       
   165     this.method = obj[sFn];
       
   166     this.before = {};
       
   167     this.after = {};
       
   168 };
       
   169 
       
   170 /**
       
   171  * Register a aop subscriber
       
   172  * @method register
       
   173  * @param sid {string} the subscriber id
       
   174  * @param fn {Function} the function to execute
       
   175  * @param when {string} when to execute the function
       
   176  */
       
   177 Y.Do.Method.prototype.register = function (sid, fn, when) {
       
   178     if (when) {
       
   179         this.after[sid] = fn;
       
   180     } else {
       
   181         this.before[sid] = fn;
       
   182     }
       
   183 };
       
   184 
       
   185 /**
       
   186  * Unregister a aop subscriber
       
   187  * @method delete
       
   188  * @param sid {string} the subscriber id
       
   189  * @param fn {Function} the function to execute
       
   190  * @param when {string} when to execute the function
       
   191  */
       
   192 Y.Do.Method.prototype._delete = function (sid) {
       
   193     // Y.log('Y.Do._delete: ' + sid, 'info', 'Event');
       
   194     delete this.before[sid];
       
   195     delete this.after[sid];
       
   196 };
       
   197 
       
   198 /**
       
   199  * Execute the wrapped method
       
   200  * @method exec
       
   201  */
       
   202 Y.Do.Method.prototype.exec = function () {
       
   203 
       
   204     var args = Y.Array(arguments, 0, true), 
       
   205         i, ret, newRet, 
       
   206         bf = this.before,
       
   207         af = this.after,
       
   208         prevented = false;
       
   209 
       
   210     // execute before
       
   211     for (i in bf) {
       
   212         if (bf.hasOwnProperty(i)) {
       
   213             ret = bf[i].apply(this.obj, args);
       
   214             if (ret) {
       
   215                 switch (ret.constructor) {
       
   216                     case Y.Do.Halt:
       
   217                         return ret.retVal;
       
   218                     case Y.Do.AlterArgs:
       
   219                         args = ret.newArgs;
       
   220                         break;
       
   221                     case Y.Do.Prevent:
       
   222                         prevented = true;
       
   223                         break;
       
   224                     default:
       
   225                 }
       
   226             }
       
   227         }
       
   228     }
       
   229 
       
   230     // execute method
       
   231     if (!prevented) {
       
   232         ret = this.method.apply(this.obj, args);
       
   233     }
       
   234 
       
   235     // execute after methods.
       
   236     for (i in af) {
       
   237         if (af.hasOwnProperty(i)) {
       
   238             newRet = af[i].apply(this.obj, args);
       
   239             // Stop processing if a Halt object is returned
       
   240             if (newRet && newRet.constructor == Y.Do.Halt) {
       
   241                 return newRet.retVal;
       
   242             // Check for a new return value
       
   243             } else if (newRet && newRet.constructor == Y.Do.AlterReturn) {
       
   244                 ret = newRet.newRetVal;
       
   245             }
       
   246         }
       
   247     }
       
   248 
       
   249     return ret;
       
   250 };
       
   251 
       
   252 //////////////////////////////////////////////////////////////////////////
       
   253 
       
   254 
       
   255 /**
       
   256  * Return an AlterArgs object when you want to change the arguments that
       
   257  * were passed into the function.  An example would be a service that scrubs
       
   258  * out illegal characters prior to executing the core business logic.
       
   259  * @class Do.AlterArgs
       
   260  */
       
   261 Y.Do.AlterArgs = function(msg, newArgs) {
       
   262     this.msg = msg;
       
   263     this.newArgs = newArgs;
       
   264 };
       
   265 
       
   266 /**
       
   267  * Return an AlterReturn object when you want to change the result returned
       
   268  * from the core method to the caller
       
   269  * @class Do.AlterReturn
       
   270  */
       
   271 Y.Do.AlterReturn = function(msg, newRetVal) {
       
   272     this.msg = msg;
       
   273     this.newRetVal = newRetVal;
       
   274 };
       
   275 
       
   276 /**
       
   277  * Return a Halt object when you want to terminate the execution
       
   278  * of all subsequent subscribers as well as the wrapped method
       
   279  * if it has not exectued yet.
       
   280  * @class Do.Halt
       
   281  */
       
   282 Y.Do.Halt = function(msg, retVal) {
       
   283     this.msg = msg;
       
   284     this.retVal = retVal;
       
   285 };
       
   286 
       
   287 /**
       
   288  * Return a Prevent object when you want to prevent the wrapped function
       
   289  * from executing, but want the remaining listeners to execute
       
   290  * @class Do.Prevent
       
   291  */
       
   292 Y.Do.Prevent = function(msg) {
       
   293     this.msg = msg;
       
   294 };
       
   295 
       
   296 /**
       
   297  * Return an Error object when you want to terminate the execution
       
   298  * of all subsequent method calls.
       
   299  * @class Do.Error
       
   300  * @deprecated use Y.Do.Halt or Y.Do.Prevent
       
   301  */
       
   302 Y.Do.Error = Y.Do.Halt;
       
   303 
       
   304 //////////////////////////////////////////////////////////////////////////
       
   305 
       
   306 // Y["Event"] && Y.Event.addListener(window, "unload", Y.Do._unload, Y.Do);
       
   307 
       
   308 })();
       
   309 
       
   310 /**
       
   311  * Custom event engine, DOM event listener abstraction layer, synthetic DOM 
       
   312  * events.
       
   313  * @module event-custom
       
   314  * @submodule event-custom-base
       
   315  */
       
   316 
       
   317 /**
       
   318  * Return value from all subscribe operations
       
   319  * @class EventHandle
       
   320  * @constructor
       
   321  * @param evt {CustomEvent} the custom event
       
   322  * @param sub {Subscriber} the subscriber
       
   323  */
       
   324 
       
   325 // var onsubscribeType = "_event:onsub",
       
   326 var AFTER = 'after', 
       
   327     CONFIGS = [
       
   328         'broadcast',
       
   329         'bubbles',
       
   330         'context',
       
   331         'contextFn',
       
   332         'currentTarget',
       
   333         'defaultFn',
       
   334         'details',
       
   335         'emitFacade',
       
   336         'fireOnce',
       
   337         'host',
       
   338         'preventable',
       
   339         'preventedFn',
       
   340         'queuable',
       
   341         'silent',
       
   342         'stoppedFn',
       
   343         'target',
       
   344         'type'
       
   345     ],
       
   346 
       
   347 
       
   348     YUI3_SIGNATURE = 9,
       
   349     YUI_LOG = 'yui:log';
       
   350 
       
   351 Y.EventHandle = function(evt, sub) {
       
   352 
       
   353     /**
       
   354      * The custom event
       
   355      * @type CustomEvent
       
   356      */
       
   357     this.evt = evt;
       
   358 
       
   359     /**
       
   360      * The subscriber object
       
   361      * @type Subscriber
       
   362      */
       
   363     this.sub = sub;
       
   364 };
       
   365 
       
   366 Y.EventHandle.prototype = {
       
   367 
       
   368     /**
       
   369      * Detaches this subscriber
       
   370      * @method detach
       
   371      */
       
   372     detach: function() {
       
   373         var evt = this.evt, i;
       
   374         if (evt) {
       
   375             // Y.log('EventHandle.detach: ' + this.sub, 'info', 'Event');
       
   376             if (Y.Lang.isArray(evt)) {
       
   377                 for (i=0; i<evt.length; i++) {
       
   378                     evt[i].detach();
       
   379                 }
       
   380             } else { 
       
   381                 evt._delete(this.sub);
       
   382             }
       
   383         }
       
   384     }
       
   385 };
       
   386 
       
   387 /**
       
   388  * The CustomEvent class lets you define events for your application
       
   389  * that can be subscribed to by one or more independent component.
       
   390  *
       
   391  * @param {String}  type The type of event, which is passed to the callback
       
   392  *                  when the event fires
       
   393  * @param o configuration object
       
   394  * @class CustomEvent
       
   395  * @constructor
       
   396  */
       
   397 Y.CustomEvent = function(type, o) {
       
   398 
       
   399     // if (arguments.length > 2) {
       
   400 // this.log('CustomEvent context and silent are now in the config', 'warn', 'Event');
       
   401     // }
       
   402 
       
   403     o = o || {};
       
   404 
       
   405     this.id = Y.stamp(this);
       
   406 
       
   407     /**
       
   408      * The type of event, returned to subscribers when the event fires
       
   409      * @property type
       
   410      * @type string
       
   411      */
       
   412     this.type = type;
       
   413 
       
   414     /**
       
   415      * The context the the event will fire from by default.  Defaults to the YUI
       
   416      * instance.
       
   417      * @property context
       
   418      * @type object
       
   419      */
       
   420     this.context = Y;
       
   421 
       
   422     this.logSystem = (type == YUI_LOG);
       
   423 
       
   424     /**
       
   425      * If 0, this event does not broadcast.  If 1, the YUI instance is notified
       
   426      * every time this event fires.  If 2, the YUI instance and the YUI global
       
   427      * (if event is enabled on the global) are notified every time this event
       
   428      * fires.
       
   429      * @property broadcast
       
   430      * @type int
       
   431      */
       
   432     // this.broadcast = 0;
       
   433 
       
   434     /**
       
   435      * By default all custom events are logged in the debug build, set silent
       
   436      * to true to disable debug outpu for this event.
       
   437      * @property silent
       
   438      * @type boolean
       
   439      */
       
   440     this.silent = this.logSystem;
       
   441 
       
   442     /**
       
   443      * Specifies whether this event should be queued when the host is actively
       
   444      * processing an event.  This will effect exectution order of the callbacks
       
   445      * for the various events.
       
   446      * @property queuable
       
   447      * @type boolean
       
   448      * @default false
       
   449      */
       
   450     // this.queuable = false;
       
   451 
       
   452     /**
       
   453      * The subscribers to this event
       
   454      * @property subscribers
       
   455      * @type Subscriber{}
       
   456      */
       
   457     this.subscribers = {};
       
   458 
       
   459     /**
       
   460      * 'After' subscribers
       
   461      * @property afters
       
   462      * @type Subscriber{}
       
   463      */
       
   464     this.afters = {};
       
   465 
       
   466     /**
       
   467      * This event has fired if true
       
   468      *
       
   469      * @property fired
       
   470      * @type boolean
       
   471      * @default false;
       
   472      */
       
   473     // this.fired = false;
       
   474 
       
   475     /**
       
   476      * An array containing the arguments the custom event
       
   477      * was last fired with.
       
   478      * @property firedWith
       
   479      * @type Array
       
   480      */
       
   481     // this.firedWith;
       
   482 
       
   483     /**
       
   484      * This event should only fire one time if true, and if
       
   485      * it has fired, any new subscribers should be notified
       
   486      * immediately.
       
   487      *
       
   488      * @property fireOnce
       
   489      * @type boolean
       
   490      * @default false;
       
   491      */
       
   492     // this.fireOnce = false;
       
   493 
       
   494     /**
       
   495      * Flag for stopPropagation that is modified during fire()
       
   496      * 1 means to stop propagation to bubble targets.  2 means
       
   497      * to also stop additional subscribers on this target.
       
   498      * @property stopped
       
   499      * @type int
       
   500      */
       
   501     // this.stopped = 0;
       
   502 
       
   503     /**
       
   504      * Flag for preventDefault that is modified during fire().
       
   505      * if it is not 0, the default behavior for this event
       
   506      * @property prevented
       
   507      * @type int
       
   508      */
       
   509     // this.prevented = 0;
       
   510 
       
   511     /**
       
   512      * Specifies the host for this custom event.  This is used
       
   513      * to enable event bubbling
       
   514      * @property host
       
   515      * @type EventTarget
       
   516      */
       
   517     // this.host = null;
       
   518 
       
   519     /**
       
   520      * The default function to execute after event listeners
       
   521      * have fire, but only if the default action was not
       
   522      * prevented.
       
   523      * @property defaultFn
       
   524      * @type Function
       
   525      */
       
   526     // this.defaultFn = null;
       
   527 
       
   528     /**
       
   529      * The function to execute if a subscriber calls
       
   530      * stopPropagation or stopImmediatePropagation
       
   531      * @property stoppedFn
       
   532      * @type Function
       
   533      */
       
   534     // this.stoppedFn = null;
       
   535 
       
   536     /**
       
   537      * The function to execute if a subscriber calls
       
   538      * preventDefault
       
   539      * @property preventedFn
       
   540      * @type Function
       
   541      */
       
   542     // this.preventedFn = null;
       
   543 
       
   544     /**
       
   545      * Specifies whether or not this event's default function
       
   546      * can be cancelled by a subscriber by executing preventDefault() 
       
   547      * on the event facade 
       
   548      * @property preventable 
       
   549      * @type boolean 
       
   550      * @default true
       
   551      */
       
   552     this.preventable = true;
       
   553 
       
   554     /**
       
   555      * Specifies whether or not a subscriber can stop the event propagation
       
   556      * via stopPropagation(), stopImmediatePropagation(), or halt()
       
   557      * @property bubbles
       
   558      * @type boolean
       
   559      * @default true
       
   560      */
       
   561     this.bubbles = true;
       
   562 
       
   563     /**
       
   564      * Supports multiple options for listener signatures in order to
       
   565      * port YUI 2 apps.
       
   566      * @property signature
       
   567      * @type int
       
   568      * @default 9
       
   569      */
       
   570     this.signature = YUI3_SIGNATURE;
       
   571 
       
   572     // this.hasSubscribers = false;
       
   573 
       
   574     // this.hasAfters = false;
       
   575 
       
   576     /**
       
   577      * If set to true, the custom event will deliver an EventFacade object
       
   578      * that is similar to a DOM event object.
       
   579      * @property emitFacade
       
   580      * @type boolean
       
   581      * @default false
       
   582      */
       
   583     // this.emitFacade = false;
       
   584 
       
   585     this.applyConfig(o, true);
       
   586 
       
   587     // this.log("Creating " + this.type);
       
   588 
       
   589 };
       
   590 
       
   591 Y.CustomEvent.prototype = {
       
   592 
       
   593     /**
       
   594      * Apply configuration properties.  Only applies the CONFIG whitelist
       
   595      * @method applyConfig
       
   596      * @param o hash of properties to apply
       
   597      * @param force {boolean} if true, properties that exist on the event 
       
   598      * will be overwritten.
       
   599      */
       
   600     applyConfig: function(o, force) {
       
   601         if (o) {
       
   602             Y.mix(this, o, force, CONFIGS);
       
   603         }
       
   604     },
       
   605 
       
   606     _on: function(fn, context, args, when) {
       
   607 
       
   608         if (!fn) {
       
   609             this.log("Invalid callback for CE: " + this.type);
       
   610         }
       
   611 
       
   612         var s = new Y.Subscriber(fn, context, args, when);
       
   613 
       
   614         if (this.fireOnce && this.fired) {
       
   615             Y.later(0, this, Y.bind(this._notify, this, s, this.firedWith));
       
   616         }
       
   617 
       
   618         if (when == AFTER) {
       
   619             this.afters[s.id] = s;
       
   620             this.hasAfters = true;
       
   621         } else {
       
   622             this.subscribers[s.id] = s;
       
   623             this.hasSubscribers = true;
       
   624         }
       
   625 
       
   626         return new Y.EventHandle(this, s);
       
   627 
       
   628     },
       
   629 
       
   630     /**
       
   631      * Listen for this event
       
   632      * @method subscribe
       
   633      * @param {Function} fn        The function to execute
       
   634      * @return {EventHandle|EventTarget} unsubscribe handle or a
       
   635      * chainable event target depending on the 'chain' config.
       
   636      * @deprecated use on
       
   637      */
       
   638     subscribe: function(fn, context) {
       
   639         Y.log('ce.subscribe deprecated, use "on"', 'warn', 'deprecated');
       
   640         var a = (arguments.length > 2) ? Y.Array(arguments, 2, true): null;
       
   641         return this._on(fn, context, a, true);
       
   642     },
       
   643 
       
   644     /**
       
   645      * Listen for this event
       
   646      * @method on
       
   647      * @param {Function} fn        The function to execute
       
   648      * @return {EventHandle|EventTarget} unsubscribe handle or a
       
   649      * chainable event target depending on the 'chain' config.
       
   650      */
       
   651     on: function(fn, context) {
       
   652         var a = (arguments.length > 2) ? Y.Array(arguments, 2, true): null;
       
   653         return this._on(fn, context, a, true);
       
   654     },
       
   655 
       
   656     /**
       
   657      * Listen for this event after the normal subscribers have been notified and
       
   658      * the default behavior has been applied.  If a normal subscriber prevents the 
       
   659      * default behavior, it also prevents after listeners from firing.
       
   660      * @method after
       
   661      * @param {Function} fn        The function to execute
       
   662      * @return {EventHandle|EventTarget} unsubscribe handle or a
       
   663      * chainable event target depending on the 'chain' config.
       
   664      */
       
   665     after: function(fn, context) {
       
   666         var a = (arguments.length > 2) ? Y.Array(arguments, 2, true): null;
       
   667         return this._on(fn, context, a, AFTER);
       
   668     },
       
   669 
       
   670     /**
       
   671      * Detach listeners.
       
   672      * @method detach 
       
   673      * @param {Function} fn  The subscribed function to remove, if not supplied
       
   674      *                       all will be removed
       
   675      * @param {Object}   context The context object passed to subscribe.
       
   676      * @return {int|EventTarget} returns a chainable event target
       
   677      * or the number of subscribers unsubscribed.
       
   678      */
       
   679     detach: function(fn, context) {
       
   680         // unsubscribe handle
       
   681         if (fn && fn.detach) {
       
   682             return fn.detach();
       
   683         }
       
   684 
       
   685         var found = 0, subs = this.subscribers, i, s;
       
   686 
       
   687         for (i in subs) {
       
   688             if (subs.hasOwnProperty(i)) {
       
   689                 s = subs[i];
       
   690                 if (s && (!fn || fn === s.fn)) {
       
   691                     this._delete(s);
       
   692                     found++;
       
   693                 }
       
   694             }
       
   695         }
       
   696 
       
   697         return found;
       
   698     },
       
   699 
       
   700     /**
       
   701      * Detach listeners.
       
   702      * @method unsubscribe
       
   703      * @param {Function} fn  The subscribed function to remove, if not supplied
       
   704      *                       all will be removed
       
   705      * @param {Object}   context The context object passed to subscribe.
       
   706      * @return {boolean|EventTarget} returns a chainable event target
       
   707      * or a boolean for legacy detach support.
       
   708      * @deprecated use detach
       
   709      */
       
   710     unsubscribe: function() {
       
   711         return this.detach.apply(this, arguments);
       
   712     },
       
   713 
       
   714 
       
   715     /**
       
   716      * Notify a single subscriber
       
   717      * @method _notify
       
   718      * @param s {Subscriber} the subscriber
       
   719      * @param args {Array} the arguments array to apply to the listener
       
   720      * @private
       
   721      */
       
   722     _notify: function(s, args, ef) {
       
   723 
       
   724         this.log(this.type + "->" + "sub: " +  s.id);
       
   725 
       
   726         var ret;
       
   727 
       
   728         ret = s.notify(args, this);
       
   729 
       
   730         if (false === ret || this.stopped > 1) {
       
   731             this.log(this.type + " cancelled by subscriber");
       
   732             return false;
       
   733         }
       
   734 
       
   735         return true;
       
   736     },
       
   737 
       
   738     /**
       
   739      * Logger abstraction to centralize the application of the silent flag
       
   740      * @method log
       
   741      * @param msg {string} message to log
       
   742      * @param cat {string} log category
       
   743      */
       
   744     log: function(msg, cat) {
       
   745         if (!this.silent) {
       
   746             Y.log(this.id + ': ' + msg, cat || "info", "event");
       
   747         }
       
   748     },
       
   749 
       
   750     /**
       
   751      * Notifies the subscribers.  The callback functions will be executed
       
   752      * from the context specified when the event was created, and with the 
       
   753      * following parameters:
       
   754      *   <ul>
       
   755      *   <li>The type of event</li>
       
   756      *   <li>All of the arguments fire() was executed with as an array</li>
       
   757      *   <li>The custom object (if any) that was passed into the subscribe() 
       
   758      *       method</li>
       
   759      *   </ul>
       
   760      * @method fire 
       
   761      * @param {Object*} arguments an arbitrary set of parameters to pass to 
       
   762      *                            the handler.
       
   763      * @return {boolean} false if one of the subscribers returned false, 
       
   764      *                   true otherwise
       
   765      * 
       
   766      */
       
   767     fire: function() {
       
   768         if (this.fireOnce && this.fired) {
       
   769             this.log('fireOnce event: ' + this.type + ' already fired');
       
   770             return true;
       
   771         } else {
       
   772 
       
   773             var args = Y.Array(arguments, 0, true);
       
   774 
       
   775             this.fired = true;
       
   776             this.firedWith = args;
       
   777 
       
   778             if (this.emitFacade) {
       
   779                 return this.fireComplex(args);
       
   780             } else {
       
   781                 return this.fireSimple(args);
       
   782             }
       
   783         }
       
   784     },
       
   785 
       
   786     fireSimple: function(args) {
       
   787         if (this.hasSubscribers || this.hasAfters) {
       
   788             this._procSubs(Y.merge(this.subscribers, this.afters), args);
       
   789         }
       
   790         this._broadcast(args);
       
   791         return this.stopped ? false : true;
       
   792     },
       
   793 
       
   794     // Requires the event-custom-complex module for full funcitonality.
       
   795     fireComplex: function(args) {
       
   796         args[0] = args[0] || {};
       
   797         return this.fireSimple(args);
       
   798     },
       
   799 
       
   800     _procSubs: function(subs, args, ef) {
       
   801         var s, i;
       
   802         for (i in subs) {
       
   803             if (subs.hasOwnProperty(i)) {
       
   804                 s = subs[i];
       
   805                 if (s && s.fn) {
       
   806                     if (false === this._notify(s, args, ef)) {
       
   807                         this.stopped = 2;
       
   808                     }
       
   809                     if (this.stopped == 2) {
       
   810                         return false;
       
   811                     }
       
   812                 }
       
   813             }
       
   814         }
       
   815 
       
   816         return true;
       
   817     },
       
   818 
       
   819     _broadcast: function(args) {
       
   820         if (!this.stopped && this.broadcast) {
       
   821 
       
   822             var a = Y.Array(args);
       
   823             a.unshift(this.type);
       
   824 
       
   825             if (this.host !== Y) {
       
   826                 Y.fire.apply(Y, a);
       
   827             }
       
   828 
       
   829             if (this.broadcast == 2) {
       
   830                 Y.Global.fire.apply(Y.Global, a);
       
   831             }
       
   832         }
       
   833     },
       
   834 
       
   835     /**
       
   836      * Removes all listeners
       
   837      * @method unsubscribeAll
       
   838      * @return {int} The number of listeners unsubscribed
       
   839      * @deprecated use detachAll
       
   840      */
       
   841     unsubscribeAll: function() {
       
   842         return this.detachAll.apply(this, arguments);
       
   843     },
       
   844 
       
   845     /**
       
   846      * Removes all listeners
       
   847      * @method detachAll
       
   848      * @return {int} The number of listeners unsubscribed
       
   849      */
       
   850     detachAll: function() {
       
   851         return this.detach();
       
   852     },
       
   853 
       
   854     /**
       
   855      * @method _delete
       
   856      * @param subscriber object
       
   857      * @private
       
   858      */
       
   859     _delete: function(s) {
       
   860         if (s) {
       
   861             delete s.fn;
       
   862             delete s.context;
       
   863             delete this.subscribers[s.id];
       
   864             delete this.afters[s.id];
       
   865         }
       
   866     }
       
   867 };
       
   868 
       
   869 /////////////////////////////////////////////////////////////////////
       
   870 
       
   871 /**
       
   872  * Stores the subscriber information to be used when the event fires.
       
   873  * @param {Function} fn       The wrapped function to execute
       
   874  * @param {Object}   context  The value of the keyword 'this' in the listener
       
   875  * @param {Array} args*       0..n additional arguments to supply the listener
       
   876  *
       
   877  * @class Subscriber
       
   878  * @constructor
       
   879  */
       
   880 Y.Subscriber = function(fn, context, args) {
       
   881 
       
   882     /**
       
   883      * The callback that will be execute when the event fires
       
   884      * This is wrapped by Y.rbind if obj was supplied.
       
   885      * @property fn
       
   886      * @type Function
       
   887      */
       
   888     this.fn = fn;
       
   889 
       
   890     /**
       
   891      * Optional 'this' keyword for the listener
       
   892      * @property context
       
   893      * @type Object
       
   894      */
       
   895     this.context = context;
       
   896 
       
   897     /**
       
   898      * Unique subscriber id
       
   899      * @property id
       
   900      * @type String
       
   901      */
       
   902     this.id = Y.stamp(this);
       
   903 
       
   904     /**
       
   905      * Additional arguments to propagate to the subscriber
       
   906      * @property args
       
   907      * @type Array
       
   908      */
       
   909     this.args = args;
       
   910 
       
   911     /**
       
   912      * Custom events for a given fire transaction.
       
   913      * @property events
       
   914      * @type {EventTarget}
       
   915      */
       
   916     this.events = null;
       
   917     
       
   918 };
       
   919 
       
   920 Y.Subscriber.prototype = {
       
   921 
       
   922     _notify: function(c, args, ce) {
       
   923         var a = this.args, ret;
       
   924         switch (ce.signature) {
       
   925             case 0:
       
   926                 ret = this.fn.call(c, ce.type, args, c);
       
   927                 break;
       
   928             case 1:
       
   929                 ret = this.fn.call(c, args[0] || null, c);
       
   930                 break;
       
   931             default:
       
   932                 if (a || args) {
       
   933                     args = args || [];
       
   934                     a = (a) ? args.concat(a) : args;
       
   935                     ret = this.fn.apply(c, a);
       
   936                 } else {
       
   937                     ret = this.fn.call(c);
       
   938                 }
       
   939         }
       
   940 
       
   941         return ret;
       
   942     },
       
   943 
       
   944     /**
       
   945      * Executes the subscriber.
       
   946      * @method notify
       
   947      * @param args {Array} Arguments array for the subscriber
       
   948      * @param ce {CustomEvent} The custom event that sent the notification
       
   949      */
       
   950     notify: function(args, ce) {
       
   951         var c = this.context,
       
   952             ret = true;
       
   953 
       
   954         if (!c) {
       
   955             c = (ce.contextFn) ? ce.contextFn() : ce.context;
       
   956         }
       
   957 
       
   958         // only catch errors if we will not re-throw them.
       
   959         if (Y.config.throwFail) {
       
   960             ret = this._notify(c, args, ce);
       
   961         } else {
       
   962             try {
       
   963                 ret = this._notify(c, args, ce);
       
   964             } catch(e) {
       
   965                 Y.error(this + ' failed: ' + e.message, e);
       
   966             }
       
   967         }
       
   968 
       
   969         return ret;
       
   970     },
       
   971 
       
   972     /**
       
   973      * Returns true if the fn and obj match this objects properties.
       
   974      * Used by the unsubscribe method to match the right subscriber.
       
   975      *
       
   976      * @method contains
       
   977      * @param {Function} fn the function to execute
       
   978      * @param {Object} context optional 'this' keyword for the listener
       
   979      * @return {boolean} true if the supplied arguments match this 
       
   980      *                   subscriber's signature.
       
   981      */
       
   982     contains: function(fn, context) {
       
   983         if (context) {
       
   984             return ((this.fn == fn) && this.context == context);
       
   985         } else {
       
   986             return (this.fn == fn);
       
   987         }
       
   988     }
       
   989 
       
   990 };
       
   991 
       
   992 /**
       
   993  * Custom event engine, DOM event listener abstraction layer, synthetic DOM 
       
   994  * events.
       
   995  * @module event-custom
       
   996  * @submodule event-custom-base
       
   997  */
       
   998 (function() {
       
   999 
       
  1000 /**
       
  1001  * EventTarget provides the implementation for any object to
       
  1002  * publish, subscribe and fire to custom events, and also
       
  1003  * alows other EventTargets to target the object with events
       
  1004  * sourced from the other object.
       
  1005  * EventTarget is designed to be used with Y.augment to wrap 
       
  1006  * EventCustom in an interface that allows events to be listened to 
       
  1007  * and fired by name.  This makes it possible for implementing code to
       
  1008  * subscribe to an event that either has not been created yet, or will
       
  1009  * not be created at all.
       
  1010  * @class EventTarget
       
  1011  * @param opts a configuration object
       
  1012  * @config emitFacade {boolean} if true, all events will emit event 
       
  1013  * facade payloads by default (default false)
       
  1014  * @config prefix {string} the prefix to apply to non-prefixed event names 
       
  1015  * @config chain {boolean} if true, on/after/detach return the host to allow 
       
  1016  * chaining, otherwise they return an EventHandle (default false)
       
  1017  */
       
  1018 
       
  1019 var L = Y.Lang,
       
  1020     PREFIX_DELIMITER = ':',
       
  1021     CATEGORY_DELIMITER = '|',
       
  1022     AFTER_PREFIX = '~AFTER~',
       
  1023 
       
  1024     /**
       
  1025      * If the instance has a prefix attribute and the
       
  1026      * event type is not prefixed, the instance prefix is
       
  1027      * applied to the supplied type.
       
  1028      * @method _getType
       
  1029      * @private
       
  1030      */
       
  1031     _getType = Y.cached(function(type, pre) {
       
  1032 
       
  1033         if (!pre || !L.isString(type) || type.indexOf(PREFIX_DELIMITER) > -1) {
       
  1034             return type;
       
  1035         } 
       
  1036 
       
  1037         return pre + PREFIX_DELIMITER + type;
       
  1038     }),
       
  1039 
       
  1040     /**
       
  1041      * Returns an array with the detach key (if provided),
       
  1042      * and the prefixed event name from _getType
       
  1043      * Y.on('detachcategory, menu:click', fn)
       
  1044      * @method _parseType
       
  1045      * @private
       
  1046      */
       
  1047     _parseType = Y.cached(function(type, pre) {
       
  1048 
       
  1049         var t = type, detachcategory, after, i;
       
  1050 
       
  1051         if (!L.isString(t)) {
       
  1052             return t;
       
  1053         } 
       
  1054         
       
  1055         i = t.indexOf(AFTER_PREFIX);
       
  1056 
       
  1057         if (i > -1) {
       
  1058             after = true;
       
  1059             t = t.substr(AFTER_PREFIX.length);
       
  1060             // Y.log(t);
       
  1061         }
       
  1062 
       
  1063         i = t.indexOf(CATEGORY_DELIMITER);
       
  1064 
       
  1065         if (i > -1) {
       
  1066             detachcategory = t.substr(0, (i));
       
  1067             t = t.substr(i+1);
       
  1068             if (t == '*') {
       
  1069                 t = null;
       
  1070             }
       
  1071         }
       
  1072 
       
  1073         // detach category, full type with instance prefix, is this an after listener, short type
       
  1074         return [detachcategory, (pre) ? _getType(t, pre) : t, after, t];
       
  1075     }),
       
  1076 
       
  1077     ET = function(opts) {
       
  1078 
       
  1079         // Y.log('EventTarget constructor executed: ' + this._yuid);
       
  1080 
       
  1081         var o = (L.isObject(opts)) ? opts : {};
       
  1082 
       
  1083         this._yuievt = this._yuievt || {
       
  1084 
       
  1085             id: Y.guid(),
       
  1086 
       
  1087             events: {},
       
  1088 
       
  1089             targets: {},
       
  1090 
       
  1091             config: o,
       
  1092 
       
  1093             chain: ('chain' in o) ? o.chain : Y.config.chain,
       
  1094 
       
  1095             defaults: {
       
  1096                 context: o.context || this, 
       
  1097                 host: this,
       
  1098                 emitFacade: o.emitFacade,
       
  1099                 fireOnce: o.fireOnce,
       
  1100                 queuable: o.queuable,
       
  1101                 broadcast: o.broadcast,
       
  1102                 bubbles: ('bubbles' in o) ? o.bubbles : true
       
  1103             }
       
  1104         };
       
  1105 
       
  1106     };
       
  1107 
       
  1108 
       
  1109 ET.prototype = {
       
  1110 
       
  1111     /**
       
  1112      * Subscribe to a custom event hosted by this object
       
  1113      * @method on 
       
  1114      * @param type    {string}   The type of the event
       
  1115      * @param fn {Function} The callback
       
  1116      * @return the event target or a detach handle per 'chain' config
       
  1117      */
       
  1118     on: function(type, fn, context, x) {
       
  1119 
       
  1120         var parts = _parseType(type, this._yuievt.config.prefix), f, c, args, ret, ce,
       
  1121             detachcategory, handle, store = Y.Env.evt.handles, after, adapt, shorttype,
       
  1122             Node = Y.Node, n, domevent;
       
  1123 
       
  1124         if (L.isObject(type)) {
       
  1125 
       
  1126             if (L.isFunction(type)) {
       
  1127                 return Y.Do.before.apply(Y.Do, arguments);
       
  1128             }
       
  1129 
       
  1130             f = fn; 
       
  1131             c = context; 
       
  1132             args = Y.Array(arguments, 0, true);
       
  1133             ret = {};
       
  1134             after = type._after;
       
  1135             delete type._after;
       
  1136 
       
  1137             Y.each(type, function(v, k) {
       
  1138 
       
  1139                 if (v) {
       
  1140                     f = v.fn || ((Y.Lang.isFunction(v)) ? v : f);
       
  1141                     c = v.context || c;
       
  1142                 }
       
  1143 
       
  1144                 args[0] = (after) ? AFTER_PREFIX + k : k;
       
  1145                 args[1] = f;
       
  1146                 args[2] = c;
       
  1147 
       
  1148                 ret[k] = this.on.apply(this, args); 
       
  1149 
       
  1150             }, this);
       
  1151 
       
  1152             return (this._yuievt.chain) ? this : new Y.EventHandle(ret);
       
  1153 
       
  1154         }
       
  1155         
       
  1156         detachcategory = parts[0];
       
  1157         after = parts[2];
       
  1158         shorttype = parts[3];
       
  1159 
       
  1160         // extra redirection so we catch adaptor events too.  take a look at this.
       
  1161         if (Node && (this instanceof Node) && (shorttype in Node.DOM_EVENTS)) {
       
  1162             args = Y.Array(arguments, 0, true);
       
  1163             args.splice(2, 0, Node.getDOMNode(this));
       
  1164             // Y.log("Node detected, redirecting with these args: " + args);
       
  1165             return Y.on.apply(Y, args);
       
  1166         }
       
  1167 
       
  1168         type = parts[1];
       
  1169 
       
  1170         if (this instanceof YUI) {
       
  1171 
       
  1172             adapt = Y.Env.evt.plugins[type];
       
  1173             args  = Y.Array(arguments, 0, true);
       
  1174             args[0] = shorttype;
       
  1175 
       
  1176             if (Node) {
       
  1177                 n = args[2];
       
  1178 
       
  1179                 if (n instanceof Y.NodeList) {
       
  1180                     n = Y.NodeList.getDOMNodes(n);
       
  1181                 } else if (n instanceof Node) {
       
  1182                     n = Node.getDOMNode(n);
       
  1183                 }
       
  1184 
       
  1185                 domevent = (shorttype in Node.DOM_EVENTS);
       
  1186 
       
  1187                 // Captures both DOM events and event plugins.
       
  1188                 if (domevent) {
       
  1189                     args[2] = n;
       
  1190                 }
       
  1191             }
       
  1192 
       
  1193             // check for the existance of an event adaptor
       
  1194             if (adapt) {
       
  1195                 Y.log('Using adaptor for ' + shorttype + ', ' + n, 'info', 'event');
       
  1196                 handle = adapt.on.apply(Y, args);
       
  1197             } else if ((!type) || domevent) {
       
  1198                 handle = Y.Event._attach(args);
       
  1199             }
       
  1200 
       
  1201         } 
       
  1202 
       
  1203         if (!handle) {
       
  1204             ce = this._yuievt.events[type] || this.publish(type);
       
  1205             handle = ce._on(fn, context, (arguments.length > 3) ? Y.Array(arguments, 3, true) : null, (after) ? 'after' : true);
       
  1206         }
       
  1207 
       
  1208         if (detachcategory) {
       
  1209             store[detachcategory] = store[detachcategory] || {};
       
  1210             store[detachcategory][type] = store[detachcategory][type] || [];
       
  1211             store[detachcategory][type].push(handle);
       
  1212         }
       
  1213 
       
  1214         return (this._yuievt.chain) ? this : handle;
       
  1215 
       
  1216     },
       
  1217 
       
  1218     /**
       
  1219      * subscribe to an event
       
  1220      * @method subscribe
       
  1221      * @deprecated use on
       
  1222      */
       
  1223     subscribe: function() {
       
  1224         Y.log('EventTarget subscribe() is deprecated, use on()', 'warn', 'deprecated');
       
  1225         return this.on.apply(this, arguments);
       
  1226     },
       
  1227 
       
  1228     /**
       
  1229      * Detach one or more listeners the from the specified event
       
  1230      * @method detach 
       
  1231      * @param type {string|Object}   Either the handle to the subscriber or the 
       
  1232      *                        type of event.  If the type
       
  1233      *                        is not specified, it will attempt to remove
       
  1234      *                        the listener from all hosted events.
       
  1235      * @param fn   {Function} The subscribed function to unsubscribe, if not
       
  1236      *                          supplied, all subscribers will be removed.
       
  1237      * @param context  {Object}   The custom object passed to subscribe.  This is
       
  1238      *                        optional, but if supplied will be used to
       
  1239      *                        disambiguate multiple listeners that are the same
       
  1240      *                        (e.g., you subscribe many object using a function
       
  1241      *                        that lives on the prototype)
       
  1242      * @return {EventTarget} the host
       
  1243      */
       
  1244     detach: function(type, fn, context) {
       
  1245         var evts = this._yuievt.events, i, ret,
       
  1246             Node = Y.Node, isNode = (this instanceof Node);
       
  1247 
       
  1248         // detachAll disabled on the Y instance.
       
  1249         if (!type && (this !== Y)) {
       
  1250             for (i in evts) {
       
  1251                 if (evts.hasOwnProperty(i)) {
       
  1252                     ret = evts[i].detach(fn, context);
       
  1253                 }
       
  1254             }
       
  1255             if (isNode) {
       
  1256 
       
  1257                 Y.Event.purgeElement(Node.getDOMNode(this));
       
  1258             }
       
  1259 
       
  1260             return ret;
       
  1261         }
       
  1262 
       
  1263         var parts = _parseType(type, this._yuievt.config.prefix), 
       
  1264         detachcategory = L.isArray(parts) ? parts[0] : null,
       
  1265         shorttype = (parts) ? parts[3] : null,
       
  1266         handle, adapt, store = Y.Env.evt.handles, cat, args,
       
  1267         ce,
       
  1268 
       
  1269         keyDetacher = function(lcat, ltype) {
       
  1270             var handles = lcat[ltype];
       
  1271             if (handles) {
       
  1272                 while (handles.length) {
       
  1273                     handle = handles.pop();
       
  1274                     handle.detach();
       
  1275                 }
       
  1276             }
       
  1277         };
       
  1278 
       
  1279         if (detachcategory) {
       
  1280 
       
  1281             cat = store[detachcategory];
       
  1282             type = parts[1];
       
  1283 
       
  1284             if (cat) {
       
  1285                 if (type) {
       
  1286                     keyDetacher(cat, type);
       
  1287                 } else {
       
  1288                     for (i in cat) {
       
  1289                         if (cat.hasOwnProperty(i)) {
       
  1290                             keyDetacher(cat, i);
       
  1291                         }
       
  1292                     }
       
  1293                 }
       
  1294 
       
  1295                 return (this._yuievt.chain) ? this : true;
       
  1296             }
       
  1297 
       
  1298         // If this is an event handle, use it to detach
       
  1299         } else if (L.isObject(type) && type.detach) {
       
  1300             ret = type.detach();
       
  1301             return (this._yuievt.chain) ? this : ret;
       
  1302         // extra redirection so we catch adaptor events too.  take a look at this.
       
  1303         } else if (isNode && ((!shorttype) || (shorttype in Node.DOM_EVENTS))) {
       
  1304             args = Y.Array(arguments, 0, true);
       
  1305             args[2] = Node.getDOMNode(this);
       
  1306             return Y.detach.apply(Y, args);
       
  1307         }
       
  1308 
       
  1309         adapt = Y.Env.evt.plugins[shorttype];
       
  1310 
       
  1311         // The YUI instance handles DOM events and adaptors
       
  1312         if (this instanceof YUI) {
       
  1313             args = Y.Array(arguments, 0, true);
       
  1314             // use the adaptor specific detach code if
       
  1315             if (adapt && adapt.detach) {
       
  1316                 return adapt.detach.apply(Y, args);
       
  1317             // DOM event fork
       
  1318             } else if (!type || (!adapt && Node && (type in Node.DOM_EVENTS))) {
       
  1319                 args[0] = type;
       
  1320                 return Y.Event.detach.apply(Y.Event, args);
       
  1321             }
       
  1322         }
       
  1323 
       
  1324         ce = evts[type];
       
  1325         if (ce) {
       
  1326             ret = ce.detach(fn, context);
       
  1327         }
       
  1328 
       
  1329         return (this._yuievt.chain) ? this : ret;
       
  1330     },
       
  1331 
       
  1332     /**
       
  1333      * detach a listener
       
  1334      * @method unsubscribe
       
  1335      * @deprecated use detach
       
  1336      */
       
  1337     unsubscribe: function() {
       
  1338         return this.detach.apply(this, arguments);
       
  1339     },
       
  1340     
       
  1341     /**
       
  1342      * Removes all listeners from the specified event.  If the event type
       
  1343      * is not specified, all listeners from all hosted custom events will
       
  1344      * be removed.
       
  1345      * @method detachAll
       
  1346      * @param type {string}   The type, or name of the event
       
  1347      */
       
  1348     detachAll: function(type) {
       
  1349         return this.detach(type);
       
  1350     },
       
  1351 
       
  1352     /**
       
  1353      * Removes all listeners from the specified event.  If the event type
       
  1354      * is not specified, all listeners from all hosted custom events will
       
  1355      * be removed.
       
  1356      * @method unsubscribeAll
       
  1357      * @param type {string}   The type, or name of the event
       
  1358      * @deprecated use detachAll
       
  1359      */
       
  1360     unsubscribeAll: function() {
       
  1361         return this.detachAll.apply(this, arguments);
       
  1362     },
       
  1363 
       
  1364     /**
       
  1365      * Creates a new custom event of the specified type.  If a custom event
       
  1366      * by that name already exists, it will not be re-created.  In either
       
  1367      * case the custom event is returned. 
       
  1368      *
       
  1369      * @method publish
       
  1370      *
       
  1371      * @param type {string} the type, or name of the event
       
  1372      * @param opts {object} optional config params.  Valid properties are:
       
  1373      *
       
  1374      *  <ul>
       
  1375      *    <li>
       
  1376      *   'broadcast': whether or not the YUI instance and YUI global are notified when the event is fired (false)
       
  1377      *    </li>
       
  1378      *    <li>
       
  1379      *   'bubbles': whether or not this event bubbles (true)
       
  1380      *    </li>
       
  1381      *    <li>
       
  1382      *   'context': the default execution context for the listeners (this)
       
  1383      *    </li>
       
  1384      *    <li>
       
  1385      *   'defaultFn': the default function to execute when this event fires if preventDefault was not called
       
  1386      *    </li>
       
  1387      *    <li>
       
  1388      *   'emitFacade': whether or not this event emits a facade (false)
       
  1389      *    </li>
       
  1390      *    <li>
       
  1391      *   'prefix': the prefix for this targets events, e.g., 'menu' in 'menu:click' 
       
  1392      *    </li>
       
  1393      *    <li>
       
  1394      *   'fireOnce': if an event is configured to fire once, new subscribers after
       
  1395      *   the fire will be notified immediately.
       
  1396      *    </li>
       
  1397      *    <li>
       
  1398      *   'preventable': whether or not preventDefault() has an effect (true)
       
  1399      *    </li>
       
  1400      *    <li>
       
  1401      *   'preventedFn': a function that is executed when preventDefault is called
       
  1402      *    </li>
       
  1403      *    <li>
       
  1404      *   'queuable': whether or not this event can be queued during bubbling (false)
       
  1405      *    </li>
       
  1406      *    <li>
       
  1407      *   'silent': if silent is true, debug messages are not provided for this event.
       
  1408      *    </li>
       
  1409      *    <li>
       
  1410      *   'stoppedFn': a function that is executed when stopPropagation is called
       
  1411      *    </li>
       
  1412      *    <li>
       
  1413      *   'type': the event type (valid option if not provided as the first parameter to publish)
       
  1414      *    </li>
       
  1415      *  </ul>
       
  1416      *
       
  1417      *  @return {Event.Custom} the custom event
       
  1418      *
       
  1419      */
       
  1420     publish: function(type, opts) {
       
  1421         var events, ce, ret, pre = this._yuievt.config.prefix;
       
  1422 
       
  1423         type = (pre) ? _getType(type, pre) : type;
       
  1424 
       
  1425 
       
  1426         if (L.isObject(type)) {
       
  1427             ret = {};
       
  1428             Y.each(type, function(v, k) {
       
  1429                 ret[k] = this.publish(k, v || opts); 
       
  1430             }, this);
       
  1431 
       
  1432             return ret;
       
  1433         }
       
  1434 
       
  1435         events = this._yuievt.events; 
       
  1436         ce = events[type];
       
  1437 
       
  1438         if (ce) {
       
  1439 // ce.log("publish applying new config to published event: '"+type+"' exists", 'info', 'event');
       
  1440             if (opts) {
       
  1441                 ce.applyConfig(opts, true);
       
  1442             }
       
  1443         } else {
       
  1444             // apply defaults
       
  1445             ce = new Y.CustomEvent(type, (opts) ? Y.mix(opts, this._yuievt.defaults) : this._yuievt.defaults);
       
  1446             events[type] = ce;
       
  1447         }
       
  1448 
       
  1449         // make sure we turn the broadcast flag off if this
       
  1450         // event was published as a result of bubbling
       
  1451         // if (opts instanceof Y.CustomEvent) {
       
  1452           //   events[type].broadcast = false;
       
  1453         // }
       
  1454 
       
  1455         return events[type];
       
  1456     },
       
  1457 
       
  1458     /**
       
  1459      * Registers another EventTarget as a bubble target.  Bubble order
       
  1460      * is determined by the order registered.  Multiple targets can
       
  1461      * be specified.
       
  1462      * @method addTarget
       
  1463      * @param o {EventTarget} the target to add
       
  1464      */
       
  1465     addTarget: function(o) {
       
  1466         this._yuievt.targets[Y.stamp(o)] = o;
       
  1467         this._yuievt.hasTargets = true;
       
  1468     },
       
  1469 
       
  1470     /**
       
  1471      * Removes a bubble target
       
  1472      * @method removeTarget
       
  1473      * @param o {EventTarget} the target to remove
       
  1474      */
       
  1475     removeTarget: function(o) {
       
  1476         delete this._yuievt.targets[Y.stamp(o)];
       
  1477     },
       
  1478 
       
  1479    /**
       
  1480      * Fire a custom event by name.  The callback functions will be executed
       
  1481      * from the context specified when the event was created, and with the 
       
  1482      * following parameters.
       
  1483      *
       
  1484      * If the custom event object hasn't been created, then the event hasn't 
       
  1485      * been published and it has no subscribers.  For performance sake, we 
       
  1486      * immediate exit in this case.  This means the event won't bubble, so 
       
  1487      * if the intention is that a bubble target be notified, the event must 
       
  1488      * be published on this object first.
       
  1489      *
       
  1490      * The first argument is the event type, and any additional arguments are
       
  1491      * passed to the listeners as parameters.  If the first of these is an
       
  1492      * object literal, and the event is configured to emit an event facade,
       
  1493      * that object is mixed into the event facade and the facade is provided 
       
  1494      * in place of the original object.
       
  1495      *
       
  1496      * @method fire
       
  1497      * @param type {String|Object} The type of the event, or an object that contains
       
  1498      * a 'type' property.
       
  1499      * @param arguments {Object*} an arbitrary set of parameters to pass to 
       
  1500      * the handler.  If the first of these is an object literal and the event is
       
  1501      * configured to emit an event facade, the event facade will replace that
       
  1502      * parameter after the properties the object literal contains are copied to
       
  1503      * the event facade.
       
  1504      * @return {Event.Target} the event host
       
  1505      *                   
       
  1506      */
       
  1507     fire: function(type) {
       
  1508 
       
  1509         var typeIncluded = L.isString(type),
       
  1510             t = (typeIncluded) ? type : (type && type.type),
       
  1511             ce, a, ret, pre=this._yuievt.config.prefix;
       
  1512 
       
  1513         t = (pre) ? _getType(t, pre) : t;
       
  1514         ce = this.getEvent(t, true);
       
  1515 
       
  1516         // this event has not been published or subscribed to
       
  1517         if (!ce) {
       
  1518             
       
  1519             if (this._yuievt.hasTargets) {
       
  1520                 a = (typeIncluded) ? arguments : Y.Array(arguments, 0, true).unshift(t);
       
  1521                 return this.bubble(null, a, this);
       
  1522             }
       
  1523 
       
  1524             // otherwise there is nothing to be done
       
  1525             ret = true;
       
  1526 
       
  1527         } else {
       
  1528 
       
  1529             a = Y.Array(arguments, (typeIncluded) ? 1 : 0, true);
       
  1530             ret = ce.fire.apply(ce, a);
       
  1531 
       
  1532             // clear target for next fire()
       
  1533             ce.target = null;
       
  1534         }
       
  1535 
       
  1536         return (this._yuievt.chain) ? this : ret;
       
  1537     },
       
  1538 
       
  1539     /**
       
  1540      * Returns the custom event of the provided type has been created, a
       
  1541      * falsy value otherwise
       
  1542      * @method getEvent
       
  1543      * @param type {string} the type, or name of the event
       
  1544      * @param prefixed {string} if true, the type is prefixed already
       
  1545      * @return {Event.Custom} the custom event or null
       
  1546      */
       
  1547     getEvent: function(type, prefixed) {
       
  1548         var pre, e;
       
  1549         if (!prefixed) {
       
  1550             pre = this._yuievt.config.prefix;
       
  1551             type = (pre) ? _getType(type, pre) : type;
       
  1552         }
       
  1553         e = this._yuievt.events;
       
  1554         return (e && type in e) ? e[type] : null;
       
  1555     },
       
  1556 
       
  1557     /**
       
  1558      * Subscribe to a custom event hosted by this object.  The
       
  1559      * supplied callback will execute after any listeners add
       
  1560      * via the subscribe method, and after the default function,
       
  1561      * if configured for the event, has executed.
       
  1562      * @method after
       
  1563      * @param type    {string}   The type of the event
       
  1564      * @param fn {Function} The callback
       
  1565      * @return the event target or a detach handle per 'chain' config
       
  1566      */
       
  1567     after: function(type, fn) {
       
  1568 
       
  1569         var a = Y.Array(arguments, 0, true);
       
  1570 
       
  1571         switch (L.type(type)) {
       
  1572             case 'function':
       
  1573                 return Y.Do.after.apply(Y.Do, arguments);
       
  1574             case 'object':
       
  1575                 a[0]._after = true;
       
  1576                 break;
       
  1577             default:
       
  1578                 a[0] = AFTER_PREFIX + type;
       
  1579         }
       
  1580 
       
  1581         return this.on.apply(this, a);
       
  1582 
       
  1583     },
       
  1584 
       
  1585     /**
       
  1586      * Executes the callback before a DOM event, custom event
       
  1587      * or method.  If the first argument is a function, it
       
  1588      * is assumed the target is a method.  For DOM and custom
       
  1589      * events, this is an alias for Y.on.
       
  1590      *
       
  1591      * For DOM and custom events:
       
  1592      * type, callback, context, 0-n arguments
       
  1593      *  
       
  1594      * For methods:
       
  1595      * callback, object (method host), methodName, context, 0-n arguments
       
  1596      *
       
  1597      * @method before
       
  1598      * @return detach handle
       
  1599      * @deprecated use the on method
       
  1600      */
       
  1601     before: function() { 
       
  1602         return this.on.apply(this, arguments);
       
  1603     }
       
  1604 
       
  1605 };
       
  1606 
       
  1607 Y.EventTarget = ET;
       
  1608 
       
  1609 // make Y an event target
       
  1610 Y.mix(Y, ET.prototype, false, false, { 
       
  1611     bubbles: false 
       
  1612 });
       
  1613 
       
  1614 ET.call(Y);
       
  1615 
       
  1616 YUI.Env.globalEvents = YUI.Env.globalEvents || new ET();
       
  1617 
       
  1618 /**
       
  1619  * Hosts YUI page level events.  This is where events bubble to
       
  1620  * when the broadcast config is set to 2.  This property is
       
  1621  * only available if the custom event module is loaded.
       
  1622  * @property Global
       
  1623  * @type EventTarget
       
  1624  * @for YUI
       
  1625  */
       
  1626 Y.Global = YUI.Env.globalEvents;
       
  1627 
       
  1628 // @TODO implement a global namespace function on Y.Global?
       
  1629 
       
  1630 })();
       
  1631 
       
  1632 
       
  1633 /**
       
  1634  * <code>YUI</code>'s <code>on</code> method is a unified interface for subscribing to
       
  1635  * most events exposed by YUI.  This includes custom events, DOM events, and 
       
  1636  * function events.  <code>detach</code> is also provided to remove listeners
       
  1637  * serviced by this function.
       
  1638  *
       
  1639  * The signature that <code>on</code> accepts varies depending on the type
       
  1640  * of event being consumed.  Refer to the specific methods that will
       
  1641  * service a specific request for additional information about subscribing
       
  1642  * to that type of event.
       
  1643  *
       
  1644  * <ul>
       
  1645  * <li>Custom events.  These events are defined by various
       
  1646  * modules in the library.  This type of event is delegated to
       
  1647  * <code>EventTarget</code>'s <code>on</code> method.
       
  1648  *   <ul>
       
  1649  *     <li>The type of the event</li>
       
  1650  *     <li>The callback to execute</li>
       
  1651  *     <li>An optional context object</li>
       
  1652  *     <li>0..n additional arguments to supply the callback.</li>
       
  1653  *   </ul>
       
  1654  *   Example: 
       
  1655  *   <code>Y.on('domready', function() { // start work });</code>
       
  1656  * </li>
       
  1657  * <li>DOM events.  These are moments reported by the browser related
       
  1658  * to browser functionality and user interaction.
       
  1659  * This type of event is delegated to <code>Event</code>'s 
       
  1660  * <code>attach</code> method.
       
  1661  *   <ul>
       
  1662  *     <li>The type of the event</li>
       
  1663  *     <li>The callback to execute</li>
       
  1664  *     <li>The specification for the Node(s) to attach the listener
       
  1665  *     to.  This can be a selector, collections, or Node/Element
       
  1666  *     refereces.</li>
       
  1667  *     <li>An optional context object</li>
       
  1668  *     <li>0..n additional arguments to supply the callback.</li>
       
  1669  *   </ul>
       
  1670  *   Example: 
       
  1671  *   <code>Y.on('click', function(e) { // something was clicked }, '#someelement');</code>
       
  1672  * </li>
       
  1673  * <li>Function events.  These events can be used to react before or after a
       
  1674  * function is executed.  This type of event is delegated to <code>Event.Do</code>'s 
       
  1675  * <code>before</code> method.
       
  1676  *   <ul>
       
  1677  *     <li>The callback to execute</li>
       
  1678  *     <li>The object that has the function that will be listened for.</li>
       
  1679  *     <li>The name of the function to listen for.</li>
       
  1680  *     <li>An optional context object</li>
       
  1681  *     <li>0..n additional arguments to supply the callback.</li>
       
  1682  *   </ul>
       
  1683  *   Example <code>Y.on(function(arg1, arg2, etc) { // obj.methodname was executed }, obj 'methodname');</code>
       
  1684  * </li>
       
  1685  * </ul>
       
  1686  *
       
  1687  * <code>on</code> corresponds to the moment before any default behavior of
       
  1688  * the event.  <code>after</code> works the same way, but these listeners
       
  1689  * execute after the event's default behavior.  <code>before</code> is an
       
  1690  * alias for <code>on</code>.
       
  1691  *
       
  1692  * @method on 
       
  1693  * @param type** event type (this parameter does not apply for function events)
       
  1694  * @param fn the callback
       
  1695  * @param target** a descriptor for the target (applies to custom events only).
       
  1696  * For function events, this is the object that contains the function to
       
  1697  * execute.
       
  1698  * @param extra** 0..n Extra information a particular event may need.  These
       
  1699  * will be documented with the event.  In the case of function events, this
       
  1700  * is the name of the function to execute on the host.  In the case of
       
  1701  * delegate listeners, this is the event delegation specification.
       
  1702  * @param context optionally change the value of 'this' in the callback
       
  1703  * @param args* 0..n additional arguments to pass to the callback.
       
  1704  * @return the event target or a detach handle per 'chain' config
       
  1705  * @for YUI
       
  1706  */
       
  1707 
       
  1708 /**
       
  1709  * after() is a unified interface for subscribing to
       
  1710  * most events exposed by YUI.  This includes custom events,
       
  1711  * DOM events, and AOP events.  This works the same way as
       
  1712  * the on() function, only it operates after any default
       
  1713  * behavior for the event has executed. @see <code>on</code> for more 
       
  1714  * information.
       
  1715  * @method after
       
  1716  * @param type event type (this parameter does not apply for function events)
       
  1717  * @param fn the callback
       
  1718  * @param target a descriptor for the target (applies to custom events only).
       
  1719  * For function events, this is the object that contains the function to
       
  1720  * execute.
       
  1721  * @param extra 0..n Extra information a particular event may need.  These
       
  1722  * will be documented with the event.  In the case of function events, this
       
  1723  * is the name of the function to execute on the host.  In the case of
       
  1724  * delegate listeners, this is the event delegation specification.
       
  1725  * @param context optionally change the value of 'this' in the callback
       
  1726  * @param args* 0..n additional arguments to pass to the callback.
       
  1727  * @return the event target or a detach handle per 'chain' config
       
  1728  * @for YUI
       
  1729  */
       
  1730 
       
  1731 
       
  1732 }, '3.0.0' ,{requires:['oop']});