@qooxdoo/framework
Version:
The JS Framework for Coders
283 lines (253 loc) • 9.37 kB
JavaScript
/* ************************************************************************
qooxdoo - the new era of web development
http://qooxdoo.org
Copyright:
2004-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:
* Sebastian Werner (wpbasti)
************************************************************************ */
/**
* This class is mainly a convenience wrapper for DOM elements to
* qooxdoo's event system.
*
* @require(qx.event.dispatch.Direct)
* @require(qx.event.dispatch.DomBubbling)
* @require(qx.event.handler.Keyboard)
* @require(qx.event.handler.Mouse)
* @require(qx.event.handler.Element)
* @require(qx.event.handler.Appear)
* @require(qx.event.handler.Touch)
* @require(qx.event.handler.Offline)
* @require(qx.event.handler.Input)
* @require(qx.event.handler.Pointer)
* @require(qx.event.handler.Gesture)
* @require(qx.event.handler.Video)
*/
qx.Class.define("qx.bom.Element", {
/*
*****************************************************************************
STATICS
*****************************************************************************
*/
statics: {
/*
---------------------------------------------------------------------------
EVENTS
---------------------------------------------------------------------------
*/
/**
* Add an event listener to a DOM element. The event listener is passed an
* instance of {@link Event} containing all relevant information
* about the event as parameter.
*
* @param element {Element} DOM element to attach the event on.
* @param type {String} Name of the event e.g. "click", "keydown", ...
* @param listener {Function} Event listener function
* @param self {Object ? null} Reference to the 'this' variable inside
* the event listener. When not given, the corresponding dispatcher
* usually falls back to a default, which is the target
* by convention. Note this is not a strict requirement, i.e.
* custom dispatchers can follow a different strategy.
* @param capture {Boolean} Whether to attach the event to the
* capturing phase or the bubbling phase of the event. The default is
* to attach the event handler to the bubbling phase.
* @return {String} An opaque id, which can be used to remove the event listener
* using the {@link #removeListenerById} method.
*/
addListener(element, type, listener, self, capture) {
return qx.event.Registration.addListener(
element,
type,
listener,
self,
capture
);
},
/**
* Remove an event listener from a from DOM node.
*
* Note: All registered event listeners will automatically be removed from
* the DOM at page unload so it is not necessary to detach events yourself.
*
* @param element {Element} DOM Element
* @param type {String} Name of the event
* @param listener {Function} The pointer to the event listener
* @param self {Object ? null} Reference to the 'this' variable inside
* the event listener.
* @param capture {Boolean} Whether to remove the event listener of
* the bubbling or of the capturing phase.
* @return {Boolean} <code>true</code> if the listener was removed
*/
removeListener(element, type, listener, self, capture) {
return qx.event.Registration.removeListener(
element,
type,
listener,
self,
capture
);
},
/**
* Removes an event listener from an event target by an id returned by
* {@link #addListener}
*
* @param target {Object} The event target
* @param id {String} The id returned by {@link #addListener}
* @return {Boolean} <code>true</code> if the listener was removed
*/
removeListenerById(target, id) {
return qx.event.Registration.removeListenerById(target, id);
},
/**
* Check whether there are one or more listeners for an event type
* registered at the element.
*
* @param element {Element} DOM element
* @param type {String} The event type
* @param capture {Boolean ? false} Whether to check for listeners of
* the bubbling or of the capturing phase.
* @return {Boolean} Whether the element has event listeners of the given type.
*/
hasListener(element, type, capture) {
return qx.event.Registration.hasListener(element, type, capture);
},
/**
* Focuses the given element. The element needs to have a positive <code>tabIndex</code> value.
*
* @param element {Element} DOM element to focus
*/
focus(element) {
qx.event.Registration.getManager(element)
.getHandler(qx.event.handler.Focus)
.focus(element);
},
/**
* Blurs the given element
*
* @param element {Element} DOM element to blur
*/
blur(element) {
qx.event.Registration.getManager(element)
.getHandler(qx.event.handler.Focus)
.blur(element);
},
/**
* Activates the given element. The active element receives all key board events.
*
* @param element {Element} DOM element to focus
*/
activate(element) {
qx.event.Registration.getManager(element)
.getHandler(qx.event.handler.Focus)
.activate(element);
},
/**
* Deactivates the given element. The active element receives all key board events.
*
* @param element {Element} DOM element to focus
*/
deactivate(element) {
qx.event.Registration.getManager(element)
.getHandler(qx.event.handler.Focus)
.deactivate(element);
},
/**
* Captures the given element
*
* @param element {Element} DOM element to capture
* @param containerCapture {Boolean?true} If true all events originating in
* the container are captured. If false events originating in the container
* are not captured.
*/
capture(element, containerCapture) {
qx.event.Registration.getManager(element)
.getDispatcher(qx.event.dispatch.MouseCapture)
.activateCapture(element, containerCapture);
},
/**
* Releases the given element (from a previous {@link #capture} call)
*
* @param element {Element} DOM element to release
*/
releaseCapture(element) {
qx.event.Registration.getManager(element)
.getDispatcher(qx.event.dispatch.MouseCapture)
.releaseCapture(element);
},
/*
---------------------------------------------------------------------------
UTILS
---------------------------------------------------------------------------
*/
/**
* Clone given DOM element. May optionally clone all attached
* events (recursively) as well.
*
* @param element {Element} Element to clone
* @param events {Boolean?false} Whether events should be copied as well
* @return {Element} The copied element
*/
clone(element, events) {
var clone;
if (
events ||
(qx.core.Environment.get("engine.name") == "mshtml" &&
!qx.xml.Document.isXmlDocument(element))
) {
var mgr = qx.event.Registration.getManager(element);
var all = qx.dom.Hierarchy.getDescendants(element);
all.push(element);
}
// IE copies events bound via attachEvent() when
// using cloneNode(). Calling detachEvent() on the
// clone will also remove the events from the original.
//
// In order to get around this, we detach all locally
// attached events first, do the cloning and recover
// them afterwards again.
if (qx.core.Environment.get("engine.name") == "mshtml") {
for (var i = 0, l = all.length; i < l; i++) {
mgr.toggleAttachedEvents(all[i], false);
}
}
// Do the native cloning
var clone = element.cloneNode(true);
// Recover events on original elements
if (qx.core.Environment.get("engine.name") == "mshtml") {
for (var i = 0, l = all.length; i < l; i++) {
mgr.toggleAttachedEvents(all[i], true);
}
}
// Attach events from original element
if (events === true) {
// Produce recursive list of elements in the clone
var cloneAll = qx.dom.Hierarchy.getDescendants(clone);
cloneAll.push(clone);
// Process all elements and copy over listeners
var eventList, cloneElem, origElem, eventEntry;
for (var i = 0, il = all.length; i < il; i++) {
origElem = all[i];
eventList = mgr.serializeListeners(origElem);
if (eventList.length > 0) {
cloneElem = cloneAll[i];
for (var j = 0, jl = eventList.length; j < jl; j++) {
eventEntry = eventList[j];
mgr.addListener(
cloneElem,
eventEntry.type,
eventEntry.handler,
eventEntry.self,
eventEntry.capture
);
}
}
}
}
// Finally return the clone
return clone;
}
}
});