src/cm/media/js/lib/yui/yui_3.10.3/build/event-custom-complex/event-custom-complex-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-custom-complex', function (Y, NAME) {
       
     9 
       
    10 
       
    11 /**
       
    12  * Adds event facades, preventable default behavior, and bubbling.
       
    13  * events.
       
    14  * @module event-custom
       
    15  * @submodule event-custom-complex
       
    16  */
       
    17 
       
    18 var FACADE,
       
    19     FACADE_KEYS,
       
    20     YObject = Y.Object,
       
    21     key,
       
    22     EMPTY = {},
       
    23     CEProto = Y.CustomEvent.prototype,
       
    24     ETProto = Y.EventTarget.prototype,
       
    25 
       
    26     mixFacadeProps = function(facade, payload) {
       
    27         var p;
       
    28 
       
    29         for (p in payload) {
       
    30             if (!(FACADE_KEYS.hasOwnProperty(p))) {
       
    31                 facade[p] = payload[p];
       
    32             }
       
    33         }
       
    34     };
       
    35 
       
    36 /**
       
    37  * Wraps and protects a custom event for use when emitFacade is set to true.
       
    38  * Requires the event-custom-complex module
       
    39  * @class EventFacade
       
    40  * @param e {Event} the custom event
       
    41  * @param currentTarget {HTMLElement} the element the listener was attached to
       
    42  */
       
    43 
       
    44 Y.EventFacade = function(e, currentTarget) {
       
    45 
       
    46     if (!e) {
       
    47         e = EMPTY;
       
    48     }
       
    49 
       
    50     this._event = e;
       
    51 
       
    52     /**
       
    53      * The arguments passed to fire
       
    54      * @property details
       
    55      * @type Array
       
    56      */
       
    57     this.details = e.details;
       
    58 
       
    59     /**
       
    60      * The event type, this can be overridden by the fire() payload
       
    61      * @property type
       
    62      * @type string
       
    63      */
       
    64     this.type = e.type;
       
    65 
       
    66     /**
       
    67      * The real event type
       
    68      * @property _type
       
    69      * @type string
       
    70      * @private
       
    71      */
       
    72     this._type = e.type;
       
    73 
       
    74     //////////////////////////////////////////////////////
       
    75 
       
    76     /**
       
    77      * Node reference for the targeted eventtarget
       
    78      * @property target
       
    79      * @type Node
       
    80      */
       
    81     this.target = e.target;
       
    82 
       
    83     /**
       
    84      * Node reference for the element that the listener was attached to.
       
    85      * @property currentTarget
       
    86      * @type Node
       
    87      */
       
    88     this.currentTarget = currentTarget;
       
    89 
       
    90     /**
       
    91      * Node reference to the relatedTarget
       
    92      * @property relatedTarget
       
    93      * @type Node
       
    94      */
       
    95     this.relatedTarget = e.relatedTarget;
       
    96 
       
    97 };
       
    98 
       
    99 Y.mix(Y.EventFacade.prototype, {
       
   100 
       
   101     /**
       
   102      * Stops the propagation to the next bubble target
       
   103      * @method stopPropagation
       
   104      */
       
   105     stopPropagation: function() {
       
   106         this._event.stopPropagation();
       
   107         this.stopped = 1;
       
   108     },
       
   109 
       
   110     /**
       
   111      * Stops the propagation to the next bubble target and
       
   112      * prevents any additional listeners from being exectued
       
   113      * on the current target.
       
   114      * @method stopImmediatePropagation
       
   115      */
       
   116     stopImmediatePropagation: function() {
       
   117         this._event.stopImmediatePropagation();
       
   118         this.stopped = 2;
       
   119     },
       
   120 
       
   121     /**
       
   122      * Prevents the event's default behavior
       
   123      * @method preventDefault
       
   124      */
       
   125     preventDefault: function() {
       
   126         this._event.preventDefault();
       
   127         this.prevented = 1;
       
   128     },
       
   129 
       
   130     /**
       
   131      * Stops the event propagation and prevents the default
       
   132      * event behavior.
       
   133      * @method halt
       
   134      * @param immediate {boolean} if true additional listeners
       
   135      * on the current target will not be executed
       
   136      */
       
   137     halt: function(immediate) {
       
   138         this._event.halt(immediate);
       
   139         this.prevented = 1;
       
   140         this.stopped = (immediate) ? 2 : 1;
       
   141     }
       
   142 
       
   143 });
       
   144 
       
   145 CEProto.fireComplex = function(args) {
       
   146 
       
   147     var es,
       
   148         ef,
       
   149         q,
       
   150         queue,
       
   151         ce,
       
   152         ret = true,
       
   153         events,
       
   154         subs,
       
   155         ons,
       
   156         afters,
       
   157         afterQueue,
       
   158         postponed,
       
   159         prevented,
       
   160         preventedFn,
       
   161         defaultFn,
       
   162         self = this,
       
   163         host = self.host || self,
       
   164         next,
       
   165         oldbubble,
       
   166         stack,
       
   167         yuievt = host._yuievt,
       
   168         hasPotentialSubscribers;
       
   169 
       
   170     stack = self.stack;
       
   171 
       
   172     if (stack) {
       
   173 
       
   174         // queue this event if the current item in the queue bubbles
       
   175         if (self.queuable && self.type !== stack.next.type) {
       
   176             self.log('queue ' + self.type);
       
   177 
       
   178             if (!stack.queue) {
       
   179                 stack.queue = [];
       
   180             }
       
   181             stack.queue.push([self, args]);
       
   182 
       
   183             return true;
       
   184         }
       
   185     }
       
   186 
       
   187     hasPotentialSubscribers = self.hasSubs() || yuievt.hasTargets || self.broadcast;
       
   188 
       
   189     self.target = self.target || host;
       
   190     self.currentTarget = host;
       
   191 
       
   192     self.details = args.concat();
       
   193 
       
   194     if (hasPotentialSubscribers) {
       
   195 
       
   196         es = stack || {
       
   197 
       
   198            id: self.id, // id of the first event in the stack
       
   199            next: self,
       
   200            silent: self.silent,
       
   201            stopped: 0,
       
   202            prevented: 0,
       
   203            bubbling: null,
       
   204            type: self.type,
       
   205            // defaultFnQueue: new Y.Queue(),
       
   206            defaultTargetOnly: self.defaultTargetOnly
       
   207 
       
   208         };
       
   209 
       
   210         subs = self.getSubs();
       
   211         ons = subs[0];
       
   212         afters = subs[1];
       
   213 
       
   214         self.stopped = (self.type !== es.type) ? 0 : es.stopped;
       
   215         self.prevented = (self.type !== es.type) ? 0 : es.prevented;
       
   216 
       
   217         if (self.stoppedFn) {
       
   218             // PERF TODO: Can we replace with callback, like preventedFn. Look into history
       
   219             events = new Y.EventTarget({
       
   220                 fireOnce: true,
       
   221                 context: host
       
   222             });
       
   223             self.events = events;
       
   224             events.on('stopped', self.stoppedFn);
       
   225         }
       
   226 
       
   227         // self.log("Firing " + self  + ", " + "args: " + args);
       
   228         self.log("Firing " + self.type);
       
   229 
       
   230         self._facade = null; // kill facade to eliminate stale properties
       
   231 
       
   232         ef = self._getFacade(args);
       
   233 
       
   234         if (ons) {
       
   235             self._procSubs(ons, args, ef);
       
   236         }
       
   237 
       
   238         // bubble if this is hosted in an event target and propagation has not been stopped
       
   239         if (self.bubbles && host.bubble && !self.stopped) {
       
   240             oldbubble = es.bubbling;
       
   241 
       
   242             es.bubbling = self.type;
       
   243 
       
   244             if (es.type !== self.type) {
       
   245                 es.stopped = 0;
       
   246                 es.prevented = 0;
       
   247             }
       
   248 
       
   249             ret = host.bubble(self, args, null, es);
       
   250 
       
   251             self.stopped = Math.max(self.stopped, es.stopped);
       
   252             self.prevented = Math.max(self.prevented, es.prevented);
       
   253 
       
   254             es.bubbling = oldbubble;
       
   255         }
       
   256 
       
   257         prevented = self.prevented;
       
   258 
       
   259         if (prevented) {
       
   260             preventedFn = self.preventedFn;
       
   261             if (preventedFn) {
       
   262                 preventedFn.apply(host, args);
       
   263             }
       
   264         } else {
       
   265             defaultFn = self.defaultFn;
       
   266 
       
   267             if (defaultFn && ((!self.defaultTargetOnly && !es.defaultTargetOnly) || host === ef.target)) {
       
   268                 defaultFn.apply(host, args);
       
   269             }
       
   270         }
       
   271 
       
   272         // broadcast listeners are fired as discreet events on the
       
   273         // YUI instance and potentially the YUI global.
       
   274         if (self.broadcast) {
       
   275             self._broadcast(args);
       
   276         }
       
   277 
       
   278         if (afters && !self.prevented && self.stopped < 2) {
       
   279 
       
   280             // Queue the after
       
   281             afterQueue = es.afterQueue;
       
   282 
       
   283             if (es.id === self.id || self.type !== yuievt.bubbling) {
       
   284 
       
   285                 self._procSubs(afters, args, ef);
       
   286 
       
   287                 if (afterQueue) {
       
   288                     while ((next = afterQueue.last())) {
       
   289                         next();
       
   290                     }
       
   291                 }
       
   292             } else {
       
   293                 postponed = afters;
       
   294 
       
   295                 if (es.execDefaultCnt) {
       
   296                     postponed = Y.merge(postponed);
       
   297 
       
   298                     Y.each(postponed, function(s) {
       
   299                         s.postponed = true;
       
   300                     });
       
   301                 }
       
   302 
       
   303                 if (!afterQueue) {
       
   304                     es.afterQueue = new Y.Queue();
       
   305                 }
       
   306 
       
   307                 es.afterQueue.add(function() {
       
   308                     self._procSubs(postponed, args, ef);
       
   309                 });
       
   310             }
       
   311 
       
   312         }
       
   313 
       
   314         self.target = null;
       
   315 
       
   316         if (es.id === self.id) {
       
   317 
       
   318             queue = es.queue;
       
   319 
       
   320             if (queue) {
       
   321                 while (queue.length) {
       
   322                     q = queue.pop();
       
   323                     ce = q[0];
       
   324                     // set up stack to allow the next item to be processed
       
   325                     es.next = ce;
       
   326                     ce._fire(q[1]);
       
   327                 }
       
   328             }
       
   329 
       
   330             self.stack = null;
       
   331         }
       
   332 
       
   333         ret = !(self.stopped);
       
   334 
       
   335         if (self.type !== yuievt.bubbling) {
       
   336             es.stopped = 0;
       
   337             es.prevented = 0;
       
   338             self.stopped = 0;
       
   339             self.prevented = 0;
       
   340         }
       
   341 
       
   342     } else {
       
   343         defaultFn = self.defaultFn;
       
   344 
       
   345         if(defaultFn) {
       
   346             ef = self._getFacade(args);
       
   347 
       
   348             if ((!self.defaultTargetOnly) || (host === ef.target)) {
       
   349                 defaultFn.apply(host, args);
       
   350             }
       
   351         }
       
   352     }
       
   353 
       
   354     // Kill the cached facade to free up memory.
       
   355     // Otherwise we have the facade from the last fire, sitting around forever.
       
   356     self._facade = null;
       
   357 
       
   358     return ret;
       
   359 };
       
   360 
       
   361 CEProto._getFacade = function(fireArgs) {
       
   362 
       
   363     var userArgs = this.details,
       
   364         firstArg = userArgs && userArgs[0],
       
   365         firstArgIsObj = (firstArg && (typeof firstArg === "object")),
       
   366         ef = this._facade;
       
   367 
       
   368     if (!ef) {
       
   369         ef = new Y.EventFacade(this, this.currentTarget);
       
   370     }
       
   371 
       
   372     if (firstArgIsObj) {
       
   373         // protect the event facade properties
       
   374         mixFacadeProps(ef, firstArg);
       
   375 
       
   376         // Allow the event type to be faked http://yuilibrary.com/projects/yui3/ticket/2528376
       
   377         if (firstArg.type) {
       
   378             ef.type = firstArg.type;
       
   379         }
       
   380 
       
   381         if (fireArgs) {
       
   382             fireArgs[0] = ef;
       
   383         }
       
   384     } else {
       
   385         if (fireArgs) {
       
   386             fireArgs.unshift(ef);
       
   387         }
       
   388     }
       
   389 
       
   390     // update the details field with the arguments
       
   391     ef.details = this.details;
       
   392 
       
   393     // use the original target when the event bubbled to this target
       
   394     ef.target = this.originalTarget || this.target;
       
   395 
       
   396     ef.currentTarget = this.currentTarget;
       
   397     ef.stopped = 0;
       
   398     ef.prevented = 0;
       
   399 
       
   400     this._facade = ef;
       
   401 
       
   402     return this._facade;
       
   403 };
       
   404 
       
   405 /**
       
   406  * Stop propagation to bubble targets
       
   407  * @for CustomEvent
       
   408  * @method stopPropagation
       
   409  */
       
   410 CEProto.stopPropagation = function() {
       
   411     this.stopped = 1;
       
   412     if (this.stack) {
       
   413         this.stack.stopped = 1;
       
   414     }
       
   415     if (this.events) {
       
   416         this.events.fire('stopped', this);
       
   417     }
       
   418 };
       
   419 
       
   420 /**
       
   421  * Stops propagation to bubble targets, and prevents any remaining
       
   422  * subscribers on the current target from executing.
       
   423  * @method stopImmediatePropagation
       
   424  */
       
   425 CEProto.stopImmediatePropagation = function() {
       
   426     this.stopped = 2;
       
   427     if (this.stack) {
       
   428         this.stack.stopped = 2;
       
   429     }
       
   430     if (this.events) {
       
   431         this.events.fire('stopped', this);
       
   432     }
       
   433 };
       
   434 
       
   435 /**
       
   436  * Prevents the execution of this event's defaultFn
       
   437  * @method preventDefault
       
   438  */
       
   439 CEProto.preventDefault = function() {
       
   440     if (this.preventable) {
       
   441         this.prevented = 1;
       
   442         if (this.stack) {
       
   443             this.stack.prevented = 1;
       
   444         }
       
   445     }
       
   446 };
       
   447 
       
   448 /**
       
   449  * Stops the event propagation and prevents the default
       
   450  * event behavior.
       
   451  * @method halt
       
   452  * @param immediate {boolean} if true additional listeners
       
   453  * on the current target will not be executed
       
   454  */
       
   455 CEProto.halt = function(immediate) {
       
   456     if (immediate) {
       
   457         this.stopImmediatePropagation();
       
   458     } else {
       
   459         this.stopPropagation();
       
   460     }
       
   461     this.preventDefault();
       
   462 };
       
   463 
       
   464 /**
       
   465  * Registers another EventTarget as a bubble target.  Bubble order
       
   466  * is determined by the order registered.  Multiple targets can
       
   467  * be specified.
       
   468  *
       
   469  * Events can only bubble if emitFacade is true.
       
   470  *
       
   471  * Included in the event-custom-complex submodule.
       
   472  *
       
   473  * @method addTarget
       
   474  * @param o {EventTarget} the target to add
       
   475  * @for EventTarget
       
   476  */
       
   477 ETProto.addTarget = function(o) {
       
   478     var etState = this._yuievt;
       
   479 
       
   480     if (!etState.targets) {
       
   481         etState.targets = {};
       
   482     }
       
   483 
       
   484     etState.targets[Y.stamp(o)] = o;
       
   485     etState.hasTargets = true;
       
   486 };
       
   487 
       
   488 /**
       
   489  * Returns an array of bubble targets for this object.
       
   490  * @method getTargets
       
   491  * @return EventTarget[]
       
   492  */
       
   493 ETProto.getTargets = function() {
       
   494     var targets = this._yuievt.targets;
       
   495     return targets ? YObject.values(targets) : [];
       
   496 };
       
   497 
       
   498 /**
       
   499  * Removes a bubble target
       
   500  * @method removeTarget
       
   501  * @param o {EventTarget} the target to remove
       
   502  * @for EventTarget
       
   503  */
       
   504 ETProto.removeTarget = function(o) {
       
   505     var targets = this._yuievt.targets;
       
   506 
       
   507     if (targets) {
       
   508         delete targets[Y.stamp(o, true)];
       
   509 
       
   510         if (YObject.size(targets) === 0) {
       
   511             this._yuievt.hasTargets = false;
       
   512         }
       
   513     }
       
   514 };
       
   515 
       
   516 /**
       
   517  * Propagate an event.  Requires the event-custom-complex module.
       
   518  * @method bubble
       
   519  * @param evt {CustomEvent} the custom event to propagate
       
   520  * @return {boolean} the aggregated return value from Event.Custom.fire
       
   521  * @for EventTarget
       
   522  */
       
   523 ETProto.bubble = function(evt, args, target, es) {
       
   524 
       
   525     var targs = this._yuievt.targets,
       
   526         ret = true,
       
   527         t,
       
   528         ce,
       
   529         i,
       
   530         bc,
       
   531         ce2,
       
   532         type = evt && evt.type,
       
   533         originalTarget = target || (evt && evt.target) || this,
       
   534         oldbubble;
       
   535 
       
   536     if (!evt || ((!evt.stopped) && targs)) {
       
   537 
       
   538         for (i in targs) {
       
   539             if (targs.hasOwnProperty(i)) {
       
   540 
       
   541                 t = targs[i];
       
   542 
       
   543                 ce = t._yuievt.events[type];
       
   544 
       
   545                 if (t._hasSiblings) {
       
   546                     ce2 = t.getSibling(type, ce);
       
   547                 }
       
   548 
       
   549                 if (ce2 && !ce) {
       
   550                     ce = t.publish(type);
       
   551                 }
       
   552 
       
   553                 oldbubble = t._yuievt.bubbling;
       
   554                 t._yuievt.bubbling = type;
       
   555 
       
   556                 // if this event was not published on the bubble target,
       
   557                 // continue propagating the event.
       
   558                 if (!ce) {
       
   559                     if (t._yuievt.hasTargets) {
       
   560                         t.bubble(evt, args, originalTarget, es);
       
   561                     }
       
   562                 } else {
       
   563 
       
   564                     if (ce2) {
       
   565                         ce.sibling = ce2;
       
   566                     }
       
   567 
       
   568                     // set the original target to that the target payload on the facade is correct.
       
   569                     ce.target = originalTarget;
       
   570                     ce.originalTarget = originalTarget;
       
   571                     ce.currentTarget = t;
       
   572                     bc = ce.broadcast;
       
   573                     ce.broadcast = false;
       
   574 
       
   575                     // default publish may not have emitFacade true -- that
       
   576                     // shouldn't be what the implementer meant to do
       
   577                     ce.emitFacade = true;
       
   578 
       
   579                     ce.stack = es;
       
   580 
       
   581                     // TODO: See what's getting in the way of changing this to use
       
   582                     // the more performant ce._fire(args || evt.details || []).
       
   583 
       
   584                     // Something in Widget Parent/Child tests is not happy if we
       
   585                     // change it - maybe evt.details related?
       
   586                     ret = ret && ce.fire.apply(ce, args || evt.details || []);
       
   587 
       
   588                     ce.broadcast = bc;
       
   589                     ce.originalTarget = null;
       
   590 
       
   591                     // stopPropagation() was called
       
   592                     if (ce.stopped) {
       
   593                         break;
       
   594                     }
       
   595                 }
       
   596 
       
   597                 t._yuievt.bubbling = oldbubble;
       
   598             }
       
   599         }
       
   600     }
       
   601 
       
   602     return ret;
       
   603 };
       
   604 
       
   605 FACADE = new Y.EventFacade();
       
   606 FACADE_KEYS = {};
       
   607 
       
   608 // Flatten whitelist
       
   609 for (key in FACADE) {
       
   610     FACADE_KEYS[key] = true;
       
   611 }
       
   612 
       
   613 
       
   614 }, '3.10.3', {"requires": ["event-custom-base"]});