From 2e3e7d282aed240e00dd2ae04eb04bfd5051865a Mon Sep 17 00:00:00 2001 From: Pete Schmitt Date: Wed, 7 Feb 2018 16:14:03 -0700 Subject: [PATCH 1/3] Adds option to retain MousePosition when pointer leaves viewport --- src/ol/control/MousePosition.js | 12 ++- test/spec/ol/control/mouseposition.test.js | 92 ++++++++++++++++++++++ 2 files changed, 100 insertions(+), 4 deletions(-) diff --git a/src/ol/control/MousePosition.js b/src/ol/control/MousePosition.js index b36abdc8ee..1fc373506d 100644 --- a/src/ol/control/MousePosition.js +++ b/src/ol/control/MousePosition.js @@ -72,6 +72,8 @@ const MousePosition = function(opt_options) { this.setProjection(options.projection); } + this.clearOnMouseOut_ = options.clearOnMouseOut !== undefined ? options.clearOnMouseOut : true; + /** * @private * @type {string} @@ -190,11 +192,13 @@ MousePosition.prototype.setMap = function(map) { if (map) { const viewport = map.getViewport(); this.listenerKeys.push( - listen(viewport, EventType.MOUSEMOVE, - this.handleMouseMove, this), - listen(viewport, EventType.MOUSEOUT, - this.handleMouseOut, this) + listen(viewport, EventType.MOUSEMOVE, this.handleMouseMove, this) ); + if (this.clearOnMouseOut_) { + this.listenerKeys.push( + listen(viewport, EventType.MOUSEOUT, this.handleMouseOut, this) + ); + } } }; diff --git a/test/spec/ol/control/mouseposition.test.js b/test/spec/ol/control/mouseposition.test.js index d0de8ae158..8a374f7226 100644 --- a/test/spec/ol/control/mouseposition.test.js +++ b/test/spec/ol/control/mouseposition.test.js @@ -1,4 +1,8 @@ +import Map from '../../../../src/ol/Map.js'; import MousePosition from '../../../../src/ol/control/MousePosition.js'; +import View from '../../../../src/ol/View.js'; + +import EventType from '../../../../src/ol/events/EventType.js'; describe('ol.control.MousePosition', function() { @@ -20,4 +24,92 @@ describe('ol.control.MousePosition', function() { }); + describe('configuration options', function() { + let target, map; + const width = 360; + const height = 180; + + beforeEach(function() { + target = document.createElement('div'); + const style = target.style; + style.position = 'absolute'; + style.left = '-1000px'; + style.top = '-1000px'; + style.width = width + 'px'; + style.height = height + 'px'; + + document.body.appendChild(target); + map = new Map({ + target: target, + controls: [], + view: new View({ + projection: 'EPSG:4326', + center: [0, 0], + resolution: 1 + }) + }); + }); + afterEach(function() { + map.dispose(); + document.body.removeChild(target); + }); + + function simulateEvent(type, x, y) { + const viewport = map.getViewport(); + // calculated in case body has top < 0 (test runner with small window) + const position = viewport.getBoundingClientRect(); + const evt = new MouseEvent(type, { + clientX: position.left + x + width / 2, + clientY: position.top + y + height / 2 + }); + document.querySelector('div.ol-viewport').dispatchEvent(evt); + } + + describe('clearOnMouseOut', function() { + it('sets div.ol-mouse-position undefinedHTML when clearOnMouseOut=true', function(done) { + const ctrl = new MousePosition({ + undefinedHTML: 'undefined', + clearOnMouseOut: true + }); + ctrl.setMap(map); + map.renderSync(); + + const element = document.querySelector('.ol-mouse-position', map.getTarget()); + expect(element.innerText).to.be('undefined'); + + simulateEvent(EventType.MOUSEMOVE, 20, 30); + map.renderSync(); + expect(element.innerText).to.be('20,-30'); + + map.once('postrender', function() { + expect(element.innerText).to.be('undefined'); + done(); + }); + simulateEvent(EventType.MOUSEOUT, width + 1, height + 1); + map.renderSync(); + }); + + it('keeps div.ol-mouse-position set when clearOnMouseOut=false', function(done) { + const ctrl = new MousePosition({ + undefinedHTML: 'undefined', + clearOnMouseOut: false + }); + ctrl.setMap(map); + map.renderSync(); + + const element = document.querySelector('.ol-mouse-position', map.getTarget()); + expect(element.innerText).to.be('undefined'); + + target.dispatchEvent(new MouseEvent('mousemove')); + simulateEvent(EventType.MOUSEMOVE, 20, 30); + map.renderSync(); + map.once('postrender', function() { + expect(element.innerText).to.be('20,-30'); + done(); + }); + simulateEvent(EventType.MOUSEOUT, width + 1, height + 1); + map.renderSync(); + }); + }); + }); }); From 2719baa0f636be61b7fd210db454c55dab9009d4 Mon Sep 17 00:00:00 2001 From: Pete Schmitt Date: Thu, 8 Feb 2018 11:49:27 -0700 Subject: [PATCH 2/3] Replace new clearOnMouseOut option with `undefinedHTML=undefined` API break: set `undefinedHTML` to special value `undefined` to retain the most recent MousePosition value. --- src/ol/control/MousePosition.js | 14 +++++++++----- test/spec/ol/control/mouseposition.test.js | 18 ++++++++---------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/ol/control/MousePosition.js b/src/ol/control/MousePosition.js index 1fc373506d..d151a964bd 100644 --- a/src/ol/control/MousePosition.js +++ b/src/ol/control/MousePosition.js @@ -72,13 +72,17 @@ const MousePosition = function(opt_options) { this.setProjection(options.projection); } - this.clearOnMouseOut_ = options.clearOnMouseOut !== undefined ? options.clearOnMouseOut : true; - /** * @private * @type {string} */ - this.undefinedHTML_ = options.undefinedHTML !== undefined ? options.undefinedHTML : ''; + this.undefinedHTML_ = 'undefinedHTML' in options ? options.undefinedHTML : ''; + + /** + * @private + * @type {boolean} + */ + this.renderOnMouseOut_ = this.undefinedHTML_ !== undefined; /** * @private @@ -194,7 +198,7 @@ MousePosition.prototype.setMap = function(map) { this.listenerKeys.push( listen(viewport, EventType.MOUSEMOVE, this.handleMouseMove, this) ); - if (this.clearOnMouseOut_) { + if (this.renderOnMouseOut_) { this.listenerKeys.push( listen(viewport, EventType.MOUSEOUT, this.handleMouseOut, this) ); @@ -232,7 +236,7 @@ MousePosition.prototype.setProjection = function(projection) { * @private */ MousePosition.prototype.updateHTML_ = function(pixel) { - let html = this.undefinedHTML_; + let html = this.undefinedHTML_ === undefined ? ' ' : this.undefinedHTML_; if (pixel && this.mapProjection_) { if (!this.transform_) { const projection = this.getProjection(); diff --git a/test/spec/ol/control/mouseposition.test.js b/test/spec/ol/control/mouseposition.test.js index 8a374f7226..acd584c8da 100644 --- a/test/spec/ol/control/mouseposition.test.js +++ b/test/spec/ol/control/mouseposition.test.js @@ -65,40 +65,38 @@ describe('ol.control.MousePosition', function() { document.querySelector('div.ol-viewport').dispatchEvent(evt); } - describe('clearOnMouseOut', function() { - it('sets div.ol-mouse-position undefinedHTML when clearOnMouseOut=true', function(done) { + describe('undefinedHTML', function() { + it('sets div.ol-mouse-position to options.undefinedHTML when mouse moves out', function(done) { const ctrl = new MousePosition({ - undefinedHTML: 'undefined', - clearOnMouseOut: true + undefinedHTML: 'some text' }); ctrl.setMap(map); map.renderSync(); const element = document.querySelector('.ol-mouse-position', map.getTarget()); - expect(element.innerText).to.be('undefined'); + expect(element.innerText).to.be('some text'); simulateEvent(EventType.MOUSEMOVE, 20, 30); map.renderSync(); expect(element.innerText).to.be('20,-30'); map.once('postrender', function() { - expect(element.innerText).to.be('undefined'); + expect(element.innerText).to.be('some text'); done(); }); simulateEvent(EventType.MOUSEOUT, width + 1, height + 1); map.renderSync(); }); - it('keeps div.ol-mouse-position set when clearOnMouseOut=false', function(done) { + it('Retain mouse position in div.ol-mouse-position when options.undefinedHTML=undefined and mouse moves outside the viewport', function(done) { const ctrl = new MousePosition({ - undefinedHTML: 'undefined', - clearOnMouseOut: false + undefinedHTML: undefined }); ctrl.setMap(map); map.renderSync(); const element = document.querySelector('.ol-mouse-position', map.getTarget()); - expect(element.innerText).to.be('undefined'); + expect(element.innerHTML).to.be(' '); target.dispatchEvent(new MouseEvent('mousemove')); simulateEvent(EventType.MOUSEMOVE, 20, 30); From d6409f55cf1ca84739cebbf878128f2d0fe83494 Mon Sep 17 00:00:00 2001 From: ahocevar Date: Mon, 23 Apr 2018 08:49:38 +0200 Subject: [PATCH 3/3] Update API docs for modified behavior. --- src/ol/control/MousePosition.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ol/control/MousePosition.js b/src/ol/control/MousePosition.js index d151a964bd..e46060789a 100644 --- a/src/ol/control/MousePosition.js +++ b/src/ol/control/MousePosition.js @@ -31,7 +31,9 @@ const COORDINATE_FORMAT = 'coordinateFormat'; * callback. * @property {Element|string} [target] Specify a target if you want the * control to be rendered outside of the map's viewport. - * @property {string} [undefinedHTML=''] Markup for undefined coordinates. + * @property {string} [undefinedHTML=''] Markup for undefined coordinates. If + * `undefined`, then the last pointer position is retained when the pointer + * moves outside the viewport. */