pointer events generated by mouse events
This commit is contained in:
+33
-208
@@ -8,7 +8,8 @@ goog.require('goog.events');
|
|||||||
goog.require('goog.events.BrowserEvent');
|
goog.require('goog.events.BrowserEvent');
|
||||||
goog.require('goog.events.EventTarget');
|
goog.require('goog.events.EventTarget');
|
||||||
goog.require('goog.events.EventType');
|
goog.require('goog.events.EventType');
|
||||||
goog.require('goog.object');
|
|
||||||
|
goog.require('ol.pointer.PointerEventHandler');
|
||||||
goog.require('ol.Coordinate');
|
goog.require('ol.Coordinate');
|
||||||
goog.require('ol.MapEvent');
|
goog.require('ol.MapEvent');
|
||||||
goog.require('ol.Pixel');
|
goog.require('ol.Pixel');
|
||||||
@@ -114,12 +115,6 @@ ol.MapBrowserEventHandler = function(map) {
|
|||||||
*/
|
*/
|
||||||
this.dragListenerKeys_ = null;
|
this.dragListenerKeys_ = null;
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {goog.events.Key}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.mousedownListenerKey_ = null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {goog.events.Key}
|
* @type {goog.events.Key}
|
||||||
* @private
|
* @private
|
||||||
@@ -127,10 +122,10 @@ ol.MapBrowserEventHandler = function(map) {
|
|||||||
this.pointerdownListenerKey_ = null;
|
this.pointerdownListenerKey_ = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {goog.events.Key}
|
* @type {goog.events.BrowserEvent}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
this.touchstartListenerKey_ = null;
|
this.down_ = null;
|
||||||
|
|
||||||
if (ol.LEGACY_IE_SUPPORT && ol.IS_LEGACY_IE) {
|
if (ol.LEGACY_IE_SUPPORT && ol.IS_LEGACY_IE) {
|
||||||
/**
|
/**
|
||||||
@@ -141,38 +136,23 @@ ol.MapBrowserEventHandler = function(map) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {goog.events.BrowserEvent}
|
* @type {ol.pointer.PointerEventHandler}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
this.down_ = null;
|
this.PointerEventHandler_ = null;
|
||||||
|
|
||||||
var element = this.map_.getViewport();
|
var element = this.map_.getViewport();
|
||||||
|
|
||||||
this.relayedListenerKeys_ = [
|
this.pointerEventHandler_ = new ol.pointer.PointerEventHandler(element);
|
||||||
goog.events.listen(element,
|
this.pointerdownListenerKey_ = goog.events.listen(this.pointerEventHandler_,
|
||||||
goog.events.EventType.MOUSEMOVE,
|
ol.pointer.EventType.POINTERDOWN,
|
||||||
this.relayEvent_, false, this),
|
|
||||||
goog.events.listen(element,
|
|
||||||
goog.events.EventType.CLICK,
|
|
||||||
this.relayEvent_, false, this)
|
|
||||||
];
|
|
||||||
|
|
||||||
this.mousedownListenerKey_ = goog.events.listen(element,
|
|
||||||
goog.events.EventType.MOUSEDOWN,
|
|
||||||
this.handleMouseDown_, false, this);
|
|
||||||
|
|
||||||
this.pointerdownListenerKey_ = goog.events.listen(element,
|
|
||||||
goog.events.EventType.MSPOINTERDOWN,
|
|
||||||
this.handlePointerDown_, false, this);
|
this.handlePointerDown_, false, this);
|
||||||
|
|
||||||
this.touchstartListenerKey_ = goog.events.listen(element,
|
this.relayedListenerKeys_ = [
|
||||||
goog.events.EventType.TOUCHSTART,
|
goog.events.listen(this.pointerEventHandler_,
|
||||||
this.handleTouchStart_, false, this);
|
ol.pointer.EventType.POINTERMOVE,
|
||||||
|
this.relayEvent_, false, this)
|
||||||
if (ol.LEGACY_IE_SUPPORT && ol.IS_LEGACY_IE) {
|
];
|
||||||
this.ieDblclickListenerKey_ = goog.events.listen(element,
|
|
||||||
goog.events.EventType.DBLCLICK, this.emulateClick_, false, this);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
goog.inherits(ol.MapBrowserEventHandler, goog.events.EventTarget);
|
goog.inherits(ol.MapBrowserEventHandler, goog.events.EventTarget);
|
||||||
|
|
||||||
@@ -232,7 +212,7 @@ ol.MapBrowserEventHandler.prototype.emulateClick_ = function(browserEvent) {
|
|||||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
ol.MapBrowserEventHandler.prototype.handleMouseUp_ = function(browserEvent) {
|
ol.MapBrowserEventHandler.prototype.handlePointerUp_ = function(browserEvent) {
|
||||||
if (this.down_) {
|
if (this.down_) {
|
||||||
goog.array.forEach(this.dragListenerKeys_, goog.events.unlistenByKey);
|
goog.array.forEach(this.dragListenerKeys_, goog.events.unlistenByKey);
|
||||||
this.dragListenerKeys_ = null;
|
this.dragListenerKeys_ = null;
|
||||||
@@ -251,28 +231,17 @@ ol.MapBrowserEventHandler.prototype.handleMouseUp_ = function(browserEvent) {
|
|||||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
ol.MapBrowserEventHandler.prototype.handleMouseDown_ = function(browserEvent) {
|
ol.MapBrowserEventHandler.prototype.handlePointerDown_ = function(browserEvent) {
|
||||||
if (!goog.isNull(this.pointerdownListenerKey_)) {
|
|
||||||
// mouse device detected - unregister the pointerdown and touchstart
|
|
||||||
// listeners
|
|
||||||
goog.events.unlistenByKey(this.pointerdownListenerKey_);
|
|
||||||
this.pointerdownListenerKey_ = null;
|
|
||||||
|
|
||||||
goog.asserts.assert(!goog.isNull(this.touchstartListenerKey_));
|
|
||||||
goog.events.unlistenByKey(this.touchstartListenerKey_);
|
|
||||||
this.touchstartListenerKey_ = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var newEvent = new ol.MapBrowserEvent(
|
var newEvent = new ol.MapBrowserEvent(
|
||||||
ol.MapBrowserEvent.EventType.DOWN, this.map_, browserEvent);
|
ol.MapBrowserEvent.EventType.DOWN, this.map_, browserEvent);
|
||||||
this.dispatchEvent(newEvent);
|
this.dispatchEvent(newEvent);
|
||||||
this.down_ = browserEvent;
|
this.down_ = browserEvent;
|
||||||
this.dragged_ = false;
|
this.dragged_ = false;
|
||||||
this.dragListenerKeys_ = [
|
this.dragListenerKeys_ = [
|
||||||
goog.events.listen(goog.global.document, goog.events.EventType.MOUSEMOVE,
|
goog.events.listen(this.pointerEventHandler_, ol.MapBrowserEvent.EventType.POINTERMOVE,
|
||||||
this.handleMouseMove_, false, this),
|
this.handlePointerMove_, false, this),
|
||||||
goog.events.listen(goog.global.document, goog.events.EventType.MOUSEUP,
|
goog.events.listen(this.pointerEventHandler_, ol.MapBrowserEvent.EventType.POINTERUP,
|
||||||
this.handleMouseUp_, false, this)
|
this.handlePointerUp_, false, this)
|
||||||
];
|
];
|
||||||
// prevent browser image dragging with the dom renderer
|
// prevent browser image dragging with the dom renderer
|
||||||
browserEvent.preventDefault();
|
browserEvent.preventDefault();
|
||||||
@@ -283,7 +252,7 @@ ol.MapBrowserEventHandler.prototype.handleMouseDown_ = function(browserEvent) {
|
|||||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
ol.MapBrowserEventHandler.prototype.handleMouseMove_ = function(browserEvent) {
|
ol.MapBrowserEventHandler.prototype.handlePointerMove_ = function(browserEvent) {
|
||||||
var newEvent;
|
var newEvent;
|
||||||
if (!this.dragged_) {
|
if (!this.dragged_) {
|
||||||
this.dragged_ = true;
|
this.dragged_ = true;
|
||||||
@@ -297,159 +266,6 @@ ol.MapBrowserEventHandler.prototype.handleMouseMove_ = function(browserEvent) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ol.MapBrowserEventHandler.prototype.handlePointerDown_ =
|
|
||||||
function(browserEvent) {
|
|
||||||
if (!goog.isNull(this.mousedownListenerKey_)) {
|
|
||||||
// pointer device detected - unregister the mousedown and touchstart
|
|
||||||
// listeners
|
|
||||||
goog.events.unlistenByKey(this.mousedownListenerKey_);
|
|
||||||
this.mousedownListenerKey_ = null;
|
|
||||||
|
|
||||||
goog.asserts.assert(!goog.isNull(this.touchstartListenerKey_));
|
|
||||||
goog.events.unlistenByKey(this.touchstartListenerKey_);
|
|
||||||
this.touchstartListenerKey_ = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var newEvent = new ol.MapBrowserEvent(
|
|
||||||
ol.MapBrowserEvent.EventType.TOUCHSTART, this.map_, browserEvent);
|
|
||||||
this.dispatchEvent(newEvent);
|
|
||||||
|
|
||||||
this.down_ = browserEvent;
|
|
||||||
this.dragged_ = false;
|
|
||||||
this.dragListenerKeys_ = [
|
|
||||||
goog.events.listen(goog.global.document,
|
|
||||||
goog.events.EventType.MSPOINTERMOVE,
|
|
||||||
this.handlePointerMove_, false, this),
|
|
||||||
goog.events.listen(goog.global.document, goog.events.EventType.MSPOINTERUP,
|
|
||||||
this.handlePointerUp_, false, this)
|
|
||||||
];
|
|
||||||
|
|
||||||
// FIXME check if/when this is necessary
|
|
||||||
// prevent context menu
|
|
||||||
browserEvent.preventDefault();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ol.MapBrowserEventHandler.prototype.handlePointerMove_ =
|
|
||||||
function(browserEvent) {
|
|
||||||
// Fix IE10 on windows Surface : When you tap the tablet, it triggers
|
|
||||||
// multiple pointermove events between pointerdown and pointerup with
|
|
||||||
// the exact same coordinates of the pointerdown event. To avoid a
|
|
||||||
// 'false' touchmove event to be dispatched , we test if the pointer
|
|
||||||
// effectively moved.
|
|
||||||
if (browserEvent.clientX != this.down_.clientX ||
|
|
||||||
browserEvent.clientY != this.down_.clientY) {
|
|
||||||
this.dragged_ = true;
|
|
||||||
var newEvent = new ol.MapBrowserEvent(
|
|
||||||
ol.MapBrowserEvent.EventType.TOUCHMOVE, this.map_, browserEvent);
|
|
||||||
this.dispatchEvent(newEvent);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ol.MapBrowserEventHandler.prototype.handlePointerUp_ = function(browserEvent) {
|
|
||||||
var newEvent = new ol.MapBrowserEvent(
|
|
||||||
ol.MapBrowserEvent.EventType.TOUCHEND, this.map_, browserEvent);
|
|
||||||
this.dispatchEvent(newEvent);
|
|
||||||
goog.array.forEach(this.dragListenerKeys_, goog.events.unlistenByKey);
|
|
||||||
|
|
||||||
// We emulate click event on left mouse button click, touch contact, and pen
|
|
||||||
// contact. isMouseActionButton returns true in these cases (evt.button is set
|
|
||||||
// to 0).
|
|
||||||
// See http://www.w3.org/TR/pointerevents/#button-states .
|
|
||||||
if (!this.dragged_ && browserEvent.isMouseActionButton()) {
|
|
||||||
goog.asserts.assert(!goog.isNull(this.down_));
|
|
||||||
this.emulateClick_(this.down_);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ol.MapBrowserEventHandler.prototype.handleTouchStart_ = function(browserEvent) {
|
|
||||||
if (!goog.isNull(this.mousedownListenerKey_)) {
|
|
||||||
// touch device detected - unregister the mousedown and pointerdown
|
|
||||||
// listeners
|
|
||||||
goog.events.unlistenByKey(this.mousedownListenerKey_);
|
|
||||||
this.mousedownListenerKey_ = null;
|
|
||||||
|
|
||||||
goog.asserts.assert(!goog.isNull(this.pointerdownListenerKey_));
|
|
||||||
goog.events.unlistenByKey(this.pointerdownListenerKey_);
|
|
||||||
this.pointerdownListenerKey_ = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var newEvent = new ol.MapBrowserEvent(
|
|
||||||
ol.MapBrowserEvent.EventType.TOUCHSTART, this.map_, browserEvent);
|
|
||||||
this.dispatchEvent(newEvent);
|
|
||||||
|
|
||||||
this.down_ = browserEvent;
|
|
||||||
this.dragged_ = false;
|
|
||||||
|
|
||||||
if (goog.isNull(this.dragListenerKeys_)) {
|
|
||||||
this.dragListenerKeys_ = [
|
|
||||||
goog.events.listen(goog.global.document, goog.events.EventType.TOUCHMOVE,
|
|
||||||
this.handleTouchMove_, false, this),
|
|
||||||
goog.events.listen(goog.global.document, goog.events.EventType.TOUCHEND,
|
|
||||||
this.handleTouchEnd_, false, this)
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME check if/when this is necessary
|
|
||||||
browserEvent.preventDefault();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ol.MapBrowserEventHandler.prototype.handleTouchMove_ = function(browserEvent) {
|
|
||||||
this.dragged_ = true;
|
|
||||||
var newEvent = new ol.MapBrowserEvent(
|
|
||||||
ol.MapBrowserEvent.EventType.TOUCHMOVE, this.map_, browserEvent);
|
|
||||||
this.dispatchEvent(newEvent);
|
|
||||||
|
|
||||||
// Some native android browser triggers mousemove events during small period
|
|
||||||
// of time. See: https://code.google.com/p/android/issues/detail?id=5491 or
|
|
||||||
// https://code.google.com/p/android/issues/detail?id=19827
|
|
||||||
// ex: Galaxy Tab P3110 + Android 4.1.1
|
|
||||||
browserEvent.preventDefault();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ol.MapBrowserEventHandler.prototype.handleTouchEnd_ = function(browserEvent) {
|
|
||||||
var newEvent = new ol.MapBrowserEvent(
|
|
||||||
ol.MapBrowserEvent.EventType.TOUCHEND, this.map_, browserEvent);
|
|
||||||
this.dispatchEvent(newEvent);
|
|
||||||
if (browserEvent.getBrowserEvent().targetTouches.length === 0) {
|
|
||||||
goog.array.forEach(this.dragListenerKeys_, goog.events.unlistenByKey);
|
|
||||||
this.dragListenerKeys_ = null;
|
|
||||||
}
|
|
||||||
if (!this.dragged_) {
|
|
||||||
goog.asserts.assert(!goog.isNull(this.down_));
|
|
||||||
this.emulateClick_(this.down_);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FIXME empty description for jsdoc
|
* FIXME empty description for jsdoc
|
||||||
*/
|
*/
|
||||||
@@ -502,13 +318,22 @@ ol.MapBrowserEventHandler.prototype.relayEvent_ = function(browserEvent) {
|
|||||||
ol.MapBrowserEvent.EventType = {
|
ol.MapBrowserEvent.EventType = {
|
||||||
CLICK: goog.events.EventType.CLICK,
|
CLICK: goog.events.EventType.CLICK,
|
||||||
DBLCLICK: goog.events.EventType.DBLCLICK,
|
DBLCLICK: goog.events.EventType.DBLCLICK,
|
||||||
MOUSEMOVE: goog.events.EventType.MOUSEMOVE,
|
|
||||||
DOWN: 'down',
|
|
||||||
DRAGSTART: 'dragstart',
|
DRAGSTART: 'dragstart',
|
||||||
DRAG: 'drag',
|
DRAG: 'drag',
|
||||||
DRAGEND: 'dragend',
|
DRAGEND: 'dragend',
|
||||||
|
DOWN: 'down',
|
||||||
|
|
||||||
|
MOUSEMOVE: goog.events.EventType.MOUSEMOVE,
|
||||||
SINGLECLICK: 'singleclick',
|
SINGLECLICK: 'singleclick',
|
||||||
TOUCHSTART: goog.events.EventType.TOUCHSTART,
|
TOUCHSTART: goog.events.EventType.TOUCHSTART,
|
||||||
TOUCHMOVE: goog.events.EventType.TOUCHMOVE,
|
TOUCHMOVE: goog.events.EventType.TOUCHMOVE,
|
||||||
TOUCHEND: goog.events.EventType.TOUCHEND
|
TOUCHEND: goog.events.EventType.TOUCHEND,
|
||||||
|
|
||||||
|
POINTERMOVE: 'pointermove',
|
||||||
|
POINTERDOWN: 'pointerdown',
|
||||||
|
POINTERUP: 'pointerup',
|
||||||
|
POINTEROVER: 'pointerover',
|
||||||
|
POINTERENTER: 'pointerenter',
|
||||||
|
POINTERLEAVE: 'pointerleave',
|
||||||
|
POINTERCANCEL: 'pointercancel'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
|
||||||
|
goog.provide('ol.pointer.EventSource');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ol.pointer.PointerEventHandler} dispatcher
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
ol.pointer.EventSource = function(dispatcher) {
|
||||||
|
/**
|
||||||
|
* @type {ol.pointer.PointerEventHandler}
|
||||||
|
*/
|
||||||
|
this.dispatcher = dispatcher;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of events supported by this source.
|
||||||
|
* @return {Array.<string>} Event names
|
||||||
|
*/
|
||||||
|
ol.pointer.EventSource.prototype.getEvents = goog.abstractMethod;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a mapping between the supported event types and
|
||||||
|
* the handlers that should handle an event.
|
||||||
|
* @return {Object.<string, function(Event)>} Event/Handler mapping
|
||||||
|
*/
|
||||||
|
ol.pointer.EventSource.prototype.getMapping = goog.abstractMethod;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the handler that should handle a given event type.
|
||||||
|
* @param {string} eventType
|
||||||
|
* @return {function(Event)} Handler
|
||||||
|
*/
|
||||||
|
ol.pointer.EventSource.prototype.getHandlerForEvent = function(eventType) {
|
||||||
|
return this.getMapping()[eventType];
|
||||||
|
};
|
||||||
@@ -0,0 +1,197 @@
|
|||||||
|
goog.provide('ol.pointer.MouseSource');
|
||||||
|
|
||||||
|
goog.require('ol.pointer.EventSource');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ol.pointer.PointerEventHandler} dispatcher
|
||||||
|
* @constructor
|
||||||
|
* @extends {ol.pointer.EventSource}
|
||||||
|
*/
|
||||||
|
ol.pointer.MouseSource = function(dispatcher) {
|
||||||
|
goog.base(this, dispatcher);
|
||||||
|
|
||||||
|
this.pointerMap = dispatcher.pointerMap;
|
||||||
|
|
||||||
|
// radius around touchend that swallows mouse events
|
||||||
|
this.DEDUP_DIST = 25;
|
||||||
|
|
||||||
|
this.POINTER_ID = 1;
|
||||||
|
this.POINTER_TYPE = 'mouse';
|
||||||
|
|
||||||
|
this.events = [
|
||||||
|
'mousedown',
|
||||||
|
'mousemove',
|
||||||
|
'mouseup',
|
||||||
|
'mouseover',
|
||||||
|
'mouseout'
|
||||||
|
];
|
||||||
|
this.mapping = {
|
||||||
|
'mousedown': this.mousedown,
|
||||||
|
'mousemove': this.mousemove,
|
||||||
|
'mouseup': this.mouseup,
|
||||||
|
'mouseover': this.mouseover,
|
||||||
|
'mouseout': this.mouseout
|
||||||
|
};
|
||||||
|
|
||||||
|
this.lastTouches = [];
|
||||||
|
};
|
||||||
|
goog.inherits(ol.pointer.MouseSource, ol.pointer.EventSource);
|
||||||
|
|
||||||
|
|
||||||
|
/** @inheritDoc */
|
||||||
|
ol.pointer.MouseSource.prototype.getEvents = function() {
|
||||||
|
return this.events;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** @inheritDoc */
|
||||||
|
ol.pointer.MouseSource.prototype.getMapping = function() {
|
||||||
|
return this.mapping;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collide with the global mouse listener
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {goog.events.BrowserEvent} inEvent
|
||||||
|
* @return {boolean} True, if the event was generated by a touch.
|
||||||
|
*/
|
||||||
|
ol.pointer.MouseSource.prototype.isEventSimulatedFromTouch_ =
|
||||||
|
function(inEvent) {
|
||||||
|
var lts = this.lastTouches;
|
||||||
|
var x = inEvent.clientX, y = inEvent.clientY;
|
||||||
|
for (var i = 0, l = lts.length, t; i < l && (t = lts[i]); i++) {
|
||||||
|
// simulated mouse events will be swallowed near a primary touchend
|
||||||
|
var dx = Math.abs(x - t.x), dy = Math.abs(y - t.y);
|
||||||
|
if (dx <= this.DEDUP_DIST && dy <= this.DEDUP_DIST) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a copy of the original event that will be used
|
||||||
|
* for the fake pointer event.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {goog.events.BrowserEvent} inEvent
|
||||||
|
* @return {Object}
|
||||||
|
*/
|
||||||
|
ol.pointer.MouseSource.prototype.prepareEvent_ = function(inEvent) {
|
||||||
|
var e = this.dispatcher.cloneEvent(inEvent);
|
||||||
|
|
||||||
|
// forward mouse preventDefault
|
||||||
|
var pd = e.preventDefault;
|
||||||
|
e.preventDefault = function() {
|
||||||
|
inEvent.preventDefault();
|
||||||
|
pd();
|
||||||
|
};
|
||||||
|
|
||||||
|
e.pointerId = this.POINTER_ID;
|
||||||
|
e.isPrimary = true;
|
||||||
|
e.pointerType = this.POINTER_TYPE;
|
||||||
|
|
||||||
|
return e;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for `mousedown`.
|
||||||
|
*
|
||||||
|
* @param {goog.events.BrowserEvent} inEvent
|
||||||
|
*/
|
||||||
|
ol.pointer.MouseSource.prototype.mousedown = function(inEvent) {
|
||||||
|
if (!this.isEventSimulatedFromTouch_(inEvent)) {
|
||||||
|
var p = this.pointerMap.containsKey(this.POINTER_ID);
|
||||||
|
// TODO(dfreedman) workaround for some elements not sending mouseup
|
||||||
|
// http://crbug/149091
|
||||||
|
if (p) {
|
||||||
|
this.cancel(inEvent);
|
||||||
|
}
|
||||||
|
var e = this.prepareEvent_(inEvent);
|
||||||
|
this.pointerMap.set(this.POINTER_ID, inEvent);
|
||||||
|
this.dispatcher.down(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for `mousemove`.
|
||||||
|
*
|
||||||
|
* @param {goog.events.BrowserEvent} inEvent
|
||||||
|
*/
|
||||||
|
ol.pointer.MouseSource.prototype.mousemove = function(inEvent) {
|
||||||
|
if (!this.isEventSimulatedFromTouch_(inEvent)) {
|
||||||
|
var e = this.prepareEvent_(inEvent);
|
||||||
|
this.dispatcher.move(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for `mouseup`.
|
||||||
|
*
|
||||||
|
* @param {goog.events.BrowserEvent} inEvent
|
||||||
|
*/
|
||||||
|
ol.pointer.MouseSource.prototype.mouseup = function(inEvent) {
|
||||||
|
if (!this.isEventSimulatedFromTouch_(inEvent)) {
|
||||||
|
var p = this.pointerMap.get(this.POINTER_ID);
|
||||||
|
|
||||||
|
if (p && p.button === inEvent.button) {
|
||||||
|
var e = this.prepareEvent_(inEvent);
|
||||||
|
this.dispatcher.up(e);
|
||||||
|
this.cleanupMouse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for `mouseover`.
|
||||||
|
*
|
||||||
|
* @param {goog.events.BrowserEvent} inEvent
|
||||||
|
*/
|
||||||
|
ol.pointer.MouseSource.prototype.mouseover = function(inEvent) {
|
||||||
|
if (!this.isEventSimulatedFromTouch_(inEvent)) {
|
||||||
|
var e = this.prepareEvent_(inEvent);
|
||||||
|
this.dispatcher.enterOver(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for `mouseout`.
|
||||||
|
*
|
||||||
|
* @param {goog.events.BrowserEvent} inEvent
|
||||||
|
*/
|
||||||
|
ol.pointer.MouseSource.prototype.mouseout = function(inEvent) {
|
||||||
|
if (!this.isEventSimulatedFromTouch_(inEvent)) {
|
||||||
|
var e = this.prepareEvent_(inEvent);
|
||||||
|
this.dispatcher.leaveOut(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatches a `pointercancel` event.
|
||||||
|
*
|
||||||
|
* @param {goog.events.BrowserEvent} inEvent
|
||||||
|
*/
|
||||||
|
ol.pointer.MouseSource.prototype.cancel = function(inEvent) {
|
||||||
|
var e = this.prepareEvent_(inEvent);
|
||||||
|
this.dispatcher.cancel(e);
|
||||||
|
this.cleanupMouse();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the mouse from the list of active pointers.
|
||||||
|
*/
|
||||||
|
ol.pointer.MouseSource.prototype.cleanupMouse = function() {
|
||||||
|
this.pointerMap.remove(this.POINTER_ID);
|
||||||
|
};
|
||||||
@@ -0,0 +1,209 @@
|
|||||||
|
goog.provide('ol.pointer.PointerEvent');
|
||||||
|
|
||||||
|
|
||||||
|
//goog.require('goog.events.Event');
|
||||||
|
goog.require('goog.events');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the constructor for new PointerEvents.
|
||||||
|
*
|
||||||
|
* New Pointer Events must be given a type, and an optional dictionary of
|
||||||
|
* initialization properties.
|
||||||
|
*
|
||||||
|
* Due to certain platform requirements, events returned from the constructor
|
||||||
|
* identify as MouseEvents.
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
* @extends {Event}
|
||||||
|
* @param {string} inType The type of the event to create.
|
||||||
|
* @param {Object.<string, ?>=} opt_inDict An optional dictionary of
|
||||||
|
* initial event properties.
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEvent = function(inType, opt_inDict) {
|
||||||
|
opt_inDict = opt_inDict || {};
|
||||||
|
// According to the w3c spec,
|
||||||
|
// http://www.w3.org/TR/DOM-Level-3-Events/#events-MouseEvent-button
|
||||||
|
// MouseEvent.button == 0 can mean either no mouse button depressed, or the
|
||||||
|
// left mouse button depressed.
|
||||||
|
//
|
||||||
|
// As of now, the only way to distinguish between the two states of
|
||||||
|
// MouseEvent.button is by using the deprecated MouseEvent.which property, as
|
||||||
|
// this maps mouse buttons to positive integers > 0, and uses 0 to mean that
|
||||||
|
// no mouse button is held.
|
||||||
|
//
|
||||||
|
// MouseEvent.which is derived from MouseEvent.button at MouseEvent creation,
|
||||||
|
// but initMouseEvent does not expose an argument with which to set
|
||||||
|
// MouseEvent.which. Calling initMouseEvent with a buttonArg of 0 will set
|
||||||
|
// MouseEvent.button == 0 and MouseEvent.which == 1, breaking the expectations
|
||||||
|
// of app developers.
|
||||||
|
//
|
||||||
|
// The only way to propagate the correct state of MouseEvent.which and
|
||||||
|
// MouseEvent.button to a new MouseEvent.button == 0 and MouseEvent.which == 0
|
||||||
|
// is to call initMouseEvent with a buttonArg value of -1.
|
||||||
|
//
|
||||||
|
// This is fixed with DOM Level 4's use of buttons
|
||||||
|
var buttons;
|
||||||
|
if (opt_inDict.buttons || ol.pointer.PointerEvent.HAS_BUTTONS) {
|
||||||
|
buttons = opt_inDict.buttons;
|
||||||
|
} else {
|
||||||
|
switch (opt_inDict.which) {
|
||||||
|
case 1: buttons = 1; break;
|
||||||
|
case 2: buttons = 4; break;
|
||||||
|
case 3: buttons = 2; break;
|
||||||
|
default: buttons = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var e;
|
||||||
|
if (ol.pointer.PointerEvent.NEW_MOUSE_EVENT) {
|
||||||
|
e = ol.pointer.PointerEvent.createMouseEvent(inType, opt_inDict);
|
||||||
|
} else {
|
||||||
|
e = document.createEvent('MouseEvent');
|
||||||
|
|
||||||
|
// import values from the given dictionary
|
||||||
|
/**
|
||||||
|
* @type {Object.<string, ?>}
|
||||||
|
*/
|
||||||
|
var props = {};
|
||||||
|
var p;
|
||||||
|
for (var i = 0; i < ol.pointer.PointerEvent.MOUSE_PROPS.length; i++) {
|
||||||
|
p = ol.pointer.PointerEvent.MOUSE_PROPS[i];
|
||||||
|
props[p] = opt_inDict[p] || ol.pointer.PointerEvent.MOUSE_DEFAULTS[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// define the properties inherited from MouseEvent
|
||||||
|
e.initMouseEvent(
|
||||||
|
inType, props.bubbles, props.cancelable, props.view, props.detail,
|
||||||
|
props.screenX, props.screenY, props.clientX, props.clientY,
|
||||||
|
props.ctrlKey, props.altKey, props.shiftKey, props.metaKey,
|
||||||
|
props.button, props.relatedTarget
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// make the event pass instanceof checks
|
||||||
|
e.__proto__ = ol.pointer.PointerEvent.prototype;
|
||||||
|
|
||||||
|
// define the buttons property according to DOM Level 3 spec
|
||||||
|
if (!ol.pointer.PointerEvent.HAS_BUTTONS) {
|
||||||
|
// IE 10 has buttons on MouseEvent.prototype as a getter w/o any setting
|
||||||
|
// mechanism
|
||||||
|
Object.defineProperty(e, 'buttons',
|
||||||
|
{get: function() { return buttons; }, enumerable: true});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spec requires that pointers without pressure specified use 0.5 for down
|
||||||
|
// state and 0 for up state.
|
||||||
|
var pressure = 0;
|
||||||
|
if (opt_inDict.pressure) {
|
||||||
|
pressure = opt_inDict.pressure;
|
||||||
|
} else {
|
||||||
|
pressure = buttons ? 0.5 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// define the properties of the PointerEvent interface
|
||||||
|
Object.defineProperties(e, {
|
||||||
|
pointerId: { value: opt_inDict.pointerId || 0, enumerable: true },
|
||||||
|
width: { value: opt_inDict.width || 0, enumerable: true },
|
||||||
|
height: { value: opt_inDict.height || 0, enumerable: true },
|
||||||
|
pressure: { value: pressure, enumerable: true },
|
||||||
|
tiltX: { value: opt_inDict.tiltX || 0, enumerable: true },
|
||||||
|
tiltY: { value: opt_inDict.tiltY || 0, enumerable: true },
|
||||||
|
pointerType: { value: opt_inDict.pointerType || '', enumerable: true },
|
||||||
|
hwTimestamp: { value: opt_inDict.hwTimestamp || 0, enumerable: true },
|
||||||
|
isPrimary: { value: opt_inDict.isPrimary || false, enumerable: true }
|
||||||
|
});
|
||||||
|
|
||||||
|
return e;
|
||||||
|
};
|
||||||
|
|
||||||
|
// PointerEvent extends MouseEvent
|
||||||
|
ol.pointer.PointerEvent.prototype = Object.create(MouseEvent.prototype);
|
||||||
|
|
||||||
|
|
||||||
|
// test for DOM Level 4 Events
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does the browser support the `MouseEvent` type?
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEvent.NEW_MOUSE_EVENT = false;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the `buttons` property supported?
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEvent.HAS_BUTTONS = false;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the `MouseEvent` type is supported.
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEvent.checkNewMouseEvent = function() {
|
||||||
|
try {
|
||||||
|
var ev = ol.pointer.PointerEvent.createMouseEvent('click', {buttons: 1});
|
||||||
|
ol.pointer.PointerEvent.NEW_MOUSE_EVENT = true;
|
||||||
|
ol.pointer.PointerEvent.HAS_BUTTONS = ev.buttons === 1;
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ol.pointer.PointerEvent.checkNewMouseEvent();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Warning is suppressed because Closure thinks MouseEvent
|
||||||
|
* has no arguments.
|
||||||
|
* @param {string} inType The type of the event to create.
|
||||||
|
* @param {Object} inDict An dictionary of initial event properties.
|
||||||
|
* @return {MouseEvent}
|
||||||
|
* @suppress {checkTypes}
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEvent.createMouseEvent = function(inType, inDict) {
|
||||||
|
return new MouseEvent(inType, inDict);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of properties to copy when creating an event.
|
||||||
|
* @type {Array.<string>}
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEvent.MOUSE_PROPS = [
|
||||||
|
'bubbles',
|
||||||
|
'cancelable',
|
||||||
|
'view',
|
||||||
|
'detail',
|
||||||
|
'screenX',
|
||||||
|
'screenY',
|
||||||
|
'clientX',
|
||||||
|
'clientY',
|
||||||
|
'ctrlKey',
|
||||||
|
'altKey',
|
||||||
|
'shiftKey',
|
||||||
|
'metaKey',
|
||||||
|
'button',
|
||||||
|
'relatedTarget'
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of default values when creating an event.
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEvent.MOUSE_DEFAULTS = [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
null
|
||||||
|
];
|
||||||
@@ -0,0 +1,509 @@
|
|||||||
|
goog.provide('ol.pointer.PointerEventHandler');
|
||||||
|
|
||||||
|
|
||||||
|
goog.require('goog.debug.Console');
|
||||||
|
goog.require('goog.events');
|
||||||
|
goog.require('goog.events.BrowserEvent');
|
||||||
|
goog.require('goog.events.Event');
|
||||||
|
goog.require('goog.events.EventTarget');
|
||||||
|
goog.require('goog.structs.Map');
|
||||||
|
|
||||||
|
goog.require('ol.pointer.MouseSource');
|
||||||
|
// goog.require('ol.pointer.MsSource');
|
||||||
|
// goog.require('ol.pointer.NativeSource');
|
||||||
|
goog.require('ol.pointer.PointerEvent');
|
||||||
|
// goog.require('ol.pointer.TouchSource');
|
||||||
|
goog.require('ol.structs.WeakMap');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @extends {goog.events.EventTarget}
|
||||||
|
* @param {Element} element Viewport element.
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEventHandler = function(element) {
|
||||||
|
goog.base(this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @const
|
||||||
|
* @private
|
||||||
|
* @type {Element}
|
||||||
|
*/
|
||||||
|
this.element_ = element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @const
|
||||||
|
* @type {goog.structs.Map}
|
||||||
|
*/
|
||||||
|
this.pointerMap = new goog.structs.Map();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @const
|
||||||
|
* @type {ol.structs.WeakMap}
|
||||||
|
*/
|
||||||
|
this.targets = new ol.structs.WeakMap();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @const
|
||||||
|
* @type {ol.structs.WeakMap}
|
||||||
|
*/
|
||||||
|
this.handledEvents = new ol.structs.WeakMap();
|
||||||
|
|
||||||
|
this.eventMap = {};
|
||||||
|
|
||||||
|
// Scope objects for native events.
|
||||||
|
// This exists for ease of testing.
|
||||||
|
this.eventSources = {};
|
||||||
|
this.eventSourceList = [];
|
||||||
|
|
||||||
|
this.boundHandler_ = this.eventHandler_.bind(this);
|
||||||
|
|
||||||
|
this.registerSources();
|
||||||
|
};
|
||||||
|
goog.inherits(ol.pointer.PointerEventHandler, goog.events.EventTarget);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up the event sources (mouse, touch and native pointers)
|
||||||
|
* that generate pointer events.
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEventHandler.prototype.registerSources = function() {
|
||||||
|
if (this.isPointerEnabled_()) {
|
||||||
|
// this.registerSource('native', new ol.pointer.NativeSource(this));
|
||||||
|
} else if (this.isMsPointerEnabled_()) {
|
||||||
|
// this.registerSource('ms', new ol.pointer.MsSource(this));
|
||||||
|
} else {
|
||||||
|
var mouseSource = new ol.pointer.MouseSource(this);
|
||||||
|
this.registerSource('mouse', mouseSource);
|
||||||
|
|
||||||
|
if (this.isTouchDefined_()) {
|
||||||
|
//this.registerSource('touch',
|
||||||
|
// new ol.pointer.TouchSource(this, mouseSource));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// register events on the viewport element
|
||||||
|
this.register_();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @return {boolean} Returns true if the browser supports
|
||||||
|
* native pointer events.
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEventHandler.prototype.isPointerEnabled_ = function() {
|
||||||
|
/* TODO navigation.pointerEnabled is actually not part of the
|
||||||
|
* spec: https://www.w3.org/Bugs/Public/show_bug.cgi?id=22890#c3
|
||||||
|
*/
|
||||||
|
return window.navigator['pointerEnabled'] !== undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @return {boolean} Returns true if the browser supports
|
||||||
|
* ms pointer events (IE10).
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEventHandler.prototype.isMsPointerEnabled_ = function() {
|
||||||
|
return window.navigator['msPointerEnabled'] !== undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @return {boolean} Returns true if the browser supports
|
||||||
|
* touch events.
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEventHandler.prototype.isTouchDefined_ = function() {
|
||||||
|
return window['ontouchstart'] !== undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new event source that will generate pointer events.
|
||||||
|
*
|
||||||
|
* @param {string} name A name for the event source
|
||||||
|
* @param {ol.pointer.EventSource} source
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEventHandler.prototype.registerSource =
|
||||||
|
function(name, source) {
|
||||||
|
var s = source;
|
||||||
|
var newEvents = s.getEvents();
|
||||||
|
|
||||||
|
if (newEvents) {
|
||||||
|
newEvents.forEach(function(e) {
|
||||||
|
var handler = s.getHandlerForEvent(e);
|
||||||
|
|
||||||
|
if (handler) {
|
||||||
|
this.eventMap[e] = handler.bind(s);
|
||||||
|
}
|
||||||
|
}, this);
|
||||||
|
this.eventSources[name] = s;
|
||||||
|
this.eventSourceList.push(s);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @suppress {undefinedVars}
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEventHandler.prototype.log = function(obj) {
|
||||||
|
console.log(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up the events for all registered event sources.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEventHandler.prototype.register_ = function() {
|
||||||
|
var l = this.eventSourceList.length;
|
||||||
|
for (var i = 0, es; (i < l) && (es = this.eventSourceList[i]); i++) {
|
||||||
|
this.addEvents_(es.getEvents());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all registered events.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEventHandler.prototype.unregister_ = function() {
|
||||||
|
var l = this.eventSourceList.length;
|
||||||
|
for (var i = 0, es; (i < l) && (es = this.eventSourceList[i]); i++) {
|
||||||
|
this.removeEvents_(es.getEvents());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls the right handler for a new event.
|
||||||
|
* @private
|
||||||
|
* @param {goog.events.BrowserEvent} inEvent Browser event.
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEventHandler.prototype.eventHandler_ = function(inEvent) {
|
||||||
|
// This is used to prevent multiple dispatch of pointerevents from
|
||||||
|
// platform events. This can happen when two elements in different scopes
|
||||||
|
// are set up to create pointer events, which is relevant to Shadow DOM.
|
||||||
|
if (this.handledEvents['get'](inEvent)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var type = inEvent.type;
|
||||||
|
var handler = this.eventMap[type];
|
||||||
|
if (handler) {
|
||||||
|
handler(inEvent);
|
||||||
|
}
|
||||||
|
this.handledEvents['set'](inEvent, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup listeners for the given events.
|
||||||
|
* @private
|
||||||
|
* @param {Array.<string>} events List of events.
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEventHandler.prototype.addEvents_ = function(events) {
|
||||||
|
events.forEach(function(eventName) {
|
||||||
|
goog.events.listen(this.element_, eventName,
|
||||||
|
this.boundHandler_);
|
||||||
|
}, this);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregister listeners for the given events.
|
||||||
|
* @private
|
||||||
|
* @param {Array.<string>} events List of events.
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEventHandler.prototype.removeEvents_ = function(events) {
|
||||||
|
events.forEach(function(e) {
|
||||||
|
goog.events.unlisten(this.element_, e,
|
||||||
|
this.boundHandler_);
|
||||||
|
}, this);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a snapshot of inEvent, with writable properties.
|
||||||
|
*
|
||||||
|
* @param {goog.events.BrowserEvent} inEvent An event that contains
|
||||||
|
* properties to copy.
|
||||||
|
* @return {Object} An object containing shallow copies of
|
||||||
|
* `inEvent`'s properties.
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEventHandler.prototype.cloneEvent = function(inEvent) {
|
||||||
|
var eventCopy = {}, p;
|
||||||
|
for (var i = 0; i < ol.pointer.CLONE_PROPS.length; i++) {
|
||||||
|
p = ol.pointer.CLONE_PROPS[i];
|
||||||
|
eventCopy[p] = inEvent[p] || ol.pointer.CLONE_DEFAULTS[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// keep the semantics of preventDefault
|
||||||
|
if (inEvent.preventDefault) {
|
||||||
|
eventCopy.preventDefault = function() {
|
||||||
|
inEvent.preventDefault();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return eventCopy;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// EVENTS
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers a 'pointerdown' event.
|
||||||
|
* @param {Object} inEvent
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEventHandler.prototype.down = function(inEvent) {
|
||||||
|
this.fireEvent('pointerdown', inEvent);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers a 'pointermove' event.
|
||||||
|
* @param {Object} inEvent
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEventHandler.prototype.move = function(inEvent) {
|
||||||
|
this.fireEvent('pointermove', inEvent);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers a 'pointerup' event.
|
||||||
|
* @param {Object} inEvent
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEventHandler.prototype.up = function(inEvent) {
|
||||||
|
this.fireEvent('pointerup', inEvent);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers a 'pointerenter' event.
|
||||||
|
* @param {Object} inEvent
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEventHandler.prototype.enter = function(inEvent) {
|
||||||
|
inEvent.bubbles = false;
|
||||||
|
this.fireEvent('pointerenter', inEvent);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers a 'pointerleave' event.
|
||||||
|
* @param {Object} inEvent
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEventHandler.prototype.leave = function(inEvent) {
|
||||||
|
inEvent.bubbles = false;
|
||||||
|
this.fireEvent('pointerleave', inEvent);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers a 'pointerover' event.
|
||||||
|
* @param {Object} inEvent
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEventHandler.prototype.over = function(inEvent) {
|
||||||
|
inEvent.bubbles = true;
|
||||||
|
this.fireEvent('pointerover', inEvent);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers a 'pointerout' event.
|
||||||
|
* @param {Object} inEvent
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEventHandler.prototype.out = function(inEvent) {
|
||||||
|
inEvent.bubbles = true;
|
||||||
|
this.fireEvent('pointerout', inEvent);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers a 'pointercancel' event.
|
||||||
|
* @param {Object} inEvent
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEventHandler.prototype.cancel = function(inEvent) {
|
||||||
|
this.fireEvent('pointercancel', inEvent);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers a combination of 'pointerout' and 'pointerleave' events.
|
||||||
|
* @param {Object} inEvent
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEventHandler.prototype.leaveOut = function(inEvent) {
|
||||||
|
this.out(inEvent);
|
||||||
|
if (!this.contains_(inEvent.target, inEvent.relatedTarget)) {
|
||||||
|
this.leave(inEvent);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers a combination of 'pointerover' and 'pointerevents' events.
|
||||||
|
* @param {Object} inEvent
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEventHandler.prototype.enterOver = function(inEvent) {
|
||||||
|
this.over(inEvent);
|
||||||
|
if (!this.contains_(inEvent.target, inEvent.relatedTarget)) {
|
||||||
|
this.enter(inEvent);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @param {Element} container
|
||||||
|
* @param {Element} contained
|
||||||
|
* @return {boolean} Returns true if the container element
|
||||||
|
* contains the other element.
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEventHandler.prototype.contains_ =
|
||||||
|
function(container, contained) {
|
||||||
|
return container.contains(contained);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// EVENT CREATION AND TRACKING
|
||||||
|
/**
|
||||||
|
* Creates a new Event of type `inType`, based on the information in
|
||||||
|
* `inEvent`.
|
||||||
|
*
|
||||||
|
* @param {string} inType A string representing the type of event to create.
|
||||||
|
* @param {Object} inEvent A platform event with a target.
|
||||||
|
* @return {ol.pointer.PointerEvent} A PointerEvent of type `inType`.
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEventHandler.prototype.makeEvent = function(inType, inEvent) {
|
||||||
|
// relatedTarget must be null if pointer is captured
|
||||||
|
if (this.captureInfo) {
|
||||||
|
inEvent.relatedTarget = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var e = new ol.pointer.PointerEvent(inType, inEvent);
|
||||||
|
if (inEvent.preventDefault) {
|
||||||
|
e.preventDefault = inEvent.preventDefault;
|
||||||
|
}
|
||||||
|
this.targets['set'](e, this.targets['get'](inEvent) || inEvent.target);
|
||||||
|
|
||||||
|
return e;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make and dispatch an event in one call.
|
||||||
|
* @param {string} inType A string representing the type of event.
|
||||||
|
* @param {Object} inEvent A platform event with a target.
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEventHandler.prototype.fireEvent = function(inType, inEvent) {
|
||||||
|
var e = this.makeEvent(inType, inEvent);
|
||||||
|
var browserEvent = new goog.events.BrowserEvent(e);
|
||||||
|
this.dispatchEvent(browserEvent);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Re-fires a native pointer event.
|
||||||
|
* @param {Event} nativeEvent A platform event with a target.
|
||||||
|
*/
|
||||||
|
ol.pointer.PointerEventHandler.prototype.fireNativeEvent =
|
||||||
|
function(nativeEvent) {
|
||||||
|
var browserEvent = new goog.events.BrowserEvent(nativeEvent);
|
||||||
|
this.dispatchEvent(browserEvent);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constants for event names.
|
||||||
|
* @enum {string}
|
||||||
|
*/
|
||||||
|
ol.pointer.EventType = {
|
||||||
|
POINTERMOVE: 'pointermove',
|
||||||
|
POINTERDOWN: 'pointerdown',
|
||||||
|
POINTERUP: 'pointerup',
|
||||||
|
POINTEROVER: 'pointerover',
|
||||||
|
POINTERENTER: 'pointerenter',
|
||||||
|
POINTERLEAVE: 'pointerleave',
|
||||||
|
POINTERCANCEL: 'pointercancel'
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of properties to copy when cloning an event.
|
||||||
|
* @type {Array.<string>}
|
||||||
|
*/
|
||||||
|
ol.pointer.CLONE_PROPS = [
|
||||||
|
// MouseEvent
|
||||||
|
'bubbles',
|
||||||
|
'cancelable',
|
||||||
|
'view',
|
||||||
|
'detail',
|
||||||
|
'screenX',
|
||||||
|
'screenY',
|
||||||
|
'clientX',
|
||||||
|
'clientY',
|
||||||
|
'ctrlKey',
|
||||||
|
'altKey',
|
||||||
|
'shiftKey',
|
||||||
|
'metaKey',
|
||||||
|
'button',
|
||||||
|
'relatedTarget',
|
||||||
|
// DOM Level 3
|
||||||
|
'buttons',
|
||||||
|
// PointerEvent
|
||||||
|
'pointerId',
|
||||||
|
'width',
|
||||||
|
'height',
|
||||||
|
'pressure',
|
||||||
|
'tiltX',
|
||||||
|
'tiltY',
|
||||||
|
'pointerType',
|
||||||
|
'hwTimestamp',
|
||||||
|
'isPrimary',
|
||||||
|
// event instance
|
||||||
|
'type',
|
||||||
|
'target',
|
||||||
|
'currentTarget',
|
||||||
|
'which'
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of default values when cloning an event.
|
||||||
|
*/
|
||||||
|
ol.pointer.CLONE_DEFAULTS = [
|
||||||
|
// MouseEvent
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
null,
|
||||||
|
// DOM Level 3
|
||||||
|
0,
|
||||||
|
// PointerEvent
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
'',
|
||||||
|
0,
|
||||||
|
false,
|
||||||
|
// event instance
|
||||||
|
'',
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
0
|
||||||
|
];
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
// Based on https://github.com/Polymer/WeakMap
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The Polymer Authors. All rights reserved.
|
||||||
|
* Use of this source code is governed by a BSD-style
|
||||||
|
* license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
goog.provide('ol.structs.WeakMap');
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @suppress {undefinedVars}
|
||||||
|
* @return {boolean} Is `WeakMap` already defined?
|
||||||
|
*/
|
||||||
|
ol.structs.isWeakMapUndefined = function() {
|
||||||
|
return typeof WeakMap === 'undefined';
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
if (ol.structs.isWeakMapUndefined()) {
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
ol.structs.WeakMap = function() {
|
||||||
|
this.name = '__st' + (Math.random() * 1e9 >>> 0) +
|
||||||
|
(ol.structs.WeakMap.counter++ + '__');
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {*} key
|
||||||
|
* @param {*} value
|
||||||
|
*/
|
||||||
|
ol.structs.WeakMap.prototype['set'] = function(key, value) {
|
||||||
|
var entry = key[this.name];
|
||||||
|
if (entry && entry[0] === key)
|
||||||
|
entry[1] = value;
|
||||||
|
else
|
||||||
|
ol.structs.WeakMap.defineProperty(key, this.name,
|
||||||
|
{value: [key, value], writable: true});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {*} key
|
||||||
|
* @return {*}
|
||||||
|
*/
|
||||||
|
ol.structs.WeakMap.prototype['get'] = function(key) {
|
||||||
|
var entry;
|
||||||
|
return (entry = key[this.name]) && entry[0] === key ?
|
||||||
|
entry[1] : undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @this {ol.structs.WeakMap}
|
||||||
|
* @param {*} key
|
||||||
|
*/
|
||||||
|
ol.structs.WeakMap.prototype['delete'] = function(key) {
|
||||||
|
this['set'](key, undefined);
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
ol.structs.WeakMap = WeakMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {function(...)}
|
||||||
|
*/
|
||||||
|
ol.structs.WeakMap.defineProperty = Object.defineProperty;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
|
ol.structs.WeakMap.counter = Date.now() % 1e9;
|
||||||
Reference in New Issue
Block a user