leaflet-html 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,56 @@
1
+ # Leaflet HTML
2
+
3
+ Leaflet expressed in HTML to add maps to Hypermedia Driven Applications (HDA).
4
+
5
+ ## Example
6
+
7
+ The HTML in `example/index.html` is a simple demonstration of the API.
8
+
9
+ ![image](https://github.com/andrewgryan/leaflet-html/assets/22789046/0186bce2-ddcc-443a-b7a2-ccd86dcffcfc)
10
+
11
+ ```html
12
+ <!-- Note: Leaflet JS/CSS must be included in <head> and [data-leaflet-html] styled to an appropriate size. -->
13
+ <div data-leaflet-html data-center="[39.61, -105.02]" data-zoom="10">
14
+ <div data-control-layers>
15
+ <div data-base-maps>
16
+ <div data-tile-layer
17
+ data-name="OpenStreetMap"
18
+ data-url-template="https://tile.openstreetmap.org/{z}/{x}/{y}.png"
19
+ data-attribution='&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
20
+ data-max-zoom="12"
21
+ ></div>
22
+ <div data-tile-layer
23
+ data-name="Toner"
24
+ data-url-template="https://tiles.stadiamaps.com/tiles/stamen_toner/{z}/{x}/{y}{r}.png"
25
+ data-attribution=''
26
+ data-max-zoom="12"
27
+ data-show
28
+ ></div>
29
+ </div>
30
+ <div data-overlay-maps>
31
+ <div data-layer-group data-name="Cities">
32
+ <div data-marker data-lat-lng="[39.61, -105.02]">
33
+ <div data-popup data-content="This is Littleton, CO."></div>
34
+ </div>
35
+ <div data-marker data-lat-lng="[39.74, -104.99]">
36
+ <div data-popup data-content="This is Denver, CO."></div>
37
+ </div>
38
+ <div data-marker data-lat-lng="[39.73, -104.8]">
39
+ <div data-popup data-content="This is Aurora, CO."></div>
40
+ </div>
41
+ <div data-marker data-lat-lng="[39.77, -105.23]">
42
+ <div data-popup data-content="This is Golden, CO."></div>
43
+ </div>
44
+ </div>
45
+ </div>
46
+ </div>
47
+ </div>
48
+ ```
49
+
50
+ ## Build
51
+
52
+ To build the source code run.
53
+
54
+ ```sh
55
+ yarn build
56
+ ```
@@ -0,0 +1,96 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <title>Leaflet HTML</title>
5
+ <meta charset="utf-8" />
6
+ <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
7
+ integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
8
+ crossorigin=""/>
9
+ <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
10
+ integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
11
+ crossorigin=""></script>
12
+ <style>
13
+ * {
14
+ margin: 0;
15
+ }
16
+
17
+ [data-leaflet-html] {
18
+ block-size: 100vh;
19
+ isolation: isolate;
20
+ z-index: 1;
21
+ }
22
+
23
+ #btn {
24
+ z-index: 2;
25
+ position: absolute;
26
+ bottom: 0;
27
+ left: 0;
28
+ margin: 1rem;
29
+ padding: 1rem;
30
+ background-color: #337;
31
+ color: white;
32
+ border-radius: 0.25rem;
33
+ cursor: pointer;
34
+ font-size: 1.2rem;
35
+ }
36
+ </style>
37
+ </head>
38
+ <body>
39
+ <div data-leaflet-html data-center="[39.61, -105.02]" data-zoom="10">
40
+ <div data-control-layers>
41
+ <div data-base-maps>
42
+ <div data-tile-layer
43
+ data-name="OpenStreetMap"
44
+ data-url-template="https://tile.openstreetmap.org/{z}/{x}/{y}.png"
45
+ data-attribution='&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
46
+ data-max-zoom="12"
47
+ ></div>
48
+ <div data-tile-layer
49
+ data-name="Toner"
50
+ data-url-template="https://tiles.stadiamaps.com/tiles/stamen_toner/{z}/{x}/{y}{r}.png"
51
+ data-attribution=''
52
+ data-max-zoom="12"
53
+ data-show
54
+ ></div>
55
+ </div>
56
+ <div data-overlay-maps>
57
+ <div data-layer-group data-name="Cities">
58
+ <div data-marker data-lat-lng="[39.61, -105.02]">
59
+ <div data-popup data-content="This is Littleton, CO."></div>
60
+ </div>
61
+ <div data-marker data-lat-lng="[39.74, -104.99]">
62
+ <div data-popup data-content="This is Denver, CO."></div>
63
+ </div>
64
+ <div data-marker data-lat-lng="[39.73, -104.8]" data-opacity="0.7">
65
+ <div data-popup data-content="This is Aurora, CO."></div>
66
+ </div>
67
+ <div data-marker data-lat-lng="[39.77, -105.23]">
68
+ <div data-popup data-content="This is Golden, CO."></div>
69
+ </div>
70
+ </div>
71
+ </div>
72
+ </div>
73
+
74
+ </div>
75
+ <button id="btn">Add a city</button>
76
+ <script type="module">
77
+ import leafletHTML from "/dist/leaflet-html.esm.js"
78
+
79
+ leafletHTML()
80
+
81
+ // Manual tests
82
+ document.getElementById("btn").addEventListener("click", () => {
83
+ // New city
84
+ let el = document.querySelector('[data-name="Cities"]')
85
+ const city = document.createElement("div")
86
+ city.dataset.marker = ''
87
+ city.dataset.latLng = "[39.60, -105.02]"
88
+ el.appendChild(city)
89
+
90
+ // Remove Denver
91
+ el = document.querySelector('[data-lat-lng="[39.74, -104.99]"]')
92
+ el.remove()
93
+ })
94
+ </script>
95
+ </body>
96
+ </html>
package/package.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "leaflet-html",
3
+ "type": "module",
4
+ "version": "0.1.0",
5
+ "description": "Leaflet expressed in HTML",
6
+ "source": "src/index.js",
7
+ "main": "./dist/leaflet-html.js",
8
+ "module": "./dist/leaflet-html.esm.js",
9
+ "author": "andrewgryan",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/andrewgryan/leaflet-html.git"
13
+ },
14
+ "license": "MIT",
15
+ "scripts": {
16
+ "build": "microbundle",
17
+ "watch": "microbundle watch"
18
+ },
19
+ "devDependencies": {
20
+ "microbundle": "^0.15.1"
21
+ }
22
+ }
package/src/index.js ADDED
@@ -0,0 +1,86 @@
1
+ const init = () => {
2
+ // Render Leaflet API calls
3
+ document.querySelectorAll("[data-leaflet-html]").forEach((el) => {
4
+ const { center, zoom } = el.dataset
5
+ const map = L.map(el).setView(JSON.parse(center), parseInt(zoom))
6
+
7
+ // L.control.layers
8
+ el.querySelectorAll("[data-control-layers]").forEach((el) => {
9
+ const baseMaps = {}
10
+
11
+ // L.tileLayers
12
+ el.querySelectorAll("[data-tile-layer]").forEach((tileEl) => {
13
+ const { show, urlTemplate, attribution, maxZoom, name } = tileEl.dataset
14
+ baseMaps[name] = L.tileLayer(urlTemplate, { maxZoom, attribution });
15
+ if (show != null) {
16
+ baseMaps[name].addTo(map)
17
+ }
18
+ })
19
+
20
+ const overlayMaps = {}
21
+ // L.layerGroup
22
+ el.querySelectorAll("[data-layer-group]").forEach((el) => {
23
+ const { name } = el.dataset
24
+ const layers = []
25
+
26
+ const observer = new MutationObserver(function(mutations) {
27
+ const group = overlayMaps[name]
28
+
29
+ mutations.forEach(mutation => {
30
+ mutation.addedNodes.forEach(node => {
31
+ const { latLng } = node.dataset // MutationObserver needed
32
+ const layer = L.marker(JSON.parse(latLng))
33
+ group.addLayer(layer)
34
+ map.addLayer(layer)
35
+ })
36
+
37
+ mutation.removedNodes.forEach(node => {
38
+ const { _leafletId } = node.dataset
39
+ const layer = group.getLayer(_leafletId)
40
+ group.removeLayer(layer)
41
+
42
+ map.removeLayer(layer)
43
+ })
44
+ })
45
+ })
46
+ observer.observe(el, { childList: true })
47
+
48
+ // L.marker
49
+ el.querySelectorAll("[data-marker]").forEach((el) => {
50
+ const { latLng } = el.dataset
51
+ const { opacity = "1.0" } = el.dataset
52
+ const options = { opacity: parseFloat(opacity) }
53
+ console.log(options)
54
+ const marker = L.marker(JSON.parse(latLng), options).addTo(map)
55
+ el.dataset._leafletId = L.stamp(marker) // Save ID for later
56
+
57
+ const observer = new MutationObserver(function(mutations) {
58
+ mutations.forEach((mutation) => {
59
+ const { latLng } = mutation.target.dataset
60
+ marker.setLatLng(JSON.parse(latLng))
61
+ })
62
+ })
63
+ observer.observe(el, { attributes: true, attributeFilter: ["data-lat-lng"] })
64
+
65
+ // marker.bindPopup
66
+ el.querySelectorAll("[data-popup]").forEach((el) => {
67
+ const { content } = el.dataset
68
+ marker.bindPopup(content)
69
+ const observer = new MutationObserver(function() {
70
+ marker.getPopup().setContent(el.dataset.content)
71
+ })
72
+ observer.observe(el, { attributes: true, attributeFilter: ["data-content"] })
73
+ })
74
+
75
+ layers.push(marker)
76
+ })
77
+
78
+ overlayMaps[name] = L.layerGroup(layers)
79
+ })
80
+
81
+ L.control.layers(baseMaps, overlayMaps).addTo(map)
82
+ })
83
+ })
84
+ }
85
+
86
+ export default init