@qooxdoo/framework
Version:
The JS Framework for Coders
400 lines (317 loc) • 10.7 kB
JavaScript
/* ************************************************************************
qooxdoo - the new era of web development
http://qooxdoo.org
Copyright:
2004-2011 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:
* Tino Butz (tbtz)
************************************************************************ */
/**
* Connects the widgets to the browser DOM events.
*
* @require(qx.event.handler.Touch)
* @require(qx.event.handler.Pointer)
* @require(qx.event.dispatch.DomBubbling)
* @require(qx.ui.mobile.core.Widget)
*/
qx.Class.define("qx.ui.mobile.core.EventHandler",
{
extend : qx.core.Object,
implement : qx.event.IEventHandler,
/*
*****************************************************************************
CONSTRUCTOR
*****************************************************************************
*/
construct : function()
{
this.base(arguments);
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,
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,
// resize event
// resize : 1,
// drag drop events
dragstart : 1,
dragend : 1,
dragover : 1,
dragleave : 1,
drop : 1,
drag : 1,
dragchange : 1,
droprequest : 1,
// scroll events
roll : 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,
// 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,
__activeTarget : null,
__scrollLeft : null,
__scrollTop : null,
__startY : null,
__timer : null,
/**
* Event handler. Called when the pointerdown event occurs.
* Sets the <code>active</class> class to the event target after a certain
* time.
*
* @param domEvent {qx.event.type.Pointer} The pointerdown event
*/
__onPointerDown : function(domEvent)
{
if (!domEvent.isPrimary()) {
return;
}
var EventHandler = qx.ui.mobile.core.EventHandler;
EventHandler.__scrollLeft = qx.bom.Viewport.getScrollLeft();
EventHandler.__scrollTop = qx.bom.Viewport.getScrollTop();
EventHandler.__startY = domEvent.getScreenTop();
EventHandler.__cancelActiveStateTimer();
var target = domEvent.getTarget();
while (target && target.parentNode && target.parentNode.nodeType == 1 && qx.bom.element.Attribute.get(target, "data-activatable") != "true") {
target = target.parentNode;
}
EventHandler.__activeTarget = target;
EventHandler.___timer = window.setTimeout(function()
{
EventHandler.___timer = null;
var target = EventHandler.__activeTarget;
if (target && (qx.bom.element.Attribute.get(target, "data-selectable") != "false")) {
qx.bom.element.Class.add(target, "active");
}
},100);
},
/**
* Event handler. Called when the pointerup event occurs.
* Removes the <code>active</class> class from the event target.
*
* @param domEvent {qx.event.type.Pointer} The pointerup event
*/
__onPointerUp : function(domEvent)
{
qx.ui.mobile.core.EventHandler.__removeActiveState();
},
/**
* Event handler. Called when the pointermove event occurs.
* Removes the <code>active</class> class from the event target
* when the viewport was scrolled.
*
* @param domEvent {qx.event.type.Pointer} The pointermove event
*/
__onPointerMove : function(domEvent)
{
if (!domEvent.isPrimary()) {
return;
}
var EventHandler = qx.ui.mobile.core.EventHandler;
var deltaY = domEvent.getScreenTop() - EventHandler.__startY;
if (EventHandler.__activeTarget && Math.abs(deltaY) >=
qx.event.handler.GestureCore.TAP_MAX_DISTANCE[domEvent.getPointerType()])
{
EventHandler.__removeActiveState();
}
if (EventHandler.__activeTarget
&& (EventHandler.__scrollLeft != qx.bom.Viewport.getScrollLeft()
|| EventHandler.__scrollTop != qx.bom.Viewport.getScrollTop())) {
EventHandler.__removeActiveState();
}
},
/**
* Cancels the active state timer.
*/
__cancelActiveStateTimer : function()
{
var EventHandler = qx.ui.mobile.core.EventHandler;
if (EventHandler.___timer) {
window.clearTimeout(EventHandler.___timer);
EventHandler.___timer = null;
}
},
/**
* Removes the <code>active</class> class from the active target.
*/
__removeActiveState : function()
{
var EventHandler = qx.ui.mobile.core.EventHandler;
EventHandler.__cancelActiveStateTimer();
var activeTarget = EventHandler.__activeTarget;
if (activeTarget) {
qx.bom.element.Class.remove(activeTarget, "active");
}
EventHandler.__activeTarget = null;
}
},
/*
*****************************************************************************
MEMBERS
*****************************************************************************
*/
members :
{
__manager : null,
// interface implementation
canHandleEvent : function(target, type) {
return target instanceof qx.ui.mobile.core.Widget;
},
// interface implementation
registerEvent : function(target, type, capture)
{
var element = target.getContainerElement();
qx.event.Registration.addListener(element, type, this._dispatchEvent, this, capture);
},
// interface implementation
unregisterEvent : function(target, type, capture)
{
var element = target.getContainerElement();
qx.event.Registration.removeListener(element, type, this._dispatchEvent, this, capture);
},
/**
* Dispatches a DOM event on a widget.
*
* @param domEvent {qx.event.type.Event} The event object to dispatch.
*/
_dispatchEvent: function(domEvent){
// EVENT TARGET
var domTarget = domEvent.getTarget();
if (!domTarget || domTarget.id == null) {
return;
}
var widgetTarget = qx.ui.mobile.core.Widget.getWidgetById(domTarget.id);
// EVENT RELATED TARGET
if (domEvent.getRelatedTarget) {
var domRelatedTarget = domEvent.getRelatedTarget();
if (domRelatedTarget && domRelatedTarget.id) {
var widgetRelatedTarget = qx.ui.mobile.core.Widget.getWidgetById(domRelatedTarget.id);
}
}
// EVENT CURRENT TARGET
var currentTarget = domEvent.getCurrentTarget();
var currentWidget = qx.ui.mobile.core.Widget.getWidgetById(currentTarget.id);
if (!currentWidget) {
return;
}
// PROCESS LISTENERS
// Load listeners
var capture = domEvent.getEventPhase() == qx.event.type.Event.CAPTURING_PHASE;
var type = domEvent.getType();
var listeners = this.__manager.getListeners(currentWidget, type, capture);
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 && orig.id) {
var widgetOriginalTarget = qx.ui.mobile.core.Widget.getWidgetById(orig.id);
widgetEvent.setOriginalTarget(widgetOriginalTarget);
}
else {
widgetEvent.setOriginalTarget(domTarget);
}
// Dispatch it on all listeners
for (var i = 0, l = listeners.length; i < l; i++) {
var context = listeners[i].context || currentWidget;
listeners[i].handler.call(context, widgetEvent);
}
// Synchronize propagation stopped/prevent default property
if (widgetEvent.getPropagationStopped()) {
domEvent.stopPropagation();
}
if (widgetEvent.getDefaultPrevented()) {
domEvent.preventDefault();
}
// Release the event instance to the event pool
qx.event.Pool.getInstance().poolObject(widgetEvent);
}
},
/*
*****************************************************************************
DESTRUCTOR
*****************************************************************************
*/
destruct : function() {
this.__manager = null;
},
/*
*****************************************************************************
DEFER
*****************************************************************************
*/
defer : function(statics)
{
qx.event.Registration.addHandler(statics);
qx.event.Registration.addListener(document, "pointerdown", statics.__onPointerDown);
qx.event.Registration.addListener(document, "pointerup", statics.__onPointerUp);
qx.event.Registration.addListener(document, "pointercancel", statics.__onPointerUp);
qx.event.Registration.addListener(document, "pointermove", statics.__onPointerMove);
}
});