leaflet-html 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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