/framework/source/class/qx/bom/Event.js
JavaScript | 364 lines | 166 code | 30 blank | 168 comment | 54 complexity | 4dc3c604edaf9d590948cf1f6a76caf5 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, LGPL-3.0, MIT
- /* ************************************************************************
- qooxdoo - the new era of web development
- http://qooxdoo.org
- Copyright:
- 2007-2008 1&1 Internet AG, Germany, http://www.1und1.de
- License:
- MIT: https://opensource.org/licenses/MIT
- See the LICENSE file in the project's top-level directory for details.
- Authors:
- * Fabian Jakobs (fjakobs)
- * Sebastian Werner (wpbasti)
- * Alexander Steitz (aback)
- * Christian Hagendorn (chris_schmidt)
- * Tobias Oberrauch (toberrauch) <tobias.oberrauch@1und1.de>
- ======================================================================
- This class contains code based on the following work:
- * Juriy Zaytsev
- http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
- Copyright (c) 2009 Juriy Zaytsev
- License:
- BSD: http://github.com/kangax/iseventsupported/blob/master/LICENSE
- ----------------------------------------------------------------------
- http://github.com/kangax/iseventsupported/blob/master/LICENSE
- Copyright (c) 2009 Juriy Zaytsev
- Permission is hereby granted, free of charge, to any person
- obtaining a copy of this software and associated documentation
- files (the "Software"), to deal in the Software without
- restriction, including without limitation the rights to use,
- copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the
- Software is furnished to do so, subject to the following
- conditions:
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
- ************************************************************************ */
- /**
- * Wrapper around native event management capabilities of the browser.
- * This class should not be used directly normally. It's better
- * to use {@link qx.event.Registration} instead.
- */
- qx.Bootstrap.define("qx.bom.Event",
- {
- statics :
- {
- /**
- * Use the low level browser functionality to attach event listeners
- * to DOM nodes.
- *
- * Use this with caution. This is only thought for event handlers and
- * qualified developers. These are not mem-leak protected!
- *
- * @param target {Object} Any valid native event target
- * @param type {String} Name of the event
- * @param listener {Function} The pointer to the function to assign
- * @param useCapture {Boolean ? false} A Boolean value that specifies the event phase to add
- * the event handler for the capturing phase or the bubbling phase.
- * @param passive {Boolean ? false} Specifies whether to set the passive option to true or false if supported.
- */
- addNativeListener : function(target, type, listener, useCapture, passive)
- {
- if (target.addEventListener) {
- if (passive === undefined || !qx.core.Environment.get("event.passive")) {
- target.addEventListener(type, listener, !!useCapture);
- } else {
- target.addEventListener(type, listener, { capture: !!useCapture, passive: !!passive });
- }
- } else if (target.attachEvent) {
- target.attachEvent("on" + type, listener);
- } else if (typeof target["on" + type] != "undefined") {
- target["on" + type] = listener;
- } else {
- if (qx.core.Environment.get("qx.debug")) {
- qx.log.Logger.warn("No method available to add native listener to " + target);
- }
- }
- },
- /**
- * Use the low level browser functionality to remove event listeners
- * from DOM nodes.
- *
- * @param target {Object} Any valid native event target
- * @param type {String} Name of the event
- * @param listener {Function} The pointer to the function to assign
- * @param useCapture {Boolean ? false} A Boolean value that specifies the event phase to remove
- * the event handler for the capturing phase or the bubbling phase.
- */
- removeNativeListener : function(target, type, listener, useCapture)
- {
- if (target.removeEventListener)
- {
- target.removeEventListener(type, listener, !!useCapture);
- }
- else if (target.detachEvent)
- {
- try {
- target.detachEvent("on" + type, listener);
- }
- catch(e)
- {
- // IE7 sometimes dispatches "unload" events on protected windows
- // Ignore the "permission denied" errors.
- if(e.number !== -2146828218) {
- throw e;
- };
- }
- }
- else if (typeof target["on" + type] != "undefined")
- {
- target["on" + type] = null;
- }
- else
- {
- if (qx.core.Environment.get("qx.debug")) {
- qx.log.Logger.warn("No method available to remove native listener from " + target);
- }
- }
- },
- /**
- * Returns the target of the event.
- *
- * @param e {Event} Native event object
- * @return {Object} Any valid native event target
- */
- getTarget : function(e) {
- return e.target || e.srcElement;
- },
- /**
- * Computes the related target from the native DOM event
- *
- * @param e {Event} Native DOM event object
- * @return {Element} The related target
- */
- getRelatedTarget : function(e)
- {
- if (e.relatedTarget !== undefined)
- {
- // In Firefox the related target of mouse events is sometimes an
- // anonymous div inside of a text area, which raises an exception if
- // the nodeType is read. This is why the try/catch block is needed.
- if ((qx.core.Environment.get("engine.name") == "gecko"))
- {
- try {
- e.relatedTarget && e.relatedTarget.nodeType;
- } catch (ex) {
- return null;
- }
- }
- return e.relatedTarget;
- }
- else if (e.fromElement !== undefined &&
- (e.type === "mouseover" || e.type === "pointerover"))
- {
- return e.fromElement;
- } else if (e.toElement !== undefined) {
- return e.toElement;
- } else {
- return null;
- }
- },
- /**
- * Prevent the native default of the event to be processed.
- *
- * This is useful to stop native keybindings, native selection
- * and other native functionality behind events.
- *
- * @param e {Event} Native event object
- */
- preventDefault : function(e)
- {
- if (e.preventDefault) {
- e.preventDefault();
- }
- else {
- try {
- // this allows us to prevent some key press events in IE.
- // See bug #1049
- e.keyCode = 0;
- } catch(ex) {}
- e.returnValue = false;
- }
- },
- /**
- * Stops the propagation of the given event to the parent element.
- *
- * Only useful for events which bubble e.g. mousedown.
- *
- * @param e {Event} Native event object
- */
- stopPropagation : function(e)
- {
- if (e.stopPropagation) {
- e.stopPropagation();
- } else {
- e.cancelBubble = true;
- }
- },
- /**
- * Fires a synthetic native event on the given element.
- *
- * @param target {Element} DOM element to fire event on
- * @param type {String} Name of the event to fire
- * @return {Boolean} A value that indicates whether any of the event handlers called {@link #preventDefault}.
- * <code>true</code> The default action is permitted, <code>false</code> the caller should prevent the default action.
- */
- fire : function(target, type)
- {
- // dispatch for standard first
- if (document.createEvent)
- {
- var evt = document.createEvent("HTMLEvents");
- evt.initEvent(type, true, true);
- return !target.dispatchEvent(evt);
- }
- // dispatch for IE
- else
- {
- var evt = document.createEventObject();
- return target.fireEvent("on" + type, evt);
- }
- },
- /**
- * Whether the given target supports the given event type.
- *
- * Useful for testing for support of new features like
- * touch events, gesture events, orientation change, on/offline, etc.
- *
- * *NOTE:* This check is *case-insensitive*.
- * <code>supportsEvent(window, "cLicK")</code> will return <code>true</code>
- * but <code>window.addEventListener("cLicK", callback)</code> will fail
- * silently!
- *
- * @param target {var} Any valid target e.g. window, dom node, etc.
- * @param type {String} Type of the event e.g. click, mousedown
- * @return {Boolean} Whether the given event is supported
- */
- supportsEvent : function(target, type)
- {
- var browserName = qx.core.Environment.get("browser.name");
- var engineName = qx.core.Environment.get("engine.name");
- // transitionEnd support can not be detected generically for Internet Explorer 10+ [BUG #7875]
- if (type.toLowerCase().indexOf("transitionend") != -1
- && engineName === "mshtml"
- && qx.core.Environment.get("browser.documentmode") > 9)
- {
- return true;
- }
- /**
- * add exception for safari mobile ()
- * @see http://bugzilla.qooxdoo.org/show_bug.cgi?id=8244
- */
- var safariBrowserNames = ["mobile safari", "safari"];
- if (
- engineName === "webkit" &&
- safariBrowserNames.indexOf(browserName) > -1
- ) {
- var supportedEvents = [
- 'loadeddata', 'progress', 'timeupdate', 'seeked', 'canplay', 'play',
- 'playing', 'pause', 'loadedmetadata', 'ended', 'volumechange'
- ];
- if (supportedEvents.indexOf(type.toLowerCase()) > -1) {
- return true;
- }
- }
- // The 'transitionend' event can only be detected on window objects,
- // not DOM elements [BUG #7249]
- if (target != window && type.toLowerCase().indexOf("transitionend") != -1) {
- var transitionSupport = qx.core.Environment.get("css.transition");
- return (transitionSupport && transitionSupport["end-event"] == type);
- }
- // Using the lowercase representation is important for the
- // detection of events like 'MSPointer*'. They have to detected
- // using the lower case name of the event.
- var eventName = "on" + type.toLowerCase();
- var supportsEvent = (eventName in target);
- if (!supportsEvent)
- {
- supportsEvent = typeof target[eventName] == "function";
- if (!supportsEvent && target.setAttribute)
- {
- target.setAttribute(eventName, "return;");
- supportsEvent = typeof target[eventName] == "function";
- target.removeAttribute(eventName);
- }
- }
- return supportsEvent;
- },
- /**
- * Returns the (possibly vendor-prefixed) name of the given event type.
- * *NOTE:* Incorrect capitalization of type names will *not* be corrected. See
- * {@link #supportsEvent} for details.
- *
- * @param target {var} Any valid target e.g. window, dom node, etc.
- * @param type {String} Type of the event e.g. click, mousedown
- * @return {String|null} Event name or <code>null</code> if the event is not
- * supported.
- */
- getEventName : function(target, type)
- {
- var pref = [""].concat(qx.bom.Style.VENDOR_PREFIXES);
- for (var i=0, l=pref.length; i<l; i++) {
- var prefix = pref[i].toLowerCase();
- if (qx.bom.Event.supportsEvent(target, prefix + type)) {
- return prefix ? prefix + qx.lang.String.firstUp(type) : type;
- }
- }
- return null;
- }
- }
- });