bc1a87910984a7fde74b22069c19a335668d20e7
[rails.git] / app / assets / javascripts / export.js
1 var vectors;
2 var box;
3 var transform;
4 var markerLayer;
5 var markerControl;
6
7 function startExport(sidebarHtml) {
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(I18n.t('export.start_rjs.export'));
35   $("#sidebar_content").html(sidebarHtml);
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_html").click(formatChanged);
49
50   $("#mapnik_scale").change(mapnikSizeChanged);
51
52   openSidebar({ onclose: stopExport });
53
54   if (map.baseLayer.name == "Mapnik") {
55     $("#format_mapnik").prop("checked", true);
56   }
57
58   formatChanged();
59   setBounds(map.getExtent());
60
61   $("#viewanchor").removeClass("active");
62   $("#exportanchor").addClass("active");
63 }
64
65 function stopExport() {
66   $("#viewanchor").addClass("active");
67   $("#exportanchor").removeClass("active");
68
69   clearBox();
70   clearMarker();
71   map.events.unregister("moveend", map, mapMoved);
72   map.events.unregister("changebaselayer", map, htmlUrlChanged);
73   map.removeLayer(vectors);
74 }
75
76 function boundsChanged() {
77   var epsg4326 = new OpenLayers.Projection("EPSG:4326");
78   var bounds = new OpenLayers.Bounds($("#minlon").val(), $("#minlat").val(),
79                                      $("#maxlon").val(), $("#maxlat").val());
80
81   bounds.transform(epsg4326, map.getProjectionObject());
82
83   map.events.unregister("moveend", map, mapMoved);
84   map.zoomToExtent(bounds);
85
86   clearBox();
87   drawBox(bounds);
88
89   validateControls();
90   mapnikSizeChanged();
91 }
92
93 function startDrag() {
94   $("#drag_box").html(I18n.t('export.start_rjs.drag_a_box'));
95
96   clearBox();
97   box.activate();
98 };
99
100 function endDrag(bbox) {
101   var bounds = bbox.getBounds();
102
103   map.events.unregister("moveend", map, mapMoved);
104   setBounds(bounds);
105   drawBox(bounds);
106   box.deactivate();
107   validateControls();
108
109   $("#drag_box").html(I18n.t('export.start_rjs.manually_select'));
110 }
111
112 function transformComplete(event) {
113   setBounds(event.feature.geometry.bounds);
114   validateControls();
115 }
116
117 function startMarker() {
118   $("#add_marker").html(I18n.t('export.start_rjs.click_add_marker'));
119
120   if (!markerLayer) {
121     markerLayer = new OpenLayers.Layer.Vector("",{
122       displayInLayerSwitcher: false,
123       style: {
124         externalGraphic: OpenLayers.Util.getImageLocation("marker.png"),
125         graphicXOffset: -10.5,
126         graphicYOffset: -25,
127         graphicWidth: 21,
128         graphicHeight: 25
129       }
130     });
131     map.addLayer(markerLayer);
132
133     markerControl = new OpenLayers.Control.DrawFeature(markerLayer, OpenLayers.Handler.Point);
134     map.addControl(markerControl);
135
136     markerLayer.events.on({ "featureadded": endMarker });
137   }
138
139   markerLayer.destroyFeatures();
140   markerControl.activate();
141
142   return false;
143 }
144
145 function endMarker(event) {
146   markerControl.deactivate();
147
148   $("#add_marker").html(I18n.t('export.start_rjs.change_marker'));
149   $("#marker_inputs").show();
150
151   var epsg4326 = new OpenLayers.Projection("EPSG:4326");
152   var epsg900913 = new OpenLayers.Projection("EPSG:900913");
153   var geom = event.feature.geometry.clone().transform(epsg900913, epsg4326);
154
155   $("#marker_lon").val(geom.x.toFixed(5));
156   $("#marker_lat").val(geom.y.toFixed(5));
157
158   htmlUrlChanged();
159 }
160
161 function clearMarker() {
162   $("#marker_lon").val("");
163   $("#marker_lat").val("");
164   $("#marker_inputs").hide();
165   $("#add_marker").html(I18n.t('export.start_rjs.add_marker'));
166
167   if (markerLayer) {
168     markerControl.destroy();
169     markerLayer.destroy();
170     markerLayer = null;
171     markerControl = null;
172   }
173 }
174
175 function mapMoved() {
176   setBounds(map.getExtent());
177   validateControls();
178 }
179
180 function setBounds(bounds) {
181   var epsg4326 = new OpenLayers.Projection("EPSG:4326");
182   var decimals = Math.pow(10, Math.floor(map.getZoom() / 3));
183
184   bounds = bounds.clone().transform(map.getProjectionObject(), epsg4326);
185
186   $("#minlon").val(Math.round(bounds.left * decimals) / decimals);
187   $("#minlat").val(Math.round(bounds.bottom * decimals) / decimals);
188   $("#maxlon").val(Math.round(bounds.right * decimals) / decimals);
189   $("#maxlat").val(Math.round(bounds.top * decimals) / decimals);
190
191   mapnikSizeChanged();
192   htmlUrlChanged();
193 }
194
195 function clearBox() {
196   transform.deactivate();
197   vectors.destroyFeatures();
198 }
199
200 function drawBox(bounds) {
201   var feature = new OpenLayers.Feature.Vector(bounds.toGeometry());
202
203   vectors.addFeatures(feature);
204   transform.setFeature(feature);
205 }
206
207 function validateControls() {
208   var bounds = new OpenLayers.Bounds($("#minlon").val(), $("#minlat").val(), $("#maxlon").val(), $("#maxlat").val());
209
210   if (bounds.getWidth() * bounds.getHeight() > OSM.MAX_REQUEST_AREA) {
211     $("#export_osm_too_large").show();
212   } else {
213     $("#export_osm_too_large").hide();
214   }
215
216   var max_scale = maxMapnikScale();
217   var disabled = true;
218
219   if ($("#format_osm").prop("checked")) {
220     disabled = bounds.getWidth() * bounds.getHeight() > OSM.MAX_REQUEST_AREA;
221   } else if ($("#format_mapnik").prop("checked")) {
222     disabled = $("#mapnik_scale").val() < max_scale;
223   }
224
225   $("#export_commit").prop("disabled", disabled);
226   $("#mapnik_max_scale").html(roundScale(max_scale));
227 }
228
229 function htmlUrlChanged() {
230   var bounds = new OpenLayers.Bounds($("#minlon").val(), $("#minlat").val(), $("#maxlon").val(), $("#maxlat").val());
231   var layerName = map.baseLayer.keyid;
232   var url = "http://" + OSM.SERVER_URL + "/export/embed.html?bbox=" + bounds.toBBOX() + "&amp;layer=" + layerName;
233   var markerUrl = "";
234
235   if ($("#marker_lat").val() && $("#marker_lon").val()) {
236     markerUrl = "&amp;mlat=" + $("#marker_lat").val() + "&amp;mlon=" + $("#marker_lon").val();
237     url += "&amp;marker=" + $("#marker_lat").val() + "," + $("#marker_lon").val();
238   }
239
240   var html = '<iframe width="425" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="'+url+'" style="border: 1px solid black"></iframe>';
241
242   // Create "larger map" link
243   var center = bounds.getCenterLonLat();
244   var epsg4326 = new OpenLayers.Projection("EPSG:4326");
245   var epsg900913 = new OpenLayers.Projection("EPSG:900913");
246
247   bounds.transform(epsg4326, epsg900913);
248   var zoom = map.getZoomForExtent(bounds);
249
250   var layers = getMapLayers();
251
252   var text = I18n.t('export.start_rjs.view_larger_map');
253   var escaped = [];
254
255   for (var i = 0; i < text.length; ++i) {
256     var c = text.charCodeAt(i);
257     escaped.push(c < 127 ? text.charAt(i) : "&#" + c + ";");
258   }
259
260   html += '<br /><small><a href="http://' + OSM.SERVER_URL + '/?lat='+center.lat+'&amp;lon='+center.lon+'&amp;zoom='+zoom+'&amp;layers='+layers+markerUrl+'">'+escaped.join("")+'</a></small>';
261
262   $("#export_html_text").val(html);
263
264   if ($("#format_html").prop("checked")) {
265     $("#export_html_text").prop("selected", true);
266   }
267 }
268
269 function formatChanged() {
270   $("#export_commit").show();
271
272   if ($("#format_osm").prop("checked")) {
273     $("#export_osm").show();
274   } else {
275     $("#export_osm").hide();
276   }
277
278   if ($("#format_mapnik").prop("checked")) {
279     $("#mapnik_scale").val(roundScale(map.getScale()));
280     $("#export_mapnik").show();
281   } else {
282     $("#export_mapnik").hide();
283   }
284
285   if ($("#format_html").prop("checked")) {
286     $("#export_html").show();
287     $("#export_commit").hide();
288     $("#export_html_text").prop("selected", true);
289   } else {
290     $("#export_html").hide();
291
292     clearMarker();
293   }
294
295   validateControls();
296 }
297
298 function maxMapnikScale() {
299   var bounds = new OpenLayers.Bounds($("#minlon").val(), $("#minlat").val(), $("#maxlon").val(), $("#maxlat").val());
300   var epsg4326 = new OpenLayers.Projection("EPSG:4326");
301   var epsg900913 = new OpenLayers.Projection("EPSG:900913");
302
303   bounds.transform(epsg4326, epsg900913);
304
305   return Math.floor(Math.sqrt(bounds.getWidth() * bounds.getHeight() / 0.3136));
306 }
307
308 function mapnikImageSize(scale) {
309   var bounds = new OpenLayers.Bounds($("#minlon").val(), $("#minlat").val(), $("#maxlon").val(), $("#maxlat").val());
310   var epsg4326 = new OpenLayers.Projection("EPSG:4326");
311   var epsg900913 = new OpenLayers.Projection("EPSG:900913");
312
313   bounds.transform(epsg4326, epsg900913);
314
315   return new OpenLayers.Size(Math.round(bounds.getWidth() / scale / 0.00028),
316                              Math.round(bounds.getHeight() / scale / 0.00028));
317 }
318
319 function roundScale(scale) {
320   var precision = 5 * Math.pow(10, Math.floor(Math.LOG10E * Math.log(scale)) - 2);
321
322   return precision * Math.ceil(scale / precision);
323 }
324
325 function mapnikSizeChanged() {
326   var size = mapnikImageSize($("#mapnik_scale").val());
327
328   $("#mapnik_image_width").html(size.w);
329   $("#mapnik_image_height").html(size.h);
330
331   validateControls();
332 }