diff --git a/changelog/upgrade-notes.md b/changelog/upgrade-notes.md index cb4a84af8d..84778891e6 100644 --- a/changelog/upgrade-notes.md +++ b/changelog/upgrade-notes.md @@ -14,6 +14,17 @@ If desired, e.g. when you don't want to adjust your code after upgrading from a "ol/*": ["node_modules/@types/ol/*"] }, ``` +#### Deprecation of `undefinedHTML` option for the MousePosition control + +The `undefinedHTML` option for the MousePosition control has been deprecated and will be removed in a future release. Use the new `placeholder` option instead. + +#### New `placeholder` option for the MousePosition control + +When the mouse position is not available, the control renders a non-breaking space. To render somthing else instead, +set the `placeholder` option. If you want to retain the last position when the mouse leaves the viewport, set +`placeholder: false`. This will be the default behavior in a future release. + +The `placeholder` option has no effect if the deprecated `undefinedHTML` option is also used. You should use the `placeholder` option instead of `undefinedHTML`. #### Deprecation of `image` render mode for vector tile layers diff --git a/examples/mouse-position.js b/examples/mouse-position.js index 5b198c3030..0849a38604 100644 --- a/examples/mouse-position.js +++ b/examples/mouse-position.js @@ -13,7 +13,6 @@ const mousePositionControl = new MousePosition({ // be placed within the map. className: 'custom-mouse-position', target: document.getElementById('mouse-position'), - undefinedHTML: ' ', }); const map = new Map({ diff --git a/src/ol/control/MousePosition.js b/src/ol/control/MousePosition.js index a8658548fb..0e4680d235 100644 --- a/src/ol/control/MousePosition.js +++ b/src/ol/control/MousePosition.js @@ -41,11 +41,13 @@ const COORDINATE_FORMAT = 'coordinateFormat'; * callback. * @property {HTMLElement|string} [target] Specify a target if you want the * control to be rendered outside of the map's viewport. - * @property {string} [undefinedHTML=' '] Markup to show when coordinates are not - * available (e.g. when the pointer leaves the map viewport). By default, the last position - * will be replaced with `' '` (` `) when the pointer leaves the viewport. To - * retain the last rendered position, set this option to something falsey. An exception is an - * empty string `''`. It does not count as falsey in this case. + * @property {string|boolean} [placeholder] Markup to show when the mouse position is not + * available (e.g. when the pointer leaves the map viewport). By default, a non-breaking space + * is rendered when the mouse leaves the viewport. To render something else, provide a string + * to be used as the text content (e.g. 'no position' or '' for an empty string). Set the placeholder + * to `false` to retain the last position when the mouse leaves the viewport. In a future release, this + * will be the default behavior. + * @property {string} [undefinedHTML=' '] This option is deprecated. Use the `placeholder` option instead. */ /** @@ -101,19 +103,42 @@ class MousePosition extends Control { this.setProjection(options.projection); } + /** + * @type {boolean} + * Change this to `false` when removing the deprecated `undefinedHTML` option. + */ + let renderOnMouseOut = true; + + /** + * @type {string} + */ + let placeholder = ' '; + + if ('undefinedHTML' in options) { + // deprecated behavior + if (options.undefinedHTML !== undefined) { + placeholder = options.undefinedHTML; + } + renderOnMouseOut = !!placeholder; + } else if ('placeholder' in options) { + if (options.placeholder === false) { + renderOnMouseOut = false; + } else { + placeholder = String(options.placeholder); + } + } + /** * @private * @type {string} */ - this.undefinedHTML_ = - options.undefinedHTML !== undefined ? options.undefinedHTML : ' '; + this.placeholder_ = placeholder; /** * @private * @type {boolean} */ - this.renderOnMouseOut_ = - this.undefinedHTML_ === '' || !!this.undefinedHTML_; + this.renderOnMouseOut_ = renderOnMouseOut; /** * @private @@ -204,6 +229,7 @@ class MousePosition extends Control { listen(viewport, EventType.POINTEROUT, this.handleMouseOut, this) ); } + this.updateHTML_(null); } } @@ -234,7 +260,7 @@ class MousePosition extends Control { * @private */ updateHTML_(pixel) { - let html = this.undefinedHTML_; + let html = this.placeholder_; if (pixel && this.mapProjection_) { if (!this.transform_) { const projection = this.getProjection(); diff --git a/test/browser/spec/ol/control/mouseposition.test.js b/test/browser/spec/ol/control/mouseposition.test.js index fa0c2a60c9..2c8bbd1386 100644 --- a/test/browser/spec/ol/control/mouseposition.test.js +++ b/test/browser/spec/ol/control/mouseposition.test.js @@ -61,7 +61,75 @@ describe('ol/control/MousePosition', function () { document.querySelector('div.ol-viewport').dispatchEvent(evt); } - describe('undefinedHTML', function () { + describe('placeholder', function () { + it('renders placeholder when mouse moves out', function () { + const ctrl = new MousePosition({ + placeholder: 'some text', + }); + ctrl.setMap(map); + map.renderSync(); + + const element = document.querySelector( + '.ol-mouse-position', + map.getTarget() + ); + + simulateEvent(EventType.POINTEROUT, width + 1, height + 1); + expect(element.innerHTML).to.be('some text'); + + simulateEvent(EventType.POINTERMOVE, 20, 30); + expect(element.innerHTML).to.be('20,-30'); + + simulateEvent(EventType.POINTEROUT, width + 1, height + 1); + expect(element.innerHTML).to.be('some text'); + }); + + it('renders the last posisition if placeholder is false and mouse moves outside the viewport', function () { + const ctrl = new MousePosition({placeholder: false}); + ctrl.setMap(map); + map.renderSync(); + + const element = document.querySelector( + '.ol-mouse-position', + map.getTarget() + ); + + simulateEvent(EventType.POINTEROUT, width + 1, height + 1); + expect(element.innerHTML).to.be(' '); + + target.dispatchEvent(new PointerEvent('pointermove')); + simulateEvent(EventType.POINTERMOVE, 20, 30); + expect(element.innerHTML).to.be('20,-30'); + + simulateEvent(EventType.POINTEROUT, width + 1, height + 1); + expect(element.innerHTML).to.be('20,-30'); + }); + + it('renders an empty space if placehodler is set to the same and mouse moves outside the viewport', function () { + const ctrl = new MousePosition({ + placeholder: '', + }); + ctrl.setMap(map); + map.renderSync(); + + const element = document.querySelector( + '.ol-mouse-position', + map.getTarget() + ); + + simulateEvent(EventType.POINTEROUT, width + 1, height + 1); + expect(element.innerHTML).to.be(''); + + target.dispatchEvent(new PointerEvent('pointermove')); + simulateEvent(EventType.POINTERMOVE, 20, 30); + expect(element.innerHTML).to.be('20,-30'); + + simulateEvent(EventType.POINTEROUT, width + 1, height + 1); + expect(element.innerHTML).to.be(''); + }); + }); + + describe('undefinedHTML (deprecated)', function () { it('renders undefinedHTML when mouse moves out', function () { const ctrl = new MousePosition({ undefinedHTML: 'some text', @@ -105,30 +173,7 @@ describe('ol/control/MousePosition', function () { expect(element.innerHTML).to.be(' '); }); - it('retains the mouse position when undefinedHTML is false and mouse moves outside the viewport', function () { - const ctrl = new MousePosition({ - undefinedHTML: false, - }); - ctrl.setMap(map); - map.renderSync(); - - const element = document.querySelector( - '.ol-mouse-position', - map.getTarget() - ); - - simulateEvent(EventType.POINTEROUT, width + 1, height + 1); - expect(element.innerHTML).to.be(''); - - target.dispatchEvent(new PointerEvent('pointermove')); - simulateEvent(EventType.POINTERMOVE, 20, 30); - expect(element.innerHTML).to.be('20,-30'); - - simulateEvent(EventType.POINTEROUT, width + 1, height + 1); - expect(element.innerHTML).to.be('20,-30'); - }); - - it('renders an empty string if undefinedHTML is an empty string and mouse moves outside the viewport', function () { + it('retains the mouse position when undefinedHTML is falsey and mouse moves outside the viewport', function () { const ctrl = new MousePosition({ undefinedHTML: '', }); @@ -148,7 +193,7 @@ describe('ol/control/MousePosition', function () { expect(element.innerHTML).to.be('20,-30'); simulateEvent(EventType.POINTEROUT, width + 1, height + 1); - expect(element.innerHTML).to.be(''); + expect(element.innerHTML).to.be('20,-30'); }); }); });