]> git.openstreetmap.org Git - rails.git/blob - app/assets/javascripts/leaflet.layers.js
Merge remote-tracking branch 'upstream/pull/6612'
[rails.git] / app / assets / javascripts / leaflet.layers.js
1 //= require @maptiler/maplibre-gl-omt-language
2 //= require maplibre/map
3 //= require maplibre/i18n
4
5 L.OSM.layers = function (options) {
6   const control = L.OSM.sidebarPane(options, "layers", "javascripts.map.layers.title", "javascripts.map.layers.header");
7
8   control.onAddPane = function (map, button, $ui, toggle) {
9     const layers = options.layers;
10
11     control.onContentLoaded = function () {
12       $ui.find(".base-layers>div").each(initBaseLayer);
13       initOverlays();
14     };
15     control.loadContent();
16
17     function initBaseLayer() {
18       const [container, input, item] = this.children;
19       const layer = layers.find(l => l.options.layerId === container.dataset.layer);
20       input.checked = map.hasLayer(layer);
21
22       map.whenReady(function () {
23         const miniMap = new OSM.MapLibre.Map({
24           container,
25           style: layer.options.style,
26           interactive: false,
27           attributionControl: false,
28           fadeDuration: 0,
29           zoomSnap: layer.options.isVectorStyle ? 0 : 1
30         });
31
32         if (layer.options.layerId === "openmaptiles_osm") {
33           OSM.MapLibre.setOMTMapLanguage(miniMap);
34         }
35
36         $ui
37           .on("show", shown)
38           .on("hide", hide);
39
40         function shown() {
41           miniMap.resize();
42           setView(false);
43           map.on("moveend", moved);
44         }
45
46         function hide() {
47           map.off("moveend", moved);
48         }
49
50         function moved() {
51           setView();
52         }
53
54         function setView(animate = true) {
55           const center = map.getCenter();
56           const zoom = Math.max(Math.floor(map.getZoom() - 3), -1);
57           if (animate) {
58             miniMap.easeTo({ center: [center.lng, center.lat], zoom });
59           } else {
60             miniMap.jumpTo({ center: [center.lng, center.lat], zoom });
61           }
62         }
63       });
64
65       $(input).on("click", function () {
66         for (const other of layers) {
67           if (other !== layer) {
68             map.removeLayer(other);
69           }
70         }
71         map.addLayer(layer);
72       });
73
74       $(item).on("dblclick", toggle);
75
76       map.on("baselayerchange", function () {
77         input.checked = map.hasLayer(layer);
78       });
79     }
80
81     function initOverlays() {
82       $ui.find(".overlay-layers div.form-check").each(function () {
83         const item = this;
84         const layer = map[this.dataset.layerId];
85         const input = this.firstElementChild.firstElementChild;
86         $(item).tooltip("disable");
87
88         let checked = map.hasLayer(layer);
89
90         input.checked = checked;
91
92         $(input).on("change", function () {
93           checked = input.checked;
94           layer.cancelLoading?.();
95
96           if (checked) {
97             map.addLayer(layer);
98           } else {
99             map.removeLayer(layer);
100             $(`#layers-${name}-loading`).remove();
101           }
102         });
103
104         map.on("overlayadd overlayremove", function () {
105           input.checked = map.hasLayer(layer);
106         });
107
108         map.on("zoomend", function () {
109           const disabled = map.getBounds().getSize() >= item.dataset.maxArea;
110           input.disabled = disabled;
111
112           if (disabled && input.checked) {
113             input.click();
114             checked = true;
115           } else if (!disabled && !input.checked && checked) {
116             input.click();
117           }
118
119           item.classList.toggle("disabled", disabled);
120           $(item).tooltip(disabled ? "enable" : "disable");
121         });
122       });
123     }
124   };
125
126   return control;
127 };