]> git.openstreetmap.org Git - rails.git/blob - app/assets/javascripts/leaflet.share.js
7880abe14060817337ffef359c850ff44ea3a561
[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     $('<a>')
14       .attr('class', 'control-button')
15       .attr('href', '#')
16       .attr('title', 'Share')
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         $('<a>')
29           .text(I18n.t('javascripts.close'))
30           .attr('class', 'sidebar_close')
31           .attr('href', '#')
32           .bind('click', toggle))
33       .append(
34         $('<h4>')
35           .text(I18n.t('javascripts.share.title')));
36
37     // Link
38
39     var $linkSection = $('<div>')
40       .attr('class', 'section share-link')
41       .appendTo($ui);
42
43     $('<h4>')
44       .text(I18n.t('javascripts.share.link'))
45       .appendTo($linkSection);
46
47     var $shortLink, $longLink;
48
49     $('<ul>')
50       .appendTo($linkSection)
51       .append($('<li>')
52         .append($longLink = $('<a>')
53           .text(I18n.t('javascripts.share.long_link'))))
54       .append($('<li>')
55         .append($shortLink = $('<a>')
56           .text(I18n.t('javascripts.share.short_link'))));
57
58     // Embeddable HTML
59
60     var $embedSection = $('<div>')
61       .attr('class', 'section share-html')
62       .appendTo($ui);
63
64     $('<h4>')
65       .text(I18n.t('javascripts.share.embed'))
66       .appendTo($embedSection);
67
68     var $form = $('<form>')
69       .attr('class', 'standard-form')
70       .attr('action', '/export/finish')
71       .attr('method', 'post')
72       .appendTo($embedSection);
73
74     $('<div>')
75       .attr('class', 'form-row')
76       .appendTo($form)
77       .append(
78         $('<label>')
79           .attr('for', 'embed_marker')
80           .append(
81             $('<input>')
82               .attr('id', 'embed_marker')
83               .attr('type', 'checkbox')
84               .bind('change', toggleMarker))
85           .append(I18n.t('javascripts.share.include_marker')))
86
87     $('<div>')
88       .attr('class', 'form-row')
89       .appendTo($form)
90       .append(
91         $('<textarea>')
92           .attr('id', 'embed_html')
93           .on('click', select));
94
95     $('<p>')
96       .attr('class', 'deemphasize')
97       .text(I18n.t('javascripts.share.paste_html'))
98       .appendTo($embedSection);
99
100     // Image
101
102     var $imageSection = $('<div>')
103       .attr('class', 'section share-image')
104       .appendTo($ui);
105
106     $('<h4>')
107       .text(I18n.t('javascripts.share.image'))
108       .appendTo($imageSection);
109
110     $form = $('<form>')
111       .attr('class', 'standard-form')
112       .attr('action', '/export/finish')
113       .attr('method', 'post')
114       .appendTo($imageSection);
115
116     $('<div>')
117       .attr('class', 'form-row')
118       .appendTo($form)
119       .append(
120         $('<label>')
121           .attr('for', 'image_filter')
122           .append(
123             $('<input>')
124               .attr('id', 'image_filter')
125               .attr('type', 'checkbox')
126               .bind('change', toggleFilter))
127           .append(I18n.t('javascripts.share.custom_dimensions')));
128
129     $('<div>')
130       .attr('class', 'form-row')
131       .appendTo($form)
132       .append(
133         $('<label>')
134           .attr('class', 'standard-label')
135           .attr('for', 'mapnik_format')
136           .text(I18n.t('javascripts.share.format')))
137       .append($('<select>')
138         .attr('name', 'mapnik_format')
139         .attr('id', 'mapnik_format')
140         .append($('<option>').val('png').text('PNG').prop('selected', true))
141         .append($('<option>').val('jpeg').text('JPEG'))
142         .append($('<option>').val('svg').text('SVG'))
143         .append($('<option>').val('pdf').text('PDF')));
144
145     $('<div>')
146       .attr('class', 'form-row')
147       .appendTo($form)
148       .append($('<label>')
149         .attr('class', 'standard-label')
150         .attr('for', 'mapnik_scale')
151         .text(I18n.t('javascripts.share.scale')))
152       .append('1 : ')
153       .append($('<input>')
154         .attr('name', 'mapnik_scale')
155         .attr('id', 'mapnik_scale')
156         .attr('type', 'text')
157         .on('change', update));
158
159     ['minlon', 'minlat', 'maxlon', 'maxlat'].forEach(function(name) {
160       $('<input>')
161         .attr('id', 'mapnik_' + name)
162         .attr('name', name)
163         .attr('type', 'hidden')
164         .appendTo($form);
165     });
166
167     $('<input>')
168       .attr('name', 'format')
169       .attr('value', 'mapnik')
170       .attr('type', 'hidden')
171       .appendTo($form);
172
173     $('<p>')
174       .attr('class', 'deemphasize')
175       .html(I18n.t('javascripts.share.image_size') + ' <span id="mapnik_image_width"></span> x <span id="mapnik_image_height"></span>')
176       .appendTo($form);
177
178     $('<input>')
179       .attr('type', 'submit')
180       .attr('value', I18n.t('javascripts.share.download'))
181       .appendTo($form);
182
183     locationFilter
184       .on('change', update)
185       .addTo(map);
186
187     map.on('moveend layeradd layerremove', update);
188
189     options.sidebar.addPane($ui);
190
191     function toggle(e) {
192       e.stopPropagation();
193       e.preventDefault();
194
195       $('#mapnik_scale').val(getScale());
196       marker.setLatLng(map.getCenter());
197
198       update();
199       options.sidebar.togglePane($ui);
200     }
201
202     function toggleMarker() {
203       if ($(this).is(':checked')) {
204         map.addLayer(marker);
205       } else {
206         map.removeLayer(marker);
207       }
208       update();
209     }
210
211     function toggleFilter() {
212       if ($(this).is(':checked')) {
213         if (!locationFilter.getBounds().isValid()) {
214           locationFilter.setBounds(map.getBounds().pad(-0.2));
215         }
216
217         locationFilter.enable();
218       } else {
219         locationFilter.disable();
220       }
221       update();
222     }
223
224     function update() {
225       // Link
226
227       $shortLink.attr('href', map.getShortUrl());
228       $longLink.attr('href', map.getUrl());
229
230       // Embed
231
232       var bounds = map.getBounds(),
233         center = bounds.getCenter(),
234         params = {
235           bbox: bounds.toBBoxString(),
236           layer: map.getMapBaseLayerId()
237         },
238         linkParams = {
239           lat: center.lat,
240           lon: center.lng,
241           zoom: map.getBoundsZoom(bounds),
242           layers: map.getLayersCode()
243         };
244
245       if (map.hasLayer(marker)) {
246         var m = marker.getLatLng();
247         params.marker = m.lat + ',' + m.lng;
248         linkParams.mlat = m.lat;
249         linkParams.mlon = m.lng;
250       }
251
252       $('#embed_html').val(
253         '<iframe width="425" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="' +
254           'http://' + OSM.SERVER_URL + '/export/embed.html?' + $.param(params) +
255           '" style="border: 1px solid black"></iframe><br/>' +
256           '<small><a href="' +
257           'http://' + OSM.SERVER_URL + '/?' + $.param(linkParams) +
258           '">' + I18n.t('export.start_rjs.view_larger_map') + '</a></small>');
259
260       // Image
261
262       if (locationFilter.isEnabled()) {
263         bounds = locationFilter.getBounds();
264       }
265
266       var scale = $("#mapnik_scale").val(),
267         size = L.bounds(L.CRS.EPSG3857.project(bounds.getSouthWest()),
268                         L.CRS.EPSG3857.project(bounds.getNorthEast())).getSize(),
269         maxScale = Math.floor(Math.sqrt(size.x * size.y / 0.3136));
270
271       $('#mapnik_minlon').val(bounds.getWest());
272       $('#mapnik_minlat').val(bounds.getSouth());
273       $('#mapnik_maxlon').val(bounds.getEast());
274       $('#mapnik_maxlat').val(bounds.getNorth());
275
276       if (scale < maxScale) {
277         scale = roundScale(maxScale);
278         $("#mapnik_scale").val(scale);
279       }
280
281       $("#mapnik_image_width").text(Math.round(size.x / scale / 0.00028));
282       $("#mapnik_image_height").text(Math.round(size.y / scale / 0.00028));
283     }
284
285     function select() {
286       $(this).select();
287     }
288
289     function getScale() {
290       var bounds = map.getBounds(),
291         centerLat = bounds.getCenter().lat,
292         halfWorldMeters = 6378137 * Math.PI * Math.cos(centerLat * Math.PI / 180),
293         meters = halfWorldMeters * (bounds.getEast() - bounds.getWest()) / 180,
294         pixelsPerMeter = map.getSize().x / meters,
295         metersPerPixel = 1 / (92 * 39.3701);
296       return Math.round(1 / (pixelsPerMeter * metersPerPixel));
297     }
298
299     function roundScale(scale) {
300       var precision = 5 * Math.pow(10, Math.floor(Math.LOG10E * Math.log(scale)) - 2);
301       return precision * Math.ceil(scale / precision);
302     }
303
304     return $container[0];
305   };
306
307   return control;
308 };