src/cm/media/js/lib/yui/yui3.0.0/build/event-custom/event-custom-base.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         var f = fn, a;
       
    61         if (c) {
       
    62             a = [fn, c].concat(Y.Array(arguments, 4, true));
       
    63             f = Y.rbind.apply(Y, a);
       
    64         }
       
    65 
       
    66         return this._inject(BEFORE, f, obj, sFn);
       
    67     },
       
    68 
       
    69     /**
       
    70      * Execute the supplied method after the specified function
       
    71      * @method after
       
    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
       
    77      * @static
       
    78      */
       
    79     after: function(fn, obj, sFn, c) {
       
    80         var f = fn, a;
       
    81         if (c) {
       
    82             a = [fn, c].concat(Y.Array(arguments, 4, true));
       
    83             f = Y.rbind.apply(Y, a);
       
    84         }
       
    85 
       
    86         return this._inject(AFTER, f, obj, sFn);
       
    87     },
       
    88 
       
    89     /**
       
    90      * Execute the supplied method after the specified function
       
    91      * @method _inject
       
    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
       
    98      * @private
       
    99      * @static
       
   100      */
       
   101     _inject: function(when, fn, obj, sFn) {
       
   102 
       
   103         // object id
       
   104         var id = Y.stamp(obj), o, sid;
       
   105 
       
   106         if (! this.objs[id]) {
       
   107             // create a map entry for the obj if it doesn't exist
       
   108             this.objs[id] = {};
       
   109         }
       
   110 
       
   111         o = this.objs[id];
       
   112 
       
   113         if (! o[sFn]) {
       
   114             // create a map entry for the method if it doesn't exist
       
   115             o[sFn] = new Y.Do.Method(obj, sFn);
       
   116 
       
   117             // re-route the method to our wrapper
       
   118             obj[sFn] = 
       
   119                 function() {
       
   120                     return o[sFn].exec.apply(o[sFn], arguments);
       
   121                 };
       
   122         }
       
   123 
       
   124         // subscriber id
       
   125         sid = id + Y.stamp(fn) + sFn;
       
   126 
       
   127         // register the callback
       
   128         o[sFn].register(sid, fn, when);
       
   129 
       
   130         return new Y.EventHandle(o[sFn], sid);
       
   131 
       
   132     },
       
   133 
       
   134     /**
       
   135      * Detach a before or after subscription
       
   136      * @method detach
       
   137      * @param handle {string} the subscription handle
       
   138      */
       
   139     detach: function(handle) {
       
   140 
       
   141         if (handle.detach) {
       
   142             handle.detach();
       
   143         }
       
   144 
       
   145     },
       
   146 
       
   147     _unload: function(e, me) {
       
   148 
       
   149     }
       
   150 };
       
   151 
       
   152 //////////////////////////////////////////////////////////////////////////
       
   153 
       
   154 /**
       
   155  * Wrapper for a displaced method with aop enabled
       
   156  * @class Do.Method
       
   157  * @constructor
       
   158  * @param obj The object to operate on
       
   159  * @param sFn The name of the method to displace
       
   160  */
       
   161 Y.Do.Method = function(obj, sFn) {
       
   162     this.obj = obj;
       
   163     this.methodName = sFn;
       
   164     this.method = obj[sFn];
       
   165     this.before = {};
       
   166     this.after = {};
       
   167 };
       
   168 
       
   169 /**
       
   170  * Register a aop subscriber
       
   171  * @method register
       
   172  * @param sid {string} the subscriber id
       
   173  * @param fn {Function} the function to execute
       
   174  * @param when {string} when to execute the function
       
   175  */
       
   176 Y.Do.Method.prototype.register = function (sid, fn, when) {
       
   177     if (when) {
       
   178         this.after[sid] = fn;
       
   179     } else {
       
   180         this.before[sid] = fn;
       
   181     }
       
   182 };
       
   183 
       
   184 /**
       
   185  * Unregister a aop subscriber
       
   186  * @method delete
       
   187  * @param sid {string} the subscriber id
       
   188  * @param fn {Function} the function to execute
       
   189  * @param when {string} when to execute the function
       
   190  */
       
   191 Y.Do.Method.prototype._delete = function (sid) {
       
   192     delete this.before[sid];
       
   193     delete this.after[sid];
       
   194 };
       
   195 
       
   196 /**
       
   197  * Execute the wrapped method
       
   198  * @method exec
       
   199  */
       
   200 Y.Do.Method.prototype.exec = function () {
       
   201 
       
   202     var args = Y.Array(arguments, 0, true), 
       
   203         i, ret, newRet, 
       
   204         bf = this.before,
       
   205         af = this.after,
       
   206         prevented = false;
       
   207 
       
   208     // execute before
       
   209     for (i in bf) {
       
   210         if (bf.hasOwnProperty(i)) {
       
   211             ret = bf[i].apply(this.obj, args);
       
   212             if (ret) {
       
   213                 switch (ret.constructor) {
       
   214                     case Y.Do.Halt:
       
   215                         return ret.retVal;
       
   216                     case Y.Do.AlterArgs:
       
   217                         args = ret.newArgs;
       
   218                         break;
       
   219                     case Y.Do.Prevent:
       
   220                         prevented = true;
       
   221                         break;
       
   222                     default:
       
   223                 }
       
   224             }
       
   225         }
       
   226     }
       
   227 
       
   228     // execute method
       
   229     if (!prevented) {
       
   230         ret = this.method.apply(this.obj, args);
       
   231     }
       
   232 
       
   233     // execute after methods.
       
   234     for (i in af) {
       
   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;
       
   243             }
       
   244         }
       
   245     }
       
   246 
       
   247     return ret;
       
   248 };
       
   249 
       
   250 //////////////////////////////////////////////////////////////////////////
       
   251 
       
   252 
       
   253 /**
       
   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
       
   258  */
       
   259 Y.Do.AlterArgs = function(msg, newArgs) {
       
   260     this.msg = msg;
       
   261     this.newArgs = newArgs;
       
   262 };
       
   263 
       
   264 /**
       
   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
       
   268  */
       
   269 Y.Do.AlterReturn = function(msg, newRetVal) {
       
   270     this.msg = msg;
       
   271     this.newRetVal = newRetVal;
       
   272 };
       
   273 
       
   274 /**
       
   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.
       
   278  * @class Do.Halt
       
   279  */
       
   280 Y.Do.Halt = function(msg, retVal) {
       
   281     this.msg = msg;
       
   282     this.retVal = retVal;
       
   283 };
       
   284 
       
   285 /**
       
   286  * Return a Prevent object when you want to prevent the wrapped function
       
   287  * from executing, but want the remaining listeners to execute
       
   288  * @class Do.Prevent
       
   289  */
       
   290 Y.Do.Prevent = function(msg) {
       
   291     this.msg = msg;
       
   292 };
       
   293 
       
   294 /**
       
   295  * Return an Error object when you want to terminate the execution
       
   296  * of all subsequent method calls.
       
   297  * @class Do.Error
       
   298  * @deprecated use Y.Do.Halt or Y.Do.Prevent
       
   299  */
       
   300 Y.Do.Error = Y.Do.Halt;
       
   301 
       
   302 //////////////////////////////////////////////////////////////////////////
       
   303 
       
   304 // Y["Event"] && Y.Event.addListener(window, "unload", Y.Do._unload, Y.Do);
       
   305 
       
   306 })();
       
   307 
       
   308 /**
       
   309  * Custom event engine, DOM event listener abstraction layer, synthetic DOM 
       
   310  * events.
       
   311  * @module event-custom
       
   312  * @submodule event-custom-base
       
   313  */
       
   314 
       
   315 /**
       
   316  * Return value from all subscribe operations
       
   317  * @class EventHandle
       
   318  * @constructor
       
   319  * @param evt {CustomEvent} the custom event
       
   320  * @param sub {Subscriber} the subscriber
       
   321  */
       
   322 
       
   323 // var onsubscribeType = "_event:onsub",
       
   324 var AFTER = 'after', 
       
   325     CONFIGS = [
       
   326         'broadcast',
       
   327         'bubbles',
       
   328         'context',
       
   329         'contextFn',
       
   330         'currentTarget',
       
   331         'defaultFn',
       
   332         'details',
       
   333         'emitFacade',
       
   334         'fireOnce',
       
   335         'host',
       
   336         'preventable',
       
   337         'preventedFn',
       
   338         'queuable',
       
   339         'silent',
       
   340         'stoppedFn',
       
   341         'target',
       
   342         'type'
       
   343     ],
       
   344 
       
   345 
       
   346     YUI3_SIGNATURE = 9,
       
   347     YUI_LOG = 'yui:log';
       
   348 
       
   349 Y.EventHandle = function(evt, sub) {
       
   350 
       
   351     /**
       
   352      * The custom event
       
   353      * @type CustomEvent
       
   354      */
       
   355     this.evt = evt;
       
   356 
       
   357     /**
       
   358      * The subscriber object
       
   359      * @type Subscriber
       
   360      */
       
   361     this.sub = sub;
       
   362 };
       
   363 
       
   364 Y.EventHandle.prototype = {
       
   365 
       
   366     /**
       
   367      * Detaches this subscriber
       
   368      * @method detach
       
   369      */
       
   370     detach: function() {
       
   371         var evt = this.evt, i;
       
   372         if (evt) {
       
   373             if (Y.Lang.isArray(evt)) {
       
   374                 for (i=0; i<evt.length; i++) {
       
   375                     evt[i].detach();
       
   376                 }
       
   377             } else { 
       
   378                 evt._delete(this.sub);
       
   379             }
       
   380         }
       
   381     }
       
   382 };
       
   383 
       
   384 /**
       
   385  * The CustomEvent class lets you define events for your application
       
   386  * that can be subscribed to by one or more independent component.
       
   387  *
       
   388  * @param {String}  type The type of event, which is passed to the callback
       
   389  *                  when the event fires
       
   390  * @param o configuration object
       
   391  * @class CustomEvent
       
   392  * @constructor
       
   393  */
       
   394 Y.CustomEvent = function(type, o) {
       
   395 
       
   396     // if (arguments.length > 2) {
       
   397 // this.log('CustomEvent context and silent are now in the config', 'warn', 'Event');
       
   398     // }
       
   399 
       
   400     o = o || {};
       
   401 
       
   402     this.id = Y.stamp(this);
       
   403 
       
   404     /**
       
   405      * The type of event, returned to subscribers when the event fires
       
   406      * @property type
       
   407      * @type string
       
   408      */
       
   409     this.type = type;
       
   410 
       
   411     /**
       
   412      * The context the the event will fire from by default.  Defaults to the YUI
       
   413      * instance.
       
   414      * @property context
       
   415      * @type object
       
   416      */
       
   417     this.context = Y;
       
   418 
       
   419     this.logSystem = (type == YUI_LOG);
       
   420 
       
   421     /**
       
   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
       
   425      * fires.
       
   426      * @property broadcast
       
   427      * @type int
       
   428      */
       
   429     // this.broadcast = 0;
       
   430 
       
   431     /**
       
   432      * By default all custom events are logged in the debug build, set silent
       
   433      * to true to disable debug outpu for this event.
       
   434      * @property silent
       
   435      * @type boolean
       
   436      */
       
   437     this.silent = this.logSystem;
       
   438 
       
   439     /**
       
   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.
       
   443      * @property queuable
       
   444      * @type boolean
       
   445      * @default false
       
   446      */
       
   447     // this.queuable = false;
       
   448 
       
   449     /**
       
   450      * The subscribers to this event
       
   451      * @property subscribers
       
   452      * @type Subscriber{}
       
   453      */
       
   454     this.subscribers = {};
       
   455 
       
   456     /**
       
   457      * 'After' subscribers
       
   458      * @property afters
       
   459      * @type Subscriber{}
       
   460      */
       
   461     this.afters = {};
       
   462 
       
   463     /**
       
   464      * This event has fired if true
       
   465      *
       
   466      * @property fired
       
   467      * @type boolean
       
   468      * @default false;
       
   469      */
       
   470     // this.fired = false;
       
   471 
       
   472     /**
       
   473      * An array containing the arguments the custom event
       
   474      * was last fired with.
       
   475      * @property firedWith
       
   476      * @type Array
       
   477      */
       
   478     // this.firedWith;
       
   479 
       
   480     /**
       
   481      * This event should only fire one time if true, and if
       
   482      * it has fired, any new subscribers should be notified
       
   483      * immediately.
       
   484      *
       
   485      * @property fireOnce
       
   486      * @type boolean
       
   487      * @default false;
       
   488      */
       
   489     // this.fireOnce = false;
       
   490 
       
   491     /**
       
   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.
       
   495      * @property stopped
       
   496      * @type int
       
   497      */
       
   498     // this.stopped = 0;
       
   499 
       
   500     /**
       
   501      * Flag for preventDefault that is modified during fire().
       
   502      * if it is not 0, the default behavior for this event
       
   503      * @property prevented
       
   504      * @type int
       
   505      */
       
   506     // this.prevented = 0;
       
   507 
       
   508     /**
       
   509      * Specifies the host for this custom event.  This is used
       
   510      * to enable event bubbling
       
   511      * @property host
       
   512      * @type EventTarget
       
   513      */
       
   514     // this.host = null;
       
   515 
       
   516     /**
       
   517      * The default function to execute after event listeners
       
   518      * have fire, but only if the default action was not
       
   519      * prevented.
       
   520      * @property defaultFn
       
   521      * @type Function
       
   522      */
       
   523     // this.defaultFn = null;
       
   524 
       
   525     /**
       
   526      * The function to execute if a subscriber calls
       
   527      * stopPropagation or stopImmediatePropagation
       
   528      * @property stoppedFn
       
   529      * @type Function
       
   530      */
       
   531     // this.stoppedFn = null;
       
   532 
       
   533     /**
       
   534      * The function to execute if a subscriber calls
       
   535      * preventDefault
       
   536      * @property preventedFn
       
   537      * @type Function
       
   538      */
       
   539     // this.preventedFn = null;
       
   540 
       
   541     /**
       
   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 
       
   546      * @type boolean 
       
   547      * @default true
       
   548      */
       
   549     this.preventable = true;
       
   550 
       
   551     /**
       
   552      * Specifies whether or not a subscriber can stop the event propagation
       
   553      * via stopPropagation(), stopImmediatePropagation(), or halt()
       
   554      * @property bubbles
       
   555      * @type boolean
       
   556      * @default true
       
   557      */
       
   558     this.bubbles = true;
       
   559 
       
   560     /**
       
   561      * Supports multiple options for listener signatures in order to
       
   562      * port YUI 2 apps.
       
   563      * @property signature
       
   564      * @type int
       
   565      * @default 9
       
   566      */
       
   567     this.signature = YUI3_SIGNATURE;
       
   568 
       
   569     // this.hasSubscribers = false;
       
   570 
       
   571     // this.hasAfters = false;
       
   572 
       
   573     /**
       
   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
       
   577      * @type boolean
       
   578      * @default false
       
   579      */
       
   580     // this.emitFacade = false;
       
   581 
       
   582     this.applyConfig(o, true);
       
   583 
       
   584     // this.log("Creating " + this.type);
       
   585 
       
   586 };
       
   587 
       
   588 Y.CustomEvent.prototype = {
       
   589 
       
   590     /**
       
   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.
       
   596      */
       
   597     applyConfig: function(o, force) {
       
   598         if (o) {
       
   599             Y.mix(this, o, force, CONFIGS);
       
   600         }
       
   601     },
       
   602 
       
   603     _on: function(fn, context, args, when) {
       
   604 
       
   605         if (!fn) {
       
   606             this.log("Invalid callback for CE: " + this.type);
       
   607         }
       
   608 
       
   609         var s = new Y.Subscriber(fn, context, args, when);
       
   610 
       
   611         if (this.fireOnce && this.fired) {
       
   612             Y.later(0, this, Y.bind(this._notify, this, s, this.firedWith));
       
   613         }
       
   614 
       
   615         if (when == AFTER) {
       
   616             this.afters[s.id] = s;
       
   617             this.hasAfters = true;
       
   618         } else {
       
   619             this.subscribers[s.id] = s;
       
   620             this.hasSubscribers = true;
       
   621         }
       
   622 
       
   623         return new Y.EventHandle(this, s);
       
   624 
       
   625     },
       
   626 
       
   627     /**
       
   628      * Listen for this event
       
   629      * @method subscribe
       
   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.
       
   633      * @deprecated use on
       
   634      */
       
   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);
       
   638     },
       
   639 
       
   640     /**
       
   641      * Listen for this event
       
   642      * @method on
       
   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.
       
   646      */
       
   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);
       
   650     },
       
   651 
       
   652     /**
       
   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.
       
   656      * @method after
       
   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.
       
   660      */
       
   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);
       
   664     },
       
   665 
       
   666     /**
       
   667      * Detach listeners.
       
   668      * @method detach 
       
   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.
       
   674      */
       
   675     detach: function(fn, context) {
       
   676         // unsubscribe handle
       
   677         if (fn && fn.detach) {
       
   678             return fn.detach();
       
   679         }
       
   680 
       
   681         var found = 0, subs = this.subscribers, i, s;
       
   682 
       
   683         for (i in subs) {
       
   684             if (subs.hasOwnProperty(i)) {
       
   685                 s = subs[i];
       
   686                 if (s && (!fn || fn === s.fn)) {
       
   687                     this._delete(s);
       
   688                     found++;
       
   689                 }
       
   690             }
       
   691         }
       
   692 
       
   693         return found;
       
   694     },
       
   695 
       
   696     /**
       
   697      * Detach listeners.
       
   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
       
   705      */
       
   706     unsubscribe: function() {
       
   707         return this.detach.apply(this, arguments);
       
   708     },
       
   709 
       
   710 
       
   711     /**
       
   712      * Notify a single subscriber
       
   713      * @method _notify
       
   714      * @param s {Subscriber} the subscriber
       
   715      * @param args {Array} the arguments array to apply to the listener
       
   716      * @private
       
   717      */
       
   718     _notify: function(s, args, ef) {
       
   719 
       
   720         this.log(this.type + "->" + "sub: " +  s.id);
       
   721 
       
   722         var ret;
       
   723 
       
   724         ret = s.notify(args, this);
       
   725 
       
   726         if (false === ret || this.stopped > 1) {
       
   727             this.log(this.type + " cancelled by subscriber");
       
   728             return false;
       
   729         }
       
   730 
       
   731         return true;
       
   732     },
       
   733 
       
   734     /**
       
   735      * Logger abstraction to centralize the application of the silent flag
       
   736      * @method log
       
   737      * @param msg {string} message to log
       
   738      * @param cat {string} log category
       
   739      */
       
   740     log: function(msg, cat) {
       
   741         if (!this.silent) {
       
   742         }
       
   743     },
       
   744 
       
   745     /**
       
   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:
       
   749      *   <ul>
       
   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() 
       
   753      *       method</li>
       
   754      *   </ul>
       
   755      * @method fire 
       
   756      * @param {Object*} arguments an arbitrary set of parameters to pass to 
       
   757      *                            the handler.
       
   758      * @return {boolean} false if one of the subscribers returned false, 
       
   759      *                   true otherwise
       
   760      * 
       
   761      */
       
   762     fire: function() {
       
   763         if (this.fireOnce && this.fired) {
       
   764             this.log('fireOnce event: ' + this.type + ' already fired');
       
   765             return true;
       
   766         } else {
       
   767 
       
   768             var args = Y.Array(arguments, 0, true);
       
   769 
       
   770             this.fired = true;
       
   771             this.firedWith = args;
       
   772 
       
   773             if (this.emitFacade) {
       
   774                 return this.fireComplex(args);
       
   775             } else {
       
   776                 return this.fireSimple(args);
       
   777             }
       
   778         }
       
   779     },
       
   780 
       
   781     fireSimple: function(args) {
       
   782         if (this.hasSubscribers || this.hasAfters) {
       
   783             this._procSubs(Y.merge(this.subscribers, this.afters), args);
       
   784         }
       
   785         this._broadcast(args);
       
   786         return this.stopped ? false : true;
       
   787     },
       
   788 
       
   789     // Requires the event-custom-complex module for full funcitonality.
       
   790     fireComplex: function(args) {
       
   791         args[0] = args[0] || {};
       
   792         return this.fireSimple(args);
       
   793     },
       
   794 
       
   795     _procSubs: function(subs, args, ef) {
       
   796         var s, i;
       
   797         for (i in subs) {
       
   798             if (subs.hasOwnProperty(i)) {
       
   799                 s = subs[i];
       
   800                 if (s && s.fn) {
       
   801                     if (false === this._notify(s, args, ef)) {
       
   802                         this.stopped = 2;
       
   803                     }
       
   804                     if (this.stopped == 2) {
       
   805                         return false;
       
   806                     }
       
   807                 }
       
   808             }
       
   809         }
       
   810 
       
   811         return true;
       
   812     },
       
   813 
       
   814     _broadcast: function(args) {
       
   815         if (!this.stopped && this.broadcast) {
       
   816 
       
   817             var a = Y.Array(args);
       
   818             a.unshift(this.type);
       
   819 
       
   820             if (this.host !== Y) {
       
   821                 Y.fire.apply(Y, a);
       
   822             }
       
   823 
       
   824             if (this.broadcast == 2) {
       
   825                 Y.Global.fire.apply(Y.Global, a);
       
   826             }
       
   827         }
       
   828     },
       
   829 
       
   830     /**
       
   831      * Removes all listeners
       
   832      * @method unsubscribeAll
       
   833      * @return {int} The number of listeners unsubscribed
       
   834      * @deprecated use detachAll
       
   835      */
       
   836     unsubscribeAll: function() {
       
   837         return this.detachAll.apply(this, arguments);
       
   838     },
       
   839 
       
   840     /**
       
   841      * Removes all listeners
       
   842      * @method detachAll
       
   843      * @return {int} The number of listeners unsubscribed
       
   844      */
       
   845     detachAll: function() {
       
   846         return this.detach();
       
   847     },
       
   848 
       
   849     /**
       
   850      * @method _delete
       
   851      * @param subscriber object
       
   852      * @private
       
   853      */
       
   854     _delete: function(s) {
       
   855         if (s) {
       
   856             delete s.fn;
       
   857             delete s.context;
       
   858             delete this.subscribers[s.id];
       
   859             delete this.afters[s.id];
       
   860         }
       
   861     }
       
   862 };
       
   863 
       
   864 /////////////////////////////////////////////////////////////////////
       
   865 
       
   866 /**
       
   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
       
   871  *
       
   872  * @class Subscriber
       
   873  * @constructor
       
   874  */
       
   875 Y.Subscriber = function(fn, context, args) {
       
   876 
       
   877     /**
       
   878      * The callback that will be execute when the event fires
       
   879      * This is wrapped by Y.rbind if obj was supplied.
       
   880      * @property fn
       
   881      * @type Function
       
   882      */
       
   883     this.fn = fn;
       
   884 
       
   885     /**
       
   886      * Optional 'this' keyword for the listener
       
   887      * @property context
       
   888      * @type Object
       
   889      */
       
   890     this.context = context;
       
   891 
       
   892     /**
       
   893      * Unique subscriber id
       
   894      * @property id
       
   895      * @type String
       
   896      */
       
   897     this.id = Y.stamp(this);
       
   898 
       
   899     /**
       
   900      * Additional arguments to propagate to the subscriber
       
   901      * @property args
       
   902      * @type Array
       
   903      */
       
   904     this.args = args;
       
   905 
       
   906     /**
       
   907      * Custom events for a given fire transaction.
       
   908      * @property events
       
   909      * @type {EventTarget}
       
   910      */
       
   911     this.events = null;
       
   912     
       
   913 };
       
   914 
       
   915 Y.Subscriber.prototype = {
       
   916 
       
   917     _notify: function(c, args, ce) {
       
   918         var a = this.args, ret;
       
   919         switch (ce.signature) {
       
   920             case 0:
       
   921                 ret = this.fn.call(c, ce.type, args, c);
       
   922                 break;
       
   923             case 1:
       
   924                 ret = this.fn.call(c, args[0] || null, c);
       
   925                 break;
       
   926             default:
       
   927                 if (a || args) {
       
   928                     args = args || [];
       
   929                     a = (a) ? args.concat(a) : args;
       
   930                     ret = this.fn.apply(c, a);
       
   931                 } else {
       
   932                     ret = this.fn.call(c);
       
   933                 }
       
   934         }
       
   935 
       
   936         return ret;
       
   937     },
       
   938 
       
   939     /**
       
   940      * Executes the subscriber.
       
   941      * @method notify
       
   942      * @param args {Array} Arguments array for the subscriber
       
   943      * @param ce {CustomEvent} The custom event that sent the notification
       
   944      */
       
   945     notify: function(args, ce) {
       
   946         var c = this.context,
       
   947             ret = true;
       
   948 
       
   949         if (!c) {
       
   950             c = (ce.contextFn) ? ce.contextFn() : ce.context;
       
   951         }
       
   952 
       
   953         // only catch errors if we will not re-throw them.
       
   954         if (Y.config.throwFail) {
       
   955             ret = this._notify(c, args, ce);
       
   956         } else {
       
   957             try {
       
   958                 ret = this._notify(c, args, ce);
       
   959             } catch(e) {
       
   960                 Y.error(this + ' failed: ' + e.message, e);
       
   961             }
       
   962         }
       
   963 
       
   964         return ret;
       
   965     },
       
   966 
       
   967     /**
       
   968      * Returns true if the fn and obj match this objects properties.
       
   969      * Used by the unsubscribe method to match the right subscriber.
       
   970      *
       
   971      * @method contains
       
   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.
       
   976      */
       
   977     contains: function(fn, context) {
       
   978         if (context) {
       
   979             return ((this.fn == fn) && this.context == context);
       
   980         } else {
       
   981             return (this.fn == fn);
       
   982         }
       
   983     }
       
   984 
       
   985 };
       
   986 
       
   987 /**
       
   988  * Custom event engine, DOM event listener abstraction layer, synthetic DOM 
       
   989  * events.
       
   990  * @module event-custom
       
   991  * @submodule event-custom-base
       
   992  */
       
   993 (function() {
       
   994 
       
   995 /**
       
   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)
       
  1012  */
       
  1013 
       
  1014 var L = Y.Lang,
       
  1015     PREFIX_DELIMITER = ':',
       
  1016     CATEGORY_DELIMITER = '|',
       
  1017     AFTER_PREFIX = '~AFTER~',
       
  1018 
       
  1019     /**
       
  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.
       
  1023      * @method _getType
       
  1024      * @private
       
  1025      */
       
  1026     _getType = Y.cached(function(type, pre) {
       
  1027 
       
  1028         if (!pre || !L.isString(type) || type.indexOf(PREFIX_DELIMITER) > -1) {
       
  1029             return type;
       
  1030         } 
       
  1031 
       
  1032         return pre + PREFIX_DELIMITER + type;
       
  1033     }),
       
  1034 
       
  1035     /**
       
  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
       
  1040      * @private
       
  1041      */
       
  1042     _parseType = Y.cached(function(type, pre) {
       
  1043 
       
  1044         var t = type, detachcategory, after, i;
       
  1045 
       
  1046         if (!L.isString(t)) {
       
  1047             return t;
       
  1048         } 
       
  1049         
       
  1050         i = t.indexOf(AFTER_PREFIX);
       
  1051 
       
  1052         if (i > -1) {
       
  1053             after = true;
       
  1054             t = t.substr(AFTER_PREFIX.length);
       
  1055         }
       
  1056 
       
  1057         i = t.indexOf(CATEGORY_DELIMITER);
       
  1058 
       
  1059         if (i > -1) {
       
  1060             detachcategory = t.substr(0, (i));
       
  1061             t = t.substr(i+1);
       
  1062             if (t == '*') {
       
  1063                 t = null;
       
  1064             }
       
  1065         }
       
  1066 
       
  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];
       
  1069     }),
       
  1070 
       
  1071     ET = function(opts) {
       
  1072 
       
  1073 
       
  1074         var o = (L.isObject(opts)) ? opts : {};
       
  1075 
       
  1076         this._yuievt = this._yuievt || {
       
  1077 
       
  1078             id: Y.guid(),
       
  1079 
       
  1080             events: {},
       
  1081 
       
  1082             targets: {},
       
  1083 
       
  1084             config: o,
       
  1085 
       
  1086             chain: ('chain' in o) ? o.chain : Y.config.chain,
       
  1087 
       
  1088             defaults: {
       
  1089                 context: o.context || this, 
       
  1090                 host: 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
       
  1096             }
       
  1097         };
       
  1098 
       
  1099     };
       
  1100 
       
  1101 
       
  1102 ET.prototype = {
       
  1103 
       
  1104     /**
       
  1105      * Subscribe to a custom event hosted by this object
       
  1106      * @method on 
       
  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
       
  1110      */
       
  1111     on: function(type, fn, context, x) {
       
  1112 
       
  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;
       
  1116 
       
  1117         if (L.isObject(type)) {
       
  1118 
       
  1119             if (L.isFunction(type)) {
       
  1120                 return Y.Do.before.apply(Y.Do, arguments);
       
  1121             }
       
  1122 
       
  1123             f = fn; 
       
  1124             c = context; 
       
  1125             args = Y.Array(arguments, 0, true);
       
  1126             ret = {};
       
  1127             after = type._after;
       
  1128             delete type._after;
       
  1129 
       
  1130             Y.each(type, function(v, k) {
       
  1131 
       
  1132                 if (v) {
       
  1133                     f = v.fn || ((Y.Lang.isFunction(v)) ? v : f);
       
  1134                     c = v.context || c;
       
  1135                 }
       
  1136 
       
  1137                 args[0] = (after) ? AFTER_PREFIX + k : k;
       
  1138                 args[1] = f;
       
  1139                 args[2] = c;
       
  1140 
       
  1141                 ret[k] = this.on.apply(this, args); 
       
  1142 
       
  1143             }, this);
       
  1144 
       
  1145             return (this._yuievt.chain) ? this : new Y.EventHandle(ret);
       
  1146 
       
  1147         }
       
  1148         
       
  1149         detachcategory = parts[0];
       
  1150         after = parts[2];
       
  1151         shorttype = parts[3];
       
  1152 
       
  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);
       
  1158         }
       
  1159 
       
  1160         type = parts[1];
       
  1161 
       
  1162         if (this instanceof YUI) {
       
  1163 
       
  1164             adapt = Y.Env.evt.plugins[type];
       
  1165             args  = Y.Array(arguments, 0, true);
       
  1166             args[0] = shorttype;
       
  1167 
       
  1168             if (Node) {
       
  1169                 n = args[2];
       
  1170 
       
  1171                 if (n instanceof Y.NodeList) {
       
  1172                     n = Y.NodeList.getDOMNodes(n);
       
  1173                 } else if (n instanceof Node) {
       
  1174                     n = Node.getDOMNode(n);
       
  1175                 }
       
  1176 
       
  1177                 domevent = (shorttype in Node.DOM_EVENTS);
       
  1178 
       
  1179                 // Captures both DOM events and event plugins.
       
  1180                 if (domevent) {
       
  1181                     args[2] = n;
       
  1182                 }
       
  1183             }
       
  1184 
       
  1185             // check for the existance of an event adaptor
       
  1186             if (adapt) {
       
  1187                 handle = adapt.on.apply(Y, args);
       
  1188             } else if ((!type) || domevent) {
       
  1189                 handle = Y.Event._attach(args);
       
  1190             }
       
  1191 
       
  1192         } 
       
  1193 
       
  1194         if (!handle) {
       
  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);
       
  1197         }
       
  1198 
       
  1199         if (detachcategory) {
       
  1200             store[detachcategory] = store[detachcategory] || {};
       
  1201             store[detachcategory][type] = store[detachcategory][type] || [];
       
  1202             store[detachcategory][type].push(handle);
       
  1203         }
       
  1204 
       
  1205         return (this._yuievt.chain) ? this : handle;
       
  1206 
       
  1207     },
       
  1208 
       
  1209     /**
       
  1210      * subscribe to an event
       
  1211      * @method subscribe
       
  1212      * @deprecated use on
       
  1213      */
       
  1214     subscribe: function() {
       
  1215         return this.on.apply(this, arguments);
       
  1216     },
       
  1217 
       
  1218     /**
       
  1219      * Detach one or more listeners the from the specified event
       
  1220      * @method detach 
       
  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
       
  1233      */
       
  1234     detach: function(type, fn, context) {
       
  1235         var evts = this._yuievt.events, i, ret,
       
  1236             Node = Y.Node, isNode = (this instanceof Node);
       
  1237 
       
  1238         // detachAll disabled on the Y instance.
       
  1239         if (!type && (this !== Y)) {
       
  1240             for (i in evts) {
       
  1241                 if (evts.hasOwnProperty(i)) {
       
  1242                     ret = evts[i].detach(fn, context);
       
  1243                 }
       
  1244             }
       
  1245             if (isNode) {
       
  1246 
       
  1247                 Y.Event.purgeElement(Node.getDOMNode(this));
       
  1248             }
       
  1249 
       
  1250             return ret;
       
  1251         }
       
  1252 
       
  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,
       
  1257         ce,
       
  1258 
       
  1259         keyDetacher = function(lcat, ltype) {
       
  1260             var handles = lcat[ltype];
       
  1261             if (handles) {
       
  1262                 while (handles.length) {
       
  1263                     handle = handles.pop();
       
  1264                     handle.detach();
       
  1265                 }
       
  1266             }
       
  1267         };
       
  1268 
       
  1269         if (detachcategory) {
       
  1270 
       
  1271             cat = store[detachcategory];
       
  1272             type = parts[1];
       
  1273 
       
  1274             if (cat) {
       
  1275                 if (type) {
       
  1276                     keyDetacher(cat, type);
       
  1277                 } else {
       
  1278                     for (i in cat) {
       
  1279                         if (cat.hasOwnProperty(i)) {
       
  1280                             keyDetacher(cat, i);
       
  1281                         }
       
  1282                     }
       
  1283                 }
       
  1284 
       
  1285                 return (this._yuievt.chain) ? this : true;
       
  1286             }
       
  1287 
       
  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);
       
  1297         }
       
  1298 
       
  1299         adapt = Y.Env.evt.plugins[shorttype];
       
  1300 
       
  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);
       
  1307             // DOM event fork
       
  1308             } else if (!type || (!adapt && Node && (type in Node.DOM_EVENTS))) {
       
  1309                 args[0] = type;
       
  1310                 return Y.Event.detach.apply(Y.Event, args);
       
  1311             }
       
  1312         }
       
  1313 
       
  1314         ce = evts[type];
       
  1315         if (ce) {
       
  1316             ret = ce.detach(fn, context);
       
  1317         }
       
  1318 
       
  1319         return (this._yuievt.chain) ? this : ret;
       
  1320     },
       
  1321 
       
  1322     /**
       
  1323      * detach a listener
       
  1324      * @method unsubscribe
       
  1325      * @deprecated use detach
       
  1326      */
       
  1327     unsubscribe: function() {
       
  1328         return this.detach.apply(this, arguments);
       
  1329     },
       
  1330     
       
  1331     /**
       
  1332      * Removes all listeners from the specified event.  If the event type
       
  1333      * is not specified, all listeners from all hosted custom events will
       
  1334      * be removed.
       
  1335      * @method detachAll
       
  1336      * @param type {string}   The type, or name of the event
       
  1337      */
       
  1338     detachAll: function(type) {
       
  1339         return this.detach(type);
       
  1340     },
       
  1341 
       
  1342     /**
       
  1343      * Removes all listeners from the specified event.  If the event type
       
  1344      * is not specified, all listeners from all hosted custom events will
       
  1345      * be removed.
       
  1346      * @method unsubscribeAll
       
  1347      * @param type {string}   The type, or name of the event
       
  1348      * @deprecated use detachAll
       
  1349      */
       
  1350     unsubscribeAll: function() {
       
  1351         return this.detachAll.apply(this, arguments);
       
  1352     },
       
  1353 
       
  1354     /**
       
  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. 
       
  1358      *
       
  1359      * @method publish
       
  1360      *
       
  1361      * @param type {string} the type, or name of the event
       
  1362      * @param opts {object} optional config params.  Valid properties are:
       
  1363      *
       
  1364      *  <ul>
       
  1365      *    <li>
       
  1366      *   'broadcast': whether or not the YUI instance and YUI global are notified when the event is fired (false)
       
  1367      *    </li>
       
  1368      *    <li>
       
  1369      *   'bubbles': whether or not this event bubbles (true)
       
  1370      *    </li>
       
  1371      *    <li>
       
  1372      *   'context': the default execution context for the listeners (this)
       
  1373      *    </li>
       
  1374      *    <li>
       
  1375      *   'defaultFn': the default function to execute when this event fires if preventDefault was not called
       
  1376      *    </li>
       
  1377      *    <li>
       
  1378      *   'emitFacade': whether or not this event emits a facade (false)
       
  1379      *    </li>
       
  1380      *    <li>
       
  1381      *   'prefix': the prefix for this targets events, e.g., 'menu' in 'menu:click' 
       
  1382      *    </li>
       
  1383      *    <li>
       
  1384      *   'fireOnce': if an event is configured to fire once, new subscribers after
       
  1385      *   the fire will be notified immediately.
       
  1386      *    </li>
       
  1387      *    <li>
       
  1388      *   'preventable': whether or not preventDefault() has an effect (true)
       
  1389      *    </li>
       
  1390      *    <li>
       
  1391      *   'preventedFn': a function that is executed when preventDefault is called
       
  1392      *    </li>
       
  1393      *    <li>
       
  1394      *   'queuable': whether or not this event can be queued during bubbling (false)
       
  1395      *    </li>
       
  1396      *    <li>
       
  1397      *   'silent': if silent is true, debug messages are not provided for this event.
       
  1398      *    </li>
       
  1399      *    <li>
       
  1400      *   'stoppedFn': a function that is executed when stopPropagation is called
       
  1401      *    </li>
       
  1402      *    <li>
       
  1403      *   'type': the event type (valid option if not provided as the first parameter to publish)
       
  1404      *    </li>
       
  1405      *  </ul>
       
  1406      *
       
  1407      *  @return {Event.Custom} the custom event
       
  1408      *
       
  1409      */
       
  1410     publish: function(type, opts) {
       
  1411         var events, ce, ret, pre = this._yuievt.config.prefix;
       
  1412 
       
  1413         type = (pre) ? _getType(type, pre) : type;
       
  1414 
       
  1415 
       
  1416         if (L.isObject(type)) {
       
  1417             ret = {};
       
  1418             Y.each(type, function(v, k) {
       
  1419                 ret[k] = this.publish(k, v || opts); 
       
  1420             }, this);
       
  1421 
       
  1422             return ret;
       
  1423         }
       
  1424 
       
  1425         events = this._yuievt.events; 
       
  1426         ce = events[type];
       
  1427 
       
  1428         if (ce) {
       
  1429 // ce.log("publish applying new config to published event: '"+type+"' exists", 'info', 'event');
       
  1430             if (opts) {
       
  1431                 ce.applyConfig(opts, true);
       
  1432             }
       
  1433         } else {
       
  1434             // apply defaults
       
  1435             ce = new Y.CustomEvent(type, (opts) ? Y.mix(opts, this._yuievt.defaults) : this._yuievt.defaults);
       
  1436             events[type] = ce;
       
  1437         }
       
  1438 
       
  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;
       
  1443         // }
       
  1444 
       
  1445         return events[type];
       
  1446     },
       
  1447 
       
  1448     /**
       
  1449      * Registers another EventTarget as a bubble target.  Bubble order
       
  1450      * is determined by the order registered.  Multiple targets can
       
  1451      * be specified.
       
  1452      * @method addTarget
       
  1453      * @param o {EventTarget} the target to add
       
  1454      */
       
  1455     addTarget: function(o) {
       
  1456         this._yuievt.targets[Y.stamp(o)] = o;
       
  1457         this._yuievt.hasTargets = true;
       
  1458     },
       
  1459 
       
  1460     /**
       
  1461      * Removes a bubble target
       
  1462      * @method removeTarget
       
  1463      * @param o {EventTarget} the target to remove
       
  1464      */
       
  1465     removeTarget: function(o) {
       
  1466         delete this._yuievt.targets[Y.stamp(o)];
       
  1467     },
       
  1468 
       
  1469    /**
       
  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.
       
  1473      *
       
  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.
       
  1479      *
       
  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.
       
  1485      *
       
  1486      * @method fire
       
  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
       
  1493      * the event facade.
       
  1494      * @return {Event.Target} the event host
       
  1495      *                   
       
  1496      */
       
  1497     fire: function(type) {
       
  1498 
       
  1499         var typeIncluded = L.isString(type),
       
  1500             t = (typeIncluded) ? type : (type && type.type),
       
  1501             ce, a, ret, pre=this._yuievt.config.prefix;
       
  1502 
       
  1503         t = (pre) ? _getType(t, pre) : t;
       
  1504         ce = this.getEvent(t, true);
       
  1505 
       
  1506         // this event has not been published or subscribed to
       
  1507         if (!ce) {
       
  1508             
       
  1509             if (this._yuievt.hasTargets) {
       
  1510                 a = (typeIncluded) ? arguments : Y.Array(arguments, 0, true).unshift(t);
       
  1511                 return this.bubble(null, a, this);
       
  1512             }
       
  1513 
       
  1514             // otherwise there is nothing to be done
       
  1515             ret = true;
       
  1516 
       
  1517         } else {
       
  1518 
       
  1519             a = Y.Array(arguments, (typeIncluded) ? 1 : 0, true);
       
  1520             ret = ce.fire.apply(ce, a);
       
  1521 
       
  1522             // clear target for next fire()
       
  1523             ce.target = null;
       
  1524         }
       
  1525 
       
  1526         return (this._yuievt.chain) ? this : ret;
       
  1527     },
       
  1528 
       
  1529     /**
       
  1530      * Returns the custom event of the provided type has been created, a
       
  1531      * falsy value otherwise
       
  1532      * @method getEvent
       
  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
       
  1536      */
       
  1537     getEvent: function(type, prefixed) {
       
  1538         var pre, e;
       
  1539         if (!prefixed) {
       
  1540             pre = this._yuievt.config.prefix;
       
  1541             type = (pre) ? _getType(type, pre) : type;
       
  1542         }
       
  1543         e = this._yuievt.events;
       
  1544         return (e && type in e) ? e[type] : null;
       
  1545     },
       
  1546 
       
  1547     /**
       
  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.
       
  1552      * @method after
       
  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
       
  1556      */
       
  1557     after: function(type, fn) {
       
  1558 
       
  1559         var a = Y.Array(arguments, 0, true);
       
  1560 
       
  1561         switch (L.type(type)) {
       
  1562             case 'function':
       
  1563                 return Y.Do.after.apply(Y.Do, arguments);
       
  1564             case 'object':
       
  1565                 a[0]._after = true;
       
  1566                 break;
       
  1567             default:
       
  1568                 a[0] = AFTER_PREFIX + type;
       
  1569         }
       
  1570 
       
  1571         return this.on.apply(this, a);
       
  1572 
       
  1573     },
       
  1574 
       
  1575     /**
       
  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.
       
  1580      *
       
  1581      * For DOM and custom events:
       
  1582      * type, callback, context, 0-n arguments
       
  1583      *  
       
  1584      * For methods:
       
  1585      * callback, object (method host), methodName, context, 0-n arguments
       
  1586      *
       
  1587      * @method before
       
  1588      * @return detach handle
       
  1589      * @deprecated use the on method
       
  1590      */
       
  1591     before: function() { 
       
  1592         return this.on.apply(this, arguments);
       
  1593     }
       
  1594 
       
  1595 };
       
  1596 
       
  1597 Y.EventTarget = ET;
       
  1598 
       
  1599 // make Y an event target
       
  1600 Y.mix(Y, ET.prototype, false, false, { 
       
  1601     bubbles: false 
       
  1602 });
       
  1603 
       
  1604 ET.call(Y);
       
  1605 
       
  1606 YUI.Env.globalEvents = YUI.Env.globalEvents || new ET();
       
  1607 
       
  1608 /**
       
  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.
       
  1612  * @property Global
       
  1613  * @type EventTarget
       
  1614  * @for YUI
       
  1615  */
       
  1616 Y.Global = YUI.Env.globalEvents;
       
  1617 
       
  1618 // @TODO implement a global namespace function on Y.Global?
       
  1619 
       
  1620 })();
       
  1621 
       
  1622 
       
  1623 /**
       
  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.
       
  1628  *
       
  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.
       
  1633  *
       
  1634  * <ul>
       
  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.
       
  1638  *   <ul>
       
  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>
       
  1643  *   </ul>
       
  1644  *   Example: 
       
  1645  *   <code>Y.on('domready', function() { // start work });</code>
       
  1646  * </li>
       
  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.
       
  1651  *   <ul>
       
  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
       
  1656  *     refereces.</li>
       
  1657  *     <li>An optional context object</li>
       
  1658  *     <li>0..n additional arguments to supply the callback.</li>
       
  1659  *   </ul>
       
  1660  *   Example: 
       
  1661  *   <code>Y.on('click', function(e) { // something was clicked }, '#someelement');</code>
       
  1662  * </li>
       
  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.
       
  1666  *   <ul>
       
  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>
       
  1672  *   </ul>
       
  1673  *   Example <code>Y.on(function(arg1, arg2, etc) { // obj.methodname was executed }, obj 'methodname');</code>
       
  1674  * </li>
       
  1675  * </ul>
       
  1676  *
       
  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>.
       
  1681  *
       
  1682  * @method on 
       
  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
       
  1687  * execute.
       
  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
       
  1695  * @for YUI
       
  1696  */
       
  1697 
       
  1698 /**
       
  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 
       
  1704  * information.
       
  1705  * @method after
       
  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
       
  1710  * execute.
       
  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
       
  1718  * @for YUI
       
  1719  */
       
  1720 
       
  1721 
       
  1722 }, '3.0.0' ,{requires:['oop']});