From: Tom Hughes Date: Tue, 6 Aug 2013 08:05:59 +0000 (+0100) Subject: Merge remote-tracking branch 'osmlab/map-ui' X-Git-Tag: live~4870 X-Git-Url: https://git.openstreetmap.org/rails.git/commitdiff_plain/feeb135760abdbfef0eea193318566d9d96f2523?hp=d4135390acff291f2f2c15d9fb86723ebf4fe755 Merge remote-tracking branch 'osmlab/map-ui' --- diff --git a/app/assets/images/sprite.png b/app/assets/images/sprite.png index 9f857f852..108c38c87 100644 Binary files a/app/assets/images/sprite.png and b/app/assets/images/sprite.png differ diff --git a/app/assets/images/sprite.svg b/app/assets/images/sprite.svg index 2e1d309e4..dea2cccc1 100644 --- a/app/assets/images/sprite.svg +++ b/app/assets/images/sprite.svg @@ -13,7 +13,7 @@ height="200" id="svg2" version="1.1" - inkscape:version="0.48.2 r9819" + inkscape:version="0.48.4 r9939" inkscape:export-filename="/Users/tmcw/src/openstreetmap-website/app/assets/images/sprite.png" inkscape:export-xdpi="90" inkscape:export-ydpi="90" @@ -27,12 +27,12 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="5" - inkscape:cx="159.62972" - inkscape:cy="181.16738" + inkscape:zoom="1.4142136" + inkscape:cx="82.865988" + inkscape:cy="195.08379" inkscape:document-units="px" inkscape:current-layer="layer1" - showgrid="true" + showgrid="false" inkscape:window-width="1280" inkscape:window-height="756" inkscape:window-x="0" @@ -122,7 +122,7 @@ image/svg+xml - + @@ -145,7 +145,7 @@ id="layer1" transform="translate(0,-852.36218)"> + style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter6591-2);enable-background:accumulate" /> + style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter6591-2);enable-background:accumulate" /> @@ -214,7 +214,7 @@ inkscape:connector-curvature="0" id="path6924" d="m 170,853.3622 -1,1 0,1 -1,0 -1,1 0,2 7,0 0,-2 -1,-1 -1,0 0,-1 -1,-1 -1,0 z m -5,3 -1,1 0,11 1,1 11,0 1,-1 0,-11 -1,-1 -1,0 0,1 0,2 0,8 -9,0 0,-8 0,-2 0,-1 -1,0 z m 3,4 0,1 5,0 0,-1 -5,0 z m 0,2 0,1 5,0 0,-1 -5,0 z m 0,2 0,1 3,0 0,-1 -3,0 z" - style="color:#000000;fill:#222222;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> + style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> - + + + + + + diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index b257f7fed..225ddaf44 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -122,6 +122,19 @@ function cookieContent(map) { return [center.lng, center.lat, map.getZoom(), map.getLayersCode()].join('|'); } +function escapeHTML(string) { + var htmlEscapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' + }; + return string == null ? '' : (string + '').replace(/[&<>"']/g, function(match) { + return htmlEscapes[match]; + }); +} + /* * Forms which have been cached by rails may have the wrong * authenticity token, so patch up any forms with the correct diff --git a/app/assets/javascripts/browse.js b/app/assets/javascripts/browse.js index 023dc878d..5d2412183 100644 --- a/app/assets/javascripts/browse.js +++ b/app/assets/javascripts/browse.js @@ -57,8 +57,8 @@ $(document).ready(function () { object.version = params.version - 1; } - addObjectToMap(object, map, { - zoom: true, + map.addObject(object, { + zoom: true, callback: function(extent) { $("#loading").hide(); $("#browse_map .geolink").show(); diff --git a/app/assets/javascripts/embed.js.erb b/app/assets/javascripts/embed.js.erb index 57572ca48..50c294b41 100644 --- a/app/assets/javascripts/embed.js.erb +++ b/app/assets/javascripts/embed.js.erb @@ -5,12 +5,11 @@ window.onload = function () { var query = (window.location.search || '?').substr(1), args = {}; - query.replace(/([^&=]+)=?([^&]*)(?:&+|$)/g, function(match, key, value) { - value = value.split(","); - if (value.length == 1) - value = value[0]; - args[key] = value; - }); + var pairs = query.split('&'); + for (var i = 0; i < pairs.length; i++) { + var parts = pairs[i].split('='); + args[parts[0]] = decodeURIComponent(parts[1] || ''); + } var map = L.map("map"); map.attributionControl.setPrefix(''); @@ -26,7 +25,7 @@ window.onload = function () { } if (args.marker) { - L.marker(args.marker, {icon: L.icon({ + L.marker(args.marker.split(','), {icon: L.icon({ iconUrl: <%= asset_path('images/marker-icon.png').to_json %>, iconSize: new L.Point(25, 41), iconAnchor: new L.Point(12, 41), @@ -36,8 +35,9 @@ window.onload = function () { } if (args.bbox) { - map.fitBounds([L.latLng(args.bbox[1], args.bbox[0]), - L.latLng(args.bbox[3], args.bbox[2])]) + var bbox = args.bbox.split(','); + map.fitBounds([L.latLng(bbox[1], bbox[0]), + L.latLng(bbox[3], bbox[2])]) } else { map.fitWorld(); } diff --git a/app/assets/javascripts/index.js b/app/assets/javascripts/index.js index 15acc6412..bae80cac5 100644 --- a/app/assets/javascripts/index.js +++ b/app/assets/javascripts/index.js @@ -48,7 +48,12 @@ $(document).ready(function () { }) ]; - layers[0].addTo(map); + for (var i = layers.length - 1; i >= 0; i--) { + if (i === 0 || params.layers.indexOf(layers[i].options.code) >= 0) { + map.addLayer(layers[i]); + break; + } + } map.noteLayer = new L.LayerGroup(); map.noteLayer.options = {code: 'N'}; @@ -116,27 +121,12 @@ $(document).ready(function () { }).addTo(map); } - if (params.layers) { - var foundLayer = false; - for (var i = 0; i < layers.length; i++) { - if (params.layers.indexOf(layers[i].options.code) >= 0) { - map.addLayer(layers[i]); - foundLayer = true; - } else { - map.removeLayer(layers[i]); - } - } - if (!foundLayer) { - map.addLayer(layers[0]); - } - } - if (params.marker) { L.marker([params.mlat, params.mlon], {icon: getUserIcon()}).addTo(map.markerLayer); } if (params.object) { - addObjectToMap(params.object, map, { zoom: params.object_zoom }); + map.addObject(params.object, { zoom: params.object_zoom }); } $("body").on("click", "a.set_position", setPositionLink(map)); @@ -195,7 +185,7 @@ function setPositionLink(map) { } if (data.type && data.id) { - addObjectToMap(data, map, { zoom: false, style: { opacity: 0.2, fill: false } }); + map.addObject(data, { zoom: false, style: { opacity: 0.2, fill: false } }); } map.markerLayer.clearLayers(); diff --git a/app/assets/javascripts/index/export.js b/app/assets/javascripts/index/export.js index 47830f8be..aec35ed2b 100644 --- a/app/assets/javascripts/index/export.js +++ b/app/assets/javascripts/index/export.js @@ -1,61 +1,32 @@ function initializeExport(map) { - $("#exportanchor").click(function (e) { - $.ajax({ url: $(this).data('url'), success: function (sidebarHtml) { - startExport(sidebarHtml); - }}); - e.preventDefault(); - }); - if (window.location.pathname == "/export") { - $("#exportanchor").click(); + startExport(); } - function startExport(sidebarHtml) { - var marker; - + function startExport() { var locationFilter = new L.LocationFilter({ enableButton: false, adjustButton: false }).addTo(map); - locationFilter.on("change", filterChanged); + locationFilter.on("change", update); - map.on("moveend", mapMoved); - map.on("baselayerchange", htmlUrlChanged); + map.on("moveend", update); $("#sidebar_title").html(I18n.t('export.start_rjs.export')); - $("#sidebar_content").html(sidebarHtml); $("#maxlat,#minlon,#maxlon,#minlat").change(boundsChanged); $("#drag_box").click(enableFilter); - $("#add_marker").click(startMarker); - - $("#format_osm,#format_mapnik,#format_html").click(formatChanged); - - $("#mapnik_scale").change(mapnikSizeChanged); - openSidebar(); - if (map.getMapBaseLayerId() == "mapnik") { - $("#format_mapnik").prop("checked", true); - } - setBounds(map.getBounds()); - formatChanged(); - - $("body").removeClass("site-index").addClass("site-export"); $("#sidebar").one("closed", function () { - $("body").removeClass("site-export").addClass("site-index"); - map.removeLayer(locationFilter); - clearMarker(); - - map.off("moveend", mapMoved); - map.off("baselayerchange", htmlUrlChanged); - locationFilter.off("change", filterChanged); + map.off("moveend", update); + locationFilter.off("change", update); }); function getBounds() { @@ -63,22 +34,6 @@ function initializeExport(map) { L.latLng($("#maxlat").val(), $("#maxlon").val())); } - function getScale() { - var bounds = map.getBounds(), - centerLat = bounds.getCenter().lat, - halfWorldMeters = 6378137 * Math.PI * Math.cos(centerLat * Math.PI / 180), - meters = halfWorldMeters * (bounds.getEast() - bounds.getWest()) / 180, - pixelsPerMeter = map.getSize().x / meters, - metersPerPixel = 1 / (92 * 39.3701); - return Math.round(1 / (pixelsPerMeter * metersPerPixel)); - } - - function getMercatorBounds() { - var bounds = getBounds(); - return L.bounds(L.CRS.EPSG3857.project(bounds.getSouthWest()), - L.CRS.EPSG3857.project(bounds.getNorthEast())); - } - function boundsChanged() { var bounds = getBounds(); @@ -87,7 +42,6 @@ function initializeExport(map) { enableFilter(); validateControls(); - mapnikSizeChanged(); } function enableFilter() { @@ -99,186 +53,21 @@ function initializeExport(map) { locationFilter.enable(); } - function filterChanged() { - setBounds(locationFilter.getBounds()); + function update() { + setBounds(locationFilter.isEnabled() ? locationFilter.getBounds() : map.getBounds()); validateControls(); } - function startMarker() { - $("#add_marker").html(I18n.t('export.start_rjs.click_add_marker')); - - map.on("click", endMarker); - - return false; - } - - function endMarker(event) { - map.off("click", endMarker); - - $("#add_marker").html(I18n.t('export.start_rjs.change_marker')); - $("#marker_inputs").show(); - - var latlng = event.latlng; - - if (marker) { - map.removeLayer(marker); - } - - marker = L.marker(latlng).addTo(map); - - $("#marker_lon").val(latlng.lng.toFixed(5)); - $("#marker_lat").val(latlng.lat.toFixed(5)); - - htmlUrlChanged(); - } - - function clearMarker() { - $("#marker_lon,#marker_lat").val(""); - $("#marker_inputs").hide(); - $("#add_marker").html(I18n.t('export.start_rjs.add_marker')); - - if (marker) { - map.removeLayer(marker); - } - } - - function mapMoved() { - if (!locationFilter.isEnabled()) { - setBounds(map.getBounds()); - validateControls(); - } - } - function setBounds(bounds) { var precision = zoomPrecision(map.getZoom()); - $("#minlon").val(bounds.getWest().toFixed(precision)); $("#minlat").val(bounds.getSouth().toFixed(precision)); $("#maxlon").val(bounds.getEast().toFixed(precision)); $("#maxlat").val(bounds.getNorth().toFixed(precision)); - - mapnikSizeChanged(); - htmlUrlChanged(); } function validateControls() { - var bounds = getBounds(); - - var tooLarge = bounds.getSize() > OSM.MAX_REQUEST_AREA; - if (tooLarge) { - $("#export_osm_too_large").show(); - } else { - $("#export_osm_too_large").hide(); - } - - var max_scale = maxMapnikScale(); - var disabled = true; - - if ($("#format_osm").prop("checked")) { - disabled = tooLarge; - } else if ($("#format_mapnik").prop("checked")) { - disabled = $("#mapnik_scale").val() < max_scale; - } - - $("#export_commit").prop("disabled", disabled); - $("#mapnik_max_scale").html(roundScale(max_scale)); - } - - function htmlUrlChanged() { - var bounds = getBounds(); - var layerName = map.getMapBaseLayerId(); - - var url = "http://" + OSM.SERVER_URL + "/export/embed.html?bbox=" + bounds.toBBoxString() + "&layer=" + layerName; - var markerUrl = ""; - - if ($("#marker_lat").val() && $("#marker_lon").val()) { - markerUrl = "&mlat=" + $("#marker_lat").val() + "&mlon=" + $("#marker_lon").val(); - url += "&marker=" + $("#marker_lat").val() + "," + $("#marker_lon").val(); - } - - var html = ''; - - // Create "larger map" link - var center = bounds.getCenter(); - - var zoom = map.getBoundsZoom(bounds); - - var layers = map.getLayersCode(); - - var text = I18n.t('export.start_rjs.view_larger_map'); - var escaped = []; - - for (var i = 0; i < text.length; ++i) { - var c = text.charCodeAt(i); - escaped.push(c < 127 ? text.charAt(i) : "&#" + c + ";"); - } - - html += '
'+escaped.join("")+''; - - $("#export_html_text").val(html); - - if ($("#format_html").prop("checked")) { - $("#export_html_text").prop("selected", true); - } - } - - function formatChanged() { - $("#export_commit").show(); - - if ($("#format_osm").prop("checked")) { - $("#export_osm").show(); - } else { - $("#export_osm").hide(); - } - - if ($("#format_mapnik").prop("checked")) { - $("#mapnik_scale").val(getScale()); - $("#export_mapnik").show(); - - mapnikSizeChanged(); - } else { - $("#export_mapnik").hide(); - } - - if ($("#format_html").prop("checked")) { - $("#export_html").show(); - $("#export_commit").hide(); - $("#export_html_text").prop("selected", true); - } else { - $("#export_html").hide(); - - clearMarker(); - } - - validateControls(); - } - - function maxMapnikScale() { - var size = getMercatorBounds().getSize(); - - return Math.floor(Math.sqrt(size.x * size.y / 0.3136)); - } - - function mapnikImageSize(scale) { - var size = getMercatorBounds().getSize(); - - return {w: Math.round(size.x / scale / 0.00028), - h: Math.round(size.y / scale / 0.00028)}; - } - - function roundScale(scale) { - var precision = 5 * Math.pow(10, Math.floor(Math.LOG10E * Math.log(scale)) - 2); - - return precision * Math.ceil(scale / precision); - } - - function mapnikSizeChanged() { - var size = mapnikImageSize($("#mapnik_scale").val()); - - $("#mapnik_image_width").html(size.w); - $("#mapnik_image_height").html(size.h); - - validateControls(); + $("#export_osm_too_large").toggle(getBounds().getSize() > OSM.MAX_REQUEST_AREA); } } } diff --git a/app/assets/javascripts/index/notes.js.erb b/app/assets/javascripts/index/notes.js.erb index 93b60c3e7..63576c06c 100644 --- a/app/assets/javascripts/index/notes.js.erb +++ b/app/assets/javascripts/index/notes.js.erb @@ -190,7 +190,7 @@ function initializeNotes(map, params) { notes[feature.properties.id] = updateMarker(marker, feature); newNote = null; - addNoteButton.removeClass("disabled").addClass("geolink"); + addNoteButton.removeClass("active").addClass("geolink"); } } @@ -223,9 +223,9 @@ function initializeNotes(map, params) { e.preventDefault(); e.stopPropagation(); - if (addNoteButton.hasClass("disabled")) return; + if (addNoteButton.hasClass("active")) return; - addNoteButton.removeClass("geolink").addClass("disabled"); + addNoteButton.removeClass("geolink").addClass("active"); map.addLayer(noteLayer); @@ -262,7 +262,7 @@ function initializeNotes(map, params) { newNote.addTo(noteLayer).bindPopup(popupContent[0], popupOptions()).openPopup(); newNote.on("remove", function (e) { - addNoteButton.removeClass("disabled").addClass("geolink"); + addNoteButton.removeClass("active").addClass("geolink"); }).on("dragstart", function (e) { $(newNote).stopTime("removenote"); }).on("dragend", function (e) { diff --git a/app/assets/javascripts/leaflet.extend.js.erb b/app/assets/javascripts/leaflet.extend.js.erb index a50df013e..a645ed253 100644 --- a/app/assets/javascripts/leaflet.extend.js.erb +++ b/app/assets/javascripts/leaflet.extend.js.erb @@ -37,6 +37,10 @@ L.extend(L.Map.prototype, { params.mlon = marker.getLatLng().lng.toFixed(precision); } + if (this._object) { + params[this._object.type] = this._object.id; + } + var url = 'http://' + OSM.SERVER_URL + '/', query = querystring.stringify(params), hash = OSM.formatHash(this); @@ -50,7 +54,8 @@ L.extend(L.Map.prototype, { getShortUrl: function(marker) { var zoom = this.getZoom(), latLng = marker && this.hasLayer(marker) ? marker.getLatLng() : this.getCenter(), - str = '', + str = window.location.hostname.match(/^www\.openstreetmap\.org/i) ? + 'http://osm.org/go/' : 'http://' + window.location.hostname + '/go/', char_array = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_~", x = Math.round((latLng.lng + 180.0) * ((1 << 30) / 90.0)), y = Math.round((latLng.lat + 90.0) * ((1 << 30) / 45.0)), @@ -83,12 +88,63 @@ L.extend(L.Map.prototype, { return (x << 1) | y; } + var params = {}; + if (marker && this.hasLayer(marker)) { - str += '?m' + params.m = ''; + } + + if (this._object) { + params[this._object.type] = this._object.id; + } + + var query = querystring.stringify(params); + if (query) { + str += '?' + query; } - return (window.location.hostname.match(/^www\.openstreetmap\.org/i) ? - 'http://osm.org/go/' : 'http://' + window.location.hostname + '/go/') + str; + return str; + }, + + addObject: function(object, options) { + this._object = object; + + if (this._objectLoader) this._objectLoader.abort(); + if (this._objectLayer) this.removeLayer(this._objectLayer); + + var map = this; + this._objectLoader = $.ajax({ + url: OSM.apiUrl(object), + dataType: "xml", + success: function (xml) { + map._objectLayer = new L.OSM.DataLayer(null, { + styles: { + node: options.style, + way: options.style, + area: options.style + } + }); + + map._objectLayer.interestingNode = function (node, ways, relations) { + if (object.type === "node") { + return true; + } else if (object.type === "relation") { + for (var i = 0; i < relations.length; i++) + if (relations[i].members.indexOf(node) != -1) + return true; + } else { + return false; + } + }; + + map._objectLayer.addData(xml); + + if (options.zoom) map.fitBounds(map._objectLayer.getBounds()); + if (options.callback) options.callback(map._objectLayer.getBounds()); + + map._objectLayer.addTo(map); + } + }); } }); diff --git a/app/assets/javascripts/leaflet.key.js b/app/assets/javascripts/leaflet.key.js index c5124e39d..d88ce5d6e 100644 --- a/app/assets/javascripts/leaflet.key.js +++ b/app/assets/javascripts/leaflet.key.js @@ -5,7 +5,7 @@ L.OSM.key = function (options) { var $container = $('
') .attr('class', 'control-key'); - $('') + var button = $('') .attr('class', 'control-button') .attr('href', '#') .attr('title', I18n.t('javascripts.key.tooltip')) @@ -39,6 +39,10 @@ L.OSM.key = function (options) { .on('show', shown) .on('hide', hidden); + map.on('baselayerchange', updateButton); + + updateButton(); + function shown() { map.on('zoomend baselayerchange', update); $section.load('/key', update); @@ -51,7 +55,14 @@ L.OSM.key = function (options) { function toggle(e) { e.stopPropagation(); e.preventDefault(); - options.sidebar.togglePane($ui); + if (!button.hasClass('disabled')) { + options.sidebar.togglePane($ui, button); + } + } + + function updateButton() { + var layer = map.getMapBaseLayerId(); + button.toggleClass('disabled', layer !== 'mapnik'); } function update() { diff --git a/app/assets/javascripts/leaflet.layers.js b/app/assets/javascripts/leaflet.layers.js index edcbfbd4d..a364588c1 100644 --- a/app/assets/javascripts/leaflet.layers.js +++ b/app/assets/javascripts/leaflet.layers.js @@ -7,7 +7,7 @@ L.OSM.layers = function(options) { var $container = $('
') .attr('class', 'control-layers'); - var link = $('') + var button = $('') .attr('class', 'control-button') .attr('href', '#') .attr('title', 'Layers') @@ -156,7 +156,7 @@ L.OSM.layers = function(options) { function toggle(e) { e.stopPropagation(); e.preventDefault(); - options.sidebar.togglePane($ui); + options.sidebar.togglePane($ui, button); } return $container[0]; diff --git a/app/assets/javascripts/leaflet.share.js b/app/assets/javascripts/leaflet.share.js index bea877e66..441acfd74 100644 --- a/app/assets/javascripts/leaflet.share.js +++ b/app/assets/javascripts/leaflet.share.js @@ -1,11 +1,16 @@ L.OSM.share = function (options) { - var control = L.control(options); + var control = L.control(options), + marker = L.marker([0, 0], {draggable: true}), + locationFilter = new L.LocationFilter({ + enableButton: false, + adjustButton: false + }); control.onAdd = function (map) { var $container = $('
') .attr('class', 'control-share'); - $('') + var button = $('') .attr('class', 'control-button') .attr('href', '#') .attr('title', 'Share') @@ -29,6 +34,8 @@ L.OSM.share = function (options) { $('

