diff --git a/elements/layercontrol/package.json b/elements/layercontrol/package.json
index ffe82a127..f58ebec62 100644
--- a/elements/layercontrol/package.json
+++ b/elements/layercontrol/package.json
@@ -32,6 +32,7 @@
},
"dependencies": {
"dayjs": "^1.11.8",
- "lit": "^3.0.2"
+ "lit": "^3.0.2",
+ "lodash.debounce": "^4.0.8"
}
}
diff --git a/elements/layercontrol/src/components/layerList.js b/elements/layercontrol/src/components/layerList.js
index 80cd4159a..01d2b1342 100644
--- a/elements/layercontrol/src/components/layerList.js
+++ b/elements/layercontrol/src/components/layerList.js
@@ -1,10 +1,10 @@
import { LitElement, html } from "lit";
import { when } from "lit/directives/when.js";
-import { keyed } from "lit/directives/keyed.js";
+import { repeat } from "lit/directives/repeat.js";
import { createSortable, getLayerType } from "../helpers";
import "./layer";
import "./layerGroup";
-
+import _debounce from "lodash.debounce";
/**
* Display of a list of layers
*
@@ -70,15 +70,28 @@ export class EOxLayerControlLayerList extends LitElement {
this.noShadow = true;
}
+ #handleLayersChangeLength = () => {
+ this.#debHandleLayersChangeLength();
+ };
+ #debHandleLayersChangeLength = _debounce(() => {
+ this.requestUpdate();
+ this.dispatchEvent(new CustomEvent("changed", { bubbles: true }));
+ }, 50);
+
+ firstUpdated() {
+ if (this.layers) {
+ createSortable(this.renderRoot.querySelector("ul"), this.layers, this);
+ }
+ }
+
updated() {
if (!this.layers) {
return;
}
- this.layers.on("change:length", () => {
- this.requestUpdate();
- this.dispatchEvent(new CustomEvent("changed", { bubbles: true }));
- });
- createSortable(this.renderRoot.querySelector("ul"), this.layers, this);
+ if (this.layers.hasListener("change:length")) {
+ this.layers?.un("change:length", this.#handleLayersChangeLength);
+ }
+ this.layers.on("change:length", this.#handleLayersChangeLength);
}
createRenderRoot() {
@@ -95,57 +108,52 @@ export class EOxLayerControlLayerList extends LitElement {
${when(
this.layers,
() => html`
- ${this.layers
- .getArray()
- .filter(
- (l) =>
- !l.get("layerControlHide") && !l.get("layerControlOptional")
- )
- .reverse()
- .map((layer) =>
- keyed(
- layer.get(this.idProperty),
- html`
-
- ${
- /** @type {import("ol/layer").Group} */ (layer)
- .getLayers
- ? html`
- this.requestUpdate()}
- >
-
- `
- : html`
- {
- this.requestUpdate();
- }}
- >
- `
- }
-
- `
+ ${repeat(
+ this.layers
+ .getArray()
+ .filter(
+ (l) =>
+ !l.get("layerControlHide") && !l.get("layerControlOptional")
)
- )}
+ .reverse(),
+ (layer) => layer,
+ (layer) => html`
+
+ ${
+ /** @type {import("ol/layer").Group} */ (layer).getLayers
+ ? html`
+ this.requestUpdate()}
+ >
+
+ `
+ : html`
+ this.requestUpdate()}
+ >
+ `
+ }
+
+ `
+ )}
`
)}
diff --git a/elements/layercontrol/src/helpers.js b/elements/layercontrol/src/helpers.js
index bfad39eaf..7707fdc98 100644
--- a/elements/layercontrol/src/helpers.js
+++ b/elements/layercontrol/src/helpers.js
@@ -3,10 +3,10 @@ import Sortable from "sortablejs";
/**
*
* @param {HTMLElement} element
- * @param {import("ol").Collection} layers
+ * @param {import("ol").Collection} collection
* @param {import("lit").LitElement} that
*/
-export const createSortable = (element, layers, that) => {
+export const createSortable = (element, collection, that) => {
/**
* @type {any[]}
*/
@@ -41,7 +41,8 @@ export const createSortable = (element, layers, that) => {
if (e.oldIndex == e.newIndex) return;
// Then move the element using your own logic.
// automatically dispatches "sort" event
- const layer = layers.getArray().find(
+ const layers = collection.getArray();
+ const layer = layers.find(
(l) =>
// @ts-ignore
l.ol_uid ===
@@ -50,8 +51,32 @@ export const createSortable = (element, layers, that) => {
// @ts-ignore
).layer.ol_uid
);
- layers.remove(layer);
- layers.insertAt(layers.getLength() - e.newIndex, layer);
+ const numberOfHiddenLayers = layers.filter(
+ (l) => l.get("layerControlHide") || l.get("layerControlOptional")
+ ).length;
+ const target =
+ layers[layers.length - 1 - e.newIndex - numberOfHiddenLayers];
+ let draggedIndex;
+ let dropIndex;
+ // remove dragged layer from collection
+ for (
+ draggedIndex = layers.length - 1;
+ draggedIndex > -1;
+ draggedIndex--
+ ) {
+ if (layers[draggedIndex] == layer) {
+ collection.removeAt(draggedIndex);
+ break;
+ }
+ }
+ // re-add dragged layer at position of layer that has beend dropped on
+ for (dropIndex = layers.length - 1; dropIndex > -1; dropIndex--) {
+ if (layers[dropIndex] === target) {
+ if (draggedIndex > dropIndex) collection.insertAt(dropIndex, layer);
+ else collection.insertAt(dropIndex + 1, layer);
+ break;
+ }
+ }
that.requestUpdate();
},
});
diff --git a/elements/layercontrol/src/main.js b/elements/layercontrol/src/main.js
index 5ed059245..7486f801f 100644
--- a/elements/layercontrol/src/main.js
+++ b/elements/layercontrol/src/main.js
@@ -99,7 +99,7 @@ export class EOxLayerControl extends LitElement {
* @type Element & { map: import("ol").Map }
*/
const foundElement = document.querySelector(this.for);
- if (foundElement) {
+ if (foundElement && foundElement?.map !== this.map) {
this.map = foundElement.map;
}
}
diff --git a/elements/layercontrol/test/_mockMap.js b/elements/layercontrol/test/_mockMap.js
index 49c348f3d..c19964ff9 100644
--- a/elements/layercontrol/test/_mockMap.js
+++ b/elements/layercontrol/test/_mockMap.js
@@ -41,6 +41,15 @@ class MockLayer {
this.visible = visible;
}
visible = true;
+ events = {
+ ["change"]: () => undefined,
+ };
+ on = (event, fun) => (this.events = { [event]: fun });
+ un = (event, fun) => {
+ if (this.events[event] == fun) {
+ delete this.events[event];
+ }
+ };
}
class MockCollection {
@@ -58,6 +67,12 @@ class MockCollection {
};
layers = [];
on = (event, fun) => (this.events = { [event]: fun });
+ un = (event, fun) => {
+ if (this.events[event] == fun) {
+ delete this.events[event];
+ }
+ };
+ hasListener = (event) => event in this.events;
pop() {
this.layers.pop();
this.events["change:length"]();
@@ -66,6 +81,33 @@ class MockCollection {
this.layers.push(new MockLayer(newLayer));
this.events["change:length"]();
}
+ remove(layer) {
+ layer = new MockLayer(layer);
+ const i = this.layers.indexOf(layer);
+ if (i) {
+ this.layers.splice(i, 1);
+ return layer;
+ } else {
+ return undefined;
+ }
+ }
+ removeAt(index) {
+ this.layers = [...this.layers.slice(index)];
+ }
+ insertAt(index, layer) {
+ layer = new MockLayer(layer);
+ this.layers = [
+ ...this.layers.slice(0, index),
+ layer,
+ ...this.layers.slice(index),
+ ];
+ }
+ getLength() {
+ return this.layers.length;
+ }
+ forEach(func) {
+ this.layers.forEach(func);
+ }
}
export class MockMap extends HTMLElement {
diff --git a/package-lock.json b/package-lock.json
index fd17c386c..3f8967060 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -128,7 +128,8 @@
"version": "0.11.1",
"dependencies": {
"dayjs": "^1.11.8",
- "lit": "^3.0.2"
+ "lit": "^3.0.2",
+ "lodash.debounce": "^4.0.8"
},
"devDependencies": {
"@eox/eslint-config": "^1.0.0",