/** * Just as {@link Ext.dom.Element} wraps around a native DOM node, {@link Ext.event.Event} wraps the browser's native * event-object normalizing cross-browser differences such as mechanisms to stop event-propagation along with a method * to prevent default actions from taking place. * * Here is a simple example of how you use it: * * @example * var container = Ext.create('Ext.Container', { * layout: 'fit', * renderTo: Ext.getBody(), * items: [{ * id: 'logger', * html: 'Click somewhere!', * padding: 5 * }] * }); * * container.getEl().on({ * click: function(e, node) { * var string = ''; * * string += 'You clicked at: <strong>{ x: ' + e.pageX + ', y: ' + e.pageY + ' }</strong> <i>(e.pageX & e.pageY)</i>'; * string += '<hr />'; * string += 'The HTMLElement you clicked has the className of: <strong>' + e.target.className + '</strong> <i>(e.target)</i>'; * string += '<hr />'; * string += 'The HTMLElement which has the listener has a className of: <strong>' + e.currentTarget.className + '</strong> <i>(e.currentTarget)</i>'; * * Ext.getCmp('logger').setHtml(string); * } * }); * * ## Recognizers * * Ext JS includes many default event recognizers to know when a user interacts with the application. * * For a full list of default recognizers, and more information, please view the {@link Ext.event.gesture.Recognizer} documentation. * * This class also provides a set of constants for use with key events. These are useful * for determining if a specific key was pressed, and are available both on instances, * and as static properties of the class. The following two statements are equivalent: * * if (e.getKey() === Ext.event.Event.TAB) { * // tab key was pressed * } * * if (e.getKey() === e.TAB) { * // tab key was pressed * } */Ext.define('Ext.event.Event', { alternateClassName: 'Ext.EventObjectImpl', requires: [ 'Ext.util.Point' ], /** * @property {Number} distance * The distance of the event. * * **This is only available when the event type is `swipe` and `pinch`.** */ /** * @property {HTMLElement} target * The element that fired this event. For the element whose handlers are currently * being processed, i.e. the element that the event handler was attached to, use * `currentTarget` */ /** * @property {HTMLElement} currentTarget * Refers to the element the event handler was attached to, vs the `target`, which is * the actual element that fired the event. For example, if the event bubbles, the * `target` element may be a descendant of the `currentTarget`, as the event may * have been triggered on the `target` and then bubbled up to the `currentTarget` * where it was handled. */ /** * @property {HTMLElement} delegatedTarget * Same as `currentTarget` * @deprecated 5.0.0 use {@link #currentTarget} instead. */ /** * @property {Number} button * Indicates which mouse button caused the event for mouse events, for example * `mousedown`, `click`, `mouseup`: * - `0` for left button. * - `1` for middle button. * - `2` for right button. * * *Note*: In IE8 & IE9, the `click` event does not provide the button. */ /** * @property {Number} pageX The browsers x coordinate of the event. * Note: this only works in browsers that support pageX on the native browser event * object (pageX is not natively supported in IE9 and earlier). In Ext JS, for a * cross browser normalized x-coordinate use {@link #getX} */ /** * @property {Number} pageY The browsers y coordinate of the event. * Note: this only works in browsers that support pageY on the native browser event * object (pageY is not natively supported in IE9 and earlier). In Ext JS, for a * cross browser normalized y-coordinate use {@link #getY} */ /** * @property {Boolean} ctrlKey * True if the control key was down during the event. * In Mac this will also be true when meta key was down. */ /** * @property {Boolean} altKey * True if the alt key was down during the event. */ /** * @property {Boolean} shiftKey * True if the shift key was down during the event. */ /** * @property {Event} browserEvent * The raw browser event which this object wraps. */ /** * @property {String} pointerType * The pointer type for this event. May be empty if the event was * not triggered by a pointer. Current available types are: * - `mouse` * - `touch` * - `pen` */ /** * @property {Boolean} * `true` if {@link #stopPropagation} has been called on this instance * @private */ stopped: false, /** * @property {Boolean} * `true` if {@link #claimGesture} has been called on this instance * @private */ claimed: false, /** * @property {Boolean} * Indicates whether or not {@link #preventDefault preventDefault()} was called on the event. */ defaultPrevented: false, isEvent: true, // With these events, the relatedTarget can sometimes be an Object literal in FF. geckoRelatedTargetEvents: { blur: 1, dragenter: 1, dragleave: 1, focus: 1 }, statics: { resolveTextNode: function(node) { return (node && node.nodeType === 3) ? node.parentNode : node; }, /** * @private * An amalgamation of pointerEvents/mouseEvents/touchEvents. * Will be populated in class callback. */ gestureEvents: {}, /** * @private */ pointerEvents: { pointerdown: 1, pointermove: 1, pointerup: 1, pointercancel: 1, pointerover: 1, pointerout: 1, pointerenter: 1, pointerleave: 1, MSPointerDown: 1, MSPointerMove: 1, MSPointerUp: 1, MSPointerOver: 1, MSPointerOut: 1, MSPointerCancel: 1, MSPointerEnter: 1, MSPointerLeave: 1 }, /** * @private */ mouseEvents: { mousedown: 1, mousemove: 1, mouseup: 1, mouseover: 1, mouseout: 1, mouseenter: 1, mouseleave: 1 }, /** * @private * These are tracked separately from mouseEvents because the mouseEvents map * is used by Dom publisher to eliminate duplicate events on devices that fire * multiple kinds of events (mouse, touch, pointer). Adding click events to the * mouse events map can cause click events to be blocked from firing in some cases. */ clickEvents: { click: 1, dblclick: 1 }, /** * @private */ touchEvents: { touchstart: 1, touchmove: 1, touchend: 1, touchcancel: 1 }, /** * @private */ focusEvents: { focus: 1, focusin: 1, focusenter: 1 }, /** * @private */ blurEvents: { blur: 1, focusout: 1, focusleave: 1 }, // msPointerTypes in IE10 are numbers, in the w3c spec they are strings. // this map allows us to normalize the pointerType for an event // http://www.w3.org/TR/pointerevents/#widl-PointerEvent-pointerType // http://msdn.microsoft.com/en-us/library/ie/hh772359(v=vs.85).aspx pointerTypeMap: { 2: 'touch', 3: 'pen', 4: 'mouse', touch: 'touch', pen: 'pen', mouse: 'mouse' }, keyEventRe: /^key/, keyFlags: { CTRL: 'ctrlKey', CONTROL: 'ctrlKey', ALT: 'altKey', SHIFT: 'shiftKey', CMD: 'metaKey', COMMAND: 'metaKey', CMDORCTRL: Ext.isMac ? 'metaKey' : 'ctrlKey', COMMANDORCONTROL: Ext.isMac ? 'metaKey' : 'ctrlKey', META: 'metaKey' }, modifierGlyphs: { ctrlKey: '\u2303', altKey: '\u2325', metaKey: Ext.isMac ? '\u2318' : '\u229e', shiftKey: '\u21E7' }, specialKeyGlyphs: { BACKSPACE: '\u232B', TAB: '\u21E5', ENTER: '\u23CE', RETURN: '\u23CE', SPACE: '\u2423', PAGE_UP: '\u21DE', PAGE_DOWN: '\u21DF', END: '\u21F2', HOME: '\u2302', LEFT: '\u2190', UP: '\u2191', RIGHT: '\u2192', DOWN: '\u2193', PRINT_SCREEN: '\u2399', INSERT: '\u2380', DELETE: '\u2326', CONTEXT_MENU: '\u2630' }, _hyphenRe: /^[a-z]+\-/i, // eg "Ctrl-" (instead of "Ctrl+") /** * Convert a key specification in the form eg: "CTRL+ALT+DELETE" to the glyph sequence * for use in menu items, eg "⌃⌥⌦". * @private */ getKeyId: function(keyName) { // Translate eg: 27 to "ESC" if (typeof keyName === 'number') { keyName = this.keyCodes[keyName]; } else { keyName = keyName.toUpperCase(); } var me = this, delim = me._hyphenRe.test(keyName) ? '-' : '+', parts = (keyName === delim) ? [delim] : keyName.split(delim), numModifiers = parts.length - 1, rawKey = parts[numModifiers], result = [], eventFlag, i; //<debug> if (!Ext.event.Event[rawKey]) { Ext.raise('Invalid key name: "' + rawKey + '"'); } //</debug> for (i = 0; i < numModifiers; i++) { eventFlag = me.keyFlags[parts[i]]; //<debug> if (!eventFlag) { Ext.raise('Invalid key modifier: "' + parts[i] + '"'); } //</debug> result[eventFlag] = true; } if (result.ctrlKey) { result.push(me.modifierGlyphs.ctrlKey); } if (result.altKey) { result.push(me.modifierGlyphs.altKey); } if (result.shiftKey) { result.push(me.modifierGlyphs.shiftKey); } if (result.metaKey) { result.push(me.modifierGlyphs.metaKey); } result.push(this.specialKeyGlyphs[rawKey] || rawKey); return result.join(''); }, /** * @private */ globalTabKeyDown: function(e) { if (e.keyCode === 9) { Ext.event.Event.forwardTab = !e.shiftKey; } }, /** * @private */ globalTabKeyUp: function(e) { if (e.keyCode === 9) { delete Ext.event.Event.forwardTab; } } }, constructor: function(event) { var me = this, self = me.self, resolveTextNode = me.self.resolveTextNode, changedTouches = event.changedTouches, // The target object from which to obtain the coordinates (pageX, pageY). For // mouse and pointer events this is simply the event object itself, but touch // events have their coordinates on the "Touch" object(s) instead. coordinateOwner = changedTouches ? changedTouches[0] : event, type = event.type, pointerType, relatedTarget; // Do not use event.timeStamp as it is not consistent cross browser (some browsers // use high resolution time stamps, while others use milliseconds) me.timeStamp = me.time = Ext.now(); me.pageX = coordinateOwner.pageX; me.pageY = coordinateOwner.pageY; me.clientX = coordinateOwner.clientX; me.clientY = coordinateOwner.clientY; me.target = me.delegatedTarget = resolveTextNode(event.target); me.currentTarget = resolveTextNode(event.currentTarget); relatedTarget = event.relatedTarget; if (relatedTarget) { if (Ext.isGecko && me.geckoRelatedTargetEvents[type]) { try { me.relatedTarget = resolveTextNode(relatedTarget); } catch(e) { me.relatedTarget = null; } } else { me.relatedTarget = resolveTextNode(relatedTarget); } } me.browserEvent = me.event = event; me.type = type; // set button to 0 if undefined so that touchstart, touchend, and tap will quack // like left mouse button mousedown mouseup, and click me.button = event.button || 0; me.shiftKey = event.shiftKey; // mac metaKey behaves like ctrlKey me.ctrlKey = event.ctrlKey || event.metaKey || false; me.altKey = event.altKey; me.charCode = event.charCode; me.keyCode = event.keyCode; me.buttons = event.buttons; // When invoking synthetic events, current APIs do not // have the ability to specify the buttons config, which // defaults to button. For buttons, 0 means no button // is pressed, whereas for button, 0 means left click. // Normalize that here if (me.button === 0 && me.buttons === 0) { me.buttons = 1; } if (self.focusEvents[type] || self.blurEvents[type]) { if (self.forwardTab !== undefined) { me.forwardTab = self.forwardTab; } if (self.focusEvents[type]) { me.fromElement = event.relatedTarget; me.toElement = event.target; } else { me.fromElement = event.target; me.toElement = event.relatedTarget; } } else if (type !== 'keydown') { // Normally this property should be cleaned up in keyup handler; // however that one might never come if something prevented default // on the keydown. Make sure the property won't get stuck. delete self.forwardTab; } if (self.mouseEvents[type]) { pointerType = 'mouse'; } else if (self.clickEvents[type]) { // On pointer events browsers like IE11 and Edge click events have a pointerType // property. On touch events devices we check if the last touchend event // happened less than a second ago - if so we can reasonably assume that // the click event happened because of a tap on the screen. pointerType = self.pointerTypeMap[event.pointerType] || (((Ext.now() - Ext.event.publisher.Dom.lastTouchEndTime) < 1000) ? 'touch' : 'mouse'); } else if (self.pointerEvents[type]) { // In electron the mousemove event when the mouse first enters the document // can have a pointerType of "", so default it to mouse if not found in the map. pointerType = self.pointerTypeMap[event.pointerType] || 'mouse'; } else if (self.touchEvents[type]) { pointerType = 'touch'; } if (pointerType) { me.pointerType = pointerType; } // Is this is not the primary touch for PointerEvents (first touch) // or there are multiples touches for Touch Events me.isMultitouch = event.isPrimary === false || (event.touches && event.touches.length > 1); }, /** * Creates a new Event object that is prototype-chained to this event. Useful for * creating identical events so that certain properties can be changed without * affecting the original event. For example, translated events have their "type" * corrected in this manner. * @param {Object} props properties to set on the chained event * @private */ chain: function(props) { var e = Ext.Object.chain(this); e.parentEvent = this; // needed for stopPropagation return Ext.apply(e, props); }, /** * Correctly scales a given wheel delta. * @param {Number} delta The delta value. * @private */ correctWheelDelta: function (delta) { var scale = this.WHEEL_SCALE, ret = Math.round(delta / scale); if (!ret && delta) { ret = (delta < 0) ? -1 : 1; // don't allow non-zero deltas to go to zero! } return ret; }, getChar: function () { var r = this.which(); return String.fromCharCode(r); }, /** * Gets the character code for the event. * @return {Number} */ getCharCode: function(){ return this.charCode || this.keyCode; }, /** * Returns a normalized keyCode for the event. * @return {Number} The key code */ getKey: function () { return this.keyCode || this.charCode; }, /** * Returns the name of the keyCode for the event. * @return {String} The key name */ getKeyName: function() { return this.type === 'keypress' ? String.fromCharCode(this.getCharCode()) : this.keyCodes[this.keyCode]; }, /** * Returns the `key` property of a keyboard event. * @return {String} */ key: function () { return this.browserEvent.key; }, which: function () { var me = this, e = me.browserEvent, r = e.which; if (r == null) { if (me.self.keyEventRe.test(e.type)) { r = e.charCode || e.keyCode; } else if ((r = e.button) !== undefined) { // L M R button codes (1, 4, 2): r = (r & 1) ? 1 : ((r & 4) ? 2 : ((r & 2) ? 3 : 0)); } } return r; }, /** * If this is an event of {@link #type} `paste`, this returns the clipboard data * of the pasesd mime type. * * @param {String} [type='text/plain'] The mime type of the data to extract from the * clipabord. * * Note that this uses non-standard browaer APIs and may not work reliably on all * platforms. * @return {Mixed} The clipboard data. * @since 6.5.1 */ getClipboardData: function(type) { var clipboardData = this.browserEvent.clipboardData, clipIE = Ext.global.clipboardData, // IE result = null, typeIE; type = type || 'text/plain'; if (clipboardData && clipboardData.getData) { result = clipboardData.getData(type); } else if (clipIE && clipIE.getData) { typeIE = this.ieMimeType[type]; if (typeIE) { result = clipIE.getData(typeIE); } } return result; }, /** * Returns a point object that consists of the object coordinates. * @return {Ext.util.Point} point */ getPoint: function () { var me = this, point = me.point, xy; if (!point) { xy = me.getXY(); point = me.point = new Ext.util.Point(xy[0], xy[1]); } return point; }, /** * Gets the related target. * @param {String} [selector] A simple selector to filter the target or look for an * ancestor of the target. See {@link Ext.dom.Query} for information about simple * selectors. * @param {Number/HTMLElement} [maxDepth] The max depth to search as a number or * element (defaults to 10 || document.body). * @param {Boolean} [returnEl] `true` to return a Ext.Element object instead of DOM * node. * @return {HTMLElement} */ getRelatedTarget: function(selector, maxDepth, returnEl){ var relatedTarget = this.relatedTarget, target = null; // In some cases in IE10/11, when the mouse is leaving the document over a scrollbar // the relatedTarget will be an empty object literal. So just check we have an element // looking object here before we proceed. if (relatedTarget && relatedTarget.nodeType) { if (selector) { target = Ext.fly(relatedTarget).findParent(selector, maxDepth, returnEl); } else { target = returnEl ? Ext.get(relatedTarget) : relatedTarget; } } return target; }, /** * Gets the target for the event. * @param {String} selector (optional) A simple selector to filter the target or look * for an ancestor of the target * @param {Number/Mixed} [maxDepth=10||document.body] (optional) The max depth to * search as a number or element (defaults to 10 || document.body) * @param {Boolean} returnEl (optional) `true` to return a Ext.Element object instead * of DOM node. * @return {HTMLElement} */ getTarget: function(selector, maxDepth, returnEl) { return selector ? Ext.fly(this.target).findParent(selector, maxDepth, returnEl) : (returnEl ? Ext.get(this.target) : this.target); }, /** * Returns the time of the event. * @return {Date} */ getTime: function() { return this.time; }, /** * Normalizes mouse wheel y-delta across browsers. To get x-delta information, use * {@link #getWheelDeltas} instead. * @return {Number} The mouse wheel y-delta */ getWheelDelta: function(){ var deltas = this.getWheelDeltas(); return deltas.y; }, /** * Returns the mouse wheel deltas for this event. * @return {Object} An object with "x" and "y" properties holding the mouse wheel deltas. */ getWheelDeltas: function () { var me = this, event = me.browserEvent, dx = 0, dy = 0; // the deltas if (Ext.isDefined(event.wheelDeltaX)) { // WebKit and Edge have both dimensions dx = event.wheelDeltaX; dy = event.wheelDeltaY; } else if (event.wheelDelta) { // old WebKit and IE dy = event.wheelDelta; } else if ('deltaX' in event) { // IE11 dx = event.deltaX; dy = -event.deltaY; // backwards } else if (event.detail) { // Gecko dy = -event.detail; // gecko is backwards // Gecko sometimes returns really big values if the user changes settings to // scroll a whole page per scroll if (dy > 100) { dy = 3; } else if (dy < -100) { dy = -3; } // Firefox 3.1 adds an axis field to the event to indicate direction of // scroll. See https://developer.mozilla.org/en/Gecko-Specific_DOM_Events if (Ext.isDefined(event.axis) && event.axis === event.HORIZONTAL_AXIS) { dx = dy; dy = 0; } } return { x: me.correctWheelDelta(dx), y: me.correctWheelDelta(dy) }; }, /** * Gets the x coordinate of the event. * @return {Number} */ getX: function() { return this.getXY()[0]; }, /** * Gets the X and Y coordinates of the event. * @return {Number[]} The xy values like [x, y] */ getXY: function() { var me = this, xy = me.xy; if (!xy) { xy = me.xy = [me.pageX, me.pageY]; //<feature legacyBrowser> var x = xy[0], browserEvent, doc, docEl, body; // pageX/pageY not available (undefined, not null), use clientX/clientY instead if (!x && x !== 0) { browserEvent = me.browserEvent; doc = document; docEl = doc.documentElement; body = doc.body; xy[0] = browserEvent.clientX + (docEl && docEl.scrollLeft || body && body.scrollLeft || 0) - (docEl && docEl.clientLeft || body && body.clientLeft || 0); xy[1] = browserEvent.clientY + (docEl && docEl.scrollTop || body && body.scrollTop || 0) - (docEl && docEl.clientTop || body && body.clientTop || 0); } //</feature> } return xy; }, /** * Gets the y coordinate of the event. * @return {Number} */ getY: function() { return this.getXY()[1]; }, /** * Returns true if the control, meta, shift or alt key was pressed during this event. * @return {Boolean} */ hasModifier: function() { var me = this; return !!(me.ctrlKey || me.altKey || me.shiftKey || me.metaKey); }, /** * Checks if the key pressed was a "navigation" key. A navigation key is defined by * these keys: * * - Page Up * - Page Down * - End * - Home * - Left * - Up * - Right * - Down * - Return * - Tab * - Esc * * @param {Boolean} [scrollableOnly] Only check navigation keys that can cause * element scrolling by their default action. * * @return {Boolean} `true` if the press is a navigation keypress */ isNavKeyPress: function(scrollableOnly) { var me = this, k = me.keyCode, isKeyPress = me.type === 'keypress'; // See specs for description of behaviour return ((!isKeyPress || Ext.isGecko) && k >= 33 && k <= 40) || // Page Up/Down, End, Home, Left, Up, Right, Down (!scrollableOnly && (k === me.RETURN || k === me.TAB || k === me.ESC)); }, /** * Checks if the key pressed was a "special" key. A special key is defined as one of * these keys: * * - Page Up * - Page Down * - End * - Home * - Left arrow * - Up arrow * - Right arrow * - Down arrow * - Return * - Tab * - Esc * - Backspace * - Delete * - Shift * - Ctrl * - Alt * - Pause * - Caps Lock * - Print Screen * - Insert * * @return {Boolean} `true` if the key for this event is special */ isSpecialKey: function() { var me = this, k = me.keyCode, isGecko = Ext.isGecko, isKeyPress = me.type === 'keypress'; // See specs for description of behaviour return (isGecko && isKeyPress && me.charCode === 0) || (this.isNavKeyPress()) || (k === me.BACKSPACE) || (k === me.ENTER) || (k >= 16 && k <= 20) || // Shift, Ctrl, Alt, Pause, Caps Lock ((!isKeyPress || isGecko) && k >= 44 && k <= 46); // Print Screen, Insert, Delete }, makeUnpreventable: function() { this.browserEvent.preventDefault = Ext.emptyFn; }, /** * Prevents the browsers default handling of the event. * @chainable */ preventDefault: function() { var me = this, parentEvent = me.parentEvent; me.defaultPrevented = true; // if the event was created by prototype-chaining a new object to an existing event // instance, we need to make sure the parent event is defaultPrevented as well. if (parentEvent) { parentEvent.defaultPrevented = true; } me.browserEvent.preventDefault(); return me; }, setCurrentTarget: function(target) { this.currentTarget = this.delegatedTarget = target; }, /** * Stop the event (`{@link #preventDefault}` and `{@link #stopPropagation}`). * @chainable */ stopEvent: function() { return this.preventDefault().stopPropagation(); }, // map of events that should fire global mousedown even if stopped mousedownEvents: { mousedown: 1, pointerdown: 1, touchstart: 1 }, // map of events that should fire global mouseup even if stopped mouseupEvents: { mouseup: 1, pointerup: 1, touchend: 1 }, /** * Cancels bubbling of the event. * @chainable */ stopPropagation: function() { var me = this, browserEvent = me.browserEvent, parentEvent = me.parentEvent; // Fire the "unstoppable" global mousedown event // (used for menu hiding, etc) if (me.mousedownEvents[me.type]) { Ext.GlobalEvents.fireMouseDown(me); } // Fire the "unstoppable" global mouseup event // (used for component unpressing, etc) if (me.mouseupEvents[me.type]) { Ext.GlobalEvents.fireMouseUp(me); } // Set stopped for delegated event listeners. Dom publisher will check this // property during its emulated propagation phase (see doPublish) me.stopped = true; // if the event was created by prototype-chaining a new object to an existing event // instance, we need to make sure the parent event is stopped. This feature most // likely comes into play when dealing with event translation. For example on touch // browsers addListener('mousedown') actually attaches a 'touchstart' listener behind // the scenes. When the 'touchstart' event is dispatched, the event system will // create a "chained" copy of the event object before correcting its type back to // 'mousedown' and calling the handler. When propagating the event we look at the // original event, not the chained one to determine if propagation should continue, // so the stopped property must be set on the parentEvent or stopPropagation // will not work. if (parentEvent && !me.isGesture) { parentEvent.stopped = true; } //<feature legacyBrowser> if (!browserEvent.stopPropagation) { // IE < 10 does not have stopPropagation() browserEvent.cancelBubble = true; return me; } //</feature> // For non-delegated event listeners (those that are directly attached to the // DOM element) we need to call the browserEvent's stopPropagation() method. browserEvent.stopPropagation(); return me; }, /** * Claims this event as the currently active gesture. Once a gesture is claimed * no other gestures will fire events until after the current gesture has completed. * For example, if `claimGesture()` is invoked on a dragstart or drag event, no * swipestart or swipe events will be fired until the drag gesture completes, even if * the gesture also meets the required duration and distance requirements to be recognized * as a swipe. * * If `claimGesture()` is invoked on a mouse, touch, or pointer event, it will disable * all gesture events until termination of the current gesture is indicated by a * mouseup, touchend, or pointerup event. * * @return {Ext.event.Event} */ claimGesture: function() { var me = this, parentEvent = me.parentEvent; me.claimed = true; if (parentEvent && !me.isGesture) { parentEvent.claimGesture(); } else { // Claiming a gesture should also prevent default browser actions like pan/zoom // if possible (only works on browsers that support touch events - browsers that // use pointer events must declare a CSS touch-action on elements to prevent the // default touch action from occurring. me.preventDefault(); } return me; }, /** * Returns true if the target of this event is a child of `el`. If the allowEl * parameter is set to false, it will return false if the target is `el`. * Example usage: * * // Handle click on any child of an element * Ext.getBody().on('click', function(e){ * if(e.within('some-el')){ * alert('Clicked on a child of some-el!'); * } * }); * * // Handle click directly on an element, ignoring clicks on child nodes * Ext.getBody().on('click', function(e,t){ * if((t.id == 'some-el') && !e.within(t, true)){ * alert('Clicked directly on some-el!'); * } * }); * * @param {String/HTMLElement/Ext.dom.Element} el The id, DOM element or Ext.Element to check * @param {Boolean} [related] `true` to test if the related target is within el instead * of the target * @param {Boolean} [allowEl=true] `true` to allow the target to be considered "within" itself. * `false` to only allow child elements. * @return {Boolean} */ within: function(el, related, allowEl) { var t; if (el) { t = related ? this.getRelatedTarget() : this.getTarget(); } if (!t || (allowEl === false && t === Ext.getDom(el))) { return false; } return Ext.fly(el).contains(t); }, privates: { ieMimeType: { "text/plain": 'Text' } }, deprecated: { '4.0': { methods: { /** * @method getPageX * Gets the x coordinate of the event. * @return {Number} * @deprecated 4.0 use {@link #getX} instead * @member Ext.event.Event */ getPageX: 'getX', /** * @method getPageY * Gets the y coordinate of the event. * @return {Number} * @deprecated 4.0 use {@link #getY} instead * @member Ext.event.Event */ getPageY: 'getY' } } }}, function(Event) { var constants = { /** Key constant @type Number */ BACKSPACE: 8, /** Key constant @type Number */ TAB: 9, /** Key constant @type Number */ NUM_CENTER: 12, /** Key constant @type Number */ ENTER: 13, /** Key constant @type Number */ RETURN: 13, /** Key constant @type Number */ SHIFT: 16, /** Key constant @type Number */ CTRL: 17, /** Key constant @type Number */ ALT: 18, /** Key constant @type Number */ PAUSE: 19, /** Key constant @type Number */ CAPS_LOCK: 20, /** Key constant @type Number */ ESC: 27, /** Key constant @type Number */ SPACE: 32, /** Key constant @type Number */ PAGE_UP: 33, /** Key constant @type Number */ PAGE_DOWN: 34, /** Key constant @type Number */ END: 35, /** Key constant @type Number */ HOME: 36, /** Key constant @type Number */ LEFT: 37, /** Key constant @type Number */ UP: 38, /** Key constant @type Number */ RIGHT: 39, /** Key constant @type Number */ DOWN: 40, /** Key constant @type Number */ PRINT_SCREEN: 44, /** Key constant @type Number */ INSERT: 45, /** Key constant @type Number */ DELETE: 46, /** Key constant @type Number */ ZERO: 48, /** Key constant @type Number */ ONE: 49, /** Key constant @type Number */ TWO: 50, /** Key constant @type Number */ THREE: 51, /** Key constant @type Number */ FOUR: 52, /** Key constant @type Number */ FIVE: 53, /** Key constant @type Number */ SIX: 54, /** Key constant @type Number */ SEVEN: 55, /** Key constant @type Number */ EIGHT: 56, /** Key constant @type Number */ NINE: 57, /** Key constant @type Number */ A: 65, /** Key constant @type Number */ B: 66, /** Key constant @type Number */ C: 67, /** Key constant @type Number */ D: 68, /** Key constant @type Number */ E: 69, /** Key constant @type Number */ F: 70, /** Key constant @type Number */ G: 71, /** Key constant @type Number */ H: 72, /** Key constant @type Number */ I: 73, /** Key constant @type Number */ J: 74, /** Key constant @type Number */ K: 75, /** Key constant @type Number */ L: 76, /** Key constant @type Number */ M: 77, /** Key constant @type Number */ N: 78, /** Key constant @type Number */ O: 79, /** Key constant @type Number */ P: 80, /** Key constant @type Number */ Q: 81, /** Key constant @type Number */ R: 82, /** Key constant @type Number */ S: 83, /** Key constant @type Number */ T: 84, /** Key constant @type Number */ U: 85, /** Key constant @type Number */ V: 86, /** Key constant @type Number */ W: 87, /** Key constant @type Number */ X: 88, /** Key constant @type Number */ Y: 89, /** Key constant @type Number */ Z: 90, /** Key constant @type Number */ META: 91, // Command key on mac, left window key on Windows /** Key constant @type Number */ CONTEXT_MENU: 93, /** Key constant @type Number */ NUM_ZERO: 96, /** Key constant @type Number */ NUM_ONE: 97, /** Key constant @type Number */ NUM_TWO: 98, /** Key constant @type Number */ NUM_THREE: 99, /** Key constant @type Number */ NUM_FOUR: 100, /** Key constant @type Number */ NUM_FIVE: 101, /** Key constant @type Number */ NUM_SIX: 102, /** Key constant @type Number */ NUM_SEVEN: 103, /** Key constant @type Number */ NUM_EIGHT: 104, /** Key constant @type Number */ NUM_NINE: 105, /** Key constant @type Number */ NUM_MULTIPLY: 106, /** Key constant @type Number */ NUM_PLUS: 107, /** Key constant @type Number */ NUM_MINUS: 109, /** Key constant @type Number */ NUM_PERIOD: 110, /** Key constant @type Number */ NUM_DIVISION: 111, /** Key constant @type Number */ F1: 112, /** Key constant @type Number */ F2: 113, /** Key constant @type Number */ F3: 114, /** Key constant @type Number */ F4: 115, /** Key constant @type Number */ F5: 116, /** Key constant @type Number */ F6: 117, /** Key constant @type Number */ F7: 118, /** Key constant @type Number */ F8: 119, /** Key constant @type Number */ F9: 120, /** Key constant @type Number */ F10: 121, /** Key constant @type Number */ F11: 122, /** Key constant @type Number */ F12: 123, /** * @property {Number} * The mouse wheel delta scaling factor. This value depends on browser * version and OS and attempts to produce a similar scrolling experience * across all platforms and browsers. * * To change this value: * * Ext.event.Event.prototype.WHEEL_SCALE = 72; */ WHEEL_SCALE: 120 // IE, Opera and other Windows browsers use 120 }, keyCodes = {}, gestureEvents = Event.gestureEvents, prototype = Event.prototype, i, keyName, keyCode, keys, s, scale; if (Ext.isGecko) { // Firefox uses 3 on all platforms constants.WHEEL_SCALE = 3; } else if (Ext.isMac) { // Continuous scrolling devices have momentum and produce much more scroll than // discrete devices on the same OS and browser. To make things exciting, Safari // (and not Chrome) changed from small values to 120 (like IE). if (Ext.isSafari && Ext.webKitVersion >= 532.0) { // Safari changed the scrolling factor to match IE (for details see // https://bugs.webkit.org/show_bug.cgi?id=24368). The WebKit version where this // change was introduced was 532.0 // Detailed discussion: // https://bugs.webkit.org/show_bug.cgi?id=29601 // http://trac.webkit.org/browser/trunk/WebKit/chromium/src/mac/WebInputEventFactory.mm#L1063 scale = 120; } else { // MS optical wheel mouse produces multiples of 12 which is close enough // to help tame the speed of the continuous mice... scale = 12; } // Momentum scrolling produces very fast scrolling, so increase the scale factor // to help produce similar results cross platform. This could be even larger and // it would help those mice, but other mice would become almost unusable as a // result (since we cannot tell which device type is in use). constants.WHEEL_SCALE = 3 * scale; } Ext.apply(gestureEvents, Event.mouseEvents); Ext.apply(gestureEvents, Event.pointerEvents); Ext.apply(gestureEvents, Event.touchEvents); Ext.apply(Event, constants); Ext.apply(prototype, constants); // Don't need that delete constants.WHEEL_SCALE; // ENTER and RETURN has the same keyCode, but since RETURN // comes later it will win over ENTER down there. However // ENTER is used more often and feels more natural. delete constants.RETURN; // We need this to do reverse lookup of key name by its code for (keyName in constants) { keyCode = constants[keyName]; keyCodes[keyCode] = keyName; } Event.keyCodes = prototype.keyCodes = keyCodes; // Classic Event override will install this handler in IE9- if (!Ext.isIE9m) { document.addEventListener('keydown', Event.globalTabKeyDown, true); document.addEventListener('keyup', Event.globalTabKeyUp, true); } /** * @member Ext.event.Event * @private * Returns the X and Y coordinates of this event without regard to any RTL * direction settings. */ prototype.getTrueXY = prototype.getXY; if (typeof KeyboardEvent !== 'undefined' && !('key' in KeyboardEvent.prototype)) { prototype._keys = keys = { 3: 'Cancel', 6: 'Help', 8: 'Backspace', 9: 'Tab', 12: 'Clear', 13: 'Enter', 16: 'Shift', 17: 'Control', 18: 'Alt', 19: 'Pause', 20: 'CapsLock', 27: 'Escape', 28: 'Convert', 29: 'NonConvert', 30: 'Accept', 31: 'ModeChange', 32: ' ', 33: 'PageUp', 34: 'PageDown', 35: 'End', 36: 'Home', 37: 'ArrowLeft', 38: 'ArrowUp', 39: 'ArrowRight', 40: 'ArrowDown', 41: 'Select', 42: 'Print', 43: 'Execute', 44: 'PrintScreen', 45: 'Insert', 46: 'Delete', 48: ['0', ')'], 49: ['1', '!'], 50: ['2', '@'], 51: ['3', '#'], 52: ['4', '$'], 53: ['5', '%'], 54: ['6', '^'], 55: ['7', '&'], 56: ['8', '*'], 57: ['9', '('], 91: 'OS', 93: 'ContextMenu', 144: 'NumLock', 145: 'ScrollLock', 181: 'VolumeMute', 182: 'VolumeDown', 183: 'VolumeUp', 186: [';', ':'], 187: ['=', '+'], 188: [',', '<'], 189: ['-', '_'], 190: ['.', '>'], 191: ['/', '?'], 192: ['`', '~'], 219: ['[', '{'], 220: ['\\', '|'], 221: [']', '}'], 222: ["'", '"'], 224: 'Meta', 225: 'AltGraph', 246: 'Attn', 247: 'CrSel', 248: 'ExSel', 249: 'EraseEof', 250: 'Play', 251: 'ZoomOut' }; for (i = 1; i < 25; ++i) { keys[i + 111] = 'F' + i; // F1 - F24 } for (i = 0; i < 26; ++i) { // a-z, A-Z keys[i] = [String.fromCharCode(i + 97), String.fromCharCode(i + 65)]; } prototype.key = function () { var k = keys[this.browserEvent.which || this.keyCode]; if (k && typeof k !== 'string') { k = k[+this.shiftKey]; } return k; }; }});