Upgrade to ExtJS 3.1.0 - Released 12/16/2009
[extjs.git] / docs / source / ext-base-event.html
1 <html>\r
2 <head>\r
3   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />    \r
4   <title>The source code</title>\r
5     <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />\r
6     <script type="text/javascript" src="../resources/prettify/prettify.js"></script>\r
7 </head>\r
8 <body  onload="prettyPrint();">\r
9     <pre class="prettyprint lang-js">Ext.lib.Event = function() {
10     var loadComplete = false,
11         unloadListeners = {},
12         retryCount = 0,
13         onAvailStack = [],
14         _interval,
15         locked = false,
16         win = window,
17         doc = document,
18
19         // constants
20         POLL_RETRYS = 200,
21         POLL_INTERVAL = 20,
22         EL = 0,
23         TYPE = 0,
24         FN = 1,
25         WFN = 2,
26         OBJ = 2,
27         ADJ_SCOPE = 3,
28         SCROLLLEFT = 'scrollLeft',
29         SCROLLTOP = 'scrollTop',
30         UNLOAD = 'unload',
31         MOUSEOVER = 'mouseover',
32         MOUSEOUT = 'mouseout',
33         // private
34         doAdd = function() {
35             var ret;
36             if (win.addEventListener) {
37                 ret = function(el, eventName, fn, capture) {
38                     if (eventName == 'mouseenter') {
39                         fn = fn.createInterceptor(checkRelatedTarget);
40                         el.addEventListener(MOUSEOVER, fn, (capture));
41                     } else if (eventName == 'mouseleave') {
42                         fn = fn.createInterceptor(checkRelatedTarget);
43                         el.addEventListener(MOUSEOUT, fn, (capture));
44                     } else {
45                         el.addEventListener(eventName, fn, (capture));
46                     }
47                     return fn;
48                 };
49             } else if (win.attachEvent) {
50                 ret = function(el, eventName, fn, capture) {
51                     el.attachEvent("on" + eventName, fn);
52                     return fn;
53                 };
54             } else {
55                 ret = function(){};
56             }
57             return ret;
58         }(),
59         // private
60         doRemove = function(){
61             var ret;
62             if (win.removeEventListener) {
63                 ret = function (el, eventName, fn, capture) {
64                     if (eventName == 'mouseenter') {
65                         eventName = MOUSEOVER;
66                     } else if (eventName == 'mouseleave') {
67                         eventName = MOUSEOUT;
68                     }
69                     el.removeEventListener(eventName, fn, (capture));
70                 };
71             } else if (win.detachEvent) {
72                 ret = function (el, eventName, fn) {
73                     el.detachEvent("on" + eventName, fn);
74                 };
75             } else {
76                 ret = function(){};
77             }
78             return ret;
79         }();
80
81     function checkRelatedTarget(e) {
82         return !elContains(e.currentTarget, pub.getRelatedTarget(e));
83     }
84
85     function elContains(parent, child) {
86        if(parent && parent.firstChild){
87          while(child) {
88             if(child === parent) {
89                 return true;
90             }
91             child = child.parentNode;
92             if(child && (child.nodeType != 1)) {
93                 child = null;
94             }
95           }
96         }
97         return false;
98     }
99
100     // private
101     function _tryPreloadAttach() {
102         var ret = false,
103             notAvail = [],
104             element, i, len, v,
105             tryAgain = !loadComplete || (retryCount > 0);
106
107         if (!locked) {
108             locked = true;
109
110             for (i = 0, len = onAvailStack.length; i < len; i++) {
111                 v = onAvailStack[i];
112                 if(v && (element = doc.getElementById(v.id))){
113                     if(!v.checkReady || loadComplete || element.nextSibling || (doc && doc.body)) {
114                         element = v.override ? (v.override === true ? v.obj : v.override) : element;
115                         v.fn.call(element, v.obj);
116                         v = null;
117                     } else {
118                         notAvail.push(v);
119                     }
120                 }
121             }
122
123             retryCount = (notAvail.length === 0) ? 0 : retryCount - 1;
124
125             if (tryAgain) {
126                 startInterval();
127             } else {
128                 clearInterval(_interval);
129                 _interval = null;
130             }
131
132             ret = !(locked = false);
133         }
134         return ret;
135     }
136
137     // private
138     function startInterval() {
139         if(!_interval){
140             var callback = function() {
141                 _tryPreloadAttach();
142             };
143             _interval = setInterval(callback, POLL_INTERVAL);
144         }
145     }
146
147     // private
148     function getScroll() {
149         var dd = doc.documentElement,
150             db = doc.body;
151         if(dd && (dd[SCROLLTOP] || dd[SCROLLLEFT])){
152             return [dd[SCROLLLEFT], dd[SCROLLTOP]];
153         }else if(db){
154             return [db[SCROLLLEFT], db[SCROLLTOP]];
155         }else{
156             return [0, 0];
157         }
158     }
159
160     // private
161     function getPageCoord (ev, xy) {
162         ev = ev.browserEvent || ev;
163         var coord  = ev['page' + xy];
164         if (!coord && coord !== 0) {
165             coord = ev['client' + xy] || 0;
166
167             if (Ext.isIE) {
168                 coord += getScroll()[xy == "X" ? 0 : 1];
169             }
170         }
171
172         return coord;
173     }
174
175     var pub =  {
176         extAdapter: true,
177         onAvailable : function(p_id, p_fn, p_obj, p_override) {
178             onAvailStack.push({
179                 id:         p_id,
180                 fn:         p_fn,
181                 obj:        p_obj,
182                 override:   p_override,
183                 checkReady: false });
184
185             retryCount = POLL_RETRYS;
186             startInterval();
187         },
188
189         // This function should ALWAYS be called from Ext.EventManager
190         addListener: function(el, eventName, fn) {
191             el = Ext.getDom(el);
192             if (el && fn) {
193                 if (eventName == UNLOAD) {
194                     if (unloadListeners[el.id] === undefined) {
195                         unloadListeners[el.id] = [];
196                     }
197                     unloadListeners[el.id].push([eventName, fn]);
198                     return fn;
199                 }
200                 return doAdd(el, eventName, fn, false);
201             }
202             return false;
203         },
204
205         // This function should ALWAYS be called from Ext.EventManager
206         removeListener: function(el, eventName, fn) {
207             el = Ext.getDom(el);
208             var i, len, li;
209             if (el && fn) {
210                 if (eventName == UNLOAD) {
211                     if (unloadListeners[id] !== undefined) {
212                         for (i = 0, len = unloadListeners[id].length; i < len; i++) {
213                             li = unloadListeners[id][i];
214                             if (li && li[TYPE] == eventName && li[FN] == fn) {
215                                 unloadListeners[id].splice(i, 1);
216                             }
217                         }
218                     }
219                     return;
220                 }
221                 doRemove(el, eventName, fn, false);
222             }
223         },
224
225         getTarget : function(ev) {
226             ev = ev.browserEvent || ev;
227             return this.resolveTextNode(ev.target || ev.srcElement);
228         },
229
230         resolveTextNode : Ext.isGecko ? function(node){
231             if(!node){
232                 return;
233             }
234             // work around firefox bug, https://bugzilla.mozilla.org/show_bug.cgi?id=101197
235             var s = HTMLElement.prototype.toString.call(node);
236             if(s == '[xpconnect wrapped native prototype]' || s == '[object XULElement]'){
237                 return;
238             }
239             return node.nodeType == 3 ? node.parentNode : node;
240         } : function(node){
241             return node && node.nodeType == 3 ? node.parentNode : node;
242         },
243
244         getRelatedTarget : function(ev) {
245             ev = ev.browserEvent || ev;
246             return this.resolveTextNode(ev.relatedTarget ||
247                     (ev.type == MOUSEOUT ? ev.toElement :
248                      ev.type == MOUSEOVER ? ev.fromElement : null));
249         },
250
251         getPageX : function(ev) {
252             return getPageCoord(ev, "X");
253         },
254
255         getPageY : function(ev) {
256             return getPageCoord(ev, "Y");
257         },
258
259
260         getXY : function(ev) {
261             return [this.getPageX(ev), this.getPageY(ev)];
262         },
263
264         stopEvent : function(ev) {
265             this.stopPropagation(ev);
266             this.preventDefault(ev);
267         },
268
269         stopPropagation : function(ev) {
270             ev = ev.browserEvent || ev;
271             if (ev.stopPropagation) {
272                 ev.stopPropagation();
273             } else {
274                 ev.cancelBubble = true;
275             }
276         },
277
278         preventDefault : function(ev) {
279             ev = ev.browserEvent || ev;
280             if (ev.preventDefault) {
281                 ev.preventDefault();
282             } else {
283                 ev.returnValue = false;
284             }
285         },
286
287         getEvent : function(e) {
288             e = e || win.event;
289             if (!e) {
290                 var c = this.getEvent.caller;
291                 while (c) {
292                     e = c.arguments[0];
293                     if (e && Event == e.constructor) {
294                         break;
295                     }
296                     c = c.caller;
297                 }
298             }
299             return e;
300         },
301
302         getCharCode : function(ev) {
303             ev = ev.browserEvent || ev;
304             return ev.charCode || ev.keyCode || 0;
305         },
306
307         //clearCache: function() {},
308         // deprecated, call from EventManager
309         getListeners : function(el, eventName) {
310             Ext.EventManager.getListeners(el, eventName);
311         },
312
313         // deprecated, call from EventManager
314         purgeElement : function(el, recurse, eventName) {
315             Ext.EventManager.purgeElement(el, recurse, eventName);
316         },
317
318         _load : function(e) {
319             loadComplete = true;
320             var EU = Ext.lib.Event;
321             if (Ext.isIE && e !== true) {
322         // IE8 complains that _load is null or not an object
323         // so lets remove self via arguments.callee
324                 doRemove(win, "load", arguments.callee);
325             }
326         },
327
328         _unload : function(e) {
329              var EU = Ext.lib.Event,
330                 i, j, l, v, ul, id, len, index, scope;
331
332
333             for (id in unloadListeners) {
334                 ul = unloadListeners[id];
335                 for (i = 0, len = ul.length; i < len; i++) {
336                     v = ul[i];
337                     if (v) {
338                         try{
339                             scope = v[ADJ_SCOPE] ? (v[ADJ_SCOPE] === true ? v[OBJ] : v[ADJ_SCOPE]) :  win;
340                             v[FN].call(scope, EU.getEvent(e), v[OBJ]);
341                         }catch(ex){}
342                     }
343                 }
344             };
345
346             unloadListeners = null;
347             Ext.EventManager._unload();
348
349             doRemove(win, UNLOAD, EU._unload);
350         }
351     };
352
353     // Initialize stuff.
354     pub.on = pub.addListener;
355     pub.un = pub.removeListener;
356     if (doc && doc.body) {
357         pub._load(true);
358     } else {
359         doAdd(win, "load", pub._load);
360     }
361     doAdd(win, UNLOAD, pub._unload);
362     _tryPreloadAttach();
363
364     return pub;
365 }();
366 </pre>    \r
367 </body>\r
368 </html>