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