1 |
efrain |
1 |
YUI.add('yui2-event-delegate', function(Y) {
|
|
|
2 |
var YAHOO = Y.YUI2;
|
|
|
3 |
/*
|
|
|
4 |
Copyright (c) 2011, Yahoo! Inc. All rights reserved.
|
|
|
5 |
Code licensed under the BSD License:
|
|
|
6 |
http://developer.yahoo.com/yui/license.html
|
|
|
7 |
version: 2.9.0
|
|
|
8 |
*/
|
|
|
9 |
/**
|
|
|
10 |
* Augments the Event Utility with a <code>delegate</code> method that
|
|
|
11 |
* facilitates easy creation of delegated event listeners. (Note: Using CSS
|
|
|
12 |
* selectors as the filtering criteria for delegated event listeners requires
|
|
|
13 |
* inclusion of the Selector Utility.)
|
|
|
14 |
*
|
|
|
15 |
* @module event-delegate
|
|
|
16 |
* @title Event Utility Event Delegation Module
|
|
|
17 |
* @namespace YAHOO.util
|
|
|
18 |
* @requires event
|
|
|
19 |
*/
|
|
|
20 |
|
|
|
21 |
(function () {
|
|
|
22 |
|
|
|
23 |
var Event = YAHOO.util.Event,
|
|
|
24 |
Lang = YAHOO.lang,
|
|
|
25 |
delegates = [],
|
|
|
26 |
|
|
|
27 |
|
|
|
28 |
getMatch = function(el, selector, container) {
|
|
|
29 |
|
|
|
30 |
var returnVal;
|
|
|
31 |
|
|
|
32 |
if (!el || el === container) {
|
|
|
33 |
returnVal = false;
|
|
|
34 |
}
|
|
|
35 |
else {
|
|
|
36 |
returnVal = YAHOO.util.Selector.test(el, selector) ? el: getMatch(el.parentNode, selector, container);
|
|
|
37 |
}
|
|
|
38 |
|
|
|
39 |
return returnVal;
|
|
|
40 |
|
|
|
41 |
};
|
|
|
42 |
|
|
|
43 |
|
|
|
44 |
Lang.augmentObject(Event, {
|
|
|
45 |
|
|
|
46 |
/**
|
|
|
47 |
* Creates a delegate function used to call event listeners specified
|
|
|
48 |
* via the <code>YAHOO.util.Event.delegate</code> method.
|
|
|
49 |
*
|
|
|
50 |
* @method _createDelegate
|
|
|
51 |
*
|
|
|
52 |
* @param {Function} fn The method (event listener) to call.
|
|
|
53 |
* @param {Function|string} filter Function or CSS selector used to
|
|
|
54 |
* determine for what element(s) the event listener should be called.
|
|
|
55 |
* @param {Object} obj An arbitrary object that will be
|
|
|
56 |
* passed as a parameter to the listener.
|
|
|
57 |
* @param {Boolean|object} overrideContext If true, the value of the
|
|
|
58 |
* obj parameter becomes the execution context
|
|
|
59 |
* of the listener. If an object, this object
|
|
|
60 |
* becomes the execution context.
|
|
|
61 |
* @return {Function} Function that will call the event listener
|
|
|
62 |
* specified by the <code>YAHOO.util.Event.delegate</code> method.
|
|
|
63 |
* @private
|
|
|
64 |
* @for Event
|
|
|
65 |
* @static
|
|
|
66 |
*/
|
|
|
67 |
_createDelegate: function (fn, filter, obj, overrideContext) {
|
|
|
68 |
|
|
|
69 |
return function (event) {
|
|
|
70 |
|
|
|
71 |
var container = this,
|
|
|
72 |
target = Event.getTarget(event),
|
|
|
73 |
selector = filter,
|
|
|
74 |
|
|
|
75 |
// The user might have specified the document object
|
|
|
76 |
// as the delegation container, in which case it is not
|
|
|
77 |
// nessary to scope the provided CSS selector(s) to the
|
|
|
78 |
// delegation container
|
|
|
79 |
bDocument = (container.nodeType === 9),
|
|
|
80 |
|
|
|
81 |
matchedEl,
|
|
|
82 |
context,
|
|
|
83 |
sID,
|
|
|
84 |
sIDSelector;
|
|
|
85 |
|
|
|
86 |
|
|
|
87 |
if (Lang.isFunction(filter)) {
|
|
|
88 |
matchedEl = filter(target);
|
|
|
89 |
}
|
|
|
90 |
else if (Lang.isString(filter)) {
|
|
|
91 |
|
|
|
92 |
if (!bDocument) {
|
|
|
93 |
|
|
|
94 |
sID = container.id;
|
|
|
95 |
|
|
|
96 |
if (!sID) {
|
|
|
97 |
sID = Event.generateId(container);
|
|
|
98 |
}
|
|
|
99 |
|
|
|
100 |
// Scope all selectors to the container
|
|
|
101 |
sIDSelector = ("#" + sID + " ");
|
|
|
102 |
selector = (sIDSelector + filter).replace(/,/gi, ("," + sIDSelector));
|
|
|
103 |
|
|
|
104 |
}
|
|
|
105 |
|
|
|
106 |
|
|
|
107 |
if (YAHOO.util.Selector.test(target, selector)) {
|
|
|
108 |
matchedEl = target;
|
|
|
109 |
}
|
|
|
110 |
else if (YAHOO.util.Selector.test(target, ((selector.replace(/,/gi, " *,")) + " *"))) {
|
|
|
111 |
|
|
|
112 |
// The target is a descendant of an element matching
|
|
|
113 |
// the selector, so crawl up to find the ancestor that
|
|
|
114 |
// matches the selector
|
|
|
115 |
|
|
|
116 |
matchedEl = getMatch(target, selector, container);
|
|
|
117 |
|
|
|
118 |
}
|
|
|
119 |
|
|
|
120 |
}
|
|
|
121 |
|
|
|
122 |
|
|
|
123 |
if (matchedEl) {
|
|
|
124 |
|
|
|
125 |
// The default context for delegated listeners is the
|
|
|
126 |
// element that matched the filter.
|
|
|
127 |
|
|
|
128 |
context = matchedEl;
|
|
|
129 |
|
|
|
130 |
if (overrideContext) {
|
|
|
131 |
if (overrideContext === true) {
|
|
|
132 |
context = obj;
|
|
|
133 |
} else {
|
|
|
134 |
context = overrideContext;
|
|
|
135 |
}
|
|
|
136 |
}
|
|
|
137 |
|
|
|
138 |
// Call the listener passing in the container and the
|
|
|
139 |
// element that matched the filter in case the user
|
|
|
140 |
// needs those.
|
|
|
141 |
|
|
|
142 |
return fn.call(context, event, matchedEl, container, obj);
|
|
|
143 |
|
|
|
144 |
}
|
|
|
145 |
|
|
|
146 |
};
|
|
|
147 |
|
|
|
148 |
},
|
|
|
149 |
|
|
|
150 |
|
|
|
151 |
/**
|
|
|
152 |
* Appends a delegated event listener. Delegated event listeners
|
|
|
153 |
* receive three arguments by default: the DOM event, the element
|
|
|
154 |
* specified by the filtering function or CSS selector, and the
|
|
|
155 |
* container element (the element to which the event listener is
|
|
|
156 |
* bound). (Note: Using the delegate method requires the event-delegate
|
|
|
157 |
* module. Using CSS selectors as the filtering criteria for delegated
|
|
|
158 |
* event listeners requires inclusion of the Selector Utility.)
|
|
|
159 |
*
|
|
|
160 |
* @method delegate
|
|
|
161 |
*
|
|
|
162 |
* @param {String|HTMLElement|Array|NodeList} container An id, an element
|
|
|
163 |
* reference, or a collection of ids and/or elements to assign the
|
|
|
164 |
* listener to.
|
|
|
165 |
* @param {String} type The type of event listener to append
|
|
|
166 |
* @param {Function} fn The method the event invokes
|
|
|
167 |
* @param {Function|string} filter Function or CSS selector used to
|
|
|
168 |
* determine for what element(s) the event listener should be called.
|
|
|
169 |
* When a function is specified, the function should return an
|
|
|
170 |
* HTML element. Using a CSS Selector requires the inclusion of the
|
|
|
171 |
* CSS Selector Utility.
|
|
|
172 |
* @param {Object} obj An arbitrary object that will be
|
|
|
173 |
* passed as a parameter to the listener
|
|
|
174 |
* @param {Boolean|object} overrideContext If true, the value of the obj parameter becomes
|
|
|
175 |
* the execution context of the listener. If an
|
|
|
176 |
* object, this object becomes the execution
|
|
|
177 |
* context.
|
|
|
178 |
* @return {Boolean} Returns true if the action was successful or defered,
|
|
|
179 |
* false if one or more of the elements
|
|
|
180 |
* could not have the listener attached,
|
|
|
181 |
* or if the operation throws an exception.
|
|
|
182 |
* @static
|
|
|
183 |
* @for Event
|
|
|
184 |
*/
|
|
|
185 |
delegate: function (container, type, fn, filter, obj, overrideContext) {
|
|
|
186 |
|
|
|
187 |
var sType = type,
|
|
|
188 |
fnMouseDelegate,
|
|
|
189 |
fnDelegate;
|
|
|
190 |
|
|
|
191 |
|
|
|
192 |
if (Lang.isString(filter) && !YAHOO.util.Selector) {
|
|
|
193 |
YAHOO.log("Using a CSS selector to define the filtering criteria for a delegated listener requires the Selector Utility.", "error", "Event");
|
|
|
194 |
return false;
|
|
|
195 |
}
|
|
|
196 |
|
|
|
197 |
|
|
|
198 |
if (type == "mouseenter" || type == "mouseleave") {
|
|
|
199 |
|
|
|
200 |
if (!Event._createMouseDelegate) {
|
|
|
201 |
YAHOO.log("Delegating a " + type + " event requires the event-mouseenter module.", "error", "Event");
|
|
|
202 |
return false;
|
|
|
203 |
}
|
|
|
204 |
|
|
|
205 |
// Look up the real event--either mouseover or mouseout
|
|
|
206 |
sType = Event._getType(type);
|
|
|
207 |
|
|
|
208 |
fnMouseDelegate = Event._createMouseDelegate(fn, obj, overrideContext);
|
|
|
209 |
|
|
|
210 |
fnDelegate = Event._createDelegate(function (event, matchedEl, container) {
|
|
|
211 |
|
|
|
212 |
return fnMouseDelegate.call(matchedEl, event, container);
|
|
|
213 |
|
|
|
214 |
}, filter, obj, overrideContext);
|
|
|
215 |
|
|
|
216 |
}
|
|
|
217 |
else {
|
|
|
218 |
|
|
|
219 |
fnDelegate = Event._createDelegate(fn, filter, obj, overrideContext);
|
|
|
220 |
|
|
|
221 |
}
|
|
|
222 |
|
|
|
223 |
delegates.push([container, sType, fn, fnDelegate]);
|
|
|
224 |
|
|
|
225 |
return Event.on(container, sType, fnDelegate);
|
|
|
226 |
|
|
|
227 |
},
|
|
|
228 |
|
|
|
229 |
|
|
|
230 |
/**
|
|
|
231 |
* Removes a delegated event listener.
|
|
|
232 |
*
|
|
|
233 |
* @method removeDelegate
|
|
|
234 |
*
|
|
|
235 |
* @param {String|HTMLElement|Array|NodeList} container An id, an element
|
|
|
236 |
* reference, or a collection of ids and/or elements to remove
|
|
|
237 |
* the listener from.
|
|
|
238 |
* @param {String} type The type of event to remove.
|
|
|
239 |
* @param {Function} fn The method the event invokes. If fn is
|
|
|
240 |
* undefined, then all event listeners for the type of event are
|
|
|
241 |
* removed.
|
|
|
242 |
* @return {boolean} Returns true if the unbind was successful, false
|
|
|
243 |
* otherwise.
|
|
|
244 |
* @static
|
|
|
245 |
* @for Event
|
|
|
246 |
*/
|
|
|
247 |
removeDelegate: function (container, type, fn) {
|
|
|
248 |
|
|
|
249 |
var sType = type,
|
|
|
250 |
returnVal = false,
|
|
|
251 |
index,
|
|
|
252 |
cacheItem;
|
|
|
253 |
|
|
|
254 |
// Look up the real event--either mouseover or mouseout
|
|
|
255 |
if (type == "mouseenter" || type == "mouseleave") {
|
|
|
256 |
sType = Event._getType(type);
|
|
|
257 |
}
|
|
|
258 |
|
|
|
259 |
index = Event._getCacheIndex(delegates, container, sType, fn);
|
|
|
260 |
|
|
|
261 |
if (index >= 0) {
|
|
|
262 |
cacheItem = delegates[index];
|
|
|
263 |
}
|
|
|
264 |
|
|
|
265 |
|
|
|
266 |
if (container && cacheItem) {
|
|
|
267 |
|
|
|
268 |
returnVal = Event.removeListener(cacheItem[0], cacheItem[1], cacheItem[3]);
|
|
|
269 |
|
|
|
270 |
if (returnVal) {
|
|
|
271 |
delete delegates[index][2];
|
|
|
272 |
delete delegates[index][3];
|
|
|
273 |
delegates.splice(index, 1);
|
|
|
274 |
}
|
|
|
275 |
|
|
|
276 |
}
|
|
|
277 |
|
|
|
278 |
return returnVal;
|
|
|
279 |
|
|
|
280 |
}
|
|
|
281 |
|
|
|
282 |
});
|
|
|
283 |
|
|
|
284 |
}());
|
|
|
285 |
YAHOO.register("event-delegate", YAHOO.util.Event, {version: "2.9.0", build: "2800"});
|
|
|
286 |
|
|
|
287 |
}, '2.9.0' ,{"requires": ["yui2-yahoo", "yui2-event"], "optional": ["yui2-dom", "yui2-selector"]});
|