synthetic.js revision 011173392d3a1a59092095d5a24857134cb16f93
/**
* Define new DOM events that can be subscribed to from Nodes.
*
* @module event
* @submodule event-synthetic
*/
toArray = Y.Array,
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
*/
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 e {EventFacade|DOMEventFacade|Object|any} (see description)
* @param arg* {any} additional arguments received by all subscriptions
* @private
*/
// first arg to delegate notifier should be an object with currentTarget
event = e || {};
if (this.emitFacade) {
if (!e || !e.preventDefault) {
if (isObject(e) && !e.preventDefault) {
} else {
}
}
if (delegate) {
}
}
};
/**
* <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() {
}
Y.mix(SyntheticEvent, {
/**
* 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
*/
type : '_synth',
capture : false,
notifiers : [],
detachAll : function () {
while (--i >= 0) {
}
}
};
}
},
/**
* 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) {
this.subscribers = {};
this.subCount = 0;
}
},
prototype: {
/**
* Construction logic for the event.
*
* @method _init
* @protected
*/
_init: function () {
// The notification mechanism handles facade creation
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}
*/
/**
* <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
*/
/**
* <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
*/
/**
* <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
*/
/**
* <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
*/
/**
* 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
*/
var handles = [],
// Can't just use Y.all because it doesn't support window (yet?)
}, selector);
return handle;
}
if (node) {
if (delegate) {
}
// (type, fn, el, thisObj, ...) => (fn, thisObj, ...)
}
}
}, this);
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.
*
* @method _getNotifier
* @param node {Node} the Node hosting the event
* @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 {SyntheticEvent.Notifier}
* @private
* @since 3.2.0
*/
Y.mix(dispatcher, {
eventDef : this,
}, true);
return handle;
},
/**
* Removes the subscription from the Notifier registry.
*
* @method _unregisterSub
* @param sub {Subscription} the subscription
* @private
* @since 3.2.0
*/
_unregisterSub: function (sub) {
i;
if (notifiers) {
break;
}
}
}
},
/**
* 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
*/
// Can't use Y.all because it doesn't support window (yet?)
// TODO: Does Y.all support window now?
// (type, fn, el, context, filter?) => (type, fn, context, filter?)
if (node) {
if (handles) {
}
}
}
}
},
/**
* Returns the detach handles of subscriptions on a node that satisfy a
* <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 {Array} detach handles for the matching subscriptions
*/
handles = [],
if (notifiers) {
if (!filter) {
}
if (first) {
return handle;
} else {
}
}
}
}
},
/**
* <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
*/
// Default detach cares only about the callback matching
}
}
}, true);
/**
* <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 Event.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)
* @static
* @return {SyntheticEvent} the subclass implementation instance created to
* handle event subscriptions of this type
* @for Event
* @since 3.1.0
* @in event-synthetic
*/
if (!config) {
config = {};
}
Impl = function () {
};
on: function () {
},
delegate: function () {
},
detach: function () {
}
};
}
return synth;
};