]> git.openstreetmap.org Git - rails.git/blob - app/assets/javascripts/leaflet.layers.js
Merge remote-tracking branch 'upstream/pull/5563'
[rails.git] / app / assets / javascripts / leaflet.layers.js
1 L.OSM.layers = function (options) {
2   var control = L.OSM.sidebarPane(options, "layers", "javascripts.map.layers.title", "javascripts.map.layers.header");
3
4   control.onAddPane = function (map, button, $ui, toggle) {
5     var layers = options.layers;
6
7     var baseSection = $("<div>")
8       .attr("class", "base-layers d-grid gap-3 p-3 border-bottom border-secondary-subtle")
9       .appendTo($ui);
10
11     layers.forEach(function (layer, i) {
12       var id = "map-ui-layer-" + i;
13
14       var buttonContainer = $("<div class='position-relative'>")
15         .appendTo(baseSection);
16
17       var mapContainer = $("<div class='position-absolute top-0 start-0 bottom-0 end-0 z-0 bg-body-secondary'>")
18         .appendTo(buttonContainer);
19
20       var input = $("<input type='radio' class='btn-check' name='layer'>")
21         .prop("id", id)
22         .prop("checked", map.hasLayer(layer))
23         .appendTo(buttonContainer);
24
25       var item = $("<label class='btn btn-outline-primary border-4 rounded-3 bg-transparent position-absolute p-0 h-100 w-100 overflow-hidden'>")
26         .prop("for", id)
27         .append($("<span class='badge position-absolute top-0 start-0 rounded-top-0 rounded-start-0 py-1 px-2 bg-body bg-opacity-75 text-body text-wrap text-start fs-6 lh-base'>").append(layer.options.name))
28         .appendTo(buttonContainer);
29
30       map.whenReady(function () {
31         var miniMap = L.map(mapContainer[0], { attributionControl: false, zoomControl: false, keyboard: false })
32           .addLayer(new layer.constructor(layer.options));
33
34         miniMap.dragging.disable();
35         miniMap.touchZoom.disable();
36         miniMap.doubleClickZoom.disable();
37         miniMap.scrollWheelZoom.disable();
38
39         $ui
40           .on("show", shown)
41           .on("hide", hide);
42
43         function shown() {
44           miniMap.invalidateSize();
45           setView({ animate: false });
46           map.on("moveend", moved);
47         }
48
49         function hide() {
50           map.off("moveend", moved);
51         }
52
53         function moved() {
54           setView();
55         }
56
57         function setView(options) {
58           miniMap.setView(map.getCenter(), Math.max(map.getZoom() - 2, 0), options);
59         }
60       });
61
62       input.on("click", function () {
63         layers.forEach(function (other) {
64           if (other !== layer) {
65             map.removeLayer(other);
66           }
67         });
68         map.addLayer(layer);
69       });
70
71       item.on("dblclick", toggle);
72
73       map.on("baselayerchange", function () {
74         input.prop("checked", map.hasLayer(layer));
75       });
76     });
77
78     if (OSM.STATUS !== "api_offline" && OSM.STATUS !== "database_offline") {
79       var overlaySection = $("<div>")
80         .attr("class", "overlay-layers p-3")
81         .appendTo($ui);
82
83       $("<p>")
84         .text(I18n.t("javascripts.map.layers.overlays"))
85         .attr("class", "text-body-secondary small mb-2")
86         .appendTo(overlaySection);
87
88       var overlays = $("<ul class='list-unstyled form-check'>")
89         .appendTo(overlaySection);
90
91       var addOverlay = function (layer, name, maxArea) {
92         var item = $("<li>")
93           .appendTo(overlays);
94
95         if (name === "notes" || name === "data") {
96           item
97             .attr("title", I18n.t("javascripts.site.map_" + name + "_zoom_in_tooltip"))
98             .tooltip("disable");
99         }
100
101         var label = $("<label>")
102           .attr("class", "form-check-label")
103           .appendTo(item);
104
105         var checked = map.hasLayer(layer);
106
107         var input = $("<input>")
108           .attr("type", "checkbox")
109           .attr("class", "form-check-input")
110           .prop("checked", checked)
111           .appendTo(label);
112
113         label.append(I18n.t("javascripts.map.layers." + name));
114
115         input.on("change", function () {
116           checked = input.is(":checked");
117           if (checked) {
118             map.addLayer(layer);
119           } else {
120             map.removeLayer(layer);
121           }
122         });
123
124         map.on("overlayadd overlayremove", function () {
125           input.prop("checked", map.hasLayer(layer));
126         });
127
128         map.on("zoomend", function () {
129           var disabled = map.getBounds().getSize() >= maxArea;
130           $(input).prop("disabled", disabled);
131
132           if (disabled && $(input).is(":checked")) {
133             $(input).prop("checked", false)
134               .trigger("change");
135             checked = true;
136           } else if (!disabled && !$(input).is(":checked") && checked) {
137             $(input).prop("checked", true)
138               .trigger("change");
139           }
140
141           $(item)
142             .attr("class", disabled ? "disabled" : "")
143             .tooltip(disabled ? "enable" : "disable");
144         });
145       };
146
147       addOverlay(map.noteLayer, "notes", OSM.MAX_NOTE_REQUEST_AREA);
148       addOverlay(map.dataLayer, "data", OSM.MAX_REQUEST_AREA);
149       addOverlay(map.gpsLayer, "gps", Number.POSITIVE_INFINITY);
150     }
151   };
152
153   return control;
154 };