2
* Ext JS Library 3.0 RC2
3
* Copyright(c) 2006-2009, Ext JS, LLC.
6
* http://extjs.com/license
10
* @class Ext.EventManager
11
* Registers event handlers that want to receive a normalized EventObject instead of the standard browser event and provides
12
* several useful events directly.
13
* See {@link Ext.EventObject} for more details on normalized event objects.
16
Ext.EventManager = function(){
19
docReadyState = false,
24
IEDEFERED = "ie-deferred-loader",
25
DOMCONTENTLOADED = "DOMContentLoaded",
27
propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
29
/// There is some jquery work around stuff here that isn't needed in Ext Core.
30
function addListener(el, ename, fn, wrap, scope){
32
es = elHash[id] = elHash[id] || {};
34
(es[ename] = es[ename] || []).push([fn, wrap, scope]);
35
E.on(el, ename, wrap);
37
// this is a workaround for jQuery and should somehow be removed from Ext Core in the future
38
// without breaking ExtJS.
39
if(ename == "mousewheel" && el.addEventListener){ // workaround for jQuery
40
var args = ["DOMMouseScroll", wrap, false];
41
el.addEventListener.apply(el, args);
42
E.on(window, 'unload', function(){
43
el.removeEventListener.apply(el, args);
46
if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
47
Ext.EventManager.stoppedMouseDownEvent.addListener(wrap);
51
function fireDocReady(){
53
Ext.isReady = docReadyState = true;
55
clearInterval(docReadyProcId);
57
if(Ext.isGecko || Ext.isOpera) {
58
DOC.removeEventListener(DOMCONTENTLOADED, fireDocReady, false);
61
var defer = DOC.getElementById(IEDEFERED);
63
defer.onreadystatechange = null;
64
defer.parentNode.removeChild(defer);
69
docReadyEvent.clearListeners();
74
function initDocReady(){
75
var COMPLETE = "complete";
77
docReadyEvent = new Ext.util.Event();
78
if (Ext.isGecko || Ext.isOpera) {
79
DOC.addEventListener(DOMCONTENTLOADED, fireDocReady, false);
81
DOC.write("<s"+'cript id=' + IEDEFERED + ' defer="defer" src="/'+'/:"></s'+"cript>");
82
DOC.getElementById(IEDEFERED).onreadystatechange = function(){
83
if(this.readyState == COMPLETE){
87
} else if (Ext.isWebKit){
88
docReadyProcId = setInterval(function(){
89
if(DOC.readyState == COMPLETE) {
94
// no matter what, make sure it fires on load
95
E.on(WINDOW, "load", fireDocReady);
98
function createTargeted(h, o){
100
var args = Ext.toArray(arguments);
101
if(o.target == Ext.EventObject.setEvent(args[0]).target){
107
function createBuffered(h, o){
108
var task = new Ext.util.DelayedTask(h);
110
// create new event object impl so new events don't wipe out properties
111
task.delay(o.buffer, h, null, [new Ext.EventObjectImpl(e)]);
115
function createSingle(h, el, ename, fn, scope){
117
Ext.EventManager.removeListener(el, ename, fn, scope);
122
function createDelayed(h, o){
124
// create new event object impl so new events don't wipe out properties
125
e = new Ext.EventObjectImpl(e);
126
setTimeout(function(){
132
function listen(element, ename, opt, fn, scope){
133
var o = !Ext.isObject(opt) ? {} : opt,
134
el = Ext.getDom(element);
137
scope = scope || o.scope;
140
throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
143
// prevent errors while unload occurring
144
if(!Ext){// !window[xname]){ ==> can't we do this?
147
e = Ext.EventObject.setEvent(e);
150
if(!(t = e.getTarget(o.delegate, el))){
159
if (o.preventDefault) {
162
if (o.stopPropagation) {
169
fn.call(scope || el, e, t, o);
172
h = createTargeted(h, o);
175
h = createDelayed(h, o);
178
h = createSingle(h, el, ename, fn, scope);
181
h = createBuffered(h, o);
184
addListener(el, ename, fn, h, scope);
190
* Appends an event handler to an element. The shorthand version {@link #on} is equivalent. Typically you will
191
* use {@link Ext.Element#addListener} directly on an Element in favor of calling this version.
192
* @param {String/HTMLElement} el The html element or id to assign the event handler to
193
* @param {String} eventName The type of event to listen for
194
* @param {Function} handler The handler function the event invokes This function is passed
195
* the following parameters:<ul>
196
* <li>evt : EventObject<div class="sub-desc">The {@link Ext.EventObject EventObject} describing the event.</div></li>
197
* <li>t : Element<div class="sub-desc">The {@link Ext.Element Element} which was the target of the event.
198
* Note that this may be filtered by using the <tt>delegate</tt> option.</div></li>
199
* <li>o : Object<div class="sub-desc">The options object from the addListener call.</div></li>
201
* @param {Object} scope (optional) The scope in which to execute the handler
202
* function (the handler function's "this" context)
203
* @param {Object} options (optional) An object containing handler configuration properties.
204
* This may contain any of the following properties:<ul>
205
* <li>scope {Object} : The scope in which to execute the handler function. The handler function's "this" context.</li>
206
* <li>delegate {String} : A simple selector to filter the target or look for a descendant of the target</li>
207
* <li>stopEvent {Boolean} : True to stop the event. That is stop propagation, and prevent the default action.</li>
208
* <li>preventDefault {Boolean} : True to prevent the default action</li>
209
* <li>stopPropagation {Boolean} : True to prevent event propagation</li>
210
* <li>normalized {Boolean} : False to pass a browser event to the handler function instead of an Ext.EventObject</li>
211
* <li>delay {Number} : The number of milliseconds to delay the invocation of the handler after te event fires.</li>
212
* <li>single {Boolean} : True to add a handler to handle just the next firing of the event, and then remove itself.</li>
213
* <li>buffer {Number} : Causes the handler to be scheduled to run in an {@link Ext.util.DelayedTask} delayed
214
* by the specified number of milliseconds. If the event fires again within that time, the original
215
* handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
216
* <li>target {Element} : Only call the handler if the event was fired on the target Element, <i>not</i>
217
* if the event was bubbled up from a child node.</li>
219
* <p>See {@link Ext.Element#addListener} for examples of how to use these options.</p>
221
addListener : function(element, eventName, fn, scope, options){
222
if(Ext.isObject(eventName)){
223
var o = eventName, e, val;
227
if(Ext.isFunction(val)){
229
listen(element, e, o, val, o.scope);
231
// individual options
232
listen(element, e, val);
237
listen(element, eventName, options, fn, scope);
242
* Removes an event handler from an element. The shorthand version {@link #un} is equivalent. Typically
243
* you will use {@link Ext.Element#removeListener} directly on an Element in favor of calling this version.
244
* @param {String/HTMLElement} el The id or html element from which to remove the event
245
* @param {String} eventName The type of event
246
* @param {Function} fn The handler function to remove
248
removeListener : function(element, eventName, fn, scope){
249
var el = Ext.getDom(element),
253
Ext.each((elHash[id] || {})[eventName], function (v,i,a) {
254
if (Ext.isArray(v) && v[0] == fn && (!scope || v[2] == scope)) {
255
E.un(el, eventName, wrap = v[1]);
261
// jQuery workaround that should be removed from Ext Core
262
if(eventName == "mousewheel" && el.addEventListener && wrap){
263
el.removeEventListener("DOMMouseScroll", wrap, false);
266
if(eventName == "mousedown" && el == DOC && wrap){ // fix stopped mousedowns on the document
267
Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);
272
* Removes all event handers from an element. Typically you will use {@link Ext.Element#removeAllListeners}
273
* directly on an Element in favor of calling this version.
274
* @param {String/HTMLElement} el The id or html element from which to remove the event
276
removeAll : function(el){
277
var id = Ext.id(el = Ext.getDom(el)),
282
if(es.hasOwnProperty(ename)){
283
Ext.each(es[ename], function(v) {
284
E.un(el, ename, v.wrap);
292
* Fires when the document is ready (before onload and before images are loaded). Can be
293
* accessed shorthanded as Ext.onReady().
294
* @param {Function} fn The method the event invokes
295
* @param {Object} scope (optional) An object that becomes the scope of the handler
296
* @param {boolean} options (optional) An object containing standard {@link #addListener} options
298
onDocumentReady : function(fn, scope, options){
299
if(docReadyState){ // if it already fired
300
docReadyEvent.addListener(fn, scope, options);
301
docReadyEvent.fire();
302
docReadyEvent.clearListeners();
304
if(!docReadyEvent) initDocReady();
305
options = options || {};
306
options.delay = options.delay || 1;
307
docReadyEvent.addListener(fn, scope, options);
314
* Appends an event handler to an element. Shorthand for {@link #addListener}.
315
* @param {String/HTMLElement} el The html element or id to assign the event handler to
316
* @param {String} eventName The type of event to listen for
317
* @param {Function} handler The handler function the event invokes
318
* @param {Object} scope (optional) The scope in which to execute the handler
319
* function (the handler function's "this" context)
320
* @param {Object} options (optional) An object containing standard {@link #addListener} options
321
* @member Ext.EventManager
324
pub.on = pub.addListener;
326
* Removes an event handler from an element. Shorthand for {@link #removeListener}.
327
* @param {String/HTMLElement} el The id or html element from which to remove the event
328
* @param {String} eventName The type of event
329
* @param {Function} fn The handler function to remove
330
* @return {Boolean} True if a listener was actually removed, else false
331
* @member Ext.EventManager
334
pub.un = pub.removeListener;
336
pub.stoppedMouseDownEvent = new Ext.util.Event();
340
* Fires when the document is ready (before onload and before images are loaded). Shorthand of {@link Ext.EventManager#onDocumentReady}.
341
* @param {Function} fn The method the event invokes
342
* @param {Object} scope An object that becomes the scope of the handler
343
* @param {boolean} options (optional) An object containing standard {@link #addListener} options
347
Ext.onReady = Ext.EventManager.onDocumentReady;
350
//Initialize doc classes
353
var initExtCss = function(){
354
// find the body element
355
var bd = document.body || document.getElementsByTagName('body')[0];
356
if(!bd){ return false; }
358
Ext.isIE ? "ext-ie " + (Ext.isIE6 ? 'ext-ie6' : (Ext.isIE7 ? 'ext-ie7' : 'ext-ie8'))
359
: Ext.isGecko ? "ext-gecko " + (Ext.isGecko2 ? 'ext-gecko2' : 'ext-gecko3')
360
: Ext.isOpera ? "ext-opera"
361
: Ext.isWebKit ? "ext-webkit" : ""];
364
cls.push("ext-safari " + (Ext.isSafari2 ? 'ext-safari2' : (Ext.isSafari3 ? 'ext-safari3' : 'ext-safari4')));
365
}else if(Ext.isChrome){
366
cls.push("ext-chrome");
373
cls.push("ext-linux");
376
cls.push('ext-border-box');
378
if(Ext.isStrict){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"
379
var p = bd.parentNode;
381
p.className += ' ext-strict';
384
bd.className += cls.join(' ');
389
Ext.onReady(initExtCss);
395
* @class Ext.EventObject
396
* Just as {@link Ext.Element} wraps around a native DOM node, Ext.EventObject
397
* wraps the browser's native event-object normalizing cross-browser differences,
398
* such as which mouse button is clicked, keys pressed, mechanisms to stop
399
* event-propagation along with a method to prevent default actions from taking place.
400
* <p>For example:</p>
402
function handleClick(e, t){ // e is not a standard event object, it is a Ext.EventObject
404
var target = e.getTarget(); // same as t (the target HTMLElement)
407
var myDiv = {@link Ext#get Ext.get}("myDiv"); // get reference to an {@link Ext.Element}
408
myDiv.on( // 'on' is shorthand for addListener
409
"click", // perform an action on click of myDiv
410
handleClick // reference to the action handler
412
// other methods to do the same:
413
Ext.EventManager.on("myDiv", 'click', handleClick);
414
Ext.EventManager.addListener("myDiv", 'click', handleClick);
418
Ext.EventObject = function(){
419
var E = Ext.lib.Event,
420
// safari keypress events for special keys return bad keycodes
427
63276 : 33, // page up
428
63277 : 34, // page down
429
63272 : 46, // delete
433
// normalize button clicks
434
btnMap = Ext.isIE ? {1:0,4:1,2:2} :
435
(Ext.isWebKit ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
437
Ext.EventObjectImpl = function(e){
439
this.setEvent(e.browserEvent || e);
443
Ext.EventObjectImpl.prototype = {
445
setEvent : function(e){
447
if(e == me || (e && e.browserEvent)){ // already wrapped
453
me.button = e.button ? btnMap[e.button] : (e.which ? e.which - 1 : -1);
454
if(e.type == 'click' && me.button == -1){
458
me.shiftKey = e.shiftKey;
459
// mac metaKey behaves like ctrlKey
460
me.ctrlKey = e.ctrlKey || e.metaKey;
461
me.altKey = e.altKey;
462
// in getKey these will be normalized for the mac
463
me.keyCode = e.keyCode;
464
me.charCode = e.charCode;
465
// cache the target for the delayed and or buffered events
466
me.target = E.getTarget(e);
483
* Stop the event (preventDefault and stopPropagation)
485
stopEvent : function(){
488
if(me.browserEvent.type == 'mousedown'){
489
Ext.EventManager.stoppedMouseDownEvent.fire(me);
491
E.stopEvent(me.browserEvent);
496
* Prevents the browsers default handling of the event.
498
preventDefault : function(){
499
if(this.browserEvent){
500
E.preventDefault(this.browserEvent);
505
* Cancels bubbling of the event.
507
stopPropagation : function(){
510
if(me.browserEvent.type == 'mousedown'){
511
Ext.EventManager.stoppedMouseDownEvent.fire(me);
513
E.stopPropagation(me.browserEvent);
518
* Gets the character code for the event.
521
getCharCode : function(){
522
return this.charCode || this.keyCode;
526
* Returns a normalized keyCode for the event.
527
* @return {Number} The key code
530
return this.normalizeKey(this.keyCode || this.charCode)
534
normalizeKey: function(k){
535
return Ext.isSafari ? (safariKeys[k] || k) : k;
539
* Gets the x coordinate of the event.
542
getPageX : function(){
547
* Gets the y coordinate of the event.
550
getPageY : function(){
555
// * Gets the time of the event.
556
// * @return {Number}
558
// getTime : function(){
559
// if(this.browserEvent){
560
// return E.getTime(this.browserEvent);
566
* Gets the page coordinates of the event.
567
* @return {Array} The xy values like [x, y]
574
* Gets the target for the event.
575
* @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
576
* @param {Number/Mixed} maxDepth (optional) The max depth to
577
search as a number or element (defaults to 10 || document.body)
578
* @param {Boolean} returnEl (optional) True to return a Ext.Element object instead of DOM node
579
* @return {HTMLelement}
581
getTarget : function(selector, maxDepth, returnEl){
582
return selector ? Ext.fly(this.target).findParent(selector, maxDepth, returnEl) : (returnEl ? Ext.get(this.target) : this.target);
586
* Gets the related target.
587
* @return {HTMLElement}
589
getRelatedTarget : function(){
590
return this.browserEvent ? E.getRelatedTarget(this.browserEvent) : null;
594
* Normalizes mouse wheel delta across browsers
595
* @return {Number} The delta
597
getWheelDelta : function(){
598
var e = this.browserEvent;
600
if(e.wheelDelta){ /* IE/Opera. */
601
delta = e.wheelDelta/120;
602
}else if(e.detail){ /* Mozilla case. */
609
* 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.
610
* Example usage:<pre><code>
611
// Handle click on any child of an element
612
Ext.getBody().on('click', function(e){
613
if(e.within('some-el')){
614
alert('Clicked on a child of some-el!');
618
// Handle click directly on an element, ignoring clicks on child nodes
619
Ext.getBody().on('click', function(e,t){
620
if((t.id == 'some-el') && !e.within(t, true)){
621
alert('Clicked directly on some-el!');
625
* @param {Mixed} el The id, DOM element or Ext.Element to check
626
* @param {Boolean} related (optional) true to test if the related target is within el instead of the target
627
* @param {Boolean} allowEl {optional} true to also check if the passed element is the target or related target
630
within : function(el, related, allowEl){
632
var t = this[related ? "getRelatedTarget" : "getTarget"]();
633
return t && ((allowEl ? (t == Ext.getDom(el)) : false) || Ext.fly(el).contains(t));
639
return new Ext.EventObjectImpl();
b'\\ No newline at end of file'