3 * Copyright(c) 2006-2010 Ext JS, Inc.
5 * http://www.extjs.com/license
7 Ext.lib.Event = function() {
8 var loadComplete = false,
24 SCROLLLEFT = 'scrollLeft',
25 SCROLLTOP = 'scrollTop',
27 MOUSEOVER = 'mouseover',
28 MOUSEOUT = 'mouseout',
32 if (win.addEventListener) {
33 ret = function(el, eventName, fn, capture) {
34 if (eventName == 'mouseenter') {
35 fn = fn.createInterceptor(checkRelatedTarget);
36 el.addEventListener(MOUSEOVER, fn, (capture));
37 } else if (eventName == 'mouseleave') {
38 fn = fn.createInterceptor(checkRelatedTarget);
39 el.addEventListener(MOUSEOUT, fn, (capture));
41 el.addEventListener(eventName, fn, (capture));
45 } else if (win.attachEvent) {
46 ret = function(el, eventName, fn, capture) {
47 el.attachEvent("on" + eventName, fn);
56 doRemove = function(){
58 if (win.removeEventListener) {
59 ret = function (el, eventName, fn, capture) {
60 if (eventName == 'mouseenter') {
61 eventName = MOUSEOVER;
62 } else if (eventName == 'mouseleave') {
65 el.removeEventListener(eventName, fn, (capture));
67 } else if (win.detachEvent) {
68 ret = function (el, eventName, fn) {
69 el.detachEvent("on" + eventName, fn);
77 function checkRelatedTarget(e) {
78 return !elContains(e.currentTarget, pub.getRelatedTarget(e));
81 function elContains(parent, child) {
82 if(parent && parent.firstChild){
84 if(child === parent) {
87 child = child.parentNode;
88 if(child && (child.nodeType != 1)) {
97 function _tryPreloadAttach() {
100 element, i, v, override,
101 tryAgain = !loadComplete || (retryCount > 0);
106 for(i = 0; i < onAvailStack.length; ++i){
108 if(v && (element = doc.getElementById(v.id))){
109 if(!v.checkReady || loadComplete || element.nextSibling || (doc && doc.body)) {
110 override = v.override;
111 element = override ? (override === true ? v.obj : override) : element;
112 v.fn.call(element, v.obj);
113 onAvailStack.remove(v);
121 retryCount = (notAvail.length === 0) ? 0 : retryCount - 1;
126 clearInterval(_interval);
129 ret = !(locked = false);
135 function startInterval() {
137 var callback = function() {
140 _interval = setInterval(callback, POLL_INTERVAL);
145 function getScroll() {
146 var dd = doc.documentElement,
148 if(dd && (dd[SCROLLTOP] || dd[SCROLLLEFT])){
149 return [dd[SCROLLLEFT], dd[SCROLLTOP]];
151 return [db[SCROLLLEFT], db[SCROLLTOP]];
158 function getPageCoord (ev, xy) {
159 ev = ev.browserEvent || ev;
160 var coord = ev['page' + xy];
161 if (!coord && coord !== 0) {
162 coord = ev['client' + xy] || 0;
165 coord += getScroll()[xy == "X" ? 0 : 1];
174 onAvailable : function(p_id, p_fn, p_obj, p_override) {
179 override: p_override,
180 checkReady: false });
182 retryCount = POLL_RETRYS;
186 // This function should ALWAYS be called from Ext.EventManager
187 addListener: function(el, eventName, fn) {
190 if (eventName == UNLOAD) {
191 if (unloadListeners[el.id] === undefined) {
192 unloadListeners[el.id] = [];
194 unloadListeners[el.id].push([eventName, fn]);
197 return doAdd(el, eventName, fn, false);
202 // This function should ALWAYS be called from Ext.EventManager
203 removeListener: function(el, eventName, fn) {
207 if(eventName == UNLOAD){
208 if((lis = unloadListeners[el.id]) !== undefined){
209 for(i = 0, len = lis.length; i < len; i++){
210 if((li = lis[i]) && li[TYPE] == eventName && li[FN] == fn){
211 unloadListeners[el.id].splice(i, 1);
217 doRemove(el, eventName, fn, false);
221 getTarget : function(ev) {
222 ev = ev.browserEvent || ev;
223 return this.resolveTextNode(ev.target || ev.srcElement);
226 resolveTextNode : Ext.isGecko ? function(node){
230 // work around firefox bug, https://bugzilla.mozilla.org/show_bug.cgi?id=101197
231 var s = HTMLElement.prototype.toString.call(node);
232 if(s == '[xpconnect wrapped native prototype]' || s == '[object XULElement]'){
235 return node.nodeType == 3 ? node.parentNode : node;
237 return node && node.nodeType == 3 ? node.parentNode : node;
240 getRelatedTarget : function(ev) {
241 ev = ev.browserEvent || ev;
242 return this.resolveTextNode(ev.relatedTarget ||
243 (/(mouseout|mouseleave)/.test(ev.type) ? ev.toElement :
244 /(mouseover|mouseenter)/.test(ev.type) ? ev.fromElement : null));
247 getPageX : function(ev) {
248 return getPageCoord(ev, "X");
251 getPageY : function(ev) {
252 return getPageCoord(ev, "Y");
256 getXY : function(ev) {
257 return [this.getPageX(ev), this.getPageY(ev)];
260 stopEvent : function(ev) {
261 this.stopPropagation(ev);
262 this.preventDefault(ev);
265 stopPropagation : function(ev) {
266 ev = ev.browserEvent || ev;
267 if (ev.stopPropagation) {
268 ev.stopPropagation();
270 ev.cancelBubble = true;
274 preventDefault : function(ev) {
275 ev = ev.browserEvent || ev;
276 if (ev.preventDefault) {
279 ev.returnValue = false;
283 getEvent : function(e) {
286 var c = this.getEvent.caller;
289 if (e && Event == e.constructor) {
298 getCharCode : function(ev) {
299 ev = ev.browserEvent || ev;
300 return ev.charCode || ev.keyCode || 0;
303 //clearCache: function() {},
304 // deprecated, call from EventManager
305 getListeners : function(el, eventName) {
306 Ext.EventManager.getListeners(el, eventName);
309 // deprecated, call from EventManager
310 purgeElement : function(el, recurse, eventName) {
311 Ext.EventManager.purgeElement(el, recurse, eventName);
314 _load : function(e) {
317 if (Ext.isIE && e !== true) {
318 // IE8 complains that _load is null or not an object
319 // so lets remove self via arguments.callee
320 doRemove(win, "load", arguments.callee);
324 _unload : function(e) {
325 var EU = Ext.lib.Event,
326 i, v, ul, id, len, scope;
328 for (id in unloadListeners) {
329 ul = unloadListeners[id];
330 for (i = 0, len = ul.length; i < len; i++) {
334 scope = v[ADJ_SCOPE] ? (v[ADJ_SCOPE] === true ? v[OBJ] : v[ADJ_SCOPE]) : win;
335 v[FN].call(scope, EU.getEvent(e), v[OBJ]);
341 Ext.EventManager._unload();
343 doRemove(win, UNLOAD, EU._unload);
348 pub.on = pub.addListener;
349 pub.un = pub.removeListener;
350 if (doc && doc.body) {
353 doAdd(win, "load", pub._load);
355 doAdd(win, UNLOAD, pub._unload);