devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
235 lines (181 loc) • 6.91 kB
JavaScript
"use strict";
var $ = require("../../core/renderer"),
eventsEngine = require("../../events/core/events_engine"),
devices = require("../../core/devices"),
styleUtils = require("../../core/utils/style"),
callOnce = require("../../core/utils/call_once"),
browser = require("../../core/utils/browser"),
domUtils = require("../../core/utils/dom"),
readyCallbacks = require("../../core/utils/ready_callbacks"),
ready = readyCallbacks.add,
mathUtils = require("../../core/utils/math"),
noop = require("../../core/utils/common").noop,
isDefined = require("../../core/utils/type").isDefined,
eventUtils = require("../utils"),
Emitter = require("../core/emitter"),
sign = mathUtils.sign,
abs = Math.abs;
var SLEEP = 0,
INITED = 1,
STARTED = 2,
TOUCH_BOUNDARY = 10,
IMMEDIATE_TOUCH_BOUNDARY = 0,
IMMEDIATE_TIMEOUT = 180;
var isMouseWheelEvent = function isMouseWheelEvent(e) {
return e && e.type === "dxmousewheel";
};
var supportPointerEvents = function supportPointerEvents() {
var cssSupport = styleUtils.styleProp("pointer-events");
var msieLess11 = browser.msie && parseInt(browser.version, 10) < 11;
return cssSupport && !msieLess11;
};
var setGestureCover = callOnce(function () {
var GESTURE_COVER_CLASS = "dx-gesture-cover";
var isDesktop = devices.real().platform === "generic";
if (!supportPointerEvents() || !isDesktop) {
return noop;
}
var $cover = $("<div>").addClass(GESTURE_COVER_CLASS).css("pointerEvents", "none");
eventsEngine.subscribeGlobal($cover, "dxmousewheel", function (e) {
e.preventDefault();
});
ready(function () {
$cover.appendTo("body");
});
return function (toggle, cursor) {
$cover.css("pointerEvents", toggle ? "all" : "none");
toggle && $cover.css("cursor", cursor);
};
});
var gestureCover = function gestureCover(toggle, cursor) {
var gestureCoverStrategy = setGestureCover();
gestureCoverStrategy(toggle, cursor);
};
var GestureEmitter = Emitter.inherit({
gesture: true,
configure: function configure(data) {
this.getElement().css("msTouchAction", data.immediate ? "pinch-zoom" : "");
this.callBase(data);
},
allowInterruptionByMouseWheel: function allowInterruptionByMouseWheel() {
return this._stage !== STARTED;
},
getDirection: function getDirection() {
return this.direction;
},
_cancel: function _cancel() {
this.callBase.apply(this, arguments);
this._toggleGestureCover(false);
this._stage = SLEEP;
},
start: function start(e) {
if (eventUtils.needSkipEvent(e)) {
this._cancel(e);
return;
}
this._startEvent = eventUtils.createEvent(e);
this._startEventData = eventUtils.eventData(e);
this._stage = INITED;
this._init(e);
this._setupImmediateTimer();
},
_setupImmediateTimer: function _setupImmediateTimer() {
clearTimeout(this._immediateTimer);
this._immediateAccepted = false;
if (!this.immediate) {
return;
}
this._immediateTimer = setTimeout(function () {
this._immediateAccepted = true;
}.bind(this), IMMEDIATE_TIMEOUT);
},
move: function move(e) {
if (this._stage === INITED && this._directionConfirmed(e)) {
this._stage = STARTED;
this._resetActiveElement();
this._toggleGestureCover(true);
this._clearSelection(e);
this._adjustStartEvent(e);
this._start(this._startEvent);
if (this._stage === SLEEP) {
return;
}
this._requestAccept(e);
this._move(e);
this._forgetAccept();
} else if (this._stage === STARTED) {
this._clearSelection(e);
this._move(e);
}
},
_directionConfirmed: function _directionConfirmed(e) {
var touchBoundary = this._getTouchBoundary(e),
delta = eventUtils.eventDelta(this._startEventData, eventUtils.eventData(e)),
deltaX = abs(delta.x),
deltaY = abs(delta.y);
var horizontalMove = this._validateMove(touchBoundary, deltaX, deltaY),
verticalMove = this._validateMove(touchBoundary, deltaY, deltaX);
var direction = this.getDirection(e),
bothAccepted = direction === "both" && (horizontalMove || verticalMove),
horizontalAccepted = direction === "horizontal" && horizontalMove,
verticalAccepted = direction === "vertical" && verticalMove;
return bothAccepted || horizontalAccepted || verticalAccepted || this._immediateAccepted;
},
_validateMove: function _validateMove(touchBoundary, mainAxis, crossAxis) {
return mainAxis && mainAxis >= touchBoundary && (this.immediate ? mainAxis >= crossAxis : true);
},
_getTouchBoundary: function _getTouchBoundary(e) {
return this.immediate || isMouseWheelEvent(e) ? IMMEDIATE_TOUCH_BOUNDARY : TOUCH_BOUNDARY;
},
_adjustStartEvent: function _adjustStartEvent(e) {
var touchBoundary = this._getTouchBoundary(e),
delta = eventUtils.eventDelta(this._startEventData, eventUtils.eventData(e));
this._startEvent.pageX += sign(delta.x) * touchBoundary;
this._startEvent.pageY += sign(delta.y) * touchBoundary;
},
_resetActiveElement: function _resetActiveElement() {
if (devices.real().platform === "ios" && this.getElement().find(":focus").length) {
domUtils.resetActiveElement();
}
},
_toggleGestureCover: function _toggleGestureCover(toggle) {
var isStarted = this._stage === STARTED;
if (isStarted) {
gestureCover(toggle, this.getElement().css("cursor"));
}
},
_clearSelection: function _clearSelection(e) {
if (isMouseWheelEvent(e) || eventUtils.isTouchEvent(e)) {
return;
}
domUtils.clearSelection();
},
end: function end(e) {
this._toggleGestureCover(false);
if (this._stage === STARTED) {
this._end(e);
} else if (this._stage === INITED) {
this._stop(e);
}
this._stage = SLEEP;
},
dispose: function dispose() {
clearTimeout(this._immediateTimer);
this.callBase.apply(this, arguments);
this._toggleGestureCover(false);
},
_init: noop,
_start: noop,
_move: noop,
_stop: noop,
_end: noop
});
GestureEmitter.initialTouchBoundary = TOUCH_BOUNDARY;
GestureEmitter.touchBoundary = function (newBoundary) {
if (isDefined(newBoundary)) {
TOUCH_BOUNDARY = newBoundary;
return;
}
return TOUCH_BOUNDARY;
};
module.exports = GestureEmitter;