makes PointerEvent a plain closure class, instead of trying to mimic a mouse event, which was required for the polyfill

This commit is contained in:
tsauerwein
2014-02-19 10:23:30 +01:00
parent 7c8713f79d
commit d772c95ccf
7 changed files with 358 additions and 268 deletions

View File

@@ -80,7 +80,7 @@ ol.interaction.PointerInteraction.isTouchEvent_ = function(mapBrowserEvent) {
ol.interaction.PointerInteraction.prototype.updateTrackedTouches_ =
function(mapBrowserEvent) {
if (ol.interaction.PointerInteraction.isTouchEvent_(mapBrowserEvent)) {
var event = mapBrowserEvent.originalEvent;
var event = mapBrowserEvent.pointerEvent;
if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.POINTERUP) {
delete this.trackedTouches_[event.pointerId];

View File

@@ -8,10 +8,12 @@ goog.require('goog.events');
goog.require('goog.events.BrowserEvent');
goog.require('goog.events.EventTarget');
goog.require('goog.events.EventType');
goog.require('goog.object');
goog.require('ol.Coordinate');
goog.require('ol.MapEvent');
goog.require('ol.Pixel');
goog.require('ol.pointer.PointerEvent');
goog.require('ol.pointer.PointerEventHandler');
@@ -81,6 +83,30 @@ ol.MapBrowserEvent.prototype.stopPropagation = function() {
/**
* @constructor
* @extends {ol.MapBrowserEvent}
* @param {string} type Event type.
* @param {ol.Map} map Map.
* @param {ol.pointer.PointerEvent} pointerEvent Pointer event.
* @param {?ol.FrameState=} opt_frameState Frame state.
* @todo stability experimental
*/
ol.MapBrowserPointerEvent = function(type, map, pointerEvent, opt_frameState) {
goog.base(this, type, map, pointerEvent.browserEvent, opt_frameState);
/**
* @const
* @type {ol.pointer.PointerEvent}
*/
this.pointerEvent = pointerEvent;
};
goog.inherits(ol.MapBrowserPointerEvent, ol.MapBrowserEvent);
/**
* @param {ol.Map} map The map with the viewport to listen to events on.
* @constructor
@@ -121,6 +147,10 @@ ol.MapBrowserEventHandler = function(map) {
*/
this.pointerdownListenerKey_ = null;
/**
* @type {ol.pointer.PointerEvent}
* @private
*/
this.down_ = null;
var element = this.map_.getViewport();
@@ -147,7 +177,7 @@ goog.inherits(ol.MapBrowserEventHandler, goog.events.EventTarget);
/**
* Get the last "down" type event. This will be set on mousedown,
* touchstart, and pointerdown.
* @return {goog.events.BrowserEvent} The most recent "down" type event (or null
* @return {ol.pointer.PointerEvent} The most recent "down" type event (or null
* if none have occurred).
*/
ol.MapBrowserEventHandler.prototype.getDown = function() {
@@ -156,41 +186,25 @@ ol.MapBrowserEventHandler.prototype.getDown = function() {
/**
* @param {goog.events.BrowserEvent} browserEvent Browser event.
* @param {ol.pointer.PointerEvent} pointerEvent Pointer event.
* @private
*/
ol.MapBrowserEventHandler.prototype.emulateClick_ = function(browserEvent) {
ol.MapBrowserEventHandler.prototype.emulateClick_ = function(pointerEvent) {
if (this.clickTimeoutId_ !== 0) {
// double-click
goog.global.clearTimeout(this.clickTimeoutId_);
this.clickTimeoutId_ = 0;
var newEvent = new ol.MapBrowserEvent(
ol.MapBrowserEvent.EventType.DBLCLICK, this.map_, browserEvent);
var newEvent = new ol.MapBrowserPointerEvent(
ol.MapBrowserEvent.EventType.DBLCLICK, this.map_, pointerEvent);
this.dispatchEvent(newEvent);
} else {
// click
if (ol.LEGACY_IE_SUPPORT && ol.IS_LEGACY_IE) {
// In IE 7-8, referring to the original event object after the current
// call stack causes "member not found" exceptions, such as in the timeout
// we use here.
var ev = /** @type {Event} */ (
goog.object.clone(browserEvent.getBrowserEvent()));
this.clickTimeoutId_ = goog.global.setTimeout(goog.bind(function() {
this.clickTimeoutId_ = 0;
var newEvent = new ol.MapBrowserEvent(
ol.MapBrowserEvent.EventType.SINGLECLICK, this.map_,
new goog.events.BrowserEvent(ev, browserEvent.currentTarget));
this.dispatchEvent(newEvent);
}, this), 250);
} else {
this.clickTimeoutId_ = goog.global.setTimeout(goog.bind(function() {
this.clickTimeoutId_ = 0;
var newEvent = new ol.MapBrowserEvent(
ol.MapBrowserEvent.EventType.SINGLECLICK, this.map_, browserEvent);
this.dispatchEvent(newEvent);
}, this), 250);
}
this.clickTimeoutId_ = goog.global.setTimeout(goog.bind(function() {
this.clickTimeoutId_ = 0;
var newEvent = new ol.MapBrowserPointerEvent(
ol.MapBrowserEvent.EventType.SINGLECLICK, this.map_, pointerEvent);
this.dispatchEvent(newEvent);
}, this), 250);
}
};
@@ -198,12 +212,12 @@ ol.MapBrowserEventHandler.prototype.emulateClick_ = function(browserEvent) {
/**
* Keeps track on how many pointers are currently active.
*
* @param {goog.events.BrowserEvent} browserEvent Browser event.
* @param {ol.pointer.PointerEvent} pointerEvent Pointer event.
* @private
*/
ol.MapBrowserEventHandler.prototype.updateActivePointers_ =
function(browserEvent) {
var event = browserEvent.getBrowserEvent();
function(pointerEvent) {
var event = pointerEvent;
if (event.type == ol.MapBrowserEvent.EventType.POINTERUP ||
event.type == ol.MapBrowserEvent.EventType.POINTERCANCEL) {
@@ -216,13 +230,13 @@ ol.MapBrowserEventHandler.prototype.updateActivePointers_ =
/**
* @param {goog.events.BrowserEvent} browserEvent Browser event.
* @param {ol.pointer.PointerEvent} pointerEvent Pointer event.
* @private
*/
ol.MapBrowserEventHandler.prototype.handlePointerUp_ = function(browserEvent) {
this.updateActivePointers_(browserEvent);
var newEvent = new ol.MapBrowserEvent(
ol.MapBrowserEvent.EventType.POINTERUP, this.map_, browserEvent);
ol.MapBrowserEventHandler.prototype.handlePointerUp_ = function(pointerEvent) {
this.updateActivePointers_(pointerEvent);
var newEvent = new ol.MapBrowserPointerEvent(
ol.MapBrowserEvent.EventType.POINTERUP, this.map_, pointerEvent);
this.dispatchEvent(newEvent);
if (this.activePointers_ <= 0) {
@@ -240,7 +254,7 @@ ol.MapBrowserEventHandler.prototype.handlePointerUp_ = function(browserEvent) {
// 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()) {
if (!this.dragged_ && pointerEvent.button == 0) {
goog.asserts.assert(!goog.isNull(this.down_));
this.emulateClick_(this.down_);
}
@@ -248,17 +262,17 @@ ol.MapBrowserEventHandler.prototype.handlePointerUp_ = function(browserEvent) {
/**
* @param {goog.events.BrowserEvent} browserEvent Browser event.
* @param {ol.pointer.PointerEvent} pointerEvent Pointer event.
* @private
*/
ol.MapBrowserEventHandler.prototype.handlePointerDown_ =
function(browserEvent) {
this.updateActivePointers_(browserEvent);
var newEvent = new ol.MapBrowserEvent(
ol.MapBrowserEvent.EventType.POINTERDOWN, this.map_, browserEvent);
function(pointerEvent) {
this.updateActivePointers_(pointerEvent);
var newEvent = new ol.MapBrowserPointerEvent(
ol.MapBrowserEvent.EventType.POINTERDOWN, this.map_, pointerEvent);
this.dispatchEvent(newEvent);
this.down_ = browserEvent;
this.down_ = pointerEvent;
this.dragged_ = false;
if (goog.isNull(this.dragListenerKeys_)) {
@@ -278,26 +292,26 @@ ol.MapBrowserEventHandler.prototype.handlePointerDown_ =
// FIXME check if/when this is necessary
// prevent context menu
browserEvent.preventDefault();
pointerEvent.preventDefault();
};
/**
* @param {goog.events.BrowserEvent} browserEvent Browser event.
* @param {ol.pointer.PointerEvent} pointerEvent Pointer event.
* @private
*/
ol.MapBrowserEventHandler.prototype.handlePointerMove_ =
function(browserEvent) {
function(pointerEvent) {
// 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) {
if (pointerEvent.clientX != this.down_.clientX ||
pointerEvent.clientY != this.down_.clientY) {
this.dragged_ = true;
var newEvent = new ol.MapBrowserEvent(
ol.MapBrowserEvent.EventType.POINTERMOVE, this.map_, browserEvent);
var newEvent = new ol.MapBrowserPointerEvent(
ol.MapBrowserEvent.EventType.POINTERMOVE, this.map_, pointerEvent);
this.dispatchEvent(newEvent);
}
@@ -305,7 +319,7 @@ ol.MapBrowserEventHandler.prototype.handlePointerMove_ =
// 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();
pointerEvent.preventDefault();
};

View File

@@ -154,7 +154,7 @@ ol.pointer.MouseSource.prototype.isEventSimulatedFromTouch_ =
* @return {Object}
*/
ol.pointer.MouseSource.prototype.prepareEvent_ = function(inEvent) {
var e = this.dispatcher.cloneEvent(inEvent.getBrowserEvent());
var e = this.dispatcher.cloneEvent(inEvent, inEvent.getBrowserEvent());
// forward mouse preventDefault
var pd = e.preventDefault;
@@ -186,7 +186,7 @@ ol.pointer.MouseSource.prototype.mousedown = function(inEvent) {
}
var e = this.prepareEvent_(inEvent);
this.pointerMap.set(this.POINTER_ID, inEvent);
this.dispatcher.down(e);
this.dispatcher.down(e, inEvent);
}
};
@@ -199,7 +199,7 @@ ol.pointer.MouseSource.prototype.mousedown = function(inEvent) {
ol.pointer.MouseSource.prototype.mousemove = function(inEvent) {
if (!this.isEventSimulatedFromTouch_(inEvent)) {
var e = this.prepareEvent_(inEvent);
this.dispatcher.move(e);
this.dispatcher.move(e, inEvent);
}
};
@@ -215,7 +215,7 @@ ol.pointer.MouseSource.prototype.mouseup = function(inEvent) {
if (p && p.button === inEvent.button) {
var e = this.prepareEvent_(inEvent);
this.dispatcher.up(e);
this.dispatcher.up(e, inEvent);
this.cleanupMouse();
}
}
@@ -230,7 +230,7 @@ ol.pointer.MouseSource.prototype.mouseup = function(inEvent) {
ol.pointer.MouseSource.prototype.mouseover = function(inEvent) {
if (!this.isEventSimulatedFromTouch_(inEvent)) {
var e = this.prepareEvent_(inEvent);
this.dispatcher.enterOver(e);
this.dispatcher.enterOver(e, inEvent);
}
};
@@ -243,7 +243,7 @@ ol.pointer.MouseSource.prototype.mouseover = function(inEvent) {
ol.pointer.MouseSource.prototype.mouseout = function(inEvent) {
if (!this.isEventSimulatedFromTouch_(inEvent)) {
var e = this.prepareEvent_(inEvent);
this.dispatcher.leaveOut(e);
this.dispatcher.leaveOut(e, inEvent);
}
};
@@ -255,7 +255,7 @@ ol.pointer.MouseSource.prototype.mouseout = function(inEvent) {
*/
ol.pointer.MouseSource.prototype.cancel = function(inEvent) {
var e = this.prepareEvent_(inEvent);
this.dispatcher.cancel(e);
this.dispatcher.cancel(e, inEvent);
this.cleanupMouse();
};

View File

@@ -135,7 +135,7 @@ ol.pointer.MsSource.prototype.hasBitmapType = function() {
ol.pointer.MsSource.prototype.prepareEvent_ = function(inEvent) {
var e = inEvent;
if (this.HAS_BITMAP_TYPE) {
e = this.dispatcher.cloneEvent(inEvent.getBrowserEvent());
e = this.dispatcher.cloneEvent(inEvent, inEvent.getBrowserEvent());
e.pointerType = this.POINTER_TYPES[inEvent.pointerType];
}
@@ -160,7 +160,7 @@ ol.pointer.MsSource.prototype.cleanup = function(pointerId) {
ol.pointer.MsSource.prototype.msPointerDown = function(inEvent) {
this.pointerMap.set(inEvent.pointerId, inEvent);
var e = this.prepareEvent_(inEvent);
this.dispatcher.down(e);
this.dispatcher.down(e, inEvent);
};
@@ -171,7 +171,7 @@ ol.pointer.MsSource.prototype.msPointerDown = function(inEvent) {
*/
ol.pointer.MsSource.prototype.msPointerMove = function(inEvent) {
var e = this.prepareEvent_(inEvent);
this.dispatcher.move(e);
this.dispatcher.move(e, inEvent);
};
@@ -182,7 +182,7 @@ ol.pointer.MsSource.prototype.msPointerMove = function(inEvent) {
*/
ol.pointer.MsSource.prototype.msPointerUp = function(inEvent) {
var e = this.prepareEvent_(inEvent);
this.dispatcher.up(e);
this.dispatcher.up(e, inEvent);
this.cleanup(inEvent.pointerId);
};
@@ -194,7 +194,7 @@ ol.pointer.MsSource.prototype.msPointerUp = function(inEvent) {
*/
ol.pointer.MsSource.prototype.msPointerOut = function(inEvent) {
var e = this.prepareEvent_(inEvent);
this.dispatcher.leaveOut(e);
this.dispatcher.leaveOut(e, inEvent);
};
@@ -205,7 +205,7 @@ ol.pointer.MsSource.prototype.msPointerOut = function(inEvent) {
*/
ol.pointer.MsSource.prototype.msPointerOver = function(inEvent) {
var e = this.prepareEvent_(inEvent);
this.dispatcher.enterOver(e);
this.dispatcher.enterOver(e, inEvent);
};
@@ -216,7 +216,7 @@ ol.pointer.MsSource.prototype.msPointerOver = function(inEvent) {
*/
ol.pointer.MsSource.prototype.msPointerCancel = function(inEvent) {
var e = this.prepareEvent_(inEvent);
this.dispatcher.cancel(e);
this.dispatcher.cancel(e, inEvent);
this.cleanup(inEvent.pointerId);
};
@@ -227,7 +227,8 @@ ol.pointer.MsSource.prototype.msPointerCancel = function(inEvent) {
* @param {goog.events.BrowserEvent} inEvent
*/
ol.pointer.MsSource.prototype.msLostPointerCapture = function(inEvent) {
var e = this.dispatcher.makeEvent('lostpointercapture', inEvent);
var e = this.dispatcher.makeEvent('lostpointercapture',
inEvent.getBrowserEvent(), inEvent);
this.dispatcher.dispatchEvent(e);
};
@@ -238,6 +239,7 @@ ol.pointer.MsSource.prototype.msLostPointerCapture = function(inEvent) {
* @param {goog.events.BrowserEvent} inEvent
*/
ol.pointer.MsSource.prototype.msGotPointerCapture = function(inEvent) {
var e = this.dispatcher.makeEvent('gotpointercapture', inEvent);
var e = this.dispatcher.makeEvent('gotpointercapture',
inEvent.getBrowserEvent(), inEvent);
this.dispatcher.dispatchEvent(e);
};

View File

@@ -31,28 +31,126 @@
goog.provide('ol.pointer.PointerEvent');
//goog.require('goog.events.Event');
goog.require('goog.events');
goog.require('goog.events.Event');
/**
* This is the constructor for new PointerEvents.
* A class for pointer events.
*
* 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.
* This class is used as an abstraction for mouse events,
* touch events and even native pointer events.
*
* @constructor
* @extends {Event}
* @param {string} inType The type of the event to create.
* @param {Object.<string, ?>=} opt_inDict An optional dictionary of
* @extends {goog.events.Event}
* @param {string} type The type of the event to create.
* @param {goog.events.BrowserEvent} browserEvent
* @param {Object.<string, ?>=} opt_eventDict An optional dictionary of
* initial event properties.
*/
ol.pointer.PointerEvent = function(inType, opt_inDict) {
opt_inDict = opt_inDict || {};
ol.pointer.PointerEvent = function(type, browserEvent, opt_eventDict) {
goog.base(this, type);
/**
* @const
* @type {goog.events.BrowserEvent}
*/
this.browserEvent = browserEvent;
/**
* @const
* @type {Event}
*/
this.originalEvent = browserEvent.getBrowserEvent();
var eventDict = goog.isDef(opt_eventDict) ? opt_eventDict : {};
this.buttons = this.getButtons_(eventDict);
this.pressure = this.getPressure_(eventDict, this.buttons);
// MouseEvent related properties
this.bubbles = this.getValue_('bubbles', eventDict);
this.cancelable = this.getValue_('cancelable', eventDict);
this.view = this.getValue_('view', eventDict);
this.detail = this.getValue_('detail', eventDict);
this.screenX = this.getValue_('screenX', eventDict);
this.screenY = this.getValue_('screenY', eventDict);
this.clientX = this.getValue_('clientX', eventDict);
this.clientY = this.getValue_('clientY', eventDict);
this.ctrlKey = this.getValue_('ctrlKey', eventDict);
this.altKey = this.getValue_('altKey', eventDict);
this.shiftKey = this.getValue_('shiftKey', eventDict);
this.metaKey = this.getValue_('metaKey', eventDict);
this.button = this.getValue_('button', eventDict);
this.relatedTarget = this.getValue_('relatedTarget', eventDict);
// PointerEvent related properties
this.pointerId = this.getValueOr_('pointerId', 0, eventDict);
this.width = this.getValueOr_('width', 0, eventDict);
this.height = this.getValueOr_('height', 0, eventDict);
this.tiltX = this.getValueOr_('tiltX', 0, eventDict);
this.tiltY = this.getValueOr_('tiltY', 0, eventDict);
this.pointerType = this.getValueOr_('pointerType', '', eventDict);
this.hwTimestamp = this.getValueOr_('hwTimestamp', 0, eventDict);
this.isPrimary = this.getValueOr_('isPrimary', false, eventDict);
};
goog.inherits(ol.pointer.PointerEvent, goog.events.Event);
/**
* @private
* @param {string} key
* @param {Object.<string, ?>} eventDict
* @return {*}
*/
ol.pointer.PointerEvent.prototype.getValue_ = function(key, eventDict) {
return goog.isDefAndNotNull(eventDict[key]) ?
eventDict[key] :
ol.pointer.PointerEvent.MOUSE_DEFAULTS['relatedTarget'];
};
/**
* @private
* @param {string} key
* @param {*} defaultValue
* @param {Object.<string, ?>} eventDict
* @return {*}
*/
ol.pointer.PointerEvent.prototype.getValueOr_ =
function(key, defaultValue, eventDict) {
return goog.isDefAndNotNull(eventDict[key]) ?
eventDict[key] : defaultValue;
};
/**
* @private
* @param {Object.<string, ?>} eventDict
* @return {number}
*/
ol.pointer.PointerEvent.prototype.getButtons_ = function(eventDict) {
// 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
@@ -75,85 +173,38 @@ ol.pointer.PointerEvent = function(inType, opt_inDict) {
//
// 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;
if (eventDict.buttons || ol.pointer.PointerEvent.HAS_BUTTONS) {
buttons = eventDict.buttons;
} else {
switch (opt_inDict.which) {
switch (eventDict.which) {
case 1: buttons = 1; break;
case 2: buttons = 4; break;
case 3: buttons = 2; break;
default: buttons = 0;
}
}
return buttons;
};
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});
}
/**
* @private
* @param {Object.<string, ?>} eventDict
* @param {number} buttons
* @return {number}
*/
ol.pointer.PointerEvent.prototype.getPressure_ = function(eventDict, buttons) {
// 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;
if (eventDict.pressure) {
pressure = eventDict.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;
return pressure;
};
// PointerEvent extends MouseEvent
ol.pointer.PointerEvent.prototype = Object.create(MouseEvent.prototype);
// test for DOM Level 4 Events
/**
* Does the browser support the `MouseEvent` type?
@@ -184,8 +235,8 @@ ol.pointer.PointerEvent.checkNewMouseEvent();
/**
* Warning is suppressed because Closure thinks MouseEvent
* has no arguments.
* Warning is suppressed because Closure thinks the MouseEvent
* constructor takes no arguments.
* @param {string} inType The type of the event to create.
* @param {Object} inDict An dictionary of initial event properties.
* @return {MouseEvent}
@@ -196,44 +247,22 @@ ol.pointer.PointerEvent.createMouseEvent = function(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
];
ol.pointer.PointerEvent.MOUSE_DEFAULTS = {
'bubbles': false,
'cancelable': false,
'view': null,
'detail': null,
'screenX': 0,
'screenY': 0,
'clientX': 0,
'clientY': 0,
'ctrlKey': false,
'altKey': false,
'shiftKey': false,
'metaKey': false,
'button': 0,
'relatedTarget': null
};

View File

@@ -164,14 +164,6 @@ ol.pointer.PointerEventHandler.prototype.registerSource =
};
/**
* @suppress {undefinedVars}
*/
ol.pointer.PointerEventHandler.prototype.log = function(obj) {
console.log(obj);
};
/**
* Set up the events for all registered event sources.
* @private
@@ -324,22 +316,27 @@ ol.pointer.PointerEventHandler.prototype.removeEvent = function(
/**
* Returns a snapshot of inEvent, with writable properties.
*
* @param {goog.events.BrowserEvent} browserEvent Browser event.
* @param {Event|Touch} 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) {
ol.pointer.PointerEventHandler.prototype.cloneEvent =
function(browserEvent, 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];
eventCopy[p] =
browserEvent[p] ||
inEvent[p] ||
ol.pointer.CLONE_DEFAULTS[i];
}
// keep the semantics of preventDefault
if (inEvent.preventDefault) {
if (browserEvent.preventDefault) {
eventCopy.preventDefault = function() {
inEvent.preventDefault();
browserEvent.preventDefault();
};
}
@@ -352,100 +349,124 @@ ol.pointer.PointerEventHandler.prototype.cloneEvent = function(inEvent) {
/**
* Triggers a 'pointerdown' event.
* @param {Object} inEvent
* @param {Object} pointerEventData
* @param {goog.events.BrowserEvent } browserEvent
*/
ol.pointer.PointerEventHandler.prototype.down = function(inEvent) {
this.fireEvent('pointerdown', inEvent);
ol.pointer.PointerEventHandler.prototype.down =
function(pointerEventData, browserEvent) {
this.fireEvent('pointerdown', pointerEventData, browserEvent);
};
/**
* Triggers a 'pointermove' event.
* @param {Object} inEvent
* @param {Object} pointerEventData
* @param {goog.events.BrowserEvent } browserEvent
*/
ol.pointer.PointerEventHandler.prototype.move = function(inEvent) {
this.fireEvent('pointermove', inEvent);
ol.pointer.PointerEventHandler.prototype.move =
function(pointerEventData, browserEvent) {
this.fireEvent('pointermove', pointerEventData, browserEvent);
};
/**
* Triggers a 'pointerup' event.
* @param {Object} inEvent
* @param {Object} pointerEventData
* @param {goog.events.BrowserEvent } browserEvent
*/
ol.pointer.PointerEventHandler.prototype.up = function(inEvent) {
this.fireEvent('pointerup', inEvent);
ol.pointer.PointerEventHandler.prototype.up =
function(pointerEventData, browserEvent) {
this.fireEvent('pointerup', pointerEventData, browserEvent);
};
/**
* Triggers a 'pointerenter' event.
* @param {Object} inEvent
* @param {Object} pointerEventData
* @param {goog.events.BrowserEvent } browserEvent
*/
ol.pointer.PointerEventHandler.prototype.enter = function(inEvent) {
inEvent.bubbles = false;
this.fireEvent('pointerenter', inEvent);
ol.pointer.PointerEventHandler.prototype.enter =
function(pointerEventData, browserEvent) {
pointerEventData.bubbles = false;
this.fireEvent('pointerenter', pointerEventData, browserEvent);
};
/**
* Triggers a 'pointerleave' event.
* @param {Object} inEvent
* @param {Object} pointerEventData
* @param {goog.events.BrowserEvent } browserEvent
*/
ol.pointer.PointerEventHandler.prototype.leave = function(inEvent) {
inEvent.bubbles = false;
this.fireEvent('pointerleave', inEvent);
ol.pointer.PointerEventHandler.prototype.leave =
function(pointerEventData, browserEvent) {
pointerEventData.bubbles = false;
this.fireEvent('pointerleave', pointerEventData, browserEvent);
};
/**
* Triggers a 'pointerover' event.
* @param {Object} inEvent
* @param {Object} pointerEventData
* @param {goog.events.BrowserEvent } browserEvent
*/
ol.pointer.PointerEventHandler.prototype.over = function(inEvent) {
inEvent.bubbles = true;
this.fireEvent('pointerover', inEvent);
ol.pointer.PointerEventHandler.prototype.over =
function(pointerEventData, browserEvent) {
pointerEventData.bubbles = true;
this.fireEvent('pointerover', pointerEventData, browserEvent);
};
/**
* Triggers a 'pointerout' event.
* @param {Object} inEvent
* @param {Object} pointerEventData
* @param {goog.events.BrowserEvent } browserEvent
*/
ol.pointer.PointerEventHandler.prototype.out = function(inEvent) {
inEvent.bubbles = true;
this.fireEvent('pointerout', inEvent);
ol.pointer.PointerEventHandler.prototype.out =
function(pointerEventData, browserEvent) {
pointerEventData.bubbles = true;
this.fireEvent('pointerout', pointerEventData, browserEvent);
};
/**
* Triggers a 'pointercancel' event.
* @param {Object} inEvent
* @param {Object} pointerEventData
* @param {goog.events.BrowserEvent } browserEvent
*/
ol.pointer.PointerEventHandler.prototype.cancel = function(inEvent) {
this.fireEvent('pointercancel', inEvent);
ol.pointer.PointerEventHandler.prototype.cancel =
function(pointerEventData, browserEvent) {
this.fireEvent('pointercancel', pointerEventData, browserEvent);
};
/**
* Triggers a combination of 'pointerout' and 'pointerleave' events.
* @param {Object} inEvent
* @param {Object} pointerEventData
* @param {goog.events.BrowserEvent } browserEvent
*/
ol.pointer.PointerEventHandler.prototype.leaveOut = function(inEvent) {
this.out(inEvent);
if (!this.contains_(inEvent.target, inEvent.relatedTarget)) {
this.leave(inEvent);
ol.pointer.PointerEventHandler.prototype.leaveOut =
function(pointerEventData, browserEvent) {
this.out(pointerEventData, browserEvent);
if (!this.contains_(
pointerEventData.target,
pointerEventData.relatedTarget)) {
this.leave(pointerEventData, browserEvent);
}
};
/**
* Triggers a combination of 'pointerover' and 'pointerevents' events.
* @param {Object} inEvent
* @param {Object} pointerEventData
* @param {goog.events.BrowserEvent } browserEvent
*/
ol.pointer.PointerEventHandler.prototype.enterOver = function(inEvent) {
this.over(inEvent);
if (!this.contains_(inEvent.target, inEvent.relatedTarget)) {
this.enter(inEvent);
ol.pointer.PointerEventHandler.prototype.enterOver =
function(pointerEventData, browserEvent) {
this.over(pointerEventData, browserEvent);
if (!this.contains_(
pointerEventData.target,
pointerEventData.relatedTarget)) {
this.enter(pointerEventData, browserEvent);
}
};
@@ -469,18 +490,20 @@ ol.pointer.PointerEventHandler.prototype.contains_ =
* `inEvent`.
*
* @param {string} inType A string representing the type of event to create.
* @param {Object} inEvent A platform event with a target.
* @param {Object} pointerEventData
* @param {goog.events.BrowserEvent } browserEvent
* @return {ol.pointer.PointerEvent} A PointerEvent of type `inType`.
*/
ol.pointer.PointerEventHandler.prototype.makeEvent = function(inType, inEvent) {
ol.pointer.PointerEventHandler.prototype.makeEvent =
function(inType, pointerEventData, browserEvent) {
// relatedTarget must be null if pointer is captured
if (this.captureInfo) {
inEvent.relatedTarget = null;
pointerEventData.relatedTarget = null;
}
var e = new ol.pointer.PointerEvent(inType, inEvent);
if (inEvent.preventDefault) {
e.preventDefault = inEvent.preventDefault;
var e = new ol.pointer.PointerEvent(inType, browserEvent, pointerEventData);
if (pointerEventData.preventDefault) {
e.preventDefault = pointerEventData.preventDefault;
}
return e;
@@ -490,12 +513,13 @@ ol.pointer.PointerEventHandler.prototype.makeEvent = function(inType, inEvent) {
/**
* 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.
* @param {Object} pointerEventData
* @param {goog.events.BrowserEvent } browserEvent
*/
ol.pointer.PointerEventHandler.prototype.fireEvent = function(inType, inEvent) {
var e = this.makeEvent(inType, inEvent);
var browserEvent = new goog.events.BrowserEvent(e);
this.dispatchEvent(browserEvent);
ol.pointer.PointerEventHandler.prototype.fireEvent =
function(inType, pointerEventData, browserEvent) {
var e = this.makeEvent(inType, pointerEventData, browserEvent);
this.dispatchEvent(e);
};
@@ -505,7 +529,9 @@ ol.pointer.PointerEventHandler.prototype.fireEvent = function(inType, inEvent) {
*/
ol.pointer.PointerEventHandler.prototype.fireNativeEvent =
function(nativeEvent) {
this.dispatchEvent(nativeEvent);
var e = this.makeEvent(nativeEvent.type, nativeEvent.getBrowserEvent(),
nativeEvent);
this.dispatchEvent(e);
};

View File

@@ -30,20 +30,30 @@
goog.provide('ol.pointer.TouchSource');
goog.require('goog.array');
goog.require('ol.pointer.EventSource');
/**
* @constructor
* @param {ol.pointer.PointerEventHandler} dispatcher
* @param {ol.pointer.MouseSource} mouseSource
* @constructor
* @extends {ol.pointer.EventSource}
*/
ol.pointer.TouchSource = function(dispatcher, mouseSource) {
goog.base(this, dispatcher);
/**
* @const
* @type {goog.structs.Map}
*/
this.pointerMap = dispatcher.pointerMap;
/**
* @const
* @type {ol.pointer.MouseSource}
*/
this.mouseSource = mouseSource;
// This should be long enough to ignore compat mouse events made by touch
@@ -144,11 +154,13 @@ ol.pointer.TouchSource.prototype.cancelResetClickCount_ = function() {
/**
* @private
* @param {goog.events.BrowserEvent} browserEvent Browser event
* @param {Touch} inTouch Touch event
* @return {Object}
*/
ol.pointer.TouchSource.prototype.touchToPointer_ = function(inTouch) {
var e = this.dispatcher.cloneEvent(inTouch);
ol.pointer.TouchSource.prototype.touchToPointer_ =
function(browserEvent, inTouch) {
var e = this.dispatcher.cloneEvent(browserEvent, inTouch);
// Spec specifies that pointerId 1 is reserved for Mouse.
// Touch identifiers can start at 0.
// Add 2 to the touch identifier for compatibility.
@@ -173,12 +185,13 @@ ol.pointer.TouchSource.prototype.touchToPointer_ = function(inTouch) {
/**
* @private
* @param {goog.events.BrowserEvent} inEvent Touch event
* @param {function(Object)} inFunction
* @param {function(goog.events.BrowserEvent, Object)} inFunction
*/
ol.pointer.TouchSource.prototype.processTouches_ =
function(inEvent, inFunction) {
var tl = inEvent.getBrowserEvent().changedTouches;
var pointers = goog.array.map(tl, this.touchToPointer_, this);
var pointers = goog.array.map(tl,
goog.partial(this.touchToPointer_, inEvent), this);
// forward touch preventDefaults
pointers.forEach(function(p) {
p.preventDefault = function() {
@@ -186,7 +199,7 @@ ol.pointer.TouchSource.prototype.processTouches_ =
inEvent.preventDefault();
};
}, this);
pointers.forEach(inFunction, this);
pointers.forEach(goog.partial(inFunction, inEvent), this);
};
@@ -232,7 +245,7 @@ ol.pointer.TouchSource.prototype.vacuumTouches_ = function(inEvent) {
d.push(this.touchToPointer_(p));
}
}, this);
d.forEach(this.cancelOut_, this);
d.forEach(goog.partial(this.cancelOut_, inEvent), this);
}
};
@@ -267,17 +280,18 @@ ol.pointer.TouchSource.prototype.touchstart = function(inEvent) {
/**
* @private
* @param {goog.events.BrowserEvent} browserEvent
* @param {Object} inPointer
*/
ol.pointer.TouchSource.prototype.overDown_ = function(inPointer) {
ol.pointer.TouchSource.prototype.overDown_ = function(browserEvent, inPointer) {
this.pointerMap.set(inPointer.pointerId, {
target: inPointer.target,
out: inPointer,
outTarget: inPointer.target
});
this.dispatcher.over(inPointer);
this.dispatcher.enter(inPointer);
this.dispatcher.down(inPointer);
this.dispatcher.over(inPointer, browserEvent);
this.dispatcher.enter(inPointer, browserEvent);
this.dispatcher.down(inPointer, browserEvent);
};
@@ -294,9 +308,11 @@ ol.pointer.TouchSource.prototype.touchmove = function(inEvent) {
/**
* @private
* @param {goog.events.BrowserEvent} browserEvent
* @param {Object} inPointer
*/
ol.pointer.TouchSource.prototype.moveOverOut_ = function(inPointer) {
ol.pointer.TouchSource.prototype.moveOverOut_ =
function(browserEvent, inPointer) {
var event = inPointer;
var pointer = this.pointerMap.get(event.pointerId);
// a finger drifted off the screen, ignore it
@@ -305,20 +321,20 @@ ol.pointer.TouchSource.prototype.moveOverOut_ = function(inPointer) {
}
var outEvent = pointer.out;
var outTarget = pointer.outTarget;
this.dispatcher.move(event);
this.dispatcher.move(event, browserEvent);
if (outEvent && outTarget !== event.target) {
outEvent.relatedTarget = event.target;
event.relatedTarget = outTarget;
// recover from retargeting by shadow
outEvent.target = outTarget;
if (event.target) {
this.dispatcher.leaveOut(outEvent);
this.dispatcher.enterOver(event);
this.dispatcher.leaveOut(outEvent, browserEvent);
this.dispatcher.enterOver(event, browserEvent);
} else {
// clean up case when finger leaves the screen
event.target = outTarget;
event.relatedTarget = null;
this.cancelOut_(event);
this.cancelOut_(browserEvent, event);
}
}
pointer.out = event;
@@ -340,12 +356,13 @@ ol.pointer.TouchSource.prototype.touchend = function(inEvent) {
/**
* @private
* @param {goog.events.BrowserEvent} browserEvent
* @param {Object} inPointer
*/
ol.pointer.TouchSource.prototype.upOut_ = function(inPointer) {
this.dispatcher.up(inPointer);
this.dispatcher.out(inPointer);
this.dispatcher.leave(inPointer);
ol.pointer.TouchSource.prototype.upOut_ = function(browserEvent, inPointer) {
this.dispatcher.up(inPointer, browserEvent);
this.dispatcher.out(inPointer, browserEvent);
this.dispatcher.leave(inPointer, browserEvent);
this.cleanUpPointer_(inPointer);
};
@@ -363,12 +380,14 @@ ol.pointer.TouchSource.prototype.touchcancel = function(inEvent) {
/**
* @private
* @param {goog.events.BrowserEvent} browserEvent
* @param {Object} inPointer
*/
ol.pointer.TouchSource.prototype.cancelOut_ = function(inPointer) {
this.dispatcher.cancel(inPointer);
this.dispatcher.out(inPointer);
this.dispatcher.leave(inPointer);
ol.pointer.TouchSource.prototype.cancelOut_ =
function(browserEvent, inPointer) {
this.dispatcher.cancel(inPointer, browserEvent);
this.dispatcher.out(inPointer, browserEvent);
this.dispatcher.leave(inPointer, browserEvent);
this.cleanUpPointer_(inPointer);
};
@@ -384,7 +403,7 @@ ol.pointer.TouchSource.prototype.cleanUpPointer_ = function(inPointer) {
/**
* Orevent synth mouse events from creating pointer events.
* Prevent synth mouse events from creating pointer events.
*
* @private
* @param {goog.events.BrowserEvent} inEvent