]> git.openstreetmap.org Git - rails.git/blob - app/assets/javascripts/leaflet.share.js
Create pane button fn
[rails.git] / app / assets / javascripts / leaflet.share.js
1 L.OSM.share = function (options) {
2   var control = L.OSM.sidebarPane(options),
3       marker = L.marker([0, 0], { draggable: true }),
4       locationFilter = new L.LocationFilter({
5         enableButton: false,
6         adjustButton: false
7       });
8
9   control.onAdd = function (map) {
10     var $container = $("<div>")
11       .attr("class", "control-share");
12
13     var button = this.makeButton("share", "javascripts.share.title", toggle)
14       .appendTo($container);
15
16     var $ui = this.makeUI("share-ui", "javascripts.share.title", toggle);
17
18     // Link / Embed
19
20     var $linkSection = $("<div>")
21       .attr("class", "section share-link")
22       .appendTo($ui);
23
24     $("<h4>")
25       .text(I18n.t("javascripts.share.link"))
26       .appendTo($linkSection);
27
28     var $form = $("<form>")
29       .appendTo($linkSection);
30
31     $("<div>")
32       .attr("class", "form-check mb-3")
33       .appendTo($form)
34       .append(
35         $("<label>")
36           .attr("for", "link_marker")
37           .attr("class", "form-check-label")
38           .append(
39             $("<input>")
40               .attr("id", "link_marker")
41               .attr("type", "checkbox")
42               .attr("class", "form-check-input")
43               .bind("change", toggleMarker))
44           .append(I18n.t("javascripts.share.include_marker")));
45
46     $("<div>")
47       .attr("class", "share-tabs")
48       .appendTo($form)
49       .append($("<a>")
50         .attr("class", "active")
51         .attr("for", "long_input")
52         .attr("id", "long_link")
53         .text(I18n.t("javascripts.share.long_link")))
54       .append($("<a>")
55         .attr("for", "short_input")
56         .attr("id", "short_link")
57         .text(I18n.t("javascripts.share.short_link")))
58       .append($("<a>")
59         .attr("for", "embed_html")
60         .attr("href", "#")
61         .text(I18n.t("javascripts.share.embed")))
62       .on("click", "a", function (e) {
63         e.preventDefault();
64         var id = "#" + $(this).attr("for");
65         $linkSection.find(".share-tabs a")
66           .removeClass("active");
67         $(this).addClass("active");
68         $linkSection.find(".share-tab")
69           .hide();
70         $linkSection.find(".share-tab:has(" + id + ")")
71           .show()
72           .find("input, textarea")
73           .select();
74       });
75
76     $("<div>")
77       .attr("class", "share-tab")
78       .css("display", "block")
79       .appendTo($form)
80       .append($("<input>")
81         .attr("id", "long_input")
82         .attr("type", "text")
83         .on("click", select));
84
85     $("<div>")
86       .attr("class", "share-tab")
87       .appendTo($form)
88       .append($("<input>")
89         .attr("id", "short_input")
90         .attr("type", "text")
91         .on("click", select));
92
93     $("<div>")
94       .attr("class", "share-tab")
95       .appendTo($form)
96       .append(
97         $("<textarea>")
98           .attr("id", "embed_html")
99           .on("click", select))
100       .append(
101         $("<p>")
102           .attr("class", "text-muted")
103           .text(I18n.t("javascripts.share.paste_html"))
104           .appendTo($linkSection));
105
106     // Geo URI
107
108     var $geoUriSection = $("<div>")
109       .attr("class", "section share-geo-uri")
110       .appendTo($ui);
111
112     $("<h4>")
113       .text(I18n.t("javascripts.share.geo_uri"))
114       .appendTo($geoUriSection);
115
116     $("<div>")
117       .appendTo($geoUriSection)
118       .append($("<a>")
119         .attr("id", "geo_uri"));
120
121     // Image
122
123     var $imageSection = $("<div>")
124       .attr("class", "section share-image")
125       .appendTo($ui);
126
127     $("<h4>")
128       .text(I18n.t("javascripts.share.image"))
129       .appendTo($imageSection);
130
131     $("<div>")
132       .attr("id", "export-warning")
133       .attr("class", "text-muted")
134       .text(I18n.t("javascripts.share.only_standard_layer"))
135       .appendTo($imageSection);
136
137     $form = $("<form>")
138       .attr("id", "export-image")
139       .attr("action", "/export/finish")
140       .attr("method", "post")
141       .appendTo($imageSection);
142
143     $("<div>")
144       .attr("class", "mb-3 form-check")
145       .appendTo($form)
146       .append(
147         $("<label>")
148           .attr("for", "image_filter")
149           .attr("class", "form-check-label")
150           .append(
151             $("<input>")
152               .attr("id", "image_filter")
153               .attr("type", "checkbox")
154               .attr("class", "form-check-input")
155               .bind("change", toggleFilter))
156           .append(I18n.t("javascripts.share.custom_dimensions")));
157
158     $("<div>")
159       .appendTo($form)
160       .append(
161         $("<label>")
162           .attr("for", "mapnik_format")
163           .text(I18n.t("javascripts.share.format")))
164       .append($("<select>")
165         .attr("name", "mapnik_format")
166         .attr("id", "mapnik_format")
167         .append($("<option>").val("png").text("PNG").prop("selected", true))
168         .append($("<option>").val("jpeg").text("JPEG"))
169         .append($("<option>").val("svg").text("SVG"))
170         .append($("<option>").val("pdf").text("PDF")));
171
172     $("<div>")
173       .appendTo($form)
174       .append($("<label>")
175         .attr("for", "mapnik_scale")
176         .text(I18n.t("javascripts.share.scale")))
177       .append("1 : ")
178       .append($("<input>")
179         .attr("name", "mapnik_scale")
180         .attr("id", "mapnik_scale")
181         .attr("type", "text")
182         .on("change", update));
183
184     ["minlon", "minlat", "maxlon", "maxlat"].forEach(function (name) {
185       $("<input>")
186         .attr("id", "mapnik_" + name)
187         .attr("name", name)
188         .attr("type", "hidden")
189         .appendTo($form);
190     });
191
192     $("<input>")
193       .attr("name", "format")
194       .attr("value", "mapnik")
195       .attr("type", "hidden")
196       .appendTo($form);
197
198     var csrf_param = $("meta[name=csrf-param]").attr("content"),
199         csrf_token = $("meta[name=csrf-token]").attr("content");
200
201     $("<input>")
202       .attr("name", csrf_param)
203       .attr("value", csrf_token)
204       .attr("type", "hidden")
205       .appendTo($form);
206
207     var args = {
208       width: "<span id=\"mapnik_image_width\"></span>",
209       height: "<span id=\"mapnik_image_height\"></span>"
210     };
211
212     $("<p>")
213       .attr("class", "text-muted")
214       .html(I18n.t("javascripts.share.image_dimensions", args))
215       .appendTo($form);
216
217     $("<input>")
218       .attr("type", "submit")
219       .attr("class", "btn btn-primary")
220       .attr("value", I18n.t("javascripts.share.download"))
221       .appendTo($form);
222
223     locationFilter
224       .on("change", update)
225       .addTo(map);
226
227     marker.on("dragend", movedMarker);
228     map.on("move", movedMap);
229     map.on("moveend layeradd layerremove", update);
230
231     options.sidebar.addPane($ui);
232
233     $ui
234       .on("hide", hidden);
235
236     function hidden() {
237       map.removeLayer(marker);
238       map.options.scrollWheelZoom = map.options.doubleClickZoom = true;
239       locationFilter.disable();
240       update();
241     }
242
243     function toggle(e) {
244       e.stopPropagation();
245       e.preventDefault();
246
247       $("#mapnik_scale").val(getScale());
248       marker.setLatLng(map.getCenter());
249
250       update();
251       options.sidebar.togglePane($ui, button);
252       $(".leaflet-control .control-button").tooltip("hide");
253     }
254
255     function toggleMarker() {
256       if ($(this).is(":checked")) {
257         marker.setLatLng(map.getCenter());
258         map.addLayer(marker);
259         map.options.scrollWheelZoom = map.options.doubleClickZoom = "center";
260       } else {
261         map.removeLayer(marker);
262         map.options.scrollWheelZoom = map.options.doubleClickZoom = true;
263       }
264       update();
265     }
266
267     function toggleFilter() {
268       if ($(this).is(":checked")) {
269         locationFilter.setBounds(map.getBounds().pad(-0.2));
270         locationFilter.enable();
271       } else {
272         locationFilter.disable();
273       }
274       update();
275     }
276
277     function movedMap() {
278       marker.setLatLng(map.getCenter());
279       update();
280     }
281
282     function movedMarker() {
283       if (map.hasLayer(marker)) {
284         map.off("move", movedMap);
285         map.on("moveend", updateOnce);
286         map.panTo(marker.getLatLng());
287       }
288     }
289
290     function updateOnce() {
291       map.off("moveend", updateOnce);
292       map.on("move", movedMap);
293       update();
294     }
295
296     function escapeHTML(string) {
297       var htmlEscapes = {
298         "&": "&amp;",
299         "<": "&lt;",
300         ">": "&gt;",
301         "\"": "&quot;",
302         "'": "&#x27;"
303       };
304       return string === null ? "" : String(string).replace(/[&<>"']/g, function (match) {
305         return htmlEscapes[match];
306       });
307     }
308
309     function update() {
310       var bounds = map.getBounds();
311
312       $("#link_marker")
313         .prop("checked", map.hasLayer(marker));
314
315       $("#image_filter")
316         .prop("checked", locationFilter.isEnabled());
317
318       // Link / Embed
319
320       $("#short_input").val(map.getShortUrl(marker));
321       $("#long_input").val(map.getUrl(marker));
322       $("#short_link").attr("href", map.getShortUrl(marker));
323       $("#long_link").attr("href", map.getUrl(marker));
324
325       var params = {
326         bbox: bounds.toBBoxString(),
327         layer: map.getMapBaseLayerId()
328       };
329
330       if (map.hasLayer(marker)) {
331         var latLng = marker.getLatLng().wrap();
332         params.marker = latLng.lat + "," + latLng.lng;
333       }
334
335       $("#embed_html").val(
336         "<iframe width=\"425\" height=\"350\" frameborder=\"0\" scrolling=\"no\" marginheight=\"0\" marginwidth=\"0\" src=\"" +
337           escapeHTML(OSM.SERVER_PROTOCOL + "://" + OSM.SERVER_URL + "/export/embed.html?" + $.param(params)) +
338           "\" style=\"border: 1px solid black\"></iframe><br/>" +
339           "<small><a href=\"" + escapeHTML(map.getUrl(marker)) + "\">" +
340           escapeHTML(I18n.t("javascripts.share.view_larger_map")) + "</a></small>");
341
342       // Geo URI
343
344       $("#geo_uri")
345         .attr("href", map.getGeoUri(marker))
346         .html(map.getGeoUri(marker));
347
348       // Image
349
350       if (locationFilter.isEnabled()) {
351         bounds = locationFilter.getBounds();
352       }
353
354       var scale = $("#mapnik_scale").val(),
355           size = L.bounds(L.CRS.EPSG3857.project(bounds.getSouthWest()),
356                           L.CRS.EPSG3857.project(bounds.getNorthEast())).getSize(),
357           maxScale = Math.floor(Math.sqrt(size.x * size.y / 0.3136));
358
359       $("#mapnik_minlon").val(bounds.getWest());
360       $("#mapnik_minlat").val(bounds.getSouth());
361       $("#mapnik_maxlon").val(bounds.getEast());
362       $("#mapnik_maxlat").val(bounds.getNorth());
363
364       if (scale < maxScale) {
365         scale = roundScale(maxScale);
366         $("#mapnik_scale").val(scale);
367       }
368
369       $("#mapnik_image_width").text(Math.round(size.x / scale / 0.00028));
370       $("#mapnik_image_height").text(Math.round(size.y / scale / 0.00028));
371
372       if (map.getMapBaseLayerId() === "mapnik") {
373         $("#export-image").show();
374         $("#export-warning").hide();
375       } else {
376         $("#export-image").hide();
377         $("#export-warning").show();
378       }
379     }
380
381     function select() {
382       $(this).select();
383     }
384
385     function getScale() {
386       var bounds = map.getBounds(),
387           centerLat = bounds.getCenter().lat,
388           halfWorldMeters = 6378137 * Math.PI * Math.cos(centerLat * Math.PI / 180),
389           meters = halfWorldMeters * (bounds.getEast() - bounds.getWest()) / 180,
390           pixelsPerMeter = map.getSize().x / meters,
391           metersPerPixel = 1 / (92 * 39.3701);
392       return Math.round(1 / (pixelsPerMeter * metersPerPixel));
393     }
394
395     function roundScale(scale) {
396       var precision = 5 * Math.pow(10, Math.floor(Math.LOG10E * Math.log(scale)) - 2);
397       return precision * Math.ceil(scale / precision);
398     }
399
400     return $container[0];
401   };
402
403   return control;
404 };