From 7a347d832f08ec9e9214ced7ad7a329d8b44af60 Mon Sep 17 00:00:00 2001 From: Saman Bemel-Benrud Date: Tue, 15 Jan 2013 16:54:50 -0500 Subject: [PATCH 01/39] lets see if I can put this site on a grid. --- css/app.css | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/css/app.css b/css/app.css index 4aba98318..fb6a894a3 100644 --- a/css/app.css +++ b/css/app.css @@ -121,6 +121,36 @@ table.tags, table.tags td, table.tags th { padding: 4px; } +/* Grid +------------------------------------------------------- */ + +.col0 { float:left; width:04.1666%; } +.col1 { float:left; width:08.3333%; } +.col2 { float:left; width:16.6666%; } +.col3 { float:left; width:25.0000%; } +.col4 { float:left; width:33.3333%; } +.col5 { float:left; width:41.6666%; } +.col6 { float:left; width:50.0000%; } +.col7 { float:left; width:58.3333%; } +.col8 { float:left; width:66.6666%; } +.col9 { float:left; width:75.0000%; } +.col10 { float:left; width:83.3333%; } +.col11 { float:left; width:91.6666%; } +.col12 { float:left; width:100.0000%; } +.margin0 { margin-left: 04.1666%; } +.margin1 { margin-left: 08.3333%; } +.margin2 { margin-left: 16.6666%; } +.margin3 { margin-left: 25.0000%; } +.margin4 { margin-left: 33.3333%; } +.margin5 { margin-left: 41.6666%; } +.margin6 { margin-left: 50.0000%; } +.margin7 { margin-left: 58.3333%; } +.margin8 { margin-left: 66.6666%; } +.margin9 { margin-left: 75.0000%; } +.margin10 { margin-left: 83.3333%; } +.margin11 { margin-left: 91.6666%; } +.margin12 { margin-left: 100.0000%; } + /* UI Lists ------------------------------------------------------- */ @@ -280,10 +310,10 @@ button.centered { } button.action { - background-color: #7092ff; + background: #444; } button.action:hover { - background-color: #6282ee; + background: #222; } button.delete { @@ -294,10 +324,8 @@ button.delete:hover { } button.save { - background-color: #6bc641; min-width: 120px; width: auto; - position: relative; } button.save.has-count { @@ -310,7 +338,7 @@ button.save .count { button.save.has-count .count { display: block; - color: #6bc641; + color: #444; background: #fff; border-radius: 0 3px 3px 0; padding: 9px; @@ -320,10 +348,6 @@ button.save.has-count .count { margin-right: -8px; } -button.save:hover { - background-color: #59ac33; -} - button.close { position: absolute; top: 10px; From b9a2914b35118950bc0b1af91cce087a694e337a Mon Sep 17 00:00:00 2001 From: Saman Bemel-Benrud Date: Tue, 15 Jan 2013 20:11:05 -0500 Subject: [PATCH 02/39] implementing flexible grid. --- css/app.css | 70 ++++++++++++++++++++----------------------- js/id/id.js | 33 ++++++++++---------- js/id/modes/browse.js | 2 +- js/id/ui/inspector.js | 32 +++++++++++++------- 4 files changed, 74 insertions(+), 63 deletions(-) diff --git a/css/app.css b/css/app.css index fb6a894a3..468478091 100644 --- a/css/app.css +++ b/css/app.css @@ -14,6 +14,11 @@ body { height: 100%; width: 100%; position: fixed; + min-width: 760px; +} + +.limiter { + max-width: 1400px; } div, textarea, input, span, ul, li, ol, a, button { @@ -230,7 +235,7 @@ button { color:#222; background: white; font-weight:bold; - font-size:14px; + font-size:12px; display: inline-block; height:40px; cursor:url(../img/cursor-pointer.png) 6 1, auto; @@ -255,20 +260,6 @@ button.narrow { border-radius:4px; } -button.wide { - margin: 10px; - width: 100px; -} - -button.add-button { - width: 80px; -} - -button.narrow, -button.Browse { - width:40px; -} - button.minor { border-radius:4px; height: 20px; @@ -289,22 +280,24 @@ button.centered { margin-right: auto; } -.buttons-joined { +.button-wrap { display: inline-block; - margin:10px; -} - -.buttons-joined button { - border-right-width: 0; - border-radius:0; + padding:10px 0 10px 10px; margin: 0; } -.buttons-joined button:first-child { +.button-wrap button:only-child { width: 100%;} + +.joined button { + border-right-width: 0; + border-radius:0; +} + +.joined button:first-child { border-radius:4px 0 0 4px; } -.buttons-joined button:last-child { +.joined button:last-child { border-right-width: 1px; border-radius:0 4px 4px 0; } @@ -324,8 +317,6 @@ button.delete:hover { } button.save { - min-width: 120px; - width: auto; } button.save.has-count { @@ -482,12 +473,6 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;} height:60px; } -/* Special rules for toolbar icons */ - -button.Browse .label { - display: none; - } - /* Status box */ .messages { @@ -497,18 +482,21 @@ button.Browse .label { /* Inspector */ .inspector-wrap { - position:absolute; - right: 0; + opacity:0; + display:none; + padding-left: 10px; + max-width: 600px; +} + +.inspector { border-left: 1px solid #ccc; border-bottom: 1px solid #ccc; min-height: 60px; - opacity:0; - display:none; + position: relative; } .inspector-inner { padding: 10px; - min-width:400px; } .inspector-inner.head { @@ -596,6 +584,10 @@ button.Browse .label { border-top: 1px solid #ccc; } +.inspector-buttons .button-wrap { + width: 20%; +} + .inspector-inner .add-tag-row { width: 100%; padding-right: 70px; @@ -616,6 +608,10 @@ button.Browse .label { position:absolute; } +.map-control button { + width: 40px; +} + .map-overlay { width: 150px; position:absolute; diff --git a/js/id/id.js b/js/id/id.js index 712656cd6..a6af4242a 100644 --- a/js/id/id.js +++ b/js/id/id.js @@ -24,13 +24,16 @@ window.iD = function(container) { var bar = container.append('div') .attr('id', 'bar').attr('class', 'fillL2'); - var buttons_joined = bar.append('div') - .attr('class', 'buttons-joined'); + var limiter = bar.append('div') + .attr('class', 'limiter'); + + var buttons_joined = limiter.append('div') + .attr('class', 'button-wrap joined col4'); var buttons = buttons_joined.selectAll('button.add-button') .data([iD.modes.Browse(), iD.modes.AddPoint(), iD.modes.AddLine(), iD.modes.AddArea()]) .enter().append('button') - .attr('class', function (mode) { return mode.title + ' add-button'; }) + .attr('class', function (mode) { return mode.title + ' add-button col3'; }) .attr('data-original-title', function (mode) { return mode.description; }) .call(bootstrap.tooltip().placement('bottom')) .on('click', function (mode) { controller.enter(mode); }); @@ -46,7 +49,7 @@ window.iD = function(container) { } } - notice = iD.ui.notice(bar + notice = iD.ui.notice(limiter .append('div') .attr('class', 'notice')); @@ -71,19 +74,19 @@ window.iD = function(container) { container.classed("mode-" + exited.id, false); }); - var undo_buttons = bar.append('div') - .attr('class', 'buttons-joined'), + var undo_buttons = limiter.append('div') + .attr('class', 'button-wrap joined col1'), undo_tooltip = bootstrap.tooltip().placement('bottom'); undo_buttons.append('button') - .attr({ id: 'undo', 'class': 'narrow' }) + .attr({ id: 'undo', 'class': 'col6 narrow' }) .property('disabled', true) .html("") .on('click', history.undo) .call(undo_tooltip); undo_buttons.append('button') - .attr({ id: 'redo', 'class': 'narrow' }) + .attr({ id: 'redo', 'class': 'col6 narrow' }) .property('disabled', true) .html("") .on('click', history.redo) @@ -94,8 +97,8 @@ window.iD = function(container) { .append('div') .attr('class', 'hello'); - var save_button = bar.append('button') - .attr('class', 'save action wide') + var save_button = limiter.append('div').attr('class','button-wrap col1').append('button') + .attr('class', 'save action wide col12') .call(iD.ui.save().map(map)); history.on('change.warn-unload', function() { @@ -110,7 +113,7 @@ window.iD = function(container) { } : null; }); - bar.append('div') + limiter.append('div') .attr('class', 'messages'); var zoom = container.append('div') @@ -139,8 +142,8 @@ window.iD = function(container) { .call(iD.ui.layerswitcher(map)); container.append('div') - .attr('class', 'inspector-wrap fillL') - .style('display', 'none'); + .style('display', 'none') + .attr('class', 'inspector-wrap fr col5'); var about = container.append('div').attr('id', 'attrib-container'); @@ -169,12 +172,12 @@ window.iD = function(container) { } } - bar.select('#undo') + limiter.select('#undo') .property('disabled', !undo) .attr('data-original-title', undo) .call(undo ? refreshTooltip : undo_tooltip.hide); - bar.select('#redo') + limiter.select('#redo') .property('disabled', !redo) .attr('data-original-title', redo) .call(redo ? refreshTooltip : undo_tooltip.hide); diff --git a/js/id/modes/browse.js b/js/id/modes/browse.js index c57b503f5..4b2ea448f 100644 --- a/js/id/modes/browse.js +++ b/js/id/modes/browse.js @@ -2,7 +2,7 @@ iD.modes.Browse = function() { var mode = { button: 'browse', id: 'browse', - title: 'Browse', + title: 'Move', description: 'Pan and zoom the map' }; diff --git a/js/id/ui/inspector.js b/js/id/ui/inspector.js index da022e8c8..5edc48e9f 100644 --- a/js/id/ui/inspector.js +++ b/js/id/ui/inspector.js @@ -14,11 +14,15 @@ iD.ui.inspector = function() { event.close(entity); }); - selection.append('div') + + var inspector = selection.append('div') + .attr('class','inspector fillL'); + + inspector.append('div') .attr('class', 'head inspector-inner') .call(drawHead); - var inspectorbody = selection.append('div') + var inspectorbody = inspector.append('div') .attr('class', 'inspector-body'); var inspectorwrap = inspectorbody.append('div') @@ -79,15 +83,23 @@ iD.ui.inspector = function() { } function drawButtons(selection) { - selection.append('button') - .attr('class', 'apply wide action') - .html("Apply") - .on('click', apply); + var inspectorButton1 = selection.append('div') + .attr('class', 'button-wrap') + .append('button') + .attr('class', 'apply wide action') + .on('click', apply); - selection.append('button') - .attr('class', 'delete wide action') - .html("Delete") - .on('click', function(entity) { event.remove(entity); }); + inspectorButton1.append('span').attr('class','icon icon-pre-text apply'); + inspectorButton1.append('span').attr('class','label').text('Apply'); + + var inspectorButton2 = selection.append('div') + .attr('class', 'button-wrap') + .append('button') + .attr('class', 'delete wide action') + .on('click', function(entity) { event.remove(entity); }); + + inspectorButton2.append('span').attr('class','icon icon-pre-text delete'); + inspectorButton2.append('span').attr('class','label').text('Delete'); } function drawTags(tags) { From a4557af225cab7a1bc48ae4c0aa97cca03bd9866 Mon Sep 17 00:00:00 2001 From: Saman Bemel-Benrud Date: Thu, 17 Jan 2013 19:12:07 -0500 Subject: [PATCH 03/39] remove save icon. --- css/app.css | 2 +- js/id/ui/inspector.js | 1 - js/id/ui/save.js | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/css/app.css b/css/app.css index 90401612c..53eec9933 100644 --- a/css/app.css +++ b/css/app.css @@ -14,7 +14,7 @@ body { height: 100%; width: 100%; position: fixed; - min-width: 760px; + min-width: 768px; } .limiter { diff --git a/js/id/ui/inspector.js b/js/id/ui/inspector.js index 9078dea7b..3aca8caca 100644 --- a/js/id/ui/inspector.js +++ b/js/id/ui/inspector.js @@ -83,7 +83,6 @@ iD.ui.inspector = function() { } function drawButtons(selection) { -<<<<<<< HEAD var inspectorButton1 = selection.append('div') .attr('class', 'button-wrap') .append('button') diff --git a/js/id/ui/save.js b/js/id/ui/save.js index 27d6ef1e5..95561da31 100644 --- a/js/id/ui/save.js +++ b/js/id/ui/save.js @@ -7,7 +7,7 @@ iD.ui.save = function() { var history = map.history(), connection = map.connection(); - selection.html("Save") + selection.html("Save") .attr('title', 'Save changes to OpenStreetMap, making them visible to other users') .property('disabled', true) .call(bootstrap.tooltip() From feab67349ed0cb29a86476b61d88a4205d94e04d Mon Sep 17 00:00:00 2001 From: Saman Bemel-Benrud Date: Thu, 17 Jan 2013 19:29:35 -0500 Subject: [PATCH 04/39] fix buttons. --- css/app.css | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/css/app.css b/css/app.css index 53eec9933..d374eee13 100644 --- a/css/app.css +++ b/css/app.css @@ -582,10 +582,15 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;} .inspector-buttons { border-top: 1px solid #ccc; + padding-right: 10px; } .inspector-buttons .button-wrap { - width: 20%; + width: 50%; +} + +.inspector-buttons .button-wrap { + width: 50%; } .inspector-inner .add-tag-row { From 0246f2c5dd759b5d8a83fa989ee7885ac7288129 Mon Sep 17 00:00:00 2001 From: saman bb Date: Fri, 18 Jan 2013 01:17:08 -0500 Subject: [PATCH 05/39] style / layout refactoring --- css/app.css | 179 +++--- img/source/sprite.svg | 1155 +++++++++++++------------------------ img/sprite.png | Bin 15999 -> 12910 bytes js/id/id.js | 3 +- js/id/ui/inspector.js | 2 +- js/id/ui/layerswitcher.js | 6 +- 6 files changed, 484 insertions(+), 861 deletions(-) diff --git a/css/app.css b/css/app.css index 53eec9933..8b46887f5 100644 --- a/css/app.css +++ b/css/app.css @@ -18,7 +18,7 @@ body { } .limiter { - max-width: 1400px; + max-width: 1200px; } div, textarea, input, span, ul, li, ol, a, button { @@ -164,24 +164,15 @@ ul li { list-style: none;} ul.toggle-list li a { font-weight: bold; padding: 10px; - border-top: 1px solid #CCC; + border-top: 1px solid white; display:block; } -ul.toggle-list li a:hover { - background: #ececec; -} - ul.toggle-list .icon { float: left; margin-right: 5px; } -a.selected { - color:#222; -} - - ul.link-list li { float: left; display: inline-block; @@ -199,11 +190,10 @@ ul.link-list li:first-child { /* Utility Classes ------------------------------------------------------- */ -.fillL { background-color: white;} +.fillL { background: white;} .fillL2 { background: #f7f7f7 url(../img/background-pattern-1.png) repeat;} .fillD { - background-color: #222222; - background-color: rgba(0,0,0,.8); + background: rgba(0,0,0,.7); color: white; } @@ -216,9 +206,8 @@ form.hide { } .content { - background-color:#fff; + background:#fff; border-radius: 4px; - border: 1px solid #ccc; } .pad1 {padding: 10px;} @@ -230,8 +219,7 @@ form.hide { button { line-height:20px; - border:1px solid #aaa; - box-shadow: inset 0 0 0px 1px #fff; + border:0; color:#222; background: white; font-weight:bold; @@ -242,17 +230,20 @@ button { } button:hover { - background-color: #ececec; + background: #ececec; +} + +button.col3:hover { + background: #bde5aa; } button.active { - box-shadow: inset 0 0 0px 1px #fff, inset 0 0 6px 1px rgba(0,0,0,.35); cursor:url(../img/cursor-pointing.png) 6 1, auto; } button.active:not([disabled]) { - background-color: #ececec; - box-shadow: inset 0 0 0px 1px #fff, inset 0 0 6px 1px rgba(0,0,0,.25); + background: #6bc641; + color: white; } button.wide, @@ -282,14 +273,15 @@ button.centered { .button-wrap { display: inline-block; - padding:10px 0 10px 10px; + padding-right:10px; margin: 0; } .button-wrap button:only-child { width: 100%;} +.button-wrap:last-child { padding-right: 0; } .joined button { - border-right-width: 0; + border-right: 1px solid rgba(0,0,0,.5); border-radius:0; } @@ -298,15 +290,16 @@ button.centered { } .joined button:last-child { - border-right-width: 1px; + border-right-width: 0px; border-radius:0 4px 4px 0; } button.action { - background: #444; + color: white; + background: #7092ff; } button.action:hover { - background: #222; + background: #597BE7; } button.delete { @@ -328,15 +321,9 @@ button.save .count { } button.save.has-count .count { - display: block; - color: #444; - background: #fff; - border-radius: 0 3px 3px 0; - padding: 9px; - float: right; - margin-left: 10px; - margin-top: -9px; - margin-right: -8px; + display: inline-block; + color: rgba(255,255,255,.5); + padding-left: 5px; } button.close { @@ -346,22 +333,22 @@ button.close { } button .label { - margin-right: 3px; + display: none; } -button.action .label { +button.save .label { + display: inline-block; color: white; - text-shadow: 0 -1px 0 rgba(0,0,0,.25); } button[disabled] { cursor:auto; - background: white; + background: #cecece; pointer-events:none; } button[disabled] .label { - color:#ccc; + color:#999999; text-shadow: none; } @@ -386,18 +373,13 @@ button[disabled]:hover { height: 40px; } -.icon.icon-pre-text { - margin-right: 3px; -} - /* Definitions for every icon */ - -.icon.browse { background-position: 0px 0px;} -.icon.add-point { background-position: -20px 0px;} -.icon.add-line { background-position: -40px 0px;} -.icon.add-area { background-position: -60px 0px;} -.icon.undo { background-position: -80px 0px;} -.icon.redo { background-position: -100px 0px;} +button.active:not([disabled]) .icon.browse { background-position: 0px -20px;} +button.active:not([disabled]) .icon.add-point { background-position: -20px -20px;} +button.active:not([disabled]) .icon.add-line { background-position: -40px -20px;} +button.active:not([disabled]) .icon.add-area { background-position: -60px -20px;} +button.active:not([disabled]) .icon.undo { background-position: -80px -20px;} +button.active:not([disabled]) .icon.redo { background-position: -100px -20px;} .icon.apply { background-position: -120px 0px;} .icon.save { background-position: -140px 0px;} .icon.close { background-position: -160px 0px;} @@ -411,10 +393,13 @@ button[disabled]:hover { .icon.avatar { background-position: -320px 0px;} .icon.nearby { background-position: -340px 0px;} -.fillD .icon.browse { background-position: 0px -20px;} -.fillD .icon.add-point { background-position: -20px -20px;} -.fillD .icon.add-line { background-position: -40px -20px;} -.fillD .icon.add-area { background-position: -60px -20px;} +.icon.browse { background-position: 0px 0px;} +.icon.add-point { background-position: -20px 0px;} +.icon.add-line { background-position: -40px 0px;} +.icon.add-area { background-position: -60px 0px;} +.icon.undo { background-position: -80px 0px;} +.icon.redo { background-position: -100px 0px;} + .fillD .icon.undo { background-position: -80px -20px;} .fillD .icon.redo { background-position: -100px -20px;} .fillD .icon.apply { background-position: -120px -20px;} @@ -422,11 +407,11 @@ button[disabled]:hover { .fillD .icon.close { background-position: -160px -20px;} .fillD .icon.delete { background-position: -180px -20px;} .fillD .icon.remove { background-position: -200px -20px;} -.fillD .icon.inspect { background-position: -220px -20px;} -.fillD .icon.zoom-in { background-position: -240px -20px;} -.fillD .icon.zoom-out { background-position: -260px -20px;} -.fillD .icon.geocode { background-position: -280px -20px;} -.fillD .icon.layers { background-position: -300px -20px;} +.map-control .icon.inspect { background-position: -220px -20px;} +.map-control .icon.zoom-in { background-position: -240px -20px;} +.map-control .icon.zoom-out { background-position: -260px -20px;} +.map-control .icon.geocode { background-position: -280px -20px;} +.map-control .icon.layers { background-position: -300px -20px;} .fillD .icon.avatar { background-position: -320px -20px;} .fillD .icon.nearby { background-position: -340px -20px;} @@ -465,12 +450,12 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;} ------------------------------------------------------- */ #bar { - border-bottom:1px solid #ccc; position:absolute; left:0px; top:0px; right:0; height:60px; + background: rgba(0,0,0,.8); } /* Status box */ @@ -485,12 +470,10 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;} opacity:0; display:none; padding-left: 10px; - max-width: 600px; + max-width: 500px; } .inspector { - border-left: 1px solid #ccc; - border-bottom: 1px solid #ccc; min-height: 60px; position: relative; } @@ -500,7 +483,6 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;} } .inspector-inner.head { - border-bottom: 1px solid #ccc; background:#fff; z-index:1; position:relative; @@ -580,13 +562,14 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;} right: 30px; } -.inspector-buttons { - border-top: 1px solid #ccc; -} - .inspector-buttons .button-wrap { width: 20%; } +.inspector-buttons .button-wrap:first-child { padding-right: 5px;} + +.inspector-buttons .button-wrap:last-child { + padding-left: 5px; +} .inspector-inner .add-tag-row { width: 100%; @@ -604,12 +587,22 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;} /* Map Controls */ .map-control { - left:10px; + left:0px; position:absolute; } .map-control button { width: 40px; + border-radius: 0 4px 4px 0; + background: rgba(0, 0, 0, .8); +} + +.map-control button:hover { + background: rgba(0, 0, 0, .9); +} + +.map-control button.active:hover { + background: #6bc641; } .map-overlay { @@ -618,6 +611,7 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;} left:50px; top:0; display: block; + border-radius: 4px; } /* Zoomer */ @@ -628,12 +622,13 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;} } .zoombuttons button.zoom-in { - border-radius:4px 4px 0 0; + border-radius:0 4px 0 0; + border-bottom: 1px solid rgba(0, 0, 0, .5); } .zoombuttons button.zoom-out { border-top:0; - border-radius:0 0 4px 4px; + border-radius:0 0 4px 0; } /* Layer Switcher */ @@ -642,28 +637,24 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;} top:210px; } -.layerswitcher-control .adjustments { - padding:5px; - opacity:0.2; -} - -.layerswitcher-control .adjustments:hover { - opacity:1; -} - -.layerswitcher-control .adjustments .reset { +.layerswitcher-control .adjustments button { + opacity:0.5; height:20px; font-size:10px; font-weight:normal; - padding:0 5px; + padding:0 5px 3px 5px; + background: white; + border: 1px solid #ddd; + border-radius: 0; +} + +.layerswitcher-control .adjustments button:hover { + opacity: 1; } .layerswitcher-control .nudge { - height:20px; width:20px; - font-size:10px; margin-right:2px; - font-weight:normal; } .opacity-options-wrapper { @@ -735,7 +726,7 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;} display:block; position:absolute; overflow:hidden; - top:60px; + top:0px; left:0; right:0; bottom:0; @@ -860,9 +851,6 @@ div.typeahead a:first-child { text-align: center; } -.modal button { margin-bottom: 0;} -.modal button:first-child { margin-left: 0;} - .modal button.close-modal { float:right; margin-right:10px; @@ -912,11 +900,14 @@ div.typeahead a:first-child { } .modal-section { - padding: 20px; - border-bottom: 1px solid #ccc; + padding: 10px; } -.modal-section:last-child { border-bottom: 0;} + +.body .modal-section:last-child { + border-bottom: 0; + border-radius: 0 0 4px 4px; +} .modal-section img.wiki-image { max-width: 400px; diff --git a/img/source/sprite.svg b/img/source/sprite.svg index f239c672f..c3fdcf407 100644 --- a/img/source/sprite.svg +++ b/img/source/sprite.svg @@ -13,7 +13,7 @@ height="200" id="svg12393" version="1.1" - inkscape:version="0.48.2 r9819" + inkscape:version="0.48.1 r9760" sodipodi:docname="sprite.svg" inkscape:export-filename="/Users/saman/work_repos/iD/img/sprite.png" inkscape:export-xdpi="90" @@ -39,8 +39,8 @@ inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="1" - inkscape:cx="150.66428" - inkscape:cy="90.493266" + inkscape:cx="54.93799" + inkscape:cy="205.49862" inkscape:document-units="px" inkscape:current-layer="layer12" showgrid="false" @@ -165,7 +165,7 @@ image/svg+xml - + @@ -175,110 +175,6 @@ id="layer1" transform="translate(-25,-62.362183)" style="display:inline"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + 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;opacity:1" /> @@ -935,26 +464,6 @@ inkscape:export-xdpi="90" inkscape:export-ydpi="90" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1260,30 +548,12 @@ - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/img/sprite.png b/img/sprite.png index 2f933d9f8a00da49db90ff2fb02c237dac4d9d75..8a536fa47d550a09c705367d8441a5eb2ba1ea2f 100644 GIT binary patch literal 12910 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 Teg1&|8v;C5)q+*4SV#U3d7R4z literal 15999 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 S$pE?#g4C3>kmZP{A^#6j{Kzx_ diff --git a/js/id/id.js b/js/id/id.js index 2edc7fd23..b1beb425f 100644 --- a/js/id/id.js +++ b/js/id/id.js @@ -22,7 +22,8 @@ window.iD = function(container) { .call(map); var bar = container.append('div') - .attr('id', 'bar').attr('class', 'fillL2'); + .attr('id', 'bar') + .attr('class','pad1'); var limiter = bar.append('div') .attr('class', 'limiter'); diff --git a/js/id/ui/inspector.js b/js/id/ui/inspector.js index b1d26a53b..1724e8ed4 100644 --- a/js/id/ui/inspector.js +++ b/js/id/ui/inspector.js @@ -47,7 +47,7 @@ iD.ui.inspector = function() { drawTags(entity.tags); inspectorbody.append('div') - .attr('class', 'inspector-buttons') + .attr('class', 'inspector-buttons pad1') .call(drawButtons); } diff --git a/js/id/ui/layerswitcher.js b/js/id/ui/layerswitcher.js index a2acad1b5..4556fbe19 100644 --- a/js/id/ui/layerswitcher.js +++ b/js/id/ui/layerswitcher.js @@ -56,7 +56,7 @@ iD.ui.layerswitcher = function(map) { var opa = content .append('div') - .attr('class', 'opacity-options-wrapper fillL2'); + .attr('class', 'opacity-options-wrapper'); opa.append('h4').text('Layers'); @@ -102,7 +102,7 @@ iD.ui.layerswitcher = function(map) { content .append('ul') - .attr('class', 'toggle-list') + .attr('class', 'toggle-list fillL2') .selectAll('a.layer') .data(sources) .enter() @@ -135,7 +135,7 @@ iD.ui.layerswitcher = function(map) { var adjustments = content .append('div') - .attr('class', 'adjustments'); + .attr('class', 'adjustments pad1'); var directions = [ ['←', [-1, 0]], From ce6e11a8a02a5d3f209208b498ad79c0c4984364 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 18 Jan 2013 10:35:15 -0800 Subject: [PATCH 06/39] Test copying tags to the split way --- js/id/actions/split_way.js | 9 ++++----- js/id/modes/select.js | 2 +- test/spec/actions/split_way.js | 14 ++++++++++++++ 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/js/id/actions/split_way.js b/js/id/actions/split_way.js index 6682ab638..fe73eeb55 100644 --- a/js/id/actions/split_way.js +++ b/js/id/actions/split_way.js @@ -7,17 +7,16 @@ iD.actions.SplitWay = function(nodeId) { // splitting ways at intersections TODO if (parents.length !== 1) return graph; - var way = parents[0]; - - var idx = _.indexOf(way.nodes, nodeId); + var way = parents[0], + idx = _.indexOf(way.nodes, nodeId); // Create a 'b' way that contains all of the tags in the second // half of this way - var newWay = iD.Way({ tags: _.clone(way.tags), nodes: way.nodes.slice(idx) }); + var newWay = iD.Way({tags: way.tags, nodes: way.nodes.slice(idx)}); graph = graph.replace(newWay); // Reduce the original way to only contain the first set of nodes - graph = graph.replace(way.update({ nodes: way.nodes.slice(0, idx + 1) }), 'changed way direction'); + graph = graph.replace(way.update({nodes: way.nodes.slice(0, idx + 1)})); var parentRelations = graph.parentRelations(way); diff --git a/js/id/modes/select.js b/js/id/modes/select.js index 62b309e29..8d59fbe43 100644 --- a/js/id/modes/select.js +++ b/js/id/modes/select.js @@ -75,7 +75,7 @@ iD.modes.Select = function (entity) { }).on('splitWay', function(d) { mode.history.perform( iD.actions.SplitWay(d.id), - 'split a way on a node'); + 'split a way'); }).on('remove', function() { remove(); diff --git a/test/spec/actions/split_way.js b/test/spec/actions/split_way.js index 6a4edc187..420fdba14 100644 --- a/test/spec/actions/split_way.js +++ b/test/spec/actions/split_way.js @@ -28,6 +28,20 @@ describe("iD.actions.SplitWay", function () { expect(waysB[1]).to.equal(waysC[0]); }); + it("copies tags to the new way", function () { + var a = iD.Node(), + b = iD.Node(), + c = iD.Node(), + tags = {highway: 'residential'}, + way = iD.Way({nodes: [a.id, b.id, c.id], tags: tags}), + graph = iD.Graph([a, b, c, way]); + + graph = iD.actions.SplitWay(b.id)(graph); + + expect(graph.parentWays(a)[0].tags).to.eql(tags); + expect(graph.parentWays(c)[0].tags).to.eql(tags); + }); + it("moves restriction relations to the new way", function () { // Situation: // a ==== b ==== c ---- d From fe8239b81ecb9b7bef53489e7701762f8cc097f0 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 18 Jan 2013 11:39:22 -0800 Subject: [PATCH 07/39] Rewrite tests --- js/id/actions/split_way.js | 14 ++++-- test/spec/actions/split_way.js | 87 ++++++++++++++++------------------ 2 files changed, 52 insertions(+), 49 deletions(-) diff --git a/js/id/actions/split_way.js b/js/id/actions/split_way.js index fe73eeb55..88566c70e 100644 --- a/js/id/actions/split_way.js +++ b/js/id/actions/split_way.js @@ -1,5 +1,13 @@ -// https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/SplitWayAction.as -iD.actions.SplitWay = function(nodeId) { +// Split a way at the given node. +// +// For testing convenience, accepts an ID to assign to the new way. +// Normally, this will be undefined and the way will automatically +// be assigned a new ID. +// +// Reference: +// https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/SplitWayAction.as +// +iD.actions.SplitWay = function(nodeId, newWayId) { return function(graph) { var node = graph.entity(nodeId), parents = graph.parentWays(node); @@ -12,7 +20,7 @@ iD.actions.SplitWay = function(nodeId) { // Create a 'b' way that contains all of the tags in the second // half of this way - var newWay = iD.Way({tags: way.tags, nodes: way.nodes.slice(idx)}); + var newWay = iD.Way({id: newWayId, tags: way.tags, nodes: way.nodes.slice(idx)}); graph = graph.replace(newWay); // Reduce the original way to only contain the first set of nodes diff --git a/test/spec/actions/split_way.js b/test/spec/actions/split_way.js index 420fdba14..f7d1e4938 100644 --- a/test/spec/actions/split_way.js +++ b/test/spec/actions/split_way.js @@ -8,69 +8,64 @@ describe("iD.actions.SplitWay", function () { // Expected result: // a ---- b ==== c // - var a = iD.Node(), - b = iD.Node(), - c = iD.Node(), - way = iD.Way({nodes: [a.id, b.id, c.id]}), - graph = iD.Graph([a, b, c, way]); + var graph = iD.Graph({ + 'a': iD.Node({id: 'a'}), + 'b': iD.Node({id: 'b'}), + 'c': iD.Node({id: 'c'}), + '-': iD.Way({id: '-', nodes: ['a', 'b', 'c']}) + }); - graph = iD.actions.SplitWay(b.id)(graph); + graph = iD.actions.SplitWay('b', '=')(graph); - var waysA = graph.parentWays(a), - waysB = graph.parentWays(b), - waysC = graph.parentWays(c); - - expect(waysA).to.have.length(1); - expect(waysB).to.have.length(2); - expect(waysC).to.have.length(1); - - expect(waysA[0]).to.equal(waysB[0]); - expect(waysB[1]).to.equal(waysC[0]); + expect(graph.entity('-').nodes).to.eql(['a', 'b']); + expect(graph.entity('=').nodes).to.eql(['b', 'c']); }); it("copies tags to the new way", function () { - var a = iD.Node(), - b = iD.Node(), - c = iD.Node(), - tags = {highway: 'residential'}, - way = iD.Way({nodes: [a.id, b.id, c.id], tags: tags}), - graph = iD.Graph([a, b, c, way]); + var tags = {highway: 'residential'}, + graph = iD.Graph({ + 'a': iD.Node({id: 'a'}), + 'b': iD.Node({id: 'b'}), + 'c': iD.Node({id: 'c'}), + '-': iD.Way({id: '-', nodes: ['a', 'b', 'c'], tags: tags}) + }); - graph = iD.actions.SplitWay(b.id)(graph); + graph = iD.actions.SplitWay('b', '=')(graph); - expect(graph.parentWays(a)[0].tags).to.eql(tags); - expect(graph.parentWays(c)[0].tags).to.eql(tags); + // Immutable tags => should be shared by identity. + expect(graph.entity('-').tags).to.equal(tags); + expect(graph.entity('=').tags).to.equal(tags); }); it("moves restriction relations to the new way", function () { // Situation: - // a ==== b ==== c ---- d - // A restriction from ==== to ---- via c. + // a ---- b ---- c ~~~~ d + // A restriction from ---- to ~~~~ via c. // // Split at b. // // Expected result: - // a ==== b ≠≠≠≠ c ---- d - // A restriction from ≠≠≠≠ to ---- via c. + // a ---- b ==== c ~~~~ d + // A restriction from ==== to ~~~~ via c. // - var a = iD.Node(), - b = iD.Node(), - c = iD.Node(), - d = iD.Node(), - from = iD.Way({nodes: [a.id, b.id, c.id]}), - to = iD.Way({nodes: [c.id, d.id]}), - restriction = iD.Relation({tags: {type: 'restriction'}, members: [ - { role: 'from', id: from.id }, - { role: 'to', id: to.id }, - { role: 'via', id: c.id }]}), - graph = iD.Graph([a, b, c, d, from, to, restriction]); + var graph = iD.Graph({ + 'a': iD.Node({id: 'a'}), + 'b': iD.Node({id: 'b'}), + 'c': iD.Node({id: 'c'}), + 'd': iD.Node({id: 'd'}), + '-': iD.Way({id: '-', nodes: ['a', 'b', 'c']}), + '~': iD.Way({id: '~', nodes: ['c', 'd']}), + 'r': iD.Relation({tags: {type: 'restriction'}, members: [ + {id: '=', role: 'from'}, + {id: '~', role: 'to'}, + {id: 'c', role: 'via'}]}) + }); - graph = iD.actions.SplitWay(b.id)(graph); + graph = iD.actions.SplitWay('b', '=')(graph); - restriction = graph.entity(restriction.id); - - expect(restriction.members[0]).not.to.eql({ role: 'from', id: from.id }); - expect(restriction.members[1]).to.eql({ role: 'to', id: to.id }); - expect(restriction.members[2]).to.eql({ role: 'via', id: c.id }); + expect(graph.entity('r').members).to.eql([ + {id: '=', role: 'from'}, + {id: '~', role: 'to'}, + {id: 'c', role: 'via'}]); }); }); From 3349e1f69ccda54c82b8d271921d5198df1da14a Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 18 Jan 2013 12:20:08 -0800 Subject: [PATCH 08/39] Add some utility methods to Relation --- js/id/graph/relation.js | 20 ++++++++++++++++++++ js/id/svg/member_classes.js | 2 +- test/spec/graph/relation.js | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/js/id/graph/relation.js b/js/id/graph/relation.js index 7d8a9aa89..989ade40c 100644 --- a/js/id/graph/relation.js +++ b/js/id/graph/relation.js @@ -18,6 +18,26 @@ iD.Relation = iD.Entity.extend({ return 'relation'; }, + // Return the first member with the given role. A copy of the member object + // is returned, extended with an 'index' property whose value is the member index. + memberByRole: function(role) { + for (var i = 0; i < this.members.length; i++) { + if (this.members[i].role === role) { + return _.extend({}, this.members[i], {index: i}); + } + } + }, + + // Return the first member with the given id. A copy of the member object + // is returned, extended with an 'index' property whose value is the member index. + memberById: function(id) { + for (var i = 0; i < this.members.length; i++) { + if (this.members[i].id === id) { + return _.extend({}, this.members[i], {index: i}); + } + } + }, + // Returns an array [A0, ... An], each Ai being an array of node arrays [Nds0, ... Ndsm], // where Nds0 is an outer ring and subsequent Ndsi's (if any i > 0) being inner rings. // diff --git a/js/id/svg/member_classes.js b/js/id/svg/member_classes.js index b675288c3..d5745a466 100644 --- a/js/id/svg/member_classes.js +++ b/js/id/svg/member_classes.js @@ -19,7 +19,7 @@ iD.svg.MemberClasses = function(graph) { relations.forEach(function (relation) { classes += ' member-type-' + relation.tags.type; - classes += ' member-role-' + _.find(relation.members, function (member) { return member.id == d.id; }).role; + classes += ' member-role-' + relation.memberById(d.id).role; }); classes = classes.trim(); diff --git a/test/spec/graph/relation.js b/test/spec/graph/relation.js index 8880fc98c..b6961a092 100644 --- a/test/spec/graph/relation.js +++ b/test/spec/graph/relation.js @@ -55,6 +55,40 @@ describe('iD.Relation', function () { }); }); + describe("#geometry", function () { + it("returns 'relation'", function () { + expect(iD.Relation().geometry()).to.equal('relation'); + }); + }); + + describe("#memberByRole", function () { + it("returns the first member with the given role", function () { + var r = iD.Relation({members: [ + {id: 'a', role: 'inner'}, + {id: 'b', role: 'outer'}, + {id: 'c', role: 'outer'}]}); + expect(r.memberByRole('outer')).to.eql({id: 'b', role: 'outer', index: 1}); + }); + + it("returns undefined if no members have the given role", function () { + expect(iD.Relation().memberByRole('outer')).to.be.undefined; + }); + }); + + describe("#memberById", function () { + it("returns the first member with the given id", function () { + var r = iD.Relation({members: [ + {id: 'a', role: 'outer'}, + {id: 'b', role: 'outer'}, + {id: 'b', role: 'inner'}]}); + expect(r.memberById('b')).to.eql({id: 'b', role: 'outer', index: 1}); + }); + + it("returns undefined if no members have the given role", function () { + expect(iD.Relation().memberById('b')).to.be.undefined; + }); + }); + describe("#multipolygon", function () { specify("single polygon consisting of a single way", function () { var a = iD.Node(), From b27903f7b5fcd6e3059a9df445b93a288353bac8 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 18 Jan 2013 13:03:54 -0800 Subject: [PATCH 09/39] Add Relation#isRestriction --- js/id/graph/relation.js | 4 ++++ test/spec/graph/relation.js | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/js/id/graph/relation.js b/js/id/graph/relation.js index 989ade40c..dc298ecbd 100644 --- a/js/id/graph/relation.js +++ b/js/id/graph/relation.js @@ -38,6 +38,10 @@ iD.Relation = iD.Entity.extend({ } }, + isRestriction: function() { + return !!(this.tags.type && this.tags.type.match(/^restriction:?/)); + }, + // Returns an array [A0, ... An], each Ai being an array of node arrays [Nds0, ... Ndsm], // where Nds0 is an outer ring and subsequent Ndsi's (if any i > 0) being inner rings. // diff --git a/test/spec/graph/relation.js b/test/spec/graph/relation.js index b6961a092..f8b49a213 100644 --- a/test/spec/graph/relation.js +++ b/test/spec/graph/relation.js @@ -89,6 +89,21 @@ describe('iD.Relation', function () { }); }); + describe("#isRestriction", function () { + it("returns true for 'restriction' type", function () { + expect(iD.Relation({tags: {type: 'restriction'}}).isRestriction()).to.be.true; + }); + + it("returns true for 'restriction:type' types", function () { + expect(iD.Relation({tags: {type: 'restriction:bus'}}).isRestriction()).to.be.true; + }); + + it("returns false otherwise", function () { + expect(iD.Relation().isRestriction()).to.be.false; + expect(iD.Relation({tags: {type: 'multipolygon'}}).isRestriction()).to.be.false; + }); + }); + describe("#multipolygon", function () { specify("single polygon consisting of a single way", function () { var a = iD.Node(), From 020c56b3a224c56ca3bef9a6f671149588de7b66 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 18 Jan 2013 13:12:36 -0800 Subject: [PATCH 10/39] Move Entity#intersects test --- test/spec/graph/entity.js | 16 ++++++++++++++++ test/spec/graph/way.js | 16 ---------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/test/spec/graph/entity.js b/test/spec/graph/entity.js index e5741104f..3f3a701fe 100644 --- a/test/spec/graph/entity.js +++ b/test/spec/graph/entity.js @@ -113,6 +113,22 @@ describe('iD.Entity', function () { }); }); + describe("#intersects", function () { + it("returns true for a way with a node within the given extent", function () { + var node = iD.Node({loc: [0, 0]}), + way = iD.Way({nodes: [node.id]}), + graph = iD.Graph([node, way]); + expect(way.intersects([[-5, -5], [5, 5]], graph)).to.equal(true); + }); + + it("returns false for way with no nodes within the given extent", function () { + var node = iD.Node({loc: [6, 6]}), + way = iD.Way({nodes: [node.id]}), + graph = iD.Graph([node, way]); + expect(way.intersects([[-5, -5], [5, 5]], graph)).to.equal(false); + }); + }); + describe("#hasInterestingTags", function () { it("returns false if the entity has no tags", function () { expect(iD.Entity().hasInterestingTags()).to.equal(false); diff --git a/test/spec/graph/way.js b/test/spec/graph/way.js index 19a4514db..c3773f6b0 100644 --- a/test/spec/graph/way.js +++ b/test/spec/graph/way.js @@ -45,22 +45,6 @@ describe('iD.Way', function() { }); }); - describe("#intersects", function () { - it("returns true for a way with a node within the given extent", function () { - var node = iD.Node({loc: [0, 0]}), - way = iD.Way({nodes: [node.id]}), - graph = iD.Graph([node, way]); - expect(way.intersects([[-5, -5], [5, 5]], graph)).to.equal(true); - }); - - it("returns false for way with no nodes within the given extent", function () { - var node = iD.Node({loc: [6, 6]}), - way = iD.Way({nodes: [node.id]}), - graph = iD.Graph([node, way]); - expect(way.intersects([[-5, -5], [5, 5]], graph)).to.equal(false); - }); - }); - describe('#isClosed', function() { it('returns false when the way has no nodes', function() { expect(iD.Way().isClosed()).to.equal(false); From 95800741fde88502984eb028834253b0b6d1fbde Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 18 Jan 2013 13:19:07 -0800 Subject: [PATCH 11/39] Add some utility methods to Way --- js/id/graph/way.js | 14 +++++++++++++- js/id/modes/draw_area.js | 2 +- js/id/modes/draw_line.js | 4 ++-- test/spec/graph/way.js | 22 ++++++++++++++++++++++ 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/js/id/graph/way.js b/js/id/graph/way.js index 305f12051..9efd4fe6c 100644 --- a/js/id/graph/way.js +++ b/js/id/graph/way.js @@ -14,12 +14,24 @@ iD.Way = iD.Entity.extend({ }); }, + first: function() { + return this.nodes[0]; + }, + + last: function() { + return this.nodes[this.nodes.length - 1]; + }, + + contains: function(node) { + return this.nodes.indexOf(node) >= 0; + }, + isOneWay: function() { return this.tags.oneway === 'yes'; }, isClosed: function() { - return this.nodes.length > 0 && this.nodes[this.nodes.length - 1] === this.nodes[0]; + return this.nodes.length > 0 && this.first() === this.last(); }, // a way is an area if: diff --git a/js/id/modes/draw_area.js b/js/id/modes/draw_area.js index cdb966351..196a4de53 100644 --- a/js/id/modes/draw_area.js +++ b/js/id/modes/draw_area.js @@ -13,7 +13,7 @@ iD.modes.DrawArea = function(wayId) { headId = (way.nodes.length == 1) ? way.nodes[0] : way.nodes[way.nodes.length - 2], - tailId = _.first(way.nodes), + tailId = way.first(), node = iD.Node({loc: map.mouseCoordinates()}); map.dblclickEnable(false) diff --git a/js/id/modes/draw_line.js b/js/id/modes/draw_line.js index 68130d7b8..72a85ae41 100644 --- a/js/id/modes/draw_line.js +++ b/js/id/modes/draw_line.js @@ -12,8 +12,8 @@ iD.modes.DrawLine = function(wayId, direction) { way = history.graph().entity(wayId), node = iD.Node({loc: map.mouseCoordinates()}), index = (direction === 'forward') ? undefined : 0, - headId = (direction === 'forward') ? _.last(way.nodes) : _.first(way.nodes), - tailId = (direction === 'forward') ? _.first(way.nodes) : _.last(way.nodes); + headId = (direction === 'forward') ? way.last() : way.first(), + tailId = (direction === 'forward') ? way.first() : way.last(); iD.behavior.Hover()(surface); diff --git a/test/spec/graph/way.js b/test/spec/graph/way.js index c3773f6b0..37df6b648 100644 --- a/test/spec/graph/way.js +++ b/test/spec/graph/way.js @@ -35,6 +35,28 @@ describe('iD.Way', function() { expect(iD.Way({tags: {foo: 'bar'}}).tags).to.eql({foo: 'bar'}); }); + describe("#first", function () { + it("returns the first node", function () { + expect(iD.Way({nodes: ['a', 'b', 'c']}).first()).to.equal('a'); + }); + }); + + describe("#last", function () { + it("returns the last node", function () { + expect(iD.Way({nodes: ['a', 'b', 'c']}).last()).to.equal('c'); + }); + }); + + describe("#contains", function () { + it("returns true if the way contains the given node", function () { + expect(iD.Way({nodes: ['a', 'b', 'c']}).contains('b')).to.be.true; + }); + + it("returns false if the way does not contain the given node", function () { + expect(iD.Way({nodes: ['a', 'b', 'c']}).contains('d')).to.be.false; + }); + }); + describe("#extent", function () { it("returns the minimal extent containing all member nodes", function () { var node1 = iD.Node({loc: [0, 0]}), From 2a0ef21548abd18533aa532d86e1a3bb07776b4c Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 18 Jan 2013 13:33:43 -0800 Subject: [PATCH 12/39] Fix restriction handling --- js/id/actions/split_way.js | 24 ++----- test/spec/actions/split_way.js | 122 +++++++++++++++++++++++++-------- 2 files changed, 100 insertions(+), 46 deletions(-) diff --git a/js/id/actions/split_way.js b/js/id/actions/split_way.js index 88566c70e..dda0c23a0 100644 --- a/js/id/actions/split_way.js +++ b/js/id/actions/split_way.js @@ -26,25 +26,13 @@ iD.actions.SplitWay = function(nodeId, newWayId) { // Reduce the original way to only contain the first set of nodes graph = graph.replace(way.update({nodes: way.nodes.slice(0, idx + 1)})); - var parentRelations = graph.parentRelations(way); + graph.parentRelations(way).forEach(function(relation) { + if (relation.isRestriction()) { + var via = relation.memberByRole('via'), + member = relation.memberById(way.id); - function isVia(x) { return x.role = 'via'; } - function isSelf(x) { return x.id = way.id; } - - parentRelations.forEach(function(relation) { - if (relation.tags.type === 'restriction') { - var via = _.find(relation.members, isVia); - var ownrole = _.find(relation.members, isSelf).role; - if (via && !_.contains(newWay.nodes, via.id)) { - // the new way doesn't contain the node that's important - // to the turn restriction, so we don't need to worry - // about adding it to the turn restriction. - } else { - graph = graph.replace(iD.actions.AddRelationMember(relation.id, { - role: ownrole, - id: newWay.id, - type: 'way' - })); + if (via && newWay.contains(via.id)) { + graph = iD.actions.UpdateRelationMember(relation.id, member.index, {id: newWay.id})(graph); } } }); diff --git a/test/spec/actions/split_way.js b/test/spec/actions/split_way.js index f7d1e4938..b12708f9c 100644 --- a/test/spec/actions/split_way.js +++ b/test/spec/actions/split_way.js @@ -37,35 +37,101 @@ describe("iD.actions.SplitWay", function () { expect(graph.entity('=').tags).to.equal(tags); }); - it("moves restriction relations to the new way", function () { - // Situation: - // a ---- b ---- c ~~~~ d - // A restriction from ---- to ~~~~ via c. - // - // Split at b. - // - // Expected result: - // a ---- b ==== c ~~~~ d - // A restriction from ==== to ~~~~ via c. - // - var graph = iD.Graph({ - 'a': iD.Node({id: 'a'}), - 'b': iD.Node({id: 'b'}), - 'c': iD.Node({id: 'c'}), - 'd': iD.Node({id: 'd'}), - '-': iD.Way({id: '-', nodes: ['a', 'b', 'c']}), - '~': iD.Way({id: '~', nodes: ['c', 'd']}), - 'r': iD.Relation({tags: {type: 'restriction'}, members: [ - {id: '=', role: 'from'}, - {id: '~', role: 'to'}, - {id: 'c', role: 'via'}]}) - }); + ['restriction', 'restriction:bus'].forEach(function (type) { + it("updates a restriction's 'from' role", function () { + // Situation: + // a ----> b ----> c ~~~~ d + // A restriction from ---- to ~~~~ via c. + // + // Split at b. + // + // Expected result: + // a ----> b ====> c ~~~~ d + // A restriction from ==== to ~~~~ via c. + // + var graph = iD.Graph({ + 'a': iD.Node({id: 'a'}), + 'b': iD.Node({id: 'b'}), + 'c': iD.Node({id: 'c'}), + 'd': iD.Node({id: 'd'}), + '-': iD.Way({id: '-', nodes: ['a', 'b', 'c']}), + '~': iD.Way({id: '~', nodes: ['c', 'd']}), + 'r': iD.Relation({id: 'r', tags: {type: type}, members: [ + {id: '-', role: 'from'}, + {id: '~', role: 'to'}, + {id: 'c', role: 'via'}]}) + }); - graph = iD.actions.SplitWay('b', '=')(graph); + graph = iD.actions.SplitWay('b', '=')(graph); - expect(graph.entity('r').members).to.eql([ - {id: '=', role: 'from'}, - {id: '~', role: 'to'}, - {id: 'c', role: 'via'}]); + expect(graph.entity('r').members).to.eql([ + {id: '=', role: 'from'}, + {id: '~', role: 'to'}, + {id: 'c', role: 'via'}]); + }); + + it("updates a restriction's 'to' role", function () { + // Situation: + // a ----> b ----> c ~~~~ d + // A restriction from ~~~~ to ---- via c. + // + // Split at b. + // + // Expected result: + // a ----> b ====> c ~~~~ d + // A restriction from ~~~~ to ==== via c. + // + var graph = iD.Graph({ + 'a': iD.Node({id: 'a'}), + 'b': iD.Node({id: 'b'}), + 'c': iD.Node({id: 'c'}), + 'd': iD.Node({id: 'd'}), + '-': iD.Way({id: '-', nodes: ['a', 'b', 'c']}), + '~': iD.Way({id: '~', nodes: ['c', 'd']}), + 'r': iD.Relation({id: 'r', tags: {type: type}, members: [ + {id: '~', role: 'from'}, + {id: '-', role: 'to'}, + {id: 'c', role: 'via'}]}) + }); + + graph = iD.actions.SplitWay('b', '=')(graph); + + expect(graph.entity('r').members).to.eql([ + {id: '~', role: 'from'}, + {id: '=', role: 'to'}, + {id: 'c', role: 'via'}]); + }); + + it("leaves unaffected restrictions unchanged", function () { + // Situation: + // a <---- b <---- c ~~~~ d + // A restriction from ---- to ~~~~ via c. + // + // Split at b. + // + // Expected result: + // a <==== b <---- c ~~~~ d + // A restriction from ---- to ~~~~ via c. + // + var graph = iD.Graph({ + 'a': iD.Node({id: 'a'}), + 'b': iD.Node({id: 'b'}), + 'c': iD.Node({id: 'c'}), + 'd': iD.Node({id: 'd'}), + '-': iD.Way({id: '-', nodes: ['c', 'b', 'a']}), + '~': iD.Way({id: '~', nodes: ['c', 'd']}), + 'r': iD.Relation({id: 'r', tags: {type: type}, members: [ + {id: '-', role: 'from'}, + {id: '~', role: 'to'}, + {id: 'c', role: 'via'}]}) + }); + + graph = iD.actions.SplitWay('b', '=')(graph); + + expect(graph.entity('r').members).to.eql([ + {id: '-', role: 'from'}, + {id: '~', role: 'to'}, + {id: 'c', role: 'via'}]); + }); }); }); From 2ee07a3b74d61715a6e7fdf00436ffc88f7c4838 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 18 Jan 2013 14:07:44 -0800 Subject: [PATCH 13/39] Add iD.actions.AddRelationMember --- index.html | 1 + js/id/actions/add_relation_member.js | 9 ++++++ test/index.html | 2 ++ test/index_packaged.html | 1 + test/spec/actions/add_relation_member.js | 37 ++++++++++++++++++++++++ 5 files changed, 50 insertions(+) create mode 100644 js/id/actions/add_relation_member.js create mode 100644 test/spec/actions/add_relation_member.js diff --git a/index.html b/index.html index 16dce5779..5853a8a50 100644 --- a/index.html +++ b/index.html @@ -71,6 +71,7 @@ + diff --git a/js/id/actions/add_relation_member.js b/js/id/actions/add_relation_member.js new file mode 100644 index 000000000..45e24a0b0 --- /dev/null +++ b/js/id/actions/add_relation_member.js @@ -0,0 +1,9 @@ +iD.actions.AddRelationMember = function(relationId, member, index) { + return function(graph) { + var relation = graph.entity(relationId), + members = relation.members.slice(); + + members.splice((index === undefined) ? members.length : index, 0, member); + return graph.replace(relation.update({members: members})); + }; +}; diff --git a/test/index.html b/test/index.html index 0777751d5..425258d20 100644 --- a/test/index.html +++ b/test/index.html @@ -66,6 +66,7 @@ + @@ -124,6 +125,7 @@ + diff --git a/test/index_packaged.html b/test/index_packaged.html index 630ed1088..8def4c0da 100644 --- a/test/index_packaged.html +++ b/test/index_packaged.html @@ -31,6 +31,7 @@ + diff --git a/test/spec/actions/add_relation_member.js b/test/spec/actions/add_relation_member.js new file mode 100644 index 000000000..aeae8e353 --- /dev/null +++ b/test/spec/actions/add_relation_member.js @@ -0,0 +1,37 @@ +describe("iD.actions.AddRelationMember", function () { + it("adds a member at the end of the relation", function () { + var relation = iD.Relation(), + graph = iD.Graph([relation]); + + graph = iD.actions.AddRelationMember(relation.id, {id: '1'})(graph); + + expect(graph.entity(relation.id).members).to.eql([{id: '1'}]); + }); + + it("adds a member at index 0", function () { + var relation = iD.Relation({members: [{id: '1'}]}), + graph = iD.Graph([relation]); + + graph = iD.actions.AddRelationMember(relation.id, {id: '2'}, 0)(graph); + + expect(graph.entity(relation.id).members).to.eql([{id: '2'}, {id: '1'}]); + }); + + it("adds a member at a positive index", function () { + var relation = iD.Relation({members: [{id: '1'}, {id: '3'}]}), + graph = iD.Graph([relation]); + + graph = iD.actions.AddRelationMember(relation.id, {id: '2'}, 1)(graph); + + expect(graph.entity(relation.id).members).to.eql([{id: '1'}, {id: '2'}, {id: '3'}]); + }); + + it("adds a member at a negative index", function () { + var relation = iD.Relation({members: [{id: '1'}, {id: '3'}]}), + graph = iD.Graph([relation]); + + graph = iD.actions.AddRelationMember(relation.id, {id: '2'}, -1)(graph); + + expect(graph.entity(relation.id).members).to.eql([{id: '1'}, {id: '2'}, {id: '3'}]); + }); +}); From f16c54e12fb7a2504cf48edf67f53a9718415d0d Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 18 Jan 2013 14:09:53 -0800 Subject: [PATCH 14/39] Match argument order with AddRelationMember --- js/id/actions/reverse_way.js | 2 +- js/id/actions/split_way.js | 9 +++++---- js/id/actions/update_relation_member.js | 2 +- test/spec/actions/update_relation_member.js | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/js/id/actions/reverse_way.js b/js/id/actions/reverse_way.js index 37ac53f10..a845fe844 100644 --- a/js/id/actions/reverse_way.js +++ b/js/id/actions/reverse_way.js @@ -65,7 +65,7 @@ iD.actions.ReverseWay = function(wayId) { graph.parentRelations(way).forEach(function (relation) { relation.members.forEach(function (member, index) { if (member.id === way.id && (role = {forward: 'backward', backward: 'forward'}[member.role])) { - graph = iD.actions.UpdateRelationMember(relation.id, index, {role: role})(graph); + graph = iD.actions.UpdateRelationMember(relation.id, {role: role}, index)(graph); } }); }); diff --git a/js/id/actions/split_way.js b/js/id/actions/split_way.js index dda0c23a0..9f33bdf73 100644 --- a/js/id/actions/split_way.js +++ b/js/id/actions/split_way.js @@ -28,11 +28,12 @@ iD.actions.SplitWay = function(nodeId, newWayId) { graph.parentRelations(way).forEach(function(relation) { if (relation.isRestriction()) { - var via = relation.memberByRole('via'), - member = relation.memberById(way.id); - + var via = relation.memberByRole('via'); if (via && newWay.contains(via.id)) { - graph = iD.actions.UpdateRelationMember(relation.id, member.index, {id: newWay.id})(graph); + graph = iD.actions.UpdateRelationMember( + relation.id, + {id: newWay.id}, + relation.memberById(way.id).index)(graph); } } }); diff --git a/js/id/actions/update_relation_member.js b/js/id/actions/update_relation_member.js index 67a45b6ab..29eb79afe 100644 --- a/js/id/actions/update_relation_member.js +++ b/js/id/actions/update_relation_member.js @@ -1,4 +1,4 @@ -iD.actions.UpdateRelationMember = function(relationId, index, properties) { +iD.actions.UpdateRelationMember = function(relationId, properties, index) { return function(graph) { var relation = graph.entity(relationId), members = relation.members.slice(); diff --git a/test/spec/actions/update_relation_member.js b/test/spec/actions/update_relation_member.js index 1878ff923..c85d72b34 100644 --- a/test/spec/actions/update_relation_member.js +++ b/test/spec/actions/update_relation_member.js @@ -2,7 +2,7 @@ describe("iD.actions.UpdateRelationMember", function () { it("updates the properties of the relation member at the specified index", function () { var node = iD.Node(), relation = iD.Relation({members: [{id: node.id, role: 'forward'}]}), - graph = iD.actions.UpdateRelationMember(relation.id, 0, {role: 'backward'})(iD.Graph([node, relation])); + graph = iD.actions.UpdateRelationMember(relation.id, {role: 'backward'}, 0)(iD.Graph([node, relation])); expect(graph.entity(relation.id).members).to.eql([{id: node.id, role: 'backward'}]); }); }); From e19f86a285148b4320de5fcc55e525efe70888fc Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 18 Jan 2013 14:43:25 -0800 Subject: [PATCH 15/39] Add newly split way to member relations --- js/id/actions/split_way.js | 20 ++++++++- test/spec/actions/split_way.js | 76 ++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 1 deletion(-) diff --git a/js/id/actions/split_way.js b/js/id/actions/split_way.js index 9f33bdf73..de399df80 100644 --- a/js/id/actions/split_way.js +++ b/js/id/actions/split_way.js @@ -33,8 +33,26 @@ iD.actions.SplitWay = function(nodeId, newWayId) { graph = iD.actions.UpdateRelationMember( relation.id, {id: newWay.id}, - relation.memberById(way.id).index)(graph); + relation.memberById(way.id).index + )(graph); } + } else { + var role = relation.memberById(way.id).role, + last = newWay.last(), + i = relation.memberById(way.id).index, + j; + + for (j = 0; j < relation.members.length; j++) { + if (relation.members[j].type === 'way' && graph.entity(relation.members[j].id).contains(last)) { + break; + } + } + + graph = iD.actions.AddRelationMember( + relation.id, + {id: newWay.id, type: 'way', role: role}, + i <= j ? i + 1 : i + )(graph); } }); diff --git a/test/spec/actions/split_way.js b/test/spec/actions/split_way.js index b12708f9c..e83d5ee1a 100644 --- a/test/spec/actions/split_way.js +++ b/test/spec/actions/split_way.js @@ -37,6 +37,82 @@ describe("iD.actions.SplitWay", function () { expect(graph.entity('=').tags).to.equal(tags); }); + it("adds the new way to parent relations (no connections)", function () { + // Situation: + // a ---- b ---- c + // Relation: [----] + // + // Split at b. + // + // Expected result: + // a ---- b ==== c + // Relation: [----, ====] + // + var graph = iD.Graph({ + 'a': iD.Node({id: 'a'}), + 'b': iD.Node({id: 'b'}), + 'c': iD.Node({id: 'c'}), + '-': iD.Way({id: '-', nodes: ['a', 'b', 'c']}), + 'r': iD.Relation({id: 'r', members: [{id: '-', type: 'way'}]}) + }); + + graph = iD.actions.SplitWay('b', '=')(graph); + + expect(_.pluck(graph.entity('r').members, 'id')).to.eql(['-', '=']); + }); + + it("adds the new way to parent relations (forward order)", function () { + // Situation: + // a ---- b ---- c ~~~~ d + // Relation: [----, ~~~~] + // + // Split at b. + // + // Expected result: + // a ---- b ==== c ~~~~ d + // Relation: [----, ====, ~~~~] + // + var graph = iD.Graph({ + 'a': iD.Node({id: 'a'}), + 'b': iD.Node({id: 'b'}), + 'c': iD.Node({id: 'c'}), + 'd': iD.Node({id: 'd'}), + '-': iD.Way({id: '-', nodes: ['a', 'b', 'c']}), + '~': iD.Way({id: '~', nodes: ['c', 'd']}), + 'r': iD.Relation({id: 'r', members: [{id: '-', type: 'way'}, {id: '~', type: 'way'}]}) + }); + + graph = iD.actions.SplitWay('b', '=')(graph); + + expect(_.pluck(graph.entity('r').members, 'id')).to.eql(['-', '=', '~']); + }); + + it("adds the new way to parent relations (reverse order)", function () { + // Situation: + // a ---- b ---- c ~~~~ d + // Relation: [~~~~, ----] + // + // Split at b. + // + // Expected result: + // a ---- b ==== c ~~~~ d + // Relation: [~~~~, ====, ----] + // + var graph = iD.Graph({ + 'a': iD.Node({id: 'a'}), + 'b': iD.Node({id: 'b'}), + 'c': iD.Node({id: 'c'}), + 'd': iD.Node({id: 'd'}), + '-': iD.Way({id: '-', nodes: ['a', 'b', 'c']}), + '~': iD.Way({id: '~', nodes: ['c', 'd']}), + 'r': iD.Relation({id: 'r', members: [{id: '~', type: 'way'}, {id: '-', type: 'way'}]}) + }); + + graph = iD.actions.SplitWay('b', '=')(graph); + + expect(_.pluck(graph.entity('r').members, 'id')).to.eql(['~', '=', '-']); + }); + ['restriction', 'restriction:bus'].forEach(function (type) { it("updates a restriction's 'from' role", function () { // Situation: From 2b45a5b452540e4f533fe7b7ae1f9c0bcb2b9b43 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 18 Jan 2013 15:00:50 -0800 Subject: [PATCH 16/39] Use sinon's fake timers --- js/id/ui/flash.js | 2 +- test/spec/ui/flash.js | 19 ++++++++++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/js/id/ui/flash.js b/js/id/ui/flash.js index 7b3b00628..4ce6a3b0a 100644 --- a/js/id/ui/flash.js +++ b/js/id/ui/flash.js @@ -10,7 +10,7 @@ iD.ui.flash = function() { modal.on('click.flash', function() { modal.remove(); }); - d3.timer(function() { + setTimeout(function() { modal.remove(); return true; }, 1000); diff --git a/test/spec/ui/flash.js b/test/spec/ui/flash.js index 0426d1734..8e6272ffa 100644 --- a/test/spec/ui/flash.js +++ b/test/spec/ui/flash.js @@ -1,13 +1,22 @@ describe("iD.ui.flash", function () { + var clock; + + beforeEach(function () { + clock = sinon.useFakeTimers(); + }); + + afterEach(function () { + clock.restore(); + }); + it('can be instantiated', function () { var flash = iD.ui.flash(); expect(flash).to.be.ok; }); - it('leaves after 1000 ms', function (done) { + + it('leaves after 1000 ms', function () { var flash = iD.ui.flash(); - window.setTimeout(function() { - expect(flash.node().parentNode).to.be.null; - done(); - }, 1200); + clock.tick(1010); + expect(flash.node().parentNode).to.be.null; }); }); From 348634a5b850e40da88060855e804c8c4aadee09 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 18 Jan 2013 15:03:34 -0800 Subject: [PATCH 17/39] This is verified as part of other test --- test/spec/ui/flash.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/spec/ui/flash.js b/test/spec/ui/flash.js index 8e6272ffa..2b43ef83e 100644 --- a/test/spec/ui/flash.js +++ b/test/spec/ui/flash.js @@ -9,11 +9,6 @@ describe("iD.ui.flash", function () { clock.restore(); }); - it('can be instantiated', function () { - var flash = iD.ui.flash(); - expect(flash).to.be.ok; - }); - it('leaves after 1000 ms', function () { var flash = iD.ui.flash(); clock.tick(1010); From 60493b005122657ec77623d168142b34002371e5 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 18 Jan 2013 15:21:27 -0800 Subject: [PATCH 18/39] Fix test --- test/spec/ui/inspector.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/spec/ui/inspector.js b/test/spec/ui/inspector.js index baa830e76..1a4df1899 100644 --- a/test/spec/ui/inspector.js +++ b/test/spec/ui/inspector.js @@ -57,11 +57,11 @@ describe("iD.ui.inspector", function () { expect(inspector.tags()).to.eql({}); }); - it("emits a close event when the close button is clicked", function () { + it("emits a close event when the apply button is clicked", function () { var spy = sinon.spy(); inspector.on('close', spy); - element.select('.close').trigger('click'); + element.select('.apply').trigger('click'); expect(spy).to.have.been.calledWith(entity); }); From 6c7f9d41b79a7ec3250791881f98f2bc11c846a1 Mon Sep 17 00:00:00 2001 From: Saman Bemel-Benrud Date: Fri, 18 Jan 2013 18:52:56 -0500 Subject: [PATCH 19/39] minor fixes + adding geolocate icon. --- css/app.css | 22 +- img/source/sprite.svg | 472 ++++++++++++++++++++------------------ img/sprite.png | Bin 12002 -> 12145 bytes js/id/ui/geolocate.js | 5 +- js/id/ui/layerswitcher.js | 2 +- 5 files changed, 267 insertions(+), 234 deletions(-) diff --git a/css/app.css b/css/app.css index 90042557e..a0bbd0e2e 100644 --- a/css/app.css +++ b/css/app.css @@ -404,6 +404,7 @@ button.active:not([disabled]) .icon.add-line { background-position: -40px -20p button.active:not([disabled]) .icon.add-area { background-position: -60px -20px;} button.active:not([disabled]) .icon.undo { background-position: -80px -20px;} button.active:not([disabled]) .icon.redo { background-position: -100px -20px;} + .icon.apply { background-position: -120px 0px;} .icon.save { background-position: -140px 0px;} .icon.close { background-position: -160px 0px;} @@ -416,6 +417,8 @@ button.active:not([disabled]) .icon.redo { background-position: -100px -20p .icon.layers { background-position: -300px 0px;} .icon.avatar { background-position: -320px 0px;} .icon.nearby { background-position: -340px 0px;} +.icon.geolocate { background-position: -360px 0px;} + .icon.browse { background-position: 0px 0px;} .icon.add-point { background-position: -20px 0px;} @@ -424,15 +427,10 @@ button.active:not([disabled]) .icon.redo { background-position: -100px -20p .icon.undo { background-position: -80px 0px;} .icon.redo { background-position: -100px 0px;} -.close-modal.icon.remove { background-position: -200px -20px;} -.map-control .icon.inspect { background-position: -220px -20px;} -.map-control .icon.zoom-in { background-position: -240px -20px;} -.map-control .icon.zoom-out { background-position: -260px -20px;} -.map-control .icon.geocode { background-position: -280px -20px;} -.map-control .icon.layers { background-position: -300px -20px;} .fillD .icon.avatar { background-position: -320px -20px;} .fillD .icon.nearby { background-position: -340px -20px;} + button[disabled] .icon.browse { background-position: 0px -40px;} button[disabled] .icon.add-point { background-position: -20px -40px;} button[disabled] .icon.add-line { background-position: -40px -40px;} @@ -531,7 +529,7 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;} .tag-row { width: 100%; - padding-right: 70px; + padding-right: 60px; position: relative; height: 30px; } @@ -572,7 +570,7 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;} .tag-row button { position: absolute; - top: 0; + top: 5px; right: 0; } @@ -586,7 +584,11 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;} .inspector-inner .add-tag-row { width: 100%; - padding-right: 70px; + padding-right: 60px; +} + +.inspector-inner .add-tag-row button { + border-radius: 0 0 4px 4px; } .inspector-inner .add-tag { @@ -606,8 +608,8 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;} .map-control button { width: 40px; + background: rgba(0,0,0,.8); border-radius: 0 4px 4px 0; - background: rgba(0, 0, 0, .8); } .map-control button:hover { diff --git a/img/source/sprite.svg b/img/source/sprite.svg index 3d2a96c84..0cc0bfb21 100644 --- a/img/source/sprite.svg +++ b/img/source/sprite.svg @@ -9,7 +9,7 @@ xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="360" + width="380" height="200" id="svg12393" version="1.1" @@ -38,11 +38,11 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="1" - inkscape:cx="348.93799" - inkscape:cy="154.49862" + inkscape:zoom="2.8284271" + inkscape:cx="173.1037" + inkscape:cy="80.703482" inkscape:document-units="px" - inkscape:current-layer="layer12" + inkscape:current-layer="layer1" showgrid="false" inkscape:window-width="1560" inkscape:window-height="922" @@ -56,7 +56,7 @@ showguides="false" inkscape:guide-bbox="true" inkscape:snap-bbox="true" - inkscape:snap-nodes="true"> + inkscape:snap-nodes="false"> + + @@ -175,6 +183,15 @@ id="layer1" transform="translate(-25,-62.362183)" style="display:inline"> + + + + + transform="translate(-25,3.0625e-6)"> + 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" /> @@ -507,9 +542,9 @@ + style="fill:#ffffff;fill-opacity:1;display:inline"> + style="fill:#ffffff;fill-opacity:1;display:inline"> @@ -626,200 +661,195 @@ inkscape:connector-curvature="0" sodipodi:nodetypes="ccsccssccssccsccc" /> + id="g9693" + style="opacity:0.5;fill:#000000;fill-opacity:1;display:inline" + transform="translate(505,-613.36218)"> + - + - - - - - - - - - - - - - - - - - - - - - - - + style="fill:#000000;fill-opacity:1" + id="g9701"> + + + + style="opacity:0.6;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + d="m -135.99999,662.86216 c 0,-3.03756 2.46242,-5.49998 5.49999,-5.49998 l 0,5.49998 z" + id="path9709" /> + + - + + + + + + + + + + + + + style="fill:#000000;fill-opacity:1" + id="g47526" + transform="matrix(0.64285714,0,0,0.64285714,332.85714,42.142857)"> - - - - - - + transform="matrix(0.35714364,0,0,0.35714364,597.14212,77.857044)" + id="g47532" + style="fill:#000000;fill-opacity:1" /> + + + + + + + + + + + style="opacity:0.1;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> @@ -923,23 +953,23 @@ + style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate" /> + style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;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:0;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:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> + style="fill:#ffffff;fill-opacity:1;display:inline"> + 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" /> + style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> diff --git a/img/sprite.png b/img/sprite.png index 7aab066d70546c32e8ef6e04ece64b872860360c..2030bf5ad0385924efa6855ae42fbbcfe93f8b69 100644 GIT binary patch literal 12145 zcmdtIXHZjL^fr1zZ&E~x^d_JpEz+e2P&y(Y(px~f1VlPggEW;I=_o~zj&u@=s7UA? zr2SNSlh8s4+~a#^?%cU^@0WM}pYEASva`=V=j^rD+G{;$JuAW3Q0EE_2MquKS03Dl zJp=$qDA@i^MFD4yZ}3|`)fV+ zH}!%02Rit<0D*yl;!nLj5Ka!hF5*6Zt~tB+H~@eTcmPv>^dfgBFC>(!FJmvFOeUCr zAl2ULG0CsVnVDxvkolL%yknmA{PGSCI6i($dmLYOXJA^N9-V{3-x=yz#`sv;lelj# z%+;DyG1kZ|Px}>3_5ro4uk|GtzfkDOQp~E+g$r8p9L=g$JaPZr7E-aspS*!1hHgTk zNAdw}Woy$iWfkoSD1NFazK)YR?RkhgBbkFUW48no3^rb7bQyk=kgXDSc9MY9osH+C ziXESr@V9kx`n6+VU@$BvBg5_H?jCF#q2eP%lw>_$U0t=iD<^kZoIZ3d(ODX0D4h1m zH24F-uGU`N1%be&qVPW+9`|A`WWhl%x}(T5O14E9(50pduPM4HZYnG8X5`-e;X_EF z^rek_4p1I#-BH9aazK7k*<%dlHaj}_iep&+^n%Zh=j7z{5h;dUD}}j~7|3euVAp#KfVoCU~I3wO>X#o(>KUVrs=I;qy&iYk-$4bIe!rBu%Lm9Mw`VC%=xYUX zUv}G(p1P!`*btO_?Q$lbF}b{TpSZkJ^(6KSn))%M#}&vWS$2^OR|%Jx`edEp$s@cl zuev!;X)hH?3CUeHJ*J4H1@3W=t`Z=jq+MD-#XXlWV3&M942Vc_Jp96JWIcqv+#C`t zjtC_lP5a0`T^bn~d3|3A?ywlr+dILbx>1)z8Xc?+ircjrXDJ&FJkB`>po!&lRs!b&)e7KBs1_;=Pbnydv z!1-dM)AR$n?_nge3Ka1Z4Bh8nnnGKh5G>wk1uyH&ftP0Yx0QH|qDG}Zy&jRh@Cp@T z7?lv|R^{n}i`LmOe8xb5hi758)7OU~`%N!9wSa1peT(m%UUbV$z!K?xQbGf0ND?I3 zTm6d@3kzZI90>7%=jPT{`^Sok&0qmV2#}30-re;+m@pvCo?loX-ejH^U)4-FXOlc_ zN3b^;k!UJnb0NTdlLXb4*Vm-$yzbuKi~kmi>yhi(;RfxB#BmCP+`1xpQQyS_pjK>4 z>dtZ{&1cS+pQ#u_K)W-aZz_1j0oN5ydkVH_m_pXWr{mId9#VFN9msGO$!)alMtdg> zdAu6I5C~5;7AUUjyoND+kXV_6B)*IT%VZqCbo zKuz>$y$^{w?6W2O97@rrLVn}8t8l$$`p>1O+ul=Pt$Q1$-R7Mh!C+g*@PjihWw4;b zW4fBNqN1W&sCdM8vf8E{eP!9XH~WHJ^o`H-hBO@;fgTh0@~`MXy)^c`8Bj@l&1)VJ zaVgy?rK}#19Yjvici{rR;E1$HSf2+}NV~=YRIWPnw%kR1AVeT2yNLxw#m1|a0`d>b*E+Gh~lWR1DE9fjukpi zDPT9x;wJ^8Z@l*}7-GZ{d9AF<(w znxzm;b#;H~0X@ihNaSqoXh&B2xiqQHDUnFLPJI4c8r3n~@8j)_Ub0C=J_PD#J&)`7 ztPHWX7)()R<<{To>guXY7a{|o(-BboFmk5%4u@^s$?Bi0*)iLkb9(za?7c}f83*6_eqZJr!90a>QAI5wf9!Pw={3p`5q2$IaWs=w+esu zM-0{0d@C|<%cZ{&6G0&prCK!HJcmc%UzE6<7#~N}wzlFqh0RfTN1)b=@P_Lsd^0%03k+ei z;0UPK`~@V^-G|%shru@Y-28m%^MC*weVANEJ+DC9M^Nqm9UmWenM5<}vLog)mS|XP z5vP>puMNe~DMfYr4&H5J(}Jhhbru1Dq`Lh-Suv|{+EVLhoS96%+(6`C9M{hKxHtNn zY~!WOsz#LQO8C-ZePh9O0^muye{euRI@0&;(r1rp2K@t)nJ1Q(K{Szh zzC=>TRa^Llzif^HykYjHp+NC3e_|ECZ1ieD$7viQaz*f*2vi{54AK*{1b*B&RVAy{ ziMSVwyhuYf*&Ev*uPc5{ubfemg!;@k4X%GdNq`QSK%s+?i<7(dCQgz5BJ1{L7P2L` ze&$qvMDY_>vd8T>DgUUc!I1=OQ$(}Cl`i~Ar~o9ekffceg|sVyuQ7QkQAPp#fk~VK zum6ZJiw!&=SQ(3aHm5V3AcN7eIcadQOts9EX?^`B zOlo?i-Lv$~ub8KnQ+CFSv;Ft6 zaqDSq`S~XD&7KNgQg+$^ZtBA|(leYKfE~lXBou)ZPPO>E#DZ8S6Q`XFlwB)N~%FxL6j%S)Q{t zd2udz7d12>WSAC~Lxqbui;_fZV9TwAExI#=?Oz$f`B8@nxd$`S$r^b-@4y8n{p7GKOX?TC2JFMh>#!VX!P zhz=*a3z$jAOEVh`BZ-IycaL|~K8rw`k`CqN`T%H7Ws=WAwnh8?w|8eF@*y6h0`MXv6TsK6cctOFZ24b5zsyi({A>Q(mQdBV=~G#L<~MEsG*!*A`W`l5dVUEW>AhF*aNO5)Us!O24szu9kQ z?O0*4?WD(--Zngws{|B&DI1SW9TaTaCI-#e>^k`b#T;MxJyWeK?_fhfr zT<4O?LHesjN+ z*y`7*05+}t6D?jP32nDa#>!uX`KW10Txx)0LEBRs)lHSWVK6R?Eammqo;k$rjwYKQ zjF5gKTxeoD;!zkbM-P5NVyC7mo9hSF1e9EmXBnc=K|Ft1mDN%3l~FilH1%$TGrm;O z{QZ@99lCiLDcqKdN@w-J!NOFd!|Z)w)63$yPVMH9WK@O4stZ2psi@D=EXZD+T;(%`tF4&yJ992~+>PfR6A-(nTS%5Sm`DLfoY_65y>BjM7a>0@b+74qu?~FN$xvo|! zCw#WsohaPmrK)@SBTrqnV?g?n+8vd?@gAQ`c_l{WKM({5eV*1>xC|DKeCawDyqPUc z-PPqp4+$kxQ~1eyDLR3^xdHY1OiT=jDE$ug8em)d=rgT;XFjLcu4Wv6pg&)feu!!^ zK68G%_RSpV&3{UJlyi1BQfT62>jMbV-l~jGg;1OpR5!#dt=~YJY7FVxuQF%jjreyi zKWxFSUtw`_-cv@bTICzrl^z#Q4QF&LdAvj2fnRjq9`-Mua=!LZOtn*GjX*r>T>a%L zMI3NRRZyw)&qiU`x>v7b&rQt-B2kkhZzCq3rVb5kD!Q`Iq5)FFjj7kC*FpT(!e{I#dpO``BIYmEGmlC?ZnsXa@3@GJh7PhN_ta*i~ zR_-~ge)HfCpCC5Bo~&SXTvc^iozKSC4t#aUJ8^9r3d#+US$=4ac-typu|+ZatY)k= z9d-G}%x&n-Y0CQWs#~Rh587#||A`3R1)Yj&=Jc%X4HT4r-f2YG!p*cG9#=KEitBGL z9KWg)8-K9DXhnZh)9NOvm9Q$kDX+z@+rExiRRe(O$_fn zP6)JI6*n(Rt5dWo!DSC-xje5^uu<@At!b=sJ~H~%i#>m4&Y_esNquuL*5>IJqrBzT zhuWSRcF%pdc|=CBVvBB>1_QD-y6Exo!NzdNh@x}LU5h!^dfuPtRmAO>!suasyNI5q z{tt%PM&Z}m7Gig6G|;^oC$6nGzPXO?m1Yk}GZ1E|{;Pf2NntK{LT@g07W7Gb1$Vec zZ)5x2i-l`-ts-ZODL#VQUMA9ExRHFHWTHXv52`6D=k9M*lg7%2zdXUEcP4D4vNV+4 zLWL*XbDsmLB(GiPXu#;+r?nd|K^4Ww4BIDHXLO9B`oG726W-|?>>4n#<@Z?6V7u3$ zXY!m~%wo{JDB~%{QGH;%$o#4SSuLge(TFUZzCFUwM2Z!JFN|Qy=3=bXlnW_J&R3!e z&sKo;5G??C-Y)CxC8}GztR(E3u&wM?Obihgg&ZOQ;1@R6Pv7<|*D-!Y@`?z)T)Z#` z^S&+w{G+h7OsN_=~}E20*cgK z0)T;HC1)2Dd;a8_62%8VKHQFskNH1S8h(-ZauEiB3X*+=^7fTvG6ZCTX_OTE(}FJg zY^mP@$VDPG?!(G})9i3e7RoMVCXmKGg7O%I8CpMTx2|cVq`lEd#A*NyMX(hwAOhI; zyjJvVbTfGHTJJXvzT%I73ax$8?RJwg1=t}JzIc6fRj52nmQ5|T(v2xnRixO!m>{v4 z=Re%D+)sK&oCm_4)-AXxc+D>mqMlUu!*kdn6YQ=5L2wm|2d4jC)gd& zG3!INFBZw*v@ay*3#q(Nfx0KfA|Utd-8ca?ShBG|#H~16_AR~a<-N$c76v}+--aan zLFJDRX!!#=9950!mIYyl?nQ!OcUrR6Q`t7A_4#E54<599S&V;b+`|OMhS z%6V^FjjkxHu6-`aQN%p@7_jRaiLR#UVneQb!&U6pH7Fp(dkwtOtw|eA3R_xV{_KBXH!xS`@ z$UaNB_MHD%py=&b$@`d1lm{3zyoR4CylaHCq$A<0uQmwDt6}?{Z7ufQ(|J6Ue4Gzm znZV?p7l0wD<=y-wXO(q_ zbY5&f{L8b6&gE&j&~K~l(r-~-0`Aj0q2#LnxuJU{pjpeLT|xq9>6PQdFE$NG?KPFn zgptD21X=j*MAHT7=78>tO;|Bd7f2@jrz7>r?#Ga9y_u`Sc zdfycx*SLB`ivJqFzaL+Q3i3&jWqriH7W3L&L@hROSC0C@X#%?JN4a5b<_P9w!(xvi z{C4^>FYnZhj5_C|-Od8zp@g5-vSCyW3QX+mqYRqyfsx%r##i)%+jI#lq`Gdn&jK5(3>rxC{q$7W}FpJOF+{ww+h= z87X^y6i-~&=6AHCX+rL3_&YMdDlVafaFC6>Vb7yUyuq_tD2&AQWi-0dS&a{z^Y;S8y}jBOK;P&&*QZcQ5@w$0zdy+Vn#5T%X=dB{&?MHn2MVvP{ zhahqB{wZq28;VxnTnzdHR=Q{b6*87BRi0=D)xZ}P(^93@eT(XezBi|r1&0&cq}h2Q zY#ElhEb_A6it^L6{*RGvY!m(K0dzFssuXLA++hJQ44WF129tpkhtoH%u$-?I?S`q6u5M+W zNFvtl4B#p-7=yZjTd;@)dzU8G^Df6RzKBKWcz1+?sf0w>i*x|DLmQ0{YMp@)HANdE z_#`jxU5S=@@jhYh;njMMZ~dHRqY_OKD$fosqu#A6LAsPgJ-NeYyRds#M~4eD;fB#q z>Q*fRn3%X_vhC!lbw@5$BSnfRGF;a!)Dkuj#si`!5cyc-RfkH*zg$B_Z{hq&DJxUr~yhO?pXa_Vz*f{*lf2A%%p&kylaorfT))~i# z38-c!6N)ao7q6tTT(T=$H)4yn{-fodWvF9goR@tPzh~c)BwfaB(J8Tc@)5Wc=t~ZR zMZBw&UxRtw{L5@=F+(lNFlyAgNO?wybLzWu?1IqpylKCh2RkICvwccXDbEfQnfM<5 zrrQ007_NoceR+0*D=;Sf40G9LA_nnO{Q9-Qm{ZoX&Eu3=y>zl`cYE6Qr3g;g3Y(!^`pN<1Q#CKMSeK%B-hL)G};{n-d9caujUt=lJ6OQQxW4ZGLq0^oaPNVy!V&3=RjE=Wy zRb$nymn_q1w_gS08XYxU{F?QHN~`{*n_g2Ef@Js?GNw><#+YorsQ*tu`u|8s(f;pV z)O|Cn1_0>)`&SF_KmFAENsn~Ayu6+Qx0PorpFDXoCio{B6f&0|E*>NTaojVO9vya; zPJjtKOYxe=p@JYxgOmV#m#>(9pnk4lcH8OWqgz(5F1TrwXZ!odlGtottY|iQMZ_Rg zzGG>DNaP#}A2d*(fA3ckG#omoLet|W{V-}6gh586Ee~CnzF-p}g(W4ix+7}@$S3kz zKAp+uKvrX8<9XeTiks?~=(4li6OjR@gp`z&XV_3EQ`pTEg5|kh}{k+0{%W8c4E*0OkC}Ia4)u zn2tx`kQTrGw>O42m=`k?JlHVA5O8KG&zSmnfOp9Cm;c%&2YQS@GTs`^dC%0YK!-vG z>d{&K&eav=<>e&4rga2&504NG&+HmG)56Hq)Un&g9;I&_3Ox_#-?N&JIpp#?8o`F8 zaU9^Pk%C0=uuw4zwqwMsDgos~vH$1Ip#`IM&f7SDP}KeF@Qa&0Mq*k_N&3QRAXzN; zox5RJtKDm!_tq3_w~k{>>RL!V6I+2Fq4RP+Y+2l-K%pN)n6 zV&zThUk}}Xr3?sNO+YY;9qS<1gMo(1%F1t22-?U?y7G3l`CF`&KqQI{ire$|`*I;Z zP|q530|<<5v@?ULQX>Bm77v@ROL@*;APG<=Wlp|hz#i1loC#i}rv!Iwpw z>82h2C_7}WqJyw0sG{~YEDGli(*0L~;E)g{Ij~s6&&Vh>u-?BUP-)>B^!)dyhCpA( zV~59?N4Y9NXa7q^tt%TznKPu32$KvpF!wnjoT0lzTH8Ni&h@dXYUg5^QuVQ&l~wy| zBnPs*sHy3B(a;u;*7T-!osYV_@XdG2siiZtB~DoDRBNw90rE-o99Ty47g&8a_e#)^UBun;qr)nHr3ccDyeHLF zZ~EE%3-mQKwMOg1+U2ZhaB41=mrTZovrSD+43v$nQyqPY_mb$#;ML$K|#+t0Z@BsAOiihvp+S;}t`hTx6McR3R22KIL2nq-Y z2=wvUdkXWv6Pb$7o(o$aDdNrex#ASFxVSh3a&2*i(g50}Bn~-r+<&q9HJQ`uT)cxs z61I)P>(o=&AvuFm_Xi$qL+m%kNzTycvXPsX4e-%a6%g!8&88T@M{dmhllqDus+hb9A#zY;mr=wliHg!4vs$e z<)9IUyV*Cty!qa2E^1L1_~LA%Ohgh#i{*NH_yAUOb@X~7o5Z4(X90;gT)J(a1~}w6 z_rvVdi2l99O2ZP;s$9<)=tqNo38W{_D1EZSTtuHOLe1g~&a#7^d3bn?T6q1QiBQl| zRomwN@!(L$Y#SBC0#!AHMd-nJNhDdi9D;yXd~{cDoqj9+Kd<+I`By%$fnNlBcx-u< z>}z`Go68G3V(h!4-X2L%?Xmdv?OTxOdLq}wK(_(x$Cy5@23c{?@ilK)Eywj><+60Q zmAOn$dZ$Ue{SdNDA?otlk~Wz^CAbe2`of3|kWd8FT3>Z)g7;T#`uzEb^i*3dW3RcX zshUbOQTfUD@%J0i$WFd%so%HuZ{NCAq5WSSvah(L#6`=>%8E5Vq=@v?8{B0wg6lsF zIAuNAsrr*N2q)JBj-wd4O}kY~`$|hn{%|OdVa#0@M#jec7N`O+G+nyfh|9cY>>>ZE z`cC2>=hor^`#+s-x?gM=5BMzTRJT{SzopNBA;DS)2J%TqRIkDwi~STmws9jkaSNPL zo7qZH{rOLCgTXqT?SCp3|4+x?|99@{e;X?N z|8aUTFyrpFfGzmd(HkHRnOs_mxCK0V^r$0!5Dvw59G~NcmpDq^Q}TxT3Pl&daAqj><|{blv-B@8BFZ78o3gf|0CJ2Gnp5oqqI z?q~)TH^}2R_l2qpWWAmY#!xeV`upn}DR8_qAKw{rG6z!b>x1xyO30_yof~Nn zD%;wE`)2B#YA}Dla(ciA-?z!xVZ0XZuodWNu#E z*2V!+*X5r+#kg3OS5@^{y5^ZF1s(hj0!VhuEG%kT_Iqg8YyysCKJRhq7VgX@w;a40 z_}gzJ_C-Xsj?u#QnZjKD0y2>PhVSI$^aO}IV{sLgmA&VnHj!6I188ot?ga63FKa4xM~GNQ+ka36tByDX+P;*{-54)5s02^JVw6LU3!9tSn!Ld9c6fa3IGnG{SN!tL zMdQWKO^>R);CE188N6$JYEFM&flgW!(cF%k6dL^ zT>jYR?@fHHsflm!9Pj-&*iXFA3{PG@kh0(%cI# ze6R2!H@UE3E|u$S>AzQzH?%cmV6wj_av7}R>F@`)B0zN|OI|*}Uw-vQ!7YiM`DUL& zZ!a8742hlD21>Jxu1~WF#F?DOvGpUfiqClP#Q(Jrpedk;gp-r4 z|FsaudrM0Npi5CPlMXrA{R}C@V0e#?j`)flGLYY?X(51rj>GXkzcE|yl4xT^ZvA4^ zrN}{Kpx$>yE32r9W(MpIJKc9sz5F-ZzDRdz++3bg;IU$*TMtY%XOR9={cJ13RRUUb z^s(vrw-oM95O36aablAam_>Rl$$x)3K*>K7$iCj>^}ei(@}J)zm&Dr2=GcTBO(;ht|Aot~ESm7W2Oh95lpC(tgBR=maD1H64FIFjdEK6I?$?$fKn2Jh}l)(6gR zf!?u_xLY|sJKK8H^^&x5`jh22;{5TlUY2c&)!qvr(Msi20yC%NGe=U^=Fn@+i+=&M z|HdEraIsp@81hLe=|5%4{Hw_D^8l%um>E7fqklV-x|eK8-8)r`Dr$dG!1y1F6LZ4q gx03Pi#ro9e?ljp*;DAakSRM~N&@zNoYuHEqA2`lBvj6}9 literal 12002 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 diff --git a/js/id/ui/geolocate.js b/js/id/ui/geolocate.js index 2e5b48cca..803b0d49d 100644 --- a/js/id/ui/geolocate.js +++ b/js/id/ui/geolocate.js @@ -11,11 +11,12 @@ iD.ui.geolocate = function(map) { .attr('class', 'geolocate-control map-control') .append('button') .attr('title', 'Show My Location') - .text('G') .on('click', function() { navigator.geolocation.getCurrentPosition( success, error); - }); + }) + .append('span') + .attr('class','icon geolocate'); }; }; diff --git a/js/id/ui/layerswitcher.js b/js/id/ui/layerswitcher.js index 82f85f82b..31b34da46 100644 --- a/js/id/ui/layerswitcher.js +++ b/js/id/ui/layerswitcher.js @@ -33,7 +33,7 @@ iD.ui.layerswitcher = function(map) { var button = selection .append('button') - .attr('class', 'narrow') + .attr('class', 'fillD') .attr('title', 'Layer Settings') .html("") .on('click.layerswitcher-toggle', toggle); From 5279839ca4221b31d29644213496da4de63fc6dd Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Sat, 19 Jan 2013 08:21:22 -0800 Subject: [PATCH 20/39] Highway rendering test page Removing the top-level clip-rect to make this work; it doesn't seem necessary? --- js/id/renderer/map.js | 5 +-- js/id/svg/surface.js | 12 +---- test/rendering.html | 100 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+), 14 deletions(-) create mode 100644 test/rendering.html diff --git a/js/id/renderer/map.js b/js/id/renderer/map.js index 729d37936..e4cb0d02e 100644 --- a/js/id/renderer/map.js +++ b/js/id/renderer/map.js @@ -235,10 +235,7 @@ iD.Map = function() { map.size = function(_) { if (!arguments.length) return dimensions; dimensions = _; - surface - .size(dimensions) - .selectAll('#clip-rect') - .size(dimensions); + surface.size(dimensions); background.size(dimensions); return redraw(); }; diff --git a/js/id/svg/surface.js b/js/id/svg/surface.js index 9fb64ca0e..e9b1b36db 100644 --- a/js/id/svg/surface.js +++ b/js/id/svg/surface.js @@ -1,16 +1,8 @@ iD.svg.Surface = function() { return function drawSurface(selection) { - selection.append('defs') - .append('clipPath') - .attr('id', 'clip') - .append('rect') - .attr('id', 'clip-rect') - .attr({ x: 0, y: 0 }); + selection.append('defs'); - var clip = selection.append('g') - .attr('clip-path', 'url(#clip)'); - - var layers = clip.selectAll('.layer') + var layers = selection.selectAll('.layer') .data(['fill', 'casing', 'stroke', 'text', 'hit']); layers.enter().append('g') diff --git a/test/rendering.html b/test/rendering.html new file mode 100644 index 000000000..4250cd949 --- /dev/null +++ b/test/rendering.html @@ -0,0 +1,100 @@ + + + + + Rendering Tests + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Highways
z16z17
BaseHoverSelectedBaseHoverSelected
+ + + + From 0751dc4ba16a1e5990f4c62244226b590f8de40e Mon Sep 17 00:00:00 2001 From: Brandon Liu Date: Sat, 19 Jan 2013 11:07:56 -0800 Subject: [PATCH 21/39] Clean up dead code in inspector. --- js/id/ui/inspector.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/js/id/ui/inspector.js b/js/id/ui/inspector.js index 192066fda..56576a387 100644 --- a/js/id/ui/inspector.js +++ b/js/id/ui/inspector.js @@ -187,10 +187,6 @@ iD.ui.inspector = function() { } }); } - d3.event.preventDefault(); - }) - .attr('href', function(d) { - return 'http://taginfo.openstreetmap.org/keys/' + d.key; }); helpBtn.append('span') From 5ab7cbb643a2ba94a182de785530de813ec68b48 Mon Sep 17 00:00:00 2001 From: Brandon Liu Date: Sat, 19 Jan 2013 13:04:23 -0800 Subject: [PATCH 22/39] Fix opening tag help in Firefox. Remove anchor tag, attach click event to tag help button. --- js/id/ui/inspector.js | 89 +++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 46 deletions(-) diff --git a/js/id/ui/inspector.js b/js/id/ui/inspector.js index 56576a387..d42791ceb 100644 --- a/js/id/ui/inspector.js +++ b/js/id/ui/inspector.js @@ -141,53 +141,50 @@ iD.ui.inspector = function() { var helpBtn = row.append('button') .attr('tabindex', -1) .attr('class', 'tag-help minor') - .append('a') - .attr('tabindex', -1) - .attr('target', '_blank') - .on('click', function(d) { - var params = _.extend({}, d, { - geometry: entity.geometry() - }); - if (d.key && d.value) { - taginfo.docs(params, function(err, docs) { - var en = _.find(docs, function(d) { - return d.lang == 'en'; - }); - if (en) { - var types = []; - if (en.on_area) types.push('area'); - if (en.on_node) types.push('point'); - if (en.on_way) types.push('line'); - en.types = types; - iD.ui.modal() - .select('.content') - .datum(en) - .call(iD.ui.tagReference); - } else { - iD.ui.flash() - .select('.content') - .text('This is no documentation available for this tag combination'); - } - }); - } else if (d.key) { - taginfo.values(params, function(err, values) { - if (values.data.length) { - iD.ui.modal() - .select('.content') - .datum({ - data: values.data, - title: 'Key:' + params.key, - geometry: params.geometry - }) - .call(iD.keyReference); - } else { - iD.ui.flash() - .select('.content') - .text('This is no documentation available for this key'); - } - }); - } + .on('click', function(d) { + var params = _.extend({}, d, { + geometry: entity.geometry() }); + if (d.key && d.value) { + taginfo.docs(params, function(err, docs) { + var en = _.find(docs, function(d) { + return d.lang == 'en'; + }); + if (en) { + var types = []; + if (en.on_area) types.push('area'); + if (en.on_node) types.push('point'); + if (en.on_way) types.push('line'); + en.types = types; + iD.ui.modal() + .select('.content') + .datum(en) + .call(iD.ui.tagReference); + } else { + iD.ui.flash() + .select('.content') + .text('This is no documentation available for this tag combination'); + } + }); + } else if (d.key) { + taginfo.values(params, function(err, values) { + if (values.data.length) { + iD.ui.modal() + .select('.content') + .datum({ + data: values.data, + title: 'Key:' + params.key, + geometry: params.geometry + }) + .call(iD.keyReference); + } else { + iD.ui.flash() + .select('.content') + .text('This is no documentation available for this key'); + } + }); + } + }); helpBtn.append('span') .attr('class', 'icon inspect'); From e5407fa49d1a44128316a32234e51776e20c6176 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Sat, 19 Jan 2013 18:00:06 -0800 Subject: [PATCH 23/39] Improve highway rendering; render halo in a separate layer --- css/map.css | 116 +++++++++++++++++++++++-------------------- js/id/svg/lines.js | 4 +- js/id/svg/surface.js | 2 +- test/rendering.html | 4 +- 4 files changed, 67 insertions(+), 59 deletions(-) diff --git a/css/map.css b/css/map.css index 479ca6454..6c8e2b3b8 100644 --- a/css/map.css +++ b/css/map.css @@ -45,22 +45,6 @@ svg[data-zoom="17"] g.vertex circle.fill { transform:scale(0.7, 0.7); } -path.casing.tag-highway { - stroke-width:10; -} - -path.stroke.tag-highway { - stroke-width:8; -} - -svg[data-zoom="16"] path.casing.tag-highway { - stroke-width:6; -} - -svg[data-zoom="16"] path.stroke.tag-highway { - stroke-width:4; -} - g.vertex circle.stroke { fill:#333; } @@ -104,32 +88,31 @@ circle.teaser-point { fill:#D3F5FF; } -path.casing { - stroke: #111; - stroke-linecap:round; - stroke-linejoin:bevel; - stroke-width: 3; - -webkit-transition: stroke 100ms linear; -} - -path.casing.hover { - stroke:#FF0F0F !important; - stroke-opacity:0.8; -} - -path.casing.selected { - stroke:#E96666 !important; - stroke-opacity:1 !important; - stroke-width:10 !important; +path.line { + stroke-linecap: round; + stroke-linejoin: bevel; } path.stroke { - stroke: #555; - stroke-linecap:round; - stroke-linejoin:bevel; + stroke: #222; stroke-width: 2; } +path.shadow { + stroke-width: 10; + -webkit-transition: stroke 100ms linear; +} + +path.shadow.hover { + stroke: #E96666; + stroke-opacity: 0.3; +} + +path.shadow.selected { + stroke: #E96666; + stroke-opacity: 0.7; +} + path.stroke.tag-railway-rail { stroke: white; stroke-width: 3; @@ -206,6 +189,26 @@ path.multipolygon.tag-amenity-parking { } /* highways */ +path.shadow.tag-highway { + stroke-width:16; +} +path.casing.tag-highway { + stroke-width:10; +} +path.stroke.tag-highway { + stroke-width:8; +} + +svg[data-zoom="16"] path.shadow.tag-highway { + stroke-width:12; +} +svg[data-zoom="16"] path.casing.tag-highway { + stroke-width:6; +} +svg[data-zoom="16"] path.stroke.tag-highway { + stroke-width:4; +} + path.stroke.tag-highway-residential { stroke:#fff; } @@ -213,33 +216,29 @@ path.casing.tag-highway-residential { stroke:#444; } -path.stroke.tag-highway-unclassified, -path.stroke.tag-highway-tertiary, -path.stroke.tag-highway-tertiary_link { - stroke:#FEFECB; -} - -path.casing.tag-highway-unclassified, -path.casing.tag-highway-tertiary, -path.casing.tag-highway-tertiary_link { } - path.stroke.tag-highway-service { stroke:#fff; stroke-width:6; } path.casing.tag-highway-service { + stroke:#666; stroke-width:8; } +path.stroke.tag-highway-path, path.stroke.tag-highway-footway, path.stroke.tag-highway-cycleway, +path.stroke.tag-highway-bridleway, path.stroke.tag-highway-steps { stroke: #ff6257; stroke-width: 4; + stroke-linecap: butt; stroke-dasharray: 6, 6; } +path.casing.tag-highway-path, path.casing.tag-highway-footway, path.casing.tag-highway-cycleway, +path.casing.tag-highway-bridleway, path.casing.tag-highway-steps { stroke-width: 6; stroke: #fff; @@ -247,22 +246,20 @@ path.casing.tag-highway-steps { path.stroke.tag-highway-motorway, path.stroke.tag-highway-motorway_link { - stroke:#809BC0; + stroke:#809bc0; } path.casing.tag-highway-motorway, path.casing.tag-highway-motorway_link { - stroke:#809BC0; - stroke-opacity:0.4; + stroke:#506077; } path.stroke.tag-highway-trunk, path.stroke.tag-highway-trunk_link { - stroke-opacity:0.4; - stroke:#7FC97F; + stroke:#97d397; } path.casing.tag-highway-trunk, path.casing.tag-highway-trunk_link { - stroke:#7FC97F; + stroke:#477147; } path.stroke.tag-highway-primary, @@ -271,16 +268,25 @@ path.stroke.tag-highway-primary_link { } path.casing.tag-highway-primary, path.casing.tag-highway-primary_link { - stroke:#681212; + stroke:#8d4346; } path.stroke.tag-highway-secondary, path.stroke.tag-highway-secondary_link { - stroke:#FDBF6F; + stroke:#fecc8b; } path.casing.tag-highway-secondary, path.casing.tag-highway-secondary_link { - stroke:#444; + stroke:#a37b48; +} + +path.stroke.tag-highway-tertiary, +path.stroke.tag-highway-tertiary_link { + stroke:#ffffb3; +} +path.casing.tag-highway-tertiary, +path.casing.tag-highway-tertiary_link { + stroke:#bbb; } path.casing.tag-bridge-yes { diff --git a/js/id/svg/lines.js b/js/id/svg/lines.js index 375a88f05..e3563bae9 100644 --- a/js/id/svg/lines.js +++ b/js/id/svg/lines.js @@ -75,10 +75,12 @@ iD.svg.Lines = function(projection) { var lineString = iD.svg.LineString(projection); - var casing = surface.select('.layer-casing'), + var shadow = surface.select('.layer-shadow'), + casing = surface.select('.layer-casing'), stroke = surface.select('.layer-stroke'), defs = surface.select('defs'), text = surface.select('.layer-text'), + shadows = drawPaths(shadow, lines, filter, 'way line shadow', lineString), casings = drawPaths(casing, lines, filter, 'way line casing', lineString), strokes = drawPaths(stroke, lines, filter, 'way line stroke', lineString); diff --git a/js/id/svg/surface.js b/js/id/svg/surface.js index e9b1b36db..57b981dc5 100644 --- a/js/id/svg/surface.js +++ b/js/id/svg/surface.js @@ -3,7 +3,7 @@ iD.svg.Surface = function() { selection.append('defs'); var layers = selection.selectAll('.layer') - .data(['fill', 'casing', 'stroke', 'text', 'hit']); + .data(['shadow', 'fill', 'casing', 'stroke', 'text', 'hit']); layers.enter().append('g') .attr('class', function(d) { return 'layer layer-' + d; }); diff --git a/test/rendering.html b/test/rendering.html index 4250cd949..948f4593f 100644 --- a/test/rendering.html +++ b/test/rendering.html @@ -48,7 +48,7 @@ var zooms = [16, 17], modes = ['base', 'hover', 'selected'], highways = [ - 'motorway', 'trunk', 'primary', 'secondary', 'tertiary', 'residential', + '', 'motorway', 'trunk', 'primary', 'secondary', 'tertiary', 'residential', 'service', 'track', 'road', 'unclassified', 'living_street', 'pedestrian', 'path', 'footway', 'cycleway', 'bridleway', 'steps', 'proposed', 'construction']; @@ -84,7 +84,7 @@ .attr('data-zoom', function (d) { return d.zoom; }) .call(iD.svg.Surface()) .each(function (d) { - var highway = way.update({tags: {highway: d.tag}}), + var highway = way.update({tags: d.tag ? {highway: d.tag} : {}}), graph = iD.Graph([a, b, highway]); d3.select(this) From 28cea97019dd6ca0d02002c60e3d273bd02b72b4 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Sat, 19 Jan 2013 21:12:53 -0500 Subject: [PATCH 24/39] fix regression, rename Apply to Close in inspector --- js/id/ui/inspector.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/id/ui/inspector.js b/js/id/ui/inspector.js index d42791ceb..ffcf163d2 100644 --- a/js/id/ui/inspector.js +++ b/js/id/ui/inspector.js @@ -82,7 +82,7 @@ iD.ui.inspector = function() { .on('click', apply); inspectorButton1.append('span').attr('class','icon icon-pre-text apply'); - inspectorButton1.append('span').attr('class','label').text('Apply'); + inspectorButton1.append('span').attr('class','label').text('Close'); var inspectorButton2 = selection.append('button') .attr('class', 'delete col6 action') From 79801e57afcdf03e47014204146f9f06d0150ab8 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Sat, 19 Jan 2013 21:04:39 -0800 Subject: [PATCH 25/39] More highway rendering improvements --- css/map.css | 139 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 104 insertions(+), 35 deletions(-) diff --git a/css/map.css b/css/map.css index 6c8e2b3b8..20d2d8f8f 100644 --- a/css/map.css +++ b/css/map.css @@ -98,6 +98,11 @@ path.stroke { stroke-width: 2; } +path.stroke, +path.casing { + shape-rendering: crispEdges; +} + path.shadow { stroke-width: 10; -webkit-transition: stroke 100ms linear; @@ -189,13 +194,16 @@ path.multipolygon.tag-amenity-parking { } /* highways */ + path.shadow.tag-highway { stroke-width:16; } path.casing.tag-highway { + stroke:#444; stroke-width:10; } path.stroke.tag-highway { + stroke:#ccc; stroke-width:8; } @@ -209,41 +217,6 @@ svg[data-zoom="16"] path.stroke.tag-highway { stroke-width:4; } -path.stroke.tag-highway-residential { - stroke:#fff; -} -path.casing.tag-highway-residential { - stroke:#444; -} - -path.stroke.tag-highway-service { - stroke:#fff; - stroke-width:6; -} -path.casing.tag-highway-service { - stroke:#666; - stroke-width:8; -} - -path.stroke.tag-highway-path, -path.stroke.tag-highway-footway, -path.stroke.tag-highway-cycleway, -path.stroke.tag-highway-bridleway, -path.stroke.tag-highway-steps { - stroke: #ff6257; - stroke-width: 4; - stroke-linecap: butt; - stroke-dasharray: 6, 6; -} -path.casing.tag-highway-path, -path.casing.tag-highway-footway, -path.casing.tag-highway-cycleway, -path.casing.tag-highway-bridleway, -path.casing.tag-highway-steps { - stroke-width: 6; - stroke: #fff; -} - path.stroke.tag-highway-motorway, path.stroke.tag-highway-motorway_link { stroke:#809bc0; @@ -289,6 +262,102 @@ path.casing.tag-highway-tertiary_link { stroke:#bbb; } +path.stroke.tag-highway-residential { + stroke:#fff; +} +path.casing.tag-highway-residential { + stroke:#444; +} + +path.stroke.tag-highway-service { + stroke:#fff; + stroke-width:4; +} +path.casing.tag-highway-service { + stroke:#666; + stroke-width:6; +} +svg[data-zoom="16"] path.stroke.tag-highway-service { + stroke-width:2; +} +svg[data-zoom="16"] path.casing.tag-highway-service { + stroke-width:4; +} + +path.stroke.tag-highway-track { + stroke: #fff; + stroke-width: 4; +} +path.casing.tag-highway-track { + stroke: #996600; + stroke-width: 6; + stroke-linecap: butt; + stroke-dasharray: 6, 6; +} +svg[data-zoom="16"] path.stroke.tag-highway-track { + stroke-width:2; +} +svg[data-zoom="16"] path.casing.tag-highway-track { + stroke-width:4; +} + +path.stroke.tag-highway-path { + stroke: #000; + stroke-width: 1 !important; + stroke-linecap: butt; + stroke-dasharray: 12, 6; +} +path.casing.tag-highway-path { + stroke-width: 3 !important; + stroke: #fff; +} + +path.stroke.tag-highway-footway, +path.stroke.tag-highway-cycleway, +path.stroke.tag-highway-bridleway { + stroke-width: 4; + stroke-linecap: butt; + stroke-dasharray: 6, 6; +} +path.casing.tag-highway-footway, +path.casing.tag-highway-cycleway, +path.casing.tag-highway-bridleway { + stroke-width: 6; + stroke: #fff; +} + +svg[data-zoom="16"] path.stroke.tag-highway-footway, +svg[data-zoom="16"] path.stroke.tag-highway-cycleway, +svg[data-zoom="16"] path.stroke.tag-highway-bridleway { + stroke-width: 2; +} +svg[data-zoom="16"] path.casing.tag-highway-footway, +svg[data-zoom="16"] path.casing.tag-highway-cycleway, +svg[data-zoom="16"] path.casing.tag-highway-bridleway { + stroke-width: 4; +} + +path.stroke.tag-highway-footway { + stroke: #996600; +} +path.stroke.tag-highway-cycleway { + stroke: #69f; +} +path.stroke.tag-highway-bridleway { + stroke: green; +} + +path.stroke.tag-highway-steps { + stroke: #ff6257; + stroke-width: 4; + stroke-linecap: butt; + stroke-dasharray: 3, 3; +} +path.casing.tag-highway-steps { + stroke-width: 6; + stroke: #fff; +} + path.casing.tag-bridge-yes { stroke-width: 14; stroke: #000; From 59d37125df545e9a26b0b7c45d9c81ca82475ab0 Mon Sep 17 00:00:00 2001 From: Brandon Liu Date: Sat, 19 Jan 2013 22:54:09 -0800 Subject: [PATCH 26/39] make notice not a global var. --- js/id/id.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/id/id.js b/js/id/id.js index ff85a68d4..ae9cadaa3 100644 --- a/js/id/id.js +++ b/js/id/id.js @@ -50,7 +50,7 @@ window.iD = function(container) { } } - notice = iD.ui.notice(limiter + var notice = iD.ui.notice(limiter .append('div') .attr('class', 'notice')); From 3b722ed5030f6e814b1ca3887e1bbefb5614770e Mon Sep 17 00:00:00 2001 From: Brandon Liu Date: Sat, 19 Jan 2013 22:57:37 -0800 Subject: [PATCH 27/39] Properly refer to iD.ui.confirm --- js/id/ui/save.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/id/ui/save.js b/js/id/ui/save.js index e711e4bde..821cc96e8 100644 --- a/js/id/ui/save.js +++ b/js/id/ui/save.js @@ -22,7 +22,7 @@ iD.ui.save = function() { history.reset(); map.flush().redraw(); if (err) { - var desc = iD.confirm() + var desc = iD.ui.confirm() .select('.description'); desc.append('h2') .text('An error occurred while trying to save'); @@ -68,7 +68,7 @@ iD.ui.save = function() { .on('save', commit)); }); } else { - iD.confirm().select('.description') + iD.ui.confirm().select('.description') .append('h3').text('You don\'t have any changes to save.'); } }); From d83ec7f1eb4862b58b62022da76d9d809c3996ac Mon Sep 17 00:00:00 2001 From: Brandon Liu Date: Sat, 19 Jan 2013 22:29:11 -0800 Subject: [PATCH 28/39] Create method history.hasChanges --- js/id/graph/history.js | 6 ++++++ test/spec/graph/history.js | 12 ++++++++++++ 2 files changed, 18 insertions(+) diff --git a/js/id/graph/history.js b/js/id/graph/history.js index e31fa5ef9..bf7cdfc88 100644 --- a/js/id/graph/history.js +++ b/js/id/graph/history.js @@ -109,6 +109,12 @@ iD.History = function() { }; }, + hasChanges: function() { + return !!d3.sum(d3.values(this.changes()).map(function(c) { + return c.length; + }));; + }, + imagery_used: function(source) { if (source) imagery_used = source; else return _.without( diff --git a/test/spec/graph/history.js b/test/spec/graph/history.js index 15fe10964..c3fa536f1 100644 --- a/test/spec/graph/history.js +++ b/test/spec/graph/history.js @@ -126,6 +126,18 @@ describe("iD.History", function () { }); }); + describe("#hasChanges", function() { + it("is true when any of change's values are nonempty", function() { + var node = iD.Node(); + history.perform(function (graph) { return graph.replace(node); }); + expect(history.hasChanges()).to.eql(true); + }); + + it("is false when any of change's values are empty", function() { + expect(history.hasChanges()).to.eql(false); + }); + }); + describe("#reset", function () { it("clears the version stack", function () { history.perform(action, "annotation"); From ded802049abeda14acd1b4657595f14820489dcf Mon Sep 17 00:00:00 2001 From: Brandon Liu Date: Sat, 19 Jan 2013 22:53:00 -0800 Subject: [PATCH 29/39] add history.numChanges method. Use hasChanges/numChanges to toggle Save button and show confirmation dialog when navigating away from page. --- js/id/graph/history.js | 8 ++++++-- js/id/id.js | 8 +------- js/id/ui/save.js | 17 +++++------------ test/spec/graph/history.js | 18 +++++++++++++++++- 4 files changed, 29 insertions(+), 22 deletions(-) diff --git a/js/id/graph/history.js b/js/id/graph/history.js index bf7cdfc88..3d027d042 100644 --- a/js/id/graph/history.js +++ b/js/id/graph/history.js @@ -110,9 +110,13 @@ iD.History = function() { }, hasChanges: function() { - return !!d3.sum(d3.values(this.changes()).map(function(c) { + return !!this.numChanges(); + }, + + numChanges: function() { + return d3.sum(d3.values(this.changes()).map(function(c) { return c.length; - }));; + })); }, imagery_used: function(source) { diff --git a/js/id/id.js b/js/id/id.js index ae9cadaa3..7a6fc6665 100644 --- a/js/id/id.js +++ b/js/id/id.js @@ -98,13 +98,7 @@ window.iD = function(container) { .call(iD.ui.save().map(map).controller(controller)); history.on('change.warn-unload', function() { - var changes = history.changes(), - - has_changes = !!d3.sum(d3.values(changes).map(function(c) { - return c.length; - })); - - window.onbeforeunload = has_changes ? function() { + window.onbeforeunload = history.hasChanges() ? function() { return 'You have unsaved changes.'; } : null; }); diff --git a/js/id/ui/save.js b/js/id/ui/save.js index 821cc96e8..afaab5023 100644 --- a/js/id/ui/save.js +++ b/js/id/ui/save.js @@ -42,12 +42,8 @@ iD.ui.save = function() { } }); } - var changes = history.changes(); - var has_changes = d3.sum(d3.values(changes).map(function(c) { - return c.length; - })) > 0; - if (has_changes) { + if (history.hasChanges()) { connection.authenticate(function(err) { var modal = iD.ui.modal(); var changes = history.changes(); @@ -77,16 +73,13 @@ iD.ui.save = function() { .attr('class', 'count'); history.on('change.save-button', function() { - var changes = history.changes(), - num_changes = d3.sum(d3.values(changes).map(function(c) { - return c.length; - })); + var hasChanges = history.hasChanges(); selection - .property('disabled', num_changes === 0) - .classed('has-count', num_changes > 0) + .property('disabled', !hasChanges) + .classed('has-count', hasChanges) .select('span.count') - .text(num_changes); + .text(history.numChanges()); }); } diff --git a/test/spec/graph/history.js b/test/spec/graph/history.js index c3fa536f1..554b22a82 100644 --- a/test/spec/graph/history.js +++ b/test/spec/graph/history.js @@ -133,11 +133,27 @@ describe("iD.History", function () { expect(history.hasChanges()).to.eql(true); }); - it("is false when any of change's values are empty", function() { + it("is false when all of change's values are empty", function() { expect(history.hasChanges()).to.eql(false); }); }); + describe("#numChanges", function() { + it("is 0 when there are no changes", function() { + expect(history.numChanges()).to.eql(0); + }); + + it("is the sum of all types of changes", function() { + var node1 = iD.Node({id: "n1"}), + node2 = iD.Node(); + history.merge(iD.Graph([node1])); + history.perform(function (graph) { return graph.remove(node1); }); + expect(history.numChanges()).to.eql(1); + history.perform(function (graph) { return graph.replace(node2); }); + expect(history.numChanges()).to.eql(2); + }); + }); + describe("#reset", function () { it("clears the version stack", function () { history.perform(action, "annotation"); From 33b1f4f23cea8aa2b3f5a51d11bc46a2d86c1b09 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Sun, 20 Jan 2013 09:39:01 -0800 Subject: [PATCH 30/39] Render more line features --- css/map.css | 181 +++++++++++++++++++++++++++++++++------ js/id/svg/tag_classes.js | 6 +- test/rendering.html | 45 ++++++++-- 3 files changed, 193 insertions(+), 39 deletions(-) diff --git a/css/map.css b/css/map.css index 20d2d8f8f..a5259d909 100644 --- a/css/map.css +++ b/css/map.css @@ -100,10 +100,11 @@ path.stroke { path.stroke, path.casing { - shape-rendering: crispEdges; + shape-rendering: optimizeSpeed; } path.shadow { + pointer-events: stroke; stroke-width: 10; -webkit-transition: stroke 100ms linear; } @@ -118,18 +119,6 @@ path.shadow.selected { stroke-opacity: 0.7; } -path.stroke.tag-railway-rail { - stroke: white; - stroke-width: 3; - stroke-dasharray: 12,12; -} - -path.stroke.tag-railway-subway { - stroke: #444; - stroke-width: 3; - stroke-dasharray: 8,8; -} - path.area, path.multipolygon { stroke-width:2; @@ -218,57 +207,98 @@ svg[data-zoom="16"] path.stroke.tag-highway { } path.stroke.tag-highway-motorway, -path.stroke.tag-highway-motorway_link { +path.stroke.tag-highway-motorway_link, +path.stroke.tag-construction-motorway { stroke:#809bc0; } path.casing.tag-highway-motorway, -path.casing.tag-highway-motorway_link { +path.casing.tag-highway-motorway_link, +path.casing.tag-construction-motorway { stroke:#506077; } path.stroke.tag-highway-trunk, -path.stroke.tag-highway-trunk_link { +path.stroke.tag-highway-trunk_link, +path.stroke.tag-construction-trunk { stroke:#97d397; } path.casing.tag-highway-trunk, -path.casing.tag-highway-trunk_link { +path.casing.tag-highway-trunk_link, +path.casing.tag-construction-trunk { stroke:#477147; } path.stroke.tag-highway-primary, -path.stroke.tag-highway-primary_link { +path.stroke.tag-highway-primary_link, +path.stroke.tag-construction-primary { stroke:#ec989a; } path.casing.tag-highway-primary, -path.casing.tag-highway-primary_link { +path.casing.tag-highway-primary_link, +path.casing.tag-construction-primary { stroke:#8d4346; } path.stroke.tag-highway-secondary, -path.stroke.tag-highway-secondary_link { +path.stroke.tag-highway-secondary_link, +path.stroke.tag-construction-secondary { stroke:#fecc8b; } path.casing.tag-highway-secondary, -path.casing.tag-highway-secondary_link { +path.casing.tag-highway-secondary_link, +path.casing.tag-construction-secondary { stroke:#a37b48; } path.stroke.tag-highway-tertiary, -path.stroke.tag-highway-tertiary_link { +path.stroke.tag-highway-tertiary_link, +path.stroke.tag-construction-tertiary { stroke:#ffffb3; } path.casing.tag-highway-tertiary, -path.casing.tag-highway-tertiary_link { +path.casing.tag-highway-tertiary_link, +path.casing.tag-construction-tertiary { stroke:#bbb; } -path.stroke.tag-highway-residential { +path.stroke.tag-highway-unclassified, +path.stroke.tag-construction-unclassified { + stroke:#eaeaea; +} +path.casing.tag-highway-unclassified, +path.casing.tag-construction-unclassified { + stroke:#444; +} + +path.stroke.tag-highway-residential, +path.stroke.tag-construction-residential { stroke:#fff; } -path.casing.tag-highway-residential { +path.casing.tag-highway-residential, +path.casing.tag-construction-residential { stroke:#444; } +path.stroke.tag-highway-living_street { + stroke:#ccc; + stroke-width:4; +} +path.casing.tag-highway-living_street { + stroke:#fff; + stroke-width:6; +} + +path.stroke.tag-highway-pedestrian { + stroke:#fff; + stroke-dasharray: 2, 8; + stroke-width:4 !important; + shapeRendering: auto; +} +path.casing.tag-highway-pedestrian { + stroke:#84C382; + stroke-width:6 !important; +} + path.stroke.tag-highway-service { stroke:#fff; stroke-width:4; @@ -305,10 +335,10 @@ path.stroke.tag-highway-path { stroke: #000; stroke-width: 1 !important; stroke-linecap: butt; - stroke-dasharray: 12, 6; + stroke-dasharray: 8, 4; } path.casing.tag-highway-path { - stroke-width: 3 !important; + stroke-width: 1 !important; stroke: #fff; } @@ -363,11 +393,108 @@ path.casing.tag-bridge-yes { stroke: #000; } +path.stroke.tag-highway-construction, +path.casing.tag-highway-construction { + stroke-linecap: butt; + stroke-dasharray: 7, 7; +} + +svg[data-zoom="16"] path.stroke.tag-highway-construction, +svg[data-zoom="16"] path.casing.tag-highway-construction { + stroke-linecap: butt; + stroke-dasharray: 5, 5; +} + +/* railways */ + +path.stroke.tag-railway { + stroke: #eee; + stroke-width: 2; + stroke-linecap: butt; + stroke-dasharray: 12,12; +} +path.casing.tag-railway { + stroke: #555; + stroke-width: 4; +} + +path.stroke.tag-railway-abandoned { + stroke: #eee; +} +path.casing.tag-railway-abandoned { + stroke: #999; +} + +path.stroke.tag-railway-subway { + stroke: #666; +} +path.casing.tag-railway-subway { + stroke: #222; +} + +/* waterways */ + path.stroke.tag-waterway { stroke: #10539a; + stroke-width: 2; +} +path.casing.tag-waterway { + stroke: #6AA2FF; + stroke-width: 4; +} + +path.stroke.tag-waterway-river { + stroke-width: 4; +} +path.casing.tag-waterway-river { + stroke-width: 6; +} + +svg[data-zoom="16"] path.stroke.tag-waterway-river { + stroke-width: 4; +} +svg[data-zoom="16"] path.casing.tag-waterway-river { + stroke-width: 6; +} + +path.stroke.tag-waterway-ditch { + stroke: #10539a; + stroke-width: 1; +} +path.casing.tag-waterway-ditch { + stroke: #999692; stroke-width: 3; } +/* power */ + +path.stroke.tag-power { + stroke: #939393; + stroke-width: 2; +} +path.casing.tag-power { + stroke: none; +} + +/* boundary */ + +path.stroke.tag-boundary { + stroke: #fff; + stroke-width: 2; + stroke-linecap: butt; + stroke-dasharray: 20, 5, 5, 5; +} +path.casing.tag-boundary { + stroke: #82B5FE; + stroke-width: 6; +} + +path.casing.tag-boundary-protected_area, +path.casing.tag-boundary-national_park { + stroke: #4D9849; +} + + text { font-size:10px; pointer-events: none; diff --git a/js/id/svg/tag_classes.js b/js/id/svg/tag_classes.js index a7660e1f5..5ce585add 100644 --- a/js/id/svg/tag_classes.js +++ b/js/id/svg/tag_classes.js @@ -1,8 +1,8 @@ iD.svg.TagClasses = function() { var keys = iD.util.trueObj([ - 'highway', 'railway', 'motorway', 'amenity', 'natural', - 'landuse', 'building', 'oneway', 'bridge', 'boundary', - 'leisure' + 'highway', 'railway', 'waterway', 'power', 'motorway', 'amenity', + 'natural', 'landuse', 'building', 'oneway', 'bridge', 'boundary', + 'leisure', 'construction' ]), tagClassRe = /^tag-/; return function tagClassesSelection(selection) { diff --git a/test/rendering.html b/test/rendering.html index 948f4593f..ebefeaa4a 100644 --- a/test/rendering.html +++ b/test/rendering.html @@ -36,7 +36,6 @@ - @@ -47,17 +46,45 @@
Highways
z16z17
BaseHoverSelectedBaseHoverSelected