Skip to content

Commit

Permalink
Merge pull request #50 from mo-martinwilson/feature/add-l-tile-layer-wms
Browse files Browse the repository at this point in the history
Feature/add l tile layer wms
  • Loading branch information
andrewgryan authored Oct 30, 2024
2 parents 91822de + 9211860 commit f1ed7ea
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import LMarker from "./l-marker.js";
import LOverlayLayers from "./l-overlay-layers.js";
import LPopup from "./l-popup.js";
import LTileLayer from "./l-tile-layer.js";
import LTileLayerWMS from "./l-tile-layer-wms.js";
import LLatLngBounds from "./l-lat-lng-bounds.js";
import LImageOverlay from "./l-image-overlay.js";
import LVideoOverlay from "./l-video-overlay.js";
Expand All @@ -28,6 +29,7 @@ const init = (() => {
customElements.define("l-overlay-layers", LOverlayLayers);
customElements.define("l-layer-group", LLayerGroup);
customElements.define("l-tile-layer", LTileLayer);
customElements.define("l-tile-layer-wms", LTileLayerWMS);
customElements.define("l-marker-cluster-group", LMarkerClusterGroup);
customElements.define("l-marker", LMarker);
customElements.define("l-popup", LPopup);
Expand Down
60 changes: 60 additions & 0 deletions src/l-tile-layer-wms.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// @ts-check
import { tileLayer } from "leaflet";
import LLayer from "./l-layer.js";
import { layerConnected } from "./events.js";
import { htmlAttribute, optional, parse, partial } from "./parse.js";

class LTileLayerWMS extends LLayer {
constructor() {
super();
this.layer = null;
}

connectedCallback() {
const urlTemplate = parse(htmlAttribute("url-template"), this);

const name = this.getAttribute("name");
const schema = partial({
// Leaflet.tileLayer default options: https://leafletjs.com/reference.html#tilelayer-wms-layers
layers: htmlAttribute("layers"),
styles: optional(htmlAttribute("styles")),
format: optional(htmlAttribute("format")),
transparent: optional(htmlAttribute("transparent")),
version: optional(htmlAttribute("version")),
crs: optional(htmlAttribute("crs")),
uppercase: optional(htmlAttribute("uppercase")),

// Inherited option from Layer: https://leafletjs.com/reference.html#tilelayer-wms-attribution
attribution: optional(htmlAttribute("attribution")),
});

const standardOptions = parse(schema, this);
const nonStandardOptionsElement = this.getAttribute("options");
const nonStandardOptions = () => {
if (nonStandardOptionsElement) {
try {
return JSON.parse(nonStandardOptionsElement);
} catch (e) {
console.error(
"Error whilst parsing JSON for options attribute in l-tile-layer-wms",
e,
);
return {};
}
} else {
return {};
}
};

this.layer = tileLayer.wms(urlTemplate, {
...standardOptions,
...nonStandardOptions(),
});
const event = new CustomEvent(layerConnected, {
detail: { name, layer: this.layer },
bubbles: true,
});
this.dispatchEvent(event);
}
}
export default LTileLayerWMS;
93 changes: 93 additions & 0 deletions src/l-tile-layer-wms.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// @vitest-environment happy-dom
import { tileLayer } from "leaflet";
import { it, expect } from "vitest";
import { layerConnected } from "./events";
import "./index";

it("should create an l-tile-layer-wms with the correct options", async () => {
const urlTemplate = "http://ows.mundialis.de/services/service?";
const el = document.createElement("l-tile-layer-wms");
el.setAttribute("url-template", urlTemplate);
el.setAttribute("layers", "example-wms-layer");

let promise = new Promise((resolve) => {
el.addEventListener(layerConnected, (ev) => {
resolve(ev.detail);
});
});
document.body.appendChild(el);

const actual = await promise;
const expected = {
name: null,
layer: tileLayer.wms(urlTemplate, { layers: "example-wms-layer" }),
};
expect(actual).toEqual(expected);
});

it.each([
["http://example.com/wms", "styles", "default"],
["http://example.com/wms", "format", "image/png"],
["http://example.com/wms", "transparent", "true"],
])("should handle WMS options %s %s", (urlTemplate, key, value) => {
const el = document.createElement("l-tile-layer-wms");
el.setAttribute("url-template", urlTemplate);
el.setAttribute("layers", "example layer ere");
el.setAttribute(key, value);
document.body.appendChild(el);

const actual = el.layer;
const expected = tileLayer.wms(urlTemplate, {
layers: "example layer ere",
[key]: value,
});
expect(actual).toEqual(expected);
});

it("should support attribution", () => {
const urlTemplate = "http://example.com/wms";
const attribution = "© OpenStreetMap contributors";
const layers = "example-wms-layer";
const el = document.createElement("l-tile-layer-wms");
el.setAttribute("url-template", urlTemplate);
el.setAttribute("attribution", attribution);
el.setAttribute("layers", layers);
document.body.appendChild(el);

const actual = el.layer;
const expected = tileLayer.wms(urlTemplate, { attribution, layers });
expect(actual).toEqual(expected);
});

it("should parse valid JSON in the options attribute", () => {
const urlTemplate = "http://example.com/wms";
const options = '{"height": 101, "bbox": "coords ere"}';
const el = document.createElement("l-tile-layer-wms");
el.setAttribute("url-template", urlTemplate);
el.setAttribute("layers", "example layer ere");
el.setAttribute("options", options);
document.body.appendChild(el);

const actual = el.layer;
const expected = tileLayer.wms(urlTemplate, {
layers: "example layer ere",
height: 101,
bbox: "coords ere",
});
expect(actual).toEqual(expected);
});

it("should handle invalid JSON in the options attribute gracefully", () => {
const urlTemplate = "http://example.com/wms";
const invalidJson = '{"height": 10, "bbox": "coords ere"'; // <- missing closing brace
const el = document.createElement("l-tile-layer-wms");
el.setAttribute("url-template", urlTemplate);
el.setAttribute("layers", "example layer ere");
el.setAttribute("options", invalidJson);
document.body.appendChild(el);

// Expect layer creation to succeed but without additional options
const actual = el.layer;
const expected = tileLayer.wms(urlTemplate, { layers: "example layer ere" });
expect(actual).toEqual(expected);
});

0 comments on commit f1ed7ea

Please sign in to comment.