- /**
- * Define new DOM events that can be subscribed to from Nodes.
- *
- * @module event
- * @submodule event-synthetic
- */
- var CustomEvent = Y.CustomEvent,
- DOMMap = Y.Env.evt.dom_map,
- toArray = Y.Array,
- YLang = Y.Lang,
- isObject = YLang.isObject,
- isString = YLang.isString,
- isArray = YLang.isArray,
- query = Y.Selector.query,
- noop = function () {};
-
- /**
- * <p>The triggering mechanism used by SyntheticEvents.</p>
- *
- * <p>Implementers should not instantiate these directly. Use the Notifier
- * provided to the event's implemented <code>on(node, sub, notifier)</code> or
- * <code>delegate(node, sub, notifier, filter)</code> methods.</p>
- *
- * @class SyntheticEvent.Notifier
- * @constructor
- * @param handle {EventHandle} the detach handle for the subscription to an
- * internal custom event used to execute the callback passed to
- * on(..) or delegate(..)
- * @param emitFacade {Boolean} take steps to ensure the first arg received by
- * the subscription callback is an event facade
- * @private
- * @since 3.2.0
- */
- function Notifier(handle, emitFacade) {
- this.handle = handle;
- this.emitFacade = emitFacade;
- }
-
- /**
- * <p>Executes the subscription callback, passing the firing arguments as the
- * first parameters to that callback. For events that are configured with
- * emitFacade=true, it is common practice to pass the triggering DOMEventFacade
- * as the first parameter. Barring a proper DOMEventFacade or EventFacade
- * (from a CustomEvent), a new EventFacade will be generated. In that case, if
- * fire() is called with a simple object, it will be mixed into the facade.
- * Otherwise, the facade will be prepended to the callback parameters.</p>
- *
- * <p>For notifiers provided to delegate logic, the first argument should be an
- * object with a "currentTarget" property to identify what object to
- * default as 'this' in the callback. Typically this is gleaned from the
- * DOMEventFacade or EventFacade, but if configured with emitFacade=false, an
- * object must be provided. In that case, the object will be removed from the
- * callback parameters.</p>
- *
- * <p>Additional arguments passed during event subscription will be
- * automatically added after those passed to fire().</p>
- *
- * @method fire
- * @param {EventFacade|DOMEventFacade|any} e (see description)
- * @param {any[]} [arg*] additional arguments received by all subscriptions
- * @private
- */
- Notifier.prototype.fire = function (e) {
- // first arg to delegate notifier should be an object with currentTarget
- var args = toArray(arguments, 0, true),
- handle = this.handle,
- ce = handle.evt,
- sub = handle.sub,
- thisObj = sub.context,
- delegate = sub.filter,
- event = e || {},
- ret;
-
- if (this.emitFacade) {
- if (!e || !e.preventDefault) {
- event = ce._getFacade();
-
- if (isObject(e) && !e.preventDefault) {
- Y.mix(event, e, true);
- args[0] = event;
- } else {
- args.unshift(event);
- }
- }
-
- event.type = ce.type;
- event.details = args.slice();
-
- if (delegate) {
- event.container = ce.host;
- }
- } else if (delegate && isObject(e) && e.currentTarget) {
- args.shift();
- }
-
- sub.context = thisObj || event.currentTarget || ce.host;
- ret = ce.fire.apply(ce, args);
-
- // have to handle preventedFn and stoppedFn manually because
- // Notifier CustomEvents are forced to emitFacade=false
- if (e.prevented && ce.preventedFn) {
- ce.preventedFn.apply(ce, args);
- }
-
- if (e.stopped && ce.stoppedFn) {
- ce.stoppedFn.apply(ce, args);
- }
-
- sub.context = thisObj; // reset for future firing
-
- // to capture callbacks that return false to stopPropagation.
- // Useful for delegate implementations
- return ret;
- };
-
- /**
- * Manager object for synthetic event subscriptions to aggregate multiple synths on the
- * same node without colliding with actual DOM subscription entries in the global map of
- * DOM subscriptions. Also facilitates proper cleanup on page unload.
- *
- * @class SynthRegistry
- * @constructor
- * @param el {HTMLElement} the DOM element
- * @param yuid {String} the yuid stamp for the element
- * @param key {String} the generated id token used to identify an event type +
- * element in the global DOM subscription map.
- * @private
- */
- function SynthRegistry(el, yuid, key) {
- this.handles = [];
- this.el = el;
- this.key = key;
- this.domkey = yuid;
- }
-
- SynthRegistry.prototype = {
- constructor: SynthRegistry,
-
- // A few object properties to fake the CustomEvent interface for page
- // unload cleanup. DON'T TOUCH!
- type : '_synth',
- fn : noop,
- capture : false,
-
- /**
- * Adds a subscription from the Notifier registry.
- *
- * @method register
- * @param handle {EventHandle} the subscription
- * @since 3.4.0
- */
- register: function (handle) {
- handle.evt.registry = this;
- this.handles.push(handle);
- },
-
- /**
- * Removes the subscription from the Notifier registry.
- *
- * @method _unregisterSub
- * @param sub {Subscription} the subscription
- * @since 3.4.0
- */
- unregister: function (sub) {
- var handles = this.handles,
- events = DOMMap[this.domkey],
- i;
-
- for (i = handles.length - 1; i >= 0; --i) {
- if (handles[i].sub === sub) {
- handles.splice(i, 1);
- break;
- }
- }
-
- // Clean up left over objects when there are no more subscribers.
- if (!handles.length) {
- delete events[this.key];
- if (!Y.Object.size(events)) {
- delete DOMMap[this.domkey];
- }
- }
- },
-
- /**
- * Used by the event system's unload cleanup process. When navigating
- * away from the page, the event system iterates the global map of element
- * subscriptions and detaches everything using detachAll(). Normally,
- * the map is populated with custom events, so this object needs to
- * at least support the detachAll method to duck type its way to
- * cleanliness.
- *
- * @method detachAll
- * @private
- * @since 3.4.0
- */
- detachAll : function () {
- var handles = this.handles,
- i = handles.length;
-
- while (--i >= 0) {
- handles[i].detach();
- }
- }
- };
-
- /**
- * <p>Wrapper class for the integration of new events into the YUI event
- * infrastructure. Don't instantiate this object directly, use
- * <code>Y.Event.define(type, config)</code>. See that method for details.</p>
- *
- * <p>Properties that MAY or SHOULD be specified in the configuration are noted
- * below and in the description of <code>Y.Event.define</code>.</p>
- *
- * @class SyntheticEvent
- * @constructor
- * @param cfg {Object} Implementation pieces and configuration
- * @since 3.1.0
- * @in event-synthetic
- */
- function SyntheticEvent() {
- this._init.apply(this, arguments);
- }
-
- Y.mix(SyntheticEvent, {
- Notifier: Notifier,
- SynthRegistry: SynthRegistry,
-
- /**
- * Returns the array of subscription handles for a node for the given event
- * type. Passing true as the third argument will create a registry entry
- * in the event system's DOM map to host the array if one doesn't yet exist.
- *
- * @method getRegistry
- * @param node {Node} the node
- * @param type {String} the event
- * @param create {Boolean} create a registration entry to host a new array
- * if one doesn't exist.
- * @return {Array}
- * @static
- * @protected
- * @since 3.2.0
- */
- getRegistry: function (node, type, create) {
- var el = node._node,
- yuid = Y.stamp(el),
- key = 'event:' + yuid + type + '_synth',
- events = DOMMap[yuid];
-
- if (create) {
- if (!events) {
- events = DOMMap[yuid] = {};
- }
- if (!events[key]) {
- events[key] = new SynthRegistry(el, yuid, key);
- }
- }
-
- return (events && events[key]) || null;
- },
-
- /**
- * Alternate <code>_delete()</code> method for the CustomEvent object
- * created to manage SyntheticEvent subscriptions.
- *
- * @method _deleteSub
- * @param sub {Subscription} the subscription to clean up
- * @private
- * @since 3.2.0
- */
- _deleteSub: function (sub) {
- if (sub && sub.fn) {
- var synth = this.eventDef,
- method = (sub.filter) ? 'detachDelegate' : 'detach';
-
- this._subscribers = [];
-
- if (CustomEvent.keepDeprecatedSubs) {
- this.subscribers = {};
- }
-
- synth[method](sub.node, sub, this.notifier, sub.filter);
- this.registry.unregister(sub);
-
- delete sub.fn;
- delete sub.node;
- delete sub.context;
- }
- },
-
- prototype: {
- constructor: SyntheticEvent,
-
- /**
- * Construction logic for the event.
- *
- * @method _init
- * @protected
- */
- _init: function () {
- var config = this.publishConfig || (this.publishConfig = {});
-
- // The notification mechanism handles facade creation
- this.emitFacade = ('emitFacade' in config) ?
- config.emitFacade :
- true;
- config.emitFacade = false;
- },
-
- /**
- * <p>Implementers MAY provide this method definition.</p>
- *
- * <p>Implement this function if the event supports a different
- * subscription signature. This function is used by both
- * <code>on()</code> and <code>delegate()</code>. The second parameter
- * indicates that the event is being subscribed via
- * <code>delegate()</code>.</p>
- *
- * <p>Implementations must remove extra arguments from the args list
- * before returning. The required args for <code>on()</code>
- * subscriptions are</p>
- * <pre><code>[type, callback, target, context, argN...]</code></pre>
- *
- * <p>The required args for <code>delegate()</code>
- * subscriptions are</p>
- *
- * <pre><code>[type, callback, target, filter, context, argN...]</code></pre>
- *
- * <p>The return value from this function will be stored on the
- * subscription in the '_extra' property for reference elsewhere.</p>
- *
- * @method processArgs
- * @param args {Array} parmeters passed to Y.on(..) or Y.delegate(..)
- * @param delegate {Boolean} true if the subscription is from Y.delegate
- * @return {any}
- */
- processArgs: noop,
-
- /**
- * <p>Implementers MAY override this property.</p>
- *
- * <p>Whether to prevent multiple subscriptions to this event that are
- * classified as being the same. By default, this means the subscribed
- * callback is the same function. See the <code>subMatch</code>
- * method. Setting this to true will impact performance for high volume
- * events.</p>
- *
- * @property preventDups
- * @type {Boolean}
- * @default false
- */
- //preventDups : false,
-
- /**
- * <p>Implementers SHOULD provide this method definition.</p>
- *
- * Implementation logic for subscriptions done via <code>node.on(type,
- * fn)</code> or <code>Y.on(type, fn, target)</code>. This
- * function should set up the monitor(s) that will eventually fire the
- * event. Typically this involves subscribing to at least one DOM
- * event. It is recommended to store detach handles from any DOM
- * subscriptions to make for easy cleanup in the <code>detach</code>
- * method. Typically these handles are added to the <code>sub</code>
- * object. Also for SyntheticEvents that leverage a single DOM
- * subscription under the hood, it is recommended to pass the DOM event
- * object to <code>notifier.fire(e)</code>. (The event name on the
- * object will be updated).
- *
- * @method on
- * @param node {Node} the node the subscription is being applied to
- * @param sub {Subscription} the object to track this subscription
- * @param notifier {SyntheticEvent.Notifier} call notifier.fire(..) to
- * trigger the execution of the subscribers
- */
- on: noop,
-
- /**
- * <p>Implementers SHOULD provide this method definition.</p>
- *
- * <p>Implementation logic for detaching subscriptions done via
- * <code>node.on(type, fn)</code>. This function should clean up any
- * subscriptions made in the <code>on()</code> phase.</p>
- *
- * @method detach
- * @param node {Node} the node the subscription was applied to
- * @param sub {Subscription} the object tracking this subscription
- * @param notifier {SyntheticEvent.Notifier} the Notifier used to
- * trigger the execution of the subscribers
- */
- detach: noop,
-
- /**
- * <p>Implementers SHOULD provide this method definition.</p>
- *
- * <p>Implementation logic for subscriptions done via
- * <code>node.delegate(type, fn, filter)</code> or
- * <code>Y.delegate(type, fn, container, filter)</code>. Like with
- * <code>on()</code> above, this function should monitor the environment
- * for the event being fired, and trigger subscription execution by
- * calling <code>notifier.fire(e)</code>.</p>
- *
- * <p>This function receives a fourth argument, which is the filter
- * used to identify which Node's are of interest to the subscription.
- * The filter will be either a boolean function that accepts a target
- * Node for each hierarchy level as the event bubbles, or a selector
- * string. To translate selector strings into filter functions, use
- * <code>Y.delegate.compileFilter(filter)</code>.</p>
- *
- * @method delegate
- * @param node {Node} the node the subscription is being applied to
- * @param sub {Subscription} the object to track this subscription
- * @param notifier {SyntheticEvent.Notifier} call notifier.fire(..) to
- * trigger the execution of the subscribers
- * @param filter {String|Function} Selector string or function that
- * accepts an event object and returns null, a Node, or an
- * array of Nodes matching the criteria for processing.
- * @since 3.2.0
- */
- delegate : noop,
-
- /**
- * <p>Implementers SHOULD provide this method definition.</p>
- *
- * <p>Implementation logic for detaching subscriptions done via
- * <code>node.delegate(type, fn, filter)</code> or
- * <code>Y.delegate(type, fn, container, filter)</code>. This function
- * should clean up any subscriptions made in the
- * <code>delegate()</code> phase.</p>
- *
- * @method detachDelegate
- * @param node {Node} the node the subscription was applied to
- * @param sub {Subscription} the object tracking this subscription
- * @param notifier {SyntheticEvent.Notifier} the Notifier used to
- * trigger the execution of the subscribers
- * @param filter {String|Function} Selector string or function that
- * accepts an event object and returns null, a Node, or an
- * array of Nodes matching the criteria for processing.
- * @since 3.2.0
- */
- detachDelegate : noop,
-
- /**
- * Sets up the boilerplate for detaching the event and facilitating the
- * execution of subscriber callbacks.
- *
- * @method _on
- * @param args {Array} array of arguments passed to
- * <code>Y.on(...)</code> or <code>Y.delegate(...)</code>
- * @param delegate {Boolean} true if called from
- * <code>Y.delegate(...)</code>
- * @return {EventHandle} the detach handle for this subscription
- * @private
- * since 3.2.0
- */
- _on: function (args, delegate) {
- var handles = [],
- originalArgs = args.slice(),
- extra = this.processArgs(args, delegate),
- selector = args[2],
- method = delegate ? 'delegate' : 'on',
- nodes, handle;
-
- // Can't just use Y.all because it doesn't support window (yet?)
- nodes = (isString(selector)) ?
- query(selector) :
- toArray(selector || Y.one(Y.config.win));
-
- if (!nodes.length && isString(selector)) {
- handle = Y.on('available', function () {
- Y.mix(handle, Y[method].apply(Y, originalArgs), true);
- }, selector);
-
- return handle;
- }
-
- Y.Array.each(nodes, function (node) {
- var subArgs = args.slice(),
- filter;
-
- node = Y.one(node);
-
- if (node) {
- if (delegate) {
- filter = subArgs.splice(3, 1)[0];
- }
-
- // (type, fn, el, thisObj, ...) => (fn, thisObj, ...)
- subArgs.splice(0, 4, subArgs[1], subArgs[3]);
-
- if (!this.preventDups ||
- !this.getSubs(node, args, null, true))
- {
- handles.push(this._subscribe(node, method, subArgs, extra, filter));
- }
- }
- }, this);
-
- return (handles.length === 1) ?
- handles[0] :
- new Y.EventHandle(handles);
- },
-
- /**
- * Creates a new Notifier object for use by this event's
- * <code>on(...)</code> or <code>delegate(...)</code> implementation
- * and register the custom event proxy in the DOM system for cleanup.
- *
- * @method _subscribe
- * @param node {Node} the Node hosting the event
- * @param method {String} "on" or "delegate"
- * @param args {Array} the subscription arguments passed to either
- * <code>Y.on(...)</code> or <code>Y.delegate(...)</code>
- * after running through <code>processArgs(args)</code> to
- * normalize the argument signature
- * @param extra {any} Extra data parsed from
- * <code>processArgs(args)</code>
- * @param filter {String|Function} the selector string or function
- * filter passed to <code>Y.delegate(...)</code> (not
- * present when called from <code>Y.on(...)</code>)
- * @return {EventHandle}
- * @private
- * @since 3.2.0
- */
- _subscribe: function (node, method, args, extra, filter) {
- var dispatcher = new Y.CustomEvent(this.type, this.publishConfig),
- handle = dispatcher.on.apply(dispatcher, args),
- notifier = new Notifier(handle, this.emitFacade),
- registry = SyntheticEvent.getRegistry(node, this.type, true),
- sub = handle.sub;
-
- sub.node = node;
- sub.filter = filter;
- if (extra) {
- this.applyArgExtras(extra, sub);
- }
-
- Y.mix(dispatcher, {
- eventDef : this,
- notifier : notifier,
- host : node, // I forget what this is for
- currentTarget: node, // for generating facades
- target : node, // for generating facades
- el : node._node, // For category detach
-
- _delete : SyntheticEvent._deleteSub
- }, true);
-
- handle.notifier = notifier;
-
- registry.register(handle);
-
- // Call the implementation's "on" or "delegate" method
- this[method](node, sub, notifier, filter);
-
- return handle;
- },
-
- /**
- * <p>Implementers MAY provide this method definition.</p>
- *
- * <p>Implement this function if you want extra data extracted during
- * processArgs to be propagated to subscriptions on a per-node basis.
- * That is to say, if you call <code>Y.on('xyz', fn, xtra, 'div')</code>
- * the data returned from processArgs will be shared
- * across the subscription objects for all the divs. If you want each
- * subscription to receive unique information, do that processing
- * here.</p>
- *
- * <p>The default implementation adds the data extracted by processArgs
- * to the subscription object as <code>sub._extra</code>.</p>
- *
- * @method applyArgExtras
- * @param extra {any} Any extra data extracted from processArgs
- * @param sub {Subscription} the individual subscription
- */
- applyArgExtras: function (extra, sub) {
- sub._extra = extra;
- },
-
- /**
- * Removes the subscription(s) from the internal subscription dispatch
- * mechanism. See <code>SyntheticEvent._deleteSub</code>.
- *
- * @method _detach
- * @param args {Array} The arguments passed to
- * <code>node.detach(...)</code>
- * @private
- * @since 3.2.0
- */
- _detach: function (args) {
- // Can't use Y.all because it doesn't support window (yet?)
- // TODO: Does Y.all support window now?
- var target = args[2],
- els = (isString(target)) ?
- query(target) : toArray(target),
- node, i, len, handles, j;
-
- // (type, fn, el, context, filter?) => (type, fn, context, filter?)
- args.splice(2, 1);
-
- for (i = 0, len = els.length; i < len; ++i) {
- node = Y.one(els[i]);
-
- if (node) {
- handles = this.getSubs(node, args);
-
- if (handles) {
- for (j = handles.length - 1; j >= 0; --j) {
- handles[j].detach();
- }
- }
- }
- }
- },
-
- /**
- * Returns the detach handles of subscriptions on a node that satisfy a
- * search/filter function. By default, the filter used is the
- * <code>subMatch</code> method.
- *
- * @method getSubs
- * @param node {Node} the node hosting the event
- * @param args {Array} the array of original subscription args passed
- * to <code>Y.on(...)</code> (before
- * <code>processArgs</code>
- * @param filter {Function} function used to identify a subscription
- * for inclusion in the returned array
- * @param first {Boolean} stop after the first match (used to check for
- * duplicate subscriptions)
- * @return {EventHandle[]} detach handles for the matching subscriptions
- */
- getSubs: function (node, args, filter, first) {
- var registry = SyntheticEvent.getRegistry(node, this.type),
- handles = [],
- allHandles, i, len, handle;
-
- if (registry) {
- allHandles = registry.handles;
-
- if (!filter) {
- filter = this.subMatch;
- }
-
- for (i = 0, len = allHandles.length; i < len; ++i) {
- handle = allHandles[i];
- if (filter.call(this, handle.sub, args)) {
- if (first) {
- return handle;
- } else {
- handles.push(allHandles[i]);
- }
- }
- }
- }
-
- return handles.length && handles;
- },
-
- /**
- * <p>Implementers MAY override this to define what constitutes a
- * "same" subscription. Override implementations should
- * consider the lack of a comparator as a match, so calling
- * <code>getSubs()</code> with no arguments will return all subs.</p>
- *
- * <p>Compares a set of subscription arguments against a Subscription
- * object to determine if they match. The default implementation
- * compares the callback function against the second argument passed to
- * <code>Y.on(...)</code> or <code>node.detach(...)</code> etc.</p>
- *
- * @method subMatch
- * @param sub {Subscription} the existing subscription
- * @param args {Array} the calling arguments passed to
- * <code>Y.on(...)</code> etc.
- * @return {Boolean} true if the sub can be described by the args
- * present
- * @since 3.2.0
- */
- subMatch: function (sub, args) {
- // Default detach cares only about the callback matching
- return !args[1] || sub.fn === args[1];
- }
- }
- }, true);
-
- Y.SyntheticEvent = SyntheticEvent;
-
- /**
- * <p>Defines a new event in the DOM event system. Implementers are
- * responsible for monitoring for a scenario whereby the event is fired. A
- * notifier object is provided to the functions identified below. When the
- * criteria defining the event are met, call notifier.fire( [args] ); to
- * execute event subscribers.</p>
- *
- * <p>The first parameter is the name of the event. The second parameter is a
- * configuration object which define the behavior of the event system when the
- * new event is subscribed to or detached from. The methods that should be
- * defined in this configuration object are <code>on</code>,
- * <code>detach</code>, <code>delegate</code>, and <code>detachDelegate</code>.
- * You are free to define any other methods or properties needed to define your
- * event. Be aware, however, that since the object is used to subclass
- * SyntheticEvent, you should avoid method names used by SyntheticEvent unless
- * your intention is to override the default behavior.</p>
- *
- * <p>This is a list of properties and methods that you can or should specify
- * in the configuration object:</p>
- *
- * <dl>
- * <dt><code>on</code></dt>
- * <dd><code>function (node, subscription, notifier)</code> The
- * implementation logic for subscription. Any special setup you need to
- * do to create the environment for the event being fired--E.g. native
- * DOM event subscriptions. Store subscription related objects and
- * state on the <code>subscription</code> object. When the
- * criteria have been met to fire the synthetic event, call
- * <code>notifier.fire(e)</code>. See Notifier's <code>fire()</code>
- * method for details about what to pass as parameters.</dd>
- *
- * <dt><code>detach</code></dt>
- * <dd><code>function (node, subscription, notifier)</code> The
- * implementation logic for cleaning up a detached subscription. E.g.
- * detach any DOM subscriptions added in <code>on</code>.</dd>
- *
- * <dt><code>delegate</code></dt>
- * <dd><code>function (node, subscription, notifier, filter)</code> The
- * implementation logic for subscription via <code>Y.delegate</code> or
- * <code>node.delegate</code>. The filter is typically either a selector
- * string or a function. You can use
- * <code>Y.delegate.compileFilter(selectorString)</code> to create a
- * filter function from a selector string if needed. The filter function
- * expects an event object as input and should output either null, a
- * matching Node, or an array of matching Nodes. Otherwise, this acts
- * like <code>on</code> DOM event subscriptions. Store subscription
- * related objects and information on the <code>subscription</code>
- * object. When the criteria have been met to fire the synthetic event,
- * call <code>notifier.fire(e)</code> as noted above.</dd>
- *
- * <dt><code>detachDelegate</code></dt>
- * <dd><code>function (node, subscription, notifier)</code> The
- * implementation logic for cleaning up a detached delegate subscription.
- * E.g. detach any DOM delegate subscriptions added in
- * <code>delegate</code>.</dd>
- *
- * <dt><code>publishConfig</code></dt>
- * <dd>(Object) The configuration object that will be used to instantiate
- * the underlying CustomEvent. See Notifier's <code>fire</code> method
- * for details.</dd>
- *
- * <dt><code>processArgs</code></dt
- * <dd>
- * <p><code>function (argArray, fromDelegate)</code> Optional method
- * to extract any additional arguments from the subscription
- * signature. Using this allows <code>on</code> or
- * <code>delegate</code> signatures like
- * <code>node.on("hover", overCallback,
- * outCallback)</code>.</p>
- * <p>When processing an atypical argument signature, make sure the
- * args array is returned to the normal signature before returning
- * from the function. For example, in the "hover" example
- * above, the <code>outCallback</code> needs to be <code>splice</code>d
- * out of the array. The expected signature of the args array for
- * <code>on()</code> subscriptions is:</p>
- * <pre>
- * <code>[type, callback, target, contextOverride, argN...]</code>
- * </pre>
- * <p>And for <code>delegate()</code>:</p>
- * <pre>
- * <code>[type, callback, target, filter, contextOverride, argN...]</code>
- * </pre>
- * <p>where <code>target</code> is the node the event is being
- * subscribed for. You can see these signatures documented for
- * <code>Y.on()</code> and <code>Y.delegate()</code> respectively.</p>
- * <p>Whatever gets returned from the function will be stored on the
- * <code>subscription</code> object under
- * <code>subscription._extra</code>.</p></dd>
- * <dt><code>subMatch</code></dt>
- * <dd>
- * <p><code>function (sub, args)</code> Compares a set of
- * subscription arguments against a Subscription object to determine
- * if they match. The default implementation compares the callback
- * function against the second argument passed to
- * <code>Y.on(...)</code> or <code>node.detach(...)</code> etc.</p>
- * </dd>
- * </dl>
- *
- * @method define
- * @param type {String} the name of the event
- * @param config {Object} the prototype definition for the new event (see above)
- * @param force {Boolean} override an existing event (use with caution)
- * @return {SyntheticEvent} the subclass implementation instance created to
- * handle event subscriptions of this type
- * @static
- * @for Event
- * @since 3.1.0
- * @in event-synthetic
- */
- Y.Event.define = function (type, config, force) {
- var eventDef, Impl, synth;
-
- if (type && type.type) {
- eventDef = type;
- force = config;
- } else if (config) {
- eventDef = Y.merge({ type: type }, config);
- }
-
- if (eventDef) {
- if (force || !Y.Node.DOM_EVENTS[eventDef.type]) {
- Impl = function () {
- SyntheticEvent.apply(this, arguments);
- };
- Y.extend(Impl, SyntheticEvent, eventDef);
- synth = new Impl();
-
- type = synth.type;
-
- Y.Node.DOM_EVENTS[type] = Y.Env.evt.plugins[type] = {
- eventDef: synth,
-
- on: function () {
- return synth._on(toArray(arguments));
- },
-
- delegate: function () {
- return synth._on(toArray(arguments), true);
- },
-
- detach: function () {
- return synth._detach(toArray(arguments));
- }
- };
-
- }
- } else if (isString(type) || isArray(type)) {
- Y.Array.each(toArray(type), function (t) {
- Y.Node.DOM_EVENTS[t] = 1;
- });
- }
-
- return synth;
- };
-
-