diff --git a/package.json b/package.json index 09c385e250..ce4b037095 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ }, "dependencies": { "pbf": "3.2.0", + "pepjs": "^0.5.2", "pixelworks": "1.1.0", "rbush": "^3.0.0" }, diff --git a/src/ol/MapBrowserEventHandler.js b/src/ol/MapBrowserEventHandler.js index 177f124595..13e3021dfe 100644 --- a/src/ol/MapBrowserEventHandler.js +++ b/src/ol/MapBrowserEventHandler.js @@ -1,13 +1,14 @@ /** * @module ol/MapBrowserEventHandler */ + +import 'pepjs'; import {DEVICE_PIXEL_RATIO} from './has.js'; import MapBrowserEventType from './MapBrowserEventType.js'; import MapBrowserPointerEvent from './MapBrowserPointerEvent.js'; import {listen, unlistenByKey} from './events.js'; import EventTarget from './events/Target.js'; import PointerEventType from './pointer/EventType.js'; -import PointerEventHandler from './pointer/PointerEventHandler.js'; class MapBrowserEventHandler extends EventTarget { @@ -54,12 +55,13 @@ class MapBrowserEventHandler extends EventTarget { /** * The most recent "down" type event (or null if none have occurred). * Set on pointerdown. - * @type {import("./pointer/PointerEvent.js").default} + * @type {PointerEvent} * @private */ this.down_ = null; const element = this.map_.getViewport(); + element.setAttribute('touch-action', 'none'); /** * @type {number} @@ -73,29 +75,13 @@ class MapBrowserEventHandler extends EventTarget { */ this.trackedTouches_ = {}; - /** - * Event handler which generates pointer events for - * the viewport element. - * - * @type {PointerEventHandler} - * @private - */ - this.pointerEventHandler_ = new PointerEventHandler(element); - - /** - * Event handler which generates pointer events for - * the document (used when dragging). - * - * @type {PointerEventHandler} - * @private - */ - this.documentPointerEventHandler_ = null; + this.element_ = element; /** * @type {?import("./events.js").EventsKey} * @private */ - this.pointerdownListenerKey_ = listen(this.pointerEventHandler_, + this.pointerdownListenerKey_ = listen(element, PointerEventType.POINTERDOWN, this.handlePointerDown_, this); @@ -103,14 +89,14 @@ class MapBrowserEventHandler extends EventTarget { * @type {?import("./events.js").EventsKey} * @private */ - this.relayedListenerKey_ = listen(this.pointerEventHandler_, + this.relayedListenerKey_ = listen(element, PointerEventType.POINTERMOVE, this.relayEvent_, this); } /** - * @param {import("./pointer/PointerEvent.js").default} pointerEvent Pointer + * @param {PointerEvent} pointerEvent Pointer * event. * @private */ @@ -139,7 +125,7 @@ class MapBrowserEventHandler extends EventTarget { /** * Keeps track on how many pointers are currently active. * - * @param {import("./pointer/PointerEvent.js").default} pointerEvent Pointer + * @param {PointerEvent} pointerEvent Pointer * event. * @private */ @@ -156,7 +142,7 @@ class MapBrowserEventHandler extends EventTarget { } /** - * @param {import("./pointer/PointerEvent.js").default} pointerEvent Pointer + * @param {PointerEvent} pointerEvent Pointer * event. * @private */ @@ -181,13 +167,11 @@ class MapBrowserEventHandler extends EventTarget { this.dragListenerKeys_.length = 0; this.dragging_ = false; this.down_ = null; - this.documentPointerEventHandler_.dispose(); - this.documentPointerEventHandler_ = null; } } /** - * @param {import("./pointer/PointerEvent.js").default} pointerEvent Pointer + * @param {PointerEvent} pointerEvent Pointer * event. * @return {boolean} If the left mouse button was pressed. * @private @@ -197,7 +181,7 @@ class MapBrowserEventHandler extends EventTarget { } /** - * @param {import("./pointer/PointerEvent.js").default} pointerEvent Pointer + * @param {PointerEvent} pointerEvent Pointer * event. * @private */ @@ -210,18 +194,11 @@ class MapBrowserEventHandler extends EventTarget { this.down_ = pointerEvent; if (this.dragListenerKeys_.length === 0) { - /* Set up a pointer event handler on the `document`, - * which is required when the pointer is moved outside - * the viewport when dragging. - */ - this.documentPointerEventHandler_ = - new PointerEventHandler(document); - this.dragListenerKeys_.push( - listen(this.documentPointerEventHandler_, + listen(document, MapBrowserEventType.POINTERMOVE, this.handlePointerMove_, this), - listen(this.documentPointerEventHandler_, + listen(document, MapBrowserEventType.POINTERUP, this.handlePointerUp_, this), /* Note that the listener for `pointercancel is set up on @@ -237,7 +214,7 @@ class MapBrowserEventHandler extends EventTarget { * only receive a `touchcancel` from `pointerEventHandler_`, because it is * only registered there. */ - listen(this.pointerEventHandler_, + listen(this.element_, MapBrowserEventType.POINTERCANCEL, this.handlePointerUp_, this) ); @@ -245,7 +222,7 @@ class MapBrowserEventHandler extends EventTarget { } /** - * @param {import("./pointer/PointerEvent.js").default} pointerEvent Pointer + * @param {PointerEvent} pointerEvent Pointer * event. * @private */ @@ -265,7 +242,7 @@ class MapBrowserEventHandler extends EventTarget { /** * Wrap and relay a pointer event. Note that this requires that the type * string for the MapBrowserPointerEvent matches the PointerEvent type. - * @param {import("./pointer/PointerEvent.js").default} pointerEvent Pointer + * @param {PointerEvent} pointerEvent Pointer * event. * @private */ @@ -276,7 +253,7 @@ class MapBrowserEventHandler extends EventTarget { } /** - * @param {import("./pointer/PointerEvent.js").default} pointerEvent Pointer + * @param {PointerEvent} pointerEvent Pointer * event. * @return {boolean} Is moving. * @private @@ -303,14 +280,7 @@ class MapBrowserEventHandler extends EventTarget { this.dragListenerKeys_.forEach(unlistenByKey); this.dragListenerKeys_.length = 0; - if (this.documentPointerEventHandler_) { - this.documentPointerEventHandler_.dispose(); - this.documentPointerEventHandler_ = null; - } - if (this.pointerEventHandler_) { - this.pointerEventHandler_.dispose(); - this.pointerEventHandler_ = null; - } + this.element_ = null; super.disposeInternal(); } } diff --git a/src/ol/MapBrowserPointerEvent.js b/src/ol/MapBrowserPointerEvent.js index 2fe55ec7d7..3eadb83837 100644 --- a/src/ol/MapBrowserPointerEvent.js +++ b/src/ol/MapBrowserPointerEvent.js @@ -8,17 +8,17 @@ class MapBrowserPointerEvent extends MapBrowserEvent { /** * @param {string} type Event type. * @param {import("./PluggableMap.js").default} map Map. - * @param {import("./pointer/PointerEvent.js").default} pointerEvent Pointer event. + * @param {PointerEvent} pointerEvent Pointer event. * @param {boolean=} opt_dragging Is the map currently being dragged? * @param {?import("./PluggableMap.js").FrameState=} opt_frameState Frame state. */ constructor(type, map, pointerEvent, opt_dragging, opt_frameState) { - super(type, map, pointerEvent.originalEvent, opt_dragging, opt_frameState); + super(type, map, pointerEvent, opt_dragging, opt_frameState); /** * @const - * @type {import("./pointer/PointerEvent.js").default} + * @type {PointerEvent} */ this.pointerEvent = pointerEvent; diff --git a/src/ol/control/ZoomSlider.js b/src/ol/control/ZoomSlider.js index 050cb0d021..c6197bd018 100644 --- a/src/ol/control/ZoomSlider.js +++ b/src/ol/control/ZoomSlider.js @@ -9,7 +9,7 @@ import {stopPropagation} from '../events/Event.js'; import EventType from '../events/EventType.js'; import {clamp} from '../math.js'; import PointerEventType from '../pointer/EventType.js'; -import PointerEventHandler from '../pointer/PointerEventHandler.js'; +import 'pepjs'; /** @@ -135,19 +135,15 @@ class ZoomSlider extends Control { thumbElement.setAttribute('type', 'button'); thumbElement.className = className + '-thumb ' + CLASS_UNSELECTABLE; const containerElement = this.element; + containerElement.setAttribute('touch-action', 'none'); containerElement.className = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL; containerElement.appendChild(thumbElement); - /** - * @type {PointerEventHandler} - * @private - */ - this.dragger_ = new PointerEventHandler(containerElement); - listen(this.dragger_, PointerEventType.POINTERDOWN, + listen(containerElement, PointerEventType.POINTERDOWN, this.handleDraggerStart_, this); - listen(this.dragger_, PointerEventType.POINTERMOVE, + listen(containerElement, PointerEventType.POINTERMOVE, this.handleDraggerDrag_, this); - listen(this.dragger_, PointerEventType.POINTERUP, + listen(containerElement, PointerEventType.POINTERUP, this.handleDraggerEnd_, this); listen(containerElement, EventType.CLICK, this.handleContainerClick_, this); @@ -158,7 +154,6 @@ class ZoomSlider extends Control { * @inheritDoc */ disposeInternal() { - this.dragger_.dispose(); super.disposeInternal(); } @@ -206,7 +201,7 @@ class ZoomSlider extends Control { } /** - * @param {MouseEvent} event The browser event to handle. + * @param {PointerEvent} event The browser event to handle. * @private */ handleContainerClick_(event) { @@ -228,11 +223,11 @@ class ZoomSlider extends Control { /** * Handle dragger start events. - * @param {import("../pointer/PointerEvent.js").default} event The drag event. + * @param {PointerEvent} event The drag event. * @private */ handleDraggerStart_(event) { - if (!this.dragging_ && event.originalEvent.target === this.element.firstElementChild) { + if (!this.dragging_ && event.target === this.element.firstElementChild) { const element = /** @type {HTMLElement} */ (this.element.firstElementChild); this.getMap().getView().beginInteraction(); this.startX_ = event.clientX - parseFloat(element.style.left); @@ -243,9 +238,7 @@ class ZoomSlider extends Control { const drag = this.handleDraggerDrag_; const end = this.handleDraggerEnd_; this.dragListenerKeys_.push( - listen(document, EventType.MOUSEMOVE, drag, this), listen(document, PointerEventType.POINTERMOVE, drag, this), - listen(document, EventType.MOUSEUP, end, this), listen(document, PointerEventType.POINTERUP, end, this) ); } @@ -255,7 +248,7 @@ class ZoomSlider extends Control { /** * Handle dragger drag events. * - * @param {import("../pointer/PointerEvent.js").default} event The drag event. + * @param {PointerEvent} event The drag event. * @private */ handleDraggerDrag_(event) { @@ -270,7 +263,7 @@ class ZoomSlider extends Control { /** * Handle dragger end events. - * @param {import("../pointer/PointerEvent.js").default} event The drag event. + * @param {PointerEvent} event The drag event. * @private */ handleDraggerEnd_(event) { diff --git a/src/ol/events/Target.js b/src/ol/events/Target.js index 23769dbe8d..2f7fa68f7c 100644 --- a/src/ol/events/Target.js +++ b/src/ol/events/Target.js @@ -82,7 +82,9 @@ class Target extends Disposable { dispatchEvent(event) { const evt = typeof event === 'string' ? new Event(event) : event; const type = evt.type; - evt.target = this; + if (!evt.target) { + evt.target = this; + } const listeners = this.listeners_[type]; let propagate; if (listeners) { diff --git a/src/ol/events/condition.js b/src/ol/events/condition.js index ca391900f5..12e20e9d39 100644 --- a/src/ol/events/condition.js +++ b/src/ol/events/condition.js @@ -207,7 +207,7 @@ export const shiftKeyOnly = function(mapBrowserEvent) { * @api */ export const targetNotEditable = function(mapBrowserEvent) { - const target = mapBrowserEvent.originalEvent.target; + const target = mapBrowserEvent.target; const tagName = /** @type {Element} */ (target).tagName; return ( tagName !== 'INPUT' && diff --git a/src/ol/interaction/Draw.js b/src/ol/interaction/Draw.js index 201cfddde0..c1b9e4c3f1 100644 --- a/src/ol/interaction/Draw.js +++ b/src/ol/interaction/Draw.js @@ -18,7 +18,6 @@ import LineString from '../geom/LineString.js'; import MultiLineString from '../geom/MultiLineString.js'; import MultiPoint from '../geom/MultiPoint.js'; import MultiPolygon from '../geom/MultiPolygon.js'; -import {POINTER_TYPE} from '../pointer/MouseSource.js'; import Point from '../geom/Point.js'; import Polygon, {fromCircle, makeRegular} from '../geom/Polygon.js'; import PointerInteraction from './Pointer.js'; @@ -511,7 +510,7 @@ class Draw extends PointerInteraction { pass = event.type === MapBrowserEventType.POINTERMOVE; if (pass && this.freehand_) { pass = this.handlePointerMove_(event); - } else if (/** @type {MapBrowserPointerEvent} */ (event).pointerEvent.pointerType == POINTER_TYPE || + } else if (/** @type {MapBrowserPointerEvent} */ (event).pointerEvent.pointerType == 'mouse' || (event.type === MapBrowserEventType.POINTERDRAG && this.downTimeout_ === undefined)) { this.handlePointerMove_(event); } diff --git a/src/ol/interaction/Pointer.js b/src/ol/interaction/Pointer.js index 02a5636ea5..87b12fc296 100644 --- a/src/ol/interaction/Pointer.js +++ b/src/ol/interaction/Pointer.js @@ -80,13 +80,13 @@ class PointerInteraction extends Interaction { this.handlingDownUpSequence = false; /** - * @type {!Object} + * @type {!Object} * @private */ this.trackedPointers_ = {}; /** - * @type {Array} + * @type {Array} * @protected */ this.targetPointers = []; @@ -199,7 +199,7 @@ class PointerInteraction extends Interaction { /** - * @param {Array} pointerEvents List of events. + * @param {Array} pointerEvents List of events. * @return {import("../pixel.js").Pixel} Centroid pixel. */ export function centroid(pointerEvents) { diff --git a/src/ol/pointer/EventSource.js b/src/ol/pointer/EventSource.js deleted file mode 100644 index d53ccc7f0d..0000000000 --- a/src/ol/pointer/EventSource.js +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @module ol/pointer/EventSource - */ - -class EventSource { - - /** - * @param {import("./PointerEventHandler.js").default} dispatcher Event handler. - * @param {!Object} mapping Event mapping. - */ - constructor(dispatcher, mapping) { - - /** - * @type {import("./PointerEventHandler.js").default} - */ - this.dispatcher = dispatcher; - - /** - * @private - * @const - * @type {!Object} - */ - this.mapping_ = mapping; - } - - /** - * List of events supported by this source. - * @return {Array} Event names - */ - getEvents() { - return Object.keys(this.mapping_); - } - - /** - * Returns the handler that should handle a given event type. - * @param {string} eventType The event type. - * @return {function(Event)} Handler - */ - getHandlerForEvent(eventType) { - return this.mapping_[eventType]; - } - -} - -export default EventSource; diff --git a/src/ol/pointer/MouseSource.js b/src/ol/pointer/MouseSource.js deleted file mode 100644 index 3e27401259..0000000000 --- a/src/ol/pointer/MouseSource.js +++ /dev/null @@ -1,247 +0,0 @@ -/** - * @module ol/pointer/MouseSource - */ - -// Based on https://github.com/Polymer/PointerEvents - -// Copyright (c) 2013 The Polymer Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import EventSource from './EventSource.js'; - - -/** - * @type {number} - */ -export const POINTER_ID = 1; - - -/** - * @type {string} - */ -export const POINTER_TYPE = 'mouse'; - - -/** - * Radius around touchend that swallows mouse events. - * - * @type {number} - */ -const DEDUP_DIST = 25; - -/** - * Handler for `mousedown`. - * - * @this {MouseSource} - * @param {MouseEvent} inEvent The in event. - */ -function mousedown(inEvent) { - if (!this.isEventSimulatedFromTouch_(inEvent)) { - // TODO(dfreedman) workaround for some elements not sending mouseup - // http://crbug/149091 - if (POINTER_ID.toString() in this.pointerMap) { - this.cancel(inEvent); - } - const e = prepareEvent(inEvent, this.dispatcher); - this.pointerMap[POINTER_ID.toString()] = inEvent; - this.dispatcher.down(e, inEvent); - } -} - -/** - * Handler for `mousemove`. - * - * @this {MouseSource} - * @param {MouseEvent} inEvent The in event. - */ -function mousemove(inEvent) { - if (!this.isEventSimulatedFromTouch_(inEvent)) { - const e = prepareEvent(inEvent, this.dispatcher); - this.dispatcher.move(e, inEvent); - } -} - -/** - * Handler for `mouseup`. - * - * @this {MouseSource} - * @param {MouseEvent} inEvent The in event. - */ -function mouseup(inEvent) { - if (!this.isEventSimulatedFromTouch_(inEvent)) { - const p = this.pointerMap[POINTER_ID.toString()]; - - if (p && p.button === inEvent.button) { - const e = prepareEvent(inEvent, this.dispatcher); - this.dispatcher.up(e, inEvent); - this.cleanupMouse(); - } - } -} - -/** - * Handler for `mouseover`. - * - * @this {MouseSource} - * @param {MouseEvent} inEvent The in event. - */ -function mouseover(inEvent) { - if (!this.isEventSimulatedFromTouch_(inEvent)) { - const e = prepareEvent(inEvent, this.dispatcher); - this.dispatcher.enterOver(e, inEvent); - } -} - -/** - * Handler for `mouseout`. - * - * @this {MouseSource} - * @param {MouseEvent} inEvent The in event. - */ -function mouseout(inEvent) { - if (!this.isEventSimulatedFromTouch_(inEvent)) { - const e = prepareEvent(inEvent, this.dispatcher); - this.dispatcher.leaveOut(e, inEvent); - } -} - - -class MouseSource extends EventSource { - - /** - * @param {import("./PointerEventHandler.js").default} dispatcher Event handler. - */ - constructor(dispatcher) { - const mapping = { - 'mousedown': mousedown, - 'mousemove': mousemove, - 'mouseup': mouseup, - 'mouseover': mouseover, - 'mouseout': mouseout - }; - super(dispatcher, mapping); - - /** - * @const - * @type {!Object} - */ - this.pointerMap = dispatcher.pointerMap; - - /** - * @const - * @type {Array} - */ - this.lastTouches = []; - } - - /** - * Detect if a mouse event was simulated from a touch by - * checking if previously there was a touch event at the - * same position. - * - * FIXME - Known problem with the native Android browser on - * Samsung GT-I9100 (Android 4.1.2): - * In case the page is scrolled, this function does not work - * correctly when a canvas is used (WebGL or canvas renderer). - * Mouse listeners on canvas elements (for this browser), create - * two mouse events: One 'good' and one 'bad' one (on other browsers or - * when a div is used, there is only one event). For the 'bad' one, - * clientX/clientY and also pageX/pageY are wrong when the page - * is scrolled. Because of that, this function can not detect if - * the events were simulated from a touch event. As result, a - * pointer event at a wrong position is dispatched, which confuses - * the map interactions. - * It is unclear, how one can get the correct position for the event - * or detect that the positions are invalid. - * - * @private - * @param {MouseEvent} inEvent The in event. - * @return {boolean} True, if the event was generated by a touch. - */ - isEventSimulatedFromTouch_(inEvent) { - const lts = this.lastTouches; - const x = inEvent.clientX; - const y = inEvent.clientY; - for (let i = 0, l = lts.length, t; i < l && (t = lts[i]); i++) { - // simulated mouse events will be swallowed near a primary touchend - const dx = Math.abs(x - t[0]); - const dy = Math.abs(y - t[1]); - if (dx <= DEDUP_DIST && dy <= DEDUP_DIST) { - return true; - } - } - return false; - } - - /** - * Dispatches a `pointercancel` event. - * - * @param {Event} inEvent The in event. - */ - cancel(inEvent) { - const e = prepareEvent(inEvent, this.dispatcher); - this.dispatcher.cancel(e, inEvent); - this.cleanupMouse(); - } - - /** - * Remove the mouse from the list of active pointers. - */ - cleanupMouse() { - delete this.pointerMap[POINTER_ID.toString()]; - } -} - - -/** - * Creates a copy of the original event that will be used - * for the fake pointer event. - * - * @param {Event} inEvent The in event. - * @param {import("./PointerEventHandler.js").default} dispatcher Event handler. - * @return {Object} The copied event. - */ -export function prepareEvent(inEvent, dispatcher) { - const e = dispatcher.cloneEvent(inEvent, inEvent); - - // forward mouse preventDefault - const pd = e.preventDefault; - e.preventDefault = function() { - inEvent.preventDefault(); - pd(); - }; - - e.pointerId = POINTER_ID; - e.isPrimary = true; - e.pointerType = POINTER_TYPE; - - return e; -} - - -export default MouseSource; diff --git a/src/ol/pointer/MsSource.js b/src/ol/pointer/MsSource.js deleted file mode 100644 index 30131a365b..0000000000 --- a/src/ol/pointer/MsSource.js +++ /dev/null @@ -1,194 +0,0 @@ -/** - * @module ol/pointer/MsSource - */ -// Based on https://github.com/Polymer/PointerEvents - -// Copyright (c) 2013 The Polymer Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import EventSource from './EventSource.js'; - - -/** - * @const - * @type {Array} - */ -const POINTER_TYPES = [ - '', - 'unavailable', - 'touch', - 'pen', - 'mouse' -]; - -/** - * Handler for `msPointerDown`. - * - * @this {MsSource} - * @param {MSPointerEvent} inEvent The in event. - */ -function msPointerDown(inEvent) { - this.pointerMap[inEvent.pointerId.toString()] = inEvent; - const e = this.prepareEvent_(inEvent); - this.dispatcher.down(e, inEvent); -} - -/** - * Handler for `msPointerMove`. - * - * @this {MsSource} - * @param {MSPointerEvent} inEvent The in event. - */ -function msPointerMove(inEvent) { - const e = this.prepareEvent_(inEvent); - this.dispatcher.move(e, inEvent); -} - -/** - * Handler for `msPointerUp`. - * - * @this {MsSource} - * @param {MSPointerEvent} inEvent The in event. - */ -function msPointerUp(inEvent) { - const e = this.prepareEvent_(inEvent); - this.dispatcher.up(e, inEvent); - this.cleanup(inEvent.pointerId); -} - -/** - * Handler for `msPointerOut`. - * - * @this {MsSource} - * @param {MSPointerEvent} inEvent The in event. - */ -function msPointerOut(inEvent) { - const e = this.prepareEvent_(inEvent); - this.dispatcher.leaveOut(e, inEvent); -} - -/** - * Handler for `msPointerOver`. - * - * @this {MsSource} - * @param {MSPointerEvent} inEvent The in event. - */ -function msPointerOver(inEvent) { - const e = this.prepareEvent_(inEvent); - this.dispatcher.enterOver(e, inEvent); -} - -/** - * Handler for `msPointerCancel`. - * - * @this {MsSource} - * @param {MSPointerEvent} inEvent The in event. - */ -function msPointerCancel(inEvent) { - const e = this.prepareEvent_(inEvent); - this.dispatcher.cancel(e, inEvent); - this.cleanup(inEvent.pointerId); -} - -/** - * Handler for `msLostPointerCapture`. - * - * @this {MsSource} - * @param {MSPointerEvent} inEvent The in event. - */ -function msLostPointerCapture(inEvent) { - const e = this.dispatcher.makeEvent('lostpointercapture', inEvent, inEvent); - this.dispatcher.dispatchEvent(e); -} - -/** - * Handler for `msGotPointerCapture`. - * - * @this {MsSource} - * @param {MSPointerEvent} inEvent The in event. - */ -function msGotPointerCapture(inEvent) { - const e = this.dispatcher.makeEvent('gotpointercapture', inEvent, inEvent); - this.dispatcher.dispatchEvent(e); -} - -class MsSource extends EventSource { - - /** - * @param {import("./PointerEventHandler.js").default} dispatcher Event handler. - */ - constructor(dispatcher) { - const mapping = { - 'MSPointerDown': msPointerDown, - 'MSPointerMove': msPointerMove, - 'MSPointerUp': msPointerUp, - 'MSPointerOut': msPointerOut, - 'MSPointerOver': msPointerOver, - 'MSPointerCancel': msPointerCancel, - 'MSGotPointerCapture': msGotPointerCapture, - 'MSLostPointerCapture': msLostPointerCapture - }; - super(dispatcher, mapping); - - /** - * @const - * @type {!Object} - */ - this.pointerMap = dispatcher.pointerMap; - } - - /** - * Creates a copy of the original event that will be used - * for the fake pointer event. - * - * @private - * @param {MSPointerEvent} inEvent The in event. - * @return {Object} The copied event. - */ - prepareEvent_(inEvent) { - /** @type {MSPointerEvent|Object} */ - let e = inEvent; - if (typeof inEvent.pointerType === 'number') { - e = this.dispatcher.cloneEvent(inEvent, inEvent); - e.pointerType = POINTER_TYPES[inEvent.pointerType]; - } - - return e; - } - - /** - * Remove this pointer from the list of active pointers. - * @param {number} pointerId Pointer identifier. - */ - cleanup(pointerId) { - delete this.pointerMap[pointerId.toString()]; - } - -} - -export default MsSource; diff --git a/src/ol/pointer/NativeSource.js b/src/ol/pointer/NativeSource.js deleted file mode 100644 index 4e133f5998..0000000000 --- a/src/ol/pointer/NativeSource.js +++ /dev/null @@ -1,138 +0,0 @@ -/** - * @module ol/pointer/NativeSource - */ - -// Based on https://github.com/Polymer/PointerEvents - -// Copyright (c) 2013 The Polymer Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import EventSource from './EventSource.js'; - -/** - * Handler for `pointerdown`. - * - * @this {NativeSource} - * @param {Event} inEvent The in event. - */ -function pointerDown(inEvent) { - this.dispatcher.fireNativeEvent(inEvent); -} - -/** - * Handler for `pointermove`. - * - * @this {NativeSource} - * @param {Event} inEvent The in event. - */ -function pointerMove(inEvent) { - this.dispatcher.fireNativeEvent(inEvent); -} - -/** - * Handler for `pointerup`. - * - * @this {NativeSource} - * @param {Event} inEvent The in event. - */ -function pointerUp(inEvent) { - this.dispatcher.fireNativeEvent(inEvent); -} - -/** - * Handler for `pointerout`. - * - * @this {NativeSource} - * @param {Event} inEvent The in event. - */ -function pointerOut(inEvent) { - this.dispatcher.fireNativeEvent(inEvent); -} - -/** - * Handler for `pointerover`. - * - * @this {NativeSource} - * @param {Event} inEvent The in event. - */ -function pointerOver(inEvent) { - this.dispatcher.fireNativeEvent(inEvent); -} - -/** - * Handler for `pointercancel`. - * - * @this {NativeSource} - * @param {Event} inEvent The in event. - */ -function pointerCancel(inEvent) { - this.dispatcher.fireNativeEvent(inEvent); -} - -/** - * Handler for `lostpointercapture`. - * - * @this {NativeSource} - * @param {Event} inEvent The in event. - */ -function lostPointerCapture(inEvent) { - this.dispatcher.fireNativeEvent(inEvent); -} - -/** - * Handler for `gotpointercapture`. - * - * @this {NativeSource} - * @param {Event} inEvent The in event. - */ -function gotPointerCapture(inEvent) { - this.dispatcher.fireNativeEvent(inEvent); -} - -class NativeSource extends EventSource { - - /** - * @param {import("./PointerEventHandler.js").default} dispatcher Event handler. - */ - constructor(dispatcher) { - const mapping = { - 'pointerdown': pointerDown, - 'pointermove': pointerMove, - 'pointerup': pointerUp, - 'pointerout': pointerOut, - 'pointerover': pointerOver, - 'pointercancel': pointerCancel, - 'gotpointercapture': gotPointerCapture, - 'lostpointercapture': lostPointerCapture - }; - super(dispatcher, mapping); - } - -} - -export default NativeSource; diff --git a/src/ol/pointer/PointerEvent.js b/src/ol/pointer/PointerEvent.js deleted file mode 100644 index 35e1239169..0000000000 --- a/src/ol/pointer/PointerEvent.js +++ /dev/null @@ -1,277 +0,0 @@ -/** - * @module ol/pointer/PointerEvent - */ - -// Based on https://github.com/Polymer/PointerEvents - -// Copyright (c) 2013 The Polymer Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import _Event from '../events/Event.js'; - - -/** - * Is the `buttons` property supported? - * @type {boolean} - */ -let HAS_BUTTONS = false; - - -class PointerEvent extends _Event { - - /** - * A class for pointer events. - * - * This class is used as an abstraction for mouse events, - * touch events and even native pointer events. - * - * @param {string} type The type of the event to create. - * @param {Event} originalEvent The event. - * @param {Object=} opt_eventDict An optional dictionary of - * initial event properties. - */ - constructor(type, originalEvent, opt_eventDict) { - super(type); - - /** - * @const - * @type {Event} - */ - this.originalEvent = originalEvent; - - const eventDict = opt_eventDict ? opt_eventDict : {}; - - /** - * @type {number} - */ - this.buttons = getButtons(eventDict); - - /** - * @type {number} - */ - this.pressure = getPressure(eventDict, this.buttons); - - // MouseEvent related properties - - /** - * @type {boolean} - */ - this.bubbles = 'bubbles' in eventDict ? eventDict['bubbles'] : false; - - /** - * @type {boolean} - */ - this.cancelable = 'cancelable' in eventDict ? eventDict['cancelable'] : false; - - /** - * @type {Object} - */ - this.view = 'view' in eventDict ? eventDict['view'] : null; - - /** - * @type {number} - */ - this.detail = 'detail' in eventDict ? eventDict['detail'] : null; - - /** - * @type {number} - */ - this.screenX = 'screenX' in eventDict ? eventDict['screenX'] : 0; - - /** - * @type {number} - */ - this.screenY = 'screenY' in eventDict ? eventDict['screenY'] : 0; - - /** - * @type {number} - */ - this.clientX = 'clientX' in eventDict ? eventDict['clientX'] : 0; - - /** - * @type {number} - */ - this.clientY = 'clientY' in eventDict ? eventDict['clientY'] : 0; - - /** - * @type {boolean} - */ - this.ctrlKey = 'ctrlKey' in eventDict ? eventDict['ctrlKey'] : false; - - /** - * @type {boolean} - */ - this.altKey = 'altKey' in eventDict ? eventDict['altKey'] : false; - - /** - * @type {boolean} - */ - this.shiftKey = 'shiftKey' in eventDict ? eventDict['shiftKey'] : false; - - /** - * @type {boolean} - */ - this.metaKey = 'metaKey' in eventDict ? eventDict['metaKey'] : false; - - /** - * @type {number} - */ - this.button = 'button' in eventDict ? eventDict['button'] : 0; - - /** - * @type {Node} - */ - this.relatedTarget = 'relatedTarget' in eventDict ? - eventDict['relatedTarget'] : null; - - // PointerEvent related properties - - /** - * @const - * @type {number} - */ - this.pointerId = 'pointerId' in eventDict ? eventDict['pointerId'] : 0; - - /** - * @type {number} - */ - this.width = 'width' in eventDict ? eventDict['width'] : 0; - - /** - * @type {number} - */ - this.height = 'height' in eventDict ? eventDict['height'] : 0; - - /** - * @type {number} - */ - this.tiltX = 'tiltX' in eventDict ? eventDict['tiltX'] : 0; - - /** - * @type {number} - */ - this.tiltY = 'tiltY' in eventDict ? eventDict['tiltY'] : 0; - - /** - * @type {string} - */ - this.pointerType = 'pointerType' in eventDict ? eventDict['pointerType'] : ''; - - /** - * @type {number} - */ - this.hwTimestamp = 'hwTimestamp' in eventDict ? eventDict['hwTimestamp'] : 0; - - /** - * @type {boolean} - */ - this.isPrimary = 'isPrimary' in eventDict ? eventDict['isPrimary'] : false; - - // keep the semantics of preventDefault - if (originalEvent.preventDefault) { - this.preventDefault = function() { - originalEvent.preventDefault(); - }; - } - } - -} - - -/** - * @param {Object} eventDict The event dictionary. - * @return {number} Button indicator. - */ -function getButtons(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 - // 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 - let buttons; - if (eventDict.buttons || HAS_BUTTONS) { - buttons = eventDict.buttons; - } else { - switch (eventDict.which) { - case 1: buttons = 1; break; - case 2: buttons = 4; break; - case 3: buttons = 2; break; - default: buttons = 0; - } - } - return buttons; -} - - -/** - * @param {Object} eventDict The event dictionary. - * @param {number} buttons Button indicator. - * @return {number} The pressure. - */ -function getPressure(eventDict, buttons) { - // Spec requires that pointers without pressure specified use 0.5 for down - // state and 0 for up state. - let pressure = 0; - if (eventDict.pressure) { - pressure = eventDict.pressure; - } else { - pressure = buttons ? 0.5 : 0; - } - return pressure; -} - - -/** - * Checks if the `buttons` property is supported. - */ -(function() { - try { - const ev = new MouseEvent('click', {buttons: 1}); - HAS_BUTTONS = ev.buttons === 1; - } catch (e) { - // pass - } -})(); - -export default PointerEvent; diff --git a/src/ol/pointer/PointerEventHandler.js b/src/ol/pointer/PointerEventHandler.js deleted file mode 100644 index 7f983ef9d9..0000000000 --- a/src/ol/pointer/PointerEventHandler.js +++ /dev/null @@ -1,417 +0,0 @@ -/** - * @module ol/pointer/PointerEventHandler - */ - -// Based on https://github.com/Polymer/PointerEvents - -// Copyright (c) 2013 The Polymer Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import {listen, unlisten} from '../events.js'; -import EventTarget from '../events/Target.js'; -import PointerEventType from './EventType.js'; -import MouseSource, {prepareEvent as prepareMouseEvent} from './MouseSource.js'; -import MsSource from './MsSource.js'; -import NativeSource from './NativeSource.js'; -import PointerEvent from './PointerEvent.js'; -import TouchSource from './TouchSource.js'; - - -/** - * Properties to copy when cloning an event, with default values. - * @type {Array} - */ -const CLONE_PROPS = [ - // MouseEvent - ['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], - // DOM Level 3 - ['buttons', 0], - // PointerEvent - ['pointerId', 0], - ['width', 0], - ['height', 0], - ['pressure', 0], - ['tiltX', 0], - ['tiltY', 0], - ['pointerType', ''], - ['hwTimestamp', 0], - ['isPrimary', false], - // event instance - ['type', ''], - ['target', null], - ['currentTarget', null], - ['which', 0] -]; - - -class PointerEventHandler extends EventTarget { - - /** - * @param {Element|HTMLDocument} element Viewport element. - */ - constructor(element) { - super(); - - /** - * @const - * @private - * @type {Element|HTMLDocument} - */ - this.element_ = element; - - /** - * @const - * @type {!Object} - */ - this.pointerMap = {}; - - /** - * @type {Object} - * @private - */ - this.eventMap_ = {}; - - /** - * @type {Array} - * @private - */ - this.eventSourceList_ = []; - - this.registerSources(); - } - - /** - * Set up the event sources (mouse, touch and native pointers) - * that generate pointer events. - */ - registerSources() { - if ('PointerEvent' in window) { - this.registerSource('native', new NativeSource(this)); - } else if (window.navigator.msPointerEnabled) { - this.registerSource('ms', new MsSource(this)); - } else { - const mouseSource = new MouseSource(this); - this.registerSource('mouse', mouseSource); - - if ('ontouchstart' in window) { - this.registerSource('touch', new TouchSource(this, mouseSource)); - } - } - - // register events on the viewport element - this.register_(); - } - - /** - * Add a new event source that will generate pointer events. - * - * @param {string} name A name for the event source - * @param {import("./EventSource.js").default} source The source event. - */ - registerSource(name, source) { - const s = source; - const newEvents = s.getEvents(); - - if (newEvents) { - newEvents.forEach(function(e) { - const handler = s.getHandlerForEvent(e); - - if (handler) { - this.eventMap_[e] = handler.bind(s); - } - }.bind(this)); - this.eventSourceList_.push(s); - } - } - - /** - * Set up the events for all registered event sources. - * @private - */ - register_() { - const l = this.eventSourceList_.length; - for (let i = 0; i < l; i++) { - const eventSource = this.eventSourceList_[i]; - this.addEvents_(eventSource.getEvents()); - } - } - - /** - * Remove all registered events. - * @private - */ - unregister_() { - const l = this.eventSourceList_.length; - for (let i = 0; i < l; i++) { - const eventSource = this.eventSourceList_[i]; - this.removeEvents_(eventSource.getEvents()); - } - } - - /** - * Calls the right handler for a new event. - * @private - * @param {Event} inEvent Browser event. - */ - eventHandler_(inEvent) { - const type = inEvent.type; - const handler = this.eventMap_[type]; - if (handler) { - handler(inEvent); - } - } - - /** - * Setup listeners for the given events. - * @private - * @param {Array} events List of events. - */ - addEvents_(events) { - events.forEach(function(eventName) { - listen(this.element_, eventName, this.eventHandler_, this); - }.bind(this)); - } - - /** - * Unregister listeners for the given events. - * @private - * @param {Array} events List of events. - */ - removeEvents_(events) { - events.forEach(function(e) { - unlisten(this.element_, e, this.eventHandler_, this); - }.bind(this)); - } - - /** - * Returns a snapshot of inEvent, with writable properties. - * - * @param {Event} event Browser event. - * @param {Event|Touch} inEvent An event that contains - * properties to copy. - * @return {Object} An object containing shallow copies of - * `inEvent`'s properties. - */ - cloneEvent(event, inEvent) { - const eventCopy = {}; - for (let i = 0, ii = CLONE_PROPS.length; i < ii; i++) { - const p = CLONE_PROPS[i][0]; - eventCopy[p] = event[p] || inEvent[p] || CLONE_PROPS[i][1]; - } - - return eventCopy; - } - - // EVENTS - - - /** - * Triggers a 'pointerdown' event. - * @param {Object} data Pointer event data. - * @param {Event} event The event. - */ - down(data, event) { - this.fireEvent(PointerEventType.POINTERDOWN, data, event); - } - - /** - * Triggers a 'pointermove' event. - * @param {Object} data Pointer event data. - * @param {Event} event The event. - */ - move(data, event) { - this.fireEvent(PointerEventType.POINTERMOVE, data, event); - } - - /** - * Triggers a 'pointerup' event. - * @param {Object} data Pointer event data. - * @param {Event} event The event. - */ - up(data, event) { - this.fireEvent(PointerEventType.POINTERUP, data, event); - } - - /** - * Triggers a 'pointerenter' event. - * @param {Object} data Pointer event data. - * @param {Event} event The event. - */ - enter(data, event) { - data.bubbles = false; - this.fireEvent(PointerEventType.POINTERENTER, data, event); - } - - /** - * Triggers a 'pointerleave' event. - * @param {Object} data Pointer event data. - * @param {Event} event The event. - */ - leave(data, event) { - data.bubbles = false; - this.fireEvent(PointerEventType.POINTERLEAVE, data, event); - } - - /** - * Triggers a 'pointerover' event. - * @param {Object} data Pointer event data. - * @param {Event} event The event. - */ - over(data, event) { - data.bubbles = true; - this.fireEvent(PointerEventType.POINTEROVER, data, event); - } - - /** - * Triggers a 'pointerout' event. - * @param {Object} data Pointer event data. - * @param {Event} event The event. - */ - out(data, event) { - data.bubbles = true; - this.fireEvent(PointerEventType.POINTEROUT, data, event); - } - - /** - * Triggers a 'pointercancel' event. - * @param {Object} data Pointer event data. - * @param {Event} event The event. - */ - cancel(data, event) { - this.fireEvent(PointerEventType.POINTERCANCEL, data, event); - } - - /** - * Triggers a combination of 'pointerout' and 'pointerleave' events. - * @param {Object} data Pointer event data. - * @param {Event} event The event. - */ - leaveOut(data, event) { - this.out(data, event); - if (!this.contains_(data.target, data.relatedTarget)) { - this.leave(data, event); - } - } - - /** - * Triggers a combination of 'pointerover' and 'pointerevents' events. - * @param {Object} data Pointer event data. - * @param {Event} event The event. - */ - enterOver(data, event) { - this.over(data, event); - if (!this.contains_(data.target, data.relatedTarget)) { - this.enter(data, event); - } - } - - /** - * @private - * @param {Element} container The container element. - * @param {Element} contained The contained element. - * @return {boolean} Returns true if the container element - * contains the other element. - */ - contains_(container, contained) { - if (!container || !contained) { - return false; - } - return container.contains(contained); - } - - // EVENT CREATION AND TRACKING - /** - * Creates a new Event of type `inType`, based on the information in - * `data`. - * - * @param {string} inType A string representing the type of event to create. - * @param {Object} data Pointer event data. - * @param {Event} event The event. - * @return {PointerEvent} A PointerEvent of type `inType`. - */ - makeEvent(inType, data, event) { - return new PointerEvent(inType, event, data); - } - - /** - * Make and dispatch an event in one call. - * @param {string} inType A string representing the type of event. - * @param {Object} data Pointer event data. - * @param {Event} event The event. - */ - fireEvent(inType, data, event) { - const e = this.makeEvent(inType, data, event); - this.dispatchEvent(e); - } - - /** - * Creates a pointer event from a native pointer event - * and dispatches this event. - * @param {Event} event A platform event with a target. - */ - fireNativeEvent(event) { - const e = this.makeEvent(event.type, event, event); - this.dispatchEvent(e); - } - - /** - * Wrap a native mouse event into a pointer event. - * This proxy method is required for the legacy IE support. - * @param {string} eventType The pointer event type. - * @param {Event} event The event. - * @return {PointerEvent} The wrapped event. - */ - wrapMouseEvent(eventType, event) { - const pointerEvent = this.makeEvent( - eventType, prepareMouseEvent(event, this), event); - return pointerEvent; - } - - /** - * @inheritDoc - */ - disposeInternal() { - this.unregister_(); - super.disposeInternal(); - } -} - -export default PointerEventHandler; diff --git a/src/ol/pointer/TouchSource.js b/src/ol/pointer/TouchSource.js deleted file mode 100644 index 54fac3a1fa..0000000000 --- a/src/ol/pointer/TouchSource.js +++ /dev/null @@ -1,424 +0,0 @@ -/** - * @module ol/pointer/TouchSource - */ - -// Based on https://github.com/Polymer/PointerEvents - -// Copyright (c) 2013 The Polymer Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import {remove} from '../array.js'; -import EventSource from './EventSource.js'; -import {POINTER_ID} from './MouseSource.js'; - - -/** - * @type {number} - */ -const CLICK_COUNT_TIMEOUT = 200; - -/** - * @type {string} - */ -const POINTER_TYPE = 'touch'; - -/** - * Handler for `touchstart`, triggers `pointerover`, - * `pointerenter` and `pointerdown` events. - * - * @this {TouchSource} - * @param {TouchEvent} inEvent The in event. - */ -function touchstart(inEvent) { - this.vacuumTouches_(inEvent); - this.setPrimaryTouch_(inEvent.changedTouches[0]); - this.dedupSynthMouse_(inEvent); - this.clickCount_++; - this.processTouches_(inEvent, this.overDown_); -} - -/** - * Handler for `touchmove`. - * - * @this {TouchSource} - * @param {TouchEvent} inEvent The in event. - */ -function touchmove(inEvent) { - this.processTouches_(inEvent, this.moveOverOut_); -} - -/** - * Handler for `touchend`, triggers `pointerup`, - * `pointerout` and `pointerleave` events. - * - * @this {TouchSource} - * @param {TouchEvent} inEvent The event. - */ -function touchend(inEvent) { - this.dedupSynthMouse_(inEvent); - this.processTouches_(inEvent, this.upOut_); -} - -/** - * Handler for `touchcancel`, triggers `pointercancel`, - * `pointerout` and `pointerleave` events. - * - * @this {TouchSource} - * @param {TouchEvent} inEvent The in event. - */ -function touchcancel(inEvent) { - this.processTouches_(inEvent, this.cancelOut_); -} - - -class TouchSource extends EventSource { - - /** - * @param {import("./PointerEventHandler.js").default} dispatcher The event handler. - * @param {import("./MouseSource.js").default} mouseSource Mouse source. - */ - constructor(dispatcher, mouseSource) { - const mapping = { - 'touchstart': touchstart, - 'touchmove': touchmove, - 'touchend': touchend, - 'touchcancel': touchcancel - }; - super(dispatcher, mapping); - - /** - * @const - * @type {!Object} - */ - this.pointerMap = dispatcher.pointerMap; - - /** - * @const - * @type {import("./MouseSource.js").default} - */ - this.mouseSource = mouseSource; - - /** - * @private - * @type {number|undefined} - */ - this.firstTouchId_ = undefined; - - /** - * @private - * @type {number} - */ - this.clickCount_ = 0; - - /** - * @private - * @type {?} - */ - this.resetId_; - - /** - * Mouse event timeout: This should be long enough to - * ignore compat mouse events made by touch. - * @private - * @type {number} - */ - this.dedupTimeout_ = 2500; - } - - /** - * @private - * @param {Touch} inTouch The in touch. - * @return {boolean} True, if this is the primary touch. - */ - isPrimaryTouch_(inTouch) { - return this.firstTouchId_ === inTouch.identifier; - } - - /** - * Set primary touch if there are no pointers, or the only pointer is the mouse. - * @param {Touch} inTouch The in touch. - * @private - */ - setPrimaryTouch_(inTouch) { - const count = Object.keys(this.pointerMap).length; - if (count === 0 || (count === 1 && POINTER_ID.toString() in this.pointerMap)) { - this.firstTouchId_ = inTouch.identifier; - this.cancelResetClickCount_(); - } - } - - /** - * @private - * @param {PointerEvent} inPointer The in pointer object. - */ - removePrimaryPointer_(inPointer) { - if (inPointer.isPrimary) { - this.firstTouchId_ = undefined; - this.resetClickCount_(); - } - } - - /** - * @private - */ - resetClickCount_() { - this.resetId_ = setTimeout( - this.resetClickCountHandler_.bind(this), - CLICK_COUNT_TIMEOUT); - } - - /** - * @private - */ - resetClickCountHandler_() { - this.clickCount_ = 0; - this.resetId_ = undefined; - } - - /** - * @private - */ - cancelResetClickCount_() { - if (this.resetId_ !== undefined) { - clearTimeout(this.resetId_); - } - } - - /** - * @private - * @param {TouchEvent} browserEvent Browser event - * @param {Touch} inTouch Touch event - * @return {PointerEvent} A pointer object. - */ - touchToPointer_(browserEvent, inTouch) { - const 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. - e.pointerId = inTouch.identifier + 2; - // TODO: check if this is necessary? - //e.target = findTarget(e); - e.bubbles = true; - e.cancelable = true; - e.detail = this.clickCount_; - e.button = 0; - e.buttons = 1; - e.width = inTouch.radiusX || 0; - e.height = inTouch.radiusY || 0; - e.pressure = inTouch.force || 0.5; - e.isPrimary = this.isPrimaryTouch_(inTouch); - e.pointerType = POINTER_TYPE; - - // make sure that the properties that are different for - // each `Touch` object are not copied from the BrowserEvent object - e.clientX = inTouch.clientX; - e.clientY = inTouch.clientY; - e.screenX = inTouch.screenX; - e.screenY = inTouch.screenY; - - return e; - } - - /** - * @private - * @param {TouchEvent} inEvent Touch event - * @param {function(TouchEvent, PointerEvent): void} inFunction In function. - */ - processTouches_(inEvent, inFunction) { - const touches = Array.prototype.slice.call(inEvent.changedTouches); - const count = touches.length; - function preventDefault() { - inEvent.preventDefault(); - } - for (let i = 0; i < count; ++i) { - const pointer = this.touchToPointer_(inEvent, touches[i]); - // forward touch preventDefaults - pointer.preventDefault = preventDefault; - inFunction.call(this, inEvent, pointer); - } - } - - /** - * @private - * @param {TouchList} touchList The touch list. - * @param {number} searchId Search identifier. - * @return {boolean} True, if the `Touch` with the given id is in the list. - */ - findTouch_(touchList, searchId) { - const l = touchList.length; - for (let i = 0; i < l; i++) { - const touch = touchList[i]; - if (touch.identifier === searchId) { - return true; - } - } - return false; - } - - /** - * In some instances, a touchstart can happen without a touchend. This - * leaves the pointermap in a broken state. - * Therefore, on every touchstart, we remove the touches that did not fire a - * touchend event. - * To keep state globally consistent, we fire a pointercancel for - * this "abandoned" touch - * - * @private - * @param {TouchEvent} inEvent The in event. - */ - vacuumTouches_(inEvent) { - const touchList = inEvent.touches; - // pointerMap.getCount() should be < touchList.length here, - // as the touchstart has not been processed yet. - const keys = Object.keys(this.pointerMap); - const count = keys.length; - if (count >= touchList.length) { - const d = []; - for (let i = 0; i < count; ++i) { - const key = Number(keys[i]); - const value = this.pointerMap[key]; - // Never remove pointerId == 1, which is mouse. - // Touch identifiers are 2 smaller than their pointerId, which is the - // index in pointermap. - if (key != POINTER_ID && !this.findTouch_(touchList, key - 2)) { - d.push(value.out); - } - } - for (let i = 0; i < d.length; ++i) { - this.cancelOut_(inEvent, d[i]); - } - } - } - - /** - * @private - * @param {TouchEvent} browserEvent The event. - * @param {PointerEvent} inPointer The in pointer object. - */ - overDown_(browserEvent, inPointer) { - this.pointerMap[inPointer.pointerId] = { - target: inPointer.target, - out: inPointer, - outTarget: inPointer.target - }; - this.dispatcher.over(inPointer, browserEvent); - this.dispatcher.enter(inPointer, browserEvent); - this.dispatcher.down(inPointer, browserEvent); - } - - /** - * @private - * @param {TouchEvent} browserEvent The event. - * @param {PointerEvent} inPointer The in pointer. - */ - moveOverOut_(browserEvent, inPointer) { - const event = inPointer; - const pointer = this.pointerMap[event.pointerId]; - // a finger drifted off the screen, ignore it - if (!pointer) { - return; - } - const outEvent = pointer.out; - const outTarget = pointer.outTarget; - this.dispatcher.move(event, browserEvent); - if (outEvent && outTarget !== event.target) { - outEvent.relatedTarget = event.target; - /** @type {Object} */ (event).relatedTarget = outTarget; - // recover from retargeting by shadow - outEvent.target = outTarget; - if (event.target) { - this.dispatcher.leaveOut(outEvent, browserEvent); - this.dispatcher.enterOver(event, browserEvent); - } else { - // clean up case when finger leaves the screen - /** @type {Object} */ (event).target = outTarget; - /** @type {Object} */ (event).relatedTarget = null; - this.cancelOut_(browserEvent, event); - } - } - pointer.out = event; - pointer.outTarget = event.target; - } - - /** - * @private - * @param {TouchEvent} browserEvent An event. - * @param {PointerEvent} inPointer The inPointer object. - */ - upOut_(browserEvent, inPointer) { - this.dispatcher.up(inPointer, browserEvent); - this.dispatcher.out(inPointer, browserEvent); - this.dispatcher.leave(inPointer, browserEvent); - this.cleanUpPointer_(inPointer); - } - - /** - * @private - * @param {TouchEvent} browserEvent The event. - * @param {PointerEvent} inPointer The in pointer. - */ - cancelOut_(browserEvent, inPointer) { - this.dispatcher.cancel(inPointer, browserEvent); - this.dispatcher.out(inPointer, browserEvent); - this.dispatcher.leave(inPointer, browserEvent); - this.cleanUpPointer_(inPointer); - } - - /** - * @private - * @param {PointerEvent} inPointer The inPointer object. - */ - cleanUpPointer_(inPointer) { - delete this.pointerMap[inPointer.pointerId]; - this.removePrimaryPointer_(inPointer); - } - - /** - * Prevent synth mouse events from creating pointer events. - * - * @private - * @param {TouchEvent} inEvent The in event. - */ - dedupSynthMouse_(inEvent) { - const lts = this.mouseSource.lastTouches; - const t = inEvent.changedTouches[0]; - // only the primary finger will synth mouse events - if (this.isPrimaryTouch_(t)) { - // remember x/y of last touch - const lt = [t.clientX, t.clientY]; - lts.push(lt); - - setTimeout(function() { - // remove touch after timeout - remove(lts, lt); - }, this.dedupTimeout_); - } - } -} - -export default TouchSource; diff --git a/test/spec/ol/control/zoomslider.test.js b/test/spec/ol/control/zoomslider.test.js index 52ab1bcafa..76f61b78e0 100644 --- a/test/spec/ol/control/zoomslider.test.js +++ b/test/spec/ol/control/zoomslider.test.js @@ -1,11 +1,24 @@ import Map from '../../../../src/ol/Map.js'; import View from '../../../../src/ol/View.js'; import ZoomSlider from '../../../../src/ol/control/ZoomSlider.js'; -import PointerEvent from '../../../../src/ol/pointer/PointerEvent.js'; +import Event from '../../../../src/ol/events/Event.js'; +import EventTarget from '../../../../src/ol/events/Target.js'; describe('ol.control.ZoomSlider', function() { let map, target, zoomslider; + const createElement = document.createElement; + function createEventElement(type) { + const element = createElement.call(document, type); + const eventTarget = new EventTarget(); + element.listeners_ = {}; + element.dispatching_ = {}; + element.pendingRemovals_ = {}; + element.dispatchEvent = eventTarget.dispatchEvent.bind(element); + element.addEventListener = eventTarget.addEventListener.bind(element); + return element; + } + beforeEach(function() { target = document.createElement('div'); document.body.appendChild(target); @@ -102,138 +115,142 @@ describe('ol.control.ZoomSlider', function() { }); it('[horizontal] handles a drag sequence', function() { + document.createElement = createEventElement; const control = new ZoomSlider(); map.addControl(control); + document.createElement = createElement; map.getView().setZoom(0); control.element.style.width = '500px'; control.element.style.height = '10px'; control.element.firstChild.style.width = '100px'; control.element.firstChild.style.height = '10px'; map.renderSync(); - const dragger = control.dragger_; - const event = new PointerEvent('pointerdown', { - target: control.element.firstElementChild - }); + const event = new Event(); + event.type = 'pointerdown', + event.target = control.element.firstElementChild; event.clientX = control.widthLimit_; event.clientY = 0; - dragger.dispatchEvent(event); + control.element.dispatchEvent(event); expect(control.currentResolution_).to.be(16); expect(control.dragging_).to.be(true); - expect(control.dragListenerKeys_.length).to.be(4); + expect(control.dragListenerKeys_.length).to.be(2); event.type = 'pointermove'; event.clientX = 6 * control.widthLimit_ / 8; event.clientY = 0; - dragger.dispatchEvent(event); + control.element.dispatchEvent(event); expect(control.currentResolution_).to.be(4); event.type = 'pointermove'; event.clientX = 4 * control.widthLimit_ / 8; event.clientY = 0; - dragger.dispatchEvent(event); + control.element.dispatchEvent(event); event.type = 'pointerup'; - dragger.dispatchEvent(event); + control.element.dispatchEvent(event); expect(control.currentResolution_).to.be(1); expect(control.dragListenerKeys_.length).to.be(0); expect(control.dragging_).to.be(false); }); it('[horizontal] handles a drag sequence ending outside its bounds', function() { + document.createElement = createEventElement; const control = new ZoomSlider(); map.addControl(control); + document.createElement = createElement; map.getView().setZoom(0); control.element.style.width = '500px'; control.element.style.height = '10px'; control.element.firstChild.style.width = '100px'; control.element.firstChild.style.height = '10px'; map.renderSync(); - const dragger = control.dragger_; - const event = new PointerEvent('pointerdown', { - target: control.element.firstElementChild - }); + const event = new Event(); + event.type = 'pointerdown'; + event.target = control.element.firstElementChild; event.clientX = control.widthLimit_; event.clientY = 0; - dragger.dispatchEvent(event); + control.element.dispatchEvent(event); expect(control.currentResolution_).to.be(16); expect(control.dragging_).to.be(true); - expect(control.dragListenerKeys_.length).to.be(4); + expect(control.dragListenerKeys_.length).to.be(2); event.type = 'pointermove'; event.clientX = 6 * control.widthLimit_ / 8; event.clientY = 0; - dragger.dispatchEvent(event); + control.element.dispatchEvent(event); expect(control.currentResolution_).to.be(4); event.type = 'pointermove'; event.clientX = 12 * control.widthLimit_ / 8; event.clientY = 0; - dragger.dispatchEvent(event); + control.element.dispatchEvent(event); event.type = 'pointerup'; event.target = 'document'; - dragger.dispatchEvent(event); + control.element.dispatchEvent(event); expect(control.dragListenerKeys_.length).to.be(0); expect(control.dragging_).to.be(false); expect(control.currentResolution_).to.be(16); }); it('[vertical] handles a drag sequence', function() { + document.createElement = createEventElement; const control = new ZoomSlider(); control.element.style.width = '10px'; control.element.style.height = '100px'; control.element.firstChild.style.width = '10px'; control.element.firstChild.style.height = '20px'; map.addControl(control); + document.createElement = createElement; map.getView().setZoom(8); map.renderSync(); - const dragger = control.dragger_; - const event = new PointerEvent('pointerdown', { - target: control.element.firstElementChild - }); + const event = new Event(); + event.type = 'pointerdown'; + event.target = control.element.firstElementChild; event.clientX = 0; event.clientY = 0; - dragger.dispatchEvent(event); + control.element.dispatchEvent(event); expect(control.currentResolution_).to.be(0.0625); expect(control.dragging_).to.be(true); - expect(control.dragListenerKeys_.length).to.be(4); + expect(control.dragListenerKeys_.length).to.be(2); event.type = 'pointermove'; event.clientX = 0; event.clientY = 2 * control.heightLimit_ / 8; - dragger.dispatchEvent(event); + control.element.dispatchEvent(event); expect(control.currentResolution_).to.be(0.25); event.type = 'pointermove'; event.clientX = 0; event.clientY = 4 * control.heightLimit_ / 8; - dragger.dispatchEvent(event); + control.element.dispatchEvent(event); event.type = 'pointerup'; - dragger.dispatchEvent(event); + control.element.dispatchEvent(event); expect(control.currentResolution_).to.be(1); expect(control.dragListenerKeys_.length).to.be(0); expect(control.dragging_).to.be(false); }); it('[vertical] handles a drag sequence ending outside its bounds', function() { + document.createElement = createEventElement; const control = new ZoomSlider(); control.element.style.width = '10px'; control.element.style.height = '100px'; control.element.firstChild.style.width = '10px'; control.element.firstChild.style.height = '20px'; map.addControl(control); + document.createElement = createElement; map.getView().setZoom(8); map.renderSync(); - const dragger = control.dragger_; - const event = new PointerEvent('pointerdown', { - target: control.element.firstElementChild - }); + const event = new Event(); + event.type = 'pointerdown'; + event.target = control.element.firstElementChild; event.clientX = 0; event.clientY = 0; - dragger.dispatchEvent(event); + control.element.dispatchEvent(event); expect(control.currentResolution_).to.be(0.0625); expect(control.dragging_).to.be(true); - expect(control.dragListenerKeys_.length).to.be(4); + expect(control.dragListenerKeys_.length).to.be(2); event.type = 'pointermove'; event.clientX = 0; event.clientY = 2 * control.heightLimit_ / 8; - dragger.dispatchEvent(event); + control.element.dispatchEvent(event); expect(control.currentResolution_).to.be(0.25); event.type = 'pointermove'; event.clientX = 0; event.clientY = 12 * control.heightLimit_ / 8; - dragger.dispatchEvent(event); + control.element.dispatchEvent(event); event.type = 'pointerup'; - dragger.dispatchEvent(event); + control.element.dispatchEvent(event); expect(control.currentResolution_).to.be(16); expect(control.dragListenerKeys_.length).to.be(0); expect(control.dragging_).to.be(false); diff --git a/test/spec/ol/interaction/dragrotateandzoom.test.js b/test/spec/ol/interaction/dragrotateandzoom.test.js index 47bc94cab4..c1af3315d9 100644 --- a/test/spec/ol/interaction/dragrotateandzoom.test.js +++ b/test/spec/ol/interaction/dragrotateandzoom.test.js @@ -3,7 +3,7 @@ import MapBrowserPointerEvent from '../../../../src/ol/MapBrowserPointerEvent.js import View from '../../../../src/ol/View.js'; import DragRotateAndZoom from '../../../../src/ol/interaction/DragRotateAndZoom.js'; import VectorLayer from '../../../../src/ol/layer/Vector.js'; -import PointerEvent from '../../../../src/ol/pointer/PointerEvent.js'; +import Event from '../../../../src/ol/events/Event.js'; import VectorSource from '../../../../src/ol/source/Vector.js'; describe('ol.interaction.DragRotateAndZoom', function() { @@ -57,9 +57,12 @@ describe('ol.interaction.DragRotateAndZoom', function() { }); it('does not rotate when rotation is disabled on the view', function() { - let event = new MapBrowserPointerEvent('pointermove', map, - new PointerEvent('pointermove', {clientX: 20, clientY: 10}, {pointerType: 'mouse'}), - true); + const pointerEvent = new Event(); + pointerEvent.type = 'pointermove'; + pointerEvent.clientX = 20; + pointerEvent.clientY = 10; + pointerEvent.pointerType = 'mouse'; + let event = new MapBrowserPointerEvent('pointermove', map, pointerEvent, true); interaction.lastAngle_ = Math.PI; let callCount = 0; @@ -85,9 +88,11 @@ describe('ol.interaction.DragRotateAndZoom', function() { callCount++; }); - event = new MapBrowserPointerEvent('pointermove', map, - new PointerEvent('pointermove', {clientX: 24, clientY: 16}, {pointerType: 'mouse'}), - true); + pointerEvent.type = 'pointermove'; + pointerEvent.clientX = 24; + pointerEvent.clientY = 16; + pointerEvent.pointerType = 'mouse'; + event = new MapBrowserPointerEvent('pointermove', map, pointerEvent, true); interaction.handleDragEvent(event); expect(callCount).to.be(0); diff --git a/test/spec/ol/interaction/draw.test.js b/test/spec/ol/interaction/draw.test.js index 1e934b5df5..75ed153f48 100644 --- a/test/spec/ol/interaction/draw.test.js +++ b/test/spec/ol/interaction/draw.test.js @@ -15,7 +15,7 @@ import Polygon from '../../../../src/ol/geom/Polygon.js'; import Draw, {createRegularPolygon, createBox} from '../../../../src/ol/interaction/Draw.js'; import Interaction from '../../../../src/ol/interaction/Interaction.js'; import VectorLayer from '../../../../src/ol/layer/Vector.js'; -import PointerEvent from '../../../../src/ol/pointer/PointerEvent.js'; +import Event from '../../../../src/ol/events/Event.js'; import VectorSource from '../../../../src/ol/source/Vector.js'; @@ -69,14 +69,14 @@ describe('ol.interaction.Draw', function() { // calculated in case body has top < 0 (test runner with small window) const position = viewport.getBoundingClientRect(); const shiftKey = opt_shiftKey !== undefined ? opt_shiftKey : false; - const event = new PointerEvent(type, { - clientX: position.left + x + width / 2, - clientY: position.top + y + height / 2, - shiftKey: shiftKey, - preventDefault: function() {} - }, { - pointerType: 'mouse' - }); + const event = new Event(); + event.type = type; + event.clientX = position.left + x + width / 2; + event.clientY = position.top + y + height / 2; + event.shiftKey = shiftKey; + event.preventDefault = function() {}; + event.pointerType = 'mouse'; + event.pointerId = 0; const simulatedEvent = new MapBrowserPointerEvent(type, map, event); map.handleMapBrowserEvent(simulatedEvent); return simulatedEvent; diff --git a/test/spec/ol/interaction/extent.test.js b/test/spec/ol/interaction/extent.test.js index 0b6d4d6e19..56fd15765e 100644 --- a/test/spec/ol/interaction/extent.test.js +++ b/test/spec/ol/interaction/extent.test.js @@ -2,7 +2,7 @@ import Map from '../../../../src/ol/Map.js'; import MapBrowserPointerEvent from '../../../../src/ol/MapBrowserPointerEvent.js'; import View from '../../../../src/ol/View.js'; import ExtentInteraction from '../../../../src/ol/interaction/Extent.js'; -import PointerEvent from '../../../../src/ol/pointer/PointerEvent.js'; +import Event from '../../../../src/ol/events/Event.js'; describe('ol.interaction.Extent', function() { let map, interaction; @@ -50,14 +50,14 @@ describe('ol.interaction.Extent', function() { // calculated in case body has top < 0 (test runner with small window) const position = viewport.getBoundingClientRect(); const shiftKey = opt_shiftKey !== undefined ? opt_shiftKey : false; - const pointerEvent = new PointerEvent(type, { - type: type, - button: button, - clientX: position.left + x + width / 2, - clientY: position.top - y + height / 2, - shiftKey: shiftKey, - preventDefault: function() {} - }); + const pointerEvent = new Event(); + pointerEvent.type = type; + pointerEvent.button = button; + pointerEvent.clientX = position.left + x + width / 2; + pointerEvent.clientY = position.top - y + height / 2; + pointerEvent.shiftKey = shiftKey; + pointerEvent.pointerId = 0; + pointerEvent.preventDefault = function() {}; const event = new MapBrowserPointerEvent(type, map, pointerEvent); event.pointerEvent.pointerId = 1; map.handleMapBrowserEvent(event); diff --git a/test/spec/ol/interaction/modify.test.js b/test/spec/ol/interaction/modify.test.js index 5e5474424e..452d47f5d1 100644 --- a/test/spec/ol/interaction/modify.test.js +++ b/test/spec/ol/interaction/modify.test.js @@ -11,8 +11,8 @@ import Point from '../../../../src/ol/geom/Point.js'; import Polygon from '../../../../src/ol/geom/Polygon.js'; import Modify, {ModifyEvent} from '../../../../src/ol/interaction/Modify.js'; import VectorLayer from '../../../../src/ol/layer/Vector.js'; -import PointerEvent from '../../../../src/ol/pointer/PointerEvent.js'; import VectorSource from '../../../../src/ol/source/Vector.js'; +import Event from '../../../../src/ol/events/Event.js'; describe('ol.interaction.Modify', function() { @@ -81,19 +81,17 @@ describe('ol.interaction.Modify', function() { const viewport = map.getViewport(); // calculated in case body has top < 0 (test runner with small window) const position = viewport.getBoundingClientRect(); - const pointerEvent = new PointerEvent(type, { - type: type, - clientX: position.left + x + width / 2, - clientY: position.top + y + height / 2, - shiftKey: modifiers.shift || false, - altKey: modifiers.alt || false, - preventDefault: function() {} - }, { - button: button, - isPrimary: true - }); + const pointerEvent = new Event(); + pointerEvent.type = type; + pointerEvent.clientX = position.left + x + width / 2; + pointerEvent.clientY = position.top + y + height / 2; + pointerEvent.shiftKey = modifiers.shift || false; + pointerEvent.altKey = modifiers.alt || false; + pointerEvent.pointerId = 1; + pointerEvent.preventDefault = function() {}; + pointerEvent.button = button; + pointerEvent.isPrimary = true; const event = new MapBrowserPointerEvent(type, map, pointerEvent); - event.pointerEvent.pointerId = 1; map.handleMapBrowserEvent(event); } diff --git a/test/spec/ol/interaction/pointer.test.js b/test/spec/ol/interaction/pointer.test.js index 462a4686ce..86c9857326 100644 --- a/test/spec/ol/interaction/pointer.test.js +++ b/test/spec/ol/interaction/pointer.test.js @@ -1,6 +1,6 @@ import Map from '../../../../src/ol/Map.js'; import MapBrowserPointerEvent from '../../../../src/ol/MapBrowserPointerEvent.js'; -import PointerEvent from '../../../../src/ol/pointer/PointerEvent.js'; +import Event from '../../../../src/ol/events/Event.js'; import PointerInteraction from '../../../../src/ol/interaction/Pointer.js'; describe('ol.interaction.Pointer', function() { @@ -12,12 +12,12 @@ describe('ol.interaction.Pointer', function() { beforeEach(function() { const type = 'pointerdown'; - const pointerEvent = new PointerEvent(type, { - type: type, - preventDefault: function() { - defaultPrevented = true; - } - }); + const pointerEvent = new Event(); + pointerEvent.type = type; + pointerEvent.pointerId = 0; + pointerEvent.preventDefault = function() { + defaultPrevented = true; + }; event = new MapBrowserPointerEvent(type, new Map(), pointerEvent); defaultPrevented = false; }); diff --git a/test/spec/ol/interaction/select.test.js b/test/spec/ol/interaction/select.test.js index 0445fecf53..9dc9e562e1 100644 --- a/test/spec/ol/interaction/select.test.js +++ b/test/spec/ol/interaction/select.test.js @@ -8,7 +8,6 @@ import Polygon from '../../../../src/ol/geom/Polygon.js'; import Interaction from '../../../../src/ol/interaction/Interaction.js'; import Select from '../../../../src/ol/interaction/Select.js'; import VectorLayer from '../../../../src/ol/layer/Vector.js'; -import PointerEvent from '../../../../src/ol/pointer/PointerEvent.js'; import VectorSource from '../../../../src/ol/source/Vector.js'; diff --git a/test/spec/ol/interaction/translate.test.js b/test/spec/ol/interaction/translate.test.js index d2b9d41825..a3df2ccebe 100644 --- a/test/spec/ol/interaction/translate.test.js +++ b/test/spec/ol/interaction/translate.test.js @@ -7,7 +7,6 @@ import Point from '../../../../src/ol/geom/Point.js'; import Translate, {TranslateEvent} from '../../../../src/ol/interaction/Translate.js'; import Interaction from '../../../../src/ol/interaction/Interaction.js'; import VectorLayer from '../../../../src/ol/layer/Vector.js'; -import PointerEvent from '../../../../src/ol/pointer/PointerEvent.js'; import VectorSource from '../../../../src/ol/source/Vector.js'; diff --git a/test/spec/ol/mapbrowserevent.test.js b/test/spec/ol/mapbrowserevent.test.js index b67b0435d2..846b457282 100644 --- a/test/spec/ol/mapbrowserevent.test.js +++ b/test/spec/ol/mapbrowserevent.test.js @@ -2,7 +2,7 @@ import Map from '../../../src/ol/Map.js'; import MapBrowserEventHandler from '../../../src/ol/MapBrowserEventHandler.js'; import {listen} from '../../../src/ol/events.js'; import {DEVICE_PIXEL_RATIO} from '../../../src/ol/has.js'; -import PointerEvent from '../../../src/ol/pointer/PointerEvent.js'; +import Event from '../../../src/ol/events/Event.js'; describe('ol.MapBrowserEventHandler', function() { describe('#emulateClick_', function() { @@ -36,22 +36,22 @@ describe('ol.MapBrowserEventHandler', function() { }); it('emulates click', function() { - handler.emulateClick_(new PointerEvent('pointerdown', { - type: 'mousedown', - target: target, - clientX: 0, - clientY: 0 - })); + const event = new Event(); + event.type = 'pointerdown'; + event.target = target, + event.clientX = 0; + event.clientY = 0; + handler.emulateClick_(event); expect(clickSpy.called).to.be.ok(); }); it('emulates singleclick', function() { - handler.emulateClick_(new PointerEvent('pointerdown', { - type: 'mousedown', - target: target, - clientX: 0, - clientY: 0 - })); + const event = new Event(); + event.type = 'pointerdown'; + event.target = target; + event.clientX = 0; + event.clientY = 0; + handler.emulateClick_(event); expect(singleclickSpy.called).to.not.be.ok(); expect(dblclickSpy.called).to.not.be.ok(); @@ -59,32 +59,22 @@ describe('ol.MapBrowserEventHandler', function() { expect(singleclickSpy.calledOnce).to.be.ok(); expect(dblclickSpy.called).to.not.be.ok(); - handler.emulateClick_(new PointerEvent('pointerdown', { - type: 'mousedown', - target: target, - clientX: 0, - clientY: 0 - })); + handler.emulateClick_(event); expect(singleclickSpy.calledOnce).to.be.ok(); expect(dblclickSpy.called).to.not.be.ok(); }); it('emulates dblclick', function() { - handler.emulateClick_(new PointerEvent('pointerdown', { - type: 'mousedown', - target: target, - clientX: 0, - clientY: 0 - })); + const event = new Event(); + event.type = 'pointerdown'; + event.target = target; + event.clientX = 0; + event.clientY = 0; + handler.emulateClick_(event); expect(singleclickSpy.called).to.not.be.ok(); expect(dblclickSpy.called).to.not.be.ok(); - handler.emulateClick_(new PointerEvent('pointerdown', { - type: 'mousedown', - target: target, - clientX: 0, - clientY: 0 - })); + handler.emulateClick_(event); expect(singleclickSpy.called).to.not.be.ok(); expect(dblclickSpy.calledOnce).to.be.ok(); @@ -107,7 +97,7 @@ describe('ol.MapBrowserEventHandler', function() { }); it('is an event after handlePointerDown_ has been called', function() { - const event = new PointerEvent('pointerdown', {}); + const event = new Event('pointerdown'); handler.handlePointerDown_(event); expect(handler.down_).to.be(event); }); @@ -121,65 +111,65 @@ describe('ol.MapBrowserEventHandler', function() { beforeEach(function() { defaultHandler = new MapBrowserEventHandler(new Map({})); moveToleranceHandler = new MapBrowserEventHandler(new Map({}), 8); - pointerdownAt0 = new PointerEvent('pointerdown', {}, { - clientX: 0, - clientY: 0 - }); + pointerdownAt0 = new Event(); + pointerdownAt0.type = 'pointerdown'; + pointerdownAt0.clientX = 0; + pointerdownAt0.clientY = 0; defaultHandler.handlePointerDown_(pointerdownAt0); moveToleranceHandler.handlePointerDown_(pointerdownAt0); }); it('is not moving if distance is 0', function() { - const pointerdownAt0 = new PointerEvent('pointerdown', {}, { - clientX: 0, - clientY: 0 - }); + pointerdownAt0 = new Event(); + pointerdownAt0.type = 'pointerdown'; + pointerdownAt0.clientX = 0; + pointerdownAt0.clientY = 0; expect(defaultHandler.isMoving_(pointerdownAt0)).to.be(false); }); it('is moving if distance is 2', function() { - const pointerdownAt2 = new PointerEvent('pointerdown', {}, { - clientX: DEVICE_PIXEL_RATIO + 1, - clientY: DEVICE_PIXEL_RATIO + 1 - }); + const pointerdownAt2 = new Event(); + pointerdownAt2.type = 'pointerdown'; + pointerdownAt2.clientX = DEVICE_PIXEL_RATIO + 1; + pointerdownAt2.clientY = DEVICE_PIXEL_RATIO + 1; expect(defaultHandler.isMoving_(pointerdownAt2)).to.be(true); }); it('is moving with negative distance', function() { - const pointerdownAt2 = new PointerEvent('pointerdown', {}, { - clientX: -(DEVICE_PIXEL_RATIO + 1), - clientY: -(DEVICE_PIXEL_RATIO + 1) - }); + const pointerdownAt2 = new Event(); + pointerdownAt2.type = 'pointerdown'; + pointerdownAt2.clientX = -(DEVICE_PIXEL_RATIO + 1); + pointerdownAt2.clientY = -(DEVICE_PIXEL_RATIO + 1); expect(defaultHandler.isMoving_(pointerdownAt2)).to.be(true); }); it('is not moving if distance is less than move tolerance', function() { - const pointerdownAt2 = new PointerEvent('pointerdown', {}, { - clientX: DEVICE_PIXEL_RATIO + 1, - clientY: DEVICE_PIXEL_RATIO + 1 - }); + const pointerdownAt2 = new Event(); + pointerdownAt2.type = 'pointerdown'; + pointerdownAt2.clientX = DEVICE_PIXEL_RATIO + 1; + pointerdownAt2.clientY = DEVICE_PIXEL_RATIO + 1; expect(moveToleranceHandler.isMoving_(pointerdownAt2)).to.be(false); }); it('is moving if distance is greater than move tolerance', function() { - const pointerdownAt9 = new PointerEvent('pointerdown', {}, { - clientX: (DEVICE_PIXEL_RATIO * 8) + 1, - clientY: (DEVICE_PIXEL_RATIO * 8) + 1 - }); + const pointerdownAt9 = new Event(); + pointerdownAt9.type = 'pointerdown'; + pointerdownAt9.clientX = (DEVICE_PIXEL_RATIO * 8) + 1; + pointerdownAt9.clientY = (DEVICE_PIXEL_RATIO * 8) + 1; expect(moveToleranceHandler.isMoving_(pointerdownAt9)).to.be(true); }); it('is moving when moving back close to the down pixel', function() { - const pointermoveAt9 = new PointerEvent('pointermove', {}, { - clientX: (DEVICE_PIXEL_RATIO * 8) + 1, - clientY: (DEVICE_PIXEL_RATIO * 8) + 1 - }); + const pointermoveAt9 = new Event(); + pointermoveAt9.type = 'pointermove'; + pointermoveAt9.clientX = (DEVICE_PIXEL_RATIO * 8) + 1; + pointermoveAt9.clientY = (DEVICE_PIXEL_RATIO * 8) + 1; moveToleranceHandler.handlePointerMove_(pointermoveAt9); expect(moveToleranceHandler.isMoving_(pointermoveAt9)).to.be(true); - const pointermoveAt2 = new PointerEvent('pointermove', {}, { - clientX: DEVICE_PIXEL_RATIO + 1, - clientY: DEVICE_PIXEL_RATIO + 1 - }); + const pointermoveAt2 = new Event(); + pointermoveAt2.type = 'pointermove'; + pointermoveAt2.clientX = DEVICE_PIXEL_RATIO + 1; + pointermoveAt2.clientY = DEVICE_PIXEL_RATIO + 1; moveToleranceHandler.handlePointerMove_(pointermoveAt2); expect(moveToleranceHandler.isMoving_(pointermoveAt2)).to.be(true); }); diff --git a/test/spec/ol/pointer/mousesource.test.js b/test/spec/ol/pointer/mousesource.test.js deleted file mode 100644 index 0fd78d4944..0000000000 --- a/test/spec/ol/pointer/mousesource.test.js +++ /dev/null @@ -1,118 +0,0 @@ -import {listen} from '../../../../src/ol/events.js'; -import EventTarget from '../../../../src/ol/events/Target.js'; -import PointerEventHandler from '../../../../src/ol/pointer/PointerEventHandler.js'; -import TouchSource from '../../../../src/ol/pointer/TouchSource.js'; -import MouseSource from '../../../../src/ol/pointer/MouseSource.js'; -import MsSource from '../../../../src/ol/pointer/MsSource.js'; -import NativeSource from '../../../../src/ol/pointer/NativeSource.js'; - - -describe('ol.pointer.MouseSource', function() { - let handler; - let target; - let eventSpy; - let clock; - - beforeEach(function() { - clock = sinon.useFakeTimers(); - target = new EventTarget(); - - // make sure that a mouse and touch event source is used - const POINTER = false; - const MSPOINTER = false; - const TOUCH = true; - const originalRegisterSources = PointerEventHandler.prototype.registerSources; - PointerEventHandler.prototype.registerSources = function() { - if (POINTER) { - this.registerSource('native', new NativeSource(this)); - } else if (MSPOINTER) { - this.registerSource('ms', new MsSource(this)); - } else { - const mouseSource = new MouseSource(this); - this.registerSource('mouse', mouseSource); - - if (TOUCH) { - const touchSource = new TouchSource(this, mouseSource); - // set the timeout to a lower value, to speed up the tests - touchSource.dedupTimeout_ = 100; - - this.registerSource('touch', touchSource); - } - } - - // register events on the viewport element - this.register_(); - }; - - handler = new PointerEventHandler(target); - PointerEventHandler.prototype.registerSources = originalRegisterSources; - - eventSpy = sinon.spy(); - }); - - afterEach(function() { - clock.restore(); - handler.dispose(); - }); - - describe('simulated mouse events', function() { - it('prevents simulated mouse events', function() { - listen(handler, 'pointerdown', eventSpy); - - // simulates that a mouse event is triggered from a touch - simulateTouchEvent('touchstart', 10, 20); - simulateEvent('mousedown', 10, 20); - - expect(eventSpy.calledOnce).to.be.ok(); - - }); - - it('dispatches real mouse events', function() { - listen(handler, 'pointerdown', eventSpy); - - // the two events are at different positions - simulateTouchEvent('touchstart', 10, 20); - simulateEvent('mousedown', 10, 50); - - expect(eventSpy.calledTwice).to.be.ok(); - }); - - it('dispatches real mouse events after timeout', function() { - listen(handler, 'pointerdown', eventSpy); - - // first simulate a touch event, then a mouse event - // at the same position after a timeout - simulateTouchEvent('touchstart', 10, 20); - clock.tick(150); - simulateEvent('mousedown', 10, 20); - - expect(eventSpy.calledTwice).to.be.ok(); - }); - }); - - function simulateTouchEvent(type, x, y) { - const touches = [{ - identifier: 4, - clientX: x, - clientY: y, - target: target - }]; - - const event = { - type: type, - touches: touches, - changedTouches: touches - }; - target.dispatchEvent(event); - } - - function simulateEvent(type, x, y) { - const event = { - type: type, - clientX: x, - clientY: y, - target: target - }; - target.dispatchEvent(event); - } -}); diff --git a/test/spec/ol/pointer/pointereventhandler.test.js b/test/spec/ol/pointer/pointereventhandler.test.js deleted file mode 100644 index 742de5ceb4..0000000000 --- a/test/spec/ol/pointer/pointereventhandler.test.js +++ /dev/null @@ -1,190 +0,0 @@ -import {listen} from '../../../../src/ol/events.js'; -import EventTarget from '../../../../src/ol/events/Target.js'; -import MouseSource from '../../../../src/ol/pointer/MouseSource.js'; -import PointerEvent from '../../../../src/ol/pointer/PointerEvent.js'; -import PointerEventHandler from '../../../../src/ol/pointer/PointerEventHandler.js'; -import TouchSource from '../../../../src/ol/pointer/TouchSource.js'; -import MsSource from '../../../../src/ol/pointer/MsSource.js'; -import NativeSource from '../../../../src/ol/pointer/NativeSource.js'; - - -describe('ol.pointer.PointerEventHandler', function() { - let handler; - let target; - let eventSpy; - - beforeEach(function() { - target = new EventTarget(); - - // make sure that a mouse event source is used - const POINTER = false; - const MSPOINTER = false; - const TOUCH = false; - const originalRegisterSources = PointerEventHandler.prototype.registerSources; - PointerEventHandler.prototype.registerSources = function() { - if (POINTER) { - this.registerSource('native', new NativeSource(this)); - } else if (MSPOINTER) { - this.registerSource('ms', new MsSource(this)); - } else { - const mouseSource = new MouseSource(this); - this.registerSource('mouse', mouseSource); - - if (TOUCH) { - this.registerSource('touch', new TouchSource(this, mouseSource)); - } - } - - // register events on the viewport element - this.register_(); - }; - - handler = new PointerEventHandler(target); - PointerEventHandler.prototype.registerSources = originalRegisterSources; - - eventSpy = sinon.spy(); - }); - - afterEach(function() { - handler.dispose(); - }); - - - describe('constructor', function() { - it('registers a least one event source', function() { - expect(handler.eventSourceList_.length).to.be.greaterThan(0); - expect(handler.eventSourceList_[0]).to.be.a(MouseSource); - }); - }); - - function simulateEvent(type, x, y) { - const event = { - type: type, - clientX: x, - clientY: y, - target: target - }; - target.dispatchEvent(event); - } - - describe('pointer down', function() { - it('fires pointerdown events', function() { - listen(handler, 'pointerdown', eventSpy); - simulateEvent('mousedown', 0, 0); - expect(eventSpy.calledOnce).to.be.ok(); - - const pointerEvent = eventSpy.firstCall.args[0]; - expect(pointerEvent).to.be.a(PointerEvent); - expect(pointerEvent.type).to.be('pointerdown'); - expect(pointerEvent.pointerId).to.be(1); - expect(pointerEvent.pointerType).to.be('mouse'); - }); - }); - - describe('pointer up', function() { - it('fires pointerup events', function() { - listen(handler, 'pointerup', eventSpy); - simulateEvent('mousedown', 0, 0); - simulateEvent('mouseup', 0, 0); - expect(eventSpy.calledOnce).to.be.ok(); - }); - }); - - describe('pointer move', function() { - it('fires pointermove events', function() { - listen(handler, 'pointermove', eventSpy); - simulateEvent('mousemove', 0, 0); - expect(eventSpy.calledOnce).to.be.ok(); - }); - }); - - describe('pointer enter and over', function() { - it('fires pointerenter and pointerover events', function() { - const enterEventSpy = sinon.spy(); - const overEventSpy = sinon.spy(); - - listen(handler, 'pointerenter', enterEventSpy); - listen(handler, 'pointerover', overEventSpy); - - simulateEvent('mouseover', 0, 0); - - expect(enterEventSpy.calledOnce).to.be.ok(); - expect(overEventSpy.calledOnce).to.be.ok(); - }); - }); - - describe('pointer leave and out', function() { - it('fires pointerleave and pointerout events', function() { - const leaveEventSpy = sinon.spy(); - const outEventSpy = sinon.spy(); - - listen(handler, 'pointerleave', leaveEventSpy); - listen(handler, 'pointerout', outEventSpy); - - simulateEvent('mouseout', 0, 0); - - expect(leaveEventSpy.calledOnce).to.be.ok(); - expect(outEventSpy.calledOnce).to.be.ok(); - }); - }); - - describe('#cloneEvent', function() { - it('copies the properties of an event', function() { - const event = { - type: 'mousedown', - target: target, - clientX: 1, - clientY: 2 - }; - const browserEvent = event; - - const eventClone = handler.cloneEvent(browserEvent, event); - - // properties are copied from `event` - expect(eventClone.type).to.be('mousedown'); - expect(eventClone.target).to.be(target); - expect(eventClone.clientX).to.be(1); - expect(eventClone.clientY).to.be(2); - - // properties are copied from `browserEvent` - expect(eventClone.screenX).to.be(0); - expect(eventClone.screenY).to.be(0); - - // properties are copied from the defaults - expect(eventClone.pointerId).to.be(0); - expect(eventClone.pressure).to.be(0); - - }); - }); - - describe('#makeEvent', function() { - it('makes a new pointer event', function() { - const event = { - type: 'mousedown', - target: target, - clientX: 1, - clientY: 2 - }; - const browserEvent = event; - - const eventClone = handler.cloneEvent(browserEvent, event); - const pointerEvent = handler.makeEvent('pointerdown', - eventClone, browserEvent); - - expect(pointerEvent.type).to.be('pointerdown'); - expect(pointerEvent.clientX).to.be(1); - expect(pointerEvent.clientY).to.be(2); - - expect(pointerEvent.screenX).to.be(0); - expect(pointerEvent.screenY).to.be(0); - - expect(pointerEvent.pointerId).to.be(0); - expect(pointerEvent.pressure).to.be(0); - - expect(pointerEvent.preventDefault).to.be.ok(); - - expect(pointerEvent).to.be.a(PointerEvent); - }); - }); - -}); diff --git a/test/spec/ol/pointer/touchsource.test.js b/test/spec/ol/pointer/touchsource.test.js deleted file mode 100644 index a10d409821..0000000000 --- a/test/spec/ol/pointer/touchsource.test.js +++ /dev/null @@ -1,156 +0,0 @@ -import {listen} from '../../../../src/ol/events.js'; -import Event from '../../../../src/ol/events/Event.js'; -import EventTarget from '../../../../src/ol/events/Target.js'; -import {assign} from '../../../../src/ol/obj.js'; -import PointerEventHandler from '../../../../src/ol/pointer/PointerEventHandler.js'; -import TouchSource from '../../../../src/ol/pointer/TouchSource.js'; -import MouseSource from '../../../../src/ol/pointer/MouseSource.js'; -import MsSource from '../../../../src/ol/pointer/MsSource.js'; -import NativeSource from '../../../../src/ol/pointer/NativeSource.js'; - -describe('ol.pointer.TouchSource', function() { - let handler; - let target; - let eventSpy; - - beforeEach(function() { - target = new EventTarget(); - - // make sure that a mouse and touch event source is used - const POINTER = false; - const MSPOINTER = false; - const TOUCH = true; - const originalRegisterSources = PointerEventHandler.prototype.registerSources; - PointerEventHandler.prototype.registerSources = function() { - if (POINTER) { - this.registerSource('native', new NativeSource(this)); - } else if (MSPOINTER) { - this.registerSource('ms', new MsSource(this)); - } else { - const mouseSource = new MouseSource(this); - this.registerSource('mouse', mouseSource); - - if (TOUCH) { - this.registerSource('touch', new TouchSource(this, mouseSource)); - } - } - - // register events on the viewport element - this.register_(); - }; - - handler = new PointerEventHandler(target); - PointerEventHandler.prototype.registerSources = originalRegisterSources; - - eventSpy = sinon.spy(); - }); - - afterEach(function() { - handler.dispose(); - }); - - describe('pointer event creation', function() { - it('generates pointer events for each touch contact', function() { - listen(handler, 'pointerdown', eventSpy); - - simulateTouchEvent('touchstart', [ - {identifier: 3, clientX: 10, clientY: 11}, - {identifier: 4, clientX: 30, clientY: 45} - ]); - - expect(eventSpy.calledTwice).to.be.ok(); - - // pointer event for the first touch contact - const pointerEvent1 = eventSpy.firstCall.args[0]; - expect(pointerEvent1.pointerId).to.be(5); - expect(pointerEvent1.pointerType).to.be('touch'); - expect(pointerEvent1.clientX).to.be(10); - expect(pointerEvent1.clientY).to.be(11); - - // pointer event for the second touch contact - const pointerEvent2 = eventSpy.secondCall.args[0]; - expect(pointerEvent2.pointerId).to.be(6); - expect(pointerEvent2.pointerType).to.be('touch'); - expect(pointerEvent2.clientX).to.be(30); - expect(pointerEvent2.clientY).to.be(45); - - expect(Object.keys(handler.pointerMap).length).to.be(2); - }); - - it('creates the right pointer events', function() { - listen(handler, 'pointerdown', eventSpy); - - // first touch - simulateTouchEvent('touchstart', [ - {identifier: 3, clientX: 10, clientY: 11} - ]); - expect(eventSpy.calledOnce).to.be.ok(); - expect(Object.keys(handler.pointerMap).length).to.be(1); - - // second touch (first touch still down) - simulateTouchEvent('touchstart', [ - {identifier: 4, clientX: 30, clientY: 45} - ], [{identifier: 3}, {identifier: 4}] - ); - expect(eventSpy.calledTwice).to.be.ok(); - expect(Object.keys(handler.pointerMap).length).to.be(2); - - // first touch moves - const moveEventSpy = sinon.spy(); - listen(handler, 'pointermove', moveEventSpy); - - simulateTouchEvent('touchmove', [ - {identifier: 3, clientX: 15, clientY: 16} - ], [{identifier: 3}, {identifier: 4}] - ); - expect(moveEventSpy.calledOnce).to.be.ok(); - - // and then both touches go up - const upEventSpy = sinon.spy(); - listen(handler, 'pointerup', upEventSpy); - - simulateTouchEvent('touchend', [ - {identifier: 3, clientX: 15, clientY: 16}, - {identifier: 4, clientX: 30, clientY: 45} - ], [{identifier: 3}, {identifier: 4}] - ); - expect(upEventSpy.calledTwice).to.be.ok(); - expect(Object.keys(handler.pointerMap).length).to.be(0); - }); - - it('handles flawed touches', function() { - listen(handler, 'pointerdown', eventSpy); - - // first touch - simulateTouchEvent('touchstart', [ - {identifier: 3, clientX: 10, clientY: 11} - ]); - expect(eventSpy.calledOnce).to.be.ok(); - expect(Object.keys(handler.pointerMap).length).to.be(1); - - // second touch, but the first touch has disappeared - const cancelEventSpy = sinon.spy(); - listen(handler, 'pointercancel', cancelEventSpy); - simulateTouchEvent('touchstart', [ - {identifier: 4, clientX: 30, clientY: 45} - ], [{identifier: 4}] - ); - expect(eventSpy.calledTwice).to.be.ok(); - - // the first (broken) touch is canceled - expect(cancelEventSpy.calledOnce).to.be.ok(); - expect(Object.keys(handler.pointerMap).length).to.be(1); - }); - }); - - function simulateTouchEvent(type, changedTouches, touches) { - touches = touches !== undefined ? touches : changedTouches; - - const event = new Event(type); - assign(event, { - touches: touches, - changedTouches: changedTouches - }); - target.dispatchEvent(event); - } -});