Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / docs / source / EventObject.html
1 <!DOCTYPE html><html><head><title>Sencha Documentation Project</title><link rel="stylesheet" href="../reset.css" type="text/css"><link rel="stylesheet" href="../prettify.css" type="text/css"><link rel="stylesheet" href="../prettify_sa.css" type="text/css"><script type="text/javascript" src="../prettify.js"></script></head><body onload="prettyPrint()"><pre class="prettyprint"><pre><span id='Ext-EventObject'>/**
2 </span> * @class Ext.EventObject
3
4 Just as {@link Ext.core.Element} wraps around a native DOM node, Ext.EventObject
5 wraps the browser's native event-object normalizing cross-browser differences,
6 such as which mouse button is clicked, keys pressed, mechanisms to stop
7 event-propagation along with a method to prevent default actions from taking place.
8
9 For example:
10
11     function handleClick(e, t){ // e is not a standard event object, it is a Ext.EventObject
12         e.preventDefault();
13         var target = e.getTarget(); // same as t (the target HTMLElement)
14         ...
15     }
16
17     var myDiv = {@link Ext#get Ext.get}(&quot;myDiv&quot;);  // get reference to an {@link Ext.core.Element}
18     myDiv.on(         // 'on' is shorthand for addListener
19         &quot;click&quot;,      // perform an action on click of myDiv
20         handleClick   // reference to the action handler
21     );
22
23     // other methods to do the same:
24     Ext.EventManager.on(&quot;myDiv&quot;, 'click', handleClick);
25     Ext.EventManager.addListener(&quot;myDiv&quot;, 'click', handleClick);
26
27  * @singleton
28  * @markdown
29  */
30 Ext.define('Ext.EventObjectImpl', {
31     uses: ['Ext.util.Point'],
32
33 <span id='Ext-EventObject-property-BACKSPACE'>    /** Key constant @type Number */
34 </span>    BACKSPACE: 8,
35 <span id='Ext-EventObject-property-TAB'>    /** Key constant @type Number */
36 </span>    TAB: 9,
37 <span id='Ext-EventObject-property-NUM_CENTER'>    /** Key constant @type Number */
38 </span>    NUM_CENTER: 12,
39 <span id='Ext-EventObject-property-ENTER'>    /** Key constant @type Number */
40 </span>    ENTER: 13,
41 <span id='Ext-EventObject-property-RETURN'>    /** Key constant @type Number */
42 </span>    RETURN: 13,
43 <span id='Ext-EventObject-property-SHIFT'>    /** Key constant @type Number */
44 </span>    SHIFT: 16,
45 <span id='Ext-EventObject-property-CTRL'>    /** Key constant @type Number */
46 </span>    CTRL: 17,
47 <span id='Ext-EventObject-property-ALT'>    /** Key constant @type Number */
48 </span>    ALT: 18,
49 <span id='Ext-EventObject-property-PAUSE'>    /** Key constant @type Number */
50 </span>    PAUSE: 19,
51 <span id='Ext-EventObject-property-CAPS_LOCK'>    /** Key constant @type Number */
52 </span>    CAPS_LOCK: 20,
53 <span id='Ext-EventObject-property-ESC'>    /** Key constant @type Number */
54 </span>    ESC: 27,
55 <span id='Ext-EventObject-property-SPACE'>    /** Key constant @type Number */
56 </span>    SPACE: 32,
57 <span id='Ext-EventObject-property-PAGE_UP'>    /** Key constant @type Number */
58 </span>    PAGE_UP: 33,
59 <span id='Ext-EventObject-property-PAGE_DOWN'>    /** Key constant @type Number */
60 </span>    PAGE_DOWN: 34,
61 <span id='Ext-EventObject-property-END'>    /** Key constant @type Number */
62 </span>    END: 35,
63 <span id='Ext-EventObject-property-HOME'>    /** Key constant @type Number */
64 </span>    HOME: 36,
65 <span id='Ext-EventObject-property-LEFT'>    /** Key constant @type Number */
66 </span>    LEFT: 37,
67 <span id='Ext-EventObject-property-UP'>    /** Key constant @type Number */
68 </span>    UP: 38,
69 <span id='Ext-EventObject-property-RIGHT'>    /** Key constant @type Number */
70 </span>    RIGHT: 39,
71 <span id='Ext-EventObject-property-DOWN'>    /** Key constant @type Number */
72 </span>    DOWN: 40,
73 <span id='Ext-EventObject-property-PRINT_SCREEN'>    /** Key constant @type Number */
74 </span>    PRINT_SCREEN: 44,
75 <span id='Ext-EventObject-property-INSERT'>    /** Key constant @type Number */
76 </span>    INSERT: 45,
77 <span id='Ext-EventObject-property-DELETE'>    /** Key constant @type Number */
78 </span>    DELETE: 46,
79 <span id='Ext-EventObject-property-ZERO'>    /** Key constant @type Number */
80 </span>    ZERO: 48,
81 <span id='Ext-EventObject-property-ONE'>    /** Key constant @type Number */
82 </span>    ONE: 49,
83 <span id='Ext-EventObject-property-TWO'>    /** Key constant @type Number */
84 </span>    TWO: 50,
85 <span id='Ext-EventObject-property-THREE'>    /** Key constant @type Number */
86 </span>    THREE: 51,
87 <span id='Ext-EventObject-property-FOUR'>    /** Key constant @type Number */
88 </span>    FOUR: 52,
89 <span id='Ext-EventObject-property-FIVE'>    /** Key constant @type Number */
90 </span>    FIVE: 53,
91 <span id='Ext-EventObject-property-SIX'>    /** Key constant @type Number */
92 </span>    SIX: 54,
93 <span id='Ext-EventObject-property-SEVEN'>    /** Key constant @type Number */
94 </span>    SEVEN: 55,
95 <span id='Ext-EventObject-property-EIGHT'>    /** Key constant @type Number */
96 </span>    EIGHT: 56,
97 <span id='Ext-EventObject-property-NINE'>    /** Key constant @type Number */
98 </span>    NINE: 57,
99 <span id='Ext-EventObject-property-A'>    /** Key constant @type Number */
100 </span>    A: 65,
101 <span id='Ext-EventObject-property-B'>    /** Key constant @type Number */
102 </span>    B: 66,
103 <span id='Ext-EventObject-property-C'>    /** Key constant @type Number */
104 </span>    C: 67,
105 <span id='Ext-EventObject-property-D'>    /** Key constant @type Number */
106 </span>    D: 68,
107 <span id='Ext-EventObject-property-E'>    /** Key constant @type Number */
108 </span>    E: 69,
109 <span id='Ext-EventObject-property-F'>    /** Key constant @type Number */
110 </span>    F: 70,
111 <span id='Ext-EventObject-property-G'>    /** Key constant @type Number */
112 </span>    G: 71,
113 <span id='Ext-EventObject-property-H'>    /** Key constant @type Number */
114 </span>    H: 72,
115 <span id='Ext-EventObject-property-I'>    /** Key constant @type Number */
116 </span>    I: 73,
117 <span id='Ext-EventObject-property-J'>    /** Key constant @type Number */
118 </span>    J: 74,
119 <span id='Ext-EventObject-property-K'>    /** Key constant @type Number */
120 </span>    K: 75,
121 <span id='Ext-EventObject-property-L'>    /** Key constant @type Number */
122 </span>    L: 76,
123 <span id='Ext-EventObject-property-M'>    /** Key constant @type Number */
124 </span>    M: 77,
125 <span id='Ext-EventObject-property-N'>    /** Key constant @type Number */
126 </span>    N: 78,
127 <span id='Ext-EventObject-property-O'>    /** Key constant @type Number */
128 </span>    O: 79,
129 <span id='Ext-EventObject-property-P'>    /** Key constant @type Number */
130 </span>    P: 80,
131 <span id='Ext-EventObject-property-Q'>    /** Key constant @type Number */
132 </span>    Q: 81,
133 <span id='Ext-EventObject-property-R'>    /** Key constant @type Number */
134 </span>    R: 82,
135 <span id='Ext-EventObject-property-S'>    /** Key constant @type Number */
136 </span>    S: 83,
137 <span id='Ext-EventObject-property-T'>    /** Key constant @type Number */
138 </span>    T: 84,
139 <span id='Ext-EventObject-property-U'>    /** Key constant @type Number */
140 </span>    U: 85,
141 <span id='Ext-EventObject-property-V'>    /** Key constant @type Number */
142 </span>    V: 86,
143 <span id='Ext-EventObject-property-W'>    /** Key constant @type Number */
144 </span>    W: 87,
145 <span id='Ext-EventObject-property-X'>    /** Key constant @type Number */
146 </span>    X: 88,
147 <span id='Ext-EventObject-property-Y'>    /** Key constant @type Number */
148 </span>    Y: 89,
149 <span id='Ext-EventObject-property-Z'>    /** Key constant @type Number */
150 </span>    Z: 90,
151 <span id='Ext-EventObject-property-CONTEXT_MENU'>    /** Key constant @type Number */
152 </span>    CONTEXT_MENU: 93,
153 <span id='Ext-EventObject-property-NUM_ZERO'>    /** Key constant @type Number */
154 </span>    NUM_ZERO: 96,
155 <span id='Ext-EventObject-property-NUM_ONE'>    /** Key constant @type Number */
156 </span>    NUM_ONE: 97,
157 <span id='Ext-EventObject-property-NUM_TWO'>    /** Key constant @type Number */
158 </span>    NUM_TWO: 98,
159 <span id='Ext-EventObject-property-NUM_THREE'>    /** Key constant @type Number */
160 </span>    NUM_THREE: 99,
161 <span id='Ext-EventObject-property-NUM_FOUR'>    /** Key constant @type Number */
162 </span>    NUM_FOUR: 100,
163 <span id='Ext-EventObject-property-NUM_FIVE'>    /** Key constant @type Number */
164 </span>    NUM_FIVE: 101,
165 <span id='Ext-EventObject-property-NUM_SIX'>    /** Key constant @type Number */
166 </span>    NUM_SIX: 102,
167 <span id='Ext-EventObject-property-NUM_SEVEN'>    /** Key constant @type Number */
168 </span>    NUM_SEVEN: 103,
169 <span id='Ext-EventObject-property-NUM_EIGHT'>    /** Key constant @type Number */
170 </span>    NUM_EIGHT: 104,
171 <span id='Ext-EventObject-property-NUM_NINE'>    /** Key constant @type Number */
172 </span>    NUM_NINE: 105,
173 <span id='Ext-EventObject-property-NUM_MULTIPLY'>    /** Key constant @type Number */
174 </span>    NUM_MULTIPLY: 106,
175 <span id='Ext-EventObject-property-NUM_PLUS'>    /** Key constant @type Number */
176 </span>    NUM_PLUS: 107,
177 <span id='Ext-EventObject-property-NUM_MINUS'>    /** Key constant @type Number */
178 </span>    NUM_MINUS: 109,
179 <span id='Ext-EventObject-property-NUM_PERIOD'>    /** Key constant @type Number */
180 </span>    NUM_PERIOD: 110,
181 <span id='Ext-EventObject-property-NUM_DIVISION'>    /** Key constant @type Number */
182 </span>    NUM_DIVISION: 111,
183 <span id='Ext-EventObject-property-F1'>    /** Key constant @type Number */
184 </span>    F1: 112,
185 <span id='Ext-EventObject-property-F2'>    /** Key constant @type Number */
186 </span>    F2: 113,
187 <span id='Ext-EventObject-property-F3'>    /** Key constant @type Number */
188 </span>    F3: 114,
189 <span id='Ext-EventObject-property-F4'>    /** Key constant @type Number */
190 </span>    F4: 115,
191 <span id='Ext-EventObject-property-F5'>    /** Key constant @type Number */
192 </span>    F5: 116,
193 <span id='Ext-EventObject-property-F6'>    /** Key constant @type Number */
194 </span>    F6: 117,
195 <span id='Ext-EventObject-property-F7'>    /** Key constant @type Number */
196 </span>    F7: 118,
197 <span id='Ext-EventObject-property-F8'>    /** Key constant @type Number */
198 </span>    F8: 119,
199 <span id='Ext-EventObject-property-F9'>    /** Key constant @type Number */
200 </span>    F9: 120,
201 <span id='Ext-EventObject-property-F10'>    /** Key constant @type Number */
202 </span>    F10: 121,
203 <span id='Ext-EventObject-property-F11'>    /** Key constant @type Number */
204 </span>    F11: 122,
205 <span id='Ext-EventObject-property-F12'>    /** Key constant @type Number */
206 </span>    F12: 123,
207
208 <span id='Ext-EventObject-property-clickRe'>    /**
209 </span>     * Simple click regex
210      * @private
211      */
212     clickRe: /(dbl)?click/,
213     // safari keypress events for special keys return bad keycodes
214     safariKeys: {
215         3: 13, // enter
216         63234: 37, // left
217         63235: 39, // right
218         63232: 38, // up
219         63233: 40, // down
220         63276: 33, // page up
221         63277: 34, // page down
222         63272: 46, // delete
223         63273: 36, // home
224         63275: 35 // end
225     },
226     // normalize button clicks, don't see any way to feature detect this.
227     btnMap: Ext.isIE ? {
228         1: 0,
229         4: 1,
230         2: 2
231     } : {
232         0: 0,
233         1: 1,
234         2: 2
235     },
236
237     constructor: function(event, freezeEvent){
238         if (event) {
239             this.setEvent(event.browserEvent || event, freezeEvent);
240         }
241     },
242
243     setEvent: function(event, freezeEvent){
244         var me = this, button, options;
245
246         if (event == me || (event &amp;&amp; event.browserEvent)) { // already wrapped
247             return event;
248         }
249         me.browserEvent = event;
250         if (event) {
251             // normalize buttons
252             button = event.button ? me.btnMap[event.button] : (event.which ? event.which - 1 : -1);
253             if (me.clickRe.test(event.type) &amp;&amp; button == -1) {
254                 button = 0;
255             }
256             options = {
257                 type: event.type,
258                 button: button,
259                 shiftKey: event.shiftKey,
260                 // mac metaKey behaves like ctrlKey
261                 ctrlKey: event.ctrlKey || event.metaKey || false,
262                 altKey: event.altKey,
263                 // in getKey these will be normalized for the mac
264                 keyCode: event.keyCode,
265                 charCode: event.charCode,
266                 // cache the targets for the delayed and or buffered events
267                 target: Ext.EventManager.getTarget(event),
268                 relatedTarget: Ext.EventManager.getRelatedTarget(event),
269                 currentTarget: event.currentTarget,
270                 xy: (freezeEvent ? me.getXY() : null)
271             };
272         } else {
273             options = {
274                 button: -1,
275                 shiftKey: false,
276                 ctrlKey: false,
277                 altKey: false,
278                 keyCode: 0,
279                 charCode: 0,
280                 target: null,
281                 xy: [0, 0]
282             };
283         }
284         Ext.apply(me, options);
285         return me;
286     },
287
288 <span id='Ext-EventObject-method-stopEvent'>    /**
289 </span>     * Stop the event (preventDefault and stopPropagation)
290      */
291     stopEvent: function(){
292         this.stopPropagation();
293         this.preventDefault();
294     },
295
296 <span id='Ext-EventObject-method-preventDefault'>    /**
297 </span>     * Prevents the browsers default handling of the event.
298      */
299     preventDefault: function(){
300         if (this.browserEvent) {
301             Ext.EventManager.preventDefault(this.browserEvent);
302         }
303     },
304
305 <span id='Ext-EventObject-method-stopPropagation'>    /**
306 </span>     * Cancels bubbling of the event.
307      */
308     stopPropagation: function(){
309         var browserEvent = this.browserEvent;
310
311         if (browserEvent) {
312             if (browserEvent.type == 'mousedown') {
313                 Ext.EventManager.stoppedMouseDownEvent.fire(this);
314             }
315             Ext.EventManager.stopPropagation(browserEvent);
316         }
317     },
318
319 <span id='Ext-EventObject-method-getCharCode'>    /**
320 </span>     * Gets the character code for the event.
321      * @return {Number}
322      */
323     getCharCode: function(){
324         return this.charCode || this.keyCode;
325     },
326
327 <span id='Ext-EventObject-method-getKey'>    /**
328 </span>     * Returns a normalized keyCode for the event.
329      * @return {Number} The key code
330      */
331     getKey: function(){
332         return this.normalizeKey(this.keyCode || this.charCode);
333     },
334
335 <span id='Ext-EventObject-method-normalizeKey'>    /**
336 </span>     * Normalize key codes across browsers
337      * @private
338      * @param {Number} key The key code
339      * @return {Number} The normalized code
340      */
341     normalizeKey: function(key){
342         // can't feature detect this
343         return Ext.isWebKit ? (this.safariKeys[key] || key) : key;
344     },
345
346 <span id='Ext-EventObject-method-getPageX'>    /**
347 </span>     * Gets the x coordinate of the event.
348      * @return {Number}
349      * @deprecated 4.0 Replaced by {@link #getX}
350      */
351     getPageX: function(){
352         return this.getX();
353     },
354
355 <span id='Ext-EventObject-method-getPageY'>    /**
356 </span>     * Gets the y coordinate of the event.
357      * @return {Number}
358      * @deprecated 4.0 Replaced by {@link #getY}
359      */
360     getPageY: function(){
361         return this.getY();
362     },
363     
364 <span id='Ext-EventObject-method-getX'>    /**
365 </span>     * Gets the x coordinate of the event.
366      * @return {Number}
367      */
368     getX: function() {
369         return this.getXY()[0];
370     },    
371     
372 <span id='Ext-EventObject-method-getY'>    /**
373 </span>     * Gets the y coordinate of the event.
374      * @return {Number}
375      */
376     getY: function() {
377         return this.getXY()[1];
378     },
379         
380 <span id='Ext-EventObject-method-getXY'>    /**
381 </span>     * Gets the page coordinates of the event.
382      * @return {Array} The xy values like [x, y]
383      */
384     getXY: function() {
385         if (!this.xy) {
386             // same for XY
387             this.xy = Ext.EventManager.getPageXY(this.browserEvent);
388         }
389         return this.xy;
390     },
391
392 <span id='Ext-EventObject-method-getTarget'>    /**
393 </span>     * Gets the target for the event.
394      * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
395      * @param {Number/Mixed} maxDepth (optional) The max depth to search as a number or element (defaults to 10 || document.body)
396      * @param {Boolean} returnEl (optional) True to return a Ext.core.Element object instead of DOM node
397      * @return {HTMLelement}
398      */
399     getTarget : function(selector, maxDepth, returnEl){
400         if (selector) {
401             return Ext.fly(this.target).findParent(selector, maxDepth, returnEl);
402         }
403         return returnEl ? Ext.get(this.target) : this.target;
404     },
405
406 <span id='Ext-EventObject-method-getRelatedTarget'>    /**
407 </span>     * Gets the related target.
408      * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
409      * @param {Number/Mixed} maxDepth (optional) The max depth to search as a number or element (defaults to 10 || document.body)
410      * @param {Boolean} returnEl (optional) True to return a Ext.core.Element object instead of DOM node
411      * @return {HTMLElement}
412      */
413     getRelatedTarget : function(selector, maxDepth, returnEl){
414         if (selector) {
415             return Ext.fly(this.relatedTarget).findParent(selector, maxDepth, returnEl);
416         }
417         return returnEl ? Ext.get(this.relatedTarget) : this.relatedTarget;
418     },
419
420 <span id='Ext-EventObject-method-getWheelDelta'>    /**
421 </span>     * Normalizes mouse wheel delta across browsers
422      * @return {Number} The delta
423      */
424     getWheelDelta : function(){
425         var event = this.browserEvent,
426             delta = 0;
427
428         if (event.wheelDelta) { /* IE/Opera. */
429             delta = event.wheelDelta / 120;
430         } else if (event.detail){ /* Mozilla case. */
431             delta = -event.detail / 3;
432         }
433         return delta;
434     },
435
436 <span id='Ext-EventObject-method-within'>    /**
437 </span>    * 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.
438     * Example usage:&lt;pre&gt;&lt;code&gt;
439 // Handle click on any child of an element
440 Ext.getBody().on('click', function(e){
441     if(e.within('some-el')){
442         alert('Clicked on a child of some-el!');
443     }
444 });
445
446 // Handle click directly on an element, ignoring clicks on child nodes
447 Ext.getBody().on('click', function(e,t){
448     if((t.id == 'some-el') &amp;&amp; !e.within(t, true)){
449         alert('Clicked directly on some-el!');
450     }
451 });
452 &lt;/code&gt;&lt;/pre&gt;
453      * @param {Mixed} el The id, DOM element or Ext.core.Element to check
454      * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
455      * @param {Boolean} allowEl {optional} true to also check if the passed element is the target or related target
456      * @return {Boolean}
457      */
458     within : function(el, related, allowEl){
459         if(el){
460             var t = related ? this.getRelatedTarget() : this.getTarget(),
461                 result;
462
463             if (t) {
464                 result = Ext.fly(el).contains(t);
465                 if (!result &amp;&amp; allowEl) {
466                     result = t == Ext.getDom(el);
467                 }
468                 return result;
469             }
470         }
471         return false;
472     },
473
474 <span id='Ext-EventObject-method-isNavKeyPress'>    /**
475 </span>     * Checks if the key pressed was a &quot;navigation&quot; key
476      * @return {Boolean} True if the press is a navigation keypress
477      */
478     isNavKeyPress : function(){
479         var me = this,
480             k = this.normalizeKey(me.keyCode);
481
482        return (k &gt;= 33 &amp;&amp; k &lt;= 40) ||  // Page Up/Down, End, Home, Left, Up, Right, Down
483        k == me.RETURN ||
484        k == me.TAB ||
485        k == me.ESC;
486     },
487
488 <span id='Ext-EventObject-method-isSpecialKey'>    /**
489 </span>     * Checks if the key pressed was a &quot;special&quot; key
490      * @return {Boolean} True if the press is a special keypress
491      */
492     isSpecialKey : function(){
493         var k = this.normalizeKey(this.keyCode);
494         return (this.type == 'keypress' &amp;&amp; this.ctrlKey) ||
495         this.isNavKeyPress() ||
496         (k == this.BACKSPACE) || // Backspace
497         (k &gt;= 16 &amp;&amp; k &lt;= 20) || // Shift, Ctrl, Alt, Pause, Caps Lock
498         (k &gt;= 44 &amp;&amp; k &lt;= 46);   // Print Screen, Insert, Delete
499     },
500
501 <span id='Ext-EventObject-method-getPoint'>    /**
502 </span>     * Returns a point object that consists of the object coordinates.
503      * @return {Ext.util.Point} point
504      */
505     getPoint : function(){
506         var xy = this.getXY();
507         return Ext.create('Ext.util.Point', xy[0], xy[1]);
508     },
509
510 <span id='Ext-EventObject-method-hasModifier'>   /**
511 </span>    * Returns true if the control, meta, shift or alt key was pressed during this event.
512     * @return {Boolean}
513     */
514     hasModifier : function(){
515         return this.ctrlKey || this.altKey || this.shiftKey || this.metaKey;
516     },
517
518 <span id='Ext-EventObject-method-injectEvent'>    /**
519 </span>     * Injects a DOM event using the data in this object and (optionally) a new target.
520      * This is a low-level technique and not likely to be used by application code. The
521      * currently supported event types are:
522      * &lt;p&gt;&lt;b&gt;HTMLEvents&lt;/b&gt;&lt;/p&gt;
523      * &lt;ul&gt;
524      * &lt;li&gt;load&lt;/li&gt;
525      * &lt;li&gt;unload&lt;/li&gt;
526      * &lt;li&gt;select&lt;/li&gt;
527      * &lt;li&gt;change&lt;/li&gt;
528      * &lt;li&gt;submit&lt;/li&gt;
529      * &lt;li&gt;reset&lt;/li&gt;
530      * &lt;li&gt;resize&lt;/li&gt;
531      * &lt;li&gt;scroll&lt;/li&gt;
532      * &lt;/ul&gt;
533      * &lt;p&gt;&lt;b&gt;MouseEvents&lt;/b&gt;&lt;/p&gt;
534      * &lt;ul&gt;
535      * &lt;li&gt;click&lt;/li&gt;
536      * &lt;li&gt;dblclick&lt;/li&gt;
537      * &lt;li&gt;mousedown&lt;/li&gt;
538      * &lt;li&gt;mouseup&lt;/li&gt;
539      * &lt;li&gt;mouseover&lt;/li&gt;
540      * &lt;li&gt;mousemove&lt;/li&gt;
541      * &lt;li&gt;mouseout&lt;/li&gt;
542      * &lt;/ul&gt;
543      * &lt;p&gt;&lt;b&gt;UIEvents&lt;/b&gt;&lt;/p&gt;
544      * &lt;ul&gt;
545      * &lt;li&gt;focusin&lt;/li&gt;
546      * &lt;li&gt;focusout&lt;/li&gt;
547      * &lt;li&gt;activate&lt;/li&gt;
548      * &lt;li&gt;focus&lt;/li&gt;
549      * &lt;li&gt;blur&lt;/li&gt;
550      * &lt;/ul&gt;
551      * @param {Element/HTMLElement} target If specified, the target for the event. This
552      * is likely to be used when relaying a DOM event. If not specified, {@link #getTarget}
553      * is used to determine the target.
554      */
555     injectEvent: function () {
556         var API,
557             dispatchers = {}; // keyed by event type (e.g., 'mousedown')
558
559         // Good reference: http://developer.yahoo.com/yui/docs/UserAction.js.html
560
561         // IE9 has createEvent, but this code causes major problems with htmleditor (it
562         // blocks all mouse events and maybe more). TODO
563
564         if (!Ext.isIE &amp;&amp; document.createEvent) { // if (DOM compliant)
565             API = {
566                 createHtmlEvent: function (doc, type, bubbles, cancelable) {
567                     var event = doc.createEvent('HTMLEvents');
568
569                     event.initEvent(type, bubbles, cancelable);
570                     return event;
571                 },
572
573                 createMouseEvent: function (doc, type, bubbles, cancelable, detail,
574                                             clientX, clientY, ctrlKey, altKey, shiftKey, metaKey,
575                                             button, relatedTarget) {
576                     var event = doc.createEvent('MouseEvents'),
577                         view = doc.defaultView || window;
578
579                     if (event.initMouseEvent) {
580                         event.initMouseEvent(type, bubbles, cancelable, view, detail,
581                                     clientX, clientY, clientX, clientY, ctrlKey, altKey,
582                                     shiftKey, metaKey, button, relatedTarget);
583                     } else { // old Safari
584                         event = doc.createEvent('UIEvents');
585                         event.initEvent(type, bubbles, cancelable);
586                         event.view = view;
587                         event.detail = detail;
588                         event.screenX = clientX;
589                         event.screenY = clientY;
590                         event.clientX = clientX;
591                         event.clientY = clientY;
592                         event.ctrlKey = ctrlKey;
593                         event.altKey = altKey;
594                         event.metaKey = metaKey;
595                         event.shiftKey = shiftKey;
596                         event.button = button;
597                         event.relatedTarget = relatedTarget;
598                     }
599
600                     return event;
601                 },
602
603                 createUIEvent: function (doc, type, bubbles, cancelable, detail) {
604                     var event = doc.createEvent('UIEvents'),
605                         view = doc.defaultView || window;
606
607                     event.initUIEvent(type, bubbles, cancelable, view, detail);
608                     return event;
609                 },
610
611                 fireEvent: function (target, type, event) {
612                     target.dispatchEvent(event);
613                 },
614
615                 fixTarget: function (target) {
616                     // Safari3 doesn't have window.dispatchEvent()
617                     if (target == window &amp;&amp; !target.dispatchEvent) {
618                         return document;
619                     }
620
621                     return target;
622                 }
623             }
624         } else if (document.createEventObject) { // else if (IE)
625             var crazyIEButtons = { 0: 1, 1: 4, 2: 2 };
626
627             API = {
628                 createHtmlEvent: function (doc, type, bubbles, cancelable) {
629                     var event = doc.createEventObject();
630                     event.bubbles = bubbles;
631                     event.cancelable = cancelable;
632                     return event;
633                 },
634
635                 createMouseEvent: function (doc, type, bubbles, cancelable, detail,
636                                             clientX, clientY, ctrlKey, altKey, shiftKey, metaKey,
637                                             button, relatedTarget) {
638                     var event = doc.createEventObject();
639                     event.bubbles = bubbles;
640                     event.cancelable = cancelable;
641                     event.detail = detail;
642                     event.screenX = clientX;
643                     event.screenY = clientY;
644                     event.clientX = clientX;
645                     event.clientY = clientY;
646                     event.ctrlKey = ctrlKey;
647                     event.altKey = altKey;
648                     event.shiftKey = shiftKey;
649                     event.metaKey = metaKey;
650                     event.button = crazyIEButtons[button] || button;
651                     event.relatedTarget = relatedTarget; // cannot assign to/fromElement
652                     return event;
653                 },
654
655                 createUIEvent: function (doc, type, bubbles, cancelable, detail) {
656                     var event = doc.createEventObject();
657                     event.bubbles = bubbles;
658                     event.cancelable = cancelable;
659                     return event;
660                 },
661
662                 fireEvent: function (target, type, event) {
663                     target.fireEvent('on' + type, event);
664                 },
665
666                 fixTarget: function (target) {
667                     if (target == document) {
668                         // IE6,IE7 thinks window==document and doesn't have window.fireEvent()
669                         // IE6,IE7 cannot properly call document.fireEvent()
670                         return document.documentElement;
671                     }
672
673                     return target;
674                 }
675             };
676         }
677
678         //----------------
679         // HTMLEvents
680
681         Ext.Object.each({
682                 load:   [false, false],
683                 unload: [false, false],
684                 select: [true, false],
685                 change: [true, false],
686                 submit: [true, true],
687                 reset:  [true, false],
688                 resize: [true, false],
689                 scroll: [true, false]
690             },
691             function (name, value) {
692                 var bubbles = value[0], cancelable = value[1];
693                 dispatchers[name] = function (targetEl, srcEvent) {
694                     var e = API.createHtmlEvent(name, bubbles, cancelable);
695                     API.fireEvent(targetEl, name, e);
696                 };
697             });
698
699         //----------------
700         // MouseEvents
701
702         function createMouseEventDispatcher (type, detail) {
703             var cancelable = (type != 'mousemove');
704             return function (targetEl, srcEvent) {
705                 var xy = srcEvent.getXY(),
706                     e = API.createMouseEvent(targetEl.ownerDocument, type, true, cancelable,
707                                 detail, xy[0], xy[1], srcEvent.ctrlKey, srcEvent.altKey,
708                                 srcEvent.shiftKey, srcEvent.metaKey, srcEvent.button,
709                                 srcEvent.relatedTarget);
710                 API.fireEvent(targetEl, type, e);
711             };
712         }
713
714         Ext.each(['click', 'dblclick', 'mousedown', 'mouseup', 'mouseover', 'mousemove', 'mouseout'],
715             function (eventName) {
716                 dispatchers[eventName] = createMouseEventDispatcher(eventName, 1);
717             });
718
719         //----------------
720         // UIEvents
721
722         Ext.Object.each({
723                 focusin:  [true, false],
724                 focusout: [true, false],
725                 activate: [true, true],
726                 focus:    [false, false],
727                 blur:     [false, false]
728             },
729             function (name, value) {
730                 var bubbles = value[0], cancelable = value[1];
731                 dispatchers[name] = function (targetEl, srcEvent) {
732                     var e = API.createUIEvent(targetEl.ownerDocument, name, bubbles, cancelable, 1);
733                     API.fireEvent(targetEl, name, e);
734                 };
735             });
736
737         //---------
738         if (!API) {
739             // not even sure what ancient browsers fall into this category...
740
741             dispatchers = {}; // never mind all those we just built :P
742
743             API = {
744                 fixTarget: function (t) {
745                     return t;
746                 }
747             };
748         }
749
750         function cannotInject (target, srcEvent) {
751             //&lt;debug&gt;
752             // TODO log something
753             //&lt;/debug&gt;
754         }
755
756         return function (target) {
757             var me = this,
758                 dispatcher = dispatchers[me.type] || cannotInject,
759                 t = target ? (target.dom || target) : me.getTarget();
760
761             t = API.fixTarget(t);
762             dispatcher(t, me);
763         };
764     }() // call to produce method
765
766 }, function() {
767
768 Ext.EventObject = new Ext.EventObjectImpl();
769
770 });
771
772 </pre></pre></body></html>