]> git.openstreetmap.org Git - rails.git/blob - app/views/export/start.js.erb
Allow the export box to be moved and resized
[rails.git] / app / views / export / start.js.erb
1 var vectors;
2 var box;
3 var transform;
4 var markerLayer;
5 var markerControl;
6
7 function startExport() {
8   vectors = new OpenLayers.Layer.Vector("Vector Layer", {
9     displayInLayerSwitcher: false
10   });
11   map.addLayer(vectors);
12
13   box = new OpenLayers.Control.DrawFeature(vectors, OpenLayers.Handler.RegularPolygon, {
14     handlerOptions: {
15       sides: 4,
16       snapAngle: 90,
17       irregular: true,
18       persist: true
19     }
20   });
21   box.handler.callbacks.done = endDrag;
22   map.addControl(box);
23
24   transform = new OpenLayers.Control.TransformFeature(vectors, {
25     rotate: false,
26     irregular: true
27   });
28   transform.events.register("transformcomplete", transform, transformComplete);
29   map.addControl(transform);
30
31   map.events.register("moveend", map, mapMoved);
32   map.events.register("changebaselayer", map, htmlUrlChanged);
33
34   $("#sidebar_title").html("<%=j t 'export.start_rjs.export' %>");
35   $("#sidebar_content").html("<%=j render :partial => "sidebar" %>");
36
37   $("#maxlat").change(boundsChanged);
38   $("#minlon").change(boundsChanged);
39   $("#maxlon").change(boundsChanged);
40   $("#minlat").change(boundsChanged);
41
42   $("#drag_box").click(startDrag);
43
44   $("#add_marker").click(startMarker);
45
46   $("#format_osm").click(formatChanged);
47   $("#format_mapnik").click(formatChanged);
48   $("#format_osmarender").click(formatChanged);
49   $("#format_html").click(formatChanged);
50
51   $("#mapnik_scale").change(mapnikSizeChanged);
52
53   openSidebar({ onclose: stopExport });
54
55   if (map.baseLayer.name == "Mapnik") {
56     $("#format_mapnik").prop("checked", true);
57   } else if (map.baseLayer.name == "Osmarender") {
58     $("#format_osmarender").prop("checked", true);
59   }
60
61   formatChanged();
62   setBounds(map.getExtent());
63
64   $("#viewanchor").removeClass("active");
65   $("#exportanchor").addClass("active");
66 }
67
68 function stopExport() {
69   $("#viewanchor").addClass("active");
70   $("#exportanchor").removeClass("active");
71
72   clearBox();
73   clearMarker();
74   map.events.unregister("moveend", map, mapMoved);
75   map.events.unregister("changebaselayer", map, htmlUrlChanged);
76   map.removeLayer(vectors);
77 }
78
79 function boundsChanged() {
80   var epsg4326 = new OpenLayers.Projection("EPSG:4326");
81   var bounds = new OpenLayers.Bounds($("#minlon").val(), $("#minlat").val(),
82                                      $("#maxlon").val(), $("#maxlat").val());
83
84   bounds.transform(epsg4326, map.getProjectionObject());
85
86   map.events.unregister("moveend", map, mapMoved);
87   map.zoomToExtent(bounds);
88
89   clearBox();
90   drawBox(bounds);
91
92   validateControls();
93   mapnikSizeChanged();
94 }
95
96 function startDrag() {
97   $("#drag_box").html("<%=j t 'export.start_rjs.drag_a_box' %>");
98
99   clearBox();
100   box.activate();
101 };
102
103 function endDrag(bbox) {
104   var bounds = bbox.getBounds();
105
106   map.events.unregister("moveend", map, mapMoved);
107   setBounds(bounds);
108   drawBox(bounds);
109   box.deactivate();
110   validateControls();
111
112   $("#drag_box").html("<%=j t 'export.start_rjs.manually_select' %>");
113 }
114
115 function transformComplete(event) {
116   setBounds(event.feature.geometry.bounds);
117   validateControls();
118 }
119
120 function startMarker() {
121   $("#add_marker").html("<%=j t 'export.start_rjs.click_add_marker' %>");
122
123   if (!markerLayer) {
124     markerLayer = new OpenLayers.Layer.Vector("",{
125       displayInLayerSwitcher: false,
126       style: {
127         externalGraphic: OpenLayers.Util.getImagesLocation() + "marker.png",
128         graphicXOffset: -10.5,
129         graphicYOffset: -25,
130         graphicWidth: 21,
131         graphicHeight: 25
132       }
133     });
134     map.addLayer(markerLayer);
135
136     markerControl = new OpenLayers.Control.DrawFeature(markerLayer, OpenLayers.Handler.Point);
137     map.addControl(markerControl);
138
139     markerLayer.events.on({ "featureadded": endMarker });
140   }
141
142   markerLayer.destroyFeatures();
143   markerControl.activate();
144
145   return false;
146 }
147
148 function endMarker(event) {
149   markerControl.deactivate();
150
151   $("#add_marker").html("<%=j t 'export.start_rjs.change_marker' %>");
152   $("#marker_inputs").show();
153
154   var epsg4326 = new OpenLayers.Projection("EPSG:4326");
155   var epsg900913 = new OpenLayers.Projection("EPSG:900913");
156   var geom = event.feature.geometry.clone().transform(epsg900913, epsg4326);
157
158   $("#marker_lon").val(geom.x.toFixed(5));
159   $("#marker_lat").val(geom.y.toFixed(5));
160
161   htmlUrlChanged();
162 }
163
164 function clearMarker() {
165   $("#marker_lon").val("");
166   $("#marker_lat").val("");
167   $("#marker_inputs").hide();
168   $("#add_marker").html("<%=j t 'export.start_rjs.add_marker' %>");
169
170   if (markerLayer) {
171     markerControl.destroy();
172     markerLayer.destroy();
173     markerLayer = null;
174     markerControl = null;
175   }
176 }
177
178 function mapMoved() {
179   setBounds(map.getExtent());
180   validateControls();
181 }
182
183 function setBounds(bounds) {
184   var epsg4326 = new OpenLayers.Projection("EPSG:4326");
185   var decimals = Math.pow(10, Math.floor(map.getZoom() / 3));
186
187   bounds = bounds.clone().transform(map.getProjectionObject(), epsg4326);
188
189   $("#minlon").val(Math.round(bounds.left * decimals) / decimals);
190   $("#minlat").val(Math.round(bounds.bottom * decimals) / decimals);
191   $("#maxlon").val(Math.round(bounds.right * decimals) / decimals);
192   $("#maxlat").val(Math.round(bounds.top * decimals) / decimals);
193
194   mapnikSizeChanged();
195   htmlUrlChanged();
196 }
197
198 function clearBox() {
199   transform.deactivate();
200   vectors.destroyFeatures();
201 }
202
203 function drawBox(bounds) {
204   var feature = new OpenLayers.Feature.Vector(bounds.toGeometry());
205
206   vectors.addFeatures(feature);
207   transform.setFeature(feature);
208 }
209
210 function validateControls() {
211   var bounds = new OpenLayers.Bounds($("#minlon").val(), $("#minlat").val(), $("#maxlon").val(), $("#maxlat").val());
212
213   if (bounds.getWidth() * bounds.getHeight() > <%= MAX_REQUEST_AREA %>) {
214     $("#export_osm_too_large").show();
215   } else {
216     $("#export_osm_too_large").hide();
217   }
218
219   var max_scale = maxMapnikScale();
220
221   if ($("#format_osm").prop("checked") && bounds.getWidth() * bounds.getHeight() > <%= MAX_REQUEST_AREA %>) {
222     $("#export_commit").prop("disabled", true);
223   } else if ($("#format_mapnik").prop("checked") && $("#mapnik_scale").val() < max_scale) {
224     $("#export_commit").prop("disabled", true);
225   } else {
226     $("#export_commit").prop("disabled", false);
227   }
228
229   $("#mapnik_max_scale").html(roundScale(max_scale));
230
231   var max_zoom = maxOsmarenderZoom();
232
233   $("#osmarender_zoom option").each(function () {
234     if ($(this).val() > max_zoom) {
235       $(this).prop("disabled", true);
236     } else {
237       $(this).prop("disabled", false);
238     }
239   });
240
241   if ($("#osmarender_zoom option").is(":disabled:selected")) {
242     $("#osmarender_zoom option").filter(":enabled").last().prop("selected", true);
243   }
244 }
245
246 function htmlUrlChanged() {
247   var bounds = new OpenLayers.Bounds($("#minlon").val(), $("#minlat").val(), $("#maxlon").val(), $("#maxlat").val());
248   var layerName = map.baseLayer.keyid;
249   var url = "http://<%= SERVER_URL %>/export/embed.html?bbox=" + bounds.toBBOX() + "&amp;layer=" + layerName;
250   var markerUrl = "";
251
252   if ($("#marker_lat").val() && $("#marker_lon").val()) {
253     markerUrl = "&amp;mlat=" + $("#marker_lat").val() + "&amp;mlon=" + $("#marker_lon").val();
254     url += "&amp;marker=" + $("#marker_lat").val() + "," + $("#marker_lon").val();
255   }
256
257   var html = '<iframe width="425" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="'+url+'" style="border: 1px solid black"></iframe>';
258
259   // Create "larger map" link
260   var center = bounds.getCenterLonLat();
261   var epsg4326 = new OpenLayers.Projection("EPSG:4326");
262   var epsg900913 = new OpenLayers.Projection("EPSG:900913");
263
264   bounds.transform(epsg4326, epsg900913);
265   var zoom = map.getZoomForExtent(bounds);
266
267   var layers = getMapLayers();
268
269   html += '<br /><small><a href="http://<%= SERVER_URL %>/?lat='+center.lat+'&amp;lon='+center.lon+'&amp;zoom='+zoom+'&amp;layers='+layers+markerUrl+'">'+"<%= html_escape_unicode(I18n.t('export.start_rjs.view_larger_map')) %>"+'</a></small>';
270
271   $("#export_html_text").val(html);
272
273   if ($("#format_html").prop("checked")) {
274     $("#export_html_text").prop("selected", true);
275   }
276 }
277
278 function formatChanged() {
279   $("#export_commit").show();
280
281   if ($("#format_osm").prop("checked")) {
282     $("#export_osm").show();
283   } else {
284     $("#export_osm").hide();
285   }
286
287   if ($("#format_mapnik").prop("checked")) {
288     $("#mapnik_scale").val(roundScale(map.getScale()));
289     $("#export_mapnik").show();
290   } else {
291     $("#export_mapnik").hide();
292   }
293
294   if ($("#format_osmarender").prop("checked")) {
295     var zoom = Math.min(map.getZoom(), maxOsmarenderZoom());
296
297     $("#osmarender_zoom option[value=" + zoom + "]").prop("selected", true);
298     $("#export_osmarender").show();
299   } else {
300     $("#export_osmarender").hide();
301   }
302
303   if ($("#format_html").prop("checked")) {
304     $("#export_html").show();
305     $("#export_commit").hide();
306     $("#export_html_text").prop("selected", true);
307   } else {
308     $("#export_html").hide();
309
310     clearMarker();
311   }
312
313   validateControls();
314 }
315
316 function maxMapnikScale() {
317   var bounds = new OpenLayers.Bounds($("#minlon").val(), $("#minlat").val(), $("#maxlon").val(), $("#maxlat").val());
318   var epsg4326 = new OpenLayers.Projection("EPSG:4326");
319   var epsg900913 = new OpenLayers.Projection("EPSG:900913");
320
321   bounds.transform(epsg4326, epsg900913);
322
323   return Math.floor(Math.sqrt(bounds.getWidth() * bounds.getHeight() / 0.3136));
324 }
325
326 function mapnikImageSize(scale) {
327   var bounds = new OpenLayers.Bounds($("#minlon").val(), $("#minlat").val(), $("#maxlon").val(), $("#maxlat").val());
328   var epsg4326 = new OpenLayers.Projection("EPSG:4326");
329   var epsg900913 = new OpenLayers.Projection("EPSG:900913");
330
331   bounds.transform(epsg4326, epsg900913);
332
333   return new OpenLayers.Size(Math.round(bounds.getWidth() / scale / 0.00028),
334                              Math.round(bounds.getHeight() / scale / 0.00028));
335 }
336
337 function maxOsmarenderZoom() {
338   var bounds = new OpenLayers.Bounds($("#minlon").val(), $("#minlat").val(), $("#maxlon").val(), $("#maxlat").val());
339   var xzoom = Math.LOG2E * Math.log(2000 * 1.40625 / bounds.getWidth());
340   var ymin = bounds.bottom * Math.PI / 180;
341   var ymax = bounds.top * Math.PI / 180;
342   var yzoom = Math.LOG2E * (Math.log(2000 * 2 * Math.PI) - Math.log(Math.log((Math.tan(ymax) + 1 / Math.cos(ymax)) / (Math.tan(ymin) + 1 / Math.cos(ymin)))))
343
344   return Math.min(Math.floor(Math.min(xzoom, yzoom)), 17);
345 }
346
347 function roundScale(scale) {
348   var precision = 5 * Math.pow(10, Math.floor(Math.LOG10E * Math.log(scale)) - 2);
349
350   return precision * Math.ceil(scale / precision);
351 }
352
353 function mapnikSizeChanged() {
354   var size = mapnikImageSize($("#mapnik_scale").val());
355
356   $("#mapnik_image_width").html(size.w);
357   $("#mapnik_image_height").html(size.h);
358
359   validateControls();
360 }
361
362 startExport();