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