@qooxdoo/framework
Version:
The JS Framework for Coders
268 lines (228 loc) • 9.18 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)
*/
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 : function(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 : function(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 : function(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 : function(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 : function(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 : function(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 : function(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 : function(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 : function(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 : function(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 : function(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;
}
}
});