event-mouseenter.js revision 21f450f4fd5fd60f951de44878aae015ed0342e3
4458N/AYUI.add('event-mouseenter', function(Y) {
4458N/A
4458N/A/**
4458N/A * Adds support for mouseenter/mouseleave events
4458N/A * @module event
4458N/A * @submodule event-mouseenter
4458N/A */
4458N/Avar Event = Y.Event,
4458N/A Lang = Y.Lang,
4458N/A
4458N/A plugins = Y.Env.evt.plugins,
4458N/A
4458N/A listeners = {},
4458N/A
4458N/A getRelatedTarget = function (e) {
4458N/A
4458N/A var target = e.relatedTarget;
4458N/A
4458N/A if (!target) {
4458N/A if (e.type == "mouseout") {
4458N/A target = e.toElement;
4458N/A } else if (e.type == "mouseover") {
5403N/A target = e.fromElement;
4458N/A }
4458N/A }
4458N/A
4458N/A return target;
4458N/A
5403N/A },
5403N/A
5403N/A eventConfig = {
4458N/A
4458N/A on: function(type, fn, el) {
4458N/A
5403N/A var args = Y.Array(arguments, 0, true),
4458N/A element = el,
4458N/A handles;
4458N/A
4458N/A
4458N/A if (Lang.isString(el)) {
5403N/A
4458N/A // Need to use Y.all because if el is a string it could be a
4458N/A // selector that returns a NodeList
4458N/A
4458N/A element = Y.all(el);
4458N/A
4458N/A if (element.size() === 0) { // Not found, check using onAvailable
4458N/A
4458N/A return Event.onAvailable(el, function() {
4458N/A Y.on.apply(Y, args);
4458N/A }, Event, true, false);
4458N/A
4458N/A }
4458N/A
4458N/A }
4458N/A
4458N/A
5403N/A if (element instanceof Y.NodeList || Event._isValidCollection(element)) { // Array or NodeList
5403N/A
5403N/A handles = [];
4458N/A
4458N/A Y.each(element, function(v, k) {
4458N/A args[2] = v;
4458N/A handles.push(Y.on.apply(Y, args));
4458N/A });
4458N/A
4458N/A return (handles.length === 1) ? handles[0] : handles;
5403N/A
4458N/A }
4458N/A
4458N/A
4458N/A // At this point el will always be a Node instance
4458N/A element = Y.Node.getDOMNode(el);
4458N/A
4458N/A
4458N/A var sDOMEvent = (type === "mouseenter") ? "mouseover" : "mouseout",
4458N/A
4458N/A // The name of the custom event
4458N/A sEventName = type + ":" + Y.stamp(element) + sDOMEvent,
4458N/A
4458N/A listener = listeners[sEventName],
4458N/A
4458N/A domEventHandle,
4458N/A
4458N/A ceHandle,
4458N/A
4458N/A nListeners;
4458N/A
4458N/A
4458N/A // Bind an actual DOM event listener that will call the
4458N/A // the custom event
4458N/A if (!listener) {
4458N/A
5403N/A domEventHandle = Event._attach([sDOMEvent, Y.rbind(Event._fireMouseEnter, Y, element, sEventName), element], { facade: false });
5403N/A
4458N/A // Hook into the _delete method for the Custom Event wrapper of this
4458N/A // DOM Event in order to clean up the 'listeners' map and unsubscribe
4458N/A // the associated Custom Event listeners fired by this DOM event
4458N/A // listener if/when the user calls "purgeElement" OR removes all
4458N/A // listeners of the Custom Event.
4458N/A
4458N/A Y.after(function (sub) {
if (domEventHandle.sub == sub) {
// Delete this event from the map of known mouseenter
// and mouseleave listeners
delete listeners[sEventName];
// Unsubscribe all listeners of the Custom Event fired
// by this DOM event.
Y.detachAll(sEventName);
}
}, domEventHandle.evt, "_delete");
listener = {};
listener.handle = domEventHandle;
listeners[sEventName] = listener;
}
nListeners = listener.count;
listener.count = nListeners ? (nListeners + 1) : 1;
args[0] = sEventName;
// Remove the element from the args
args.splice(2, 1);
// Subscribe to the custom event
ceHandle = Y.on.apply(Y, args);
// Hook into the detach method of the handle in order to clean up the
// 'listeners' map and remove the associated DOM event handler
// responsible for firing this Custom Event if all listener for this
// event have been removed.
Y.after(function () {
listener.count = (listener.count - 1);
if (listener.count === 0) {
listener.handle.detach();
}
}, ceHandle, "detach");
return ceHandle;
}
};
Event._fireMouseEnter = function (e, currentTarget, eventName) {
var relatedTarget = getRelatedTarget(e),
eventFacade;
if (currentTarget !== relatedTarget &&
!Y.DOM.contains(currentTarget, relatedTarget)) {
eventFacade = new Y.DOMEventFacade(e, currentTarget);
Y.publish(eventName, {
contextFn: function() {
return eventFacade.currentTarget;
}
});
Y.fire(eventName, eventFacade);
}
};
/**
* Sets up a "mouseenter" listener—a listener that is called the first time
* the user's mouse enters the specified element(s).
*
* @event mouseenter
* @param type {string} "mouseenter"
* @param fn {function} The method the event invokes.
* @param el {string|node} The element(s) to assign the listener to.
* @param spec {string} Optional. String representing a selector that must
* match the target of the event in order for the listener to be called.
* @return {EventHandle} the detach handle
* @for YUI
*/
plugins.mouseenter = eventConfig;
/**
* Sets up a "mouseleave" listener—a listener that is called the first time
* the user's mouse leaves the specified element(s).
*
* @event mouseleave
* @param type {string} "mouseleave"
* @param fn {function} The method the event invokes.
* @param el {string|node} The element(s) to assign the listener to.
* @param spec {string} Optional. String representing a selector that must
* match the target of the event in order for the listener to be called.
* @return {EventHandle} the detach handle
* @for YUI
*/
plugins.mouseleave = eventConfig;
}, '@VERSION@' ,{requires:['node-base']});