From 6ae683dedc086a7c512d2ad74dcd912ac9a92cde Mon Sep 17 00:00:00 2001 From: Tom MacWright Date: Mon, 28 Jan 2013 16:18:49 -0500 Subject: [PATCH 01/48] Hints for keybindings. Refs #517 --- css/app.css | 11 +++++++++++ js/id/id.js | 24 +++++++++++++++--------- js/id/modes/add_area.js | 3 ++- js/id/modes/add_line.js | 3 ++- js/id/modes/add_point.js | 3 ++- js/id/modes/browse.js | 3 ++- 6 files changed, 34 insertions(+), 13 deletions(-) diff --git a/css/app.css b/css/app.css index e83c7152f..19d6660cd 100644 --- a/css/app.css +++ b/css/app.css @@ -1110,6 +1110,17 @@ div.typeahead a:first-child { left: 30px; } +.tooltip .keyhint { + float: right; + background: #eee; + font-size: 10px; + padding: 0 4px; + background:#aaa; + color:#fff; + border-radius: 2px; + margin-left: 4px; +} + .tail { pointer-events:none; position: absolute; diff --git a/js/id/id.js b/js/id/id.js index 770cbde43..ab6dd37f2 100644 --- a/js/id/id.js +++ b/js/id/id.js @@ -21,6 +21,10 @@ window.iD = function(container) { return; } + function hintprefix(x, y) { + return '' + x + ' ' + y; + } + var m = container.append('div') .attr('id', 'map') .call(map); @@ -40,8 +44,10 @@ window.iD = function(container) { .enter().append('button') .attr('tabindex', -1) .attr('class', function (mode) { return mode.title + ' add-button col3'; }) - .attr('data-original-title', function (mode) { return mode.description; }) - .call(bootstrap.tooltip().placement('bottom')) + .attr('data-original-title', function (mode) { + return hintprefix(mode.key, mode.description); + }) + .call(bootstrap.tooltip().placement('bottom').html(true)) .on('click.editor', function (mode) { controller.enter(mode); }); function disableTooHigh() { @@ -82,7 +88,7 @@ window.iD = function(container) { var undo_buttons = limiter.append('div') .attr('class', 'button-wrap joined col1'), - undo_tooltip = bootstrap.tooltip().placement('bottom'); + undo_tooltip = bootstrap.tooltip().placement('bottom').html(true); undo_buttons.append('button') .attr({ id: 'undo', 'class': 'col6' }) @@ -201,12 +207,12 @@ window.iD = function(container) { limiter.select('#undo') .property('disabled', !undo) - .attr('data-original-title', undo) + .attr('data-original-title', hintprefix('⌘Z', undo)) .call(refreshTooltip); limiter.select('#redo') .property('disabled', !redo) - .attr('data-original-title', redo) + .attr('data-original-title', hintprefix('⌘⇧Z', redo)) .call(refreshTooltip); }); @@ -215,16 +221,16 @@ window.iD = function(container) { }); var keybinding = d3.keybinding('main') - .on('M', function() { if (map.editable()) controller.enter(iD.modes.Browse()); }) - .on('P', function() { if (map.editable()) controller.enter(iD.modes.AddPoint()); }) - .on('L', function() { if (map.editable()) controller.enter(iD.modes.AddLine()); }) - .on('A', function() { if (map.editable()) controller.enter(iD.modes.AddArea()); }) .on('⌘+Z', function() { history.undo(); }) .on('⌃+Z', function() { history.undo(); }) .on('⌘+⇧+Z', function() { history.redo(); }) .on('⌃+⇧+Z', function() { history.redo(); }) .on('⌫', function() { d3.event.preventDefault(); }); + [iD.modes.Browse(), iD.modes.AddPoint(), iD.modes.AddLine(), iD.modes.AddArea()].forEach(function(m) { + keybinding.on(m.key, function() { if (map.editable()) controller.enter(m); }); + }); + d3.select(document) .call(keybinding); diff --git a/js/id/modes/add_area.js b/js/id/modes/add_area.js index e00031723..cbfdffbd0 100644 --- a/js/id/modes/add_area.js +++ b/js/id/modes/add_area.js @@ -3,7 +3,8 @@ iD.modes.AddArea = function() { id: 'add-area', button: 'area', title: 'Area', - description: 'Add parks, buildings, lakes, or other areas to the map.' + description: 'Add parks, buildings, lakes, or other areas to the map.', + key: 'a' }; var behavior, diff --git a/js/id/modes/add_line.js b/js/id/modes/add_line.js index ad446a0f0..f9d52a9a0 100644 --- a/js/id/modes/add_line.js +++ b/js/id/modes/add_line.js @@ -3,7 +3,8 @@ iD.modes.AddLine = function() { id: 'add-line', button: 'line', title: 'Line', - description: 'Lines can be highways, streets, pedestrian paths, or even canals.' + description: 'Lines can be highways, streets, pedestrian paths, or even canals.', + key: 'l' }; var behavior, diff --git a/js/id/modes/add_point.js b/js/id/modes/add_point.js index 89f7aa536..1a51c314d 100644 --- a/js/id/modes/add_point.js +++ b/js/id/modes/add_point.js @@ -2,7 +2,8 @@ iD.modes.AddPoint = function() { var mode = { id: 'add-point', title: 'Point', - description: 'Restaurants, monuments, and postal boxes are points.' + description: 'Restaurants, monuments, and postal boxes are points.', + key: 'p' }; var behavior; diff --git a/js/id/modes/browse.js b/js/id/modes/browse.js index 4b2ea448f..90726b6bc 100644 --- a/js/id/modes/browse.js +++ b/js/id/modes/browse.js @@ -3,7 +3,8 @@ iD.modes.Browse = function() { button: 'browse', id: 'browse', title: 'Move', - description: 'Pan and zoom the map' + description: 'Pan and zoom the map', + key: 'b' }; var behaviors; From 73fd21fefb088b19ed65e4b1da8d9d08252a4d38 Mon Sep 17 00:00:00 2001 From: Tom MacWright Date: Mon, 28 Jan 2013 16:25:54 -0500 Subject: [PATCH 02/48] Replace gray dot with marker icon. Fixes #474 --- icons/unknown.png | Bin 278 -> 1476 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/icons/unknown.png b/icons/unknown.png index a47dd947dd41e3f45ba73b52034bd90abdd3c23d..404602aa4de44786ef78c6551f51c3e23a3ec3da 100644 GIT binary patch literal 1476 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#X$M%Ak65bF}s3+fyE>< zB%&n3*T*V3KUXg?B|j-uuOhbqsG5Pnrosxy%uOvxRH(?!$t$+1uvG%9umZ9{!um=I zU?nBlwn`Dc0SeCfMX3s=dWL#NN_Jcd3JNwwDQQ+gE^bimK%T8qMoCG5mA-y?dAVM> zv0i>ry1t>MrKP@sk-m|UE>MMTab;dfVufyAu`tKo-FP)SbBnaEtPap}qq8Pro9uK;KZ$Kp$>0P@@gdk5<0FM2bZyT0xdlb3#l;|NOrh$L#n9CwYzfWFEP=ZWO&DEQ z1VY{p&2h+5P;FET_|%F_903oK!3=nis1-PUM7U(;rsjb|#n8+~AFBkCC&BX0`8oMT z!3BxQsdi?jrpCa~L>ETa0k$dwEs=+y_)3i1SltFNa%`2Fun>D}<9SD1g#C<>qU z)av}_{MqZ@_;)ON!5hJ|aR%QF)*CvWlcr`W@l*NrrP+B7@W4v%HFamrI&$L|i{Iz45v8$bT8BvmJYEg;$@?_^@=V5Pw#uY>3ai-4;iV@a2?qh#&dz>sguq|97Sr jmh8KA%Ta#k>hJu2F7G+w=fBYeRL*+3`njxgN@xNAqdD_9 delta 231 zcmV}LP=Bz2nYy#2xN$nAs2rD8FWQhbW?9;ba!ELWdL_~cP?pe zYja~^aAhuUa%Y?FJQ@H10Fy~XK~y-6)svwPgFp~OA5E*Mz(Imo$^U;2as)|n2v9XO zYxW8U2^c0>vpX|4xxFhSaR!f5>MIPMYfUqI12s^3YXL?{^KJq&Yk&@@fR|SVbUxcQ z@RLv5Oybr#n+fWSc$JeHl~_SXOa002ovPDHLkV1l>YTL=IE From 7ffda8c7d32a3bd83afb756e9fefad8b433780bb Mon Sep 17 00:00:00 2001 From: Tom MacWright Date: Mon, 28 Jan 2013 16:31:57 -0500 Subject: [PATCH 03/48] Use nicer transitions on buttons like layerswitcher and geocoder. Refs #449 --- css/app.css | 3 +++ 1 file changed, 3 insertions(+) diff --git a/css/app.css b/css/app.css index 19d6660cd..36b09e392 100644 --- a/css/app.css +++ b/css/app.css @@ -255,6 +255,9 @@ button { height:40px; cursor:url(../img/cursor-pointer.png) 6 1, auto; border-radius:4px; + -webkit-transition: background 100ms; + -moz-transition: background 100ms; + transition: background 100ms; } button:hover { From 859ae1c1cc6aa52ab9be722094fa24f6dd66ab00 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Mon, 28 Jan 2013 16:38:54 -0500 Subject: [PATCH 04/48] DrawWay#cancel shouldn't unconditionally delete the way Fixes #514. --- js/id/behavior/draw_way.js | 4 ++-- js/id/modes/add_area.js | 15 +++++++++------ js/id/modes/add_line.js | 16 +++++++++------- js/id/modes/draw_area.js | 4 ++-- js/id/modes/draw_line.js | 4 ++-- 5 files changed, 24 insertions(+), 19 deletions(-) diff --git a/js/id/behavior/draw_way.js b/js/id/behavior/draw_way.js index a9f1f5c91..649d79e55 100644 --- a/js/id/behavior/draw_way.js +++ b/js/id/behavior/draw_way.js @@ -1,4 +1,4 @@ -iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode) { +iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode, baseGraph) { var map = mode.map, history = mode.history, controller = mode.controller, @@ -129,7 +129,7 @@ iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode) { // Cancel the draw operation and return to browse, deleting everything drawn. drawWay.cancel = function() { - history.perform(iD.actions.DeleteWay(wayId), 'cancelled drawing'); + history.perform(d3.functor(baseGraph), 'cancelled drawing'); controller.enter(iD.modes.Browse()); }; diff --git a/js/id/modes/add_area.js b/js/id/modes/add_area.js index cbfdffbd0..d1a3efb08 100644 --- a/js/id/modes/add_area.js +++ b/js/id/modes/add_area.js @@ -16,18 +16,20 @@ iD.modes.AddArea = function() { controller = mode.controller; function startFromNode(node) { - var way = iD.Way({tags: defaultTags}); + var graph = history.graph(), + way = iD.Way({tags: defaultTags}); history.perform( iD.actions.AddWay(way), iD.actions.AddWayNode(way.id, node.id), iD.actions.AddWayNode(way.id, node.id)); - controller.enter(iD.modes.DrawArea(way.id)); + controller.enter(iD.modes.DrawArea(way.id, graph)); } function startFromWay(other, loc, index) { - var node = iD.Node({loc: loc}), + var graph = history.graph(), + node = iD.Node({loc: loc}), way = iD.Way({tags: defaultTags}); history.perform( @@ -37,11 +39,12 @@ iD.modes.AddArea = function() { iD.actions.AddWayNode(way.id, node.id), iD.actions.AddWayNode(other.id, node.id, index)); - controller.enter(iD.modes.DrawArea(way.id)); + controller.enter(iD.modes.DrawArea(way.id, graph)); } function start(loc) { - var node = iD.Node({loc: loc}), + var graph = history.graph(), + node = iD.Node({loc: loc}), way = iD.Way({tags: defaultTags}); history.perform( @@ -50,7 +53,7 @@ iD.modes.AddArea = function() { iD.actions.AddWayNode(way.id, node.id), iD.actions.AddWayNode(way.id, node.id)); - controller.enter(iD.modes.DrawArea(way.id)); + controller.enter(iD.modes.DrawArea(way.id, graph)); } behavior = iD.behavior.AddWay(mode) diff --git a/js/id/modes/add_line.js b/js/id/modes/add_line.js index f9d52a9a0..bf419d2bb 100644 --- a/js/id/modes/add_line.js +++ b/js/id/modes/add_line.js @@ -21,10 +21,10 @@ iD.modes.AddLine = function() { isLine = parent && parent.geometry(graph) === 'line'; if (isLine && parent.first() === node.id) { - controller.enter(iD.modes.DrawLine(parent.id, 'backward')); + controller.enter(iD.modes.DrawLine(parent.id, 'backward', graph)); } else if (isLine && parent.last() === node.id) { - controller.enter(iD.modes.DrawLine(parent.id, 'forward')); + controller.enter(iD.modes.DrawLine(parent.id, 'forward', graph)); } else { var way = iD.Way({tags: defaultTags}); @@ -33,12 +33,13 @@ iD.modes.AddLine = function() { iD.actions.AddWay(way), iD.actions.AddWayNode(way.id, node.id)); - controller.enter(iD.modes.DrawLine(way.id, 'forward')); + controller.enter(iD.modes.DrawLine(way.id, 'forward', graph)); } } function startFromWay(other, loc, index) { - var node = iD.Node({loc: loc}), + var graph = history.graph(), + node = iD.Node({loc: loc}), way = iD.Way({tags: defaultTags}); history.perform( @@ -47,11 +48,12 @@ iD.modes.AddLine = function() { iD.actions.AddWayNode(way.id, node.id), iD.actions.AddWayNode(other.id, node.id, index)); - controller.enter(iD.modes.DrawLine(way.id, 'forward')); + controller.enter(iD.modes.DrawLine(way.id, 'forward', graph)); } function start(loc) { - var node = iD.Node({loc: loc}), + var graph = history.graph(), + node = iD.Node({loc: loc}), way = iD.Way({tags: defaultTags}); history.perform( @@ -59,7 +61,7 @@ iD.modes.AddLine = function() { iD.actions.AddWay(way), iD.actions.AddWayNode(way.id, node.id)); - controller.enter(iD.modes.DrawLine(way.id, 'forward')); + controller.enter(iD.modes.DrawLine(way.id, 'forward', graph)); } behavior = iD.behavior.AddWay(mode) diff --git a/js/id/modes/draw_area.js b/js/id/modes/draw_area.js index 9e2bd6a32..721452bae 100644 --- a/js/id/modes/draw_area.js +++ b/js/id/modes/draw_area.js @@ -1,4 +1,4 @@ -iD.modes.DrawArea = function(wayId) { +iD.modes.DrawArea = function(wayId, baseGraph) { var mode = { button: 'area', id: 'draw-area' @@ -29,7 +29,7 @@ iD.modes.DrawArea = function(wayId) { behavior.add(loc, annotation); } - behavior = iD.behavior.DrawWay(wayId, headId, tailId, index, mode) + behavior = iD.behavior.DrawWay(wayId, headId, tailId, index, mode, baseGraph) .on('addHead', addHeadTail) .on('addTail', addHeadTail) .on('addNode', addNode) diff --git a/js/id/modes/draw_line.js b/js/id/modes/draw_line.js index 7980b0549..289d91c14 100644 --- a/js/id/modes/draw_line.js +++ b/js/id/modes/draw_line.js @@ -1,4 +1,4 @@ -iD.modes.DrawLine = function(wayId, direction) { +iD.modes.DrawLine = function(wayId, direction, baseGraph) { var mode = { button: 'line', id: 'draw-line' @@ -38,7 +38,7 @@ iD.modes.DrawLine = function(wayId, direction) { behavior.add(loc, annotation); } - behavior = iD.behavior.DrawWay(wayId, headId, tailId, index, mode) + behavior = iD.behavior.DrawWay(wayId, headId, tailId, index, mode, baseGraph) .on('addHead', addHead) .on('addTail', addTail) .on('addNode', addNode) From 7acca8e6d29a12bbdb608d0eff90e3086f6869f6 Mon Sep 17 00:00:00 2001 From: Tom MacWright Date: Mon, 28 Jan 2013 16:41:25 -0500 Subject: [PATCH 05/48] Reformat success page. Fixes #532 --- css/app.css | 30 +++++++++++++++++++----------- js/id/connection.js | 5 +++++ js/id/ui/save.js | 2 +- js/id/ui/success.js | 21 +++++++++++++++------ 4 files changed, 40 insertions(+), 18 deletions(-) diff --git a/css/app.css b/css/app.css index 36b09e392..5deef6b50 100644 --- a/css/app.css +++ b/css/app.css @@ -994,6 +994,14 @@ div.typeahead a:first-child { text-align: center; } +/* Success +------------------------------------------------------- */ +a.success-action { + display:inline-block; + padding:10px; + margin:10px; +} + /* Notices ------------------------------------------------------- */ @@ -1056,17 +1064,17 @@ div.typeahead a:first-child { } .tooltip-inner { - text-align: left; - width: 200px; - font-size: 11px; - font-weight: bold; - line-height: 20px; - padding: 5px 10px; - color: #333; - background-color: white; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; + text-align: left; + width: 200px; + font-size: 11px; + font-weight: bold; + line-height: 20px; + padding: 5px 10px; + color: #333; + background-color: white; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; } .tooltip-arrow { diff --git a/js/id/connection.js b/js/id/connection.js index 53c96bd96..0460b09ab 100644 --- a/js/id/connection.js +++ b/js/id/connection.js @@ -10,6 +10,10 @@ iD.Connection = function() { loadedTiles = {}, oauth = iD.OAuth().url(url); + function changesetUrl(changesetId) { + return url + '/browse/changeset/' + changesetId; + } + function bboxUrl(b) { return url + '/api/0.6/map?bbox=' + [b[0][0],b[1][1],b[1][0],b[0][1]]; } @@ -325,6 +329,7 @@ iD.Connection = function() { }; connection.bboxFromAPI = bboxFromAPI; + connection.changesetUrl = changesetUrl; connection.loadFromURL = loadFromURL; connection.loadTiles = _.debounce(loadTiles, 100); connection.userDetails = userDetails; diff --git a/js/id/ui/save.js b/js/id/ui/save.js index 21af956d9..50f9891f7 100644 --- a/js/id/ui/save.js +++ b/js/id/ui/save.js @@ -37,7 +37,7 @@ iD.ui.save = function() { id: changeset_id, comment: e.comment }) - .call(iD.ui.success() + .call(iD.ui.success(connection) .on('cancel', function() { modal.remove(); })); diff --git a/js/id/ui/success.js b/js/id/ui/success.js index d135f7d80..8cc6e328b 100644 --- a/js/id/ui/success.js +++ b/js/id/ui/success.js @@ -1,4 +1,4 @@ -iD.ui.success = function() { +iD.ui.success = function(connection) { var event = d3.dispatch('cancel', 'save'); function success(selection) { @@ -9,22 +9,31 @@ iD.ui.success = function() { var section = body.append('div').attr('class','modal-section fillD'); header.append('h2').text('You Just Edited OpenStreetMap!'); - header.append('p').text('You just improved the world\'s best free map'); var m = ''; if (changeset.comment) { m = '"' + changeset.comment.substring(0, 20) + '" '; } - var message = 'Edited OpenStreetMap! ' + m + - 'http://osm.org/browse/changeset/' + changeset.id; + var message = (m || 'Edited OSM!') + + connection.changesetUrl(changeset.id); - section.append('a') + header.append('a') + .attr('href', function(d) { + return connection.changesetUrl(changeset.id); + }) + .attr('target', '_blank') + .attr('class', 'success-action') + .text('View on OSM'); + + header.append('a') + .attr('target', '_blank') .attr('href', function(d) { return 'https://twitter.com/intent/tweet?source=webclient&text=' + encodeURIComponent(message); }) - .text('Tweet: ' + message); + .attr('class', 'success-action') + .text('Tweet'); var buttonwrap = section.append('div') .attr('class', 'buttons cf'); From 3c99d36a768a2e17a4b9bea0aefd39592d57b197 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Mon, 28 Jan 2013 16:54:38 -0500 Subject: [PATCH 06/48] Fix differenced redraw artifacts during pan/zoom Fixes #543. --- js/id/renderer/map.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/js/id/renderer/map.js b/js/id/renderer/map.js index bc4ca8e03..60ad3de39 100644 --- a/js/id/renderer/map.js +++ b/js/id/renderer/map.js @@ -165,24 +165,33 @@ iD.Map = function() { } function resetTransform() { - if (!surface.style(transformProp)) return; + if (!surface.style(transformProp)) return false; surface.style(transformProp, ''); tilegroup.style(transformProp, ''); + return true; } function redraw(difference) { - resetTransform(); + // If we are in the middle of a zoom/pan, we can't do differenced redraws. + // It would result in artifacts where differenced entities are redrawn with + // one transform and unchanged entities with another. + if (resetTransform()) + difference = undefined; + surface.attr('data-zoom', ~~map.zoom()); tilegroup.call(background); + if (map.editable()) { connection.loadTiles(projection, dimensions); drawVector(difference); } else { editOff(); } + transformStart = [ projection.scale(), projection.translate().slice()]; + return map; } From d998b000d55f7a8e36665c2d4c551539c78b314a Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Mon, 28 Jan 2013 17:02:07 -0500 Subject: [PATCH 07/48] Fix midpoint dragging, break multiple touch drags --- js/id/behavior/drag.js | 16 ++++++++++++---- js/id/behavior/drag_midpoint.js | 12 ++++++++---- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/js/id/behavior/drag.js b/js/id/behavior/drag.js index 9a7ed4fdc..d88e8a44a 100644 --- a/js/id/behavior/drag.js +++ b/js/id/behavior/drag.js @@ -24,7 +24,8 @@ iD.behavior.drag = function () { origin = null, selector = '', filter = null, - keybinding = d3.keybinding('drag'); + keybinding = d3.keybinding('drag'), + event_, target; event.of = function(thiz, argumentz) { return function(e1) { @@ -40,9 +41,9 @@ iD.behavior.drag = function () { }; function mousedown() { - var target = this, - event_ = event.of(target, arguments), - eventTarget = d3.event.target, + target = this, + event_ = event.of(target, arguments); + var eventTarget = d3.event.target, touchId = d3.event.touches ? d3.event.changedTouches[0].identifier : null, offset, origin_ = point(), @@ -166,6 +167,13 @@ iD.behavior.drag = function () { return drag; }; + drag.target = function() { + if (!arguments.length) return target; + target = arguments[0]; + event_ = event.of(target, Array.prototype.slice.call(arguments, 1)); + return drag; + }; + keybinding .on('⌘+Z', drag.cancel) .on('⌃+Z', drag.cancel); diff --git a/js/id/behavior/drag_midpoint.js b/js/id/behavior/drag_midpoint.js index 5445003b8..9f73a7115 100644 --- a/js/id/behavior/drag_midpoint.js +++ b/js/id/behavior/drag_midpoint.js @@ -1,8 +1,7 @@ iD.behavior.DragMidpoint = function(mode) { var history = mode.history, - projection = mode.map.projection; - - return iD.behavior.drag() + projection = mode.map.projection, + behavior = iD.behavior.drag() .delegate(".midpoint") .origin(function(d) { return projection(d.loc); @@ -21,15 +20,20 @@ iD.behavior.DragMidpoint = function(mode) { } } history.perform.apply(history, args); + var node = d3.selectAll('.node.vertex') + .filter(function(data) { return data.id === d.node.id; }); + behavior.target(node.node(), node.datum()); + }) .on('move', function(d) { d3.event.sourceEvent.stopPropagation(); history.replace( - iD.actions.MoveNode(d.node.id, projection.invert(d3.event.point))); + iD.actions.MoveNode(d.id, projection.invert(d3.event.point))); }) .on('end', function() { history.replace( iD.actions.Noop(), 'added a node to a way'); }); + return behavior; }; From 5d73e45b50452d932013b533e065096fadeaadea Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Mon, 28 Jan 2013 17:26:06 -0500 Subject: [PATCH 08/48] Fix exiting draw mode via other means (fixes #503) --- js/id/behavior/draw_way.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/js/id/behavior/draw_way.js b/js/id/behavior/draw_way.js index 649d79e55..0e5bcf4fd 100644 --- a/js/id/behavior/draw_way.js +++ b/js/id/behavior/draw_way.js @@ -4,6 +4,7 @@ iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode, baseGraph) { controller = mode.controller, event = d3.dispatch('add', 'addHead', 'addTail', 'addNode', 'addWay'), way = mode.history.graph().entity(wayId), + finished = false, hover, draw; var node = iD.Node({loc: map.mouseCoordinates()}), @@ -56,6 +57,9 @@ iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode, baseGraph) { }; drawWay.off = function(surface) { + if (!finished) + history.pop(); + map.fastEnable(true) .minzoom(0) .tail(false); @@ -86,6 +90,7 @@ iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode, baseGraph) { ReplaceTemporaryNode(node), annotation); + finished = true; controller.enter(mode); }; @@ -99,6 +104,7 @@ iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode, baseGraph) { ReplaceTemporaryNode(newNode), annotation); + finished = true; controller.enter(mode); }; @@ -111,6 +117,7 @@ iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode, baseGraph) { ReplaceTemporaryNode(newNode), annotation); + finished = true; controller.enter(mode); }; @@ -118,6 +125,7 @@ iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode, baseGraph) { // nodes to be valid, it's selected. Otherwise, return to browse mode. drawWay.finish = function() { history.pop(); + finished = true; var way = history.graph().entity(wayId); if (way) { @@ -129,7 +137,11 @@ iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode, baseGraph) { // Cancel the draw operation and return to browse, deleting everything drawn. drawWay.cancel = function() { - history.perform(d3.functor(baseGraph), 'cancelled drawing'); + history.perform( + d3.functor(baseGraph), + 'cancelled drawing'); + + finished = true; controller.enter(iD.modes.Browse()); }; From 8fe9da4710e6de4ad0459000569bab46b82f3253 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Mon, 28 Jan 2013 17:29:21 -0500 Subject: [PATCH 09/48] Mode name and shortcut key should match --- js/id/modes/browse.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/id/modes/browse.js b/js/id/modes/browse.js index 90726b6bc..9782bac27 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: 'Move', + title: 'Browse', description: 'Pan and zoom the map', key: 'b' }; From 541ff96af67c8baf1bfcd680c2b114cccc977b52 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Mon, 28 Jan 2013 17:46:25 -0500 Subject: [PATCH 10/48] Close modals with esc or backspace --- js/id/ui/modal.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/js/id/ui/modal.js b/js/id/ui/modal.js index 498f1e241..2e58166cb 100644 --- a/js/id/ui/modal.js +++ b/js/id/ui/modal.js @@ -1,6 +1,13 @@ iD.ui.modal = function(blocking) { + var animate = d3.select('div.modal').empty(); + var keybinding = d3.keybinding('modal') + .on('⌫', close) + .on('⎋', close); + + d3.select(document).call(keybinding); + d3.select('div.modal').transition() .style('opacity', 0).remove(); @@ -30,5 +37,10 @@ iD.ui.modal = function(blocking) { shaded.style('opacity', 1); } + function close() { + shaded.remove(); + keybinding.off(); + } + return shaded; }; From 6cb1692e44e0e8abc353c3a3bd8b53fea796d1f2 Mon Sep 17 00:00:00 2001 From: Saman Bemel-Benrud Date: Mon, 28 Jan 2013 21:06:07 -0500 Subject: [PATCH 11/48] radial menu source, better user icon commit modal integration, small fixes. --- css/app.css | 42 +- img/source/radial-menu.svg | 14044 +++++++++++++++++++++++++++++++++++ img/source/sprite.svg | 111 +- img/sprite.png | Bin 12337 -> 12783 bytes js/id/ui/commit.js | 51 +- js/id/ui/modal.js | 2 +- 6 files changed, 14164 insertions(+), 86 deletions(-) create mode 100644 img/source/radial-menu.svg diff --git a/css/app.css b/css/app.css index e83c7152f..47bf15f45 100644 --- a/css/app.css +++ b/css/app.css @@ -89,7 +89,7 @@ a:visited, a { } a:hover { - color:#154dff; + color:#597be7; } @@ -220,9 +220,10 @@ ul.link-list li:last-child { .fillD { background:rgba(0,0,0,.8); - color: white; + color: #a9a9a9; } + .fl { float: left;} .fr { float: right;} @@ -399,7 +400,7 @@ button[disabled] .label { height: 40px; } -.icon.icon-pre-text { +.icon-pre-text { margin-right: 3px; } @@ -424,6 +425,9 @@ button[disabled] .label { .icon.avatar { background-position: -320px 0px;} .icon.nearby { background-position: -340px 0px;} .icon.geolocate { background-position: -360px 0px;} +.icon.warning { background-position: -380px 0px;} + +.icon.close-modal{ background-position: -200px -40px;} .icon.invert.zoom-in { background-position: -240px -40px;} @@ -900,6 +904,18 @@ div.typeahead a:first-child { left:0px; right:0px; top:0px; bottom:0px; } +.commit-modal .user-info { + display: inline-block; +} + +.commit-modal .commit-info { + margin-top: 10px; +} + +.commit-modal .user-info img { + float: left; +} + .commit-modal h3 small.count { margin-right: 10px; text-align: center; @@ -919,10 +935,26 @@ div.typeahead a:first-child { border:1px solid #ccc; background:#fff; max-height: 160px; + overflow: visible; } -.commit-modal .user-details { - float: right; +.commit-modal .warning-section .changeset-list { + margin-right: 20px; +} + +.commit-section.modal-section { + padding-bottom: 0; +} + +.commit-section.modal-section:last-child { padding-bottom: 20px;} + +.commit-modal .changeset-list li { + position: relative; +} + +.commit-modal .changeset-list li button { + position: absolute; + right: -30px; } .user-icon { diff --git a/img/source/radial-menu.svg b/img/source/radial-menu.svg new file mode 100644 index 000000000..7c43c61d8 --- /dev/null +++ b/img/source/radial-menu.svg @@ -0,0 +1,14044 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Delete + + + + + Unjoin + Split way + + diff --git a/img/source/sprite.svg b/img/source/sprite.svg index 537a84226..e11e3a93e 100644 --- a/img/source/sprite.svg +++ b/img/source/sprite.svg @@ -9,11 +9,11 @@ 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="380" + width="400" height="200" id="svg12393" version="1.1" - inkscape:version="0.48.1 r9760" + inkscape:version="0.48.2 r9819" sodipodi:docname="sprite.svg" inkscape:export-filename="/Users/saman/work_repos/iD/img/sprite.png" inkscape:export-xdpi="90" @@ -38,15 +38,15 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="2.8284271" - inkscape:cx="173.1037" - inkscape:cy="123.12989" + inkscape:zoom="2" + inkscape:cx="300.38044" + inkscape:cy="166.96802" inkscape:document-units="px" inkscape:current-layer="layer12" showgrid="false" - inkscape:window-width="1560" - inkscape:window-height="922" - inkscape:window-x="223" + inkscape:window-width="1280" + inkscape:window-height="756" + inkscape:window-x="119" inkscape:window-y="0" inkscape:window-maximized="0" fit-margin-top="0" @@ -56,7 +56,7 @@ showguides="false" inkscape:guide-bbox="true" inkscape:snap-bbox="true" - inkscape:snap-nodes="false"> + inkscape:snap-nodes="true"> + + @@ -173,7 +181,7 @@ image/svg+xml - + @@ -183,15 +191,6 @@ id="layer1" transform="translate(-25,-62.362183)" style="display:inline"> - + style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.79999375;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> - - - - - - + + transform="translate(-511.00001,-14)" + 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"> + style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.55555558;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"> + d="m 925.00003,-6.4444512 c -3.86599,0 -7,3.1340096 -7,6.99999958 0,1.12543002 0.30585,2.16901002 0.77778,3.11112002 l -5.44445,5.444436 0,3.1111096 3.11112,0 5.44444,-5.4444396 c 0.94211,0.47192 1.98568,0.77777 3.11111,0.77777 3.86599,0 7,-3.133996 7,-6.99999602 0,-3.86598998 -3.13401,-6.99999958 -7,-6.99999958 z m 0,3.1111096 c 2.14777,0 3.88889,1.74112 3.88889,3.88888998 0,2.14778002 -1.74112,3.88889002 -3.88889,3.88889002 -2.14777,0 -3.88889,-1.74111 -3.88889,-3.88889002 0,-2.14776998 1.74112,-3.88888998 3.88889,-3.88888998 z" + style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.55555558;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> @@ -1080,5 +1062,28 @@ id="path33359" d="m 354.5,22.999997 c -1.5,0 -2.5,2 -2.5,3 0,0.666667 0,1.333333 0,2 0,1 1,2.153847 1,2.153847 l 0,0.846153 -1.69231,0.384617 c -1.45419,0.330499 -2.02608,1.236079 -2.15384,2.76923 L 349,35.999998 l 12,0 -0.15385,-1.846154 c -0.12776,-1.533151 -0.69965,-2.438731 -2.15384,-2.76923 L 357,30.999997 l 0,-0.846153 c 0,0 1,-1.153847 1,-2.153847 0,-0.666667 0,-1.333333 0,-2 0,-1 -1,-3 -2.5,-3 z" 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 e3037eebdaf5efa7c25cd049b331b165218798cd..82dde059e5fd437b97fd193b590cce0038b3579b 100644 GIT binary patch literal 12783 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 literal 12337 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 diff --git a/js/id/ui/commit.js b/js/id/ui/commit.js index 47484419a..e62c8415d 100644 --- a/js/id/ui/commit.js +++ b/js/id/ui/commit.js @@ -31,32 +31,7 @@ iD.ui.commit = function(map) { header = selection.append('div').attr('class', 'header modal-section fillL'), body = selection.append('div').attr('class', 'body'); - - var user_details = header - .append('div') - .attr('class', 'user-details'); - - var user_link = user_details - .append('div') - .append('a') - .attr('href', connection.url() + '/user/' + - user.display_name) - .attr('target', '_blank'); - - if (user.image_url) { - user_link - .append('img') - .attr('src', user.image_url) - .attr('class', 'user-icon'); - } - - user_link - .append('div') - .text(user.display_name); - - header.append('h2').text('Save Changes'); - - header.append('p').text('The changes you upload will be visible on all maps that use OpenStreetMap data.'); + header.append('h2').text('Save Changes to OpenStreetMap'); // Comment Box var comment_section = body.append('div').attr('class','modal-section fillD'); @@ -66,6 +41,28 @@ iD.ui.commit = function(map) { .property('value', localStorage.comment || '') .node().select(); + var commit_info = + comment_section + .append('p') + .attr('class','commit-info'); + + commit_info.append('span').text('The changes you upload as '); + + var user_link = commit_info.append('a') + .attr('class','user-info') + .text(user.display_name) + .attr('href', connection.url() + '/user/' + user.display_name) + .attr('target', '_blank'); + + commit_info.append('span').text(' will be visible on all maps that use OpenStreetMap data:'); + + if (user.image_url) { + user_link + .append('img') + .attr('src', user.image_url) + .attr('class', 'icon icon-pre-text'); + } + // Confirm / Cancel Buttons var buttonwrap = comment_section.append('div') .attr('class', 'buttons cf') @@ -111,7 +108,7 @@ iD.ui.commit = function(map) { .attr('class', 'minor') .on('click', event.fix) .append('span') - .attr('class', 'icon inspect'); + .attr('class', 'icon warning'); warning_li.append('strong').text(function(d) { return d.message; diff --git a/js/id/ui/modal.js b/js/id/ui/modal.js index 498f1e241..3ea341f42 100644 --- a/js/id/ui/modal.js +++ b/js/id/ui/modal.js @@ -16,7 +16,7 @@ iD.ui.modal = function(blocking) { .attr('class', 'modal'); modal.append('button') - .attr('class', 'icon remove close-modal') + .attr('class', 'icon close-modal') .on('click', function() { if (!blocking) shaded.remove(); }); From b13e6d13d924a3371e7550556c0b06fdf46d8d95 Mon Sep 17 00:00:00 2001 From: Saman Bemel-Benrud Date: Mon, 28 Jan 2013 21:08:40 -0500 Subject: [PATCH 12/48] copy tweaks. --- js/id/ui/commit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/id/ui/commit.js b/js/id/ui/commit.js index e62c8415d..c624ac91f 100644 --- a/js/id/ui/commit.js +++ b/js/id/ui/commit.js @@ -31,7 +31,7 @@ iD.ui.commit = function(map) { header = selection.append('div').attr('class', 'header modal-section fillL'), body = selection.append('div').attr('class', 'body'); - header.append('h2').text('Save Changes to OpenStreetMap'); + header.append('h2').text('Save Changes'); // Comment Box var comment_section = body.append('div').attr('class','modal-section fillD'); From 7b374de5f8423fbf260d89a465d4d9b5b998c7be Mon Sep 17 00:00:00 2001 From: Saman Bemel-Benrud Date: Tue, 29 Jan 2013 11:08:16 -0500 Subject: [PATCH 13/48] adding relation icon. --- css/app.css | 1 + img/source/sprite.svg | 85 ++++++++++++++++++++++++++++++++++++++++-- img/sprite.png | Bin 12783 -> 12916 bytes 3 files changed, 82 insertions(+), 4 deletions(-) diff --git a/css/app.css b/css/app.css index 49e2a8e65..8ba20a02c 100644 --- a/css/app.css +++ b/css/app.css @@ -468,6 +468,7 @@ button[disabled] .icon.nearby { background-position: -340px -40px;} .icon.big-area { background-position: -80px -80px;} .icon.big-vertex { background-position: -120px -80px;} .icon.big-inspect { background-position: -160px -80px;} +.icon.big-relation { background-position: -200px -80px;} /* Toggle icon is special */ .toggle.icon { background-position: 0px -180px;} diff --git a/img/source/sprite.svg b/img/source/sprite.svg index e11e3a93e..5589fc2d5 100644 --- a/img/source/sprite.svg +++ b/img/source/sprite.svg @@ -38,9 +38,9 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="2" - inkscape:cx="300.38044" - inkscape:cy="166.96802" + inkscape:zoom="1" + inkscape:cx="336.77382" + inkscape:cy="126.79999" inkscape:document-units="px" inkscape:current-layer="layer12" showgrid="false" @@ -836,7 +836,7 @@ + + + + + + + + + + diff --git a/img/sprite.png b/img/sprite.png index 82dde059e5fd437b97fd193b590cce0038b3579b..be9ba0fdbdefcc9c8159a1ffdb21b104a6664f18 100644 GIT binary patch literal 12916 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 literal 12783 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 From b37ef978f45af985538b176dd417f12b63e8e368 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 25 Jan 2013 11:47:05 -0500 Subject: [PATCH 14/48] Snap to ways/vertices/midpoints when drawing (#240) Also add anti-snapping behavior when option key is down. --- css/map.css | 26 ++++---- js/id/behavior/add_way.js | 14 ++--- js/id/behavior/draw.js | 114 +++++++++++++++++++++++------------- js/id/behavior/draw_way.js | 26 ++++---- js/id/behavior/hover.js | 5 +- test/spec/behavior/hover.js | 19 +++++- 6 files changed, 126 insertions(+), 78 deletions(-) diff --git a/css/map.css b/css/map.css index 8f235bb18..7b3038d6c 100644 --- a/css/map.css +++ b/css/map.css @@ -16,7 +16,7 @@ g.point .shadow { transition: transform 100ms linear; -moz-transition: fill 100ms linear; } -g.point.hover .shadow { +.behavior-hover g.point.hover .shadow { fill: #E96666; fill-opacity: 0.3; } @@ -106,7 +106,7 @@ g.vertex .shadow { transition: transform 100ms linear; -moz-transition: fill 100ms linear; } -g.vertex.hover .shadow { +.behavior-hover g.vertex.hover .shadow { fill: #E96666; fill-opacity: 0.3; } @@ -120,7 +120,7 @@ g.vertex.selected .shadow { g.midpoint .fill { fill:#aaa; } -g.midpoint .fill.hover { +.behavior-hover g.midpoint .fill.hover { fill:#fff; stroke:#000; } @@ -133,7 +133,7 @@ g.midpoint .shadow { transition: transform 100ms linear; -moz-transition: fill 100ms linear; } -g.midpoint .shadow.hover { +.behavior-hover g.midpoint .shadow.hover { fill:#E96666; fill-opacity: 0.3; } @@ -161,7 +161,7 @@ path.shadow { -webkit-transition: stroke 100ms linear; } -path.shadow.hover { +.behavior-hover path.shadow.hover { stroke: #E96666; stroke-opacity: 0.3; } @@ -691,17 +691,17 @@ text.point.tag-amenity { cursor:url(../img/cursor-draw.png) 9 9, auto; } -.mode-draw-line .way, -.mode-draw-area .way, -.mode-add-line .way, -.mode-add-area .way { +.mode-draw-line .behavior-hover .way, +.mode-draw-area .behavior-hover .way, +.mode-add-line .behavior-hover .way, +.mode-add-area .behavior-hover .way { cursor:url(../img/cursor-draw-connect-line.png) 9 9, auto; } -.mode-draw-line .vertex, -.mode-draw-area .vertex, -.mode-add-line .vertex, -.mode-add-area .vertex { +.mode-draw-line .behavior-hover .vertex, +.mode-draw-area .behavior-hover .vertex, +.mode-add-line .behavior-hover .vertex, +.mode-add-area .behavior-hover .vertex { cursor:url(../img/cursor-draw-connect-vertex.png) 9 9, auto; } diff --git a/js/id/behavior/add_way.js b/js/id/behavior/add_way.js index 7c02355fb..021377890 100644 --- a/js/id/behavior/add_way.js +++ b/js/id/behavior/add_way.js @@ -3,11 +3,9 @@ iD.behavior.AddWay = function(mode) { history = mode.history, controller = mode.controller, event = d3.dispatch('startFromNode', 'startFromWay', 'start'), - hover, draw; - - function add() { - var datum = d3.select(d3.event.target).datum() || {}; + draw; + function add(datum) { if (datum.type === 'node') { event.startFromNode(datum); } else if (datum.type === 'way') { @@ -26,8 +24,7 @@ iD.behavior.AddWay = function(mode) { .minzoom(16) .dblclickEnable(false); - surface.call(hover) - .call(draw); + surface.call(draw); }; addWay.off = function(surface) { @@ -39,16 +36,13 @@ iD.behavior.AddWay = function(mode) { map.dblclickEnable(true); }, 1000); - surface.call(hover.off) - .call(draw.off); + surface.call(draw.off); }; addWay.cancel = function() { controller.exit(); }; - hover = iD.behavior.Hover(); - draw = iD.behavior.Draw() .on('add', add) .on('cancel', addWay.cancel) diff --git a/js/id/behavior/draw.js b/js/id/behavior/draw.js index 2725b8111..4d0153505 100644 --- a/js/id/behavior/draw.js +++ b/js/id/behavior/draw.js @@ -1,45 +1,64 @@ iD.behavior.Draw = function () { var event = d3.dispatch('move', 'add', 'undo', 'cancel', 'finish'), keybinding = d3.keybinding('draw'), - down; + down, surface, hover; + + function datum() { + if (d3.event.altKey) { + return {}; + } else { + return d3.event.target.__data__ || {}; + } + } + + function mousedown() { + down = true; + } + + function mouseup() { + down = false; + } + + function mousemove() { + if (!down) { + event.move(datum()); + } + } + + function click() { + event.add(datum()); + } + + function keydown() { + if (d3.event.keyCode === d3.keybinding.modifierCodes.alt) { + surface.call(hover.off); + } + } + + function keyup() { + if (d3.event.keyCode === d3.keybinding.modifierCodes.alt) { + surface.call(hover); + } + } + + function backspace() { + d3.event.preventDefault(); + event.undo(); + } + + function del() { + d3.event.preventDefault(); + event.cancel(); + } + + function ret() { + d3.event.preventDefault(); + event.finish(); + } function draw(selection) { - function mousemove() { - if (!down) event.move(); - } - - function click() { - event.add(); - } - - function mousedown() { - down = true; - } - - function mouseup() { - down = false; - } - - function backspace() { - d3.event.preventDefault(); - event.undo(); - } - - function del() { - d3.event.preventDefault(); - event.cancel(); - } - - function ret() { - d3.event.preventDefault(); - event.finish(); - } - - selection - .on('mousedown.draw', mousedown) - .on('mouseup.draw', mouseup) - .on('mousemove.draw', mousemove) - .on('click.draw', click); + surface = selection; + hover = iD.behavior.Hover(); keybinding .on('⌫', backspace) @@ -47,18 +66,33 @@ iD.behavior.Draw = function () { .on('⎋', ret) .on('↩', ret); + selection + .on('mousedown.draw', mousedown) + .on('mouseup.draw', mouseup) + .on('mousemove.draw', mousemove) + .on('click.draw', click) + .call(hover); + d3.select(document) - .call(keybinding); + .call(keybinding) + .on('keydown.draw', keydown) + .on('keyup.draw', keyup); return draw; } draw.off = function(selection) { selection + .on('mousedown.draw', null) + .on('mouseup.draw', null) .on('mousemove.draw', null) - .on('click.draw', null); + .on('click.draw', null) + .call(hover.off); - keybinding.off(); + d3.select(document) + .call(keybinding.off) + .on('keydown.draw', null) + .on('keyup.draw', null); }; return d3.rebind(draw, event, 'on'); diff --git a/js/id/behavior/draw_way.js b/js/id/behavior/draw_way.js index 0e5bcf4fd..63526df7a 100644 --- a/js/id/behavior/draw_way.js +++ b/js/id/behavior/draw_way.js @@ -5,7 +5,7 @@ iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode, baseGraph) { event = d3.dispatch('add', 'addHead', 'addTail', 'addNode', 'addWay'), way = mode.history.graph().entity(wayId), finished = false, - hover, draw; + draw; var node = iD.Node({loc: map.mouseCoordinates()}), nodeId = node.id; @@ -14,13 +14,19 @@ iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode, baseGraph) { iD.actions.AddNode(node), iD.actions.AddWayNode(wayId, node.id, index)); - function move() { - history.replace(iD.actions.MoveNode(nodeId, map.mouseCoordinates())); + function move(datum) { + var loc = map.mouseCoordinates(); + + if (datum.type === 'node' || datum.midpoint) { + loc = datum.loc; + } else if (datum.type === 'way') { + loc = iD.geo.chooseIndex(datum, d3.mouse(map.surface.node()), map).loc; + } + + history.replace(iD.actions.MoveNode(nodeId, loc)); } - function add() { - var datum = d3.select(d3.event.target).datum() || {}; - + function add(datum) { if (datum.id === headId) { event.addHead(datum); } else if (datum.id === tailId) { @@ -47,8 +53,7 @@ iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode, baseGraph) { .minzoom(16) .dblclickEnable(false); - surface.call(hover) - .call(draw) + surface.call(draw) .selectAll('.way, .node') .filter(function (d) { return d.id === wayId || d.id === nodeId; }) .classed('active', true); @@ -68,8 +73,7 @@ iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode, baseGraph) { map.dblclickEnable(true); }, 1000); - surface.call(hover.off) - .call(draw.off) + surface.call(draw.off) .selectAll('.way, .node') .classed('active', false); @@ -145,8 +149,6 @@ iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode, baseGraph) { controller.enter(iD.modes.Browse()); }; - hover = iD.behavior.Hover(); - draw = iD.behavior.Draw() .on('move', move) .on('add', add) diff --git a/js/id/behavior/hover.js b/js/id/behavior/hover.js index 9d50cbbd0..e4d33dd98 100644 --- a/js/id/behavior/hover.js +++ b/js/id/behavior/hover.js @@ -9,6 +9,8 @@ */ iD.behavior.Hover = function () { var hover = function(selection) { + selection.classed('behavior-hover', true); + selection.on('mouseover.hover', function () { var datum = d3.event.target.__data__; if (datum) { @@ -25,7 +27,8 @@ iD.behavior.Hover = function () { }; hover.off = function(selection) { - selection.on('mouseover.hover', null) + selection.classed('behavior-hover', false) + .on('mouseover.hover', null) .on('mouseout.hover', null); }; diff --git a/test/spec/behavior/hover.js b/test/spec/behavior/hover.js index 817654d59..62d301d19 100644 --- a/test/spec/behavior/hover.js +++ b/test/spec/behavior/hover.js @@ -9,8 +9,23 @@ describe("iD.behavior.Hover", function() { container.remove(); }); + describe("#on", function () { + it("adds the .behavior-hover class to the selection", function () { + container.call(iD.behavior.Hover()); + expect(container).to.be.classed('behavior-hover') + }); + }); + + describe("#off", function () { + it("removes the .behavior-hover class from the selection", function () { + container.classed('behavior-hover', true); + container.call(iD.behavior.Hover().off); + expect(container).not.to.be.classed('behavior-hover') + }); + }); + describe("mouseover", function () { - it("adds the 'hover' class to all elements to which the same datum is bound", function () { + it("adds the .hover class to all elements to which the same datum is bound", function () { container.selectAll('span') .data(['a', 'b', 'a', 'b']) .enter().append('span').attr('class', Object); @@ -24,7 +39,7 @@ describe("iD.behavior.Hover", function() { }); describe("mouseout", function () { - it("removes the 'hover' class from all elements", function () { + it("removes the .hover class from all elements", function () { container.append('span').attr('class', 'hover'); container.call(iD.behavior.Hover()); From 69d95a6082be23b64fdad29c2c75ffa0b0c35e40 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Tue, 29 Jan 2013 12:05:52 -0500 Subject: [PATCH 15/48] Refactor operations They're something distinct from actions. Actions are independent of UI, operations are actions + UI (title, keybinding, modality, etc.) --- Makefile | 2 + index.html | 7 +++ js/id/actions/circular.js | 2 +- js/id/actions/delete_node.js | 8 +--- js/id/actions/delete_way.js | 8 +--- js/id/actions/reverse_way.js | 8 +--- js/id/modes/select.js | 2 +- js/id/operations.js | 1 + js/id/operations/circular.js | 34 ++++++++++++++ js/id/operations/delete.js | 42 +++++++++++++++++ js/id/operations/reverse.js | 21 +++++++++ js/id/operations/split.js | 21 +++++++++ js/id/operations/unjoin.js | 21 +++++++++ js/id/ui/radial_menu.js | 87 ++++-------------------------------- test/index.html | 7 +++ 15 files changed, 169 insertions(+), 102 deletions(-) create mode 100644 js/id/operations.js create mode 100644 js/id/operations/circular.js create mode 100644 js/id/operations/delete.js create mode 100644 js/id/operations/reverse.js create mode 100644 js/id/operations/split.js create mode 100644 js/id/operations/unjoin.js diff --git a/Makefile b/Makefile index c9d13ff60..70ac208d6 100644 --- a/Makefile +++ b/Makefile @@ -38,6 +38,8 @@ all: \ js/id/behavior/*.js \ js/id/modes.js \ js/id/modes/*.js \ + js/id/operations.js \ + js/id/operations/*.js \ js/id/controller/*.js \ js/id/graph/*.js \ js/id/renderer/*.js \ diff --git a/index.html b/index.html index af436a86e..cc45f4a48 100644 --- a/index.html +++ b/index.html @@ -106,6 +106,13 @@ + + + + + + + diff --git a/js/id/actions/circular.js b/js/id/actions/circular.js index d6af08560..da7965c79 100644 --- a/js/id/actions/circular.js +++ b/js/id/actions/circular.js @@ -51,7 +51,7 @@ iD.actions.Circular = function(wayId, map) { }; action.enabled = function(graph) { - return true; + return graph.entity(wayId).isClosed(); }; return action; diff --git a/js/id/actions/delete_node.js b/js/id/actions/delete_node.js index 48e704ac3..a93129ce3 100644 --- a/js/id/actions/delete_node.js +++ b/js/id/actions/delete_node.js @@ -1,6 +1,6 @@ // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteNodeAction.as iD.actions.DeleteNode = function(nodeId) { - var action = function(graph) { + return function(graph) { var node = graph.entity(nodeId); graph.parentWays(node) @@ -20,10 +20,4 @@ iD.actions.DeleteNode = function(nodeId) { return graph.remove(node); }; - - action.enabled = function(graph) { - return true; - }; - - return action; }; diff --git a/js/id/actions/delete_way.js b/js/id/actions/delete_way.js index eb58223cb..211447228 100644 --- a/js/id/actions/delete_way.js +++ b/js/id/actions/delete_way.js @@ -1,6 +1,6 @@ // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteWayAction.as iD.actions.DeleteWay = function(wayId) { - var action = function(graph) { + return function(graph) { var way = graph.entity(wayId); graph.parentRelations(way) @@ -27,10 +27,4 @@ iD.actions.DeleteWay = function(wayId) { return graph.remove(way); }; - - action.enabled = function(graph) { - return true; - }; - - return action; }; diff --git a/js/id/actions/reverse_way.js b/js/id/actions/reverse_way.js index 4a7d392b7..160017637 100644 --- a/js/id/actions/reverse_way.js +++ b/js/id/actions/reverse_way.js @@ -53,7 +53,7 @@ iD.actions.ReverseWay = function(wayId) { } } - var action = function(graph) { + return function(graph) { var way = graph.entity(wayId), nodes = way.nodes.slice().reverse(), tags = {}, key, role; @@ -73,10 +73,4 @@ iD.actions.ReverseWay = function(wayId) { return graph.replace(way.update({nodes: nodes, tags: tags})); }; - - action.enabled = function(graph) { - return true; - }; - - return action; }; diff --git a/js/id/modes/select.js b/js/id/modes/select.js index fb4e5dc06..8871dd2ec 100644 --- a/js/id/modes/select.js +++ b/js/id/modes/select.js @@ -138,7 +138,7 @@ iD.modes.Select = function(entity, initial) { }) .classed('selected', true); - radialMenu = iD.ui.RadialMenu(entity, history, mode.map); + radialMenu = iD.ui.RadialMenu(entity, mode); if (d3.event && !initial) { var loc = map.mouseCoordinates(); diff --git a/js/id/operations.js b/js/id/operations.js new file mode 100644 index 000000000..2786d046f --- /dev/null +++ b/js/id/operations.js @@ -0,0 +1 @@ +iD.operations = {} diff --git a/js/id/operations/circular.js b/js/id/operations/circular.js new file mode 100644 index 000000000..0af64aa20 --- /dev/null +++ b/js/id/operations/circular.js @@ -0,0 +1,34 @@ +iD.operations.Circular = function(entityId, mode) { + var action = iD.actions.Circular(entityId, mode.map); + + var operation = function(history) { + var graph = history.graph(), + entity = graph.entity(entityId), + geometry = entity.geometry(graph); + + if (geometry === 'line') { + history.perform( + action, + 'made a line circular'); + + } else if (geometry === 'area') { + history.perform( + action, + 'made an area circular'); + } + }; + + operation.available = function(graph) { + var entity = graph.entity(entityId); + return entity.geometry(graph) === 'area' || entity.geometry(graph) === 'line'; + }; + + operation.enabled = function(graph) { + return action.enabled(graph); + }; + + operation.id = "circular"; + operation.title = "Circular"; + + return operation; +}; diff --git a/js/id/operations/delete.js b/js/id/operations/delete.js new file mode 100644 index 000000000..53038dbc4 --- /dev/null +++ b/js/id/operations/delete.js @@ -0,0 +1,42 @@ +iD.operations.Delete = function(entityId) { + var operation = function(history) { + var graph = history.graph(), + entity = graph.entity(entityId), + geometry = entity.geometry(graph); + + if (geometry === 'vertex') { + history.perform( + iD.actions.DeleteNode(entityId), + 'deleted a vertex'); + + } else if (geometry === 'point') { + history.perform( + iD.actions.DeleteNode(entityId), + 'deleted a point'); + + } else if (geometry === 'line') { + history.perform( + iD.actions.DeleteWay(entityId), + 'deleted a line'); + + } else if (geometry === 'area') { + history.perform( + iD.actions.DeleteWay(entityId), + 'deleted an area'); + } + }; + + operation.available = function(graph) { + var entity = graph.entity(entityId); + return _.contains(['vertex', 'point', 'line', 'area'], entity.geometry(graph)); + }; + + operation.enabled = function() { + return true; + }; + + operation.id = "delete"; + operation.title = "Delete"; + + return operation; +}; diff --git a/js/id/operations/reverse.js b/js/id/operations/reverse.js new file mode 100644 index 000000000..941d8a4da --- /dev/null +++ b/js/id/operations/reverse.js @@ -0,0 +1,21 @@ +iD.operations.Reverse = function(entityId) { + var operation = function(history) { + history.perform( + iD.actions.ReverseWay(entityId), + 'reversed a line'); + }; + + operation.available = function(graph) { + var entity = graph.entity(entityId); + return entity.geometry(graph) === 'line'; + }; + + operation.enabled = function() { + return true; + }; + + operation.id = "reverse"; + operation.title = "Reverse"; + + return operation; +}; diff --git a/js/id/operations/split.js b/js/id/operations/split.js new file mode 100644 index 000000000..838dac88e --- /dev/null +++ b/js/id/operations/split.js @@ -0,0 +1,21 @@ +iD.operations.Split = function(entityId) { + var action = iD.actions.SplitWay(entityId); + + var operation = function(history) { + history.perform(action, 'split a way'); + }; + + operation.available = function(graph) { + var entity = graph.entity(entityId); + return entity.geometry(graph) === 'vertex'; + }; + + operation.enabled = function(graph) { + return action.enabled(graph); + }; + + operation.id = "split"; + operation.title = "Split"; + + return operation; +}; diff --git a/js/id/operations/unjoin.js b/js/id/operations/unjoin.js new file mode 100644 index 000000000..985a41697 --- /dev/null +++ b/js/id/operations/unjoin.js @@ -0,0 +1,21 @@ +iD.operations.Unjoin = function(entityId) { + var action = iD.actions.UnjoinNode(entityId); + + var operation = function(history) { + history.perform(action, 'unjoined lines'); + }; + + operation.available = function(graph) { + var entity = graph.entity(entityId); + return entity.geometry(graph) === 'vertex'; + }; + + operation.enabled = function(graph) { + return action.enabled(graph); + }; + + operation.id = "unjoin"; + operation.title = "Unjoin"; + + return operation; +}; diff --git a/js/id/ui/radial_menu.js b/js/id/ui/radial_menu.js index ff895ea81..a891b7d8e 100644 --- a/js/id/ui/radial_menu.js +++ b/js/id/ui/radial_menu.js @@ -1,83 +1,12 @@ -iD.ui.RadialMenu = function(entity, history, map) { +iD.ui.RadialMenu = function(entity, mode) { var arcs; var radialMenu = function(selection, center) { - var operations, + var history = mode.map.history(), graph = history.graph(), - geometry = entity.geometry(graph); - - if (geometry === 'vertex') { - operations = [ - { - id: 'delete', - text: 'Delete', - description: 'deleted a node', - action: iD.actions.DeleteNode(entity.id) - }, - { - id: 'split', - text: 'Split Way', - description: 'split a way', - action: iD.actions.SplitWay(entity.id) - }, - { - id: 'unjoin', - text: 'Unjoin', - description: 'unjoined lines', - action: iD.actions.UnjoinNode(entity.id) - } - ]; - } else if (geometry === 'point') { - operations = [ - { - id: 'delete', - text: 'Delete', - description: 'deleted a point', - action: iD.actions.DeleteNode(entity.id) - } - ]; - } else if (geometry === 'line') { - operations = [ - { - id: 'delete', - text: 'Delete', - description: 'deleted a line', - action: iD.actions.DeleteWay(entity.id) - }, - { - id: 'reverse', - text: 'Reverse', - description: 'reversed a way', - action: iD.actions.ReverseWay(entity.id) - } - ]; - if (entity.isClosed()) { - operations.push({ - id: 'circlar', - text: 'Circular', - description: 'made way circular', - action: iD.actions.Circular(entity.id, map) - }); - } - } else if (geometry === 'area') { - operations = [ - { - id: 'delete', - text: 'Delete', - description: 'deleted an area', - action: iD.actions.DeleteWay(entity.id) - }, - { - id: 'circlar', - text: 'Circular', - description: 'made area circular', - action: iD.actions.Circular(entity.id, map) - } - ]; - } else { - // Relation, not implemented yet. - return; - } + operations = d3.values(iD.operations) + .map(function (o) { return o(entity.id, mode); }) + .filter(function (o) { return o.available(graph); }); var arc = d3.svg.arc() .outerRadius(70) @@ -98,14 +27,14 @@ iD.ui.RadialMenu = function(entity, history, map) { arcs.append('path') .attr('class', function (d) { return 'radial-menu-item radial-menu-item-' + d.id; }) .attr('d', arc) - .classed('disabled', function (d) { return !d.action.enabled(history.graph()); }) - .on('click', function (d) { history.perform(d.action, d.description); }); + .classed('disabled', function (d) { return !d.enabled(graph); }) + .on('click', function (d) { d(history); }); arcs.append('text') .attr("transform", function(d, i) { return "translate(" + arc.centroid(d, i) + ")"; }) .attr("dy", ".35em") .style("text-anchor", "middle") - .text(function(d) { return d.text; }); + .text(function(d) { return d.title; }); }; radialMenu.close = function(selection) { diff --git a/test/index.html b/test/index.html index 859d5b95d..de83d89e0 100644 --- a/test/index.html +++ b/test/index.html @@ -100,6 +100,13 @@ + + + + + + + From 03de3ffba66524518b19ce978de75a337be0cd74 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Tue, 29 Jan 2013 12:13:15 -0500 Subject: [PATCH 16/48] Move operation (fixes #536) --- index.html | 2 ++ js/id/modes/move_way.js | 69 ++++++++++++++++++++++++++++++++++++++++ js/id/modes/select.js | 1 - js/id/operations/move.js | 18 +++++++++++ js/id/ui/radial_menu.js | 7 +++- test/index.html | 2 ++ 6 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 js/id/modes/move_way.js create mode 100644 js/id/operations/move.js diff --git a/index.html b/index.html index cc45f4a48..387f4a0e1 100644 --- a/index.html +++ b/index.html @@ -104,11 +104,13 @@ + + diff --git a/js/id/modes/move_way.js b/js/id/modes/move_way.js new file mode 100644 index 000000000..7fe07d1ce --- /dev/null +++ b/js/id/modes/move_way.js @@ -0,0 +1,69 @@ +iD.modes.MoveWay = function(wayId) { + var mode = { + id: 'move-way' + }; + + var keybinding = d3.keybinding('move-way'); + + mode.enter = function() { + var map = mode.map, + history = mode.history, + graph = history.graph(), + selection = map.surface, + controller = mode.controller, + projection = map.projection; + + var way = graph.entity(wayId), + origin = d3.mouse(selection.node()); + + history.perform( + iD.actions.Noop(), + 'moved a way'); + + function move() { + var p = d3.mouse(selection.node()), + delta = [p[0] - origin[0], + p[1] - origin[1]]; + + origin = p; + + history.replace( + iD.actions.MoveWay(wayId, delta, projection), + 'moved a way'); + } + + function finish() { + d3.event.stopPropagation(); + controller.enter(iD.modes.Select(way, true)); + } + + function cancel() { + history.pop(); + controller.enter(iD.modes.Select(way, true)); + } + + selection + .on('mousemove.move-way', move) + .on('click.move-way', finish); + + keybinding + .on('⎋', cancel) + .on('↩', finish); + + d3.select(document) + .call(keybinding); + }; + + mode.exit = function() { + var map = mode.map, + selection = map.surface; + + selection + .on('mousemove.move-way', null) + .on('click.move-way', null); + + keybinding.off(); + }; + + return mode; +}; diff --git a/js/id/modes/select.js b/js/id/modes/select.js index 8871dd2ec..06c05b7ea 100644 --- a/js/id/modes/select.js +++ b/js/id/modes/select.js @@ -43,7 +43,6 @@ iD.modes.Select = function(entity, initial) { behaviors = [ iD.behavior.Hover(), iD.behavior.DragNode(mode), - iD.behavior.DragWay(mode), iD.behavior.DragMidpoint(mode)]; behaviors.forEach(function(behavior) { diff --git a/js/id/operations/move.js b/js/id/operations/move.js new file mode 100644 index 000000000..9806ede67 --- /dev/null +++ b/js/id/operations/move.js @@ -0,0 +1,18 @@ +iD.operations.Move = function(entityId, mode) { + var operation = function() { + mode.controller.enter(iD.modes.MoveWay(entityId)); + }; + + operation.available = function(graph) { + return graph.entity(entityId).type === 'way'; + }; + + operation.enabled = function() { + return true; + }; + + operation.id = "move"; + operation.title = "Move"; + + return operation; +}; diff --git a/js/id/ui/radial_menu.js b/js/id/ui/radial_menu.js index a891b7d8e..d38ef3679 100644 --- a/js/id/ui/radial_menu.js +++ b/js/id/ui/radial_menu.js @@ -8,6 +8,11 @@ iD.ui.RadialMenu = function(entity, mode) { .map(function (o) { return o(entity.id, mode); }) .filter(function (o) { return o.available(graph); }); + function click(operation) { + d3.event.stopPropagation(); + operation(history); + } + var arc = d3.svg.arc() .outerRadius(70) .innerRadius(30) @@ -28,7 +33,7 @@ iD.ui.RadialMenu = function(entity, mode) { .attr('class', function (d) { return 'radial-menu-item radial-menu-item-' + d.id; }) .attr('d', arc) .classed('disabled', function (d) { return !d.enabled(graph); }) - .on('click', function (d) { d(history); }); + .on('click', click); arcs.append('text') .attr("transform", function(d, i) { return "translate(" + arc.centroid(d, i) + ")"; }) diff --git a/test/index.html b/test/index.html index de83d89e0..00dc91ed5 100644 --- a/test/index.html +++ b/test/index.html @@ -98,11 +98,13 @@ + + From 65baf361439c709d070bb7fe7491eea935e7ac31 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Tue, 29 Jan 2013 13:19:04 -0500 Subject: [PATCH 17/48] Remove unused DragWay behavior --- index.html | 1 - js/id/behavior/drag_way.js | 28 ---------------------------- test/index.html | 1 - 3 files changed, 30 deletions(-) delete mode 100644 js/id/behavior/drag_way.js diff --git a/index.html b/index.html index 387f4a0e1..deadb5add 100644 --- a/index.html +++ b/index.html @@ -92,7 +92,6 @@ - diff --git a/js/id/behavior/drag_way.js b/js/id/behavior/drag_way.js deleted file mode 100644 index 6de8ca252..000000000 --- a/js/id/behavior/drag_way.js +++ /dev/null @@ -1,28 +0,0 @@ -iD.behavior.DragWay = function(mode) { - var history = mode.history, - projection = mode.map.projection; - - return iD.behavior.drag() - .delegate('.casing, .stroke, .area') - .filter(function(d) { - return d && d.id === mode.entity.id; - }) - .origin(function(entity) { - return projection(history.graph().entity(entity.nodes[0]).loc); - }) - .on('start', function() { - history.perform( - iD.actions.Noop()); - }) - .on('move', function(entity) { - d3.event.sourceEvent.stopPropagation(); - history.replace( - iD.actions.MoveWay(entity.id, d3.event.delta, projection), - 'moved a way'); - }) - .on('end', function() { - history.replace( - iD.actions.Noop(), - 'moved a way'); - }); -}; diff --git a/test/index.html b/test/index.html index 00dc91ed5..12cf31886 100644 --- a/test/index.html +++ b/test/index.html @@ -86,7 +86,6 @@ - From 6d6d3ce7fe6570dfcdbf93f808b40cc809437156 Mon Sep 17 00:00:00 2001 From: Saman Bemel-Benrud Date: Tue, 29 Jan 2013 13:23:52 -0500 Subject: [PATCH 18/48] better user icon style. --- css/app.css | 13 ++++++++----- js/id/ui/commit.js | 2 +- js/id/ui/userpanel.js | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/css/app.css b/css/app.css index 8ba20a02c..4cf72174d 100644 --- a/css/app.css +++ b/css/app.css @@ -407,6 +407,14 @@ button[disabled] .label { margin-right: 3px; } +.user-icon { + max-height: 20px; + max-width: 20px; + height: auto; + width: auto; + border-radius: 3px; +} + /* Definitions for every icon */ .icon.browse { background-position: 0px -20px;} .icon.add-point { background-position: -20px -20px;} @@ -961,11 +969,6 @@ div.typeahead a:first-child { right: -30px; } -.user-icon { - max-width: 50px; - max-height: 50px; -} - .modal-section { padding: 20px; } diff --git a/js/id/ui/commit.js b/js/id/ui/commit.js index c624ac91f..29cf64b2f 100644 --- a/js/id/ui/commit.js +++ b/js/id/ui/commit.js @@ -60,7 +60,7 @@ iD.ui.commit = function(map) { user_link .append('img') .attr('src', user.image_url) - .attr('class', 'icon icon-pre-text'); + .attr('class', 'icon icon-pre-text user-icon'); } // Confirm / Cancel Buttons diff --git a/js/id/ui/userpanel.js b/js/id/ui/userpanel.js index 3c087e402..d0d8fa63d 100644 --- a/js/id/ui/userpanel.js +++ b/js/id/ui/userpanel.js @@ -18,7 +18,7 @@ iD.ui.userpanel = function(connection) { // Add thumbnail or dont if (user_details.image_url) { userLink.append('img') - .attr('class', 'icon icon-pre-text') + .attr('class', 'icon icon-pre-text user-icon') .attr('src', user_details.image_url); } else { userLink.append('span') From 852973f61d702fdfd5af117bfa9646909b5068c0 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Tue, 29 Jan 2013 15:03:13 -0500 Subject: [PATCH 19/48] Fix global leak --- js/lib/d3.tail.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/lib/d3.tail.js b/js/lib/d3.tail.js index 0667227ee..4afaf97ff 100644 --- a/js/lib/d3.tail.js +++ b/js/lib/d3.tail.js @@ -32,7 +32,7 @@ d3.tail = function() { function mousemove() { if (text === false) return; var xoffset = ((d3.event.x + tooltip_size[0] + xmargin) > selection_size[0]) ? - -tooltip_size[0] - xmargin : xoffset = xmargin; + -tooltip_size[0] - xmargin : xmargin; container.style(transformProp, 'translate(' + (~~d3.event.x + xoffset) + 'px,' + ~~d3.event.y + 'px)'); From 699041019f300ecdf162331596c5d0078328f507 Mon Sep 17 00:00:00 2001 From: Tom MacWright Date: Tue, 29 Jan 2013 17:02:56 -0500 Subject: [PATCH 20/48] Pan map when dragging to pad. Fixes #534 --- js/id/behavior/drag_node.js | 29 +++++++++++++++++++++++++++++ js/id/renderer/map.js | 10 ++++++++++ 2 files changed, 39 insertions(+) diff --git a/js/id/behavior/drag_node.js b/js/id/behavior/drag_node.js index 084c81895..1bfddfed6 100644 --- a/js/id/behavior/drag_node.js +++ b/js/id/behavior/drag_node.js @@ -1,7 +1,30 @@ iD.behavior.DragNode = function(mode) { var history = mode.history, + size = mode.map.size(), + nudgeInterval, projection = mode.map.projection; + function edge(point) { + var pad = [30, 100, 30, 100]; + if (point[0] > size[0] - pad[0]) return [-10, 0]; + else if (point[0] < pad[2]) return [10, 0]; + else if (point[1] > size[1] - pad[1]) return [0, -10]; + else if (point[1] < pad[3]) return [0, 10]; + return null; + } + + function startNudge(nudge) { + if (nudgeInterval) window.clearInterval(nudgeInterval); + nudgeInterval = window.setInterval(function() { + mode.map.pan(nudge).redraw(); + }, 50); + } + + function stopNudge(nudge) { + if (nudgeInterval) window.clearInterval(nudgeInterval); + nudgeInterval = null; + } + return iD.behavior.drag() .delegate(".node") .origin(function(entity) { @@ -13,11 +36,17 @@ iD.behavior.DragNode = function(mode) { }) .on('move', function(entity) { d3.event.sourceEvent.stopPropagation(); + + var nudge = edge(d3.event.point); + if (nudge) startNudge(nudge); + else stopNudge(); + history.replace( iD.actions.MoveNode(entity.id, projection.invert(d3.event.point)), 'moved a node'); }) .on('end', function() { + stopNudge(); history.replace( iD.actions.Noop(), 'moved a node'); diff --git a/js/id/renderer/map.js b/js/id/renderer/map.js index 60ad3de39..487ac736a 100644 --- a/js/id/renderer/map.js +++ b/js/id/renderer/map.js @@ -258,9 +258,19 @@ iD.Map = function() { t[0] - ll[0] + c[0], t[1] - ll[1] + c[1]]); zoom.translate(projection.translate()); + dispatch.move(map); return true; } + map.pan = function(d) { + var t = projection.translate(); + t[0] += d[0]; + t[1] += d[1]; + projection.translate(t); + zoom.translate(projection.translate()); + return map; + }; + map.size = function(_) { if (!arguments.length) return dimensions; dimensions = _; From f39b502c5a7c6e5a837ae77798ee8dc49ce45a96 Mon Sep 17 00:00:00 2001 From: Saman Bemel-Benrud Date: Tue, 29 Jan 2013 17:41:08 -0500 Subject: [PATCH 21/48] adding operations icons. --- img/source/radial-menu.svg | 13941 +++-------------------------------- img/source/sprite.svg | 294 +- img/sprite.png | Bin 12916 -> 14238 bytes 3 files changed, 1120 insertions(+), 13115 deletions(-) diff --git a/img/source/radial-menu.svg b/img/source/radial-menu.svg index 7c43c61d8..2fa1e44f9 100644 --- a/img/source/radial-menu.svg +++ b/img/source/radial-menu.svg @@ -50,15 +50,15 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="1" - inkscape:cx="-252.25018" - inkscape:cy="571.71412" + inkscape:zoom="4" + inkscape:cx="53.004316" + inkscape:cy="144.37657" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="false" - inkscape:window-width="1287" + inkscape:window-width="1280" inkscape:window-height="753" - inkscape:window-x="159" + inkscape:window-x="37" inkscape:window-y="0" inkscape:window-maximized="0" inkscape:snap-bbox="true" @@ -102,6 +102,14 @@ orientation="0,1" position="1052,739" id="guide15758" /> + + @@ -111,7 +119,7 @@ image/svg+xml - + @@ -119,6959 +127,17 @@ inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Split way + + + + + + + + + + + + Delete + Circularize + Straighten + + Split + + + + Unjoin + Reverse + + + + + + + + + Move + + + + + + + + + + + + Merge + Orthogonalize + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/img/source/sprite.svg b/img/source/sprite.svg index 5589fc2d5..8af12723b 100644 --- a/img/source/sprite.svg +++ b/img/source/sprite.svg @@ -38,22 +38,22 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="1" - inkscape:cx="336.77382" - inkscape:cy="126.79999" + inkscape:zoom="16" + inkscape:cx="174.72757" + inkscape:cy="45.850291" inkscape:document-units="px" inkscape:current-layer="layer12" - showgrid="false" + showgrid="true" inkscape:window-width="1280" inkscape:window-height="756" - inkscape:window-x="119" + inkscape:window-x="240" inkscape:window-y="0" inkscape:window-maximized="0" fit-margin-top="0" fit-margin-left="0" fit-margin-right="0" fit-margin-bottom="0" - showguides="false" + showguides="true" inkscape:guide-bbox="true" inkscape:snap-bbox="true" inkscape:snap-nodes="true"> @@ -181,7 +181,7 @@ image/svg+xml - + @@ -587,20 +587,6 @@ id="path55334" d="m 35,4 c 0,1 0,4 0,4 0,0 0,0.5 -0.5,0.5 C 34,8.5 34.070717,8.22484 34,8 33.695312,7.03125 33.132813,5.63541 33,5 32.795405,4.02115 32.333333,4 32,4 31,4 31,5 31,5 l 1,4 0,3 C 32,12 31.5,11.5 30.5,10.5 29.945312,9.94531 29.257659,9.7508 28.8125,10.00781 28.377049,10.25922 28.150942,10.89541 28.5,11.5 28.853553,12.11237 32,16 32,16 c 1,1 2,1 4,1 2.666667,0 1,0 3,0 2,0 2.288488,-2.86546 3,-5 C 43,9 43.5,7 43.5,7 43.613427,6.57668 43.45711,6.154 43,6 42.119539,5.70338 41.63994,6.35278 41.5,7 41.25,8.15625 41,9 41,9 40.90625,9.31383 41.0013,9.5 40.5,9.5 39.99086,9.5 40,9 40,9 40,9 40,6.33333 40,5 40,4 39,4 39,4 c 0,0 -1,0 -1,1 0,1 0,1.66667 0,3 0,0 0.01305,0.5 -0.5,0.5 C 36.998673,8.5 37,8 37,8 37,8 37,5 37,4 37,3 36,3 36,3 36,3 35,3 35,4 z" style="color:#000000;fill:#222222;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate" /> - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/img/sprite.png b/img/sprite.png index be9ba0fdbdefcc9c8159a1ffdb21b104a6664f18..2bdbc9d8606bc12ffe5b2beded0983ec36c2bc9d 100644 GIT binary patch literal 14238 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 From bfafc8e929c3ac72cc7928e561dd6ae4e4f1f21b Mon Sep 17 00:00:00 2001 From: Saman Bemel-Benrud Date: Tue, 29 Jan 2013 17:56:47 -0500 Subject: [PATCH 22/48] adding css classes for operation icons. --- css/app.css | 44 +++++++++++++++++++++---------------------- img/source/sprite.svg | 35 ++++++++++------------------------ 2 files changed, 32 insertions(+), 47 deletions(-) diff --git a/css/app.css b/css/app.css index 4cf72174d..d82d7d292 100644 --- a/css/app.css +++ b/css/app.css @@ -416,12 +416,12 @@ button[disabled] .label { } /* Definitions for every icon */ -.icon.browse { background-position: 0px -20px;} -.icon.add-point { background-position: -20px -20px;} -.icon.add-line { background-position: -40px -20px;} -.icon.add-area { background-position: -60px -20px;} -.icon.undo { background-position: -80px -20px;} -.icon.redo { background-position: -100px -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;} .icon.apply { background-position: -120px 0px;} .icon.save { background-position: -140px 0px;} @@ -437,18 +437,7 @@ button[disabled] .label { .icon.nearby { background-position: -340px 0px;} .icon.geolocate { background-position: -360px 0px;} .icon.warning { background-position: -380px 0px;} - .icon.close-modal{ background-position: -200px -40px;} - -.icon.invert.zoom-in { background-position: -240px -40px;} - -.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.avatar { background-position: -320px -20px;} .fillD .icon.nearby { background-position: -340px -20px;} @@ -471,13 +460,24 @@ button[disabled] .icon.layers { background-position: -300px -40px;} button[disabled] .icon.avatar { background-position: -320px -40px;} button[disabled] .icon.nearby { background-position: -340px -40px;} -.icon.big-line { background-position: 0px -80px;} -.icon.big-point { background-position: -40px -80px;} -.icon.big-area { background-position: -80px -80px;} -.icon.big-vertex { background-position: -120px -80px;} -.icon.big-inspect { background-position: -160px -80px;} +.icon.big-line { background-position: 0px -80px;} +.icon.big-point { background-position: -40px -80px;} +.icon.big-area { background-position: -80px -80px;} +.icon.big-vertex { background-position: -120px -80px;} +.icon.big-inspect { background-position: -160px -80px;} .icon.big-relation { background-position: -200px -80px;} +.icon.operation.delete { background-position: 0px -140px;} +.icon.operation.circularize { background-position: -20px -140px;} +.icon.operation.straighten { background-position: -40px -140px;} +.icon.operation.split { background-position: -60px -140px;} +.icon.operation.unjoin { background-position: -80px -140px;} +.icon.operation.reverse { background-position: -100px -140px;} +.icon.operation.move { background-position: -120px -140px;} +.icon.operation.merge { background-position: -140px -140px;} +.icon.operation.orthogonalize { background-position: -160px -140px;} + + /* Toggle icon is special */ .toggle.icon { background-position: 0px -180px;} a:hover .toggle.icon { background-position: -20px -180px;} diff --git a/img/source/sprite.svg b/img/source/sprite.svg index 8af12723b..25984e5b2 100644 --- a/img/source/sprite.svg +++ b/img/source/sprite.svg @@ -38,22 +38,22 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="16" - inkscape:cx="174.72757" - inkscape:cy="45.850291" + inkscape:zoom="1" + inkscape:cx="123.06085" + inkscape:cy="91.554201" inkscape:document-units="px" inkscape:current-layer="layer12" showgrid="true" inkscape:window-width="1280" inkscape:window-height="756" - inkscape:window-x="240" + inkscape:window-x="69" inkscape:window-y="0" inkscape:window-maximized="0" fit-margin-top="0" fit-margin-left="0" fit-margin-right="0" fit-margin-bottom="0" - showguides="true" + showguides="false" inkscape:guide-bbox="true" inkscape:snap-bbox="true" inkscape:snap-nodes="true"> @@ -181,7 +181,7 @@ image/svg+xml - + @@ -822,26 +822,11 @@ transform="matrix(2,0,0,2,-1601,221.27564)" style="display:inline"> + style="color:#000000;fill:#c1c1c1;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + d="M 136 92 L 132 96 L 125 96 L 125 104 L 132 104 L 136 108 L 144 108 L 148 104 L 155 104 L 155 96 L 148 96 L 144 92 L 136 92 z M 140 96 C 142.20912 96 144 97.79086 144 100 C 144 102.20914 142.20912 104 140 104 C 137.79088 104 136 102.20914 136 100 C 136 97.79086 137.79088 96 140 96 z " + transform="matrix(0.5,0,0,0.5,813,-110.63782)" + id="path4439" /> - - Date: Tue, 29 Jan 2013 18:34:40 -0500 Subject: [PATCH 23/48] Micro translation framework. --- index.html | 4 ++++ js/id/ui/inspector.js | 6 +++--- js/id/ui/layerswitcher.js | 6 +++--- js/id/ui/notice.js | 2 +- js/id/ui/save.js | 10 +++++----- js/id/ui/success.js | 4 ++-- js/id/ui/tag_reference.js | 2 +- js/id/ui/userpanel.js | 2 +- locale/en.js | 40 +++++++++++++++++++++++++++++++++++++++ locale/locale.js | 11 +++++++++++ 10 files changed, 71 insertions(+), 16 deletions(-) create mode 100644 locale/en.js create mode 100644 locale/locale.js diff --git a/index.html b/index.html index deadb5add..4b12084e5 100644 --- a/index.html +++ b/index.html @@ -125,9 +125,13 @@ + + +
+ + + + From 8d78aa060bf6d973a092ca1c62b79d1b5e7b3ee1 Mon Sep 17 00:00:00 2001 From: Saman Bemel-Benrud Date: Tue, 29 Jan 2013 18:57:14 -0500 Subject: [PATCH 31/48] fix layout for tag reference image. --- css/app.css | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/css/app.css b/css/app.css index 211efc4df..5064b435e 100644 --- a/css/app.css +++ b/css/app.css @@ -988,9 +988,8 @@ div.typeahead a:first-child { } .modal-section img.wiki-image { - max-width: 400px; + max-width: 100%; max-height: 300px; - padding: 10px; display: block; } From 13e7d03395c458f0f0704a089df8af98a84d6907 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Tue, 29 Jan 2013 19:01:49 -0500 Subject: [PATCH 32/48] Fix build --- Makefile | 4 +++- test/index_packaged.html | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 70ac208d6..ddeef62b9 100644 --- a/Makefile +++ b/Makefile @@ -47,7 +47,9 @@ all: \ js/id/svg/*.js \ js/id/ui.js \ js/id/ui/*.js \ - js/id/end.js + js/id/end.js \ + locale/locale.js \ + locale/en.js iD.js: Makefile @rm -f $@ diff --git a/test/index_packaged.html b/test/index_packaged.html index c4eca2cca..7ae72a056 100644 --- a/test/index_packaged.html +++ b/test/index_packaged.html @@ -34,7 +34,6 @@ - From c787d9f4a21f59091900ae25996a9965141cadf4 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Wed, 30 Jan 2013 10:36:11 -0500 Subject: [PATCH 33/48] Add areas to rendering test --- test/rendering.html | 63 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/test/rendering.html b/test/rendering.html index e5347d0b4..9b6bedfe2 100644 --- a/test/rendering.html +++ b/test/rendering.html @@ -4,6 +4,7 @@ Rendering Tests + @@ -123,5 +124,67 @@ .classed(d.mode, d.mode !== 'base'); }); + + + + + + + +
BaseSelected
+ + + From 0dd7bbc1fff84d00a256804accff64f7411a61a6 Mon Sep 17 00:00:00 2001 From: Saman Bemel-Benrud Date: Wed, 30 Jan 2013 10:39:42 -0500 Subject: [PATCH 34/48] update source graphics. --- img/source/sprite.svg | 16 ++++++++-------- img/sprite.png | Bin 14580 -> 14583 bytes 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/img/source/sprite.svg b/img/source/sprite.svg index 6ea063f7d..4d9d877ea 100644 --- a/img/source/sprite.svg +++ b/img/source/sprite.svg @@ -38,22 +38,22 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="4" - inkscape:cx="411.11786" - inkscape:cy="180.48311" + inkscape:zoom="1" + inkscape:cx="257.08321" + inkscape:cy="180.29859" inkscape:document-units="px" inkscape:current-layer="layer12" - showgrid="true" + showgrid="false" inkscape:window-width="1280" - inkscape:window-height="756" - inkscape:window-x="69" + inkscape:window-height="700" + inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="0" fit-margin-top="0" fit-margin-left="0" fit-margin-right="0" fit-margin-bottom="0" - showguides="true" + showguides="false" inkscape:guide-bbox="true" inkscape:snap-bbox="true" inkscape:snap-nodes="true"> @@ -1032,7 +1032,7 @@ d="m 354.5,22.999997 c -1.5,0 -2.5,2 -2.5,3 0,0.666667 0,1.333333 0,2 0,1 1,2.153847 1,2.153847 l 0,0.846153 -1.69231,0.384617 c -1.45419,0.330499 -2.02608,1.236079 -2.15384,2.76923 L 349,35.999998 l 12,0 -0.15385,-1.846154 c -0.12776,-1.533151 -0.69965,-2.438731 -2.15384,-2.76923 L 357,30.999997 l 0,-0.846153 c 0,0 1,-1.153847 1,-2.153847 0,-0.666667 0,-1.333333 0,-2 0,-1 -1,-3 -2.5,-3 z" 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" /> UX% 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 delta 13864 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 kItWuLEn3}E-+q#kpb Date: Wed, 30 Jan 2013 10:45:24 -0500 Subject: [PATCH 35/48] Add background color slider --- test/rendering.html | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/test/rendering.html b/test/rendering.html index 9b6bedfe2..2ec58da95 100644 --- a/test/rendering.html +++ b/test/rendering.html @@ -4,7 +4,6 @@ Rendering Tests - @@ -35,6 +34,20 @@ +
+ + +
+ + + From bfa823f71d500d4b66c14560caadfbf0f0314051 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Wed, 30 Jan 2013 10:57:26 -0500 Subject: [PATCH 36/48] Fix hover --- test/rendering.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/rendering.html b/test/rendering.html index 2ec58da95..196122b2c 100644 --- a/test/rendering.html +++ b/test/rendering.html @@ -119,6 +119,7 @@ }) .enter() .append('td') + .attr('class', function (d) { return d.mode === 'selected' ? 'mode-select' : 'mode-browse'; }) .append('svg') .attr('width', 200) .attr('height', 30) @@ -129,7 +130,7 @@ graph = iD.Graph([a, b, highway]); d3.select(this) - .attr('class', d.mode === 'selected' ? 'mode-select' : 'mode-browse') + .attr('class', 'behavior-hover') .call(vertices, graph, [a, b], filter) .call(lines, graph, [highway], filter) .call(midpoints, graph, [highway], filter) From ec4f4266ade33516ee9cdf6f18da442df855f051 Mon Sep 17 00:00:00 2001 From: Saman Bemel-Benrud Date: Wed, 30 Jan 2013 11:27:03 -0500 Subject: [PATCH 37/48] fix overflow in commit dialog. --- css/app.css | 11 +---------- js/id/ui/commit.js | 1 + 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/css/app.css b/css/app.css index 440bed8e3..f69ba9a07 100644 --- a/css/app.css +++ b/css/app.css @@ -948,11 +948,11 @@ div.typeahead a:first-child { border:1px solid #ccc; background:#fff; max-height: 160px; - overflow: visible; } .commit-modal .warning-section .changeset-list { margin-right: 20px; + overflow-x: visible; } .commit-section.modal-section { @@ -961,15 +961,6 @@ div.typeahead a:first-child { .commit-section.modal-section:last-child { padding-bottom: 20px;} -.commit-modal .changeset-list li { - position: relative; -} - -.commit-modal .changeset-list li button { - position: absolute; - right: -30px; -} - .modal-section { padding: 20px; } diff --git a/js/id/ui/commit.js b/js/id/ui/commit.js index d883b1748..29cf64b2f 100644 --- a/js/id/ui/commit.js +++ b/js/id/ui/commit.js @@ -86,6 +86,7 @@ iD.ui.commit = function(map) { .on('click.cancel', function() { event.cancel(); }); + cancelbutton.append('span').attr('class','icon close icon-pre-text'); cancelbutton.append('span').attr('class','label').text('Cancel'); var warnings = body.selectAll('div.warning-section') From 30d7296a00830ad759a76151c080b06bd782b9ca Mon Sep 17 00:00:00 2001 From: Tom MacWright Date: Wed, 30 Jan 2013 11:38:53 -0500 Subject: [PATCH 38/48] Relative path for loader --- js/id/ui/loading.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/id/ui/loading.js b/js/id/ui/loading.js index 23d5b7c2d..ec6568e5d 100644 --- a/js/id/ui/loading.js +++ b/js/id/ui/loading.js @@ -4,7 +4,7 @@ iD.ui.loading = function(message, blocking) { var loadertext = modal.select('.content') .classed('loading-modal', true) .append('div').attr('class','modal-section fillL'); - loadertext.append('img').attr('class','loader').attr('src', '/img/loader.gif'); + loadertext.append('img').attr('class','loader').attr('src', 'img/loader.gif'); loadertext.append('h3').text(message || ''); return modal; From 6576ec650110f146a05d99bac24c1b6bf2d8bc41 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Wed, 30 Jan 2013 11:56:49 -0500 Subject: [PATCH 39/48] Operation sprites --- css/app.css | 20 +++++++++---------- index.html | 4 ++-- js/id/actions/{circular.js => circularize.js} | 2 +- .../{circular.js => circularize.js} | 8 ++++---- js/id/ui/radial_menu.js | 14 ++++++++----- test/index.html | 4 ++-- 6 files changed, 28 insertions(+), 24 deletions(-) rename js/id/actions/{circular.js => circularize.js} (97%) rename js/id/operations/{circular.js => circularize.js} (83%) diff --git a/css/app.css b/css/app.css index f69ba9a07..1da04f481 100644 --- a/css/app.css +++ b/css/app.css @@ -470,15 +470,15 @@ button[disabled] .icon.nearby { background-position: -340px -40px;} .icon.big-inspect { background-position: -160px -80px;} .icon.big-relation { background-position: -200px -80px;} -.icon.operation.delete { background-position: 0px -140px;} -.icon.operation.circularize { background-position: -20px -140px;} -.icon.operation.straighten { background-position: -40px -140px;} -.icon.operation.split { background-position: -60px -140px;} -.icon.operation.unjoin { background-position: -80px -140px;} -.icon.operation.reverse { background-position: -100px -140px;} -.icon.operation.move { background-position: -120px -140px;} -.icon.operation.merge { background-position: -140px -140px;} -.icon.operation.orthogonalize { background-position: -160px -140px;} +.icon-operation-delete { background-position: 0px -140px;} +.icon-operation-circularize { background-position: -20px -140px;} +.icon-operation-straighten { background-position: -40px -140px;} +.icon-operation-split { background-position: -60px -140px;} +.icon-operation-unjoin { background-position: -80px -140px;} +.icon-operation-reverse { background-position: -100px -140px;} +.icon-operation-move { background-position: -120px -140px;} +.icon-operation-merge { background-position: -140px -140px;} +.icon-operation-orthogonalize { background-position: -160px -140px;} /* Toggle icon is special */ @@ -1195,7 +1195,7 @@ a.success-action { fill: rgba(255,255,255,.5); } -.radial-menu image { +.radial-menu .icon { pointer-events: none; } diff --git a/index.html b/index.html index 4b12084e5..fae1fc940 100644 --- a/index.html +++ b/index.html @@ -81,7 +81,7 @@ - + @@ -107,7 +107,7 @@ - + diff --git a/js/id/actions/circular.js b/js/id/actions/circularize.js similarity index 97% rename from js/id/actions/circular.js rename to js/id/actions/circularize.js index da7965c79..edbd0d8b3 100644 --- a/js/id/actions/circular.js +++ b/js/id/actions/circularize.js @@ -1,4 +1,4 @@ -iD.actions.Circular = function(wayId, map) { +iD.actions.Circularize = function(wayId, map) { var action = function(graph) { var way = graph.entity(wayId), diff --git a/js/id/operations/circular.js b/js/id/operations/circularize.js similarity index 83% rename from js/id/operations/circular.js rename to js/id/operations/circularize.js index eb94150fc..49956430e 100644 --- a/js/id/operations/circular.js +++ b/js/id/operations/circularize.js @@ -1,6 +1,6 @@ -iD.operations.Circular = function(entityId, mode) { +iD.operations.Circularize = function(entityId, mode) { var history = mode.map.history(), - action = iD.actions.Circular(entityId, mode.map); + action = iD.actions.Circularize(entityId, mode.map); var operation = function() { var graph = history.graph(), @@ -30,9 +30,9 @@ iD.operations.Circular = function(entityId, mode) { return action.enabled(graph); }; - operation.id = "circular"; + operation.id = "circularize"; operation.key = "O"; - operation.title = "Circular"; + operation.title = "Circularize"; operation.description = "Make this round"; return operation; diff --git a/js/id/ui/radial_menu.js b/js/id/ui/radial_menu.js index f06fa362e..fe0d7ee86 100644 --- a/js/id/ui/radial_menu.js +++ b/js/id/ui/radial_menu.js @@ -50,11 +50,15 @@ iD.ui.RadialMenu = function(operations) { .on('mouseover', mouseover) .on('mouseout', mouseout); - button.append('image') - .attr('width', 16) - .attr('height', 16) - .attr('transform', 'translate(-8, -8)') - .attr('xlink:href', 'icons/helipad.png'); + var image = button.append('foreignObject') + .style('pointer-events', 'none') + .attr('width', 20) + .attr('height', 20) + .attr('x', -10) + .attr('y', -10); + + image.append('xhtml:span') + .attr('class', function (d) { return 'icon icon-operation icon-operation-' + d.id; }); var tooltip = menu.append('foreignObject') .style('display', 'none') diff --git a/test/index.html b/test/index.html index b682f2cdd..4bdd4b5ba 100644 --- a/test/index.html +++ b/test/index.html @@ -72,7 +72,7 @@ - + @@ -102,7 +102,7 @@ - + From 217577da95f2d8e0b4f195259ab526b84f88a366 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Wed, 30 Jan 2013 12:02:49 -0500 Subject: [PATCH 40/48] Exit MoveWay mode on undo (fixes #562) --- js/id/modes/move_way.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/js/id/modes/move_way.js b/js/id/modes/move_way.js index 7fe07d1ce..1f559da82 100644 --- a/js/id/modes/move_way.js +++ b/js/id/modes/move_way.js @@ -42,10 +42,16 @@ iD.modes.MoveWay = function(wayId) { controller.enter(iD.modes.Select(way, true)); } + function undone() { + controller.enter(iD.modes.Browse()); + } + selection .on('mousemove.move-way', move) .on('click.move-way', finish); + history.on('undone.move-way', undone); + keybinding .on('⎋', cancel) .on('↩', finish); @@ -56,12 +62,15 @@ iD.modes.MoveWay = function(wayId) { mode.exit = function() { var map = mode.map, + history = mode.history, selection = map.surface; selection .on('mousemove.move-way', null) .on('click.move-way', null); + history.on('undone.move-way', null); + keybinding.off(); }; From b50160b4d9607380500f2c39484d589da6751289 Mon Sep 17 00:00:00 2001 From: Saman Bemel-Benrud Date: Wed, 30 Jan 2013 15:29:10 -0500 Subject: [PATCH 41/48] more screwing around with button styles. --- css/app.css | 50 ++++++++++------- img/source/sprite.svg | 127 ++++++++++++++---------------------------- img/sprite.png | Bin 14583 -> 14025 bytes js/id/ui/commit.js | 1 - js/id/ui/inspector.js | 6 +- 5 files changed, 77 insertions(+), 107 deletions(-) diff --git a/css/app.css b/css/app.css index 1da04f481..0ba223a99 100644 --- a/css/app.css +++ b/css/app.css @@ -283,11 +283,11 @@ button.minor { width: 20px; border: 0; box-shadow: none; - background-color: transparent; + background: rgba(0,0,0,.5); } button.minor:hover { - background: white; + background: #222; } button.centered { @@ -319,6 +319,8 @@ button.centered { border-radius:0 4px 4px 0; } +button.Browse .label { display: none;} + button.action { background: #7092ff; } @@ -431,13 +433,13 @@ button[disabled] .label { .icon.inspect { background-position: -220px 0px;} .icon.zoom-in { background-position: -240px 0px;} .icon.zoom-out { background-position: -260px 0px;} +.icon.plus { background-position: -240px 0px;} .icon.geocode { background-position: -280px 0px;} .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.warning { background-position: -380px 0px;} -.icon.plus { background-position: -400px 0px;} .icon.close-modal { background-position: -200px -40px;} @@ -613,16 +615,20 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;} } .inspector-inner .add-tag { - width: 40%; + width: 20%; height: 30px; - border: 1px solid #ccc; border-top: 0; - background: white; + background: rgba(0,0,0,.5); border-radius: 0 0 4px 4px; - } - .inspector-inner .add-tag:hover { - background: #ececec; - } +} +.inspector-inner .add-tag:hover { + background: rgba(0,0,0,.8); +} + +.inspector-inner .add-tag .label { + display: none; +} + /* Map Controls */ .map-control { @@ -632,12 +638,13 @@ 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,.5); + border-radius: 0; + border-bottom: 1px solid rgba(0, 0, 0, 1); } .map-control button:hover { - background: rgba(0, 0, 0, .9); + background: rgba(0, 0, 0, .8); } .map-control button.active:hover { @@ -662,18 +669,16 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;} .zoombuttons button.zoom-in { 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 0; } /* Layer Switcher */ .layerswitcher-control { - top:210px; + top:190px; } .layerswitcher-control .adjustments button { @@ -744,7 +749,7 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;} /* Geocoder */ .geocode-control { - top:160px; + top:150px; } .geocode-control input { @@ -753,8 +758,15 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;} margin: 4px; } +/* Geolocator */ + .geolocate-control { - top:260px; + top:230px; +} + +.geolocate-control button { + border-radius: 0 0 4px 0; + border-bottom: 0; } /* Map @@ -1214,5 +1226,5 @@ a.success-action { span.label {display: none;} /* override hide for save button */ .icon.icon-pre-text { margin-right: 0px;} - .save .label { display: block;} + .save .label, .apply .label { display: block;} } diff --git a/img/source/sprite.svg b/img/source/sprite.svg index 4d9d877ea..4cc5abb47 100644 --- a/img/source/sprite.svg +++ b/img/source/sprite.svg @@ -38,9 +38,9 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="1" - inkscape:cx="257.08321" - inkscape:cy="180.29859" + inkscape:zoom="4" + inkscape:cx="230.7911" + inkscape:cy="190.13176" inkscape:document-units="px" inkscape:current-layer="layer12" showgrid="false" @@ -53,7 +53,7 @@ fit-margin-left="0" fit-margin-right="0" fit-margin-bottom="0" - showguides="false" + showguides="true" inkscape:guide-bbox="true" inkscape:snap-bbox="true" inkscape:snap-nodes="true"> @@ -279,6 +279,11 @@ id="layer12" inkscape:label="sprite" transform="translate(-25,3.0625001e-6)"> + - - - - - - - - - - - - - - - - + + + + + + + diff --git a/img/sprite.png b/img/sprite.png index 3c4a93b63c75d86cae923c21d238c571aa4570fc..b0f45f2cd6b06d74235373880618d7a550ef047f 100644 GIT binary patch literal 14025 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 Date: Wed, 30 Jan 2013 12:42:34 -0500 Subject: [PATCH 42/48] Change the midpoint data a bit Store the ways which share the segment and the index of the segment. This will be used in both DragWay and Draw behaviors. --- js/id/behavior/drag_midpoint.js | 34 ++++++++++----------- js/id/svg/midpoints.js | 20 ++++++------- test/index.html | 1 + test/index_packaged.html | 1 + test/spec/svg/midpoints.js | 52 +++++++++++++++++++++++++++++++++ 5 files changed, 79 insertions(+), 29 deletions(-) create mode 100644 test/spec/svg/midpoints.js diff --git a/js/id/behavior/drag_midpoint.js b/js/id/behavior/drag_midpoint.js index 9f73a7115..e0b0c7a1a 100644 --- a/js/id/behavior/drag_midpoint.js +++ b/js/id/behavior/drag_midpoint.js @@ -1,29 +1,26 @@ iD.behavior.DragMidpoint = function(mode) { var history = mode.history, - projection = mode.map.projection, - behavior = iD.behavior.drag() + projection = mode.map.projection; + + var behavior = iD.behavior.drag() .delegate(".midpoint") .origin(function(d) { return projection(d.loc); }) .on('start', function(d) { - var w, nds; - d.node = iD.Node({loc: d.loc}); - var args = [iD.actions.AddNode(d.node)]; - for (var i = 0; i < d.ways.length; i++) { - w = d.ways[i], nds = w.nodes; - for (var j = 0; j < nds.length; j++) { - if ((nds[j] === d.nodes[0] && nds[j + 1] === d.nodes[1]) || - (nds[j] === d.nodes[1] && nds[j + 1] === d.nodes[0])) { - args.push(iD.actions.AddWayNode(w.id, d.node.id, j + 1)); - } - } - } - history.perform.apply(history, args); - var node = d3.selectAll('.node.vertex') - .filter(function(data) { return data.id === d.node.id; }); - behavior.target(node.node(), node.datum()); + var node = iD.Node({loc: d.loc}); + var args = [iD.actions.AddNode(node)]; + for (var i = 0; i < d.ways.length; i++) { + args.push(iD.actions.AddWayNode(d.ways[i].id, node.id, d.ways[i].index)); + } + + history.perform.apply(history, args); + + var vertex = d3.selectAll('.vertex') + .filter(function(data) { return data.id === node.id; }); + + behavior.target(vertex.node(), vertex.datum()); }) .on('move', function(d) { d3.event.sourceEvent.stopPropagation(); @@ -35,5 +32,6 @@ iD.behavior.DragMidpoint = function(mode) { iD.actions.Noop(), 'added a node to a way'); }); + return behavior; }; diff --git a/js/id/svg/midpoints.js b/js/id/svg/midpoints.js index 655e35013..da4af659c 100644 --- a/js/id/svg/midpoints.js +++ b/js/id/svg/midpoints.js @@ -15,19 +15,17 @@ iD.svg.Midpoints = function(projection) { b = nodes[j + 1], id = [a.id, b.id].sort().join('-'); - if (!midpoints[id] && - iD.geo.dist(projection(a.loc), projection(b.loc)) > 40) { - - var midpoint_loc = iD.geo.interp(a.loc, b.loc, 0.5), - parents = _.intersection(graph.parentWays(a), - graph.parentWays(b)); + if (midpoints[id]) { + midpoints[id].ways.push({id: entity.id, index: j + 1}); + } else if (iD.geo.dist(projection(a.loc), projection(b.loc)) > 40) { midpoints[id] = { - loc: midpoint_loc, - ways: parents, - nodes: [a.id, b.id], + midpoint: true, id: id, - midpoint: true + loc: iD.geo.interp(a.loc, b.loc, 0.5), + a: a.id, + b: b.id, + ways: [{id: entity.id, index: j + 1}] }; } } @@ -35,7 +33,7 @@ iD.svg.Midpoints = function(projection) { var groups = surface.select('.layer-hit').selectAll('g.midpoint') .filter(filter) - .data(_.values(midpoints), function (d) { return [d.parents, d.id].join(","); }); + .data(_.values(midpoints), function (d) { return d.id; }); var group = groups.enter() .insert('g', ':first-child') diff --git a/test/index.html b/test/index.html index 4bdd4b5ba..97cd63b9b 100644 --- a/test/index.html +++ b/test/index.html @@ -170,6 +170,7 @@ + diff --git a/test/index_packaged.html b/test/index_packaged.html index 7ae72a056..25093d5b3 100644 --- a/test/index_packaged.html +++ b/test/index_packaged.html @@ -65,6 +65,7 @@ + diff --git a/test/spec/svg/midpoints.js b/test/spec/svg/midpoints.js new file mode 100644 index 000000000..c34ac0350 --- /dev/null +++ b/test/spec/svg/midpoints.js @@ -0,0 +1,52 @@ +describe("iD.svg.Midpoints", function () { + var surface, + projection = Object, + filter = d3.functor(true); + + beforeEach(function () { + surface = d3.select(document.createElementNS('http://www.w3.org/2000/svg', 'svg')) + .call(iD.svg.Surface()); + }); + + it("finds the location of the midpoints", function () { + var a = iD.Node({loc: [0, 0]}), + b = iD.Node({loc: [50, 0]}), + line = iD.Way({nodes: [a.id, b.id]}), + graph = iD.Graph([a, b, line]); + + surface.call(iD.svg.Midpoints(projection), graph, [line], filter); + + expect(surface.select('.midpoint').datum().loc).to.eql([25, 0]); + }); + + it("doesn't create midpoints on segments with pixel length less than 40", function () { + var a = iD.Node({loc: [0, 0]}), + b = iD.Node({loc: [39, 0]}), + line = iD.Way({nodes: [a.id, b.id]}), + graph = iD.Graph([a, b, line]); + + surface.call(iD.svg.Midpoints(projection), graph, [line], filter); + + expect(surface.selectAll('.midpoint')[0]).to.have.length(0); + }); + + it("binds a datum whose 'ways' property lists ways which include the segement", function () { + var a = iD.Node({loc: [0, 0]}), + b = iD.Node({loc: [50, 0]}), + c = iD.Node({loc: [1, 1]}), + d = iD.Node({loc: [2, 2]}), + l1 = iD.Way({nodes: [a.id, b.id]}), + l2 = iD.Way({nodes: [b.id, a.id]}), + l3 = iD.Way({nodes: [c.id, a.id, b.id, d.id]}), + l4 = iD.Way({nodes: [a.id, d.id, b.id]}), + graph = iD.Graph([a, b, c, d, l1, l2, l3, l4]), + ab = function (d) { return d.id === [a.id, b.id].sort().join("-"); }; + + surface.call(iD.svg.Midpoints(projection), graph, [l1, l2, l3, l4], filter); + + expect(surface.selectAll('.midpoint').filter(ab).datum().ways).to.eql([ + {id: l1.id, index: 1}, + {id: l2.id, index: 1}, + {id: l3.id, index: 2}]); + }); +}); From e381b6ab261b9d83875c7c2ad6edf92bbaa5e860 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Wed, 30 Jan 2013 15:44:21 -0500 Subject: [PATCH 43/48] Extract AddMidpoint action --- index.html | 1 + js/id/actions/add_midpoint.js | 11 +++++++++++ js/id/behavior/drag_midpoint.js | 9 ++------- test/index.html | 2 ++ test/index_packaged.html | 1 + test/spec/actions/add_midpoint.js | 22 ++++++++++++++++++++++ 6 files changed, 39 insertions(+), 7 deletions(-) create mode 100644 js/id/actions/add_midpoint.js create mode 100644 test/spec/actions/add_midpoint.js diff --git a/index.html b/index.html index fae1fc940..5f62b0f8f 100644 --- a/index.html +++ b/index.html @@ -73,6 +73,7 @@ + diff --git a/js/id/actions/add_midpoint.js b/js/id/actions/add_midpoint.js new file mode 100644 index 000000000..c0cb97f59 --- /dev/null +++ b/js/id/actions/add_midpoint.js @@ -0,0 +1,11 @@ +iD.actions.AddMidpoint = function(midpoint, node) { + return function(graph) { + graph = graph.replace(node.move(midpoint.loc)); + + midpoint.ways.forEach(function(way) { + graph = graph.replace(graph.entity(way.id).addNode(node.id, way.index)); + }); + + return graph; + }; +}; diff --git a/js/id/behavior/drag_midpoint.js b/js/id/behavior/drag_midpoint.js index e0b0c7a1a..72691a512 100644 --- a/js/id/behavior/drag_midpoint.js +++ b/js/id/behavior/drag_midpoint.js @@ -8,14 +8,9 @@ iD.behavior.DragMidpoint = function(mode) { return projection(d.loc); }) .on('start', function(d) { - var node = iD.Node({loc: d.loc}); + var node = iD.Node(); - var args = [iD.actions.AddNode(node)]; - for (var i = 0; i < d.ways.length; i++) { - args.push(iD.actions.AddWayNode(d.ways[i].id, node.id, d.ways[i].index)); - } - - history.perform.apply(history, args); + history.perform(iD.actions.AddMidpoint(d, node)); var vertex = d3.selectAll('.vertex') .filter(function(data) { return data.id === node.id; }); diff --git a/test/index.html b/test/index.html index 97cd63b9b..731800f62 100644 --- a/test/index.html +++ b/test/index.html @@ -68,6 +68,7 @@ + @@ -137,6 +138,7 @@ + diff --git a/test/index_packaged.html b/test/index_packaged.html index 25093d5b3..aba99ba04 100644 --- a/test/index_packaged.html +++ b/test/index_packaged.html @@ -32,6 +32,7 @@ + diff --git a/test/spec/actions/add_midpoint.js b/test/spec/actions/add_midpoint.js new file mode 100644 index 000000000..1f749217e --- /dev/null +++ b/test/spec/actions/add_midpoint.js @@ -0,0 +1,22 @@ +describe("iD.actions.AddMidpoint", function () { + it("adds the node at the midpoint location", function () { + var node = iD.Node(), + midpoint = {loc: [1, 2], ways: []}, + graph = iD.actions.AddMidpoint(midpoint, node)(iD.Graph()); + + expect(graph.entity(node.id).loc).to.eql([1, 2]); + }); + + it("adds the node to all ways at the respective indexes", function () { + var node = iD.Node(), + a = iD.Node(), + b = iD.Node(), + w1 = iD.Way(), + w2 = iD.Way({nodes: [a.id, b.id]}), + midpoint = {loc: [1, 2], ways: [{id: w1.id, index: 0}, {id: w2.id, index: 1}]}, + graph = iD.actions.AddMidpoint(midpoint, node)(iD.Graph([a, b, w1, w2])); + + expect(graph.entity(w1.id).nodes).to.eql([node.id]); + expect(graph.entity(w2.id).nodes).to.eql([a.id, node.id, b.id]); + }); +}); From c1348e231e0c7bcd18f92689170ba390c5d53ded Mon Sep 17 00:00:00 2001 From: Saman Bemel-Benrud Date: Wed, 30 Jan 2013 15:54:36 -0500 Subject: [PATCH 44/48] fix inspect icon on warnings. --- css/app.css | 98 +++++++++++++++++++++--------------------- img/source/sprite.svg | 6 +-- img/sprite.png | Bin 14025 -> 14014 bytes 3 files changed, 53 insertions(+), 51 deletions(-) diff --git a/css/app.css b/css/app.css index 0ba223a99..054863230 100644 --- a/css/app.css +++ b/css/app.css @@ -929,50 +929,6 @@ div.typeahead a:first-child { left:0px; right:0px; top:0px; bottom:0px; } -.commit-modal .user-info { - display: inline-block; -} - -.commit-modal .commit-info { - margin-top: 10px; -} - -.commit-modal .user-info img { - float: left; -} - -.commit-modal h3 small.count { - margin-right: 10px; - text-align: center; - float: left; - height: 12px; - min-width: 12px; - font-size:12px; - line-height: 12px; - border-radius:24px; - padding:5px; - background:#7092ff; - color:#fff; -} - -.commit-modal .changeset-list { - overflow: auto; - border:1px solid #ccc; - background:#fff; - max-height: 160px; -} - -.commit-modal .warning-section .changeset-list { - margin-right: 20px; - overflow-x: visible; -} - -.commit-section.modal-section { - padding-bottom: 0; -} - -.commit-section.modal-section:last-child { padding-bottom: 20px;} - .modal-section { padding: 20px; } @@ -1007,6 +963,56 @@ div.typeahead a:first-child { display:none; } +.loading-modal { + text-align: center; +} + +/* Commit Modal +------------------------------------------------------- */ + +.commit-modal .user-info { + display: inline-block; +} + +.commit-modal .commit-info { + margin-top: 10px; +} + +.commit-modal .user-info img { + float: left; +} + +.commit-modal h3 small.count { + margin-right: 10px; + text-align: center; + float: left; + height: 12px; + min-width: 12px; + font-size:12px; + line-height: 12px; + border-radius:24px; + padding:5px; + background:#7092ff; + color:#fff; +} + +.commit-modal .changeset-list { + overflow: auto; + border:1px solid #ccc; + background:#fff; + max-height: 160px; +} + +.commit-modal .warning-section .changeset-list button { + float: right; +} + +.commit-section.modal-section { + padding-bottom: 0; +} + +.commit-section.modal-section:last-child { padding-bottom: 20px;} + .changeset-list li { border-top:1px solid #ccc; padding:5px 10px; @@ -1029,10 +1035,6 @@ div.typeahead a:first-child { font:normal 12px/20px 'Helvetica Neue', Arial, sans-serif; } -.loading-modal { - text-align: center; -} - /* Success ------------------------------------------------------- */ a.success-action { diff --git a/img/source/sprite.svg b/img/source/sprite.svg index 4cc5abb47..01a28e513 100644 --- a/img/source/sprite.svg +++ b/img/source/sprite.svg @@ -39,8 +39,8 @@ inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="4" - inkscape:cx="230.7911" - inkscape:cy="190.13176" + inkscape:cx="332.2911" + inkscape:cy="175.13176" inkscape:document-units="px" inkscape:current-layer="layer12" showgrid="false" @@ -733,7 +733,7 @@ inkscape:export-xdpi="90" inkscape:export-ydpi="90" /> diff --git a/img/sprite.png b/img/sprite.png index b0f45f2cd6b06d74235373880618d7a550ef047f..5922c06c17edfe79b8f96c5f48cc97092487fadf 100644 GIT binary patch delta 13286 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 `&vlbT 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 delta 13300 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 O^-xV4S*&6f`2PSXCA5VA From dbac370c71979dc7992619d2634cf01c19d812ac Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Wed, 30 Jan 2013 14:07:52 -0500 Subject: [PATCH 45/48] More draw refactoring --- js/id/behavior/add_way.js | 28 ++++++--------------- js/id/behavior/draw.js | 17 ++++++++++--- js/id/behavior/draw_way.js | 51 +++++++++++++++----------------------- js/id/modes/add_point.js | 18 +++++++++++--- js/id/modes/draw_area.js | 34 ++++++++----------------- js/id/modes/draw_line.js | 41 ++++++++---------------------- 6 files changed, 76 insertions(+), 113 deletions(-) diff --git a/js/id/behavior/add_way.js b/js/id/behavior/add_way.js index 021377890..8eacd9372 100644 --- a/js/id/behavior/add_way.js +++ b/js/id/behavior/add_way.js @@ -1,25 +1,16 @@ iD.behavior.AddWay = function(mode) { var map = mode.map, - history = mode.history, controller = mode.controller, event = d3.dispatch('startFromNode', 'startFromWay', 'start'), - draw; - - function add(datum) { - if (datum.type === 'node') { - event.startFromNode(datum); - } else if (datum.type === 'way') { - var choice = iD.geo.chooseIndex(datum, d3.mouse(map.surface.node()), map); - event.startFromWay(datum, choice.loc, choice.index); - } else if (datum.midpoint) { - var way = history.graph().entity(datum.way); - event.startFromWay(way, datum.loc, datum.index); - } else { - event.start(map.mouseCoordinates()); - } - } + draw = iD.behavior.Draw(map); var addWay = function(surface) { + draw.on('click', event.start) + .on('clickNode', event.startFromNode) + .on('clickWay', event.startFromWay) + .on('cancel', addWay.cancel) + .on('finish', addWay.cancel); + map.fastEnable(false) .minzoom(16) .dblclickEnable(false); @@ -43,10 +34,5 @@ iD.behavior.AddWay = function(mode) { controller.exit(); }; - draw = iD.behavior.Draw() - .on('add', add) - .on('cancel', addWay.cancel) - .on('finish', addWay.cancel); - return d3.rebind(addWay, event, 'on'); }; diff --git a/js/id/behavior/draw.js b/js/id/behavior/draw.js index 4d0153505..41e7fe2a9 100644 --- a/js/id/behavior/draw.js +++ b/js/id/behavior/draw.js @@ -1,5 +1,5 @@ -iD.behavior.Draw = function () { - var event = d3.dispatch('move', 'add', 'undo', 'cancel', 'finish'), +iD.behavior.Draw = function(map) { + var event = d3.dispatch('move', 'click', 'clickNode', 'clickWay', 'undo', 'cancel', 'finish'), keybinding = d3.keybinding('draw'), down, surface, hover; @@ -26,7 +26,18 @@ iD.behavior.Draw = function () { } function click() { - event.add(datum()); + var d = datum(); + if (d.type === 'node') { + event.clickNode(d); + } else if (d.type === 'way') { + var choice = iD.geo.chooseIndex(d, d3.mouse(map.surface.node()), map); + event.clickWay(d, choice.loc, choice.index); + } else if (d.midpoint) { + var way = history.graph().entity(d.way); + event.clickWay(way, d.loc, d.index); + } else { + event.click(map.mouseCoordinates()); + } } function keydown() { diff --git a/js/id/behavior/draw_way.js b/js/id/behavior/draw_way.js index 63526df7a..3bcef869d 100644 --- a/js/id/behavior/draw_way.js +++ b/js/id/behavior/draw_way.js @@ -1,11 +1,11 @@ -iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode, baseGraph) { +iD.behavior.DrawWay = function(wayId, index, mode, baseGraph) { var map = mode.map, history = mode.history, controller = mode.controller, - event = d3.dispatch('add', 'addHead', 'addTail', 'addNode', 'addWay'), way = mode.history.graph().entity(wayId), finished = false, - draw; + annotation = 'added to a way', + draw = iD.behavior.Draw(map); var node = iD.Node({loc: map.mouseCoordinates()}), nodeId = node.id; @@ -26,29 +26,19 @@ iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode, baseGraph) { history.replace(iD.actions.MoveNode(nodeId, loc)); } - function add(datum) { - if (datum.id === headId) { - event.addHead(datum); - } else if (datum.id === tailId) { - event.addTail(datum); - } else if (datum.type === 'node' && datum.id !== nodeId) { - event.addNode(datum); - } else if (datum.type === 'way') { - var choice = iD.geo.chooseIndex(datum, d3.mouse(map.surface.node()), map); - event.addWay(datum, choice.loc, choice.index); - } else if (datum.midpoint) { - var way = history.graph().entity(datum.way); - event.addWay(way, datum.loc, datum.index); - } else { - event.add(map.mouseCoordinates()); - } - } - function undone() { controller.enter(iD.modes.Browse()); } var drawWay = function(surface) { + draw.on('move', move) + .on('click', drawWay.add) + .on('clickNode', drawWay.addNode) + .on('clickWay', drawWay.addWay) + .on('undo', history.undo) + .on('cancel', drawWay.cancel) + .on('finish', drawWay.finish); + map.fastEnable(false) .minzoom(16) .dblclickEnable(false); @@ -80,6 +70,12 @@ iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode, baseGraph) { history.on('undone.draw', null); }; + drawWay.annotation = function(_) { + if (!arguments.length) return annotation; + annotation = _; + return drawWay; + }; + function ReplaceTemporaryNode(newNode) { return function(graph) { return graph @@ -89,7 +85,7 @@ iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode, baseGraph) { } // Connect the way to an existing node and continue drawing. - drawWay.addNode = function(node, annotation) { + drawWay.addNode = function(node) { history.perform( ReplaceTemporaryNode(node), annotation); @@ -99,7 +95,7 @@ iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode, baseGraph) { }; // Connect the way to an existing way. - drawWay.addWay = function(way, loc, wayIndex, annotation) { + drawWay.addWay = function(way, loc, wayIndex) { var newNode = iD.Node({loc: loc}); history.perform( @@ -113,7 +109,7 @@ iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode, baseGraph) { }; // Accept the current position of the temporary node and continue drawing. - drawWay.add = function(loc, annotation) { + drawWay.add = function(loc) { var newNode = iD.Node({loc: loc}); history.replace( @@ -149,12 +145,5 @@ iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode, baseGraph) { controller.enter(iD.modes.Browse()); }; - draw = iD.behavior.Draw() - .on('move', move) - .on('add', add) - .on('undo', history.undo) - .on('cancel', drawWay.cancel) - .on('finish', drawWay.finish); - return d3.rebind(drawWay, event, 'on'); }; diff --git a/js/id/modes/add_point.js b/js/id/modes/add_point.js index 1a51c314d..1bcfc5d04 100644 --- a/js/id/modes/add_point.js +++ b/js/id/modes/add_point.js @@ -16,8 +16,8 @@ iD.modes.AddPoint = function() { map.tail('Click on the map to add a point.', true); - function add() { - var node = iD.Node({loc: map.mouseCoordinates()}); + function add(loc) { + var node = iD.Node({loc: loc}); history.perform( iD.actions.AddNode(node), @@ -26,12 +26,22 @@ iD.modes.AddPoint = function() { controller.enter(iD.modes.Select(node, true)); } + function addWay(way, loc, index) { + add(loc); + } + + function addNode(node) { + add(node.loc); + } + function cancel() { controller.exit(); } - behavior = iD.behavior.Draw() - .on('add', add) + behavior = iD.behavior.Draw(map) + .on('click', add) + .on('clickWay', addWay) + .on('clickNode', addNode) .on('cancel', cancel) .on('finish', cancel) (surface); diff --git a/js/id/modes/draw_area.js b/js/id/modes/draw_area.js index 721452bae..8423ff436 100644 --- a/js/id/modes/draw_area.js +++ b/js/id/modes/draw_area.js @@ -8,33 +8,21 @@ iD.modes.DrawArea = function(wayId, baseGraph) { mode.enter = function() { var way = mode.history.graph().entity(wayId), - index = -1, headId = way.nodes[way.nodes.length - 2], - tailId = way.first(), - annotation = way.isDegenerate() ? 'started an area' : 'continued an area'; + tailId = way.first(); - function addHeadTail() { - behavior.finish(); - } + behavior = iD.behavior.DrawWay(wayId, -1, mode, baseGraph) + .annotation(way.isDegenerate() ? 'started an area' : 'continued an area'); - function addNode(node) { - behavior.addNode(node, annotation); - } + var addNode = behavior.addNode; - function addWay(way, loc, index) { - behavior.addWay(way, loc, index, annotation); - } - - function add(loc) { - behavior.add(loc, annotation); - } - - behavior = iD.behavior.DrawWay(wayId, headId, tailId, index, mode, baseGraph) - .on('addHead', addHeadTail) - .on('addTail', addHeadTail) - .on('addNode', addNode) - .on('addWay', addWay) - .on('add', add); + behavior.addNode = function(node) { + if (node.id === headId || node.id === tailId) { + behavior.finish(); + } else { + addNode(node); + } + }; mode.map.surface.call(behavior); mode.map.tail('Click to add points to your area. Click the first point to finish the area.', true); diff --git a/js/id/modes/draw_line.js b/js/id/modes/draw_line.js index 289d91c14..5dee157b3 100644 --- a/js/id/modes/draw_line.js +++ b/js/id/modes/draw_line.js @@ -9,41 +9,20 @@ iD.modes.DrawLine = function(wayId, direction, baseGraph) { mode.enter = function() { var way = mode.history.graph().entity(wayId), index = (direction === 'forward') ? undefined : 0, - headId = (direction === 'forward') ? way.last() : way.first(), - tailId = (direction === 'forward') ? way.first() : way.last(), - annotation = way.isDegenerate() ? 'started a line' : 'continued a line'; + headId = (direction === 'forward') ? way.last() : way.first(); - function addHead() { - behavior.finish(); - } + behavior = iD.behavior.DrawWay(wayId, index, mode, baseGraph) + .annotation(way.isDegenerate() ? 'started a line' : 'continued a line'); - function addTail(node) { - // connect the way in a loop - if (way.nodes.length > 2) { - behavior.addNode(node, annotation); + var addNode = behavior.addNode; + + behavior.addNode = function(node) { + if (node.id === headId) { + behavior.finish(); } else { - behavior.cancel(); + addNode(node); } - } - - function addNode(node) { - behavior.addNode(node, annotation); - } - - function addWay(way, loc, index) { - behavior.addWay(way, loc, index, annotation); - } - - function add(loc) { - behavior.add(loc, annotation); - } - - behavior = iD.behavior.DrawWay(wayId, headId, tailId, index, mode, baseGraph) - .on('addHead', addHead) - .on('addTail', addTail) - .on('addNode', addNode) - .on('addWay', addWay) - .on('add', add); + }; mode.map.surface.call(behavior); mode.map.tail('Click to add more points to the line. ' + From 168a3b5e2668daace5a025a951cca785d654bfe7 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Wed, 30 Jan 2013 15:59:13 -0500 Subject: [PATCH 46/48] Fix drawing on midpoints (fixes #559) --- js/id/behavior/add_way.js | 5 +++-- js/id/behavior/draw.js | 14 ++++++++------ js/id/behavior/draw_way.js | 16 +++++++++++++++- js/id/modes/add_area.js | 15 +++++++++++++++ js/id/modes/add_line.js | 14 ++++++++++++++ js/id/modes/add_point.js | 1 + 6 files changed, 56 insertions(+), 9 deletions(-) diff --git a/js/id/behavior/add_way.js b/js/id/behavior/add_way.js index 8eacd9372..fa038d201 100644 --- a/js/id/behavior/add_way.js +++ b/js/id/behavior/add_way.js @@ -1,13 +1,14 @@ iD.behavior.AddWay = function(mode) { var map = mode.map, controller = mode.controller, - event = d3.dispatch('startFromNode', 'startFromWay', 'start'), + event = d3.dispatch('start', 'startFromWay', 'startFromNode', 'startFromMidpoint'), draw = iD.behavior.Draw(map); var addWay = function(surface) { draw.on('click', event.start) - .on('clickNode', event.startFromNode) .on('clickWay', event.startFromWay) + .on('clickNode', event.startFromNode) + .on('clickMidpoint', event.startFromMidpoint) .on('cancel', addWay.cancel) .on('finish', addWay.cancel); diff --git a/js/id/behavior/draw.js b/js/id/behavior/draw.js index 41e7fe2a9..783d9e42c 100644 --- a/js/id/behavior/draw.js +++ b/js/id/behavior/draw.js @@ -1,5 +1,5 @@ iD.behavior.Draw = function(map) { - var event = d3.dispatch('move', 'click', 'clickNode', 'clickWay', 'undo', 'cancel', 'finish'), + var event = d3.dispatch('move', 'click', 'clickWay', 'clickNode', 'clickMidpoint', 'undo', 'cancel', 'finish'), keybinding = d3.keybinding('draw'), down, surface, hover; @@ -27,14 +27,16 @@ iD.behavior.Draw = function(map) { function click() { var d = datum(); - if (d.type === 'node') { - event.clickNode(d); - } else if (d.type === 'way') { + if (d.type === 'way') { var choice = iD.geo.chooseIndex(d, d3.mouse(map.surface.node()), map); event.clickWay(d, choice.loc, choice.index); + + } else if (d.type === 'node') { + event.clickNode(d); + } else if (d.midpoint) { - var way = history.graph().entity(d.way); - event.clickWay(way, d.loc, d.index); + event.clickMidpoint(d); + } else { event.click(map.mouseCoordinates()); } diff --git a/js/id/behavior/draw_way.js b/js/id/behavior/draw_way.js index 3bcef869d..1103bc143 100644 --- a/js/id/behavior/draw_way.js +++ b/js/id/behavior/draw_way.js @@ -33,8 +33,9 @@ iD.behavior.DrawWay = function(wayId, index, mode, baseGraph) { var drawWay = function(surface) { draw.on('move', move) .on('click', drawWay.add) - .on('clickNode', drawWay.addNode) .on('clickWay', drawWay.addWay) + .on('clickNode', drawWay.addNode) + .on('clickMidpoint', drawWay.addMidpoint) .on('undo', history.undo) .on('cancel', drawWay.cancel) .on('finish', drawWay.finish); @@ -121,6 +122,19 @@ iD.behavior.DrawWay = function(wayId, index, mode, baseGraph) { controller.enter(mode); }; + // Add a midpoint, connect the way to it, and continue drawing. + drawWay.addMidpoint = function(midpoint) { + var node = iD.Node(); + + history.perform( + iD.actions.AddMidpoint(midpoint, node), + ReplaceTemporaryNode(node), + annotation); + + finished = true; + controller.enter(mode); + }; + // Finish the draw operation, removing the temporary node. If the way has enough // nodes to be valid, it's selected. Otherwise, return to browse mode. drawWay.finish = function() { diff --git a/js/id/modes/add_area.js b/js/id/modes/add_area.js index d1a3efb08..153060b3a 100644 --- a/js/id/modes/add_area.js +++ b/js/id/modes/add_area.js @@ -15,6 +15,20 @@ iD.modes.AddArea = function() { history = mode.history, controller = mode.controller; + function startFromMidpoint(midpoint) { + var graph = history.graph(), + node = iD.Node(), + way = iD.Way({tags: defaultTags}); + + history.perform( + iD.actions.AddMidpoint(midpoint, node), + iD.actions.AddWay(way), + iD.actions.AddWayNode(way.id, node.id), + iD.actions.AddWayNode(way.id, node.id)); + + controller.enter(iD.modes.DrawArea(way.id, graph)); + } + function startFromNode(node) { var graph = history.graph(), way = iD.Way({tags: defaultTags}); @@ -57,6 +71,7 @@ iD.modes.AddArea = function() { } behavior = iD.behavior.AddWay(mode) + .on('startFromMidpoint', startFromMidpoint) .on('startFromNode', startFromNode) .on('startFromWay', startFromWay) .on('start', start); diff --git a/js/id/modes/add_line.js b/js/id/modes/add_line.js index bf419d2bb..df6f33a57 100644 --- a/js/id/modes/add_line.js +++ b/js/id/modes/add_line.js @@ -15,6 +15,19 @@ iD.modes.AddLine = function() { history = mode.history, controller = mode.controller; + function startFromMidpoint(midpoint) { + var graph = history.graph(), + node = iD.Node(), + way = iD.Way({tags: defaultTags}); + + history.perform( + iD.actions.AddMidpoint(midpoint, node), + iD.actions.AddWay(way), + iD.actions.AddWayNode(way.id, node.id)); + + controller.enter(iD.modes.DrawLine(way.id, 'forward', graph)); + } + function startFromNode(node) { var graph = history.graph(), parent = graph.parentWays(node)[0], @@ -65,6 +78,7 @@ iD.modes.AddLine = function() { } behavior = iD.behavior.AddWay(mode) + .on('startFromMidpoint', startFromMidpoint) .on('startFromNode', startFromNode) .on('startFromWay', startFromWay) .on('start', start); diff --git a/js/id/modes/add_point.js b/js/id/modes/add_point.js index 1bcfc5d04..723b1935b 100644 --- a/js/id/modes/add_point.js +++ b/js/id/modes/add_point.js @@ -42,6 +42,7 @@ iD.modes.AddPoint = function() { .on('click', add) .on('clickWay', addWay) .on('clickNode', addNode) + .on('clickMidpoint', addNode) .on('cancel', cancel) .on('finish', cancel) (surface); From 363cd53af14939accb8f124d8f06775513c2ee06 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Wed, 30 Jan 2013 16:17:30 -0500 Subject: [PATCH 47/48] Rearrange code --- js/id/behavior/draw_way.js | 22 +++++++++--------- js/id/modes/add_area.js | 42 +++++++++++++++++----------------- js/id/modes/add_line.js | 46 +++++++++++++++++++------------------- 3 files changed, 55 insertions(+), 55 deletions(-) diff --git a/js/id/behavior/draw_way.js b/js/id/behavior/draw_way.js index 1103bc143..65231a277 100644 --- a/js/id/behavior/draw_way.js +++ b/js/id/behavior/draw_way.js @@ -85,10 +85,13 @@ iD.behavior.DrawWay = function(wayId, index, mode, baseGraph) { } } - // Connect the way to an existing node and continue drawing. - drawWay.addNode = function(node) { - history.perform( - ReplaceTemporaryNode(node), + // Accept the current position of the temporary node and continue drawing. + drawWay.add = function(loc) { + var newNode = iD.Node({loc: loc}); + + history.replace( + iD.actions.AddNode(newNode), + ReplaceTemporaryNode(newNode), annotation); finished = true; @@ -109,13 +112,10 @@ iD.behavior.DrawWay = function(wayId, index, mode, baseGraph) { controller.enter(mode); }; - // Accept the current position of the temporary node and continue drawing. - drawWay.add = function(loc) { - var newNode = iD.Node({loc: loc}); - - history.replace( - iD.actions.AddNode(newNode), - ReplaceTemporaryNode(newNode), + // Connect the way to an existing node and continue drawing. + drawWay.addNode = function(node) { + history.perform( + ReplaceTemporaryNode(node), annotation); finished = true; diff --git a/js/id/modes/add_area.js b/js/id/modes/add_area.js index 153060b3a..614c66677 100644 --- a/js/id/modes/add_area.js +++ b/js/id/modes/add_area.js @@ -15,25 +15,13 @@ iD.modes.AddArea = function() { history = mode.history, controller = mode.controller; - function startFromMidpoint(midpoint) { - var graph = history.graph(), - node = iD.Node(), - way = iD.Way({tags: defaultTags}); - - history.perform( - iD.actions.AddMidpoint(midpoint, node), - iD.actions.AddWay(way), - iD.actions.AddWayNode(way.id, node.id), - iD.actions.AddWayNode(way.id, node.id)); - - controller.enter(iD.modes.DrawArea(way.id, graph)); - } - - function startFromNode(node) { + function start(loc) { var graph = history.graph(), + node = iD.Node({loc: loc}), way = iD.Way({tags: defaultTags}); history.perform( + iD.actions.AddNode(node), iD.actions.AddWay(way), iD.actions.AddWayNode(way.id, node.id), iD.actions.AddWayNode(way.id, node.id)); @@ -56,13 +44,25 @@ iD.modes.AddArea = function() { controller.enter(iD.modes.DrawArea(way.id, graph)); } - function start(loc) { + function startFromNode(node) { var graph = history.graph(), - node = iD.Node({loc: loc}), way = iD.Way({tags: defaultTags}); history.perform( - iD.actions.AddNode(node), + iD.actions.AddWay(way), + iD.actions.AddWayNode(way.id, node.id), + iD.actions.AddWayNode(way.id, node.id)); + + controller.enter(iD.modes.DrawArea(way.id, graph)); + } + + function startFromMidpoint(midpoint) { + var graph = history.graph(), + node = iD.Node(), + way = iD.Way({tags: defaultTags}); + + history.perform( + iD.actions.AddMidpoint(midpoint, node), iD.actions.AddWay(way), iD.actions.AddWayNode(way.id, node.id), iD.actions.AddWayNode(way.id, node.id)); @@ -71,10 +71,10 @@ iD.modes.AddArea = function() { } behavior = iD.behavior.AddWay(mode) - .on('startFromMidpoint', startFromMidpoint) - .on('startFromNode', startFromNode) + .on('start', start) .on('startFromWay', startFromWay) - .on('start', start); + .on('startFromNode', startFromNode) + .on('startFromMidpoint', startFromMidpoint); mode.map.surface.call(behavior); mode.map.tail('Click on the map to start drawing an area, like a park, lake, or building.', true); diff --git a/js/id/modes/add_line.js b/js/id/modes/add_line.js index df6f33a57..90adac738 100644 --- a/js/id/modes/add_line.js +++ b/js/id/modes/add_line.js @@ -15,19 +15,33 @@ iD.modes.AddLine = function() { history = mode.history, controller = mode.controller; - function startFromMidpoint(midpoint) { + function start(loc) { var graph = history.graph(), - node = iD.Node(), + node = iD.Node({loc: loc}), way = iD.Way({tags: defaultTags}); history.perform( - iD.actions.AddMidpoint(midpoint, node), + iD.actions.AddNode(node), iD.actions.AddWay(way), iD.actions.AddWayNode(way.id, node.id)); controller.enter(iD.modes.DrawLine(way.id, 'forward', graph)); } + function startFromWay(other, loc, index) { + var graph = history.graph(), + node = iD.Node({loc: loc}), + way = iD.Way({tags: defaultTags}); + + history.perform( + iD.actions.AddNode(node), + iD.actions.AddWay(way), + iD.actions.AddWayNode(way.id, node.id), + iD.actions.AddWayNode(other.id, node.id, index)); + + controller.enter(iD.modes.DrawLine(way.id, 'forward', graph)); + } + function startFromNode(node) { var graph = history.graph(), parent = graph.parentWays(node)[0], @@ -50,27 +64,13 @@ iD.modes.AddLine = function() { } } - function startFromWay(other, loc, index) { + function startFromMidpoint(midpoint) { var graph = history.graph(), - node = iD.Node({loc: loc}), + node = iD.Node(), way = iD.Way({tags: defaultTags}); history.perform( - iD.actions.AddNode(node), - iD.actions.AddWay(way), - iD.actions.AddWayNode(way.id, node.id), - iD.actions.AddWayNode(other.id, node.id, index)); - - controller.enter(iD.modes.DrawLine(way.id, 'forward', graph)); - } - - function start(loc) { - var graph = history.graph(), - node = iD.Node({loc: loc}), - way = iD.Way({tags: defaultTags}); - - history.perform( - iD.actions.AddNode(node), + iD.actions.AddMidpoint(midpoint, node), iD.actions.AddWay(way), iD.actions.AddWayNode(way.id, node.id)); @@ -78,10 +78,10 @@ iD.modes.AddLine = function() { } behavior = iD.behavior.AddWay(mode) - .on('startFromMidpoint', startFromMidpoint) - .on('startFromNode', startFromNode) + .on('start', start) .on('startFromWay', startFromWay) - .on('start', start); + .on('startFromNode', startFromNode) + .on('startFromMidpoint', startFromMidpoint); mode.map.surface.call(behavior); mode.map.tail('Click on the map to start drawing an road, path, or route.', true); From e4c513ae87b235310c77204448cf3f48e92e69b0 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Wed, 30 Jan 2013 16:24:33 -0500 Subject: [PATCH 48/48] midpoint = true -> type = 'midpoint' Makes it more consistent with entities. --- js/id/behavior/draw.js | 2 +- js/id/behavior/draw_way.js | 2 +- js/id/renderer/map.js | 2 +- js/id/svg/midpoints.js | 4 +--- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/js/id/behavior/draw.js b/js/id/behavior/draw.js index 783d9e42c..bce4470b6 100644 --- a/js/id/behavior/draw.js +++ b/js/id/behavior/draw.js @@ -34,7 +34,7 @@ iD.behavior.Draw = function(map) { } else if (d.type === 'node') { event.clickNode(d); - } else if (d.midpoint) { + } else if (d.type === 'midpoint') { event.clickMidpoint(d); } else { diff --git a/js/id/behavior/draw_way.js b/js/id/behavior/draw_way.js index 65231a277..884d72ddb 100644 --- a/js/id/behavior/draw_way.js +++ b/js/id/behavior/draw_way.js @@ -17,7 +17,7 @@ iD.behavior.DrawWay = function(wayId, index, mode, baseGraph) { function move(datum) { var loc = map.mouseCoordinates(); - if (datum.type === 'node' || datum.midpoint) { + if (datum.type === 'node' || datum.type === 'midpoint') { loc = datum.loc; } else if (datum.type === 'way') { loc = iD.geo.chooseIndex(datum, d3.mouse(map.surface.node()), map).loc; diff --git a/js/id/renderer/map.js b/js/id/renderer/map.js index 487ac736a..c7c1ed632 100644 --- a/js/id/renderer/map.js +++ b/js/id/renderer/map.js @@ -92,7 +92,7 @@ iD.Map = function() { all = _.compact(_.values(only)); filter = function(d) { - if (d.midpoint) { + if (d.type === 'midpoint') { for (var i = 0; i < d.ways.length; i++) { if (d.ways[i].id in only) return true; } diff --git a/js/id/svg/midpoints.js b/js/id/svg/midpoints.js index da4af659c..ee8d2c5e2 100644 --- a/js/id/svg/midpoints.js +++ b/js/id/svg/midpoints.js @@ -20,11 +20,9 @@ iD.svg.Midpoints = function(projection) { } else if (iD.geo.dist(projection(a.loc), projection(b.loc)) > 40) { midpoints[id] = { - midpoint: true, + type: 'midpoint', id: id, loc: iD.geo.interp(a.loc, b.loc, 0.5), - a: a.id, - b: b.id, ways: [{id: entity.id, index: j + 1}] }; }

z16z17