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