294 lines
10 KiB
JavaScript
294 lines
10 KiB
JavaScript
import { __extends } from "tslib";
|
|
import { addEventListener, removeEventListener, normalizeEvent, getNativeEvent } from '../core/event.js';
|
|
import * as zrUtil from '../core/util.js';
|
|
import Eventful from '../core/Eventful.js';
|
|
import env from '../core/env.js';
|
|
var TOUCH_CLICK_DELAY = 300;
|
|
var globalEventSupported = env.domSupported;
|
|
var localNativeListenerNames = (function () {
|
|
var mouseHandlerNames = [
|
|
'click', 'dblclick', 'mousewheel', 'wheel', 'mouseout',
|
|
'mouseup', 'mousedown', 'mousemove', 'contextmenu'
|
|
];
|
|
var touchHandlerNames = [
|
|
'touchstart', 'touchend', 'touchmove'
|
|
];
|
|
var pointerEventNameMap = {
|
|
pointerdown: 1, pointerup: 1, pointermove: 1, pointerout: 1
|
|
};
|
|
var pointerHandlerNames = zrUtil.map(mouseHandlerNames, function (name) {
|
|
var nm = name.replace('mouse', 'pointer');
|
|
return pointerEventNameMap.hasOwnProperty(nm) ? nm : name;
|
|
});
|
|
return {
|
|
mouse: mouseHandlerNames,
|
|
touch: touchHandlerNames,
|
|
pointer: pointerHandlerNames
|
|
};
|
|
})();
|
|
var globalNativeListenerNames = {
|
|
mouse: ['mousemove', 'mouseup'],
|
|
pointer: ['pointermove', 'pointerup']
|
|
};
|
|
var wheelEventSupported = false;
|
|
function isPointerFromTouch(event) {
|
|
var pointerType = event.pointerType;
|
|
return pointerType === 'pen' || pointerType === 'touch';
|
|
}
|
|
function setTouchTimer(scope) {
|
|
scope.touching = true;
|
|
if (scope.touchTimer != null) {
|
|
clearTimeout(scope.touchTimer);
|
|
scope.touchTimer = null;
|
|
}
|
|
scope.touchTimer = setTimeout(function () {
|
|
scope.touching = false;
|
|
scope.touchTimer = null;
|
|
}, 700);
|
|
}
|
|
function markTouch(event) {
|
|
event && (event.zrByTouch = true);
|
|
}
|
|
function normalizeGlobalEvent(instance, event) {
|
|
return normalizeEvent(instance.dom, new FakeGlobalEvent(instance, event), true);
|
|
}
|
|
function isLocalEl(instance, el) {
|
|
var elTmp = el;
|
|
var isLocal = false;
|
|
while (elTmp && elTmp.nodeType !== 9
|
|
&& !(isLocal = elTmp.domBelongToZr
|
|
|| (elTmp !== el && elTmp === instance.painterRoot))) {
|
|
elTmp = elTmp.parentNode;
|
|
}
|
|
return isLocal;
|
|
}
|
|
var FakeGlobalEvent = (function () {
|
|
function FakeGlobalEvent(instance, event) {
|
|
this.stopPropagation = zrUtil.noop;
|
|
this.stopImmediatePropagation = zrUtil.noop;
|
|
this.preventDefault = zrUtil.noop;
|
|
this.type = event.type;
|
|
this.target = this.currentTarget = instance.dom;
|
|
this.pointerType = event.pointerType;
|
|
this.clientX = event.clientX;
|
|
this.clientY = event.clientY;
|
|
}
|
|
return FakeGlobalEvent;
|
|
}());
|
|
var localDOMHandlers = {
|
|
mousedown: function (event) {
|
|
event = normalizeEvent(this.dom, event);
|
|
this.__mayPointerCapture = [event.zrX, event.zrY];
|
|
this.trigger('mousedown', event);
|
|
},
|
|
mousemove: function (event) {
|
|
event = normalizeEvent(this.dom, event);
|
|
var downPoint = this.__mayPointerCapture;
|
|
if (downPoint && (event.zrX !== downPoint[0] || event.zrY !== downPoint[1])) {
|
|
this.__togglePointerCapture(true);
|
|
}
|
|
this.trigger('mousemove', event);
|
|
},
|
|
mouseup: function (event) {
|
|
event = normalizeEvent(this.dom, event);
|
|
this.__togglePointerCapture(false);
|
|
this.trigger('mouseup', event);
|
|
},
|
|
mouseout: function (event) {
|
|
event = normalizeEvent(this.dom, event);
|
|
var element = event.toElement || event.relatedTarget;
|
|
if (!isLocalEl(this, element)) {
|
|
if (this.__pointerCapturing) {
|
|
event.zrEventControl = 'no_globalout';
|
|
}
|
|
this.trigger('mouseout', event);
|
|
}
|
|
},
|
|
wheel: function (event) {
|
|
wheelEventSupported = true;
|
|
event = normalizeEvent(this.dom, event);
|
|
this.trigger('mousewheel', event);
|
|
},
|
|
mousewheel: function (event) {
|
|
if (wheelEventSupported) {
|
|
return;
|
|
}
|
|
event = normalizeEvent(this.dom, event);
|
|
this.trigger('mousewheel', event);
|
|
},
|
|
touchstart: function (event) {
|
|
event = normalizeEvent(this.dom, event);
|
|
markTouch(event);
|
|
this.__lastTouchMoment = new Date();
|
|
this.handler.processGesture(event, 'start');
|
|
localDOMHandlers.mousemove.call(this, event);
|
|
localDOMHandlers.mousedown.call(this, event);
|
|
},
|
|
touchmove: function (event) {
|
|
event = normalizeEvent(this.dom, event);
|
|
markTouch(event);
|
|
this.handler.processGesture(event, 'change');
|
|
localDOMHandlers.mousemove.call(this, event);
|
|
},
|
|
touchend: function (event) {
|
|
event = normalizeEvent(this.dom, event);
|
|
markTouch(event);
|
|
this.handler.processGesture(event, 'end');
|
|
localDOMHandlers.mouseup.call(this, event);
|
|
if (+new Date() - (+this.__lastTouchMoment) < TOUCH_CLICK_DELAY) {
|
|
localDOMHandlers.click.call(this, event);
|
|
}
|
|
},
|
|
pointerdown: function (event) {
|
|
localDOMHandlers.mousedown.call(this, event);
|
|
},
|
|
pointermove: function (event) {
|
|
if (!isPointerFromTouch(event)) {
|
|
localDOMHandlers.mousemove.call(this, event);
|
|
}
|
|
},
|
|
pointerup: function (event) {
|
|
localDOMHandlers.mouseup.call(this, event);
|
|
},
|
|
pointerout: function (event) {
|
|
if (!isPointerFromTouch(event)) {
|
|
localDOMHandlers.mouseout.call(this, event);
|
|
}
|
|
}
|
|
};
|
|
zrUtil.each(['click', 'dblclick', 'contextmenu'], function (name) {
|
|
localDOMHandlers[name] = function (event) {
|
|
event = normalizeEvent(this.dom, event);
|
|
this.trigger(name, event);
|
|
};
|
|
});
|
|
var globalDOMHandlers = {
|
|
pointermove: function (event) {
|
|
if (!isPointerFromTouch(event)) {
|
|
globalDOMHandlers.mousemove.call(this, event);
|
|
}
|
|
},
|
|
pointerup: function (event) {
|
|
globalDOMHandlers.mouseup.call(this, event);
|
|
},
|
|
mousemove: function (event) {
|
|
this.trigger('mousemove', event);
|
|
},
|
|
mouseup: function (event) {
|
|
var pointerCaptureReleasing = this.__pointerCapturing;
|
|
this.__togglePointerCapture(false);
|
|
this.trigger('mouseup', event);
|
|
if (pointerCaptureReleasing) {
|
|
event.zrEventControl = 'only_globalout';
|
|
this.trigger('mouseout', event);
|
|
}
|
|
}
|
|
};
|
|
function mountLocalDOMEventListeners(instance, scope) {
|
|
var domHandlers = scope.domHandlers;
|
|
if (env.pointerEventsSupported) {
|
|
zrUtil.each(localNativeListenerNames.pointer, function (nativeEventName) {
|
|
mountSingleDOMEventListener(scope, nativeEventName, function (event) {
|
|
domHandlers[nativeEventName].call(instance, event);
|
|
});
|
|
});
|
|
}
|
|
else {
|
|
if (env.touchEventsSupported) {
|
|
zrUtil.each(localNativeListenerNames.touch, function (nativeEventName) {
|
|
mountSingleDOMEventListener(scope, nativeEventName, function (event) {
|
|
domHandlers[nativeEventName].call(instance, event);
|
|
setTouchTimer(scope);
|
|
});
|
|
});
|
|
}
|
|
zrUtil.each(localNativeListenerNames.mouse, function (nativeEventName) {
|
|
mountSingleDOMEventListener(scope, nativeEventName, function (event) {
|
|
event = getNativeEvent(event);
|
|
if (!scope.touching) {
|
|
domHandlers[nativeEventName].call(instance, event);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
}
|
|
function mountGlobalDOMEventListeners(instance, scope) {
|
|
if (env.pointerEventsSupported) {
|
|
zrUtil.each(globalNativeListenerNames.pointer, mount);
|
|
}
|
|
else if (!env.touchEventsSupported) {
|
|
zrUtil.each(globalNativeListenerNames.mouse, mount);
|
|
}
|
|
function mount(nativeEventName) {
|
|
function nativeEventListener(event) {
|
|
event = getNativeEvent(event);
|
|
if (!isLocalEl(instance, event.target)) {
|
|
event = normalizeGlobalEvent(instance, event);
|
|
scope.domHandlers[nativeEventName].call(instance, event);
|
|
}
|
|
}
|
|
mountSingleDOMEventListener(scope, nativeEventName, nativeEventListener, { capture: true });
|
|
}
|
|
}
|
|
function mountSingleDOMEventListener(scope, nativeEventName, listener, opt) {
|
|
scope.mounted[nativeEventName] = listener;
|
|
scope.listenerOpts[nativeEventName] = opt;
|
|
addEventListener(scope.domTarget, nativeEventName, listener, opt);
|
|
}
|
|
function unmountDOMEventListeners(scope) {
|
|
var mounted = scope.mounted;
|
|
for (var nativeEventName in mounted) {
|
|
if (mounted.hasOwnProperty(nativeEventName)) {
|
|
removeEventListener(scope.domTarget, nativeEventName, mounted[nativeEventName], scope.listenerOpts[nativeEventName]);
|
|
}
|
|
}
|
|
scope.mounted = {};
|
|
}
|
|
var DOMHandlerScope = (function () {
|
|
function DOMHandlerScope(domTarget, domHandlers) {
|
|
this.mounted = {};
|
|
this.listenerOpts = {};
|
|
this.touching = false;
|
|
this.domTarget = domTarget;
|
|
this.domHandlers = domHandlers;
|
|
}
|
|
return DOMHandlerScope;
|
|
}());
|
|
var HandlerDomProxy = (function (_super) {
|
|
__extends(HandlerDomProxy, _super);
|
|
function HandlerDomProxy(dom, painterRoot) {
|
|
var _this = _super.call(this) || this;
|
|
_this.__pointerCapturing = false;
|
|
_this.dom = dom;
|
|
_this.painterRoot = painterRoot;
|
|
_this._localHandlerScope = new DOMHandlerScope(dom, localDOMHandlers);
|
|
if (globalEventSupported) {
|
|
_this._globalHandlerScope = new DOMHandlerScope(document, globalDOMHandlers);
|
|
}
|
|
mountLocalDOMEventListeners(_this, _this._localHandlerScope);
|
|
return _this;
|
|
}
|
|
HandlerDomProxy.prototype.dispose = function () {
|
|
unmountDOMEventListeners(this._localHandlerScope);
|
|
if (globalEventSupported) {
|
|
unmountDOMEventListeners(this._globalHandlerScope);
|
|
}
|
|
};
|
|
HandlerDomProxy.prototype.setCursor = function (cursorStyle) {
|
|
this.dom.style && (this.dom.style.cursor = cursorStyle || 'default');
|
|
};
|
|
HandlerDomProxy.prototype.__togglePointerCapture = function (isPointerCapturing) {
|
|
this.__mayPointerCapture = null;
|
|
if (globalEventSupported
|
|
&& ((+this.__pointerCapturing) ^ (+isPointerCapturing))) {
|
|
this.__pointerCapturing = isPointerCapturing;
|
|
var globalHandlerScope = this._globalHandlerScope;
|
|
isPointerCapturing
|
|
? mountGlobalDOMEventListeners(this, globalHandlerScope)
|
|
: unmountDOMEventListeners(globalHandlerScope);
|
|
}
|
|
};
|
|
return HandlerDomProxy;
|
|
}(Eventful));
|
|
export default HandlerDomProxy;
|