From d772c95ccf15d35ab237e7afb47c74134cd95fcd Mon Sep 17 00:00:00 2001 From: tsauerwein Date: Wed, 19 Feb 2014 10:23:30 +0100 Subject: [PATCH] makes `PointerEvent` a plain closure class, instead of trying to mimic a mouse event, which was required for the polyfill --- src/ol/interaction/pointerinteraction.js | 2 +- src/ol/mapbrowserevent.js | 114 +++++----- src/ol/pointer/mousesource.js | 14 +- src/ol/pointer/mssource.js | 20 +- src/ol/pointer/pointerevent.js | 257 +++++++++++++---------- src/ol/pointer/pointereventhandler.js | 150 +++++++------ src/ol/pointer/touchsource.js | 69 +++--- 7 files changed, 358 insertions(+), 268 deletions(-) diff --git a/src/ol/interaction/pointerinteraction.js b/src/ol/interaction/pointerinteraction.js index 559ce021ba..9c0e0dc00b 100644 --- a/src/ol/interaction/pointerinteraction.js +++ b/src/ol/interaction/pointerinteraction.js @@ -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]; diff --git a/src/ol/mapbrowserevent.js b/src/ol/mapbrowserevent.js index ca0d48c774..b49e010a64 100644 --- a/src/ol/mapbrowserevent.js +++ b/src/ol/mapbrowserevent.js @@ -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(); }; diff --git a/src/ol/pointer/mousesource.js b/src/ol/pointer/mousesource.js index 8e8a58f4bc..f23f917fac 100644 --- a/src/ol/pointer/mousesource.js +++ b/src/ol/pointer/mousesource.js @@ -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(); }; diff --git a/src/ol/pointer/mssource.js b/src/ol/pointer/mssource.js index 44d5c686f1..4d5f8d1998 100644 --- a/src/ol/pointer/mssource.js +++ b/src/ol/pointer/mssource.js @@ -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); }; diff --git a/src/ol/pointer/pointerevent.js b/src/ol/pointer/pointerevent.js index 9183afbf84..d25346d90e 100644 --- a/src/ol/pointer/pointerevent.js +++ b/src/ol/pointer/pointerevent.js @@ -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.=} 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.=} 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.} 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.} eventDict + * @return {*} + */ +ol.pointer.PointerEvent.prototype.getValueOr_ = + function(key, defaultValue, eventDict) { + return goog.isDefAndNotNull(eventDict[key]) ? + eventDict[key] : defaultValue; +}; + + +/** + * @private + * @param {Object.} 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.} - */ - 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.} 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.} - */ -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 +}; diff --git a/src/ol/pointer/pointereventhandler.js b/src/ol/pointer/pointereventhandler.js index 4d2bb81ac4..1bde747ac6 100644 --- a/src/ol/pointer/pointereventhandler.js +++ b/src/ol/pointer/pointereventhandler.js @@ -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); }; diff --git a/src/ol/pointer/touchsource.js b/src/ol/pointer/touchsource.js index 4cfc79a220..6328b3f235 100644 --- a/src/ol/pointer/touchsource.js +++ b/src/ol/pointer/touchsource.js @@ -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