source: trunk/web/addons/job_monarch/lib/extjs-30/src/adapter/core/ext-base-event.js @ 625

Last change on this file since 625 was 625, checked in by ramonb, 15 years ago

lib/extjs-30:

  • new ExtJS 3.0
File size: 14.2 KB
Line 
1/*!
2 * Ext JS Library 3.0.0
3 * Copyright(c) 2006-2009 Ext JS, LLC
4 * licensing@extjs.com
5 * http://www.extjs.com/license
6 */
7Ext.lib.Event = function() {
8    var loadComplete = false,
9        listeners = [],
10        unloadListeners = [],
11        retryCount = 0,
12        onAvailStack = [],
13        _interval,
14        locked = false,
15        win = window,
16        doc = document,
17       
18        // constants           
19        POLL_RETRYS = 200,
20        POLL_INTERVAL = 20,
21        EL = 0,
22        TYPE = 1,
23        FN = 2,
24        WFN = 3,
25        OBJ = 3,
26        ADJ_SCOPE = 4,   
27        SCROLLLEFT = 'scrollLeft',
28        SCROLLTOP = 'scrollTop',
29        UNLOAD = 'unload',
30        MOUSEOVER = 'mouseover',
31        MOUSEOUT = 'mouseout',
32        // private
33        doAdd = function() {
34            var ret;
35            if (win.addEventListener) {
36                ret = function(el, eventName, fn, capture) {
37                    if (eventName == 'mouseenter') {
38                        fn = fn.createInterceptor(checkRelatedTarget);
39                        el.addEventListener(MOUSEOVER, fn, (capture));
40                    } else if (eventName == 'mouseleave') {
41                        fn = fn.createInterceptor(checkRelatedTarget);
42                        el.addEventListener(MOUSEOUT, fn, (capture));
43                    } else {
44                        el.addEventListener(eventName, fn, (capture));
45                    }
46                    return fn;
47                };
48            } else if (win.attachEvent) {
49                ret = function(el, eventName, fn, capture) {
50                    el.attachEvent("on" + eventName, fn);
51                    return fn;
52                };
53            } else {
54                ret = function(){};
55            }
56            return ret;
57        }(),   
58        // private
59        doRemove = function(){
60            var ret;
61            if (win.removeEventListener) {
62                ret = function (el, eventName, fn, capture) {
63                    if (eventName == 'mouseenter') {
64                        eventName = MOUSEOVER;
65                    } else if (eventName == 'mouseleave') {
66                        eventName = MOUSEOUT;
67                    }                       
68                    el.removeEventListener(eventName, fn, (capture));
69                };
70            } else if (win.detachEvent) {
71                ret = function (el, eventName, fn) {
72                    el.detachEvent("on" + eventName, fn);
73                };
74            } else {
75                ret = function(){};
76            }
77            return ret;
78        }();       
79
80    var isXUL = Ext.isGecko ? function(node){ 
81        return Object.prototype.toString.call(node) == '[object XULElement]';
82    } : function(){};
83       
84    var isTextNode = Ext.isGecko ? function(node){
85        try{
86            return node.nodeType == 3;
87        }catch(e) {
88            return false;
89        }
90
91    } : function(node){
92        return node.nodeType == 3;
93    };
94       
95    function checkRelatedTarget(e) {
96        var related = pub.getRelatedTarget(e);
97        return !(isXUL(related) || elContains(e.currentTarget,related));
98    }
99
100    function elContains(parent, child) {
101       if(parent && parent.firstChild){ 
102         while(child) {
103            if(child === parent) {
104                return true;
105            }
106            try {
107                child = child.parentNode;
108            } catch(e) {
109                // In FF if you mouseout an text input element
110                // thats inside a div sometimes it randomly throws
111                // Permission denied to get property HTMLDivElement.parentNode
112                // See https://bugzilla.mozilla.org/show_bug.cgi?id=208427
113               
114                return false;
115            }               
116            if(child && (child.nodeType != 1)) {
117                child = null;
118            }
119          }
120        }
121        return false;
122    }
123
124       
125    // private 
126    function _getCacheIndex(el, eventName, fn) {
127        var index = -1;
128        Ext.each(listeners, function (v,i) {
129            if(v && v[FN] == fn && v[EL] == el && v[TYPE] == eventName) {
130                index = i;
131            }
132        });
133        return index;
134    }
135                   
136    // private
137    function _tryPreloadAttach() {
138        var ret = false,               
139            notAvail = [],
140            element,
141            tryAgain = !loadComplete || (retryCount > 0);                       
142       
143        if (!locked) {
144            locked = true;
145           
146            Ext.each(onAvailStack, function (v,i,a){
147                if(v && (element = doc.getElementById(v.id))){
148                    if(!v.checkReady || loadComplete || element.nextSibling || (doc && doc.body)) {
149                        element = v.override ? (v.override === true ? v.obj : v.override) : element;
150                        v.fn.call(element, v.obj);
151                        onAvailStack[i] = null;
152                    } else {
153                        notAvail.push(v);
154                    }
155                }   
156            });
157
158            retryCount = (notAvail.length === 0) ? 0 : retryCount - 1;
159
160            if (tryAgain) { 
161                startInterval();
162            } else {
163                clearInterval(_interval);
164                _interval = null;
165            }
166
167            ret = !(locked = false);
168        }
169        return ret;
170    }
171   
172    // private             
173    function startInterval() {           
174        if(!_interval){                   
175            var callback = function() {
176                _tryPreloadAttach();
177            };
178            _interval = setInterval(callback, POLL_INTERVAL);
179        }
180    }
181   
182    // private
183    function getScroll() {
184        var dd = doc.documentElement, 
185            db = doc.body;
186        if(dd && (dd[SCROLLTOP] || dd[SCROLLLEFT])){
187            return [dd[SCROLLLEFT], dd[SCROLLTOP]];
188        }else if(db){
189            return [db[SCROLLLEFT], db[SCROLLTOP]];
190        }else{
191            return [0, 0];
192        }
193    }
194       
195    // private
196    function getPageCoord (ev, xy) {
197        ev = ev.browserEvent || ev;
198        var coord  = ev['page' + xy];
199        if (!coord && coord !== 0) {
200            coord = ev['client' + xy] || 0;
201
202            if (Ext.isIE) {
203                coord += getScroll()[xy == "X" ? 0 : 1];
204            }
205        }
206
207        return coord;
208    }
209
210    var pub =  {
211        onAvailable : function(p_id, p_fn, p_obj, p_override) {             
212            onAvailStack.push({ 
213                id:         p_id,
214                fn:         p_fn,
215                obj:        p_obj,
216                override:   p_override,
217                checkReady: false });
218
219            retryCount = POLL_RETRYS;
220            startInterval();
221        },
222
223
224        addListener: function(el, eventName, fn) {
225            var ret;               
226            el = Ext.getDom(el);               
227            if (el && fn) {
228                if (UNLOAD == eventName) {
229                    ret = !!(unloadListeners[unloadListeners.length] = [el, eventName, fn]);                   
230                } else {
231                    listeners.push([el, eventName, fn, ret = doAdd(el, eventName, fn, false)]);
232                }
233            }
234            return !!ret;
235        },
236
237        removeListener: function(el, eventName, fn) {
238            var ret = false,
239                index, 
240                cacheItem;
241
242            el = Ext.getDom(el);
243
244            if(!fn) {                   
245                ret = this.purgeElement(el, false, eventName);
246            } else if (UNLOAD == eventName) {   
247                Ext.each(unloadListeners, function(v, i, a) {
248                    if( v && v[0] == el && v[1] == eventName && v[2] == fn) {
249                        unloadListeners.splice(i, 1);
250                        ret = true;
251                    }
252                });
253            } else {   
254                index = arguments[3] || _getCacheIndex(el, eventName, fn);
255                cacheItem = listeners[index];
256               
257                if (el && cacheItem) {
258                    doRemove(el, eventName, cacheItem[WFN], false);     
259                    cacheItem[WFN] = cacheItem[FN] = null;                       
260                    listeners.splice(index, 1);     
261                    ret = true;
262                }
263            }
264            return ret;
265        },
266
267        getTarget : function(ev) {
268            ev = ev.browserEvent || ev;               
269            return this.resolveTextNode(ev.target || ev.srcElement);
270        },
271
272        resolveTextNode : function(node) {
273            return node && !isXUL(node) && isTextNode(node) ? node.parentNode : node;
274        },
275
276        getRelatedTarget : function(ev) {
277            ev = ev.browserEvent || ev;
278            return this.resolveTextNode(ev.relatedTarget || 
279                    (ev.type == MOUSEOUT ? ev.toElement :
280                     ev.type == MOUSEOVER ? ev.fromElement : null));
281        },
282       
283        getPageX : function(ev) {
284            return getPageCoord(ev, "X");
285        },
286
287        getPageY : function(ev) {
288            return getPageCoord(ev, "Y");
289        },
290
291
292        getXY : function(ev) {                             
293            return [this.getPageX(ev), this.getPageY(ev)];
294        },
295
296// Is this useful?  Removing to save space unless use case exists.
297//             getTime: function(ev) {
298//                 ev = ev.browserEvent || ev;
299//                 if (!ev.time) {
300//                     var t = new Date().getTime();
301//                     try {
302//                         ev.time = t;
303//                     } catch(ex) {
304//                         return t;
305//                     }
306//                 }
307
308//                 return ev.time;
309//             },
310
311        stopEvent : function(ev) {                           
312            this.stopPropagation(ev);
313            this.preventDefault(ev);
314        },
315
316        stopPropagation : function(ev) {
317            ev = ev.browserEvent || ev;
318            if (ev.stopPropagation) {
319                ev.stopPropagation();
320            } else {
321                ev.cancelBubble = true;
322            }
323        },
324
325        preventDefault : function(ev) {
326            ev = ev.browserEvent || ev;
327            if (ev.preventDefault) {
328                ev.preventDefault();
329            } else {
330                ev.returnValue = false;
331            }
332        },
333       
334        getEvent : function(e) {
335            e = e || win.event;
336            if (!e) {
337                var c = this.getEvent.caller;
338                while (c) {
339                    e = c.arguments[0];
340                    if (e && Event == e.constructor) {
341                        break;
342                    }
343                    c = c.caller;
344                }
345            }
346            return e;
347        },
348
349        getCharCode : function(ev) {
350            ev = ev.browserEvent || ev;
351            return ev.charCode || ev.keyCode || 0;
352        },
353
354        //clearCache: function() {},
355
356        _load : function(e) {
357            loadComplete = true;
358            var EU = Ext.lib.Event;   
359            if (Ext.isIE && e !== true) {
360        // IE8 complains that _load is null or not an object
361        // so lets remove self via arguments.callee
362                doRemove(win, "load", arguments.callee);
363            }
364        },           
365       
366        purgeElement : function(el, recurse, eventName) {
367            var me = this;
368            Ext.each( me.getListeners(el, eventName), function(v){
369                if(v){
370                    me.removeListener(el, v.type, v.fn);
371                }
372            });
373
374            if (recurse && el && el.childNodes) {
375                Ext.each(el.childNodes, function(v){
376                    me.purgeElement(v, recurse, eventName);
377                });
378            }
379        },
380
381        getListeners : function(el, eventName) {
382            var me = this,
383                results = [], 
384                searchLists;
385
386            if (eventName){ 
387                searchLists = eventName == UNLOAD ? unloadListeners : listeners;
388            }else{
389                searchLists = listeners.concat(unloadListeners);
390            }
391
392            Ext.each(searchLists, function(v, i){
393                if (v && v[EL] == el && (!eventName || eventName == v[TYPE])) {
394                    results.push({
395                                type:   v[TYPE],
396                                fn:     v[FN],
397                                obj:    v[OBJ],
398                                adjust: v[ADJ_SCOPE],
399                                index:  i
400                            });
401                }   
402            });               
403
404            return results.length ? results : null;
405        },
406
407        _unload : function(e) {
408             var EU = Ext.lib.Event, 
409                i, 
410                j, 
411                l, 
412                len, 
413                index,
414                scope;
415               
416
417            Ext.each(unloadListeners, function(v) {
418                if (v) {
419                    try{
420                        scope =  v[ADJ_SCOPE] ? (v[ADJ_SCOPE] === true ? v[OBJ] : v[ADJ_SCOPE]) :  win; 
421                        v[FN].call(scope, EU.getEvent(e), v[OBJ]);
422                    }catch(ex){}
423                }   
424            });     
425
426            unloadListeners = null;
427
428            if(listeners && (j = listeners.length)){                   
429                while(j){                       
430                    if((l = listeners[index = --j])){
431                        EU.removeListener(l[EL], l[TYPE], l[FN], index);
432                    }                       
433                }
434                //EU.clearCache();
435            }
436
437            doRemove(win, UNLOAD, EU._unload);
438        }           
439    };       
440   
441    // Initialize stuff.
442    pub.on = pub.addListener;
443    pub.un = pub.removeListener;
444    if (doc && doc.body) {
445        pub._load(true);
446    } else {
447        doAdd(win, "load", pub._load);
448    }
449    doAdd(win, UNLOAD, pub._unload);   
450    _tryPreloadAttach();
451   
452    return pub;
453}();
Note: See TracBrowser for help on using the repository browser.