EventManager.js
上传用户:dawnssy
上传日期:2022-08-06
资源大小:9345k
文件大小:30k
源码类别:

JavaScript

开发平台:

JavaScript

  1. /*!  * Ext JS Library 3.1.0  * Copyright(c) 2006-2009 Ext JS, LLC  * licensing@extjs.com  * http://www.extjs.com/license  */ /**
  2.  * @class Ext.EventManager
  3.  * Registers event handlers that want to receive a normalized EventObject instead of the standard browser event and provides
  4.  * several useful events directly.
  5.  * See {@link Ext.EventObject} for more details on normalized event objects.
  6.  * @singleton
  7.  */
  8. Ext.EventManager = function(){
  9.     var docReadyEvent,
  10.         docReadyProcId,
  11.         docReadyState = false,
  12.         E = Ext.lib.Event,
  13.         D = Ext.lib.Dom,
  14.         DOC = document,
  15.         WINDOW = window,
  16.         IEDEFERED = "ie-deferred-loader",
  17.         DOMCONTENTLOADED = "DOMContentLoaded",
  18.         propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,
  19.         /*
  20.          * This cache is used to hold special js objects, the document and window, that don't have an id. We need to keep
  21.          * a reference to them so we can look them up at a later point.
  22.          */
  23.         specialElCache = [];
  24.      function getId(el){
  25.         var id = false,
  26.             i = 0,
  27.             len = specialElCache.length,
  28.             id = false,
  29.             skip = false,
  30.             o;
  31.         if(el){
  32.             if(el.getElementById || el.navigator){
  33.                 // look up the id
  34.                 for(; i < len; ++i){
  35.                     o = specialElCache[i];
  36.                     if(o.el === el){
  37.                         id = o.id;
  38.                         break;
  39.                     }
  40.                 }
  41.                 if(!id){
  42.                     // for browsers that support it, ensure that give the el the same id
  43.                     id = Ext.id(el);
  44.                     specialElCache.push({
  45.                         id: id,
  46.                         el: el
  47.                     });
  48.                     skip = true;
  49.                 }
  50.             }else{
  51.                 id = Ext.id(el);
  52.             }
  53.             if(!Ext.elCache[id]){
  54.                 Ext.Element.addToCache(new Ext.Element(el), id);
  55.                 if(skip){
  56.                     Ext.elCache[id].skipGC = true;
  57.                 }
  58.             }
  59.         }
  60.         return id;
  61.      };
  62.     /// There is some jquery work around stuff here that isn't needed in Ext Core.
  63.     function addListener(el, ename, fn, wrap, scope){
  64.         el = Ext.getDom(el);
  65.         var id = getId(el),
  66.             es = Ext.elCache[id].events,
  67.             wfn;
  68.         wfn = E.on(el, ename, wrap);
  69.         es[ename] = es[ename] || [];
  70.         es[ename].push([fn, wrap, scope, wfn]);
  71.         // this is a workaround for jQuery and should somehow be removed from Ext Core in the future
  72.         // without breaking ExtJS.
  73.         if(ename == "mousewheel" && el.addEventListener){ // workaround for jQuery
  74.             var args = ["DOMMouseScroll", wrap, false];
  75.             el.addEventListener.apply(el, args);
  76.             Ext.EventManager.addListener(WINDOW, 'unload', function(){
  77.                 el.removeEventListener.apply(el, args);
  78.             });
  79.         }
  80.         if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
  81.             Ext.EventManager.stoppedMouseDownEvent.addListener(wrap);
  82.         }
  83.     };
  84.     function fireDocReady(){
  85.         if(!docReadyState){
  86.             Ext.isReady = docReadyState = true;
  87.             if(docReadyProcId){
  88.                 clearInterval(docReadyProcId);
  89.             }
  90.             if(Ext.isGecko || Ext.isOpera) {
  91.                 DOC.removeEventListener(DOMCONTENTLOADED, fireDocReady, false);
  92.             }
  93.             if(Ext.isIE){
  94.                 var defer = DOC.getElementById(IEDEFERED);
  95.                 if(defer){
  96.                     defer.onreadystatechange = null;
  97.                     defer.parentNode.removeChild(defer);
  98.                 }
  99.             }
  100.             if(docReadyEvent){
  101.                 docReadyEvent.fire();
  102.                 docReadyEvent.listeners = []; // clearListeners no longer compatible.  Force single: true?
  103.             }
  104.         }
  105.     };
  106.     function initDocReady(){
  107.         var COMPLETE = "complete";
  108.         docReadyEvent = new Ext.util.Event();
  109.         if (Ext.isGecko || Ext.isOpera) {
  110.             DOC.addEventListener(DOMCONTENTLOADED, fireDocReady, false);
  111.         } else if (Ext.isIE){
  112.             DOC.write("<s"+'cript id=' + IEDEFERED + ' defer="defer" src="/'+'/:"></s'+"cript>");
  113.             DOC.getElementById(IEDEFERED).onreadystatechange = function(){
  114.                 if(this.readyState == COMPLETE){
  115.                     fireDocReady();
  116.                 }
  117.             };
  118.         } else if (Ext.isWebKit){
  119.             docReadyProcId = setInterval(function(){
  120.                 if(DOC.readyState == COMPLETE) {
  121.                     fireDocReady();
  122.                  }
  123.             }, 10);
  124.         }
  125.         // no matter what, make sure it fires on load
  126.         E.on(WINDOW, "load", fireDocReady);
  127.     };
  128.     function createTargeted(h, o){
  129.         return function(){
  130.             var args = Ext.toArray(arguments);
  131.             if(o.target == Ext.EventObject.setEvent(args[0]).target){
  132.                 h.apply(this, args);
  133.             }
  134.         };
  135.     };
  136.     function createBuffered(h, o, fn){
  137.         fn.task = new Ext.util.DelayedTask(h);
  138.         var w = function(e){
  139.             // create new event object impl so new events don't wipe out properties
  140.             fn.task.delay(o.buffer, h, null, [new Ext.EventObjectImpl(e)]);
  141.         };
  142.         return w;
  143.     };
  144.     function createSingle(h, el, ename, fn, scope){
  145.         return function(e){
  146.             Ext.EventManager.removeListener(el, ename, fn, scope);
  147.             h(e);
  148.         };
  149.     };
  150.     function createDelayed(h, o, fn){
  151.         return function(e){
  152.             var task = new Ext.util.DelayedTask(h);
  153.             if(!fn.tasks) {
  154.                 fn.tasks = [];
  155.             }
  156.             fn.tasks.push(task);
  157.             task.delay(o.delay || 10, h, null, [new Ext.EventObjectImpl(e)]);
  158.         };
  159.     };
  160.     function listen(element, ename, opt, fn, scope){
  161.         var o = !Ext.isObject(opt) ? {} : opt,
  162.             el = Ext.getDom(element);
  163.         fn = fn || o.fn;
  164.         scope = scope || o.scope;
  165.         if(!el){
  166.             throw "Error listening for "" + ename + '". Element "' + element + '" doesn't exist.';
  167.         }
  168.         function h(e){
  169.             // prevent errors while unload occurring
  170.             if(!Ext){// !window[xname]){  ==> can't we do this?
  171.                 return;
  172.             }
  173.             e = Ext.EventObject.setEvent(e);
  174.             var t;
  175.             if (o.delegate) {
  176.                 if(!(t = e.getTarget(o.delegate, el))){
  177.                     return;
  178.                 }
  179.             } else {
  180.                 t = e.target;
  181.             }
  182.             if (o.stopEvent) {
  183.                 e.stopEvent();
  184.             }
  185.             if (o.preventDefault) {
  186.                e.preventDefault();
  187.             }
  188.             if (o.stopPropagation) {
  189.                 e.stopPropagation();
  190.             }
  191.             if (o.normalized) {
  192.                 e = e.browserEvent;
  193.             }
  194.             fn.call(scope || el, e, t, o);
  195.         };
  196.         if(o.target){
  197.             h = createTargeted(h, o);
  198.         }
  199.         if(o.delay){
  200.             h = createDelayed(h, o, fn);
  201.         }
  202.         if(o.single){
  203.             h = createSingle(h, el, ename, fn, scope);
  204.         }
  205.         if(o.buffer){
  206.             h = createBuffered(h, o, fn);
  207.         }
  208.         addListener(el, ename, fn, h, scope);
  209.         return h;
  210.     };
  211.     var pub = {
  212.         /**
  213.          * Appends an event handler to an element.  The shorthand version {@link #on} is equivalent.  Typically you will
  214.          * use {@link Ext.Element#addListener} directly on an Element in favor of calling this version.
  215.          * @param {String/HTMLElement} el The html element or id to assign the event handler to.
  216.          * @param {String} eventName The name of the event to listen for.
  217.          * @param {Function} handler The handler function the event invokes. This function is passed
  218.          * the following parameters:<ul>
  219.          * <li>evt : EventObject<div class="sub-desc">The {@link Ext.EventObject EventObject} describing the event.</div></li>
  220.          * <li>t : Element<div class="sub-desc">The {@link Ext.Element Element} which was the target of the event.
  221.          * Note that this may be filtered by using the <tt>delegate</tt> option.</div></li>
  222.          * <li>o : Object<div class="sub-desc">The options object from the addListener call.</div></li>
  223.          * </ul>
  224.          * @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>.
  225.          * @param {Object} options (optional) An object containing handler configuration properties.
  226.          * This may contain any of the following properties:<ul>
  227.          * <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>
  228.          * <li>delegate : String<div class="sub-desc">A simple selector to filter the target or look for a descendant of the target</div></li>
  229.          * <li>stopEvent : Boolean<div class="sub-desc">True to stop the event. That is stop propagation, and prevent the default action.</div></li>
  230.          * <li>preventDefault : Boolean<div class="sub-desc">True to prevent the default action</div></li>
  231.          * <li>stopPropagation : Boolean<div class="sub-desc">True to prevent event propagation</div></li>
  232.          * <li>normalized : Boolean<div class="sub-desc">False to pass a browser event to the handler function instead of an Ext.EventObject</div></li>
  233.          * <li>delay : Number<div class="sub-desc">The number of milliseconds to delay the invocation of the handler after te event fires.</div></li>
  234.          * <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>
  235.          * <li>buffer : Number<div class="sub-desc">Causes the handler to be scheduled to run in an {@link Ext.util.DelayedTask} delayed
  236.          * by the specified number of milliseconds. If the event fires again within that time, the original
  237.          * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</div></li>
  238.          * <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>
  239.          * </ul><br>
  240.          * <p>See {@link Ext.Element#addListener} for examples of how to use these options.</p>
  241.          */
  242.         addListener : function(element, eventName, fn, scope, options){
  243.             if(Ext.isObject(eventName)){
  244.                 var o = eventName, e, val;
  245.                 for(e in o){
  246.                     val = o[e];
  247.                     if(!propRe.test(e)){
  248.                         if(Ext.isFunction(val)){
  249.                             // shared options
  250.                             listen(element, e, o, val, o.scope);
  251.                         }else{
  252.                             // individual options
  253.                             listen(element, e, val);
  254.                         }
  255.                     }
  256.                 }
  257.             } else {
  258.                 listen(element, eventName, options, fn, scope);
  259.             }
  260.         },
  261.         /**
  262.          * Removes an event handler from an element.  The shorthand version {@link #un} is equivalent.  Typically
  263.          * you will use {@link Ext.Element#removeListener} directly on an Element in favor of calling this version.
  264.          * @param {String/HTMLElement} el The id or html element from which to remove the listener.
  265.          * @param {String} eventName The name of the event.
  266.          * @param {Function} fn The handler function to remove. <b>This must be a reference to the function passed into the {@link #addListener} call.</b>
  267.          * @param {Object} scope If a scope (<b><code>this</code></b> reference) was specified when the listener was added,
  268.          * then this must refer to the same object.
  269.          */
  270.         removeListener : function(el, eventName, fn, scope){
  271.             el = Ext.getDom(el);
  272.             var id = getId(el),
  273.                 f = el && (Ext.elCache[id].events)[eventName] || [],
  274.                 wrap, i, l, k, wf;
  275.             for (i = 0, len = f.length; i < len; i++) {
  276.                 if (Ext.isArray(f[i]) && f[i][0] == fn && (!scope || f[i][2] == scope)) {
  277.                     if(fn.task) {
  278.                         fn.task.cancel();
  279.                         delete fn.task;
  280.                     }
  281.                     k = fn.tasks && fn.tasks.length;
  282.                     if(k) {
  283.                         while(k--) {
  284.                             fn.tasks[k].cancel();
  285.                         }
  286.                         delete fn.tasks;
  287.                     }
  288.                     wf = wrap = f[i][1];
  289.                     if (E.extAdapter) {
  290.                         wf = f[i][3];
  291.                     }
  292.                     E.un(el, eventName, wf);
  293.                     f.splice(i,1);
  294.                     if (f.length === 0) {
  295.                         delete Ext.elCache[id].events[eventName];
  296.                     }
  297.                     for (k in Ext.elCache[id].events) {
  298.                         return false;
  299.                     }
  300.                     Ext.elCache[id].events = {};
  301.                     return false;
  302.                 }
  303.             }
  304.             // jQuery workaround that should be removed from Ext Core
  305.             if(eventName == "mousewheel" && el.addEventListener && wrap){
  306.                 el.removeEventListener("DOMMouseScroll", wrap, false);
  307.             }
  308.             if(eventName == "mousedown" && el == DOC && wrap){ // fix stopped mousedowns on the document
  309.                 Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);
  310.             }
  311.         },
  312.         /**
  313.          * Removes all event handers from an element.  Typically you will use {@link Ext.Element#removeAllListeners}
  314.          * directly on an Element in favor of calling this version.
  315.          * @param {String/HTMLElement} el The id or html element from which to remove all event handlers.
  316.          */
  317.         removeAll : function(el){
  318.             el = Ext.getDom(el);
  319.             var id = getId(el),
  320.                 ec = Ext.elCache[id] || {},
  321.                 es = ec.events || {},
  322.                 f, i, len, ename, fn, k;
  323.             for(ename in es){
  324.                 if(es.hasOwnProperty(ename)){
  325.                     f = es[ename];
  326.                     for (i = 0, len = f.length; i < len; i++) {
  327.                         fn = f[i][0];
  328.                         if(fn.task) {
  329.                             fn.task.cancel();
  330.                             delete fn.task;
  331.                         }
  332.                         if(fn.tasks && (k = fn.tasks.length)) {
  333.                             while(k--) {
  334.                                 fn.tasks[k].cancel();
  335.                             }
  336.                             delete fn.tasks;
  337.                         }
  338.                         E.un(el, ename, E.extAdapter ? f[i][3] : f[i][1]);
  339.                     }
  340.                 }
  341.             }
  342.             if (Ext.elCache[id]) {
  343.                 Ext.elCache[id].events = {};
  344.             }
  345.         },
  346.         getListeners : function(el, eventName) {
  347.             el = Ext.getDom(el);
  348.             var id = getId(el),
  349.                 ec = Ext.elCache[id] || {},
  350.                 es = ec.events || {},
  351.                 results = [];
  352.             if (es && es[eventName]) {
  353.                 return es[eventName];
  354.             } else {
  355.                 return null;
  356.             }
  357.         },
  358.         purgeElement : function(el, recurse, eventName) {
  359.             el = Ext.getDom(el);
  360.             var id = getId(el),
  361.                 ec = Ext.elCache[id] || {},
  362.                 es = ec.events || {},
  363.                 i, f, len;
  364.             if (eventName) {
  365.                 if (es && es.hasOwnProperty(eventName)) {
  366.                     f = es[eventName];
  367.                     for (i = 0, len = f.length; i < len; i++) {
  368.                         Ext.EventManager.removeListener(el, eventName, f[i][0]);
  369.                     }
  370.                 }
  371.             } else {
  372.                 Ext.EventManager.removeAll(el);
  373.             }
  374.             if (recurse && el && el.childNodes) {
  375.                 for (i = 0, len = el.childNodes.length; i < len; i++) {
  376.                     Ext.EventManager.purgeElement(el.childNodes[i], recurse, eventName);
  377.                 }
  378.             }
  379.         },
  380.         _unload : function() {
  381.             var el;
  382.             for (el in Ext.elCache) {
  383.                 Ext.EventManager.removeAll(el);
  384.             }
  385.         },
  386.         /**
  387.          * Adds a listener to be notified when the document is ready (before onload and before images are loaded). Can be
  388.          * accessed shorthanded as Ext.onReady().
  389.          * @param {Function} fn The method the event invokes.
  390.          * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the handler function executes. Defaults to the browser window.
  391.          * @param {boolean} options (optional) Options object as passed to {@link Ext.Element#addListener}. It is recommended that the options
  392.          * <code>{single: true}</code> be used so that the handler is removed on first invocation.
  393.          */
  394.         onDocumentReady : function(fn, scope, options){
  395.             if(docReadyState){ // if it already fired
  396.                 docReadyEvent.addListener(fn, scope, options);
  397.                 docReadyEvent.fire();
  398.                 docReadyEvent.listeners = []; // clearListeners no longer compatible.  Force single: true?
  399.             } else {
  400.                 if(!docReadyEvent) initDocReady();
  401.                 options = options || {};
  402.                 options.delay = options.delay || 1;
  403.                 docReadyEvent.addListener(fn, scope, options);
  404.             }
  405.         }
  406.     };
  407.      /**
  408.      * Appends an event handler to an element.  Shorthand for {@link #addListener}.
  409.      * @param {String/HTMLElement} el The html element or id to assign the event handler to
  410.      * @param {String} eventName The name of the event to listen for.
  411.      * @param {Function} handler The handler function the event invokes.
  412.      * @param {Object} scope (optional) (<code>this</code> reference) in which the handler function executes. <b>Defaults to the Element</b>.
  413.      * @param {Object} options (optional) An object containing standard {@link #addListener} options
  414.      * @member Ext.EventManager
  415.      * @method on
  416.      */
  417.     pub.on = pub.addListener;
  418.     /**
  419.      * Removes an event handler from an element.  Shorthand for {@link #removeListener}.
  420.      * @param {String/HTMLElement} el The id or html element from which to remove the listener.
  421.      * @param {String} eventName The name of the event.
  422.      * @param {Function} fn The handler function to remove. <b>This must be a reference to the function passed into the {@link #on} call.</b>
  423.      * @param {Object} scope If a scope (<b><code>this</code></b> reference) was specified when the listener was added,
  424.      * then this must refer to the same object.
  425.      * @member Ext.EventManager
  426.      * @method un
  427.      */
  428.     pub.un = pub.removeListener;
  429.     pub.stoppedMouseDownEvent = new Ext.util.Event();
  430.     return pub;
  431. }();
  432. /**
  433.   * Adds a listener to be notified when the document is ready (before onload and before images are loaded). Shorthand of {@link Ext.EventManager#onDocumentReady}.
  434.   * @param {Function} fn The method the event invokes.
  435.   * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the handler function executes. Defaults to the browser window.
  436.   * @param {boolean} options (optional) Options object as passed to {@link Ext.Element#addListener}. It is recommended that the options
  437.   * <code>{single: true}</code> be used so that the handler is removed on first invocation.
  438.   * @member Ext
  439.   * @method onReady
  440.  */
  441. Ext.onReady = Ext.EventManager.onDocumentReady;
  442. //Initialize doc classes
  443. (function(){
  444.     var initExtCss = function(){
  445.         // find the body element
  446.         var bd = document.body || document.getElementsByTagName('body')[0];
  447.         if(!bd){ return false; }
  448.         var cls = [' ',
  449.                 Ext.isIE ? "ext-ie " + (Ext.isIE6 ? 'ext-ie6' : (Ext.isIE7 ? 'ext-ie7' : 'ext-ie8'))
  450.                 : Ext.isGecko ? "ext-gecko " + (Ext.isGecko2 ? 'ext-gecko2' : 'ext-gecko3')
  451.                 : Ext.isOpera ? "ext-opera"
  452.                 : Ext.isWebKit ? "ext-webkit" : ""];
  453.         if(Ext.isSafari){
  454.             cls.push("ext-safari " + (Ext.isSafari2 ? 'ext-safari2' : (Ext.isSafari3 ? 'ext-safari3' : 'ext-safari4')));
  455.         }else if(Ext.isChrome){
  456.             cls.push("ext-chrome");
  457.         }
  458.         if(Ext.isMac){
  459.             cls.push("ext-mac");
  460.         }
  461.         if(Ext.isLinux){
  462.             cls.push("ext-linux");
  463.         }
  464.         if(Ext.isStrict || Ext.isBorderBox){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"
  465.             var p = bd.parentNode;
  466.             if(p){
  467.                 p.className += Ext.isStrict ? ' ext-strict' : ' ext-border-box';
  468.             }
  469.         }
  470.         bd.className += cls.join(' ');
  471.         return true;
  472.     }
  473.     if(!initExtCss()){
  474.         Ext.onReady(initExtCss);
  475.     }
  476. })();
  477. /**
  478.  * @class Ext.EventObject
  479.  * Just as {@link Ext.Element} wraps around a native DOM node, Ext.EventObject
  480.  * wraps the browser's native event-object normalizing cross-browser differences,
  481.  * such as which mouse button is clicked, keys pressed, mechanisms to stop
  482.  * event-propagation along with a method to prevent default actions from taking place.
  483.  * <p>For example:</p>
  484.  * <pre><code>
  485. function handleClick(e, t){ // e is not a standard event object, it is a Ext.EventObject
  486.     e.preventDefault();
  487.     var target = e.getTarget(); // same as t (the target HTMLElement)
  488.     ...
  489. }
  490. var myDiv = {@link Ext#get Ext.get}("myDiv");  // get reference to an {@link Ext.Element}
  491. myDiv.on(         // 'on' is shorthand for addListener
  492.     "click",      // perform an action on click of myDiv
  493.     handleClick   // reference to the action handler
  494. );
  495. // other methods to do the same:
  496. Ext.EventManager.on("myDiv", 'click', handleClick);
  497. Ext.EventManager.addListener("myDiv", 'click', handleClick);
  498.  </code></pre>
  499.  * @singleton
  500.  */
  501. Ext.EventObject = function(){
  502.     var E = Ext.lib.Event,
  503.         // safari keypress events for special keys return bad keycodes
  504.         safariKeys = {
  505.             3 : 13, // enter
  506.             63234 : 37, // left
  507.             63235 : 39, // right
  508.             63232 : 38, // up
  509.             63233 : 40, // down
  510.             63276 : 33, // page up
  511.             63277 : 34, // page down
  512.             63272 : 46, // delete
  513.             63273 : 36, // home
  514.             63275 : 35  // end
  515.         },
  516.         // normalize button clicks
  517.         btnMap = Ext.isIE ? {1:0,4:1,2:2} :
  518.                 (Ext.isWebKit ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
  519.     Ext.EventObjectImpl = function(e){
  520.         if(e){
  521.             this.setEvent(e.browserEvent || e);
  522.         }
  523.     };
  524.     Ext.EventObjectImpl.prototype = {
  525.            /** @private */
  526.         setEvent : function(e){
  527.             var me = this;
  528.             if(e == me || (e && e.browserEvent)){ // already wrapped
  529.                 return e;
  530.             }
  531.             me.browserEvent = e;
  532.             if(e){
  533.                 // normalize buttons
  534.                 me.button = e.button ? btnMap[e.button] : (e.which ? e.which - 1 : -1);
  535.                 if(e.type == 'click' && me.button == -1){
  536.                     me.button = 0;
  537.                 }
  538.                 me.type = e.type;
  539.                 me.shiftKey = e.shiftKey;
  540.                 // mac metaKey behaves like ctrlKey
  541.                 me.ctrlKey = e.ctrlKey || e.metaKey || false;
  542.                 me.altKey = e.altKey;
  543.                 // in getKey these will be normalized for the mac
  544.                 me.keyCode = e.keyCode;
  545.                 me.charCode = e.charCode;
  546.                 // cache the target for the delayed and or buffered events
  547.                 me.target = E.getTarget(e);
  548.                 // same for XY
  549.                 me.xy = E.getXY(e);
  550.             }else{
  551.                 me.button = -1;
  552.                 me.shiftKey = false;
  553.                 me.ctrlKey = false;
  554.                 me.altKey = false;
  555.                 me.keyCode = 0;
  556.                 me.charCode = 0;
  557.                 me.target = null;
  558.                 me.xy = [0, 0];
  559.             }
  560.             return me;
  561.         },
  562.         /**
  563.          * Stop the event (preventDefault and stopPropagation)
  564.          */
  565.         stopEvent : function(){
  566.             var me = this;
  567.             if(me.browserEvent){
  568.                 if(me.browserEvent.type == 'mousedown'){
  569.                     Ext.EventManager.stoppedMouseDownEvent.fire(me);
  570.                 }
  571.                 E.stopEvent(me.browserEvent);
  572.             }
  573.         },
  574.         /**
  575.          * Prevents the browsers default handling of the event.
  576.          */
  577.         preventDefault : function(){
  578.             if(this.browserEvent){
  579.                 E.preventDefault(this.browserEvent);
  580.             }
  581.         },
  582.         /**
  583.          * Cancels bubbling of the event.
  584.          */
  585.         stopPropagation : function(){
  586.             var me = this;
  587.             if(me.browserEvent){
  588.                 if(me.browserEvent.type == 'mousedown'){
  589.                     Ext.EventManager.stoppedMouseDownEvent.fire(me);
  590.                 }
  591.                 E.stopPropagation(me.browserEvent);
  592.             }
  593.         },
  594.         /**
  595.          * Gets the character code for the event.
  596.          * @return {Number}
  597.          */
  598.         getCharCode : function(){
  599.             return this.charCode || this.keyCode;
  600.         },
  601.         /**
  602.          * Returns a normalized keyCode for the event.
  603.          * @return {Number} The key code
  604.          */
  605.         getKey : function(){
  606.             return this.normalizeKey(this.keyCode || this.charCode)
  607.         },
  608.         // private
  609.         normalizeKey: function(k){
  610.             return Ext.isSafari ? (safariKeys[k] || k) : k;
  611.         },
  612.         /**
  613.          * Gets the x coordinate of the event.
  614.          * @return {Number}
  615.          */
  616.         getPageX : function(){
  617.             return this.xy[0];
  618.         },
  619.         /**
  620.          * Gets the y coordinate of the event.
  621.          * @return {Number}
  622.          */
  623.         getPageY : function(){
  624.             return this.xy[1];
  625.         },
  626.         /**
  627.          * Gets the page coordinates of the event.
  628.          * @return {Array} The xy values like [x, y]
  629.          */
  630.         getXY : function(){
  631.             return this.xy;
  632.         },
  633.         /**
  634.          * Gets the target for the event.
  635.          * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
  636.          * @param {Number/Mixed} maxDepth (optional) The max depth to
  637.                 search as a number or element (defaults to 10 || document.body)
  638.          * @param {Boolean} returnEl (optional) True to return a Ext.Element object instead of DOM node
  639.          * @return {HTMLelement}
  640.          */
  641.         getTarget : function(selector, maxDepth, returnEl){
  642.             return selector ? Ext.fly(this.target).findParent(selector, maxDepth, returnEl) : (returnEl ? Ext.get(this.target) : this.target);
  643.         },
  644.         /**
  645.          * Gets the related target.
  646.          * @return {HTMLElement}
  647.          */
  648.         getRelatedTarget : function(){
  649.             return this.browserEvent ? E.getRelatedTarget(this.browserEvent) : null;
  650.         },
  651.         /**
  652.          * Normalizes mouse wheel delta across browsers
  653.          * @return {Number} The delta
  654.          */
  655.         getWheelDelta : function(){
  656.             var e = this.browserEvent;
  657.             var delta = 0;
  658.             if(e.wheelDelta){ /* IE/Opera. */
  659.                 delta = e.wheelDelta/120;
  660.             }else if(e.detail){ /* Mozilla case. */
  661.                 delta = -e.detail/3;
  662.             }
  663.             return delta;
  664.         },
  665.         /**
  666.         * 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.
  667.         * Example usage:<pre><code>
  668.         // Handle click on any child of an element
  669.         Ext.getBody().on('click', function(e){
  670.             if(e.within('some-el')){
  671.                 alert('Clicked on a child of some-el!');
  672.             }
  673.         });
  674.         // Handle click directly on an element, ignoring clicks on child nodes
  675.         Ext.getBody().on('click', function(e,t){
  676.             if((t.id == 'some-el') && !e.within(t, true)){
  677.                 alert('Clicked directly on some-el!');
  678.             }
  679.         });
  680.         </code></pre>
  681.          * @param {Mixed} el The id, DOM element or Ext.Element to check
  682.          * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
  683.          * @param {Boolean} allowEl {optional} true to also check if the passed element is the target or related target
  684.          * @return {Boolean}
  685.          */
  686.         within : function(el, related, allowEl){
  687.             if(el){
  688.                 var t = this[related ? "getRelatedTarget" : "getTarget"]();
  689.                 return t && ((allowEl ? (t == Ext.getDom(el)) : false) || Ext.fly(el).contains(t));
  690.             }
  691.             return false;
  692.         }
  693.      };
  694.     return new Ext.EventObjectImpl();
  695. }();