1 page.replace_html :sidebar_title, t('browse.start_rjs.data_frame_title')
2 page.replace_html :sidebar_content, :partial => 'start'
6 var browseMode = "auto";
9 var browseActiveFeature;
11 var browseSelectControl;
14 OpenLayers.Feature.Vector.style['default'].strokeWidth = 3;
15 OpenLayers.Feature.Vector.style['default'].cursor = "pointer";
17 function startBrowse() {
20 openSidebar({ onclose: stopBrowse });
22 var vectors = new OpenLayers.Layer.Vector();
24 browseBoxControl = new OpenLayers.Control.DrawFeature(vectors, OpenLayers.Handler.RegularPolygon, {
30 callbacks: { done: endDrag }
33 map.addControl(browseBoxControl);
35 map.events.register("moveend", map, showData);
36 map.events.triggerEvent("moveend");
40 if (browseMode == "auto") {
41 if (map.getZoom() >= 15) {
44 setStatus("#{I18n.t('browse.start_rjs.zoom_or_select')}");
49 function stopBrowse() {
53 if (browseSelectControl) {
54 browseSelectControl.destroy();
55 browseSelectControl = null;
58 if (browseBoxControl) {
59 browseBoxControl.destroy();
60 browseBoxControl = null;
63 if (browseActiveFeature) {
64 browseActiveFeature.destroy();
65 browseActiveFeature = null;
68 if (browseDataLayer) {
69 browseDataLayer.destroy();
70 browseDataLayer = null;
73 map.dataLayer.setVisibility(false);
74 map.events.unregister("moveend", map, showData);
78 function startDrag() {
79 $("browse_select_box").innerHTML='#{I18n.t('browse.start_rjs.drag_a_box')}';
81 browseBoxControl.activate();
86 $("browse_select_box").onclick = startDrag;
89 var bounds = map.getExtent();
90 var projected = bounds.clone().transform(map.getProjectionObject(), epsg4326);
92 if (!browseBounds || !browseBounds.containsBounds(projected)) {
93 var center = bounds.getCenterLonLat();
94 var tileWidth = bounds.getWidth() * 1.2;
95 var tileHeight = bounds.getHeight() * 1.2;
96 var tileBounds = new OpenLayers.Bounds(center.lon - (tileWidth / 2),
97 center.lat - (tileHeight / 2),
98 center.lon + (tileWidth / 2),
99 center.lat + (tileHeight / 2));
101 browseBounds = tileBounds;
106 $("browse_select_view").style.display = "none";
112 $("browse_select_view").onclick = useMap;
114 function endDrag(bbox) {
115 var bounds = bbox.getBounds();
116 var projected = bounds.clone().transform(map.getProjectionObject(), epsg4326);
118 browseBoxControl.deactivate();
119 browseBounds = projected;
122 browseMode = "manual";
124 $("browse_select_box").innerHTML = "#{I18n.t('browse.start_rjs.manually_select')}";
125 $("browse_select_view").style.display = "inline";
128 function displayFeatureWarning() {
131 var div = document.createElement("div");
133 var p = document.createElement("p");
134 p.appendChild(document.createTextNode(i18n_js("#{I18n.t('browse.start_rjs.loaded_an_area_with_num_features', :num_features => '{{num_features}}')}", { num_features: browseFeatureList.length })));
137 var input = document.createElement("input");
138 input.type = "submit";
139 input.value = "#{I18n.t('browse.start_rjs.load_data')}";
140 input.onclick = loadFeatureList;
141 div.appendChild(input);
143 $("browse_content").innerHTML = "";
144 $("browse_content").appendChild(div);
147 function loadFeatureList() {
148 browseDataLayer.addFeatures(browseFeatureList);
149 browseDataLayer.events.triggerEvent("loadend");
151 browseFeatureList = [];
156 function customDataLoader(request) {
158 var doc = request.responseXML;
160 if (!doc || !doc.documentElement) {
161 doc = request.responseText;
166 OpenLayers.Util.extend(options, this.formatOptions);
168 if (this.map && !this.projection.equals(this.map.getProjectionObject())) {
169 options.externalProjection = this.projection;
170 options.internalProjection = this.map.getProjectionObject();
173 var gml = this.format ? new this.format(options) : new OpenLayers.Format.GML(options);
175 browseFeatureList = gml.read(doc);
177 if (!this.maxFeatures || browseFeatureList.length <= this.maxFeatures) {
180 displayFeatureWarning();
185 function getData(bounds) {
186 var projected = bounds.clone().transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326"));
187 var size = projected.getWidth() * projected.getHeight();
190 setStatus("#{I18n.t('browse.start_rjs.unable_to_load')} " + size + " #{I18n.t('browse.start_rjs.must_be_smaller')}");
192 loadGML("/api/#{API_VERSION}/map?bbox=" + projected.toBBOX());
196 function loadGML(url) {
197 setStatus("#{I18n.t('browse.start_rjs.loading')}");
198 $("browse_content").innerHTML = "";
200 if (!browseDataLayer) {
201 var style = new OpenLayers.Style();
203 style.addRules([new OpenLayers.Rule({
205 Polygon: { fillColor: '#ff0000', strokeColor: '#ff0000' },
206 Line: { fillColor: '#ffff00', strokeColor: '#000000', strokeOpacity: '0.4' },
207 Point: { fillColor: '#00ff00', strokeColor: '#00ff00' }
211 browseDataLayer = new OpenLayers.Layer.GML("Data", url, {
212 format: OpenLayers.Format.OSM,
215 interestingTagsExclude: ['source','source_ref','source:ref','history','attribution','created_by','tiger:county','tiger:tlid','tiger:upload_uuid']
218 requestSuccess: customDataLoader,
219 displayInLayerSwitcher: false,
220 styleMap: new OpenLayers.StyleMap({
222 'select': { strokeColor: '#0000ff', strokeWidth: 8 }
225 browseDataLayer.events.register("loadend", browseDataLayer, dataLoaded );
226 map.addLayer(browseDataLayer);
228 browseSelectControl = new OpenLayers.Control.SelectFeature(browseDataLayer, { onSelect: onFeatureSelect });
229 browseSelectControl.handlers.feature.stopDown = false;
230 browseSelectControl.handlers.feature.stopUp = false;
231 map.addControl(browseSelectControl);
232 browseSelectControl.activate();
234 browseDataLayer.setUrl(url);
237 browseActiveFeature = null;
240 function dataLoaded() {
244 browseObjectList = document.createElement("div")
246 var heading = document.createElement("p");
247 heading.className = "browse_heading";
248 heading.appendChild(document.createTextNode("#{I18n.t('browse.start_rjs.object_list.heading')}"));
249 browseObjectList.appendChild(heading);
251 var list = document.createElement("ul");
253 for (var i = 0; i < this.features.length; i++) {
254 var feature = this.features[i];
257 var type = featureType(feature);
258 var typeName = featureTypeName(feature);
259 var li = document.createElement("li");
260 li.appendChild(document.createTextNode(typeName + " "));
262 // Link, for viewing in the tab
263 var link = document.createElement("a");
264 link.href = "/browse/" + type + "/" + feature.osm_id;
265 var name = feature.attributes.name || feature.osm_id;
266 link.appendChild(document.createTextNode(name));
267 link.feature = feature;
268 link.onclick = OpenLayers.Function.bind(viewFeatureLink, link);
269 li.appendChild(link);
271 list.appendChild(li);
274 browseObjectList.appendChild(list)
276 var link = document.createElement("a");
277 link.href = this.url;
278 link.appendChild(document.createTextNode("#{I18n.t('browse.start_rjs.object_list.api')}"));
279 browseObjectList.appendChild(link);
281 $("browse_content").innerHTML = "";
282 $("browse_content").appendChild(browseObjectList);
286 function viewFeatureLink() {
287 var layer = this.feature.layer;
289 for (var i = 0; i < layer.selectedFeatures.length; i++) {
290 var f = layer.selectedFeatures[i];
291 layer.drawFeature(f, layer.styleMap.createSymbolizer(f, "default"));
294 onFeatureSelect(this.feature);
296 if (browseMode != "auto") {
297 map.setCenter(this.feature.geometry.getBounds().getCenterLonLat());
303 function loadObjectList() {
304 $("browse_content").innerHTML="";
305 $("browse_content").appendChild(browseObjectList);
310 function onFeatureSelect(feature) {
311 // Unselect previously selected feature
312 if (browseActiveFeature) {
313 browseActiveFeature.layer.drawFeature(
315 browseActiveFeature.layer.styleMap.createSymbolizer(browseActiveFeature, "default")
319 // Redraw in selected style
320 feature.layer.drawFeature(
321 feature, feature.layer.styleMap.createSymbolizer(feature, "select")
324 // If the current object is the list, don't innerHTML="", since that could clear it.
325 if ($("browse_content").firstChild == browseObjectList) {
326 $("browse_content").removeChild(browseObjectList);
328 $("browse_content").innerHTML = "";
331 // Create a link back to the object list
332 var div = document.createElement("div");
333 div.style.textAlign = "center";
334 div.style.marginBottom = "20px";
335 $("browse_content").appendChild(div);
336 var link = document.createElement("a");
338 link.onclick = loadObjectList;
339 link.appendChild(document.createTextNode("#{I18n.t('browse.start_rjs.object_list.back')}"));
340 div.appendChild(link);
342 var table = document.createElement("table");
343 table.width = "100%";
344 table.className = "browse_heading";
345 $("browse_content").appendChild(table);
347 var tr = document.createElement("tr");
348 table.appendChild(tr);
350 var heading = document.createElement("td");
351 heading.appendChild(document.createTextNode(featureNameSelect(feature)));
352 tr.appendChild(heading);
354 var td = document.createElement("td");
358 var type = featureType(feature);
359 var link = document.createElement("a");
360 link.href = "/browse/" + type + "/" + feature.osm_id;
361 link.appendChild(document.createTextNode("#{I18n.t('browse.start_rjs.object_list.details')}"));
362 td.appendChild(link);
364 var div = document.createElement("div");
365 div.className = "browse_details";
367 $("browse_content").appendChild(div);
369 // Now the list of attributes
370 var ul = document.createElement("ul");
371 for (var key in feature.attributes) {
372 var li = document.createElement("li");
373 var b = document.createElement("b");
374 b.appendChild(document.createTextNode(key));
376 li.appendChild(document.createTextNode(": " + feature.attributes[key]));
382 var link = document.createElement("a");
383 link.href = "/browse/" + type + "/" + feature.osm_id + "/history";
384 link.appendChild(document.createTextNode("#{I18n.t('browse.start_rjs.show_history')}"));
385 link.onclick = OpenLayers.Function.bind(loadHistory, {
386 type: type, feature: feature, link: link
389 div.appendChild(link);
391 // Stash the currently drawn feature
392 browseActiveFeature = feature;
395 function loadHistory() {
397 this.link.innerHTML = "#{I18n.t('browse.start_rjs.wait')}";
399 new Ajax.Request("/api/#{API_VERSION}/" + this.type + "/" + this.feature.osm_id + "/history", {
400 onComplete: OpenLayers.Function.bind(displayHistory, this)
406 function displayHistory(request) {
407 if (browseActiveFeature.osm_id != this.feature.osm_id || $("browse_content").firstChild == browseObjectList) {
411 this.link.parentNode.removeChild(this.link);
413 var doc = request.responseXML;
415 var table = document.createElement("table");
416 table.width = "100%";
417 table.className = "browse_heading";
418 $("browse_content").appendChild(table);
420 var tr = document.createElement("tr");
421 table.appendChild(tr);
423 var heading = document.createElement("td");
424 heading.appendChild(document.createTextNode("#{I18n.t('browse.start_rjs.history_for')} " + featureNameHistory(this.feature)));
425 tr.appendChild(heading);
427 var td = document.createElement("td");
431 var link = document.createElement("a");
432 link.href = "/browse/" + this.type + "/" + this.feature.osm_id + "/history";
433 link.appendChild(document.createTextNode("#{I18n.t('browse.start_rjs.details')}"));
434 td.appendChild(link);
436 var div = document.createElement("div");
437 div.className = "browse_details";
439 var nodes = doc.getElementsByTagName(this.type);
440 var history = document.createElement("ul");
441 for (var i = nodes.length - 1; i >= 0; i--) {
442 var user = nodes[i].getAttribute("user") || "#{I18n.t('browse.start_rjs.private_user')}";
443 var timestamp = nodes[i].getAttribute("timestamp");
444 var item = document.createElement("li");
445 item.appendChild(document.createTextNode("#{I18n.t('browse.start_rjs.edited_by')} " + user + " #{I18n.t('browse.start_rjs.at_timestamp')} " + timestamp));
446 history.appendChild(item);
448 div.appendChild(history);
450 $("browse_content").appendChild(div);
453 function featureType(feature) {
454 if (feature.geometry.CLASS_NAME == "OpenLayers.Geometry.Point") {
461 function featureTypeName(feature) {
462 if (featureType(feature) == "node") {
463 return "#{I18n.t('browse.start_rjs.object_list.type.node')}";
464 } else if (featureType(feature) == "way") {
465 return "#{I18n.t('browse.start_rjs.object_list.type.way')}";
469 function featureNameSelect(feature) {
470 if (feature.attributes.name) {
471 return feature.attributes.name;
472 } else if (featureType(feature) == "node") {
473 return "#{I18n.t('browse.start_rjs.object_list.selected.type.node')} " + feature.osm_id;
474 } else if (featureType(feature) == "way") {
475 return "#{I18n.t('browse.start_rjs.object_list.selected.type.way')} " + feature.osm_id;
479 function featureNameHistory(feature) {
480 if (feature.attributes.name) {
481 return feature.attributes.name;
482 } else if (featureType(feature) == "node") {
483 return "#{I18n.t('browse.start_rjs.object_list.history.type.node')} " + feature.osm_id;
484 } else if (featureType(feature) == "way") {
485 return "#{I18n.t('browse.start_rjs.object_list.history.type.way')} " + feature.osm_id;
490 This is a hack so that we can interpolate JavaScript variables in
491 translation strings from Ruby, doing the string replacement
492 client-side instead of on the server.
494 function i18n_js(string, keys) {
495 for (var key in keys) {
496 var re_key = '\{\{' + key + '\}\}';
497 var re = new RegExp(re_key, "g");
499 string = string.replace(re, keys[key]);
505 function setStatus(status) {
506 $("browse_status").innerHTML = status;
507 $("browse_status").style.display = "block";
510 function clearStatus() {
511 $("browse_status").innerHTML = "";
512 $("browse_status").style.display = "none";