X-Git-Url: https://git.openstreetmap.org./rails.git/blobdiff_plain/ca0989f90fcc14832a54fe129dfdedd907850304..de18f26d3c3449d3a56b0941a3a39b40fffd3947:/app/views/browse/start.rjs diff --git a/app/views/browse/start.rjs b/app/views/browse/start.rjs index 80a691b4e..4df614847 100644 --- a/app/views/browse/start.rjs +++ b/app/views/browse/start.rjs @@ -1,359 +1,516 @@ -page.replace_html :sidebar_title, 'Data' +page.replace_html :sidebar_title, t('browse.start_rjs.data_frame_title') page.replace_html :sidebar_content, :partial => 'start' page << <= 15) { - useMap(); - } else { - $("status").innerHTML = "Zoom in or Select an area of the map to view."; - } - } - - function stopBrowse() { - if (browsing) { - browsing = false; - map.dataLayer.stopBrowse = null; - if (gml) { - gml.destroy(); - gml = null; - } - if (sf) { - sf.destroy(); - sf = null; - } - if (box) { - box.destroy(); - box = null; - } - if (currentFeature) { - currentFeature.destroy(); - currentFeature = null; - } - map.dataLayer.setVisibility(false); - map.events.unregister("moveend", map, showData); - } - } - - function startDrag() { - $("drag_box").innerHTML='Drag a box on the map to select an area'; - box.activate(); - return false; - }; - $("drag_box").onclick = startDrag; - - function useMap() { - var bounds = map.getExtent(); - var projected = bounds.clone().transform(map.getProjectionObject(), epsg4326); - if (!currentBounds || !currentBounds.containsBounds(projected)) { - var center = bounds.getCenterLonLat(); - var tileWidth = bounds.getWidth() * 1.2; - var tileHeight = bounds.getHeight() * 1.2; - var tileBounds = - new OpenLayers.Bounds(center.lon - (tileWidth / 2), - center.lat - (tileHeight / 2), - center.lon + (tileWidth / 2), - center.lat + (tileHeight / 2)); - - currentBounds = tileBounds; - getData(tileBounds); - mode = "auto"; - $("use_map").style.display="none"; - } - return false; - } - $("use_map").onclick = useMap; + OpenLayers.Feature.Vector.style['default'].strokeWidth = 3; + OpenLayers.Feature.Vector.style['default'].cursor = "pointer"; - function endDrag(bbox) { - var bounds = bbox.getBounds(); - box.deactivate(); - currentBounds = bounds; - getData(bounds); - $("drag_box").innerHTML = "Manually select a different area"; - mode = "manual"; - $("use_map").style.display="inline"; - } + function startBrowse() { + browseActive = true; + + openSidebar({ onclose: stopBrowse }); + + var vectors = new OpenLayers.Layer.Vector(); - function displayFeatureWarning() { - $("status").innerHTML = ""; - var div = document.createElement("div"); - var p = document.createElement("p"); - p.appendChild(document.createTextNode("You have loaded an area which contains " + featureList.length + " features. In general, some browsers may not cope well with displaying this quantity of data. Generally, browsers work best at displaying less than 100 features at a time: doing anything else may make your browser slow/unresponsive. If you are sure you want to display this data, you may do so by clicking the button below.")); - div.appendChild(p); - var input = document.createElement("input"); - input.type = "submit"; - input.value = "Load Data"; - input.onclick = loadFeatureList; - div.appendChild(input); - $("object").innerHTML=""; - $("object").appendChild(div); + browseBoxControl = new OpenLayers.Control.DrawFeature(vectors, OpenLayers.Handler.RegularPolygon, { + handlerOptions: { + sides: 4, + snapAngle: 90, + irregular: true, + persist: true, + callbacks: { done: endDrag } + } + }); + map.addControl(browseBoxControl); + + map.events.register("moveend", map, showData); + map.events.triggerEvent("moveend"); + } + + function showData() { + if (browseMode == "auto") { + if (map.getZoom() >= 15) { + useMap(); + } else { + setStatus("#{I18n.t('browse.start_rjs.zoom_or_select')}"); + } } - - function loadFeatureList() { - gml.addFeatures(featureList); - gml.events.triggerEvent("loadend"); - return false; + } + + function stopBrowse() { + if (browseActive) { + browseActive = false; + + if (browseSelectControl) { + browseSelectControl.destroy(); + browseSelectControl = null; + } + + if (browseBoxControl) { + browseBoxControl.destroy(); + browseBoxControl = null; + } + + if (browseActiveFeature) { + browseActiveFeature.destroy(); + browseActiveFeature = null; + } + + if (browseDataLayer) { + browseDataLayer.destroy(); + browseDataLayer = null; + } + + map.dataLayer.setVisibility(false); + map.events.unregister("moveend", map, showData); } + } - function customDataLoader(request) { - if (!browsing) { return; } - var doc = request.responseXML; - - if (!doc || !doc.documentElement) { - doc = request.responseText; - } - - var options = {}; - - OpenLayers.Util.extend(options, this.formatOptions); - if (this.map && !this.projection.equals(this.map.getProjectionObject())) { - options.externalProjection = this.projection; - options.internalProjection = this.map.getProjectionObject(); - } - - var gml = this.format ? new this.format(options) : new OpenLayers.Format.GML(options); - var features = gml.read(doc); - if (!this.maxFeatures || features.length <= this.maxFeatures) { - this.addFeatures(features); - this.events.triggerEvent("loadend"); - featureList = []; - } else { - featureList = features; - displayFeatureWarning(); - } + function startDrag() { + $("browse_select_box").innerHTML='#{I18n.t('browse.start_rjs.drag_a_box')}'; + + browseBoxControl.activate(); + + return false; + }; + + $("browse_select_box").onclick = startDrag; + + function useMap() { + var bounds = map.getExtent(); + var projected = bounds.clone().transform(map.getProjectionObject(), epsg4326); + + if (!browseBounds || !browseBounds.containsBounds(projected)) { + var center = bounds.getCenterLonLat(); + var tileWidth = bounds.getWidth() * 1.2; + var tileHeight = bounds.getHeight() * 1.2; + var tileBounds = new OpenLayers.Bounds(center.lon - (tileWidth / 2), + center.lat - (tileHeight / 2), + center.lon + (tileWidth / 2), + center.lat + (tileHeight / 2)); + + browseBounds = tileBounds; + getData(tileBounds); + + browseMode = "auto"; + + $("browse_select_view").style.display = "none"; } - function getData(bounds) { - - bounds.transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326")); - var size = bounds.getWidth() * bounds.getHeight(); - if (size > 0.25) { - $("status").innerHTML = "Unable to load: Bounding box size of " + size + " is too large. (Must be smaller than 0.25)
"; - return; - } + return false; + } - var url = "/api/0.5/map?bbox="+bounds.toBBOX(); - - loadGML(url); + $("browse_select_view").onclick = useMap; + + function endDrag(bbox) { + var bounds = bbox.getBounds(); + var projected = bounds.clone().transform(map.getProjectionObject(), epsg4326); + + browseBoxControl.deactivate(); + browseBounds = projected; + getData(bounds); + + browseMode = "manual"; + + $("browse_select_box").innerHTML = "#{I18n.t('browse.start_rjs.manually_select')}"; + $("browse_select_view").style.display = "inline"; + } + + function displayFeatureWarning() { + clearStatus(); + + var div = document.createElement("div"); + + var p = document.createElement("p"); + 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 }))); + div.appendChild(p); + + var input = document.createElement("input"); + input.type = "submit"; + input.value = "#{I18n.t('browse.start_rjs.load_data')}"; + input.onclick = loadFeatureList; + div.appendChild(input); + + $("browse_content").innerHTML = ""; + $("browse_content").appendChild(div); + } + + function loadFeatureList() { + browseDataLayer.addFeatures(browseFeatureList); + browseDataLayer.events.triggerEvent("loadend"); + + browseFeatureList = []; + + return false; + } + + function customDataLoader(request) { + if (browseActive) { + var doc = request.responseXML; + + if (!doc || !doc.documentElement) { + doc = request.responseText; + } + + var options = {}; + + OpenLayers.Util.extend(options, this.formatOptions); + + if (this.map && !this.projection.equals(this.map.getProjectionObject())) { + options.externalProjection = this.projection; + options.internalProjection = this.map.getProjectionObject(); + } + + var gml = this.format ? new this.format(options) : new OpenLayers.Format.GML(options); + + browseFeatureList = gml.read(doc); + + if (!this.maxFeatures || browseFeatureList.length <= this.maxFeatures) { + loadFeatureList(); + } else { + displayFeatureWarning(); + } } - function loadGML(url) { - $("status").innerHTML = "Loading..."; - $("object").innerHTML = ""; - if (!gml) { - var style = new OpenLayers.Style(); - style.addRules([new OpenLayers.Rule( - {'symbolizer': - {"Polygon": {'fillColor': '#ff0000', 'strokeColor': '#ff0000'}, - "Line": {'fillColor': '#ffff00', 'strokeColor': '#000000', strokeOpacity: '0.4'}, - "Point": {'fillColor': '#00ff00', 'strokeColor': '#00ff00'}} - } - )]); - gml = new OpenLayers.Layer.GML("Data",url, - {format: OpenLayers.Format.OSM, formatOptions: {checkTags: true}, - maxFeatures: 100, requestSuccess: customDataLoader, - displayInLayerSwitcher: false, - styleMap: new OpenLayers.StyleMap({'default': style, 'select': {'strokeColor': '#0000ff', strokeWidth: 8}}) - } - ); - gml.events.register("loadend", gml, dataLoaded ); - map.addLayer(gml); - - sf = new OpenLayers.Control.SelectFeature(gml, {'onSelect': onFeatureSelect}); - sf.handler.stopDown = false; - sf.handler.stopUp = false; - map.addControl(sf); - sf.activate(); - - } else { - gml.setUrl(url); + } + + function getData(bounds) { + var projected = bounds.clone().transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326")); + var size = projected.getWidth() * projected.getHeight(); + + if (size > #{APP_CONFIG['max_request_area']}) { + setStatus(i18n_js("#{I18n.t('browse.start_rjs.unable_to_load_size', :bbox_size => '{{bbox_size}}', :max_bbox_size => APP_CONFIG['max_request_area'])}", { bbox_size: size })); + } else { + loadGML("/api/#{API_VERSION}/map?bbox=" + projected.toBBOX()); + } + } + + function loadGML(url) { + setStatus("#{I18n.t('browse.start_rjs.loading')}"); + $("browse_content").innerHTML = ""; + + if (!browseDataLayer) { + var style = new OpenLayers.Style(); + + style.addRules([new OpenLayers.Rule({ + symbolizer: { + Polygon: { fillColor: '#ff0000', strokeColor: '#ff0000' }, + Line: { fillColor: '#ffff00', strokeColor: '#000000', strokeOpacity: '0.4' }, + Point: { fillColor: '#00ff00', strokeColor: '#00ff00' } } + })]); - currentFeature = null; + browseDataLayer = new OpenLayers.Layer.GML("Data", url, { + format: OpenLayers.Format.OSM, + formatOptions: { + checkTags: true, + interestingTagsExclude: ['source','source_ref','source:ref','history','attribution','created_by','tiger:county','tiger:tlid','tiger:upload_uuid'] + }, + maxFeatures: 100, + requestSuccess: customDataLoader, + displayInLayerSwitcher: false, + styleMap: new OpenLayers.StyleMap({ + 'default': style, + 'select': { strokeColor: '#0000ff', strokeWidth: 8 } + }) + }); + browseDataLayer.events.register("loadend", browseDataLayer, dataLoaded ); + map.addLayer(browseDataLayer); + + browseSelectControl = new OpenLayers.Control.SelectFeature(browseDataLayer, { onSelect: onFeatureSelect }); + browseSelectControl.handlers.feature.stopDown = false; + browseSelectControl.handlers.feature.stopUp = false; + map.addControl(browseSelectControl); + browseSelectControl.activate(); + } else { + browseDataLayer.setUrl(url); } - function dataLoaded() { - if (!browsing) { return; } - $("status").innerHTML = "Loaded." + + browseActiveFeature = null; + } + + function dataLoaded() { + if (browseActive) { + clearStatus(); - objList = document.createElement("div") + browseObjectList = document.createElement("div") + + var heading = document.createElement("p"); + heading.className = "browse_heading"; + heading.appendChild(document.createTextNode("#{I18n.t('browse.start_rjs.object_list.heading')}")); + browseObjectList.appendChild(heading); + + var list = document.createElement("ul"); - list = document.createElement("ul"); - for (var i = 0; i < this.features.length; i++) { - var feature = this.features[i]; + for (var i = 0; i < this.features.length; i++) { + var feature = this.features[i]; - // Type, for linking - var type ="way"; - if (feature.geometry.CLASS_NAME == "OpenLayers.Geometry.Point") { - type = "node"; - } - var nice_name = type.substr(0,1).toUpperCase() + type.substr(1,type.length); - var li = document.createElement("li"); - li.appendChild(document.createTextNode(nice_name + " ")); + // Type, for linking + var type = featureType(feature); + var typeName = featureTypeName(feature); + var li = document.createElement("li"); + li.appendChild(document.createTextNode(typeName + " ")); - // Link, for viewing in the tab - var link = document.createElement("a"); - link.href = "/browse/" + type + "/" + feature.osm_id; - var name = feature.attributes.name || feature.osm_id; - link.appendChild(document.createTextNode(name)); - link.feature = feature; - link.onclick = OpenLayers.Function.bind(viewFeatureLink, link); - li.appendChild(link); - - list.appendChild(li); - } - objList.appendChild(list) + // Link, for viewing in the tab var link = document.createElement("a"); - link.href = this.url; - link.appendChild(document.createTextNode("API")); - objList.appendChild(link) - $("object").innerHTML = ""; - $("object").appendChild(objList); + link.href = "/browse/" + type + "/" + feature.osm_id; + var name = feature.attributes.name || feature.osm_id; + link.appendChild(document.createTextNode(name)); + link.feature = feature; + link.onclick = OpenLayers.Function.bind(viewFeatureLink, link); + li.appendChild(link); + + list.appendChild(li); + } + + browseObjectList.appendChild(list) + + var link = document.createElement("a"); + link.href = this.url; + link.appendChild(document.createTextNode("#{I18n.t('browse.start_rjs.object_list.api')}")); + browseObjectList.appendChild(link); + $("browse_content").innerHTML = ""; + $("browse_content").appendChild(browseObjectList); } + } - function viewFeatureLink() { - var layer = this.feature.layer; - for (var i = 0; i < layer.selectedFeatures.length; i++) { - var f = layer.selectedFeatures[i]; - layer.drawFeature(f, layer.styleMap.createSymbolizer(f, "default")); - } - onFeatureSelect(this.feature); - if (mode != "auto") { - map.setCenter(this.feature.geometry.getBounds().getCenterLonLat()); - } - return false; + function viewFeatureLink() { + var layer = this.feature.layer; + + for (var i = 0; i < layer.selectedFeatures.length; i++) { + var f = layer.selectedFeatures[i]; + layer.drawFeature(f, layer.styleMap.createSymbolizer(f, "default")); } - - function loadObjList() { - $("object").innerHTML=""; - $("object").appendChild(objList); - return false; + + onFeatureSelect(this.feature); + + if (browseMode != "auto") { + map.setCenter(this.feature.geometry.getBounds().getCenterLonLat()); } + + return false; + } + + function loadObjectList() { + $("browse_content").innerHTML=""; + $("browse_content").appendChild(browseObjectList); + + return false; + } - function onFeatureSelect(feature) { - // Unselect previously selected feature - if (currentFeature) { - currentFeature.layer.drawFeature( - currentFeature, currentFeature.layer.styleMap.createSymbolizer(currentFeature, "default") - ); - } + function onFeatureSelect(feature) { + // Unselect previously selected feature + if (browseActiveFeature) { + browseActiveFeature.layer.drawFeature( + browseActiveFeature, + browseActiveFeature.layer.styleMap.createSymbolizer(browseActiveFeature, "default") + ); + } - // Redraw in selected style - feature.layer.drawFeature( - feature, feature.layer.styleMap.createSymbolizer(feature, "select") - ); - - // If the current object is the list, don't innerHTML="", since that could clar it. - if ($("object").firstChild == objList) { - $("object").removeChild(objList); - } else { - $("object").innerHTML = ""; - } - - // Create a link back to the object list - var div = document.createElement("div"); - var link = document.createElement("a"); - link.href="#"; - link.onclick = loadObjList; - link.appendChild(document.createTextNode("Back to Object List")); - div.appendChild(link) - $("object").appendChild(div); - - var type = "way"; - if (feature.geometry.CLASS_NAME == "OpenLayers.Geometry.Point") { - type = "node"; - } - - var link = document.createElement("a"); - link.href = "/browse/"+type+"/"+feature.osm_id; - link.appendChild(document.createTextNode("Database entry for " + feature.osm_id)); + // Redraw in selected style + feature.layer.drawFeature( + feature, feature.layer.styleMap.createSymbolizer(feature, "select") + ); + + // If the current object is the list, don't innerHTML="", since that could clear it. + if ($("browse_content").firstChild == browseObjectList) { + $("browse_content").removeChild(browseObjectList); + } else { + $("browse_content").innerHTML = ""; + } - var div = document.createElement("div"); - div.style.marginTop = "20px" - div.appendChild(link); - - $("object").appendChild(div); - - // Now the list of attributes - var ul = document.createElement("ul"); - for (var key in feature.attributes) { - var li = document.createElement("li"); - var b = document.createElement("b"); - b.appendChild(document.createTextNode(key)); - li.appendChild(b); - li.appendChild(document.createTextNode(": " + feature.attributes[key])); - ul.appendChild(li); - } + // Create a link back to the object list + var div = document.createElement("div"); + div.style.textAlign = "center"; + div.style.marginBottom = "20px"; + $("browse_content").appendChild(div); + var link = document.createElement("a"); + link.href = "#"; + link.onclick = loadObjectList; + link.appendChild(document.createTextNode("#{I18n.t('browse.start_rjs.object_list.back')}")); + div.appendChild(link); + + var table = document.createElement("table"); + table.width = "100%"; + table.className = "browse_heading"; + $("browse_content").appendChild(table); + + var tr = document.createElement("tr"); + table.appendChild(tr); + + var heading = document.createElement("td"); + heading.appendChild(document.createTextNode(featureNameSelect(feature))); + tr.appendChild(heading); + + var td = document.createElement("td"); + td.align = "right"; + tr.appendChild(td); + + var type = featureType(feature); + var link = document.createElement("a"); + link.href = "/browse/" + type + "/" + feature.osm_id; + link.appendChild(document.createTextNode("#{I18n.t('browse.start_rjs.object_list.details')}")); + td.appendChild(link); + + var div = document.createElement("div"); + div.className = "browse_details"; + + $("browse_content").appendChild(div); + + // Now the list of attributes + var ul = document.createElement("ul"); + for (var key in feature.attributes) { + var li = document.createElement("li"); + var b = document.createElement("b"); + b.appendChild(document.createTextNode(key)); + li.appendChild(b); + li.appendChild(document.createTextNode(": " + feature.attributes[key])); + ul.appendChild(li); + } - $("object").appendChild(ul); + div.appendChild(ul); - var link = document.createElement("a"); - link.href = "/browse/"+type+"/"+feature.osm_id+"/history"; - link.appendChild(document.createTextNode("History")); - ul.appendChild(li); - link.onclick = OpenLayers.Function.bind(loadHistory, {type: type, feature: feature, link: link}); + var link = document.createElement("a"); + link.href = "/browse/" + type + "/" + feature.osm_id + "/history"; + link.appendChild(document.createTextNode("#{I18n.t('browse.start_rjs.show_history')}")); + link.onclick = OpenLayers.Function.bind(loadHistory, { + type: type, feature: feature, link: link + }); - $("object").appendChild(link); + div.appendChild(link); - // Stash the currently drawn feature - currentFeature = feature; - } - function loadHistory() { - this.link.href = ""; - this.link.innerHTML = "Wait..."; - new Ajax.Request("/api/0.5/"+this.type+"/"+this.feature.osm_id+"/history", {onComplete: OpenLayers.Function.bind(displayHistory, this)}); + // Stash the currently drawn feature + browseActiveFeature = feature; + } + + function loadHistory() { + this.link.href = ""; + this.link.innerHTML = "#{I18n.t('browse.start_rjs.wait')}"; + + new Ajax.Request("/api/#{API_VERSION}/" + this.type + "/" + this.feature.osm_id + "/history", { + onComplete: OpenLayers.Function.bind(displayHistory, this) + }); + + return false; + } + + function displayHistory(request) { + if (browseActiveFeature.osm_id != this.feature.osm_id || $("browse_content").firstChild == browseObjectList) { return false; + } + + this.link.parentNode.removeChild(this.link); + + var doc = request.responseXML; + + var table = document.createElement("table"); + table.width = "100%"; + table.className = "browse_heading"; + $("browse_content").appendChild(table); + + var tr = document.createElement("tr"); + table.appendChild(tr); + + var heading = document.createElement("td"); + heading.appendChild(document.createTextNode("#{I18n.t('browse.start_rjs.history_for')} " + featureNameHistory(this.feature))); + tr.appendChild(heading); + + var td = document.createElement("td"); + td.align = "right"; + tr.appendChild(td); + + var link = document.createElement("a"); + link.href = "/browse/" + this.type + "/" + this.feature.osm_id + "/history"; + link.appendChild(document.createTextNode("#{I18n.t('browse.start_rjs.details')}")); + td.appendChild(link); + + var div = document.createElement("div"); + div.className = "browse_details"; + + var nodes = doc.getElementsByTagName(this.type); + var history = document.createElement("ul"); + for (var i = nodes.length - 1; i >= 0; i--) { + var user = nodes[i].getAttribute("user") || "#{I18n.t('browse.start_rjs.private_user')}"; + var timestamp = nodes[i].getAttribute("timestamp"); + var item = document.createElement("li"); + item.appendChild(document.createTextNode("#{I18n.t('browse.start_rjs.edited_by')} " + user + " #{I18n.t('browse.start_rjs.at_timestamp')} " + timestamp)); + history.appendChild(item); } - function displayHistory(request) { - if (currentFeature.osm_id != this.feature.osm_id || $("object").firstChild == objList) { - return false; - } - this.link.parentNode.removeChild(this.link); - var doc = request.responseXML; - var div = document.createElement("div"); - var h3 = document.createElement("h3"); - h3.appendChild(document.createTextNode("History")); - div.appendChild(h3); - var nodes = doc.getElementsByTagName(this.type); - var history = document.createElement("ul"); - for (var i = nodes.length - 1; i >= 0; i--) { - var user = nodes[i].getAttribute("user") || "private user"; - var timestamp = nodes[i].getAttribute("timestamp"); - var item = document.createElement("li"); - item.appendChild(document.createTextNode("Edited by " + user + " at " + timestamp)); - history.appendChild(item); - } - div.appendChild(history); - var link = document.createElement("a"); - link.appendChild(document.createTextNode("History entry for " + this.feature.osm_id)); - link.href = "/browse/"+this.type+"/"+this.feature.osm_id+"/history"; - div.appendChild(link); - $("object").appendChild(div); + div.appendChild(history); + + $("browse_content").appendChild(div); + } + + function featureType(feature) { + if (feature.geometry.CLASS_NAME == "OpenLayers.Geometry.Point") { + return "node"; + } else { + return "way"; } - - start(); + } + + function featureTypeName(feature) { + if (featureType(feature) == "node") { + return "#{I18n.t('browse.start_rjs.object_list.type.node')}"; + } else if (featureType(feature) == "way") { + return "#{I18n.t('browse.start_rjs.object_list.type.way')}"; + } + } + + function featureNameSelect(feature) { + if (feature.attributes.name) { + return feature.attributes.name; + } else if (featureType(feature) == "node") { + return "#{I18n.t('browse.start_rjs.object_list.selected.type.node')} " + feature.osm_id; + } else if (featureType(feature) == "way") { + return "#{I18n.t('browse.start_rjs.object_list.selected.type.way')} " + feature.osm_id; + } + } + + function featureNameHistory(feature) { + if (feature.attributes.name) { + return feature.attributes.name; + } else if (featureType(feature) == "node") { + return "#{I18n.t('browse.start_rjs.object_list.history.type.node')} " + feature.osm_id; + } else if (featureType(feature) == "way") { + return "#{I18n.t('browse.start_rjs.object_list.history.type.way')} " + feature.osm_id; + } + } + + /* + This is a hack so that we can interpolate JavaScript variables in + translation strings from Ruby, doing the string replacement + client-side instead of on the server. + */ + function i18n_js(string, keys) { + for (var key in keys) { + var re_key = '\{\{' + key + '\}\}'; + var re = new RegExp(re_key, "g"); + + string = string.replace(re, keys[key]); + } + + return string; + } + + function setStatus(status) { + $("browse_status").innerHTML = status; + $("browse_status").style.display = "block"; + } + + function clearStatus() { + $("browse_status").innerHTML = ""; + $("browse_status").style.display = "none"; + } + + startBrowse(); EOJ