event-custom-complex.js revision bd03a79f6dc612d2940a331a52ee4cf0f364b1ba
0f2dc02ed2763dadc70bec1db8dd407e16db8e49ek * Adds event facades, preventable default behavior, and bubbling.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @module event-custom
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @submodule event-custom-complex
fa9e4066f08beec538e775443c5be79dd423fcabahrens(function() {
fa9e4066f08beec538e775443c5be79dd423fcabahrensvar FACADE, FACADE_KEYS, CEProto = Y.CustomEvent.prototype,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Wraps and protects a custom event for use when emitFacade is set to true.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Requires the event-custom-complex module
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @class EventFacade
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param e {Event} the custom event
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param currentTarget {HTMLElement} the element the listener was attached to
fa9e4066f08beec538e775443c5be79dd423fcabahrens e = e || {};
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The arguments passed to fire
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @property details
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @type Array
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The event type, this can be overridden by the fire() payload
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @property type
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @type string
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The real event type
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @property type
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @type string
fa9e4066f08beec538e775443c5be79dd423fcabahrens //////////////////////////////////////////////////////
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Node reference for the targeted eventtarget
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @propery target
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @type Node
f18faf3f3e5def85fdfff681617d227703ace2adek * Node reference for the element that the listener was attached to.
f18faf3f3e5def85fdfff681617d227703ace2adek * @propery currentTarget
f18faf3f3e5def85fdfff681617d227703ace2adek * @type Node
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Node reference to the relatedTarget
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @propery relatedTarget
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @type Node
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Stops the propagation to the next bubble target
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @method stopPropagation
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens this.stopPropagation = function() {
6d1e0b89f3e34478a022854df6b0cfab82ccce66marks * Stops the propagation to the next bubble target and
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck * prevents any additional listeners from being exectued
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck * on the current target.
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck * @method stopImmediatePropagation
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck this.stopImmediatePropagation = function() {
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck * Prevents the event's default behavior
8bf40bf00a7564d0ccb4a33906734188cb2d1e9bck * @method preventDefault
fa9e4066f08beec538e775443c5be79dd423fcabahrens this.preventDefault = function() {
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Stops the event propagation and prevents the default
fa9e4066f08beec538e775443c5be79dd423fcabahrens * event behavior.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @method halt
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param immediate {boolean} if true additional listeners
fa9e4066f08beec538e775443c5be79dd423fcabahrens * on the current target will not be executed
fa9e4066f08beec538e775443c5be79dd423fcabahrens var es = Y.Env._eventstack, ef, q, queue, ce, ret, events, subs,
fa9e4066f08beec538e775443c5be79dd423fcabahrens self = this, host = self.host || self, next, oldbubble;
fa9e4066f08beec538e775443c5be79dd423fcabahrens // queue this event if the current item in the queue bubbles
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright return true;
fa9e4066f08beec538e775443c5be79dd423fcabahrens // id of the first event in the stack
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright // defaultFnQueue: new Y.Queue(),
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright self.stopped = (self.type !== es.type) ? 0 : es.stopped;
fa9e4066f08beec538e775443c5be79dd423fcabahrens self.prevented = (self.type !== es.type) ? 0 : es.prevented;
fa9e4066f08beec538e775443c5be79dd423fcabahrens self.details = args.slice(); // original arguments in the details
fa9e4066f08beec538e775443c5be79dd423fcabahrens // self.log("Firing " + self + ", " + "args: " + args);
fa9e4066f08beec538e775443c5be79dd423fcabahrens self._facade = null; // kill facade to eliminate stale properties
fa9e4066f08beec538e775443c5be79dd423fcabahrens // if (subCount) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens // self._procSubs(Y.merge(self.subscribers), args, ef);
fa9e4066f08beec538e775443c5be79dd423fcabahrens // bubble if this is hosted in an event target and propagation has not been stopped
d39ee142a97a7c58f60f7b52c62409f2ff64b234Mark Shellenbaum if (self.bubbles && host.bubble && !self.stopped) {
d39ee142a97a7c58f60f7b52c62409f2ff64b234Mark Shellenbaum // self.bubbling = true;
d39ee142a97a7c58f60f7b52c62409f2ff64b234Mark Shellenbaum // if (host !== ef.target || es.type != self.type) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens self.prevented = Math.max(self.prevented, es.prevented);
fa9e4066f08beec538e775443c5be79dd423fcabahrens // self.bubbling = false;
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright // execute the default behavior if not prevented
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright // console.log('defaultTargetOnly: ' + self.defaultTargetOnly);
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright // console.log('host === target: ' + (host === ef.target));
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright // if (self.defaultFn && !self.prevented && ((!self.defaultTargetOnly) || host === es.id === self.id)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (self.defaultFn && !self.prevented && ((!self.defaultTargetOnly && !es.defaultTargetOnly) || host === ef.target)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens // if (es.id === self.id) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens // self.defaultFn.apply(host, args);
fa9e4066f08beec538e775443c5be79dd423fcabahrens // while ((next = es.defaultFnQueue.last())) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens // } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens // es.defaultFnQueue.add(function() {
fa9e4066f08beec538e775443c5be79dd423fcabahrens // self.defaultFn.apply(host, args);
fa9e4066f08beec538e775443c5be79dd423fcabahrens // broadcast listeners are fired as discreet events on the
fa9e4066f08beec538e775443c5be79dd423fcabahrens // YUI instance and potentially the YUI global.
fa9e4066f08beec538e775443c5be79dd423fcabahrens // process after listeners. If the default behavior was
fa9e4066f08beec538e775443c5be79dd423fcabahrens // prevented, the after events don't fire.
fa9e4066f08beec538e775443c5be79dd423fcabahrens // if (self.afterCount && !self.prevented && self.stopped < 2) {
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum // if (subs[1] && !self.prevented && self.stopped < 2) {
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum // // self._procSubs(Y.merge(self.afters), args, ef);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum // self._procSubs(subs[1], args, ef);
fa9e4066f08beec538e775443c5be79dd423fcabahrens // Queue the after
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (subs[1] && !self.prevented && self.stopped < 2) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (es.id === self.id || self.type != host._yuievt.bubbling) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens // es.stopped = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens // es.prevented = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens // set up stack to allow the next item to be processed
fa9e4066f08beec538e775443c5be79dd423fcabahrens // es.stopped = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens // es.prevented = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens // if the first argument is an object literal, apply the
fa9e4066f08beec538e775443c5be79dd423fcabahrens // properties to the event facade
fa9e4066f08beec538e775443c5be79dd423fcabahrens // protect the event facade properties
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens // mix the data
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens // restore ef
fa9e4066f08beec538e775443c5be79dd423fcabahrens // Allow the event type to be faked
fa9e4066f08beec538e775443c5be79dd423fcabahrens // http://yuilibrary.com/projects/yui3/ticket/2528376
fa9e4066f08beec538e775443c5be79dd423fcabahrens // update the details field with the arguments
fa9e4066f08beec538e775443c5be79dd423fcabahrens // ef.type = this.type;
a32fded1a905061abae92da5bcbab429cb6146f1ek // use the original target when the event bubbled to this target
fa9e4066f08beec538e775443c5be79dd423fcabahrens return this._facade;
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Stop propagation to bubble targets
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @for CustomEvent
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @method stopPropagation
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Stops propagation to bubble targets, and prevents any remaining
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * subscribers on the current target from executing.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @method stopImmediatePropagation
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Prevents the execution of this event's defaultFn
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @method preventDefault
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Stops the event propagation and prevents the default
fa9e4066f08beec538e775443c5be79dd423fcabahrens * event behavior.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @method halt
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param immediate {boolean} if true additional listeners
fa9e4066f08beec538e775443c5be79dd423fcabahrens * on the current target will not be executed
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright * Registers another EventTarget as a bubble target. Bubble order
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright * is determined by the order registered. Multiple targets can
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright * be specified.
9e1320c015cea6985d2122bc1d654b79fa479f7aMark Shellenbaum * Events can only bubble if emitFacade is true.
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens * Included in the event-custom-complex submodule.
9e1320c015cea6985d2122bc1d654b79fa479f7aMark Shellenbaum * @method addTarget
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright * @param o {EventTarget} the target to add
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright * @for EventTarget
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Returns an array of bubble targets for this object.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @method getTargets
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @return EventTarget[]
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Removes a bubble target
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @method removeTarget
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param o {EventTarget} the target to remove
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @for EventTarget
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Propagate an event. Requires the event-custom-complex module.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @method bubble
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param evt {Event.Custom} the custom event to propagate
71eb05381846ad14a2087631474e832d0f316654Chris Kirby * @return {boolean} the aggregated return value from Event.Custom.fire
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @for EventTarget
fa9e4066f08beec538e775443c5be79dd423fcabahrens originalTarget = target || (evt && evt.target) || this,
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i in targs) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw // if this event was not published on the bubble target,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw // continue propagating the event.
fa9e4066f08beec538e775443c5be79dd423fcabahrens // set the original target to that the target payload on the
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh // facade is correct.
fa9e4066f08beec538e775443c5be79dd423fcabahrens // default publish may not have emitFacade true -- that
fa9e4066f08beec538e775443c5be79dd423fcabahrens // shouldn't be what the implementer meant to do
60030f278c9b10a64cb18b6443f7e8d97d6e45e4Mark Shellenbaum ret = ret && ce.fire.apply(ce, args || evt.details || []);
60030f278c9b10a64cb18b6443f7e8d97d6e45e4Mark Shellenbaum // stopPropagation() was called