diff --git a/src/mapml-viewer.js b/src/mapml-viewer.js index 9dbbe41d3..d2f98f3b0 100644 --- a/src/mapml-viewer.js +++ b/src/mapml-viewer.js @@ -201,6 +201,7 @@ export class MapViewer extends HTMLElement { if (this.controls) { this._layerControl = M.mapMlLayerControl(null,{"collapsed": true, mapEl: this}).addTo(this._map); this._zoomControl = L.control.zoom().addTo(this._map); + this._reloadButton = M.reloadButton().addTo(this._map); if (!this.controlslist.toLowerCase().includes("nofullscreen")) { this._fullScreenControl = L.control.fullscreen().addTo(this._map); } @@ -399,6 +400,7 @@ export class MapViewer extends HTMLElement { if (this._map) { if (controls && !this._layerControl) { this._zoomControl = L.control.zoom().addTo(this._map); + this._reloadButton = M.reloadButton().addTo(this._map); this._layerControl = M.mapMlLayerControl(null,{"collapsed": true, mapEl: this}).addTo(this._map); if (!this.controlslist.toLowerCase().includes("nofullscreen")) { this._fullScreenControl = L.control.fullscreen().addTo(this._map); @@ -413,12 +415,14 @@ export class MapViewer extends HTMLElement { } else if (this._layerControl) { this._map.removeControl(this._layerControl); this._map.removeControl(this._zoomControl); + this._map.removeControl(this._reloadButton); if (this._fullScreenControl) { this._map.removeControl(this._fullScreenControl); delete this._fullScreenControl; } delete this._layerControl; delete this._zoomControl; + delete this._reloadButton; } } } diff --git a/src/mapml/control/ReloadButton.js b/src/mapml/control/ReloadButton.js new file mode 100644 index 000000000..a5364ce9d --- /dev/null +++ b/src/mapml/control/ReloadButton.js @@ -0,0 +1,63 @@ +export var ReloadButton = L.Control.extend({ + options: { + position: 'topleft', + }, + + onAdd: function (map) { + let container = L.DomUtil.create("div", "mapml-reload-button leaflet-bar"); + + let link = L.DomUtil.create("a", "mapml-reload-button", container); + link.innerHTML = "↺"; + link.href = "#"; + link.title = "Reload"; + link.setAttribute('role', 'button'); + link.setAttribute('aria-label', "Reload"); + + L.DomEvent.disableClickPropagation(link); + L.DomEvent.on(link, 'click', L.DomEvent.stop); + L.DomEvent.on(link, 'click', this._goReload, this); + + this._reloadButton = link; + + this._updateDisabled(); + map.on('moveend', this._updateDisabled, this); + + return container; + }, + + onRemove: function (map) { + map.off('moveend', this._updateDisabled, this); + }, + + disable: function () { + this._disabled = true; + this._updateDisabled(); + return this; + }, + + enable: function () { + this._disabled = false; + this._updateDisabled(); + return this; + }, + + _goReload: function (e) { + if (!this._disabled && this._map.options.mapEl._history.length > 1) { + this._map.options.mapEl.reload(); + } + }, + + _updateDisabled: function () { + setTimeout(() => { + L.DomUtil.removeClass(this._reloadButton, "leaflet-disabled"); + + if (this._disabled || this._map.options.mapEl._history.length <= 1) { + L.DomUtil.addClass(this._reloadButton, "leaflet-disabled"); + } + }, 0); + } +}); + +export var reloadButton = function (options) { + return new ReloadButton(options); +}; \ No newline at end of file diff --git a/src/mapml/index.js b/src/mapml/index.js index 147f4e140..68c7d2ffb 100644 --- a/src/mapml/index.js +++ b/src/mapml/index.js @@ -51,7 +51,7 @@ import { DebugOverlay, debugOverlay} from './layers/DebugLayer'; import { QueryHandler } from './handlers/QueryHandler'; import { ContextMenu } from './handlers/ContextMenu'; import { Util } from './utils/Util'; - +import { ReloadButton, reloadButton } from './control/ReloadButton'; /* global L, Node */ (function (window, document, undefined) { @@ -616,6 +616,9 @@ M.mapMlFeatures = mapMlFeatures; M.MapMLLayerControl = MapMLLayerControl; M.mapMlLayerControl = mapMlLayerControl; +M.ReloadButton = ReloadButton; +M.reloadButton = reloadButton; + M.MapMLStaticTileLayer = MapMLStaticTileLayer; M.mapMLStaticTileLayer = mapMLStaticTileLayer; diff --git a/src/web-map.js b/src/web-map.js index fcc935a2c..9409b5e46 100644 --- a/src/web-map.js +++ b/src/web-map.js @@ -216,6 +216,7 @@ export class WebMap extends HTMLMapElement { if (this.controls) { this._layerControl = M.mapMlLayerControl(null,{"collapsed": true, mapEl: this}).addTo(this._map); this._zoomControl = L.control.zoom().addTo(this._map); + this._reloadButton = M.reloadButton().addTo(this._map); if (!this.controlslist.toLowerCase().includes("nofullscreen")) { this._fullScreenControl = L.control.fullscreen().addTo(this._map); } @@ -436,6 +437,7 @@ export class WebMap extends HTMLMapElement { if (this._map) { if (controls && !this._layerControl) { this._zoomControl = L.control.zoom().addTo(this._map); + this._reloadButton = M.reloadButton().addTo(this._map); this._layerControl = M.mapMlLayerControl(null,{"collapsed": true, mapEl: this}).addTo(this._map); if (!this.controlslist.toLowerCase().includes("nofullscreen")) { this._fullScreenControl = L.control.fullscreen().addTo(this._map); @@ -450,12 +452,14 @@ export class WebMap extends HTMLMapElement { } else if (this._layerControl) { this._map.removeControl(this._layerControl); this._map.removeControl(this._zoomControl); + this._map.removeControl(this._reloadButton); if (this._fullScreenControl) { this._map.removeControl(this._fullScreenControl); delete this._fullScreenControl; } delete this._layerControl; delete this._zoomControl; + delete this._reloadButton; } } } diff --git a/test/e2e/core/mapContextMenu.test.js b/test/e2e/core/mapContextMenu.test.js index d79c2bfe8..fb8827f3a 100644 --- a/test/e2e/core/mapContextMenu.test.js +++ b/test/e2e/core/mapContextMenu.test.js @@ -160,7 +160,7 @@ jest.setTimeout(50000); (controls) => controls.childElementCount ); - expect(controlsOn).toEqual(2); + expect(controlsOn).toEqual(3); expect(controlsOff).toEqual(0); }); @@ -179,7 +179,7 @@ jest.setTimeout(50000); ); expect(controlsOn).toEqual(0); - expect(controlsOff).toEqual(2); + expect(controlsOff).toEqual(3); }); test("[" + browserType + "]" + " Context menu, toggle controls after changing opacity", async () => { @@ -214,7 +214,7 @@ jest.setTimeout(50000); }); test("[" + browserType + "]" + " Submenu, copy all coordinate systems using tab + enter to access", async () => { - await page.click("div > div.leaflet-control-container > div.leaflet-top.leaflet-left"); + await page.click("body > map"); await page.keyboard.press("Shift+F10"); for (let i = 0; i < 4; i++) @@ -229,11 +229,11 @@ jest.setTimeout(50000); "body > textarea", (text) => text.value ); - let expected = "z:0\n"; - expected += "tile: i:150, j:162\n"; - expected += "tilematrix: column:3.585937500000002, row:3.6317349137931063\n"; + let expected = "z:1\n"; + expected += "tile: i:30, j:50\n"; + expected += "tilematrix: column:6.1171875000000036, row:6.195312500000004\n"; expected += "map: i:250, j:300\n"; - expected += "tcrs: x:918.0000000000006, y:929.7241379310352\n"; + expected += "tcrs: x:1566.000000000001, y:1586.0000000000011\n"; expected += "pcrs: easting:562957.9375158995, northing:3641449.4962322935\n"; expected += "gcrs: lon :-62.72946572940102, lat:80.88192121974802"; diff --git a/test/e2e/core/mapElement.test.js b/test/e2e/core/mapElement.test.js index 8333ce4da..8a1b6f572 100644 --- a/test/e2e/core/mapElement.test.js +++ b/test/e2e/core/mapElement.test.js @@ -68,6 +68,27 @@ jest.setTimeout(50000); expect(extent.topLeft.tilematrix[0]).toEqual(expectedFirstTileMatrix[1]); expect(extent.topLeft.tcrs[0]).toEqual(expectedFirstTCRS[1]); }); + + test("[" + browserType + "]" + " Reload button takes you back to initial state", async () => { + await page.click("div > div.leaflet-control-container > div.leaflet-top.leaflet-left > div.mapml-reload-button.leaflet-bar.leaflet-control > a"); + const extent = await page.$eval( + "body > map", + (map) => map.extent + ); + + const history = await page.$eval( + "body > map", + (map) => map._history + ); + + expect(history.length).toEqual(1); + expect(extent.projection).toEqual("CBMTILE"); + expect(extent.zoom).toEqual({ minZoom: 0, maxZoom: 25 }); + expect(extent.topLeft.pcrs).toEqual(expectedPCRS[0]); + expect(extent.topLeft.gcrs).toEqual(expectedGCRS[0]); + expect(extent.topLeft.tilematrix[0]).toEqual(expectedFirstTileMatrix[0]); + expect(extent.topLeft.tcrs[0]).toEqual(expectedFirstTCRS[0]); + }); } ); } diff --git a/test/e2e/mapml-viewer/viewerContextMenu.test.js b/test/e2e/mapml-viewer/viewerContextMenu.test.js index b65ce1cc0..f037ebd3d 100644 --- a/test/e2e/mapml-viewer/viewerContextMenu.test.js +++ b/test/e2e/mapml-viewer/viewerContextMenu.test.js @@ -160,7 +160,7 @@ jest.setTimeout(50000); (controls) => controls.childElementCount ); - expect(controlsOn).toEqual(2); + expect(controlsOn).toEqual(3); expect(controlsOff).toEqual(0); }); @@ -179,7 +179,7 @@ jest.setTimeout(50000); ); expect(controlsOn).toEqual(0); - expect(controlsOff).toEqual(2); + expect(controlsOff).toEqual(3); }); test("[" + browserType + "]" + " Context menu, toggle controls after changing opacity", async () => {