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