3 * Copyright(c) 2006-2010 Ext JS, LLC
5 * http://www.extjs.com/license
7 Ext.lib.Event = function() {
8 var loadComplete = false,
26 SCROLLLEFT = 'scrollLeft',
27 SCROLLTOP = 'scrollTop',
29 MOUSEOVER = 'mouseover',
30 MOUSEOUT = 'mouseout',
34 if (win.addEventListener) {
35 ret = function(el, eventName, fn, capture) {
36 if (eventName == 'mouseenter') {
37 fn = fn.createInterceptor(checkRelatedTarget);
38 el.addEventListener(MOUSEOVER, fn, (capture));
39 } else if (eventName == 'mouseleave') {
40 fn = fn.createInterceptor(checkRelatedTarget);
41 el.addEventListener(MOUSEOUT, fn, (capture));
43 el.addEventListener(eventName, fn, (capture));
47 } else if (win.attachEvent) {
48 ret = function(el, eventName, fn, capture) {
49 el.attachEvent("on" + eventName, fn);
58 doRemove = function(){
60 if (win.removeEventListener) {
61 ret = function (el, eventName, fn, capture) {
62 if (eventName == 'mouseenter') {
63 eventName = MOUSEOVER;
64 } else if (eventName == 'mouseleave') {
67 el.removeEventListener(eventName, fn, (capture));
69 } else if (win.detachEvent) {
70 ret = function (el, eventName, fn) {
71 el.detachEvent("on" + eventName, fn);
79 function checkRelatedTarget(e) {
80 return !elContains(e.currentTarget, pub.getRelatedTarget(e));
83 function elContains(parent, child) {
84 if(parent && parent.firstChild){
86 if(child === parent) {
89 child = child.parentNode;
90 if(child && (child.nodeType != 1)) {
99 function _tryPreloadAttach() {
103 tryAgain = !loadComplete || (retryCount > 0);
108 for (i = 0, len = onAvailStack.length; i < len; i++) {
110 if(v && (element = doc.getElementById(v.id))){
111 if(!v.checkReady || loadComplete || element.nextSibling || (doc && doc.body)) {
112 element = v.override ? (v.override === true ? v.obj : v.override) : element;
113 v.fn.call(element, v.obj);
114 onAvailStack.remove(v);
121 retryCount = (notAvail.length === 0) ? 0 : retryCount - 1;
126 clearInterval(_interval);
130 ret = !(locked = false);
136 function startInterval() {
138 var callback = function() {
141 _interval = setInterval(callback, POLL_INTERVAL);
146 function getScroll() {
147 var dd = doc.documentElement,
149 if(dd && (dd[SCROLLTOP] || dd[SCROLLLEFT])){
150 return [dd[SCROLLLEFT], dd[SCROLLTOP]];
152 return [db[SCROLLLEFT], db[SCROLLTOP]];
159 function getPageCoord (ev, xy) {
160 ev = ev.browserEvent || ev;
161 var coord = ev['page' + xy];
162 if (!coord && coord !== 0) {
163 coord = ev['client' + xy] || 0;
166 coord += getScroll()[xy == "X" ? 0 : 1];
175 onAvailable : function(p_id, p_fn, p_obj, p_override) {
180 override: p_override,
181 checkReady: false });
183 retryCount = POLL_RETRYS;
187 // This function should ALWAYS be called from Ext.EventManager
188 addListener: function(el, eventName, fn) {
191 if (eventName == UNLOAD) {
192 if (unloadListeners[el.id] === undefined) {
193 unloadListeners[el.id] = [];
195 unloadListeners[el.id].push([eventName, fn]);
198 return doAdd(el, eventName, fn, false);
203 // This function should ALWAYS be called from Ext.EventManager
204 removeListener: function(el, eventName, fn) {
208 if(eventName == UNLOAD){
209 if((lis = unloadListeners[el.id]) !== undefined){
210 for(i = 0, len = lis.length; i < len; i++){
211 if((li = lis[i]) && li[TYPE] == eventName && li[FN] == fn){
212 unloadListeners[el.id].splice(i, 1);
218 doRemove(el, eventName, fn, false);
222 getTarget : function(ev) {
223 ev = ev.browserEvent || ev;
224 return this.resolveTextNode(ev.target || ev.srcElement);
227 resolveTextNode : Ext.isGecko ? function(node){
231 // work around firefox bug, https://bugzilla.mozilla.org/show_bug.cgi?id=101197
232 var s = HTMLElement.prototype.toString.call(node);
233 if(s == '[xpconnect wrapped native prototype]' || s == '[object XULElement]'){
236 return node.nodeType == 3 ? node.parentNode : node;
238 return node && node.nodeType == 3 ? node.parentNode : node;
241 getRelatedTarget : function(ev) {
242 ev = ev.browserEvent || ev;
243 return this.resolveTextNode(ev.relatedTarget ||
244 (ev.type == MOUSEOUT ? ev.toElement :
245 ev.type == MOUSEOVER ? ev.fromElement : null));
248 getPageX : function(ev) {
249 return getPageCoord(ev, "X");
252 getPageY : function(ev) {
253 return getPageCoord(ev, "Y");
257 getXY : function(ev) {
258 return [this.getPageX(ev), this.getPageY(ev)];
261 stopEvent : function(ev) {
262 this.stopPropagation(ev);
263 this.preventDefault(ev);
266 stopPropagation : function(ev) {
267 ev = ev.browserEvent || ev;
268 if (ev.stopPropagation) {
269 ev.stopPropagation();
271 ev.cancelBubble = true;
275 preventDefault : function(ev) {
276 ev = ev.browserEvent || ev;
277 if (ev.preventDefault) {
280 ev.returnValue = false;
284 getEvent : function(e) {
287 var c = this.getEvent.caller;
290 if (e && Event == e.constructor) {
299 getCharCode : function(ev) {
300 ev = ev.browserEvent || ev;
301 return ev.charCode || ev.keyCode || 0;
304 //clearCache: function() {},
305 // deprecated, call from EventManager
306 getListeners : function(el, eventName) {
307 Ext.EventManager.getListeners(el, eventName);
310 // deprecated, call from EventManager
311 purgeElement : function(el, recurse, eventName) {
312 Ext.EventManager.purgeElement(el, recurse, eventName);
315 _load : function(e) {
317 var EU = Ext.lib.Event;
318 if (Ext.isIE && e !== true) {
319 // IE8 complains that _load is null or not an object
320 // so lets remove self via arguments.callee
321 doRemove(win, "load", arguments.callee);
325 _unload : function(e) {
326 var EU = Ext.lib.Event,
327 i, j, l, v, ul, id, len, index, scope;
330 for (id in unloadListeners) {
331 ul = unloadListeners[id];
332 for (i = 0, len = ul.length; i < len; i++) {
336 scope = v[ADJ_SCOPE] ? (v[ADJ_SCOPE] === true ? v[OBJ] : v[ADJ_SCOPE]) : win;
337 v[FN].call(scope, EU.getEvent(e), v[OBJ]);
343 unloadListeners = null;
344 Ext.EventManager._unload();
346 doRemove(win, UNLOAD, EU._unload);
351 pub.on = pub.addListener;
352 pub.un = pub.removeListener;
353 if (doc && doc.body) {
356 doAdd(win, "load", pub._load);
358 doAdd(win, UNLOAD, pub._unload);