1f624f125f60c5a61471c6d59a8fe2b03a453a30
[rails.git] / app / assets / javascripts / index / export.js
1 function initializeExport(map) {
2   $("#exportanchor").click(function (e) {
3     $.ajax({ url: $(this).data('url'), success: function (sidebarHtml) {
4       startExport(sidebarHtml);
5     }});
6     e.preventDefault();
7   });
8
9   if (window.location.pathname == "/export") {
10     $("#exportanchor").click();
11   }
12
13   function startExport(sidebarHtml) {
14     var marker;
15
16     var locationFilter = new L.LocationFilter({
17       enableButton: false,
18       adjustButton: false
19     }).addTo(map);
20
21     locationFilter.on("change", filterChanged);
22
23     map.on("moveend", mapMoved);
24     map.on("baselayerchange", htmlUrlChanged);
25
26     $("#sidebar_title").html(I18n.t('export.start_rjs.export'));
27     $("#sidebar_content").html(sidebarHtml);
28
29     $("#maxlat,#minlon,#maxlon,#minlat").change(boundsChanged);
30
31     $("#drag_box").click(enableFilter);
32
33     $("#add_marker").click(startMarker);
34
35     $("#format_osm,#format_mapnik,#format_html").click(formatChanged);
36
37     $("#mapnik_scale").change(mapnikSizeChanged);
38
39     openSidebar();
40
41     if (map.getMapBaseLayerId() == "mapnik") {
42       $("#format_mapnik").prop("checked", true);
43     }
44
45     setBounds(map.getBounds());
46     formatChanged();
47
48     $("body").removeClass("site-index").addClass("site-export");
49
50     $("#sidebar").one("closed", function () {
51       $("body").removeClass("site-export").addClass("site-index");
52
53       map.removeLayer(locationFilter);
54       clearMarker();
55
56       map.off("moveend", mapMoved);
57       map.off("baselayerchange", htmlUrlChanged);
58       locationFilter.off("change", filterChanged);
59     });
60
61     function getBounds() {
62       return L.latLngBounds(L.latLng($("#minlat").val(), $("#minlon").val()),
63                             L.latLng($("#maxlat").val(), $("#maxlon").val()));
64     }
65
66     function getScale() {
67       var bounds = map.getBounds(),
68         centerLat = bounds.getCenter().lat,
69         halfWorldMeters = 6378137 * Math.PI * Math.cos(centerLat * Math.PI / 180),
70         meters = halfWorldMeters * (bounds.getEast() - bounds.getWest()) / 180,
71         pixelsPerMeter = map.getSize().x / meters,
72         metersPerPixel = 1 / (92 * 39.3701);
73       return Math.round(1 / (pixelsPerMeter * metersPerPixel));
74     }
75
76     function getMercatorBounds() {
77       var bounds = getBounds();
78       return L.bounds(L.CRS.EPSG3857.project(bounds.getSouthWest()),
79                       L.CRS.EPSG3857.project(bounds.getNorthEast()));
80     }
81
82     function boundsChanged() {
83       var bounds = getBounds();
84
85       map.fitBounds(bounds);
86       locationFilter.setBounds(bounds);
87
88       enableFilter();
89       validateControls();
90       mapnikSizeChanged();
91     }
92
93     function enableFilter() {
94       if (!locationFilter.getBounds().isValid()) {
95         locationFilter.setBounds(map.getBounds().pad(-0.2));
96       }
97
98       $("#drag_box").hide();
99       locationFilter.enable();
100     }
101
102     function filterChanged() {
103       setBounds(locationFilter.getBounds());
104       validateControls();
105     }
106
107     function startMarker() {
108       $("#add_marker").html(I18n.t('export.start_rjs.click_add_marker'));
109
110       map.on("click", endMarker);
111
112       return false;
113     }
114
115     function endMarker(event) {
116       map.off("click", endMarker);
117
118       $("#add_marker").html(I18n.t('export.start_rjs.change_marker'));
119       $("#marker_inputs").show();
120
121       var latlng = event.latlng;
122
123       if (marker) {
124         map.removeLayer(marker);
125       }
126
127       marker = L.marker(latlng).addTo(map);
128
129       $("#marker_lon").val(latlng.lng.toFixed(5));
130       $("#marker_lat").val(latlng.lat.toFixed(5));
131
132       htmlUrlChanged();
133     }
134
135     function clearMarker() {
136       $("#marker_lon,#marker_lat").val("");
137       $("#marker_inputs").hide();
138       $("#add_marker").html(I18n.t('export.start_rjs.add_marker'));
139
140       if (marker) {
141         map.removeLayer(marker);
142       }
143     }
144
145     function mapMoved() {
146       if (!locationFilter.isEnabled()) {
147         setBounds(map.getBounds());
148         validateControls();
149       }
150     }
151
152     function setBounds(bounds) {
153       var toPrecision = zoomPrecision(map.getZoom());
154
155       $("#minlon").val(toPrecision(bounds.getWest()));
156       $("#minlat").val(toPrecision(bounds.getSouth()));
157       $("#maxlon").val(toPrecision(bounds.getEast()));
158       $("#maxlat").val(toPrecision(bounds.getNorth()));
159
160       mapnikSizeChanged();
161       htmlUrlChanged();
162     }
163
164     function validateControls() {
165       var bounds = getBounds();
166
167       var tooLarge = bounds.getSize() > OSM.MAX_REQUEST_AREA;
168       if (tooLarge) {
169         $("#export_osm_too_large").show();
170       } else {
171         $("#export_osm_too_large").hide();
172       }
173
174       var max_scale = maxMapnikScale();
175       var disabled = true;
176
177       if ($("#format_osm").prop("checked")) {
178         disabled = tooLarge;
179       } else if ($("#format_mapnik").prop("checked")) {
180         disabled = $("#mapnik_scale").val() < max_scale;
181       }
182
183       $("#export_commit").prop("disabled", disabled);
184       $("#mapnik_max_scale").html(roundScale(max_scale));
185     }
186
187     function htmlUrlChanged() {
188       var bounds = getBounds();
189       var layerName = map.getMapBaseLayerId();
190
191       var url = "http://" + OSM.SERVER_URL + "/export/embed.html?bbox=" + bounds.toBBoxString() + "&amp;layer=" + layerName;
192       var markerUrl = "";
193
194       if ($("#marker_lat").val() && $("#marker_lon").val()) {
195         markerUrl = "&amp;mlat=" + $("#marker_lat").val() + "&amp;mlon=" + $("#marker_lon").val();
196         url += "&amp;marker=" + $("#marker_lat").val() + "," + $("#marker_lon").val();
197       }
198
199       var html = '<iframe width="425" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="'+url+'" style="border: 1px solid black"></iframe>';
200
201       // Create "larger map" link
202       var center = bounds.getCenter();
203
204       var zoom = map.getBoundsZoom(bounds);
205
206       var layers = getMapLayers(map);
207
208       var text = I18n.t('export.start_rjs.view_larger_map');
209       var escaped = [];
210
211       for (var i = 0; i < text.length; ++i) {
212         var c = text.charCodeAt(i);
213         escaped.push(c < 127 ? text.charAt(i) : "&#" + c + ";");
214       }
215
216       html += '<br /><small><a href="http://' + OSM.SERVER_URL + '/?lat='+center.lat+'&amp;lon='+center.lng+'&amp;zoom='+zoom+'&amp;layers='+layers+markerUrl+'">'+escaped.join("")+'</a></small>';
217
218       $("#export_html_text").val(html);
219
220       if ($("#format_html").prop("checked")) {
221         $("#export_html_text").prop("selected", true);
222       }
223     }
224
225     function formatChanged() {
226       $("#export_commit").show();
227
228       if ($("#format_osm").prop("checked")) {
229         $("#export_osm").show();
230       } else {
231         $("#export_osm").hide();
232       }
233
234       if ($("#format_mapnik").prop("checked")) {
235         $("#mapnik_scale").val(getScale());
236         $("#export_mapnik").show();
237
238         mapnikSizeChanged();
239       } else {
240         $("#export_mapnik").hide();
241       }
242
243       if ($("#format_html").prop("checked")) {
244         $("#export_html").show();
245         $("#export_commit").hide();
246         $("#export_html_text").prop("selected", true);
247       } else {
248         $("#export_html").hide();
249
250         clearMarker();
251       }
252
253       validateControls();
254     }
255
256     function maxMapnikScale() {
257       var size = getMercatorBounds().getSize();
258
259       return Math.floor(Math.sqrt(size.x * size.y / 0.3136));
260     }
261
262     function mapnikImageSize(scale) {
263       var size = getMercatorBounds().getSize();
264
265       return {w: Math.round(size.x / scale / 0.00028),
266               h: Math.round(size.y / scale / 0.00028)};
267     }
268
269     function roundScale(scale) {
270       var precision = 5 * Math.pow(10, Math.floor(Math.LOG10E * Math.log(scale)) - 2);
271
272       return precision * Math.ceil(scale / precision);
273     }
274
275     function mapnikSizeChanged() {
276       var size = mapnikImageSize($("#mapnik_scale").val());
277
278       $("#mapnik_image_width").html(size.w);
279       $("#mapnik_image_height").html(size.h);
280
281       validateControls();
282     }
283   }
284 }