') .text(I18n.t('javascripts.share.title'))); + // Link / Embed + var $linkSection = $('
') .attr('class', 'section share-link') .appendTo($ui); @@ -37,37 +44,311 @@ L.OSM.share = function (options) { .text(I18n.t('javascripts.share.link')) .appendTo($linkSection); - var $shortLink, $longLink; + var $form = $('
') + .attr('class', 'standard-form') + .appendTo($linkSection); + + $('
') + .attr('class', 'form-row') + .appendTo($form) + .append( + $('
') + .attr('class', 'share-tabs') + .appendTo($form) + .append($('') + .attr('class', 'active') + .attr('for', 'long_input') + .attr('id', 'long_link') + .text(I18n.t('javascripts.share.long_link'))) + .append($('') + .attr('for', 'short_input') + .attr('id', 'short_link') + .text(I18n.t('javascripts.share.short_link'))) + .append($('') + .attr('for', 'embed_html') + .attr('href', '#') + .text(I18n.t('javascripts.share.embed'))) + .on('click', 'a', function(e) { + e.preventDefault(); + var id = '#' + $(this).attr('for'); + $linkSection.find('.share-tabs a') + .removeClass('active'); + $(this).addClass('active'); + $linkSection.find('.share-tab') + .hide(); + $linkSection.find('.share-tab:has(' + id + ')') + .show() + .find('input, textarea') + .select(); + }); + + $('
') + .attr('class', 'form-row share-tab') + .css('display', 'block') + .appendTo($form) + .append($('') + .attr('id', 'long_input') + .attr('type', 'text') + .on('click', select)); + + $('
') + .attr('class', 'form-row share-tab') + .appendTo($form) + .append($('') + .attr('id', 'short_input') + .attr('type', 'text') + .on('click', select)); - $('