Upgrade to ExtJS 3.3.1 - Released 11/30/2010
[extjs.git] / docs / source / EventManager.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.3.1
11  * Copyright(c) 2006-2010 Sencha Inc.
12  * licensing@sencha.com
13  * http://www.sencha.com/license
14  */
15 <div id="cls-Ext.EventManager"></div>/**
16  * @class Ext.EventManager
17  * Registers event handlers that want to receive a normalized EventObject instead of the standard browser event and provides
18  * several useful events directly.
19  * See {@link Ext.EventObject} for more details on normalized event objects.
20  * @singleton
21  */
22 Ext.EventManager = function(){
23     var docReadyEvent,
24         docReadyProcId,
25         docReadyState = false,
26         DETECT_NATIVE = Ext.isGecko || Ext.isWebKit || Ext.isSafari,
27         E = Ext.lib.Event,
28         D = Ext.lib.Dom,
29         DOC = document,
30         WINDOW = window,
31         DOMCONTENTLOADED = "DOMContentLoaded",
32         COMPLETE = 'complete',
33         propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,
34         /*
35          * This cache is used to hold special js objects, the document and window, that don't have an id. We need to keep
36          * a reference to them so we can look them up at a later point.
37          */
38         specialElCache = [];
39
40      function getId(el){
41         var id = false,
42             i = 0,
43             len = specialElCache.length,
44             skip = false,
45             o;
46             
47         if (el) {
48             if (el.getElementById || el.navigator) {
49                 // look up the id
50                 for(; i < len; ++i){
51                     o = specialElCache[i];
52                     if(o.el === el){
53                         id = o.id;
54                         break;
55                     }
56                 }
57                 if(!id){
58                     // for browsers that support it, ensure that give the el the same id
59                     id = Ext.id(el);
60                     specialElCache.push({
61                         id: id,
62                         el: el
63                     });
64                     skip = true;
65                 }
66             }else{
67                 id = Ext.id(el);
68             }
69             if(!Ext.elCache[id]){
70                 Ext.Element.addToCache(new Ext.Element(el), id);
71                 if(skip){
72                     Ext.elCache[id].skipGC = true;
73                 }
74             }
75         }
76         return id;
77      }
78
79     /// There is some jquery work around stuff here that isn't needed in Ext Core.
80     function addListener(el, ename, fn, task, wrap, scope){
81         el = Ext.getDom(el);
82         var id = getId(el),
83             es = Ext.elCache[id].events,
84             wfn;
85
86         wfn = E.on(el, ename, wrap);
87         es[ename] = es[ename] || [];
88
89         /* 0 = Original Function,
90            1 = Event Manager Wrapped Function,
91            2 = Scope,
92            3 = Adapter Wrapped Function,
93            4 = Buffered Task
94         */
95         es[ename].push([fn, wrap, scope, wfn, task]);
96
97         // this is a workaround for jQuery and should somehow be removed from Ext Core in the future
98         // without breaking ExtJS.
99
100         // workaround for jQuery
101         if(el.addEventListener && ename == "mousewheel"){
102             var args = ["DOMMouseScroll", wrap, false];
103             el.addEventListener.apply(el, args);
104             Ext.EventManager.addListener(WINDOW, 'unload', function(){
105                 el.removeEventListener.apply(el, args);
106             });
107         }
108
109         // fix stopped mousedowns on the document
110         if(el == DOC && ename == "mousedown"){
111             Ext.EventManager.stoppedMouseDownEvent.addListener(wrap);
112         }
113     }
114
115     function doScrollChk(){
116         /* Notes:
117              'doScroll' will NOT work in a IFRAME/FRAMESET.
118              The method succeeds but, a DOM query done immediately after -- FAILS.
119           */
120         if(window != top){
121             return false;
122         }
123
124         try{
125             DOC.documentElement.doScroll('left');
126         }catch(e){
127              return false;
128         }
129
130         fireDocReady();
131         return true;
132     }
133     <div id="method-Ext.EventManager-function"></div>/**
134      * @return {Boolean} True if the document is in a 'complete' state (or was determined to
135      * be true by other means). If false, the state is evaluated again until canceled.
136      */
137     function checkReadyState(e){
138
139         if(Ext.isIE && doScrollChk()){
140             return true;
141         }
142         if(DOC.readyState == COMPLETE){
143             fireDocReady();
144             return true;
145         }
146         docReadyState || (docReadyProcId = setTimeout(arguments.callee, 2));
147         return false;
148     }
149
150     var styles;
151     function checkStyleSheets(e){
152         styles || (styles = Ext.query('style, link[rel=stylesheet]'));
153         if(styles.length == DOC.styleSheets.length){
154             fireDocReady();
155             return true;
156         }
157         docReadyState || (docReadyProcId = setTimeout(arguments.callee, 2));
158         return false;
159     }
160
161     function OperaDOMContentLoaded(e){
162         DOC.removeEventListener(DOMCONTENTLOADED, arguments.callee, false);
163         checkStyleSheets();
164     }
165
166     function fireDocReady(e){
167         if(!docReadyState){
168             docReadyState = true; //only attempt listener removal once
169
170             if(docReadyProcId){
171                 clearTimeout(docReadyProcId);
172             }
173             if(DETECT_NATIVE) {
174                 DOC.removeEventListener(DOMCONTENTLOADED, fireDocReady, false);
175             }
176             if(Ext.isIE && checkReadyState.bindIE){  //was this was actually set ??
177                 DOC.detachEvent('onreadystatechange', checkReadyState);
178             }
179             E.un(WINDOW, "load", arguments.callee);
180         }
181         if(docReadyEvent && !Ext.isReady){
182             Ext.isReady = true;
183             docReadyEvent.fire();
184             docReadyEvent.listeners = [];
185         }
186
187     }
188
189     function initDocReady(){
190         docReadyEvent || (docReadyEvent = new Ext.util.Event());
191         if (DETECT_NATIVE) {
192             DOC.addEventListener(DOMCONTENTLOADED, fireDocReady, false);
193         }
194         /*
195          * Handle additional (exceptional) detection strategies here
196          */
197         if (Ext.isIE){
198             //Use readystatechange as a backup AND primary detection mechanism for a FRAME/IFRAME
199             //See if page is already loaded
200             if(!checkReadyState()){
201                 checkReadyState.bindIE = true;
202                 DOC.attachEvent('onreadystatechange', checkReadyState);
203             }
204
205         }else if(Ext.isOpera ){
206             /* Notes:
207                Opera needs special treatment needed here because CSS rules are NOT QUITE
208                available after DOMContentLoaded is raised.
209             */
210
211             //See if page is already loaded and all styleSheets are in place
212             (DOC.readyState == COMPLETE && checkStyleSheets()) ||
213                 DOC.addEventListener(DOMCONTENTLOADED, OperaDOMContentLoaded, false);
214
215         }else if (Ext.isWebKit){
216             //Fallback for older Webkits without DOMCONTENTLOADED support
217             checkReadyState();
218         }
219         // no matter what, make sure it fires on load
220         E.on(WINDOW, "load", fireDocReady);
221     }
222
223     function createTargeted(h, o){
224         return function(){
225             var args = Ext.toArray(arguments);
226             if(o.target == Ext.EventObject.setEvent(args[0]).target){
227                 h.apply(this, args);
228             }
229         };
230     }
231
232     function createBuffered(h, o, task){
233         return function(e){
234             // create new event object impl so new events don't wipe out properties
235             task.delay(o.buffer, h, null, [new Ext.EventObjectImpl(e)]);
236         };
237     }
238
239     function createSingle(h, el, ename, fn, scope){
240         return function(e){
241             Ext.EventManager.removeListener(el, ename, fn, scope);
242             h(e);
243         };
244     }
245
246     function createDelayed(h, o, fn){
247         return function(e){
248             var task = new Ext.util.DelayedTask(h);
249             if(!fn.tasks) {
250                 fn.tasks = [];
251             }
252             fn.tasks.push(task);
253             task.delay(o.delay || 10, h, null, [new Ext.EventObjectImpl(e)]);
254         };
255     }
256
257     function listen(element, ename, opt, fn, scope){
258         var o = (!opt || typeof opt == "boolean") ? {} : opt,
259             el = Ext.getDom(element), task;
260
261         fn = fn || o.fn;
262         scope = scope || o.scope;
263
264         if(!el){
265             throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
266         }
267         function h(e){
268             // prevent errors while unload occurring
269             if(!Ext){// !window[xname]){  ==> can't we do this?
270                 return;
271             }
272             e = Ext.EventObject.setEvent(e);
273             var t;
274             if (o.delegate) {
275                 if(!(t = e.getTarget(o.delegate, el))){
276                     return;
277                 }
278             } else {
279                 t = e.target;
280             }
281             if (o.stopEvent) {
282                 e.stopEvent();
283             }
284             if (o.preventDefault) {
285                e.preventDefault();
286             }
287             if (o.stopPropagation) {
288                 e.stopPropagation();
289             }
290             if (o.normalized === false) {
291                 e = e.browserEvent;
292             }
293
294             fn.call(scope || el, e, t, o);
295         }
296         if(o.target){
297             h = createTargeted(h, o);
298         }
299         if(o.delay){
300             h = createDelayed(h, o, fn);
301         }
302         if(o.single){
303             h = createSingle(h, el, ename, fn, scope);
304         }
305         if(o.buffer){
306             task = new Ext.util.DelayedTask(h);
307             h = createBuffered(h, o, task);
308         }
309
310         addListener(el, ename, fn, task, h, scope);
311         return h;
312     }
313
314     var pub = {
315         <div id="method-Ext.EventManager-addListener"></div>/**
316          * Appends an event handler to an element.  The shorthand version {@link #on} is equivalent.  Typically you will
317          * use {@link Ext.Element#addListener} directly on an Element in favor of calling this version.
318          * @param {String/HTMLElement} el The html element or id to assign the event handler to.
319          * @param {String} eventName The name of the event to listen for.
320          * @param {Function} handler The handler function the event invokes. This function is passed
321          * the following parameters:<ul>
322          * <li>evt : EventObject<div class="sub-desc">The {@link Ext.EventObject EventObject} describing the event.</div></li>
323          * <li>t : Element<div class="sub-desc">The {@link Ext.Element Element} which was the target of the event.
324          * Note that this may be filtered by using the <tt>delegate</tt> option.</div></li>
325          * <li>o : Object<div class="sub-desc">The options object from the addListener call.</div></li>
326          * </ul>
327          * @param {Object} scope (optional) The scope (<b><code>this</code></b> reference) in which the handler function is executed. <b>Defaults to the Element</b>.
328          * @param {Object} options (optional) An object containing handler configuration properties.
329          * This may contain any of the following properties:<ul>
330          * <li>scope : Object<div class="sub-desc">The scope (<b><code>this</code></b> reference) in which the handler function is executed. <b>Defaults to the Element</b>.</div></li>
331          * <li>delegate : String<div class="sub-desc">A simple selector to filter the target or look for a descendant of the target</div></li>
332          * <li>stopEvent : Boolean<div class="sub-desc">True to stop the event. That is stop propagation, and prevent the default action.</div></li>
333          * <li>preventDefault : Boolean<div class="sub-desc">True to prevent the default action</div></li>
334          * <li>stopPropagation : Boolean<div class="sub-desc">True to prevent event propagation</div></li>
335          * <li>normalized : Boolean<div class="sub-desc">False to pass a browser event to the handler function instead of an Ext.EventObject</div></li>
336          * <li>delay : Number<div class="sub-desc">The number of milliseconds to delay the invocation of the handler after te event fires.</div></li>
337          * <li>single : Boolean<div class="sub-desc">True to add a handler to handle just the next firing of the event, and then remove itself.</div></li>
338          * <li>buffer : Number<div class="sub-desc">Causes the handler to be scheduled to run in an {@link Ext.util.DelayedTask} delayed
339          * by the specified number of milliseconds. If the event fires again within that time, the original
340          * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</div></li>
341          * <li>target : Element<div class="sub-desc">Only call the handler if the event was fired on the target Element, <i>not</i> if the event was bubbled up from a child node.</div></li>
342          * </ul><br>
343          * <p>See {@link Ext.Element#addListener} for examples of how to use these options.</p>
344          */
345         addListener : function(element, eventName, fn, scope, options){
346             if(typeof eventName == 'object'){
347                 var o = eventName, e, val;
348                 for(e in o){
349                     val = o[e];
350                     if(!propRe.test(e)){
351                         if(Ext.isFunction(val)){
352                             // shared options
353                             listen(element, e, o, val, o.scope);
354                         }else{
355                             // individual options
356                             listen(element, e, val);
357                         }
358                     }
359                 }
360             } else {
361                 listen(element, eventName, options, fn, scope);
362             }
363         },
364
365         <div id="method-Ext.EventManager-removeListener"></div>/**
366          * Removes an event handler from an element.  The shorthand version {@link #un} is equivalent.  Typically
367          * you will use {@link Ext.Element#removeListener} directly on an Element in favor of calling this version.
368          * @param {String/HTMLElement} el The id or html element from which to remove the listener.
369          * @param {String} eventName The name of the event.
370          * @param {Function} fn The handler function to remove. <b>This must be a reference to the function passed into the {@link #addListener} call.</b>
371          * @param {Object} scope If a scope (<b><code>this</code></b> reference) was specified when the listener was added,
372          * then this must refer to the same object.
373          */
374         removeListener : function(el, eventName, fn, scope){
375             el = Ext.getDom(el);
376             var id = getId(el),
377                 f = el && (Ext.elCache[id].events)[eventName] || [],
378                 wrap, i, l, k, len, fnc;
379
380             for (i = 0, len = f.length; i < len; i++) {
381
382                 /* 0 = Original Function,
383                    1 = Event Manager Wrapped Function,
384                    2 = Scope,
385                    3 = Adapter Wrapped Function,
386                    4 = Buffered Task
387                 */
388                 if (Ext.isArray(fnc = f[i]) && fnc[0] == fn && (!scope || fnc[2] == scope)) {
389                     if(fnc[4]) {
390                         fnc[4].cancel();
391                     }
392                     k = fn.tasks && fn.tasks.length;
393                     if(k) {
394                         while(k--) {
395                             fn.tasks[k].cancel();
396                         }
397                         delete fn.tasks;
398                     }
399                     wrap = fnc[1];
400                     E.un(el, eventName, E.extAdapter ? fnc[3] : wrap);
401
402                     // jQuery workaround that should be removed from Ext Core
403                     if(wrap && el.addEventListener && eventName == "mousewheel"){
404                         el.removeEventListener("DOMMouseScroll", wrap, false);
405                     }
406
407                     // fix stopped mousedowns on the document
408                     if(wrap && el == DOC && eventName == "mousedown"){
409                         Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);
410                     }
411
412                     f.splice(i, 1);
413                     if (f.length === 0) {
414                         delete Ext.elCache[id].events[eventName];
415                     }
416                     for (k in Ext.elCache[id].events) {
417                         return false;
418                     }
419                     Ext.elCache[id].events = {};
420                     return false;
421                 }
422             }
423         },
424
425         <div id="method-Ext.EventManager-removeAll"></div>/**
426          * Removes all event handers from an element.  Typically you will use {@link Ext.Element#removeAllListeners}
427          * directly on an Element in favor of calling this version.
428          * @param {String/HTMLElement} el The id or html element from which to remove all event handlers.
429          */
430         removeAll : function(el){
431             el = Ext.getDom(el);
432             var id = getId(el),
433                 ec = Ext.elCache[id] || {},
434                 es = ec.events || {},
435                 f, i, len, ename, fn, k, wrap;
436
437             for(ename in es){
438                 if(es.hasOwnProperty(ename)){
439                     f = es[ename];
440                     /* 0 = Original Function,
441                        1 = Event Manager Wrapped Function,
442                        2 = Scope,
443                        3 = Adapter Wrapped Function,
444                        4 = Buffered Task
445                     */
446                     for (i = 0, len = f.length; i < len; i++) {
447                         fn = f[i];
448                         if(fn[4]) {
449                             fn[4].cancel();
450                         }
451                         if(fn[0].tasks && (k = fn[0].tasks.length)) {
452                             while(k--) {
453                                 fn[0].tasks[k].cancel();
454                             }
455                             delete fn.tasks;
456                         }
457                         wrap =  fn[1];
458                         E.un(el, ename, E.extAdapter ? fn[3] : wrap);
459
460                         // jQuery workaround that should be removed from Ext Core
461                         if(el.addEventListener && wrap && ename == "mousewheel"){
462                             el.removeEventListener("DOMMouseScroll", wrap, false);
463                         }
464
465                         // fix stopped mousedowns on the document
466                         if(wrap && el == DOC &&  ename == "mousedown"){
467                             Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);
468                         }
469                     }
470                 }
471             }
472             if (Ext.elCache[id]) {
473                 Ext.elCache[id].events = {};
474             }
475         },
476
477         getListeners : function(el, eventName) {
478             el = Ext.getDom(el);
479             var id = getId(el),
480                 ec = Ext.elCache[id] || {},
481                 es = ec.events || {},
482                 results = [];
483             if (es && es[eventName]) {
484                 return es[eventName];
485             } else {
486                 return null;
487             }
488         },
489
490         purgeElement : function(el, recurse, eventName) {
491             el = Ext.getDom(el);
492             var id = getId(el),
493                 ec = Ext.elCache[id] || {},
494                 es = ec.events || {},
495                 i, f, len;
496             if (eventName) {
497                 if (es && es.hasOwnProperty(eventName)) {
498                     f = es[eventName];
499                     for (i = 0, len = f.length; i < len; i++) {
500                         Ext.EventManager.removeListener(el, eventName, f[i][0]);
501                     }
502                 }
503             } else {
504                 Ext.EventManager.removeAll(el);
505             }
506             if (recurse && el && el.childNodes) {
507                 for (i = 0, len = el.childNodes.length; i < len; i++) {
508                     Ext.EventManager.purgeElement(el.childNodes[i], recurse, eventName);
509                 }
510             }
511         },
512
513         _unload : function() {
514             var el;
515             for (el in Ext.elCache) {
516                 Ext.EventManager.removeAll(el);
517             }
518             delete Ext.elCache;
519             delete Ext.Element._flyweights;
520
521             // Abort any outstanding Ajax requests
522             var c,
523                 conn,
524                 tid,
525                 ajax = Ext.lib.Ajax;
526             (typeof ajax.conn == 'object') ? conn = ajax.conn : conn = {};
527             for (tid in conn) {
528                 c = conn[tid];
529                 if (c) {
530                     ajax.abort({conn: c, tId: tid});
531                 }
532             }
533         },
534         <div id="method-Ext.EventManager-onDocumentReady"></div>/**
535          * Adds a listener to be notified when the document is ready (before onload and before images are loaded). Can be
536          * accessed shorthanded as Ext.onReady().
537          * @param {Function} fn The method the event invokes.
538          * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the handler function executes. Defaults to the browser window.
539          * @param {boolean} options (optional) Options object as passed to {@link Ext.Element#addListener}. It is recommended that the options
540          * <code>{single: true}</code> be used so that the handler is removed on first invocation.
541          */
542         onDocumentReady : function(fn, scope, options){
543             if (Ext.isReady) { // if it already fired or document.body is present
544                 docReadyEvent || (docReadyEvent = new Ext.util.Event());
545                 docReadyEvent.addListener(fn, scope, options);
546                 docReadyEvent.fire();
547                 docReadyEvent.listeners = [];
548             } else {
549                 if (!docReadyEvent) {
550                     initDocReady();
551                 }
552                 options = options || {};
553                 options.delay = options.delay || 1;
554                 docReadyEvent.addListener(fn, scope, options);
555             }
556         },
557
558         <div id="prop-Ext.EventManager-fireDocReady"></div>/**
559          * Forces a document ready state transition for the framework.  Used when Ext is loaded
560          * into a DOM structure AFTER initial page load (Google API or other dynamic load scenario.
561          * Any pending 'onDocumentReady' handlers will be fired (if not already handled).
562          */
563         fireDocReady  : fireDocReady
564     };
565      <div id="method-Ext.EventManager-on"></div>/**
566      * Appends an event handler to an element.  Shorthand for {@link #addListener}.
567      * @param {String/HTMLElement} el The html element or id to assign the event handler to
568      * @param {String} eventName The name of the event to listen for.
569      * @param {Function} handler The handler function the event invokes.
570      * @param {Object} scope (optional) (<code>this</code> reference) in which the handler function executes. <b>Defaults to the Element</b>.
571      * @param {Object} options (optional) An object containing standard {@link #addListener} options
572      * @member Ext.EventManager
573      * @method on
574      */
575     pub.on = pub.addListener;
576     <div id="method-Ext.EventManager-un"></div>/**
577      * Removes an event handler from an element.  Shorthand for {@link #removeListener}.
578      * @param {String/HTMLElement} el The id or html element from which to remove the listener.
579      * @param {String} eventName The name of the event.
580      * @param {Function} fn The handler function to remove. <b>This must be a reference to the function passed into the {@link #on} call.</b>
581      * @param {Object} scope If a scope (<b><code>this</code></b> reference) was specified when the listener was added,
582      * then this must refer to the same object.
583      * @member Ext.EventManager
584      * @method un
585      */
586     pub.un = pub.removeListener;
587
588     pub.stoppedMouseDownEvent = new Ext.util.Event();
589     return pub;
590 }();
591 <div id="method-Ext-onReady"></div>/**
592   * Adds a listener to be notified when the document is ready (before onload and before images are loaded). Shorthand of {@link Ext.EventManager#onDocumentReady}.
593   * @param {Function} fn The method the event invokes.
594   * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the handler function executes. Defaults to the browser window.
595   * @param {boolean} options (optional) Options object as passed to {@link Ext.Element#addListener}. It is recommended that the options
596   * <code>{single: true}</code> be used so that the handler is removed on first invocation.
597   * @member Ext
598   * @method onReady
599  */
600 Ext.onReady = Ext.EventManager.onDocumentReady;
601
602
603 //Initialize doc classes
604 (function(){
605     var initExtCss = function() {
606         // find the body element
607         var bd = document.body || document.getElementsByTagName('body')[0];
608         if (!bd) {
609             return false;
610         }
611         
612         var cls = [' ',
613                 Ext.isIE ? "ext-ie " + (Ext.isIE6 ? 'ext-ie6' : (Ext.isIE7 ? 'ext-ie7' : 'ext-ie8'))
614                 : Ext.isGecko ? "ext-gecko " + (Ext.isGecko2 ? 'ext-gecko2' : 'ext-gecko3')
615                 : Ext.isOpera ? "ext-opera"
616                 : Ext.isWebKit ? "ext-webkit" : ""];
617
618         if (Ext.isSafari) {
619             cls.push("ext-safari " + (Ext.isSafari2 ? 'ext-safari2' : (Ext.isSafari3 ? 'ext-safari3' : 'ext-safari4')));
620         } else if(Ext.isChrome) {
621             cls.push("ext-chrome");
622         }
623
624         if (Ext.isMac) {
625             cls.push("ext-mac");
626         }
627         if (Ext.isLinux) {
628             cls.push("ext-linux");
629         }
630
631         // add to the parent to allow for selectors like ".ext-strict .ext-ie"
632         if (Ext.isStrict || Ext.isBorderBox) {
633             var p = bd.parentNode;
634             if (p) {
635                 Ext.fly(p, '_internal').addClass(((Ext.isStrict && Ext.isIE ) || (!Ext.enableForcedBoxModel && !Ext.isIE)) ? ' ext-strict' : ' ext-border-box');
636             }
637         }
638         // Forced border box model class applied to all elements. Bypassing javascript based box model adjustments
639         // in favor of css.  This is for non-IE browsers.
640         if (Ext.enableForcedBoxModel && !Ext.isIE) {
641             Ext.isForcedBorderBox = true;
642             cls.push("ext-forced-border-box");
643         }
644         
645         Ext.fly(bd, '_internal').addClass(cls);
646         return true;
647     };
648     
649     if (!initExtCss()) {
650         Ext.onReady(initExtCss);
651     }
652 })();
653
654 <div id="prop-Ext.EventManager-function"></div>/**
655  * Code used to detect certain browser feature/quirks/bugs at startup.
656  */
657 (function(){
658     var supports = Ext.apply(Ext.supports, {
659         <div id="prop-Ext.EventManager-correctRightMargin"></div>/**
660          * In Webkit, there is an issue with getting the margin right property, see
661          * https://bugs.webkit.org/show_bug.cgi?id=13343
662          */
663         correctRightMargin: true,
664         
665         <div id="prop-Ext.EventManager-correctTransparentColor"></div>/**
666          * Webkit browsers return rgba(0, 0, 0) when a transparent color is used
667          */
668         correctTransparentColor: true,
669         
670         <div id="prop-Ext.EventManager-cssFloat"></div>/**
671          * IE uses styleFloat, not cssFloat for the float property.
672          */
673         cssFloat: true
674     });
675     
676     var supportTests = function(){
677             var div = document.createElement('div'),
678                 doc = document,
679                 view,
680                 last;
681                 
682             div.innerHTML = '<div style="height:30px;width:50px;"><div style="height:20px;width:20px;"></div></div><div style="float:left;background-color:transparent;">';
683             doc.body.appendChild(div);
684             last = div.lastChild;
685             
686             if((view = doc.defaultView)){
687                 if(view.getComputedStyle(div.firstChild.firstChild, null).marginRight != '0px'){
688                     supports.correctRightMargin = false;
689                 }
690                 if(view.getComputedStyle(last, null).backgroundColor != 'transparent'){
691                     supports.correctTransparentColor = false;
692                 }
693             }
694             supports.cssFloat = !!last.style.cssFloat;
695             doc.body.removeChild(div);
696     };
697     
698     if (Ext.isReady) {
699         supportTests();    
700     } else {
701         Ext.onReady(supportTests);
702     }
703 })();
704
705
706 <div id="cls-Ext.EventObject"></div>/**
707  * @class Ext.EventObject
708  * Just as {@link Ext.Element} wraps around a native DOM node, Ext.EventObject
709  * wraps the browser's native event-object normalizing cross-browser differences,
710  * such as which mouse button is clicked, keys pressed, mechanisms to stop
711  * event-propagation along with a method to prevent default actions from taking place.
712  * <p>For example:</p>
713  * <pre><code>
714 function handleClick(e, t){ // e is not a standard event object, it is a Ext.EventObject
715     e.preventDefault();
716     var target = e.getTarget(); // same as t (the target HTMLElement)
717     ...
718 }
719 var myDiv = {@link Ext#get Ext.get}("myDiv");  // get reference to an {@link Ext.Element}
720 myDiv.on(         // 'on' is shorthand for addListener
721     "click",      // perform an action on click of myDiv
722     handleClick   // reference to the action handler
723 );
724 // other methods to do the same:
725 Ext.EventManager.on("myDiv", 'click', handleClick);
726 Ext.EventManager.addListener("myDiv", 'click', handleClick);
727  </code></pre>
728  * @singleton
729  */
730 Ext.EventObject = function(){
731     var E = Ext.lib.Event,
732         clickRe = /(dbl)?click/,
733         // safari keypress events for special keys return bad keycodes
734         safariKeys = {
735             3 : 13, // enter
736             63234 : 37, // left
737             63235 : 39, // right
738             63232 : 38, // up
739             63233 : 40, // down
740             63276 : 33, // page up
741             63277 : 34, // page down
742             63272 : 46, // delete
743             63273 : 36, // home
744             63275 : 35  // end
745         },
746         // normalize button clicks
747         btnMap = Ext.isIE ? {1:0,4:1,2:2} : {0:0,1:1,2:2};
748
749     Ext.EventObjectImpl = function(e){
750         if(e){
751             this.setEvent(e.browserEvent || e);
752         }
753     };
754
755     Ext.EventObjectImpl.prototype = {
756            /** @private */
757         setEvent : function(e){
758             var me = this;
759             if(e == me || (e && e.browserEvent)){ // already wrapped
760                 return e;
761             }
762             me.browserEvent = e;
763             if(e){
764                 // normalize buttons
765                 me.button = e.button ? btnMap[e.button] : (e.which ? e.which - 1 : -1);
766                 if(clickRe.test(e.type) && me.button == -1){
767                     me.button = 0;
768                 }
769                 me.type = e.type;
770                 me.shiftKey = e.shiftKey;
771                 // mac metaKey behaves like ctrlKey
772                 me.ctrlKey = e.ctrlKey || e.metaKey || false;
773                 me.altKey = e.altKey;
774                 // in getKey these will be normalized for the mac
775                 me.keyCode = e.keyCode;
776                 me.charCode = e.charCode;
777                 // cache the target for the delayed and or buffered events
778                 me.target = E.getTarget(e);
779                 // same for XY
780                 me.xy = E.getXY(e);
781             }else{
782                 me.button = -1;
783                 me.shiftKey = false;
784                 me.ctrlKey = false;
785                 me.altKey = false;
786                 me.keyCode = 0;
787                 me.charCode = 0;
788                 me.target = null;
789                 me.xy = [0, 0];
790             }
791             return me;
792         },
793
794         <div id="method-Ext.EventObject-stopEvent"></div>/**
795          * Stop the event (preventDefault and stopPropagation)
796          */
797         stopEvent : function(){
798             var me = this;
799             if(me.browserEvent){
800                 if(me.browserEvent.type == 'mousedown'){
801                     Ext.EventManager.stoppedMouseDownEvent.fire(me);
802                 }
803                 E.stopEvent(me.browserEvent);
804             }
805         },
806
807         <div id="method-Ext.EventObject-preventDefault"></div>/**
808          * Prevents the browsers default handling of the event.
809          */
810         preventDefault : function(){
811             if(this.browserEvent){
812                 E.preventDefault(this.browserEvent);
813             }
814         },
815
816         <div id="method-Ext.EventObject-stopPropagation"></div>/**
817          * Cancels bubbling of the event.
818          */
819         stopPropagation : function(){
820             var me = this;
821             if(me.browserEvent){
822                 if(me.browserEvent.type == 'mousedown'){
823                     Ext.EventManager.stoppedMouseDownEvent.fire(me);
824                 }
825                 E.stopPropagation(me.browserEvent);
826             }
827         },
828
829         <div id="method-Ext.EventObject-getCharCode"></div>/**
830          * Gets the character code for the event.
831          * @return {Number}
832          */
833         getCharCode : function(){
834             return this.charCode || this.keyCode;
835         },
836
837         <div id="method-Ext.EventObject-getKey"></div>/**
838          * Returns a normalized keyCode for the event.
839          * @return {Number} The key code
840          */
841         getKey : function(){
842             return this.normalizeKey(this.keyCode || this.charCode);
843         },
844
845         // private
846         normalizeKey: function(k){
847             return Ext.isSafari ? (safariKeys[k] || k) : k;
848         },
849
850         <div id="method-Ext.EventObject-getPageX"></div>/**
851          * Gets the x coordinate of the event.
852          * @return {Number}
853          */
854         getPageX : function(){
855             return this.xy[0];
856         },
857
858         <div id="method-Ext.EventObject-getPageY"></div>/**
859          * Gets the y coordinate of the event.
860          * @return {Number}
861          */
862         getPageY : function(){
863             return this.xy[1];
864         },
865
866         <div id="method-Ext.EventObject-getXY"></div>/**
867          * Gets the page coordinates of the event.
868          * @return {Array} The xy values like [x, y]
869          */
870         getXY : function(){
871             return this.xy;
872         },
873
874         <div id="method-Ext.EventObject-getTarget"></div>/**
875          * Gets the target for the event.
876          * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
877          * @param {Number/Mixed} maxDepth (optional) The max depth to
878                 search as a number or element (defaults to 10 || document.body)
879          * @param {Boolean} returnEl (optional) True to return a Ext.Element object instead of DOM node
880          * @return {HTMLelement}
881          */
882         getTarget : function(selector, maxDepth, returnEl){
883             return selector ? Ext.fly(this.target).findParent(selector, maxDepth, returnEl) : (returnEl ? Ext.get(this.target) : this.target);
884         },
885
886         <div id="method-Ext.EventObject-getRelatedTarget"></div>/**
887          * Gets the related target.
888          * @return {HTMLElement}
889          */
890         getRelatedTarget : function(){
891             return this.browserEvent ? E.getRelatedTarget(this.browserEvent) : null;
892         },
893
894         <div id="method-Ext.EventObject-getWheelDelta"></div>/**
895          * Normalizes mouse wheel delta across browsers
896          * @return {Number} The delta
897          */
898         getWheelDelta : function(){
899             var e = this.browserEvent;
900             var delta = 0;
901             if(e.wheelDelta){ /* IE/Opera. */
902                 delta = e.wheelDelta/120;
903             }else if(e.detail){ /* Mozilla case. */
904                 delta = -e.detail/3;
905             }
906             return delta;
907         },
908
909         <div id="method-Ext.EventObject-within"></div>/**
910         * Returns true if the target of this event is a child of el.  Unless the allowEl parameter is set, it will return false if if the target is el.
911         * Example usage:<pre><code>
912         // Handle click on any child of an element
913         Ext.getBody().on('click', function(e){
914             if(e.within('some-el')){
915                 alert('Clicked on a child of some-el!');
916             }
917         });
918
919         // Handle click directly on an element, ignoring clicks on child nodes
920         Ext.getBody().on('click', function(e,t){
921             if((t.id == 'some-el') && !e.within(t, true)){
922                 alert('Clicked directly on some-el!');
923             }
924         });
925         </code></pre>
926          * @param {Mixed} el The id, DOM element or Ext.Element to check
927          * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
928          * @param {Boolean} allowEl {optional} true to also check if the passed element is the target or related target
929          * @return {Boolean}
930          */
931         within : function(el, related, allowEl){
932             if(el){
933                 var t = this[related ? "getRelatedTarget" : "getTarget"]();
934                 return t && ((allowEl ? (t == Ext.getDom(el)) : false) || Ext.fly(el).contains(t));
935             }
936             return false;
937         }
938      };
939
940     return new Ext.EventObjectImpl();
941 }();
942 </pre>    
943 </body>
944 </html>