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