@qooxdoo/framework
Version:
The JS Framework for Coders
369 lines (304 loc) • 9.53 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)
* Fabian Jakobs (fjakobs)
************************************************************************ */
/**
* Connects the widgets to the browser DOM events.
*/
qx.Class.define("qx.ui.core.EventHandler", {
extend: qx.core.Object,
implement: qx.event.IEventHandler,
/*
*****************************************************************************
CONSTRUCTOR
*****************************************************************************
*/
construct() {
super();
this.__manager = qx.event.Registration.getManager(window);
},
/*
*****************************************************************************
STATICS
*****************************************************************************
*/
statics: {
/** @type {Integer} Priority of this handler */
PRIORITY: qx.event.Registration.PRIORITY_FIRST,
/** @type {Map} Supported event types. Identical to events map of qx.ui.core.Widget */
SUPPORTED_TYPES: {
// mouse events
mousemove: 1,
mouseover: 1,
mouseout: 1,
mousedown: 1,
mouseup: 1,
click: 1,
auxclick: 1,
dblclick: 1,
contextmenu: 1,
mousewheel: 1,
// key events
keyup: 1,
keydown: 1,
keypress: 1,
keyinput: 1,
// mouse capture
capture: 1,
losecapture: 1,
// focus events
focusin: 1,
focusout: 1,
focus: 1,
blur: 1,
activate: 1,
deactivate: 1,
// appear events
appear: 1,
disappear: 1,
// drag drop events
dragstart: 1,
dragend: 1,
dragover: 1,
dragleave: 1,
drop: 1,
drag: 1,
dragchange: 1,
droprequest: 1,
// touch events
touchstart: 1,
touchend: 1,
touchmove: 1,
touchcancel: 1,
// gestures
tap: 1,
longtap: 1,
swipe: 1,
dbltap: 1,
track: 1,
trackend: 1,
trackstart: 1,
pinch: 1,
rotate: 1,
roll: 1,
// pointer events
pointermove: 1,
pointerover: 1,
pointerout: 1,
pointerdown: 1,
pointerup: 1,
pointercancel: 1
},
/** @type {Integer} Whether the method "canHandleEvent" must be called */
IGNORE_CAN_HANDLE: false
},
/*
*****************************************************************************
MEMBERS
*****************************************************************************
*/
/* eslint-disable @qooxdoo/qx/no-refs-in-members */
members: {
__manager: null,
/**
* @type {Map} Supported focus event types
*
* @lint ignoreReferenceField(__focusEvents)
*/
__focusEvents: {
focusin: 1,
focusout: 1,
focus: 1,
blur: 1
},
/**
* @type {Map} Map of events which should be fired independently from being disabled
*
* @lint ignoreReferenceField(__ignoreDisabled)
*/
__ignoreDisabled: {
// mouse events
mouseover: 1,
mouseout: 1,
// appear events
appear: 1,
disappear: 1
},
// interface implementation
canHandleEvent(target, type) {
return target instanceof qx.ui.core.Widget;
},
/**
* Dispatches a DOM event on a widget.
*
* @param domEvent {qx.event.type.Event} The event object to dispatch.
*/
_dispatchEvent(domEvent) {
// EVENT TARGET
var domTarget = domEvent.getTarget();
var widgetTarget = qx.ui.core.Widget.getWidgetByElement(domTarget);
var targetChanged = false;
while (widgetTarget && widgetTarget.isAnonymous()) {
var targetChanged = true;
widgetTarget = widgetTarget.getLayoutParent();
}
// don't activate anonymous widgets!
if (widgetTarget && targetChanged && domEvent.getType() == "activate") {
widgetTarget.getContentElement().activate();
}
// Correcting target for focus events
if (this.__focusEvents[domEvent.getType()]) {
widgetTarget = widgetTarget && widgetTarget.getFocusTarget();
// Whether nothing is returned
if (!widgetTarget) {
return;
}
}
// EVENT RELATED TARGET
if (domEvent.getRelatedTarget) {
var domRelatedTarget = domEvent.getRelatedTarget();
var widgetRelatedTarget =
qx.ui.core.Widget.getWidgetByElement(domRelatedTarget);
while (widgetRelatedTarget && widgetRelatedTarget.isAnonymous()) {
widgetRelatedTarget = widgetRelatedTarget.getLayoutParent();
}
if (widgetRelatedTarget) {
// Correcting target for focus events
if (this.__focusEvents[domEvent.getType()]) {
widgetRelatedTarget = widgetRelatedTarget.getFocusTarget();
}
// If target and related target are identical ignore the event
if (widgetRelatedTarget === widgetTarget) {
return;
}
}
}
// EVENT CURRENT TARGET
var currentTarget = domEvent.getCurrentTarget();
var currentWidget = qx.ui.core.Widget.getWidgetByElement(currentTarget);
if (!currentWidget || currentWidget.isAnonymous()) {
return;
}
// Correcting target for focus events
if (this.__focusEvents[domEvent.getType()]) {
currentWidget = currentWidget.getFocusTarget();
}
// Ignore most events in the disabled state.
var type = domEvent.getType();
if (
!currentWidget ||
!(currentWidget.isEnabled() || this.__ignoreDisabled[type])
) {
return;
}
// PROCESS LISTENERS
// Load listeners
var capture =
domEvent.getEventPhase() == qx.event.type.Event.CAPTURING_PHASE;
var listeners = this.__manager.getListeners(currentWidget, type, capture);
if (domEvent.getEventPhase() == qx.event.type.Event.AT_TARGET) {
if (!listeners) {
listeners = [];
}
var otherListeners = this.__manager.getListeners(
currentWidget,
type,
!capture
);
if (otherListeners) {
listeners = listeners.concat(otherListeners);
}
}
if (!listeners || listeners.length === 0) {
return;
}
// Create cloned event with correct target
var widgetEvent = qx.event.Pool.getInstance().getObject(
domEvent.constructor
);
domEvent.clone(widgetEvent);
widgetEvent.setTarget(widgetTarget);
widgetEvent.setRelatedTarget(widgetRelatedTarget || null);
widgetEvent.setCurrentTarget(currentWidget);
// Keep original target of DOM event, otherwise map it to the original
var orig = domEvent.getOriginalTarget();
if (orig) {
var widgetOriginalTarget = qx.ui.core.Widget.getWidgetByElement(orig);
while (widgetOriginalTarget && widgetOriginalTarget.isAnonymous()) {
widgetOriginalTarget = widgetOriginalTarget.getLayoutParent();
}
widgetEvent.setOriginalTarget(widgetOriginalTarget);
} else {
widgetEvent.setOriginalTarget(domTarget);
}
// Dispatch it on all listeners
var tracker = {};
qx.event.Utils.then(tracker, function () {
return qx.event.Utils.series(listeners, function (listener) {
var context = listener.context || currentWidget;
return listener.handler.call(context, widgetEvent);
});
});
// Synchronize propagation stopped/prevent default property
qx.event.Utils.then(tracker, function () {
if (widgetEvent.getPropagationStopped()) {
domEvent.stopPropagation();
}
if (widgetEvent.getDefaultPrevented()) {
domEvent.preventDefault();
}
});
return qx.event.Utils.then(tracker, function () {
qx.event.Pool.getInstance().poolObject(widgetEvent);
});
},
// interface implementation
registerEvent(target, type, capture) {
var elem;
if (type === "focus" || type === "blur") {
elem = target.getFocusElement();
} else {
elem = target.getContentElement();
}
if (elem) {
elem.addListener(type, this._dispatchEvent, this, capture);
}
},
// interface implementation
unregisterEvent(target, type, capture) {
var elem;
if (type === "focus" || type === "blur") {
elem = target.getFocusElement();
} else {
elem = target.getContentElement();
}
if (elem) {
elem.removeListener(type, this._dispatchEvent, this, capture);
}
}
},
/*
*****************************************************************************
DESTRUCTOR
*****************************************************************************
*/
destruct() {
this.__manager = null;
},
/*
*****************************************************************************
DEFER
*****************************************************************************
*/
defer(statics) {
qx.event.Registration.addHandler(statics);
}
});