src/cm/media/js/lib/yui/yui_3.10.3/build/event-synthetic/event-synthetic-debug.js
changeset 525 89ef5ed3c48b
equal deleted inserted replaced
524:322d0feea350 525:89ef5ed3c48b
       
     1 /*
       
     2 YUI 3.10.3 (build 2fb5187)
       
     3 Copyright 2013 Yahoo! Inc. All rights reserved.
       
     4 Licensed under the BSD License.
       
     5 http://yuilibrary.com/license/
       
     6 */
       
     7 
       
     8 YUI.add('event-synthetic', function (Y, NAME) {
       
     9 
       
    10 /**
       
    11  * Define new DOM events that can be subscribed to from Nodes.
       
    12  *
       
    13  * @module event
       
    14  * @submodule event-synthetic
       
    15  */
       
    16 var CustomEvent = Y.CustomEvent,
       
    17     DOMMap   = Y.Env.evt.dom_map,
       
    18     toArray  = Y.Array,
       
    19     YLang    = Y.Lang,
       
    20     isObject = YLang.isObject,
       
    21     isString = YLang.isString,
       
    22     isArray  = YLang.isArray,
       
    23     query    = Y.Selector.query,
       
    24     noop     = function () {};
       
    25 
       
    26 /**
       
    27  * <p>The triggering mechanism used by SyntheticEvents.</p>
       
    28  *
       
    29  * <p>Implementers should not instantiate these directly.  Use the Notifier
       
    30  * provided to the event's implemented <code>on(node, sub, notifier)</code> or
       
    31  * <code>delegate(node, sub, notifier, filter)</code> methods.</p>
       
    32  *
       
    33  * @class SyntheticEvent.Notifier
       
    34  * @constructor
       
    35  * @param handle {EventHandle} the detach handle for the subscription to an
       
    36  *              internal custom event used to execute the callback passed to
       
    37  *              on(..) or delegate(..)
       
    38  * @param emitFacade {Boolean} take steps to ensure the first arg received by
       
    39  *              the subscription callback is an event facade
       
    40  * @private
       
    41  * @since 3.2.0
       
    42  */
       
    43 function Notifier(handle, emitFacade) {
       
    44     this.handle     = handle;
       
    45     this.emitFacade = emitFacade;
       
    46 }
       
    47 
       
    48 /**
       
    49  * <p>Executes the subscription callback, passing the firing arguments as the
       
    50  * first parameters to that callback. For events that are configured with
       
    51  * emitFacade=true, it is common practice to pass the triggering DOMEventFacade
       
    52  * as the first parameter.  Barring a proper DOMEventFacade or EventFacade
       
    53  * (from a CustomEvent), a new EventFacade will be generated.  In that case, if
       
    54  * fire() is called with a simple object, it will be mixed into the facade.
       
    55  * Otherwise, the facade will be prepended to the callback parameters.</p>
       
    56  *
       
    57  * <p>For notifiers provided to delegate logic, the first argument should be an
       
    58  * object with a &quot;currentTarget&quot; property to identify what object to
       
    59  * default as 'this' in the callback.  Typically this is gleaned from the
       
    60  * DOMEventFacade or EventFacade, but if configured with emitFacade=false, an
       
    61  * object must be provided.  In that case, the object will be removed from the
       
    62  * callback parameters.</p>
       
    63  *
       
    64  * <p>Additional arguments passed during event subscription will be
       
    65  * automatically added after those passed to fire().</p>
       
    66  *
       
    67  * @method fire
       
    68  * @param e {EventFacade|DOMEventFacade|Object|any} (see description)
       
    69  * @param arg* {any} additional arguments received by all subscriptions
       
    70  * @private
       
    71  */
       
    72 Notifier.prototype.fire = function (e) {
       
    73     // first arg to delegate notifier should be an object with currentTarget
       
    74     var args     = toArray(arguments, 0, true),
       
    75         handle   = this.handle,
       
    76         ce       = handle.evt,
       
    77         sub      = handle.sub,
       
    78         thisObj  = sub.context,
       
    79         delegate = sub.filter,
       
    80         event    = e || {},
       
    81         ret;
       
    82 
       
    83     if (this.emitFacade) {
       
    84         if (!e || !e.preventDefault) {
       
    85             event = ce._getFacade();
       
    86 
       
    87             if (isObject(e) && !e.preventDefault) {
       
    88                 Y.mix(event, e, true);
       
    89                 args[0] = event;
       
    90             } else {
       
    91                 args.unshift(event);
       
    92             }
       
    93         }
       
    94 
       
    95         event.type    = ce.type;
       
    96         event.details = args.slice();
       
    97 
       
    98         if (delegate) {
       
    99             event.container = ce.host;
       
   100         }
       
   101     } else if (delegate && isObject(e) && e.currentTarget) {
       
   102         args.shift();
       
   103     }
       
   104 
       
   105     sub.context = thisObj || event.currentTarget || ce.host;
       
   106     ret = ce.fire.apply(ce, args);
       
   107     sub.context = thisObj; // reset for future firing
       
   108 
       
   109     // to capture callbacks that return false to stopPropagation.
       
   110     // Useful for delegate implementations
       
   111     return ret;
       
   112 };
       
   113 
       
   114 /**
       
   115  * Manager object for synthetic event subscriptions to aggregate multiple synths on the
       
   116  * same node without colliding with actual DOM subscription entries in the global map of
       
   117  * DOM subscriptions.  Also facilitates proper cleanup on page unload.
       
   118  *
       
   119  * @class SynthRegistry
       
   120  * @constructor
       
   121  * @param el {HTMLElement} the DOM element
       
   122  * @param yuid {String} the yuid stamp for the element
       
   123  * @param key {String} the generated id token used to identify an event type +
       
   124  *                     element in the global DOM subscription map.
       
   125  * @private
       
   126  */
       
   127 function SynthRegistry(el, yuid, key) {
       
   128     this.handles = [];
       
   129     this.el      = el;
       
   130     this.key     = key;
       
   131     this.domkey  = yuid;
       
   132 }
       
   133 
       
   134 SynthRegistry.prototype = {
       
   135     constructor: SynthRegistry,
       
   136 
       
   137     // A few object properties to fake the CustomEvent interface for page
       
   138     // unload cleanup.  DON'T TOUCH!
       
   139     type      : '_synth',
       
   140     fn        : noop,
       
   141     capture   : false,
       
   142 
       
   143     /**
       
   144      * Adds a subscription from the Notifier registry.
       
   145      *
       
   146      * @method register
       
   147      * @param handle {EventHandle} the subscription
       
   148      * @since 3.4.0
       
   149      */
       
   150     register: function (handle) {
       
   151         handle.evt.registry = this;
       
   152         this.handles.push(handle);
       
   153     },
       
   154 
       
   155     /**
       
   156      * Removes the subscription from the Notifier registry.
       
   157      *
       
   158      * @method _unregisterSub
       
   159      * @param sub {Subscription} the subscription
       
   160      * @since 3.4.0
       
   161      */
       
   162     unregister: function (sub) {
       
   163         var handles = this.handles,
       
   164             events = DOMMap[this.domkey],
       
   165             i;
       
   166 
       
   167         for (i = handles.length - 1; i >= 0; --i) {
       
   168             if (handles[i].sub === sub) {
       
   169                 handles.splice(i, 1);
       
   170                 break;
       
   171             }
       
   172         }
       
   173 
       
   174         // Clean up left over objects when there are no more subscribers.
       
   175         if (!handles.length) {
       
   176             delete events[this.key];
       
   177             if (!Y.Object.size(events)) {
       
   178                 delete DOMMap[this.domkey];
       
   179             }
       
   180         }
       
   181     },
       
   182 
       
   183     /**
       
   184      * Used by the event system's unload cleanup process.  When navigating
       
   185      * away from the page, the event system iterates the global map of element
       
   186      * subscriptions and detaches everything using detachAll().  Normally,
       
   187      * the map is populated with custom events, so this object needs to
       
   188      * at least support the detachAll method to duck type its way to
       
   189      * cleanliness.
       
   190      *
       
   191      * @method detachAll
       
   192      * @private
       
   193      * @since 3.4.0
       
   194      */
       
   195     detachAll : function () {
       
   196         var handles = this.handles,
       
   197             i = handles.length;
       
   198 
       
   199         while (--i >= 0) {
       
   200             handles[i].detach();
       
   201         }
       
   202     }
       
   203 };
       
   204 
       
   205 /**
       
   206  * <p>Wrapper class for the integration of new events into the YUI event
       
   207  * infrastructure.  Don't instantiate this object directly, use
       
   208  * <code>Y.Event.define(type, config)</code>.  See that method for details.</p>
       
   209  *
       
   210  * <p>Properties that MAY or SHOULD be specified in the configuration are noted
       
   211  * below and in the description of <code>Y.Event.define</code>.</p>
       
   212  *
       
   213  * @class SyntheticEvent
       
   214  * @constructor
       
   215  * @param cfg {Object} Implementation pieces and configuration
       
   216  * @since 3.1.0
       
   217  * @in event-synthetic
       
   218  */
       
   219 function SyntheticEvent() {
       
   220     this._init.apply(this, arguments);
       
   221 }
       
   222 
       
   223 Y.mix(SyntheticEvent, {
       
   224     Notifier: Notifier,
       
   225     SynthRegistry: SynthRegistry,
       
   226 
       
   227     /**
       
   228      * Returns the array of subscription handles for a node for the given event
       
   229      * type.  Passing true as the third argument will create a registry entry
       
   230      * in the event system's DOM map to host the array if one doesn't yet exist.
       
   231      *
       
   232      * @method getRegistry
       
   233      * @param node {Node} the node
       
   234      * @param type {String} the event
       
   235      * @param create {Boolean} create a registration entry to host a new array
       
   236      *                  if one doesn't exist.
       
   237      * @return {Array}
       
   238      * @static
       
   239      * @protected
       
   240      * @since 3.2.0
       
   241      */
       
   242     getRegistry: function (node, type, create) {
       
   243         var el     = node._node,
       
   244             yuid   = Y.stamp(el),
       
   245             key    = 'event:' + yuid + type + '_synth',
       
   246             events = DOMMap[yuid];
       
   247 
       
   248         if (create) {
       
   249             if (!events) {
       
   250                 events = DOMMap[yuid] = {};
       
   251             }
       
   252             if (!events[key]) {
       
   253                 events[key] = new SynthRegistry(el, yuid, key);
       
   254             }
       
   255         }
       
   256 
       
   257         return (events && events[key]) || null;
       
   258     },
       
   259 
       
   260     /**
       
   261      * Alternate <code>_delete()</code> method for the CustomEvent object
       
   262      * created to manage SyntheticEvent subscriptions.
       
   263      *
       
   264      * @method _deleteSub
       
   265      * @param sub {Subscription} the subscription to clean up
       
   266      * @private
       
   267      * @since 3.2.0
       
   268      */
       
   269     _deleteSub: function (sub) {
       
   270         if (sub && sub.fn) {
       
   271             var synth = this.eventDef,
       
   272                 method = (sub.filter) ? 'detachDelegate' : 'detach';
       
   273 
       
   274             this._subscribers = [];
       
   275 
       
   276             if (CustomEvent.keepDeprecatedSubs) {
       
   277                 this.subscribers = {};
       
   278             }
       
   279 
       
   280             synth[method](sub.node, sub, this.notifier, sub.filter);
       
   281             this.registry.unregister(sub);
       
   282 
       
   283             delete sub.fn;
       
   284             delete sub.node;
       
   285             delete sub.context;
       
   286         }
       
   287     },
       
   288 
       
   289     prototype: {
       
   290         constructor: SyntheticEvent,
       
   291 
       
   292         /**
       
   293          * Construction logic for the event.
       
   294          *
       
   295          * @method _init
       
   296          * @protected
       
   297          */
       
   298         _init: function () {
       
   299             var config = this.publishConfig || (this.publishConfig = {});
       
   300 
       
   301             // The notification mechanism handles facade creation
       
   302             this.emitFacade = ('emitFacade' in config) ?
       
   303                                 config.emitFacade :
       
   304                                 true;
       
   305             config.emitFacade  = false;
       
   306         },
       
   307 
       
   308         /**
       
   309          * <p>Implementers MAY provide this method definition.</p>
       
   310          *
       
   311          * <p>Implement this function if the event supports a different
       
   312          * subscription signature.  This function is used by both
       
   313          * <code>on()</code> and <code>delegate()</code>.  The second parameter
       
   314          * indicates that the event is being subscribed via
       
   315          * <code>delegate()</code>.</p>
       
   316          *
       
   317          * <p>Implementations must remove extra arguments from the args list
       
   318          * before returning.  The required args for <code>on()</code>
       
   319          * subscriptions are</p>
       
   320          * <pre><code>[type, callback, target, context, argN...]</code></pre>
       
   321          *
       
   322          * <p>The required args for <code>delegate()</code>
       
   323          * subscriptions are</p>
       
   324          *
       
   325          * <pre><code>[type, callback, target, filter, context, argN...]</code></pre>
       
   326          *
       
   327          * <p>The return value from this function will be stored on the
       
   328          * subscription in the '_extra' property for reference elsewhere.</p>
       
   329          *
       
   330          * @method processArgs
       
   331          * @param args {Array} parmeters passed to Y.on(..) or Y.delegate(..)
       
   332          * @param delegate {Boolean} true if the subscription is from Y.delegate
       
   333          * @return {any}
       
   334          */
       
   335         processArgs: noop,
       
   336 
       
   337         /**
       
   338          * <p>Implementers MAY override this property.</p>
       
   339          *
       
   340          * <p>Whether to prevent multiple subscriptions to this event that are
       
   341          * classified as being the same.  By default, this means the subscribed
       
   342          * callback is the same function.  See the <code>subMatch</code>
       
   343          * method.  Setting this to true will impact performance for high volume
       
   344          * events.</p>
       
   345          *
       
   346          * @property preventDups
       
   347          * @type {Boolean}
       
   348          * @default false
       
   349          */
       
   350         //preventDups  : false,
       
   351 
       
   352         /**
       
   353          * <p>Implementers SHOULD provide this method definition.</p>
       
   354          *
       
   355          * Implementation logic for subscriptions done via <code>node.on(type,
       
   356          * fn)</code> or <code>Y.on(type, fn, target)</code>.  This
       
   357          * function should set up the monitor(s) that will eventually fire the
       
   358          * event.  Typically this involves subscribing to at least one DOM
       
   359          * event.  It is recommended to store detach handles from any DOM
       
   360          * subscriptions to make for easy cleanup in the <code>detach</code>
       
   361          * method.  Typically these handles are added to the <code>sub</code>
       
   362          * object.  Also for SyntheticEvents that leverage a single DOM
       
   363          * subscription under the hood, it is recommended to pass the DOM event
       
   364          * object to <code>notifier.fire(e)</code>.  (The event name on the
       
   365          * object will be updated).
       
   366          *
       
   367          * @method on
       
   368          * @param node {Node} the node the subscription is being applied to
       
   369          * @param sub {Subscription} the object to track this subscription
       
   370          * @param notifier {SyntheticEvent.Notifier} call notifier.fire(..) to
       
   371          *              trigger the execution of the subscribers
       
   372          */
       
   373         on: noop,
       
   374 
       
   375         /**
       
   376          * <p>Implementers SHOULD provide this method definition.</p>
       
   377          *
       
   378          * <p>Implementation logic for detaching subscriptions done via
       
   379          * <code>node.on(type, fn)</code>.  This function should clean up any
       
   380          * subscriptions made in the <code>on()</code> phase.</p>
       
   381          *
       
   382          * @method detach
       
   383          * @param node {Node} the node the subscription was applied to
       
   384          * @param sub {Subscription} the object tracking this subscription
       
   385          * @param notifier {SyntheticEvent.Notifier} the Notifier used to
       
   386          *              trigger the execution of the subscribers
       
   387          */
       
   388         detach: noop,
       
   389 
       
   390         /**
       
   391          * <p>Implementers SHOULD provide this method definition.</p>
       
   392          *
       
   393          * <p>Implementation logic for subscriptions done via
       
   394          * <code>node.delegate(type, fn, filter)</code> or
       
   395          * <code>Y.delegate(type, fn, container, filter)</code>.  Like with
       
   396          * <code>on()</code> above, this function should monitor the environment
       
   397          * for the event being fired, and trigger subscription execution by
       
   398          * calling <code>notifier.fire(e)</code>.</p>
       
   399          *
       
   400          * <p>This function receives a fourth argument, which is the filter
       
   401          * used to identify which Node's are of interest to the subscription.
       
   402          * The filter will be either a boolean function that accepts a target
       
   403          * Node for each hierarchy level as the event bubbles, or a selector
       
   404          * string.  To translate selector strings into filter functions, use
       
   405          * <code>Y.delegate.compileFilter(filter)</code>.</p>
       
   406          *
       
   407          * @method delegate
       
   408          * @param node {Node} the node the subscription is being applied to
       
   409          * @param sub {Subscription} the object to track this subscription
       
   410          * @param notifier {SyntheticEvent.Notifier} call notifier.fire(..) to
       
   411          *              trigger the execution of the subscribers
       
   412          * @param filter {String|Function} Selector string or function that
       
   413          *              accepts an event object and returns null, a Node, or an
       
   414          *              array of Nodes matching the criteria for processing.
       
   415          * @since 3.2.0
       
   416          */
       
   417         delegate       : noop,
       
   418 
       
   419         /**
       
   420          * <p>Implementers SHOULD provide this method definition.</p>
       
   421          *
       
   422          * <p>Implementation logic for detaching subscriptions done via
       
   423          * <code>node.delegate(type, fn, filter)</code> or
       
   424          * <code>Y.delegate(type, fn, container, filter)</code>.  This function
       
   425          * should clean up any subscriptions made in the
       
   426          * <code>delegate()</code> phase.</p>
       
   427          *
       
   428          * @method detachDelegate
       
   429          * @param node {Node} the node the subscription was applied to
       
   430          * @param sub {Subscription} the object tracking this subscription
       
   431          * @param notifier {SyntheticEvent.Notifier} the Notifier used to
       
   432          *              trigger the execution of the subscribers
       
   433          * @param filter {String|Function} Selector string or function that
       
   434          *              accepts an event object and returns null, a Node, or an
       
   435          *              array of Nodes matching the criteria for processing.
       
   436          * @since 3.2.0
       
   437          */
       
   438         detachDelegate : noop,
       
   439 
       
   440         /**
       
   441          * Sets up the boilerplate for detaching the event and facilitating the
       
   442          * execution of subscriber callbacks.
       
   443          *
       
   444          * @method _on
       
   445          * @param args {Array} array of arguments passed to
       
   446          *              <code>Y.on(...)</code> or <code>Y.delegate(...)</code>
       
   447          * @param delegate {Boolean} true if called from
       
   448          * <code>Y.delegate(...)</code>
       
   449          * @return {EventHandle} the detach handle for this subscription
       
   450          * @private
       
   451          * since 3.2.0
       
   452          */
       
   453         _on: function (args, delegate) {
       
   454             var handles  = [],
       
   455                 originalArgs = args.slice(),
       
   456                 extra    = this.processArgs(args, delegate),
       
   457                 selector = args[2],
       
   458                 method   = delegate ? 'delegate' : 'on',
       
   459                 nodes, handle;
       
   460 
       
   461             // Can't just use Y.all because it doesn't support window (yet?)
       
   462             nodes = (isString(selector)) ?
       
   463                 query(selector) :
       
   464                 toArray(selector || Y.one(Y.config.win));
       
   465 
       
   466             if (!nodes.length && isString(selector)) {
       
   467                 handle = Y.on('available', function () {
       
   468                     Y.mix(handle, Y[method].apply(Y, originalArgs), true);
       
   469                 }, selector);
       
   470 
       
   471                 return handle;
       
   472             }
       
   473 
       
   474             Y.Array.each(nodes, function (node) {
       
   475                 var subArgs = args.slice(),
       
   476                     filter;
       
   477 
       
   478                 node = Y.one(node);
       
   479 
       
   480                 if (node) {
       
   481                     if (delegate) {
       
   482                         filter = subArgs.splice(3, 1)[0];
       
   483                     }
       
   484 
       
   485                     // (type, fn, el, thisObj, ...) => (fn, thisObj, ...)
       
   486                     subArgs.splice(0, 4, subArgs[1], subArgs[3]);
       
   487 
       
   488                     if (!this.preventDups ||
       
   489                         !this.getSubs(node, args, null, true))
       
   490                     {
       
   491                         handles.push(this._subscribe(node, method, subArgs, extra, filter));
       
   492                     }
       
   493                 }
       
   494             }, this);
       
   495 
       
   496             return (handles.length === 1) ?
       
   497                 handles[0] :
       
   498                 new Y.EventHandle(handles);
       
   499         },
       
   500 
       
   501         /**
       
   502          * Creates a new Notifier object for use by this event's
       
   503          * <code>on(...)</code> or <code>delegate(...)</code> implementation
       
   504          * and register the custom event proxy in the DOM system for cleanup.
       
   505          *
       
   506          * @method _subscribe
       
   507          * @param node {Node} the Node hosting the event
       
   508          * @param method {String} "on" or "delegate"
       
   509          * @param args {Array} the subscription arguments passed to either
       
   510          *              <code>Y.on(...)</code> or <code>Y.delegate(...)</code>
       
   511          *              after running through <code>processArgs(args)</code> to
       
   512          *              normalize the argument signature
       
   513          * @param extra {any} Extra data parsed from
       
   514          *              <code>processArgs(args)</code>
       
   515          * @param filter {String|Function} the selector string or function
       
   516          *              filter passed to <code>Y.delegate(...)</code> (not
       
   517          *              present when called from <code>Y.on(...)</code>)
       
   518          * @return {EventHandle}
       
   519          * @private
       
   520          * @since 3.2.0
       
   521          */
       
   522         _subscribe: function (node, method, args, extra, filter) {
       
   523             var dispatcher = new Y.CustomEvent(this.type, this.publishConfig),
       
   524                 handle     = dispatcher.on.apply(dispatcher, args),
       
   525                 notifier   = new Notifier(handle, this.emitFacade),
       
   526                 registry   = SyntheticEvent.getRegistry(node, this.type, true),
       
   527                 sub        = handle.sub;
       
   528 
       
   529             sub.node   = node;
       
   530             sub.filter = filter;
       
   531             if (extra) {
       
   532                 this.applyArgExtras(extra, sub);
       
   533             }
       
   534 
       
   535             Y.mix(dispatcher, {
       
   536                 eventDef     : this,
       
   537                 notifier     : notifier,
       
   538                 host         : node,       // I forget what this is for
       
   539                 currentTarget: node,       // for generating facades
       
   540                 target       : node,       // for generating facades
       
   541                 el           : node._node, // For category detach
       
   542 
       
   543                 _delete      : SyntheticEvent._deleteSub
       
   544             }, true);
       
   545 
       
   546             handle.notifier = notifier;
       
   547 
       
   548             registry.register(handle);
       
   549 
       
   550             // Call the implementation's "on" or "delegate" method
       
   551             this[method](node, sub, notifier, filter);
       
   552 
       
   553             return handle;
       
   554         },
       
   555 
       
   556         /**
       
   557          * <p>Implementers MAY provide this method definition.</p>
       
   558          *
       
   559          * <p>Implement this function if you want extra data extracted during
       
   560          * processArgs to be propagated to subscriptions on a per-node basis.
       
   561          * That is to say, if you call <code>Y.on('xyz', fn, xtra, 'div')</code>
       
   562          * the data returned from processArgs will be shared
       
   563          * across the subscription objects for all the divs.  If you want each
       
   564          * subscription to receive unique information, do that processing
       
   565          * here.</p>
       
   566          *
       
   567          * <p>The default implementation adds the data extracted by processArgs
       
   568          * to the subscription object as <code>sub._extra</code>.</p>
       
   569          *
       
   570          * @method applyArgExtras
       
   571          * @param extra {any} Any extra data extracted from processArgs
       
   572          * @param sub {Subscription} the individual subscription
       
   573          */
       
   574         applyArgExtras: function (extra, sub) {
       
   575             sub._extra = extra;
       
   576         },
       
   577 
       
   578         /**
       
   579          * Removes the subscription(s) from the internal subscription dispatch
       
   580          * mechanism.  See <code>SyntheticEvent._deleteSub</code>.
       
   581          *
       
   582          * @method _detach
       
   583          * @param args {Array} The arguments passed to
       
   584          *                  <code>node.detach(...)</code>
       
   585          * @private
       
   586          * @since 3.2.0
       
   587          */
       
   588         _detach: function (args) {
       
   589             // Can't use Y.all because it doesn't support window (yet?)
       
   590             // TODO: Does Y.all support window now?
       
   591             var target = args[2],
       
   592                 els    = (isString(target)) ?
       
   593                             query(target) : toArray(target),
       
   594                 node, i, len, handles, j;
       
   595 
       
   596             // (type, fn, el, context, filter?) => (type, fn, context, filter?)
       
   597             args.splice(2, 1);
       
   598 
       
   599             for (i = 0, len = els.length; i < len; ++i) {
       
   600                 node = Y.one(els[i]);
       
   601 
       
   602                 if (node) {
       
   603                     handles = this.getSubs(node, args);
       
   604 
       
   605                     if (handles) {
       
   606                         for (j = handles.length - 1; j >= 0; --j) {
       
   607                             handles[j].detach();
       
   608                         }
       
   609                     }
       
   610                 }
       
   611             }
       
   612         },
       
   613 
       
   614         /**
       
   615          * Returns the detach handles of subscriptions on a node that satisfy a
       
   616          * search/filter function.  By default, the filter used is the
       
   617          * <code>subMatch</code> method.
       
   618          *
       
   619          * @method getSubs
       
   620          * @param node {Node} the node hosting the event
       
   621          * @param args {Array} the array of original subscription args passed
       
   622          *              to <code>Y.on(...)</code> (before
       
   623          *              <code>processArgs</code>
       
   624          * @param filter {Function} function used to identify a subscription
       
   625          *              for inclusion in the returned array
       
   626          * @param first {Boolean} stop after the first match (used to check for
       
   627          *              duplicate subscriptions)
       
   628          * @return {EventHandle[]} detach handles for the matching subscriptions
       
   629          */
       
   630         getSubs: function (node, args, filter, first) {
       
   631             var registry = SyntheticEvent.getRegistry(node, this.type),
       
   632                 handles  = [],
       
   633                 allHandles, i, len, handle;
       
   634 
       
   635             if (registry) {
       
   636                 allHandles = registry.handles;
       
   637 
       
   638                 if (!filter) {
       
   639                     filter = this.subMatch;
       
   640                 }
       
   641 
       
   642                 for (i = 0, len = allHandles.length; i < len; ++i) {
       
   643                     handle = allHandles[i];
       
   644                     if (filter.call(this, handle.sub, args)) {
       
   645                         if (first) {
       
   646                             return handle;
       
   647                         } else {
       
   648                             handles.push(allHandles[i]);
       
   649                         }
       
   650                     }
       
   651                 }
       
   652             }
       
   653 
       
   654             return handles.length && handles;
       
   655         },
       
   656 
       
   657         /**
       
   658          * <p>Implementers MAY override this to define what constitutes a
       
   659          * &quot;same&quot; subscription.  Override implementations should
       
   660          * consider the lack of a comparator as a match, so calling
       
   661          * <code>getSubs()</code> with no arguments will return all subs.</p>
       
   662          *
       
   663          * <p>Compares a set of subscription arguments against a Subscription
       
   664          * object to determine if they match.  The default implementation
       
   665          * compares the callback function against the second argument passed to
       
   666          * <code>Y.on(...)</code> or <code>node.detach(...)</code> etc.</p>
       
   667          *
       
   668          * @method subMatch
       
   669          * @param sub {Subscription} the existing subscription
       
   670          * @param args {Array} the calling arguments passed to
       
   671          *                  <code>Y.on(...)</code> etc.
       
   672          * @return {Boolean} true if the sub can be described by the args
       
   673          *                  present
       
   674          * @since 3.2.0
       
   675          */
       
   676         subMatch: function (sub, args) {
       
   677             // Default detach cares only about the callback matching
       
   678             return !args[1] || sub.fn === args[1];
       
   679         }
       
   680     }
       
   681 }, true);
       
   682 
       
   683 Y.SyntheticEvent = SyntheticEvent;
       
   684 
       
   685 /**
       
   686  * <p>Defines a new event in the DOM event system.  Implementers are
       
   687  * responsible for monitoring for a scenario whereby the event is fired.  A
       
   688  * notifier object is provided to the functions identified below.  When the
       
   689  * criteria defining the event are met, call notifier.fire( [args] ); to
       
   690  * execute event subscribers.</p>
       
   691  *
       
   692  * <p>The first parameter is the name of the event.  The second parameter is a
       
   693  * configuration object which define the behavior of the event system when the
       
   694  * new event is subscribed to or detached from.  The methods that should be
       
   695  * defined in this configuration object are <code>on</code>,
       
   696  * <code>detach</code>, <code>delegate</code>, and <code>detachDelegate</code>.
       
   697  * You are free to define any other methods or properties needed to define your
       
   698  * event.  Be aware, however, that since the object is used to subclass
       
   699  * SyntheticEvent, you should avoid method names used by SyntheticEvent unless
       
   700  * your intention is to override the default behavior.</p>
       
   701  *
       
   702  * <p>This is a list of properties and methods that you can or should specify
       
   703  * in the configuration object:</p>
       
   704  *
       
   705  * <dl>
       
   706  *   <dt><code>on</code></dt>
       
   707  *       <dd><code>function (node, subscription, notifier)</code> The
       
   708  *       implementation logic for subscription.  Any special setup you need to
       
   709  *       do to create the environment for the event being fired--E.g. native
       
   710  *       DOM event subscriptions.  Store subscription related objects and
       
   711  *       state on the <code>subscription</code> object.  When the
       
   712  *       criteria have been met to fire the synthetic event, call
       
   713  *       <code>notifier.fire(e)</code>.  See Notifier's <code>fire()</code>
       
   714  *       method for details about what to pass as parameters.</dd>
       
   715  *
       
   716  *   <dt><code>detach</code></dt>
       
   717  *       <dd><code>function (node, subscription, notifier)</code> The
       
   718  *       implementation logic for cleaning up a detached subscription. E.g.
       
   719  *       detach any DOM subscriptions added in <code>on</code>.</dd>
       
   720  *
       
   721  *   <dt><code>delegate</code></dt>
       
   722  *       <dd><code>function (node, subscription, notifier, filter)</code> The
       
   723  *       implementation logic for subscription via <code>Y.delegate</code> or
       
   724  *       <code>node.delegate</code>.  The filter is typically either a selector
       
   725  *       string or a function.  You can use
       
   726  *       <code>Y.delegate.compileFilter(selectorString)</code> to create a
       
   727  *       filter function from a selector string if needed.  The filter function
       
   728  *       expects an event object as input and should output either null, a
       
   729  *       matching Node, or an array of matching Nodes.  Otherwise, this acts
       
   730  *       like <code>on</code> DOM event subscriptions.  Store subscription
       
   731  *       related objects and information on the <code>subscription</code>
       
   732  *       object.  When the criteria have been met to fire the synthetic event,
       
   733  *       call <code>notifier.fire(e)</code> as noted above.</dd>
       
   734  *
       
   735  *   <dt><code>detachDelegate</code></dt>
       
   736  *       <dd><code>function (node, subscription, notifier)</code> The
       
   737  *       implementation logic for cleaning up a detached delegate subscription.
       
   738  *       E.g. detach any DOM delegate subscriptions added in
       
   739  *       <code>delegate</code>.</dd>
       
   740  *
       
   741  *   <dt><code>publishConfig</code></dt>
       
   742  *       <dd>(Object) The configuration object that will be used to instantiate
       
   743  *       the underlying CustomEvent. See Notifier's <code>fire</code> method
       
   744  *       for details.</dd>
       
   745  *
       
   746  *   <dt><code>processArgs</code></dt
       
   747  *       <dd>
       
   748  *          <p><code>function (argArray, fromDelegate)</code> Optional method
       
   749  *          to extract any additional arguments from the subscription
       
   750  *          signature.  Using this allows <code>on</code> or
       
   751  *          <code>delegate</code> signatures like
       
   752  *          <code>node.on(&quot;hover&quot;, overCallback,
       
   753  *          outCallback)</code>.</p>
       
   754  *          <p>When processing an atypical argument signature, make sure the
       
   755  *          args array is returned to the normal signature before returning
       
   756  *          from the function.  For example, in the &quot;hover&quot; example
       
   757  *          above, the <code>outCallback</code> needs to be <code>splice</code>d
       
   758  *          out of the array.  The expected signature of the args array for
       
   759  *          <code>on()</code> subscriptions is:</p>
       
   760  *          <pre>
       
   761  *              <code>[type, callback, target, contextOverride, argN...]</code>
       
   762  *          </pre>
       
   763  *          <p>And for <code>delegate()</code>:</p>
       
   764  *          <pre>
       
   765  *              <code>[type, callback, target, filter, contextOverride, argN...]</code>
       
   766  *          </pre>
       
   767  *          <p>where <code>target</code> is the node the event is being
       
   768  *          subscribed for.  You can see these signatures documented for
       
   769  *          <code>Y.on()</code> and <code>Y.delegate()</code> respectively.</p>
       
   770  *          <p>Whatever gets returned from the function will be stored on the
       
   771  *          <code>subscription</code> object under
       
   772  *          <code>subscription._extra</code>.</p></dd>
       
   773  *   <dt><code>subMatch</code></dt>
       
   774  *       <dd>
       
   775  *           <p><code>function (sub, args)</code>  Compares a set of
       
   776  *           subscription arguments against a Subscription object to determine
       
   777  *           if they match.  The default implementation compares the callback
       
   778  *           function against the second argument passed to
       
   779  *           <code>Y.on(...)</code> or <code>node.detach(...)</code> etc.</p>
       
   780  *       </dd>
       
   781  * </dl>
       
   782  *
       
   783  * @method define
       
   784  * @param type {String} the name of the event
       
   785  * @param config {Object} the prototype definition for the new event (see above)
       
   786  * @param force {Boolean} override an existing event (use with caution)
       
   787  * @return {SyntheticEvent} the subclass implementation instance created to
       
   788  *              handle event subscriptions of this type
       
   789  * @static
       
   790  * @for Event
       
   791  * @since 3.1.0
       
   792  * @in event-synthetic
       
   793  */
       
   794 Y.Event.define = function (type, config, force) {
       
   795     var eventDef, Impl, synth;
       
   796 
       
   797     if (type && type.type) {
       
   798         eventDef = type;
       
   799         force = config;
       
   800     } else if (config) {
       
   801         eventDef = Y.merge({ type: type }, config);
       
   802     }
       
   803 
       
   804     if (eventDef) {
       
   805         if (force || !Y.Node.DOM_EVENTS[eventDef.type]) {
       
   806             Impl = function () {
       
   807                 SyntheticEvent.apply(this, arguments);
       
   808             };
       
   809             Y.extend(Impl, SyntheticEvent, eventDef);
       
   810             synth = new Impl();
       
   811 
       
   812             type = synth.type;
       
   813 
       
   814             Y.Node.DOM_EVENTS[type] = Y.Env.evt.plugins[type] = {
       
   815                 eventDef: synth,
       
   816 
       
   817                 on: function () {
       
   818                     return synth._on(toArray(arguments));
       
   819                 },
       
   820 
       
   821                 delegate: function () {
       
   822                     return synth._on(toArray(arguments), true);
       
   823                 },
       
   824 
       
   825                 detach: function () {
       
   826                     return synth._detach(toArray(arguments));
       
   827                 }
       
   828             };
       
   829 
       
   830         }
       
   831     } else if (isString(type) || isArray(type)) {
       
   832         Y.Array.each(toArray(type), function (t) {
       
   833             Y.Node.DOM_EVENTS[t] = 1;
       
   834         });
       
   835     }
       
   836 
       
   837     return synth;
       
   838 };
       
   839 
       
   840 
       
   841 }, '3.10.3', {"requires": ["node-base", "event-custom-complex"]});