]> git.openstreetmap.org Git - rails.git/blob - app/assets/javascripts/leaflet.layers.js
Create Leaflet sidebar pane control with header writer fn
[rails.git] / app / assets / javascripts / leaflet.layers.js
1 L.OSM.layers = function (options) {
2   var control = L.OSM.sidebarPane(options);
3
4   control.onAdd = function (map) {
5     var layers = options.layers;
6
7     var $container = $("<div>")
8       .attr("class", "control-layers");
9
10     var button = $("<a>")
11       .attr("class", "control-button")
12       .attr("href", "#")
13       .attr("title", I18n.t("javascripts.map.layers.title"))
14       .html("<span class=\"icon layers\"></span>")
15       .on("click", toggle)
16       .appendTo($container);
17
18     var $ui = this.makeUI("layers-ui", "javascripts.map.layers.header", toggle);
19
20     var baseSection = $("<div>")
21       .attr("class", "section base-layers")
22       .appendTo($ui);
23
24     var baseLayers = $("<ul class='list-unstyled'>")
25       .appendTo(baseSection);
26
27     layers.forEach(function (layer) {
28       var item = $("<li>")
29         .appendTo(baseLayers);
30
31       if (map.hasLayer(layer)) {
32         item.addClass("active");
33       }
34
35       var div = $("<div>")
36         .appendTo(item);
37
38       map.whenReady(function () {
39         var miniMap = L.map(div[0], { attributionControl: false, zoomControl: false, keyboard: false })
40           .addLayer(new layer.constructor({ apikey: layer.options.apikey }));
41
42         miniMap.dragging.disable();
43         miniMap.touchZoom.disable();
44         miniMap.doubleClickZoom.disable();
45         miniMap.scrollWheelZoom.disable();
46
47         $ui
48           .on("show", shown)
49           .on("hide", hide);
50
51         function shown() {
52           miniMap.invalidateSize();
53           setView({ animate: false });
54           map.on("moveend", moved);
55         }
56
57         function hide() {
58           map.off("moveend", moved);
59         }
60
61         function moved() {
62           setView();
63         }
64
65         function setView(options) {
66           miniMap.setView(map.getCenter(), Math.max(map.getZoom() - 2, 0), options);
67         }
68       });
69
70       var label = $("<label>")
71         .appendTo(item);
72
73       var input = $("<input>")
74         .attr("type", "radio")
75         .prop("checked", map.hasLayer(layer))
76         .appendTo(label);
77
78       label.append(layer.options.name);
79
80       item.on("click", function () {
81         layers.forEach(function (other) {
82           if (other === layer) {
83             map.addLayer(other);
84           } else {
85             map.removeLayer(other);
86           }
87         });
88         map.fire("baselayerchange", { layer: layer });
89       });
90
91       item.on("dblclick", toggle);
92
93       map.on("layeradd layerremove", function () {
94         item.toggleClass("active", map.hasLayer(layer));
95         input.prop("checked", map.hasLayer(layer));
96       });
97     });
98
99     if (OSM.STATUS !== "api_offline" && OSM.STATUS !== "database_offline") {
100       var overlaySection = $("<div>")
101         .attr("class", "section overlay-layers")
102         .appendTo($ui);
103
104       $("<p>")
105         .text(I18n.t("javascripts.map.layers.overlays"))
106         .attr("class", "text-muted")
107         .appendTo(overlaySection);
108
109       var overlays = $("<ul class='list-unstyled form-check'>")
110         .appendTo(overlaySection);
111
112       var addOverlay = function (layer, name, maxArea) {
113         var item = $("<li>")
114           .tooltip({
115             placement: "top"
116           })
117           .appendTo(overlays);
118
119         var label = $("<label>")
120           .attr("class", "form-check-label")
121           .appendTo(item);
122
123         var checked = map.hasLayer(layer);
124
125         var input = $("<input>")
126           .attr("type", "checkbox")
127           .attr("class", "form-check-input")
128           .prop("checked", checked)
129           .appendTo(label);
130
131         label.append(I18n.t("javascripts.map.layers." + name));
132
133         input.on("change", function () {
134           checked = input.is(":checked");
135           if (checked) {
136             map.addLayer(layer);
137           } else {
138             map.removeLayer(layer);
139           }
140           map.fire("overlaylayerchange", { layer: layer });
141         });
142
143         map.on("layeradd layerremove", function () {
144           input.prop("checked", map.hasLayer(layer));
145         });
146
147         map.on("zoomend", function () {
148           var disabled = map.getBounds().getSize() >= maxArea;
149           $(input).prop("disabled", disabled);
150
151           if (disabled && $(input).is(":checked")) {
152             $(input).prop("checked", false)
153               .trigger("change");
154             checked = true;
155           } else if (!disabled && !$(input).is(":checked") && checked) {
156             $(input).prop("checked", true)
157               .trigger("change");
158           }
159
160           $(item).attr("class", disabled ? "disabled" : "");
161           item.attr("data-bs-original-title", disabled ?
162             I18n.t("javascripts.site.map_" + name + "_zoom_in_tooltip") : "");
163         });
164       };
165
166       addOverlay(map.noteLayer, "notes", OSM.MAX_NOTE_REQUEST_AREA);
167       addOverlay(map.dataLayer, "data", OSM.MAX_REQUEST_AREA);
168       addOverlay(map.gpsLayer, "gps", Number.POSITIVE_INFINITY);
169     }
170
171     options.sidebar.addPane($ui);
172
173     function toggle(e) {
174       e.stopPropagation();
175       e.preventDefault();
176       options.sidebar.togglePane($ui, button);
177       $(".leaflet-control .control-button").tooltip("hide");
178     }
179
180     return $container[0];
181   };
182
183   return control;
184 };