pointer events generated by mouse events
This commit is contained in:
509
src/ol/pointer/pointereventhandler.js
Normal file
509
src/ol/pointer/pointereventhandler.js
Normal file
@@ -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
|
||||
];
|
||||
Reference in New Issue
Block a user