From 6ae360a533115cefc2edcbec9475f46598145eda Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 31 Jan 2013 08:28:10 -0500 Subject: [PATCH 01/32] These tests now pass --- test/spec/actions/delete_way.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/spec/actions/delete_way.js b/test/spec/actions/delete_way.js index 863b0fa2f..d550803fa 100644 --- a/test/spec/actions/delete_way.js +++ b/test/spec/actions/delete_way.js @@ -31,8 +31,7 @@ describe("iD.actions.DeleteWay", function () { expect(graph.entity(node.id)).not.to.be.undefined; }); - // See #508 - xit("deletes multiple member nodes", function () { + it("deletes multiple member nodes", function () { var a = iD.Node(), b = iD.Node(), way = iD.Way({nodes: [a.id, b.id]}), @@ -42,7 +41,7 @@ describe("iD.actions.DeleteWay", function () { expect(graph.entity(b.id)).to.be.undefined; }); - xit("deletes a circular way's start/end node", function () { + it("deletes a circular way's start/end node", function () { var a = iD.Node(), b = iD.Node(), c = iD.Node(), From 208ed6a2ed9425a8c2be4c0e8d6a179ede9c4bbe Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 31 Jan 2013 08:30:46 -0500 Subject: [PATCH 02/32] Move iD.geo tests to own file --- test/index.html | 1 + test/index_packaged.html | 1 + test/spec/geo.js | 96 +++++++++++++++++++++++++++++++++++ test/spec/util.js | 107 ++------------------------------------- 4 files changed, 102 insertions(+), 103 deletions(-) create mode 100644 test/spec/geo.js diff --git a/test/index.html b/test/index.html index 731800f62..d8d3f8f6f 100644 --- a/test/index.html +++ b/test/index.html @@ -185,6 +185,7 @@ + diff --git a/test/index_packaged.html b/test/index_packaged.html index aba99ba04..719a5a999 100644 --- a/test/index_packaged.html +++ b/test/index_packaged.html @@ -79,6 +79,7 @@ + diff --git a/test/spec/geo.js b/test/spec/geo.js new file mode 100644 index 000000000..113d4795d --- /dev/null +++ b/test/spec/geo.js @@ -0,0 +1,96 @@ +describe('iD.geo', function() { + describe('.roundCoords', function() { + expect(iD.geo.roundCoords([0.1, 1])).to.eql([0, 1]); + expect(iD.geo.roundCoords([0, 1])).to.eql([0, 1]); + expect(iD.geo.roundCoords([0, 1.1])).to.eql([0, 1]); + }); + + describe('.interp', function() { + it('interpolates halfway', function() { + var a = [0, 0], + b = [10, 10]; + expect(iD.geo.interp(a, b, 0.5)).to.eql([5, 5]); + }); + it('interpolates to one side', function() { + var a = [0, 0], + b = [10, 10]; + expect(iD.geo.interp(a, b, 0)).to.eql([0, 0]); + }); + }); + + describe('.dist', function() { + it('distance between two same points is zero', function() { + var a = [0, 0], + b = [0, 0]; + expect(iD.geo.dist(a, b)).to.eql(0); + }); + it('a straight 10 unit line is 10', function() { + var a = [0, 0], + b = [10, 0]; + expect(iD.geo.dist(a, b)).to.eql(10); + }); + it('a pythagorean triangle is right', function() { + var a = [0, 0], + b = [4, 3]; + expect(iD.geo.dist(a, b)).to.eql(5); + }); + }); + + describe('.pointInPolygon', function() { + it('says a point in a polygon is on a polygon', function() { + var poly = [[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]; + var point = [0.5, 0.5]; + expect(iD.geo.pointInPolygon(point, poly)).to.be.true; + }); + it('says a point outside of a polygon is outside', function() { + var poly = [ + [0, 0], + [0, 1], + [1, 1], + [1, 0], + [0, 0]]; + var point = [0.5, 1.5]; + expect(iD.geo.pointInPolygon(point, poly)).to.be.false; + }); + }); + + describe('.polygonContainsPolygon', function() { + it('says a polygon in a polygon is in', function() { + var outer = [[0, 0], [0, 3], [3, 3], [3, 0], [0, 0]]; + var inner = [[1, 1], [1, 2], [2, 2], [2, 1], [1, 1]]; + expect(iD.geo.polygonContainsPolygon(outer, inner)).to.be.true; + }); + it('says a polygon outside of a polygon is out', function() { + var outer = [[0, 0], [0, 3], [3, 3], [3, 0], [0, 0]]; + var inner = [[1, 1], [1, 9], [2, 2], [2, 1], [1, 1]]; + expect(iD.geo.polygonContainsPolygon(outer, inner)).to.be.false; + }); + }); + + describe('.polygonIntersectsPolygon', function() { + it('says a polygon in a polygon intersects it', function() { + var outer = [[0, 0], [0, 3], [3, 3], [3, 0], [0, 0]]; + var inner = [[1, 1], [1, 2], [2, 2], [2, 1], [1, 1]]; + expect(iD.geo.polygonIntersectsPolygon(outer, inner)).to.be.true; + }); + + it('says a polygon that partially intersects does', function() { + var outer = [[0, 0], [0, 3], [3, 3], [3, 0], [0, 0]]; + var inner = [[-1, -1], [1, 2], [2, 2], [2, 1], [1, 1]]; + expect(iD.geo.polygonIntersectsPolygon(outer, inner)).to.be.true; + }); + + it('says totally disjoint polygons do not intersect', function() { + var outer = [[0, 0], [0, 3], [3, 3], [3, 0], [0, 0]]; + var inner = [[-1, -1], [-1, -2], [-2, -2], [-2, -1], [-1, -1]]; + expect(iD.geo.polygonIntersectsPolygon(outer, inner)).to.be.false; + }); + }); + + describe('.pathLength', function() { + it('calculates a simple path length', function() { + var path = [[0, 0], [0, 1], [3, 5]]; + expect(iD.geo.pathLength(path)).to.eql(6); + }); + }); +}); diff --git a/test/spec/util.js b/test/spec/util.js index 9d5cf082b..de3fab735 100644 --- a/test/spec/util.js +++ b/test/spec/util.js @@ -1,123 +1,24 @@ describe('iD.Util', function() { - var util; - - it('#trueObj', function() { + it('.trueObj', function() { expect(iD.util.trueObj(['a', 'b', 'c'])).to.eql({ a: true, b: true, c: true }); expect(iD.util.trueObj([])).to.eql({}); }); - it('#tagText', function() { + it('.tagText', function() { expect(iD.util.tagText({})).to.eql(''); expect(iD.util.tagText({tags:{foo:'bar'}})).to.eql('foo: bar'); expect(iD.util.tagText({tags:{foo:'bar',two:'three'}})).to.eql('foo: bar\ntwo: three'); }); - it('#stringQs', function() { + it('.stringQs', function() { expect(iD.util.stringQs('foo=bar')).to.eql({foo: 'bar'}); expect(iD.util.stringQs('foo=bar&one=2')).to.eql({foo: 'bar', one: '2' }); expect(iD.util.stringQs('')).to.eql({}); }); - it('#qsString', function() { + it('.qsString', function() { expect(iD.util.qsString({ foo: 'bar' })).to.eql('foo=bar'); expect(iD.util.qsString({ foo: 'bar', one: 2 })).to.eql('foo=bar&one=2'); expect(iD.util.qsString({})).to.eql(''); }); - - describe('geo', function() { - describe('#roundCoords', function() { - expect(iD.geo.roundCoords([0.1, 1])).to.eql([0, 1]); - expect(iD.geo.roundCoords([0, 1])).to.eql([0, 1]); - expect(iD.geo.roundCoords([0, 1.1])).to.eql([0, 1]); - }); - - describe('#interp', function() { - it('interpolates halfway', function() { - var a = [0, 0], - b = [10, 10]; - expect(iD.geo.interp(a, b, 0.5)).to.eql([5, 5]); - }); - it('interpolates to one side', function() { - var a = [0, 0], - b = [10, 10]; - expect(iD.geo.interp(a, b, 0)).to.eql([0, 0]); - }); - }); - - describe('#dist', function() { - it('distance between two same points is zero', function() { - var a = [0, 0], - b = [0, 0]; - expect(iD.geo.dist(a, b)).to.eql(0); - }); - it('a straight 10 unit line is 10', function() { - var a = [0, 0], - b = [10, 0]; - expect(iD.geo.dist(a, b)).to.eql(10); - }); - it('a pythagorean triangle is right', function() { - var a = [0, 0], - b = [4, 3]; - expect(iD.geo.dist(a, b)).to.eql(5); - }); - }); - - describe('#pointInPolygon', function() { - it('says a point in a polygon is on a polygon', function() { - var poly = [[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]; - var point = [0.5, 0.5]; - expect(iD.geo.pointInPolygon(point, poly)).to.be.true; - }); - it('says a point outside of a polygon is outside', function() { - var poly = [ - [0, 0], - [0, 1], - [1, 1], - [1, 0], - [0, 0]]; - var point = [0.5, 1.5]; - expect(iD.geo.pointInPolygon(point, poly)).to.be.false; - }); - }); - - describe('#polygonContainsPolygon', function() { - it('says a polygon in a polygon is in', function() { - var outer = [[0, 0], [0, 3], [3, 3], [3, 0], [0, 0]]; - var inner = [[1, 1], [1, 2], [2, 2], [2, 1], [1, 1]]; - expect(iD.geo.polygonContainsPolygon(outer, inner)).to.be.true; - }); - it('says a polygon outside of a polygon is out', function() { - var outer = [[0, 0], [0, 3], [3, 3], [3, 0], [0, 0]]; - var inner = [[1, 1], [1, 9], [2, 2], [2, 1], [1, 1]]; - expect(iD.geo.polygonContainsPolygon(outer, inner)).to.be.false; - }); - }); - - describe('#polygonIntersectsPolygon', function() { - it('says a polygon in a polygon intersects it', function() { - var outer = [[0, 0], [0, 3], [3, 3], [3, 0], [0, 0]]; - var inner = [[1, 1], [1, 2], [2, 2], [2, 1], [1, 1]]; - expect(iD.geo.polygonIntersectsPolygon(outer, inner)).to.be.true; - }); - - it('says a polygon that partially intersects does', function() { - var outer = [[0, 0], [0, 3], [3, 3], [3, 0], [0, 0]]; - var inner = [[-1, -1], [1, 2], [2, 2], [2, 1], [1, 1]]; - expect(iD.geo.polygonIntersectsPolygon(outer, inner)).to.be.true; - }); - - it('says totally disjoint polygons do not intersect', function() { - var outer = [[0, 0], [0, 3], [3, 3], [3, 0], [0, 0]]; - var inner = [[-1, -1], [-1, -2], [-2, -2], [-2, -1], [-1, -1]]; - expect(iD.geo.polygonIntersectsPolygon(outer, inner)).to.be.false; - }); - }); - - describe('#pathLength', function() { - it('calculates a simple path length', function() { - var path = [[0, 0], [0, 1], [3, 5]]; - expect(iD.geo.pathLength(path)).to.eql(6); - }); - }); - }); }); From edb3a3b68210e26b3eb0548dfae2dceb4ee00180 Mon Sep 17 00:00:00 2001 From: Tom MacWright Date: Thu, 31 Jan 2013 10:03:43 -0500 Subject: [PATCH 03/32] Entire notice is clickable. Fixes #262 --- css/app.css | 16 ++++++++++++---- js/id/ui/notice.js | 21 +++++++++------------ 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/css/app.css b/css/app.css index 98ba49e57..4c149843d 100644 --- a/css/app.css +++ b/css/app.css @@ -1052,7 +1052,8 @@ a.success-action { text-align:center; } -.notice .notice-inner { +.notice .zoom-to { + width:100%; height: 40px; border-radius: 5px; line-height: 40px; @@ -1061,12 +1062,19 @@ a.success-action { opacity: 0.9; } -.notice .notice-inner .zoom-to { - width:40px; - height:40px; +.notice .zoom-to:hover { + background: #bde5aa; +} + +.notice .zoom-to .icon { + margin-top:10px; margin-right:10px; } +.icon.zoom-in-invert { + background-position: -240px -40px; +} + /* Tooltips ------------------------------------------------------- */ diff --git a/js/id/ui/notice.js b/js/id/ui/notice.js index bcf44b7c9..12b1a2c09 100644 --- a/js/id/ui/notice.js +++ b/js/id/ui/notice.js @@ -4,20 +4,17 @@ iD.ui.notice = function(selection) { notice = {}; var div = selection.append('div') - .attr('class', 'notice') - .append('div') - .attr('class', 'notice-inner'); + .attr('class', 'notice'); - div.append('button') - .attr('class', 'zoom-to') - .on('click', function() { - event.zoom(); - }) - .append('span') - .attr('class', 'icon invert zoom-in'); + var button = div.append('button') + .attr('class', 'zoom-to notice') + .on('click', event.zoom); - div.append('span') - .attr('class', 'notice-text') + button.append('span') + .attr('class', 'icon zoom-in-invert'); + + button.append('span') + .attr('class', 'label') .text(t('zoom_in_edit')); notice.message = function(_) { From 5c1d3cc18e41b4aba60d6f4058da47da0a818489 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Thu, 31 Jan 2013 10:34:57 -0500 Subject: [PATCH 04/32] Preserve label tree between partial redraws --- js/id/renderer/map.js | 2 +- js/id/svg/labels.js | 29 ++++++++++++++++++++++------- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/js/id/renderer/map.js b/js/id/renderer/map.js index 0d1532948..08c18e915 100644 --- a/js/id/renderer/map.js +++ b/js/id/renderer/map.js @@ -112,7 +112,7 @@ iD.Map = function() { .call(areas, graph, all, filter) .call(multipolygons, graph, all, filter) .call(midpoints, graph, all, filter) - .call(labels, graph, all, filter, dimensions); + .call(labels, graph, all, filter, dimensions, !difference); } dispatch.drawn(map); } diff --git a/js/id/svg/labels.js b/js/id/svg/labels.js index 2fcc2fcc1..5f300f147 100644 --- a/js/id/svg/labels.js +++ b/js/id/svg/labels.js @@ -183,14 +183,26 @@ iD.svg.Labels = function(projection) { } - return function drawLabels(surface, graph, entities, filter, dimensions) { + var rtree = new RTree(), + rectangles = {}; + + return function drawLabels(surface, graph, entities, filter, dimensions, fullRedraw) { + - var rtree = new RTree(); var hidePoints = !d3.select('.node.point').node(); var labelable = [], i, k, entity; for (i = 0; i < label_stack.length; i++) labelable.push([]); + if (fullRedraw) { + rtree = new RTree(); + rectangles = {}; + } else { + for (i = 0; i < entities.length; i++) { + rtree.remove(rectangles[entities[i].id], entities[i].id); + } + } + // Split entities into groups specified by label_stack for (i = 0; i < entities.length; i++) { entity = entities[i]; @@ -252,7 +264,7 @@ iD.svg.Labels = function(projection) { textAnchor: offset[2] }; var rect = new RTree.Rectangle(p.x - m, p.y - m, width + 2*m, height + 2*m); - if (tryInsert(rect)) return p; + if (tryInsert(rect, entity.id)) return p; } @@ -275,7 +287,7 @@ iD.svg.Labels = function(projection) { Math.abs(sub[0][1] - sub[sub.length - 1][1]) + 30 ); if (rev) sub = sub.reverse(); - if (tryInsert(rect)) return { + if (tryInsert(rect, entity.id)) return { 'font-size': height + 2, lineString: lineString(sub), startOffset: offset + '%' @@ -298,16 +310,19 @@ iD.svg.Labels = function(projection) { height: height }; var rect = new RTree.Rectangle(p.x - width/2, p.y, width, height); - if (tryInsert(rect)) return p; + if (tryInsert(rect, entity.id)) return p; } - function tryInsert(rect) { + function tryInsert(rect, id) { // Check that label is visible if (rect.x1 < 0 || rect.y1 < 0 || rect.x2 > dimensions[0] || rect.y2 > dimensions[1]) return false; var v = rtree.search(rect, true).length === 0; - if (v) rtree.insert(rect); + if (v) { + rtree.insert(rect, id); + rectangles[id] = rect; + } return v; } From c69345e0398cf7c94b633dfcc5f0db621bf3a63d Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Thu, 31 Jan 2013 10:50:14 -0500 Subject: [PATCH 05/32] Fix comparisons in `subpath` --- js/id/svg/labels.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/id/svg/labels.js b/js/id/svg/labels.js index 5f300f147..3962c4915 100644 --- a/js/id/svg/labels.js +++ b/js/id/svg/labels.js @@ -156,7 +156,7 @@ iD.svg.Labels = function(projection) { for (var i = 0; i < nodes.length - 1; i++) { var current = segmentLength(i); var portion; - if (!start && sofar + current > from) { + if (!start && sofar + current >= from) { portion = (from - sofar) / current; start = [ nodes[i][0] + portion * (nodes[i + 1][0] - nodes[i][0]), @@ -164,7 +164,7 @@ iD.svg.Labels = function(projection) { ]; i0 = i + 1; } - if (!end && sofar + current > to) { + if (!end && sofar + current >= to) { portion = (to - sofar) / current; end = [ nodes[i][0] + portion * (nodes[i + 1][0] - nodes[i][0]), From 2c2efe3b65ea3ccb37a4c113defc9940285c1962 Mon Sep 17 00:00:00 2001 From: Tom MacWright Date: Thu, 31 Jan 2013 11:02:41 -0500 Subject: [PATCH 06/32] Background refinements. Fixes #561, fixes #456 --- js/id/renderer/background.js | 136 ++++++++++++++++++----------------- 1 file changed, 70 insertions(+), 66 deletions(-) diff --git a/js/id/renderer/background.js b/js/id/renderer/background.js index 6476e7a28..752853e6b 100644 --- a/js/id/renderer/background.js +++ b/js/id/renderer/background.js @@ -1,4 +1,10 @@ iD.Background = function() { + + var deviceRatio = (window.devicePixelRatio && + window.devicePixelRatio === 2) ? 0.5 : 1; + // tileSize = (deviceRatio === 0.5) ? [128,128] : [256,256]; + tileSize = [256, 256]; + var tile = d3.geo.tile(), projection, cache = {}, @@ -13,7 +19,12 @@ iD.Background = function() { '-o-transform-origin:0 0;' + '-webkit-user-select: none;' + '-webkit-user-drag: none;' + - '-moz-user-drag: none;'; + '-moz-user-drag: none;' + + 'opacity:0;'; + + function tileSizeAtZoom(d, z) { + return Math.ceil(tileSize[0] * Math.pow(2, z - d[2])) / tileSize[0]; + } function atZoom(t, distance) { var power = Math.pow(2, distance); @@ -21,108 +32,101 @@ iD.Background = function() { Math.floor(t[0] * power), Math.floor(t[1] * power), t[2] + distance]; - az.push(source(az)); return az; } - function upZoom(t, distance) { - var az = atZoom(t, distance), tiles = []; - for (var x = 0; x < 2; x++) { - for (var y = 0; y < 2; y++) { - var up = [az[0] + x, az[1] + y, az[2]]; - up.push(source(up)); - tiles.push(up); - } - } - return tiles; - } - - function tileSize(d, z) { - return Math.ceil(256 * Math.pow(2, z - d[2])) / 256; - } - function lookUp(d) { for (var up = -1; up > -d[2]; up--) { if (cache[atZoom(d, up)] !== false) return atZoom(d, up); } } + function uniqueBy(a, n) { + var o = [], seen = {}; + for (var i = 0; i < a.length; i++) { + if (seen[a[i][n]] === undefined) { + o.push(a[i]); + seen[a[i][n]] = true; + } + } + return o; + } + + function addSource(d) { + d.push(source(d)); + return d; + } + // derive the tiles onscreen, remove those offscreen and position tiles // correctly for the currentstate of `projection` function background() { - var tiles = tile + var sel = this, + tiles = tile .scale(projection.scale()) .scaleExtent(source.scaleExtent || [1, 17]) .translate(projection.translate())(), + requests = [], scaleExtent = tile.scaleExtent(), z = Math.max(Math.log(projection.scale()) / Math.log(2) - 8, 0), - rz = Math.max(scaleExtent[0], Math.min(scaleExtent[1], Math.floor(z))), - ts = 256 * Math.pow(2, z - rz), + rz = Math.max(scaleExtent[0], + Math.min(scaleExtent[1], Math.floor(z))), + ts = tileSize[0] * Math.pow(2, z - rz), tile_origin = [ projection.scale() / 2 - projection.translate()[0], - projection.scale() / 2 - projection.translate()[1]], - ups = {}; + projection.scale() / 2 - projection.translate()[1]]; tiles.forEach(function(d) { - - if (cache[d] === true) { - d.push(source(d)); - } else if (cache[d] === false && - cache[atZoom(d, -1)] !== false && - !ups[atZoom(d, -1)]) { - - ups[atZoom(d, -1)] = true; - tiles.push(atZoom(d, -1)); - - } else if (cache[d] === undefined && - lookUp(d)) { - - var upTile = lookUp(d); - if (!ups[upTile]) { - ups[upTile] = true; - tiles.push(upTile); - } - - } else if (cache[d] === undefined || - cache[d] === false) { - upZoom(d, 1).forEach(function(u) { - if (cache[u] && !ups[u]) { - ups[u] = true; - tiles.push(u); - } - }); + addSource(d); + requests.push(d); + if (!cache[d[3]] && lookUp(d)) { + requests.push(addSource(lookUp(d))); } }); - var image = this - .selectAll('img') - .data(tiles, function(d) { return d; }); + requests = uniqueBy(requests, 3); function load(d) { - cache[d.slice(0, 3)] = true; - d3.select(this).on('load', null); + cache[d[3]] = true; + d3.select(this) + .on('load', null) + .transition() + .style('opacity', 1); + background.apply(sel); } function error(d) { - cache[d.slice(0, 3)] = false; + cache[d[3]] = false; + d3.select(this).on('load', null); d3.select(this).remove(); + background.apply(sel); } + function imageTransform(d) { + var _ts = tileSize[0] * Math.pow(2, z - d[2]); + var scale = tileSizeAtZoom(d, z); + return 'translate(' + + (Math.round((d[0] * _ts) - tile_origin[0]) + offset[0]) + 'px,' + + (Math.round((d[1] * _ts) - tile_origin[1]) + offset[1]) + 'px)' + + 'scale(' + scale + ',' + scale + ')'; + } + + var image = this + .selectAll('img') + .data(requests, function(d) { return d[3]; }); + + image.exit() + .style(transformProp, imageTransform) + .transition() + .style('opacity', 0) + .remove(); + image.enter().append('img') .attr('style', imgstyle) .attr('src', function(d) { return d[3]; }) .on('error', error) .on('load', load); - - image.exit().remove(); - - image.style(transformProp, function(d) { - var _ts = 256 * Math.pow(2, z - d[2]); - var scale = tileSize(d, z); - return 'translate(' + - (Math.round((d[0] * _ts) - tile_origin[0]) + offset[0]) + 'px,' + - (Math.round((d[1] * _ts) - tile_origin[1]) + offset[1]) + 'px) scale(' + scale + ',' + scale + ')'; - }); + + image.style(transformProp, imageTransform); if (Object.keys(cache).length > 100) cache = {}; } From f0414f7ca11915eb1110bed71cd82dd6214cacc3 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Thu, 31 Jan 2013 11:17:32 -0500 Subject: [PATCH 07/32] Fix call to flash --- js/id/renderer/map.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/id/renderer/map.js b/js/id/renderer/map.js index 08c18e915..04521bdd7 100644 --- a/js/id/renderer/map.js +++ b/js/id/renderer/map.js @@ -136,7 +136,7 @@ iD.Map = function() { } if (Math.log(d3.event.scale / Math.LN2 - 8) < minzoom + 1) { - iD.flash() + iD.ui.flash() .select('.content') .text('Cannot zoom out further in current mode.'); return map.zoom(16); From 7e8126ded984102eea9e286b25bc76f4e4fd1ad4 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 31 Jan 2013 11:20:34 -0500 Subject: [PATCH 08/32] I18n for modes and operations --- js/id/behavior/drag_midpoint.js | 2 +- js/id/behavior/drag_node.js | 10 ++- js/id/behavior/draw_way.js | 14 ++-- js/id/graph/validate.js | 8 +-- js/id/modes/add_area.js | 8 +-- js/id/modes/add_line.js | 8 +-- js/id/modes/add_point.js | 17 +++-- js/id/modes/browse.js | 6 +- js/id/modes/draw_area.js | 5 +- js/id/modes/draw_line.js | 7 +- js/id/modes/move_way.js | 12 ++-- js/id/modes/select.js | 4 +- js/id/operations/circularize.js | 21 ++---- js/id/operations/delete.js | 34 +++------ js/id/operations/move.js | 6 +- js/id/operations/reverse.js | 8 +-- js/id/operations/split.js | 8 +-- js/id/operations/unjoin.js | 6 +- locale/en.js | 120 ++++++++++++++++++++++++++++++-- locale/locale.js | 8 ++- 20 files changed, 198 insertions(+), 114 deletions(-) diff --git a/js/id/behavior/drag_midpoint.js b/js/id/behavior/drag_midpoint.js index bd1a40bd9..6041946cd 100644 --- a/js/id/behavior/drag_midpoint.js +++ b/js/id/behavior/drag_midpoint.js @@ -25,7 +25,7 @@ iD.behavior.DragMidpoint = function(mode) { .on('end', function() { history.replace( iD.actions.Noop(), - 'Added a node to a way.'); + t('operations.add.annotation.vertex')); }); return behavior; diff --git a/js/id/behavior/drag_node.js b/js/id/behavior/drag_node.js index 1bfddfed6..b9846617d 100644 --- a/js/id/behavior/drag_node.js +++ b/js/id/behavior/drag_node.js @@ -25,6 +25,10 @@ iD.behavior.DragNode = function(mode) { nudgeInterval = null; } + function annotation(entity) { + return t('operations.move.annotation.' + entity.geometry(mode.history.graph())); + } + return iD.behavior.drag() .delegate(".node") .origin(function(entity) { @@ -43,12 +47,12 @@ iD.behavior.DragNode = function(mode) { history.replace( iD.actions.MoveNode(entity.id, projection.invert(d3.event.point)), - 'moved a node'); + annotation(entity)); }) - .on('end', function() { + .on('end', function(entity) { stopNudge(); history.replace( iD.actions.Noop(), - 'moved a node'); + annotation(entity)); }); }; diff --git a/js/id/behavior/draw_way.js b/js/id/behavior/draw_way.js index 21c13d2fa..c8341337c 100644 --- a/js/id/behavior/draw_way.js +++ b/js/id/behavior/draw_way.js @@ -2,9 +2,11 @@ iD.behavior.DrawWay = function(wayId, index, mode, baseGraph) { var map = mode.map, history = mode.history, controller = mode.controller, - way = mode.history.graph().entity(wayId), + way = history.graph().entity(wayId), finished = false, - annotation = 'Added to a way.', + annotation = t((way.isDegenerate() ? + 'operations.start.annotation.' : + 'operations.continue.annotation.') + way.geometry(history.graph())), draw = iD.behavior.Draw(map); var node = iD.Node({loc: map.mouseCoordinates()}), @@ -71,12 +73,6 @@ iD.behavior.DrawWay = function(wayId, 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 @@ -153,7 +149,7 @@ iD.behavior.DrawWay = function(wayId, index, mode, baseGraph) { drawWay.cancel = function() { history.perform( d3.functor(baseGraph), - 'Cancelled drawing.'); + t('operations.cancel_draw.annotation')); finished = true; controller.enter(iD.modes.Browse()); diff --git a/js/id/graph/validate.js b/js/id/graph/validate.js index 805b775c3..aa7d8771b 100644 --- a/js/id/graph/validate.js +++ b/js/id/graph/validate.js @@ -21,22 +21,22 @@ iD.validate = function(changes, graph) { if (change.geometry(graph) === 'point' && _.isEmpty(change.tags)) { warnings.push({ - message: 'Untagged point which is not part of a line or area', + message: t('validations.untagged_point'), entity: change }); } if (change.geometry(graph) === 'line' && _.isEmpty(change.tags)) { - warnings.push({ message: 'Untagged line', entity: change }); + warnings.push({ message: t('validations.untagged_line'), entity: change }); } if (change.geometry(graph) === 'area' && _.isEmpty(change.tags)) { - warnings.push({ message: 'Untagged area', entity: change }); + warnings.push({ message: t('validations.untagged_area'), entity: change }); } if (change.geometry(graph) === 'line' && tagSuggestsArea(change)) { warnings.push({ - message: 'The tag ' + tagSuggestsArea(change) + ' suggests line should be area, but it is not and area', + message: t('validations.tag_suggests_area', {tag: tagSuggestsArea(change)}), entity: change }); } diff --git a/js/id/modes/add_area.js b/js/id/modes/add_area.js index 614c66677..03b7582cc 100644 --- a/js/id/modes/add_area.js +++ b/js/id/modes/add_area.js @@ -2,9 +2,9 @@ iD.modes.AddArea = function() { var mode = { id: 'add-area', button: 'area', - title: 'Area', - description: 'Add parks, buildings, lakes, or other areas to the map.', - key: 'a' + title: t('modes.add_area.title'), + description: t('modes.add_area.description'), + key: t('modes.add_area.key') }; var behavior, @@ -77,7 +77,7 @@ iD.modes.AddArea = function() { .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); + mode.map.tail(t('modes.add_area.tail'), true); }; mode.exit = function() { diff --git a/js/id/modes/add_line.js b/js/id/modes/add_line.js index 90adac738..c40a78fce 100644 --- a/js/id/modes/add_line.js +++ b/js/id/modes/add_line.js @@ -2,9 +2,9 @@ iD.modes.AddLine = function() { var mode = { id: 'add-line', button: 'line', - title: 'Line', - description: 'Lines can be highways, streets, pedestrian paths, or even canals.', - key: 'l' + title: t('modes.add_line.title'), + description: t('modes.add_line.description'), + key: t('modes.add_line.key') }; var behavior, @@ -84,7 +84,7 @@ iD.modes.AddLine = function() { .on('startFromMidpoint', startFromMidpoint); mode.map.surface.call(behavior); - mode.map.tail('Click on the map to start drawing an road, path, or route.', true); + mode.map.tail(t('modes.add_line.tail'), true); }; mode.exit = function() { diff --git a/js/id/modes/add_point.js b/js/id/modes/add_point.js index 1b9781a9d..5db73dc0f 100644 --- a/js/id/modes/add_point.js +++ b/js/id/modes/add_point.js @@ -1,27 +1,24 @@ iD.modes.AddPoint = function() { var mode = { id: 'add-point', - title: 'Point', - description: 'Restaurants, monuments, and postal boxes are points.', - key: 'p' + title: t('modes.add_point.title'), + description: t('modes.add_point.description'), + key: t('modes.add_point.key') }; var behavior; mode.enter = function() { var map = mode.map, - surface = map.surface, history = mode.history, controller = mode.controller; - map.tail('Click on the map to add a point.', true); - function add(loc) { var node = iD.Node({loc: loc}); history.perform( iD.actions.AddNode(node), - 'Added a point.'); + t('operations.add.annotation.point')); controller.enter(iD.modes.Select(node, true)); } @@ -44,8 +41,10 @@ iD.modes.AddPoint = function() { .on('clickNode', addNode) .on('clickMidpoint', addNode) .on('cancel', cancel) - .on('finish', cancel) - (surface); + .on('finish', cancel); + + mode.map.surface.call(behavior); + mode.map.tail(t('modes.add_point.tail'), true); }; mode.exit = function() { diff --git a/js/id/modes/browse.js b/js/id/modes/browse.js index ab6bc80cb..c7358bdea 100644 --- a/js/id/modes/browse.js +++ b/js/id/modes/browse.js @@ -2,9 +2,9 @@ iD.modes.Browse = function() { var mode = { button: 'browse', id: 'browse', - title: 'Browse', - description: 'Pan and zoom the map.', - key: 'b' + title: t('modes.browse.title'), + description: t('modes.browse.description'), + key: t('modes.browse.key') }; var behaviors; diff --git a/js/id/modes/draw_area.js b/js/id/modes/draw_area.js index 8423ff436..fd26d5eda 100644 --- a/js/id/modes/draw_area.js +++ b/js/id/modes/draw_area.js @@ -11,8 +11,7 @@ iD.modes.DrawArea = function(wayId, baseGraph) { headId = way.nodes[way.nodes.length - 2], tailId = way.first(); - behavior = iD.behavior.DrawWay(wayId, -1, mode, baseGraph) - .annotation(way.isDegenerate() ? 'started an area' : 'continued an area'); + behavior = iD.behavior.DrawWay(wayId, -1, mode, baseGraph); var addNode = behavior.addNode; @@ -25,7 +24,7 @@ iD.modes.DrawArea = function(wayId, baseGraph) { }; mode.map.surface.call(behavior); - mode.map.tail('Click to add points to your area. Click the first point to finish the area.', true); + mode.map.tail(t('modes.draw_area.tail'), true); }; mode.exit = function() { diff --git a/js/id/modes/draw_line.js b/js/id/modes/draw_line.js index ae54ab2e1..0596c9065 100644 --- a/js/id/modes/draw_line.js +++ b/js/id/modes/draw_line.js @@ -11,8 +11,7 @@ iD.modes.DrawLine = function(wayId, direction, baseGraph) { index = (direction === 'forward') ? undefined : 0, headId = (direction === 'forward') ? way.last() : way.first(); - behavior = iD.behavior.DrawWay(wayId, index, mode, baseGraph) - .annotation(way.isDegenerate() ? 'Started a line.' : 'Continued a line.'); + behavior = iD.behavior.DrawWay(wayId, index, mode, baseGraph); var addNode = behavior.addNode; @@ -25,9 +24,7 @@ iD.modes.DrawLine = function(wayId, direction, baseGraph) { }; mode.map.surface.call(behavior); - mode.map.tail('Click to add more points to the line. ' + - 'Click on other lines to connect to them, and double-click to ' + - 'end the line.', true); + mode.map.tail(t('modes.draw_line.tail'), true); }; mode.exit = function() { diff --git a/js/id/modes/move_way.js b/js/id/modes/move_way.js index 18c6ee619..d977f6719 100644 --- a/js/id/modes/move_way.js +++ b/js/id/modes/move_way.js @@ -11,14 +11,14 @@ iD.modes.MoveWay = function(wayId) { graph = history.graph(), selection = map.surface, controller = mode.controller, - projection = map.projection; - - var way = graph.entity(wayId), - origin = d3.mouse(selection.node()); + projection = map.projection, + way = graph.entity(wayId), + origin = d3.mouse(selection.node()), + annotation = t('operations.move.annotation.' + way.geometry(graph)); history.perform( iD.actions.Noop(), - 'Moved a way.'); + annotation); function move() { var p = d3.mouse(selection.node()), @@ -29,7 +29,7 @@ iD.modes.MoveWay = function(wayId) { history.replace( iD.actions.MoveWay(wayId, delta, projection), - 'Moved a way.'); + annotation); } function finish() { diff --git a/js/id/modes/select.js b/js/id/modes/select.js index 1ddd4ffc4..455f94913 100644 --- a/js/id/modes/select.js +++ b/js/id/modes/select.js @@ -14,7 +14,7 @@ iD.modes.Select = function(entity, initial) { if (!_.isEqual(entity.tags, tags)) { mode.history.perform( iD.actions.ChangeEntityTags(d.id, tags), - 'Changed tags.'); + t('operations.change_tags.annotation')); } } @@ -114,7 +114,7 @@ iD.modes.Select = function(entity, initial) { history.perform( iD.actions.AddNode(node), iD.actions.AddWayNode(datum.id, node.id, choice.index), - 'Added a point to a road.'); + t('operations.add.annotation.vertex')); d3.event.preventDefault(); d3.event.stopPropagation(); diff --git a/js/id/operations/circularize.js b/js/id/operations/circularize.js index ce161aef4..91921dc2a 100644 --- a/js/id/operations/circularize.js +++ b/js/id/operations/circularize.js @@ -5,24 +5,15 @@ iD.operations.Circularize = function(entityId, mode) { var operation = function() { var graph = history.graph(), entity = graph.entity(entityId), - geometry = entity.geometry(graph); + annotation = t('operations.circularize.annotation.' + entity.geometry(graph)); - if (geometry === 'line') { - history.perform( - action, - 'Made a line circular.'); - - } else if (geometry === 'area') { - history.perform( - action, - 'Made an area circular.'); - } + history.perform(action, annotation); }; operation.available = function() { var graph = history.graph(), entity = graph.entity(entityId); - return entity.geometry(graph) === 'area' || entity.geometry(graph) === 'line'; + return entity.type === 'way'; }; operation.enabled = function() { @@ -31,9 +22,9 @@ iD.operations.Circularize = function(entityId, mode) { }; operation.id = "circularize"; - operation.key = "O"; - operation.title = "Circularize"; - operation.description = "Make this round"; + operation.key = t('operations.circularize.key'); + operation.title = t('operations.circularize.title'); + operation.description = t('operations.circularize.description'); return operation; }; diff --git a/js/id/operations/delete.js b/js/id/operations/delete.js index cc3750360..993d3eef4 100644 --- a/js/id/operations/delete.js +++ b/js/id/operations/delete.js @@ -4,34 +4,18 @@ iD.operations.Delete = function(entityId, mode) { var operation = function() { var graph = history.graph(), entity = graph.entity(entityId), - geometry = entity.geometry(graph); + action = {way: iD.actions.DeleteWay, node: iD.actions.DeleteNode}[entity.type], + annotation = t('operations.delete.annotation.' + 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.'); - } + history.perform( + action(entityId), + annotation); }; operation.available = function() { var graph = history.graph(), entity = graph.entity(entityId); - return _.contains(['vertex', 'point', 'line', 'area'], entity.geometry(graph)); + return entity.type === 'way' || entity.type === 'node'; }; operation.enabled = function() { @@ -39,9 +23,9 @@ iD.operations.Delete = function(entityId, mode) { }; operation.id = "delete"; - operation.key = "⌫"; - operation.title = "Delete"; - operation.description = "Remove this from the map."; + operation.key = t('operations.delete.key'); + operation.title = t('operations.delete.title'); + operation.description = t('operations.delete.description'); return operation; }; diff --git a/js/id/operations/move.js b/js/id/operations/move.js index 383ca4206..5034c2f75 100644 --- a/js/id/operations/move.js +++ b/js/id/operations/move.js @@ -15,9 +15,9 @@ iD.operations.Move = function(entityId, mode) { }; operation.id = "move"; - operation.key = "M"; - operation.title = "Move"; - operation.description = "Move this to a different location"; + operation.key = t('operations.move.key'); + operation.title = t('operations.move.title'); + operation.description = t('operations.move.description'); return operation; }; diff --git a/js/id/operations/reverse.js b/js/id/operations/reverse.js index 62fd8810b..ca9dd6440 100644 --- a/js/id/operations/reverse.js +++ b/js/id/operations/reverse.js @@ -4,7 +4,7 @@ iD.operations.Reverse = function(entityId, mode) { var operation = function() { history.perform( iD.actions.ReverseWay(entityId), - 'Reversed a line.'); + t('operations.reverse.annotation')); }; operation.available = function() { @@ -18,9 +18,9 @@ iD.operations.Reverse = function(entityId, mode) { }; operation.id = "reverse"; - operation.key = "V"; - operation.title = "Reverse"; - operation.description = "Make this way go in the opposite direction."; + operation.key = t('operations.reverse.key'); + operation.title = t('operations.reverse.title'); + operation.description = t('operations.reverse.description'); return operation; }; diff --git a/js/id/operations/split.js b/js/id/operations/split.js index 40aa55fd0..ff3f8af20 100644 --- a/js/id/operations/split.js +++ b/js/id/operations/split.js @@ -3,7 +3,7 @@ iD.operations.Split = function(entityId, mode) { action = iD.actions.SplitWay(entityId); var operation = function() { - history.perform(action, 'Split a way.'); + history.perform(action, t('operations.split.annotation')); }; operation.available = function() { @@ -18,9 +18,9 @@ iD.operations.Split = function(entityId, mode) { }; operation.id = "split"; - operation.key = "X"; - operation.title = "Split"; - operation.description = "Split this into two ways at this point."; + operation.key = t('operations.split.key'); + operation.title = t('operations.split.title'); + operation.description = t('operations.split.description'); return operation; }; diff --git a/js/id/operations/unjoin.js b/js/id/operations/unjoin.js index f38333bb4..175c13973 100644 --- a/js/id/operations/unjoin.js +++ b/js/id/operations/unjoin.js @@ -18,9 +18,9 @@ iD.operations.Unjoin = function(entityId, mode) { }; operation.id = "unjoin"; - operation.key = "⇧-J"; - operation.title = "Unjoin"; - operation.description = "Disconnect these ways from each other."; + operation.key = t('operations.unjoin.key'); + operation.title = t('operations.unjoin.title'); + operation.description = t('operations.unjoin.description'); return operation; }; diff --git a/locale/en.js b/locale/en.js index 2a011a734..d7fc3628f 100644 --- a/locale/en.js +++ b/locale/en.js @@ -1,8 +1,118 @@ locale.en = { - "browse": "Browse", - "point": "Point", - "line": "Line", - "area": "Area", + modes: { + add_area: { + title: "Area", + description: "Add parks, buildings, lakes, or other areas to the map.", + tail: "Click on the map to start drawing an area, like a park, lake, or building.", + key: "A" + }, + add_line: { + title: "Line", + description: "Lines can be highways, streets, pedestrian paths, or even canals.", + tail: "Click on the map to start drawing an road, path, or route.", + key: "L" + }, + add_point: { + title: "Point", + description: "Restaurants, monuments, and postal boxes are points.", + tail: "Click on the map to add a point.", + key: "P" + }, + browse: { + title: "Browse", + description: "Pan and zoom the map.", + key: "B" + }, + draw_area: { + tail: "Click to add points to your area. Click the first point to finish the area." + }, + draw_line: { + tail: "Click to add more points to the line. Click on other lines to connect to them, and double-click to end the line." + } + }, + + operations: { + add: { + annotation: { + point: "Added a point.", + vertex: "Added a node to a way." + } + }, + start: { + annotation: { + line: "Started a line.", + area: "Started an area." + } + }, + continue: { + annotation: { + line: "Continued a line.", + area: "Continued an area." + } + }, + cancel_draw: { + annotation: "Cancelled drawing." + }, + change_tags: { + annotation: "Changed tags." + }, + circularize: { + title: "Circularize", + description: "Make this round.", + key: "O", + annotation: { + line: "Made a line circular.", + area: "Made an area circular." + } + }, + delete: { + title: "Delete", + description: "Remove this from the map.", + key: "⌫", + annotation: { + point: "Deleted a point.", + vertex: "Deleted a node from a way.", + line: "Deleted a line.", + area: "Deleted an area." + } + }, + move: { + title: "Move", + description: "Move this to a different location.", + key: "M", + annotation: { + point: "Moved a point.", + vertex: "Moved a node in a way.", + line: "Moved a line.", + area: "Moved an area." + } + }, + reverse: { + title: "Reverse", + description: "Make this line go in the opposite direction.", + key: "V", + annotation: "Reversed a line." + }, + split: { + title: "Split", + description: "Split this into two ways at this point.", + key: "X", + annotation: "Split a way." + }, + unjoin: { + title: "Unjoin", + description: "Disconnect these ways from each other.", + key: "⇧-J", + annotation: "Unjoined ways." + } + }, + + validations: { + untagged_point: "Untagged point which is not part of a line or area", + untagged_line: "Untagged line", + untagged_area: "Untagged area", + tag_suggests_area: "The tag {tag} suggests line should be area, but it is not an area" + }, "save": "Save", "save_help": "Save changes to OpenStreetMap, making them visible to other users", @@ -37,4 +147,4 @@ locale.en = { "layers": "Layers", "percent_opacity": "{opacity}% opacity" -} +}; diff --git a/locale/locale.js b/locale/locale.js index 9e4786059..291b255a0 100644 --- a/locale/locale.js +++ b/locale/locale.js @@ -1,8 +1,12 @@ var locale = { current: 'en' }; function t(s, o) { - if (locale[locale.current][s] !== undefined) { - var rep = locale[locale.current][s]; + var path = s.split(".").reverse(), + rep = locale[locale.current]; + + while (rep !== undefined && path.length) rep = rep[path.pop()]; + + if (rep !== undefined) { if (o) for (var k in o) rep = rep.replace('{' + k + '}', o[k]); return rep; } else { From 806ec9fae329c280e962fc41c53a884969ae1cec Mon Sep 17 00:00:00 2001 From: Tom MacWright Date: Thu, 31 Jan 2013 11:39:51 -0500 Subject: [PATCH 09/32] Add google analytics. --- index.html | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/index.html b/index.html index 5f62b0f8f..8c777292e 100644 --- a/index.html +++ b/index.html @@ -140,4 +140,15 @@ d3.select("#iD").call(id); }); + + From 2655810efe1721d78bf1f7101bb405a9937a99fa Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 31 Jan 2013 11:55:01 -0500 Subject: [PATCH 10/32] Remove unused parameter --- js/id/modes/add_area.js | 2 +- js/id/modes/add_line.js | 2 +- js/id/modes/add_point.js | 2 +- js/id/modes/draw_area.js | 2 +- js/id/modes/draw_line.js | 2 +- js/id/renderer/map.js | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/js/id/modes/add_area.js b/js/id/modes/add_area.js index 03b7582cc..4519c3d7e 100644 --- a/js/id/modes/add_area.js +++ b/js/id/modes/add_area.js @@ -77,7 +77,7 @@ iD.modes.AddArea = function() { .on('startFromMidpoint', startFromMidpoint); mode.map.surface.call(behavior); - mode.map.tail(t('modes.add_area.tail'), true); + mode.map.tail(t('modes.add_area.tail')); }; mode.exit = function() { diff --git a/js/id/modes/add_line.js b/js/id/modes/add_line.js index c40a78fce..4a49e4955 100644 --- a/js/id/modes/add_line.js +++ b/js/id/modes/add_line.js @@ -84,7 +84,7 @@ iD.modes.AddLine = function() { .on('startFromMidpoint', startFromMidpoint); mode.map.surface.call(behavior); - mode.map.tail(t('modes.add_line.tail'), true); + mode.map.tail(t('modes.add_line.tail')); }; mode.exit = function() { diff --git a/js/id/modes/add_point.js b/js/id/modes/add_point.js index 5db73dc0f..74389cb0c 100644 --- a/js/id/modes/add_point.js +++ b/js/id/modes/add_point.js @@ -44,7 +44,7 @@ iD.modes.AddPoint = function() { .on('finish', cancel); mode.map.surface.call(behavior); - mode.map.tail(t('modes.add_point.tail'), true); + mode.map.tail(t('modes.add_point.tail')); }; mode.exit = function() { diff --git a/js/id/modes/draw_area.js b/js/id/modes/draw_area.js index fd26d5eda..9801a092c 100644 --- a/js/id/modes/draw_area.js +++ b/js/id/modes/draw_area.js @@ -24,7 +24,7 @@ iD.modes.DrawArea = function(wayId, baseGraph) { }; mode.map.surface.call(behavior); - mode.map.tail(t('modes.draw_area.tail'), true); + mode.map.tail(t('modes.draw_area.tail')); }; mode.exit = function() { diff --git a/js/id/modes/draw_line.js b/js/id/modes/draw_line.js index 0596c9065..5ae8c2703 100644 --- a/js/id/modes/draw_line.js +++ b/js/id/modes/draw_line.js @@ -24,7 +24,7 @@ iD.modes.DrawLine = function(wayId, direction, baseGraph) { }; mode.map.surface.call(behavior); - mode.map.tail(t('modes.draw_line.tail'), true); + mode.map.tail(t('modes.draw_line.tail')); }; mode.exit = function() { diff --git a/js/id/renderer/map.js b/js/id/renderer/map.js index 04521bdd7..a2c4781ef 100644 --- a/js/id/renderer/map.js +++ b/js/id/renderer/map.js @@ -361,7 +361,7 @@ iD.Map = function() { }; var usedTails = {}; - map.tail = function (_, once) { + map.tail = function (_) { if (!_ || usedTails[_] === undefined) { tail.text(_); usedTails[_] = true; From 1bfe1359ecf32c104817108e77ddded0784b1f8b Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 31 Jan 2013 11:57:41 -0500 Subject: [PATCH 11/32] AddWayNode -> AddVertex --- index.html | 2 +- .../actions/{add_way_node.js => add_vertex.js} | 2 +- js/id/behavior/draw_way.js | 4 ++-- js/id/modes/add_area.js | 18 +++++++++--------- js/id/modes/add_line.js | 10 +++++----- js/id/modes/select.js | 2 +- test/index.html | 2 +- 7 files changed, 20 insertions(+), 20 deletions(-) rename js/id/actions/{add_way_node.js => add_vertex.js} (80%) diff --git a/index.html b/index.html index 8c777292e..ede3e9a26 100644 --- a/index.html +++ b/index.html @@ -76,7 +76,7 @@ - + diff --git a/js/id/actions/add_way_node.js b/js/id/actions/add_vertex.js similarity index 80% rename from js/id/actions/add_way_node.js rename to js/id/actions/add_vertex.js index 3e4fffcfc..279737c05 100644 --- a/js/id/actions/add_way_node.js +++ b/js/id/actions/add_vertex.js @@ -1,5 +1,5 @@ // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as -iD.actions.AddWayNode = function(wayId, nodeId, index) { +iD.actions.AddVertex = function(wayId, nodeId, index) { return function(graph) { return graph.replace(graph.entity(wayId).addNode(nodeId, index)); }; diff --git a/js/id/behavior/draw_way.js b/js/id/behavior/draw_way.js index c8341337c..be64ac9c2 100644 --- a/js/id/behavior/draw_way.js +++ b/js/id/behavior/draw_way.js @@ -14,7 +14,7 @@ iD.behavior.DrawWay = function(wayId, index, mode, baseGraph) { history[way.isDegenerate() ? 'replace' : 'perform']( iD.actions.AddNode(node), - iD.actions.AddWayNode(wayId, node.id, index)); + iD.actions.AddVertex(wayId, node.id, index)); function move(datum) { var loc = map.mouseCoordinates(); @@ -100,7 +100,7 @@ iD.behavior.DrawWay = function(wayId, index, mode, baseGraph) { history.perform( iD.actions.AddNode(newNode), - iD.actions.AddWayNode(way.id, newNode.id, wayIndex), + iD.actions.AddVertex(way.id, newNode.id, wayIndex), ReplaceTemporaryNode(newNode), annotation); diff --git a/js/id/modes/add_area.js b/js/id/modes/add_area.js index 4519c3d7e..b90ba1891 100644 --- a/js/id/modes/add_area.js +++ b/js/id/modes/add_area.js @@ -23,8 +23,8 @@ iD.modes.AddArea = function() { history.perform( iD.actions.AddNode(node), iD.actions.AddWay(way), - iD.actions.AddWayNode(way.id, node.id), - iD.actions.AddWayNode(way.id, node.id)); + iD.actions.AddVertex(way.id, node.id), + iD.actions.AddVertex(way.id, node.id)); controller.enter(iD.modes.DrawArea(way.id, graph)); } @@ -37,9 +37,9 @@ iD.modes.AddArea = function() { history.perform( iD.actions.AddNode(node), iD.actions.AddWay(way), - iD.actions.AddWayNode(way.id, node.id), - iD.actions.AddWayNode(way.id, node.id), - iD.actions.AddWayNode(other.id, node.id, index)); + iD.actions.AddVertex(way.id, node.id), + iD.actions.AddVertex(way.id, node.id), + iD.actions.AddVertex(other.id, node.id, index)); controller.enter(iD.modes.DrawArea(way.id, graph)); } @@ -50,8 +50,8 @@ iD.modes.AddArea = function() { history.perform( iD.actions.AddWay(way), - iD.actions.AddWayNode(way.id, node.id), - iD.actions.AddWayNode(way.id, node.id)); + iD.actions.AddVertex(way.id, node.id), + iD.actions.AddVertex(way.id, node.id)); controller.enter(iD.modes.DrawArea(way.id, graph)); } @@ -64,8 +64,8 @@ iD.modes.AddArea = function() { 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)); + iD.actions.AddVertex(way.id, node.id), + iD.actions.AddVertex(way.id, node.id)); controller.enter(iD.modes.DrawArea(way.id, graph)); } diff --git a/js/id/modes/add_line.js b/js/id/modes/add_line.js index 4a49e4955..f14d8ed06 100644 --- a/js/id/modes/add_line.js +++ b/js/id/modes/add_line.js @@ -23,7 +23,7 @@ iD.modes.AddLine = function() { history.perform( iD.actions.AddNode(node), iD.actions.AddWay(way), - iD.actions.AddWayNode(way.id, node.id)); + iD.actions.AddVertex(way.id, node.id)); controller.enter(iD.modes.DrawLine(way.id, 'forward', graph)); } @@ -36,8 +36,8 @@ iD.modes.AddLine = function() { 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)); + iD.actions.AddVertex(way.id, node.id), + iD.actions.AddVertex(other.id, node.id, index)); controller.enter(iD.modes.DrawLine(way.id, 'forward', graph)); } @@ -58,7 +58,7 @@ iD.modes.AddLine = function() { history.perform( iD.actions.AddWay(way), - iD.actions.AddWayNode(way.id, node.id)); + iD.actions.AddVertex(way.id, node.id)); controller.enter(iD.modes.DrawLine(way.id, 'forward', graph)); } @@ -72,7 +72,7 @@ iD.modes.AddLine = function() { history.perform( iD.actions.AddMidpoint(midpoint, node), iD.actions.AddWay(way), - iD.actions.AddWayNode(way.id, node.id)); + iD.actions.AddVertex(way.id, node.id)); controller.enter(iD.modes.DrawLine(way.id, 'forward', graph)); } diff --git a/js/id/modes/select.js b/js/id/modes/select.js index 455f94913..49bdbc37c 100644 --- a/js/id/modes/select.js +++ b/js/id/modes/select.js @@ -113,7 +113,7 @@ iD.modes.Select = function(entity, initial) { history.perform( iD.actions.AddNode(node), - iD.actions.AddWayNode(datum.id, node.id, choice.index), + iD.actions.AddVertex(datum.id, node.id, choice.index), t('operations.add.annotation.vertex')); d3.event.preventDefault(); diff --git a/test/index.html b/test/index.html index d8d3f8f6f..57ceab240 100644 --- a/test/index.html +++ b/test/index.html @@ -71,7 +71,7 @@ - + From 6f7079d11cc755e692239380b6f93e37f68575d6 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 31 Jan 2013 12:04:21 -0500 Subject: [PATCH 12/32] AddWay/AddNode -> AddEntity --- index.html | 3 +-- js/id/actions/{add_way.js => add_entity.js} | 2 +- js/id/actions/add_node.js | 6 ------ js/id/behavior/draw_way.js | 6 +++--- js/id/modes/add_area.js | 12 ++++++------ js/id/modes/add_line.js | 12 ++++++------ js/id/modes/add_point.js | 2 +- js/id/modes/select.js | 2 +- test/index.html | 6 ++---- test/index_packaged.html | 3 +-- test/spec/actions/add_entity.js | 7 +++++++ test/spec/actions/add_node.js | 7 ------- test/spec/actions/add_way.js | 7 ------- 13 files changed, 29 insertions(+), 46 deletions(-) rename js/id/actions/{add_way.js => add_entity.js} (65%) delete mode 100644 js/id/actions/add_node.js create mode 100644 test/spec/actions/add_entity.js delete mode 100644 test/spec/actions/add_node.js delete mode 100644 test/spec/actions/add_way.js diff --git a/index.html b/index.html index ede3e9a26..ff98e791c 100644 --- a/index.html +++ b/index.html @@ -74,8 +74,7 @@ - - + diff --git a/js/id/actions/add_way.js b/js/id/actions/add_entity.js similarity index 65% rename from js/id/actions/add_way.js rename to js/id/actions/add_entity.js index 2be062d3a..0011d0fe5 100644 --- a/js/id/actions/add_way.js +++ b/js/id/actions/add_entity.js @@ -1,4 +1,4 @@ -iD.actions.AddWay = function(way) { +iD.actions.AddEntity = function(way) { return function(graph) { return graph.replace(way); }; diff --git a/js/id/actions/add_node.js b/js/id/actions/add_node.js deleted file mode 100644 index 669a81d49..000000000 --- a/js/id/actions/add_node.js +++ /dev/null @@ -1,6 +0,0 @@ -// https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/AddCommand.java -iD.actions.AddNode = function(node) { - return function(graph) { - return graph.replace(node); - }; -}; diff --git a/js/id/behavior/draw_way.js b/js/id/behavior/draw_way.js index be64ac9c2..ba28fe14b 100644 --- a/js/id/behavior/draw_way.js +++ b/js/id/behavior/draw_way.js @@ -13,7 +13,7 @@ iD.behavior.DrawWay = function(wayId, index, mode, baseGraph) { nodeId = node.id; history[way.isDegenerate() ? 'replace' : 'perform']( - iD.actions.AddNode(node), + iD.actions.AddEntity(node), iD.actions.AddVertex(wayId, node.id, index)); function move(datum) { @@ -86,7 +86,7 @@ iD.behavior.DrawWay = function(wayId, index, mode, baseGraph) { var newNode = iD.Node({loc: loc}); history.replace( - iD.actions.AddNode(newNode), + iD.actions.AddEntity(newNode), ReplaceTemporaryNode(newNode), annotation); @@ -99,7 +99,7 @@ iD.behavior.DrawWay = function(wayId, index, mode, baseGraph) { var newNode = iD.Node({loc: loc}); history.perform( - iD.actions.AddNode(newNode), + iD.actions.AddEntity(newNode), iD.actions.AddVertex(way.id, newNode.id, wayIndex), ReplaceTemporaryNode(newNode), annotation); diff --git a/js/id/modes/add_area.js b/js/id/modes/add_area.js index b90ba1891..bda4e0daa 100644 --- a/js/id/modes/add_area.js +++ b/js/id/modes/add_area.js @@ -21,8 +21,8 @@ iD.modes.AddArea = function() { way = iD.Way({tags: defaultTags}); history.perform( - iD.actions.AddNode(node), - iD.actions.AddWay(way), + iD.actions.AddEntity(node), + iD.actions.AddEntity(way), iD.actions.AddVertex(way.id, node.id), iD.actions.AddVertex(way.id, node.id)); @@ -35,8 +35,8 @@ iD.modes.AddArea = function() { way = iD.Way({tags: defaultTags}); history.perform( - iD.actions.AddNode(node), - iD.actions.AddWay(way), + iD.actions.AddEntity(node), + iD.actions.AddEntity(way), iD.actions.AddVertex(way.id, node.id), iD.actions.AddVertex(way.id, node.id), iD.actions.AddVertex(other.id, node.id, index)); @@ -49,7 +49,7 @@ iD.modes.AddArea = function() { way = iD.Way({tags: defaultTags}); history.perform( - iD.actions.AddWay(way), + iD.actions.AddEntity(way), iD.actions.AddVertex(way.id, node.id), iD.actions.AddVertex(way.id, node.id)); @@ -63,7 +63,7 @@ iD.modes.AddArea = function() { history.perform( iD.actions.AddMidpoint(midpoint, node), - iD.actions.AddWay(way), + iD.actions.AddEntity(way), iD.actions.AddVertex(way.id, node.id), iD.actions.AddVertex(way.id, node.id)); diff --git a/js/id/modes/add_line.js b/js/id/modes/add_line.js index f14d8ed06..92e9a64d7 100644 --- a/js/id/modes/add_line.js +++ b/js/id/modes/add_line.js @@ -21,8 +21,8 @@ iD.modes.AddLine = function() { way = iD.Way({tags: defaultTags}); history.perform( - iD.actions.AddNode(node), - iD.actions.AddWay(way), + iD.actions.AddEntity(node), + iD.actions.AddEntity(way), iD.actions.AddVertex(way.id, node.id)); controller.enter(iD.modes.DrawLine(way.id, 'forward', graph)); @@ -34,8 +34,8 @@ iD.modes.AddLine = function() { way = iD.Way({tags: defaultTags}); history.perform( - iD.actions.AddNode(node), - iD.actions.AddWay(way), + iD.actions.AddEntity(node), + iD.actions.AddEntity(way), iD.actions.AddVertex(way.id, node.id), iD.actions.AddVertex(other.id, node.id, index)); @@ -57,7 +57,7 @@ iD.modes.AddLine = function() { var way = iD.Way({tags: defaultTags}); history.perform( - iD.actions.AddWay(way), + iD.actions.AddEntity(way), iD.actions.AddVertex(way.id, node.id)); controller.enter(iD.modes.DrawLine(way.id, 'forward', graph)); @@ -71,7 +71,7 @@ iD.modes.AddLine = function() { history.perform( iD.actions.AddMidpoint(midpoint, node), - iD.actions.AddWay(way), + iD.actions.AddEntity(way), iD.actions.AddVertex(way.id, node.id)); controller.enter(iD.modes.DrawLine(way.id, 'forward', graph)); diff --git a/js/id/modes/add_point.js b/js/id/modes/add_point.js index 74389cb0c..61ff51424 100644 --- a/js/id/modes/add_point.js +++ b/js/id/modes/add_point.js @@ -17,7 +17,7 @@ iD.modes.AddPoint = function() { var node = iD.Node({loc: loc}); history.perform( - iD.actions.AddNode(node), + iD.actions.AddEntity(node), t('operations.add.annotation.point')); controller.enter(iD.modes.Select(node, true)); diff --git a/js/id/modes/select.js b/js/id/modes/select.js index 49bdbc37c..3e0acc5a1 100644 --- a/js/id/modes/select.js +++ b/js/id/modes/select.js @@ -112,7 +112,7 @@ iD.modes.Select = function(entity, initial) { node = iD.Node({ loc: choice.loc }); history.perform( - iD.actions.AddNode(node), + iD.actions.AddEntity(node), iD.actions.AddVertex(datum.id, node.id, choice.index), t('operations.add.annotation.vertex')); diff --git a/test/index.html b/test/index.html index 57ceab240..f9da20905 100644 --- a/test/index.html +++ b/test/index.html @@ -69,8 +69,7 @@ - - + @@ -139,8 +138,7 @@ - - + diff --git a/test/index_packaged.html b/test/index_packaged.html index 719a5a999..291f47f71 100644 --- a/test/index_packaged.html +++ b/test/index_packaged.html @@ -33,8 +33,7 @@ - - + diff --git a/test/spec/actions/add_entity.js b/test/spec/actions/add_entity.js new file mode 100644 index 000000000..1e2e092ca --- /dev/null +++ b/test/spec/actions/add_entity.js @@ -0,0 +1,7 @@ +describe("iD.actions.AddEntity", function () { + it("adds an entity to the graph", function () { + var entity = iD.Entity(), + graph = iD.actions.AddEntity(entity)(iD.Graph()); + expect(graph.entity(entity.id)).to.equal(entity); + }); +}); diff --git a/test/spec/actions/add_node.js b/test/spec/actions/add_node.js deleted file mode 100644 index ae066edc5..000000000 --- a/test/spec/actions/add_node.js +++ /dev/null @@ -1,7 +0,0 @@ -describe("iD.actions.AddNode", function () { - it("adds a node to the graph", function () { - var node = iD.Node(), - graph = iD.actions.AddNode(node)(iD.Graph()); - expect(graph.entity(node.id)).to.equal(node); - }); -}); diff --git a/test/spec/actions/add_way.js b/test/spec/actions/add_way.js deleted file mode 100644 index 19948c5b2..000000000 --- a/test/spec/actions/add_way.js +++ /dev/null @@ -1,7 +0,0 @@ -describe("iD.actions.AddWay", function () { - it("adds a way to the graph", function () { - var way = iD.Way(), - graph = iD.actions.AddWay(way)(iD.Graph()); - expect(graph.entity(way.id)).to.equal(way); - }); -}); From df72ef254f984218cf650e87fbca5d44a1d3f732 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 31 Jan 2013 12:07:54 -0500 Subject: [PATCH 13/32] ChangeEntityTags -> ChangeTags --- js/id/actions/{change_entity_tags.js => change_tags.js} | 2 +- js/id/modes/select.js | 2 +- test/spec/actions/change_entity_tags.js | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) rename js/id/actions/{change_entity_tags.js => change_tags.js} (71%) diff --git a/js/id/actions/change_entity_tags.js b/js/id/actions/change_tags.js similarity index 71% rename from js/id/actions/change_entity_tags.js rename to js/id/actions/change_tags.js index 96901c2eb..c5972644e 100644 --- a/js/id/actions/change_entity_tags.js +++ b/js/id/actions/change_tags.js @@ -1,4 +1,4 @@ -iD.actions.ChangeEntityTags = function(entityId, tags) { +iD.actions.ChangeTags = function(entityId, tags) { return function(graph) { var entity = graph.entity(entityId); return graph.replace(entity.update({tags: tags})); diff --git a/js/id/modes/select.js b/js/id/modes/select.js index 3e0acc5a1..83e0d72b8 100644 --- a/js/id/modes/select.js +++ b/js/id/modes/select.js @@ -13,7 +13,7 @@ iD.modes.Select = function(entity, initial) { function changeTags(d, tags) { if (!_.isEqual(entity.tags, tags)) { mode.history.perform( - iD.actions.ChangeEntityTags(d.id, tags), + iD.actions.ChangeTags(d.id, tags), t('operations.change_tags.annotation')); } } diff --git a/test/spec/actions/change_entity_tags.js b/test/spec/actions/change_entity_tags.js index bfa9830c6..0cc198230 100644 --- a/test/spec/actions/change_entity_tags.js +++ b/test/spec/actions/change_entity_tags.js @@ -1,8 +1,8 @@ -describe("iD.actions.ChangeEntityTags", function () { +describe("iD.actions.ChangeTags", function () { it("changes an entity's tags", function () { var entity = iD.Entity(), tags = {foo: 'bar'}, - graph = iD.actions.ChangeEntityTags(entity.id, tags)(iD.Graph([entity])); + graph = iD.actions.ChangeTags(entity.id, tags)(iD.Graph([entity])); expect(graph.entity(entity.id).tags).to.eql(tags); }); }); From 3605895dfad0dde494cde95745d797286df08865 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 31 Jan 2013 12:41:29 -0500 Subject: [PATCH 14/32] ChangeEntityTags -> ChangeTags --- index.html | 2 +- test/index.html | 4 ++-- test/index_packaged.html | 2 +- test/spec/actions/{change_entity_tags.js => change_tags.js} | 0 4 files changed, 4 insertions(+), 4 deletions(-) rename test/spec/actions/{change_entity_tags.js => change_tags.js} (100%) diff --git a/index.html b/index.html index ff98e791c..03bf6386f 100644 --- a/index.html +++ b/index.html @@ -76,7 +76,7 @@ - + diff --git a/test/index.html b/test/index.html index f9da20905..90e5bc9fa 100644 --- a/test/index.html +++ b/test/index.html @@ -71,7 +71,7 @@ - + @@ -139,7 +139,7 @@ - + diff --git a/test/index_packaged.html b/test/index_packaged.html index 291f47f71..007392f3b 100644 --- a/test/index_packaged.html +++ b/test/index_packaged.html @@ -34,7 +34,7 @@ - + diff --git a/test/spec/actions/change_entity_tags.js b/test/spec/actions/change_tags.js similarity index 100% rename from test/spec/actions/change_entity_tags.js rename to test/spec/actions/change_tags.js From 3bdd314eb8b6a87efe8e02bb0c5f4fd474970ba8 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 31 Jan 2013 12:42:37 -0500 Subject: [PATCH 15/32] Fix global leak --- js/id/renderer/background.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/id/renderer/background.js b/js/id/renderer/background.js index 752853e6b..54e3835ee 100644 --- a/js/id/renderer/background.js +++ b/js/id/renderer/background.js @@ -3,7 +3,7 @@ iD.Background = function() { var deviceRatio = (window.devicePixelRatio && window.devicePixelRatio === 2) ? 0.5 : 1; // tileSize = (deviceRatio === 0.5) ? [128,128] : [256,256]; - tileSize = [256, 256]; + var tileSize = [256, 256]; var tile = d3.geo.tile(), projection, From 514ec1e28b75f90f7e6325e2f8b3408dd3b280ba Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 31 Jan 2013 12:44:11 -0500 Subject: [PATCH 16/32] Move validate --- Makefile | 1 + index.html | 2 +- js/id/{graph => }/validate.js | 0 3 files changed, 2 insertions(+), 1 deletion(-) rename js/id/{graph => }/validate.js (100%) diff --git a/Makefile b/Makefile index ddeef62b9..38244edc3 100644 --- a/Makefile +++ b/Makefile @@ -47,6 +47,7 @@ all: \ js/id/svg/*.js \ js/id/ui.js \ js/id/ui/*.js \ + js/id/validate.js \ js/id/end.js \ locale/locale.js \ locale/en.js diff --git a/index.html b/index.html index 03bf6386f..3bb3152e4 100644 --- a/index.html +++ b/index.html @@ -122,7 +122,7 @@ - + diff --git a/js/id/graph/validate.js b/js/id/validate.js similarity index 100% rename from js/id/graph/validate.js rename to js/id/validate.js From 15e1bee3ecc04fac789a80de9444758b71173891 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 31 Jan 2013 12:45:39 -0500 Subject: [PATCH 17/32] Move controller --- Makefile | 2 +- index.html | 5 ++--- js/id/{controller => }/controller.js | 0 test/index.html | 3 +-- 4 files changed, 4 insertions(+), 6 deletions(-) rename js/id/{controller => }/controller.js (100%) diff --git a/Makefile b/Makefile index 38244edc3..a501d0d20 100644 --- a/Makefile +++ b/Makefile @@ -40,7 +40,7 @@ all: \ js/id/modes/*.js \ js/id/operations.js \ js/id/operations/*.js \ - js/id/controller/*.js \ + js/id/controller.js \ js/id/graph/*.js \ js/id/renderer/*.js \ js/id/svg.js \ diff --git a/index.html b/index.html index 3bb3152e4..e5e202c4a 100644 --- a/index.html +++ b/index.html @@ -114,16 +114,15 @@ - - - + + diff --git a/js/id/controller/controller.js b/js/id/controller.js similarity index 100% rename from js/id/controller/controller.js rename to js/id/controller.js diff --git a/test/index.html b/test/index.html index 90e5bc9fa..52070c414 100644 --- a/test/index.html +++ b/test/index.html @@ -109,8 +109,6 @@ - - @@ -119,6 +117,7 @@ + From 5c8aa46e1f6739d93d6a57e47812af9d54bbc535 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Thu, 31 Jan 2013 12:47:02 -0500 Subject: [PATCH 18/32] Fix graph.difference --- js/id/graph/graph.js | 54 ++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/js/id/graph/graph.js b/js/id/graph/graph.js index 5e865b9ec..26735ff2e 100644 --- a/js/id/graph/graph.js +++ b/js/id/graph/graph.js @@ -235,44 +235,38 @@ iD.Graph.prototype = { }, difference: function (graph) { - var result = [], - keys = Object.keys(this.entities), - entity, oldentity, id, i; - for (i = 0; i < keys.length; i++) { - id = keys[i]; - entity = this.entities[id]; - oldentity = graph.entities[id]; - if (entity !== oldentity) { + function diff(a, b) { + var result = [], + keys = Object.keys(a.entities), + entity, oldentity, id, i; - if (entity && entity.type === 'way' && - oldentity && oldentity.type === 'way') { - result = result - .concat(_.difference(entity.nodes, oldentity.nodes)) - .concat(_.difference(oldentity.nodes, entity.nodes)); + for (i = 0; i < keys.length; i++) { + id = keys[i]; + entity = a.entities[id]; + oldentity = b.entities[id]; + if (entity !== oldentity) { - } else if (entity && entity.type === 'way') { - result = result.concat(entity.nodes); + if (entity && entity.type === 'way' && + oldentity && oldentity.type === 'way') { + result = result + .concat(_.difference(entity.nodes, oldentity.nodes)) + .concat(_.difference(oldentity.nodes, entity.nodes)); - } else if (oldentity && oldentity.type === 'way') { - result = result.concat(oldentity.nodes); + } else if (entity && entity.type === 'way') { + result = result.concat(entity.nodes); + + } else if (oldentity && oldentity.type === 'way') { + result = result.concat(oldentity.nodes); + } + + result.push(id); } - - result.push(id); } + return result; } - keys = Object.keys(graph.entities); - for (i = 0; i < keys.length; i++) { - id = keys[i]; - entity = graph.entities[id]; - if (entity && !this.entities.hasOwnProperty(id)) { - result.push(id); - if (entity.type === 'way') result = result.concat(entity.nodes); - } - } - - return result.sort(); + return _.unique(diff(this, graph).concat(diff(graph, this)).sort()); }, modified: function() { From d5133b1a5ea8cf6052b67f8db9ea4361b4cf0656 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 31 Jan 2013 12:54:01 -0500 Subject: [PATCH 19/32] Fix build --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index a501d0d20..1db4f2efb 100644 --- a/Makefile +++ b/Makefile @@ -23,6 +23,7 @@ all: \ js/lib/jxon.js \ js/lib/lodash.js \ js/lib/ohauth.js \ + js/lib/rtree.js \ js/lib/sha.js \ js/id/start.js \ js/id/id.js \ From 8bece3de15547b1f79fa9f3e6f7602fd99818be7 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 31 Jan 2013 12:55:35 -0500 Subject: [PATCH 20/32] Remove unused --- index.html | 1 - js/lib/queue.js | 84 ------------------------------------------------- 2 files changed, 85 deletions(-) delete mode 100644 js/lib/queue.js diff --git a/index.html b/index.html index e5e202c4a..f286e8a52 100644 --- a/index.html +++ b/index.html @@ -24,7 +24,6 @@ - diff --git a/js/lib/queue.js b/js/lib/queue.js deleted file mode 100644 index 9a3b9da47..000000000 --- a/js/lib/queue.js +++ /dev/null @@ -1,84 +0,0 @@ -(function() { - if (typeof module === "undefined") self.queue = queue; - else module.exports = queue; - - queue.version = "1.0.0"; - - function queue(parallelism) { - var queue = {}, - active = 0, // number of in-flight deferrals - remaining = 0, // number of deferrals remaining - head, tail, // singly-linked list of deferrals - error = null, - results = [], - await = noop, - awaitAll; - - if (arguments.length < 1) parallelism = Infinity; - - queue.defer = function() { - if (!error) { - var node = arguments; - node.index = results.push(undefined) - 1; - if (tail) tail.next = node, tail = tail.next; - else head = tail = node; - ++remaining; - pop(); - } - return queue; - }; - - queue.await = function(f) { - await = f; - awaitAll = false; - if (!remaining) notify(); - return queue; - }; - - queue.awaitAll = function(f) { - await = f; - awaitAll = true; - if (!remaining) notify(); - return queue; - }; - - function pop() { - if (head && active < parallelism) { - var node = head, - f = node[0], - a = Array.prototype.slice.call(node, 1), - i = node.index; - if (head === tail) head = tail = null; - else head = head.next; - ++active; - a.push(function(e, r) { - --active; - if (error != null) return; - if (e != null) { - // clearing remaining cancels subsequent callbacks - // clearing head stops queued tasks from being executed - // setting error ignores subsequent calls to defer - error = e; - remaining = results = head = tail = null; - notify(); - } else { - results[i] = r; - if (--remaining) pop(); - else notify(); - } - }); - f.apply(null, a); - } - } - - function notify() { - if (error != null) await(error); - else if (awaitAll) await(null, results); - else await.apply(null, [null].concat(results)); - } - - return queue; - } - - function noop() {} -})(); From a48453c6eddd1d8be71a28c061b91feb2f365f96 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 31 Jan 2013 13:03:50 -0500 Subject: [PATCH 21/32] Selected style should take precedence over hover (fixes #568) --- css/map.css | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/css/map.css b/css/map.css index 7b3038d6c..7589ac042 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; } -.behavior-hover g.point.hover .shadow { +.behavior-hover g.point.hover:not(.selected) .shadow { fill: #E96666; fill-opacity: 0.3; } @@ -106,7 +106,7 @@ g.vertex .shadow { transition: transform 100ms linear; -moz-transition: fill 100ms linear; } -.behavior-hover g.vertex.hover .shadow { +.behavior-hover g.vertex.hover:not(.selected) .shadow { fill: #E96666; fill-opacity: 0.3; } @@ -120,7 +120,7 @@ g.vertex.selected .shadow { g.midpoint .fill { fill:#aaa; } -.behavior-hover g.midpoint .fill.hover { +.behavior-hover g.midpoint .fill.hover:not(.selected) { fill:#fff; stroke:#000; } @@ -133,7 +133,7 @@ g.midpoint .shadow { transition: transform 100ms linear; -moz-transition: fill 100ms linear; } -.behavior-hover g.midpoint .shadow.hover { +.behavior-hover g.midpoint .shadow.hover:not(.selected) { fill:#E96666; fill-opacity: 0.3; } @@ -161,7 +161,7 @@ path.shadow { -webkit-transition: stroke 100ms linear; } -.behavior-hover path.shadow.hover { +.behavior-hover path.shadow.hover:not(.selected) { stroke: #E96666; stroke-opacity: 0.3; } From 846cf6e43de7c99a42ba147ad3dfb3f14667673e Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Thu, 31 Jan 2013 13:37:54 -0500 Subject: [PATCH 22/32] Add difference tests --- js/id/graph/graph.js | 1 + test/spec/graph/graph.js | 36 +++++++++++++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/js/id/graph/graph.js b/js/id/graph/graph.js index 26735ff2e..a19bfe094 100644 --- a/js/id/graph/graph.js +++ b/js/id/graph/graph.js @@ -247,6 +247,7 @@ iD.Graph.prototype = { oldentity = b.entities[id]; if (entity !== oldentity) { + // maybe adding affected children better belongs in renderer/map.js? if (entity && entity.type === 'way' && oldentity && oldentity.type === 'way') { result = result diff --git a/test/spec/graph/graph.js b/test/spec/graph/graph.js index 327d66295..05bcbbe89 100644 --- a/test/spec/graph/graph.js +++ b/test/spec/graph/graph.js @@ -345,12 +345,42 @@ describe('iD.Graph', function() { expect(graph2.difference(graph1)).to.eql([created.id, updated.id, deleted.id]); }); - it("includes created entities that were subsequently deleted", function () { + + it("includes created entities, and reverse", function () { var node = iD.Node(), - graph1 = iD.Graph([node]), - graph2 = graph1.remove(node); + graph1 = iD.Graph(), + graph2 = graph1.replace(node); expect(graph2.difference(graph1)).to.eql([node.id]); + expect(graph1.difference(graph2)).to.eql([node.id]); }); + + it("includes entities changed from base, and reverse", function () { + var node = iD.Node(), + graph1 = iD.Graph(node), + graph2 = graph1.replace(node.update()); + expect(graph2.difference(graph1)).to.eql([node.id]); + expect(graph1.difference(graph2)).to.eql([node.id]); + }); + + it("includes already changed entities that were updated, and reverse", function () { + var node = iD.Node(), + graph1 = iD.Graph().replace(node), + graph2 = graph1.replace(node.update()); + expect(graph2.difference(graph1)).to.eql([node.id]); + expect(graph1.difference(graph2)).to.eql([node.id]); + }); + + it("includes affected child nodes", function () { + var n = iD.Node({id: 'n'}), + n2 = iD.Node({id: 'n2'}), + w1 = iD.Way({id: 'w1', nodes: ['n']}), + w1_ = iD.Way({id: 'w1', nodes: ['n', 'n2']}), + graph1 = iD.Graph([n, n2, w1]), + graph2 = graph1.replace(w1_); + expect(graph2.difference(graph1)).to.eql(['n2', 'w1']); + expect(graph1.difference(graph2)).to.eql(['n2', 'w1']); + }); + }); describe("#modified", function () { From 402a9424c0af236bcaffa00c889b9c8b3f6aed61 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 31 Jan 2013 13:27:57 -0500 Subject: [PATCH 23/32] Make selection an array of entity IDs Should have no visible effect yet. --- js/id/behavior/draw_way.js | 2 +- js/id/modes/add_point.js | 2 +- js/id/modes/browse.js | 2 +- js/id/modes/move_way.js | 4 +- js/id/modes/select.js | 115 +++++++++++++++++--------------- js/id/operations/circularize.js | 7 +- js/id/operations/delete.js | 8 ++- js/id/operations/move.js | 8 ++- js/id/operations/reverse.js | 8 ++- js/id/operations/split.js | 8 ++- js/id/operations/unjoin.js | 8 ++- js/id/renderer/hash.js | 2 +- js/id/ui/save.js | 2 +- test/spec/modes/add_point.js | 2 +- 14 files changed, 100 insertions(+), 78 deletions(-) diff --git a/js/id/behavior/draw_way.js b/js/id/behavior/draw_way.js index ba28fe14b..1cc62b755 100644 --- a/js/id/behavior/draw_way.js +++ b/js/id/behavior/draw_way.js @@ -139,7 +139,7 @@ iD.behavior.DrawWay = function(wayId, index, mode, baseGraph) { var way = history.graph().entity(wayId); if (way) { - controller.enter(iD.modes.Select(way, true)); + controller.enter(iD.modes.Select([way.id], true)); } else { controller.enter(iD.modes.Browse()); } diff --git a/js/id/modes/add_point.js b/js/id/modes/add_point.js index 61ff51424..feff66f43 100644 --- a/js/id/modes/add_point.js +++ b/js/id/modes/add_point.js @@ -20,7 +20,7 @@ iD.modes.AddPoint = function() { iD.actions.AddEntity(node), t('operations.add.annotation.point')); - controller.enter(iD.modes.Select(node, true)); + controller.enter(iD.modes.Select([node.id], true)); } function addWay(way, loc, index) { diff --git a/js/id/modes/browse.js b/js/id/modes/browse.js index c7358bdea..b1fb1c8ae 100644 --- a/js/id/modes/browse.js +++ b/js/id/modes/browse.js @@ -24,7 +24,7 @@ iD.modes.Browse = function() { surface.on('click.browse', function () { var datum = d3.select(d3.event.target).datum(); if (datum instanceof iD.Entity) { - mode.controller.enter(iD.modes.Select(datum)); + mode.controller.enter(iD.modes.Select([datum.id])); } }); }; diff --git a/js/id/modes/move_way.js b/js/id/modes/move_way.js index d977f6719..50c228d8e 100644 --- a/js/id/modes/move_way.js +++ b/js/id/modes/move_way.js @@ -34,12 +34,12 @@ iD.modes.MoveWay = function(wayId) { function finish() { d3.event.stopPropagation(); - controller.enter(iD.modes.Select(way, true)); + controller.enter(iD.modes.Select([way.id], true)); } function cancel() { history.pop(); - controller.enter(iD.modes.Select(way, true)); + controller.enter(iD.modes.Select([way.id], true)); } function undone() { diff --git a/js/id/modes/select.js b/js/id/modes/select.js index 83e0d72b8..37b2dee1d 100644 --- a/js/id/modes/select.js +++ b/js/id/modes/select.js @@ -1,8 +1,7 @@ -iD.modes.Select = function(entity, initial) { +iD.modes.Select = function(selection, initial) { var mode = { id: 'select', - button: 'browse', - entity: entity + button: 'browse' }; var inspector = iD.ui.inspector().initial(!!initial), @@ -11,20 +10,29 @@ iD.modes.Select = function(entity, initial) { radialMenu; function changeTags(d, tags) { - if (!_.isEqual(entity.tags, tags)) { + if (!_.isEqual(singular().tags, tags)) { mode.history.perform( iD.actions.ChangeTags(d.id, tags), t('operations.change_tags.annotation')); } } + function singular() { + if (selection.length === 1) { + return mode.map.history().graph().entity(selection[0]); + } + } + + mode.selection = function() { + return selection; + }; + mode.enter = function() { var map = mode.map, - graph = map.history().graph(), history = map.history(), - surface = mode.map.surface; - - inspector.graph(graph); + graph = history.graph(), + surface = map.surface, + entity = singular(); behaviors = [ iD.behavior.Hover(), @@ -36,7 +44,7 @@ iD.modes.Select = function(entity, initial) { }); var operations = d3.values(iD.operations) - .map(function (o) { return o(entity.id, mode); }) + .map(function (o) { return o(selection, mode); }) .filter(function (o) { return o.available(); }); operations.forEach(function(operation) { @@ -49,46 +57,51 @@ iD.modes.Select = function(entity, initial) { var q = iD.util.stringQs(location.hash.substring(1)); location.replace('#' + iD.util.qsString(_.assign(q, { - id: entity.id + id: selection.join(',') }), true)); - d3.select('.inspector-wrap') - .style('display', 'block') - .style('opacity', 1) - .datum(entity) - .call(inspector); + if (entity) { + inspector.graph(graph); - if (d3.event) { - // Pan the map if the clicked feature intersects with the position - // of the inspector - var inspector_size = d3.select('.inspector-wrap').size(), - map_size = mode.map.size(), - offset = 50, - shift_left = d3.event.x - map_size[0] + inspector_size[0] + offset, - center = (map_size[0] / 2) + shift_left + offset; + d3.select('.inspector-wrap') + .style('display', 'block') + .style('opacity', 1) + .datum(entity) + .call(inspector); - if (shift_left > 0 && inspector_size[1] > d3.event.y) { - mode.map.centerEase(mode.map.projection.invert([center, map_size[1]/2])); + if (d3.event) { + // Pan the map if the clicked feature intersects with the position + // of the inspector + var inspector_size = d3.select('.inspector-wrap').size(), + map_size = mode.map.size(), + offset = 50, + shift_left = d3.event.x - map_size[0] + inspector_size[0] + offset, + center = (map_size[0] / 2) + shift_left + offset; + + if (shift_left > 0 && inspector_size[1] > d3.event.y) { + mode.map.centerEase(mode.map.projection.invert([center, map_size[1]/2])); + } } + + inspector + .on('changeTags', changeTags) + .on('close', function() { mode.controller.exit(); }); + + history.on('change.select', function() { + // Exit mode if selected entity gets undone + var oldEntity = entity, + newEntity = history.graph().entity(selection[0]); + + if (!newEntity) { + mode.controller.enter(iD.modes.Browse()); + } else if (!_.isEqual(oldEntity.tags, newEntity.tags)) { + inspector.tags(newEntity.tags); + } + + surface.call(radialMenu.close); + }); } - inspector - .on('changeTags', changeTags) - .on('close', function() { mode.controller.exit(); }); - - history.on('change.select', function() { - // Exit mode if selected entity gets undone - var old = entity; - entity = history.graph().entity(entity.id); - if (!entity) { - mode.controller.enter(iD.modes.Browse()); - } else if(!_.isEqual(entity.tags, old.tags)) { - inspector.tags(entity.tags); - } - - surface.call(radialMenu.close); - }); - map.on('move.select', function() { surface.call(radialMenu.close); }); @@ -96,17 +109,17 @@ iD.modes.Select = function(entity, initial) { function click() { var datum = d3.select(d3.event.target).datum(); if (datum instanceof iD.Entity) { - mode.controller.enter(iD.modes.Select(datum)); + mode.controller.enter(iD.modes.Select([datum.id])); } else { mode.controller.enter(iD.modes.Browse()); } } function dblclick() { - var selection = d3.select(d3.event.target), - datum = selection.datum(); + var target = d3.select(d3.event.target), + datum = target.datum(); - if (datum instanceof iD.Way && !selection.classed('fill')) { + if (datum instanceof iD.Way && !target.classed('fill')) { var choice = iD.geo.chooseIndex(datum, d3.mouse(mode.map.surface.node()), mode.map), node = iD.Node({ loc: choice.loc }); @@ -128,9 +141,7 @@ iD.modes.Select = function(entity, initial) { .call(keybinding); surface.selectAll("*") - .filter(function (d) { - return d && entity && d.id === entity.id; - }) + .filter(function (d) { return d && selection.indexOf(d.id) >= 0; }) .classed('selected', true); radialMenu = iD.ui.RadialMenu(operations); @@ -138,7 +149,7 @@ iD.modes.Select = function(entity, initial) { if (d3.event && !initial) { var loc = map.mouseCoordinates(); - if (entity.type === 'node') { + if (entity && entity.type === 'node') { loc = entity.loc; } @@ -150,8 +161,8 @@ iD.modes.Select = function(entity, initial) { var surface = mode.map.surface, history = mode.history; - if (entity) { - changeTags(entity, inspector.tags()); + if (singular()) { + changeTags(singular(), inspector.tags()); } d3.select('.inspector-wrap') diff --git a/js/id/operations/circularize.js b/js/id/operations/circularize.js index 91921dc2a..4b0f27bf9 100644 --- a/js/id/operations/circularize.js +++ b/js/id/operations/circularize.js @@ -1,5 +1,6 @@ -iD.operations.Circularize = function(entityId, mode) { - var history = mode.map.history(), +iD.operations.Circularize = function(selection, mode) { + var entityId = selection[0], + history = mode.map.history(), action = iD.actions.Circularize(entityId, mode.map); var operation = function() { @@ -13,7 +14,7 @@ iD.operations.Circularize = function(entityId, mode) { operation.available = function() { var graph = history.graph(), entity = graph.entity(entityId); - return entity.type === 'way'; + return selection.length === 1 && entity.type === 'way'; }; operation.enabled = function() { diff --git a/js/id/operations/delete.js b/js/id/operations/delete.js index 993d3eef4..12df22a09 100644 --- a/js/id/operations/delete.js +++ b/js/id/operations/delete.js @@ -1,5 +1,6 @@ -iD.operations.Delete = function(entityId, mode) { - var history = mode.map.history(); +iD.operations.Delete = function(selection, mode) { + var entityId = selection[0], + history = mode.map.history(); var operation = function() { var graph = history.graph(), @@ -15,7 +16,8 @@ iD.operations.Delete = function(entityId, mode) { operation.available = function() { var graph = history.graph(), entity = graph.entity(entityId); - return entity.type === 'way' || entity.type === 'node'; + return selection.length === 1 && + (entity.type === 'way' || entity.type === 'node'); }; operation.enabled = function() { diff --git a/js/id/operations/move.js b/js/id/operations/move.js index 5034c2f75..10405cc53 100644 --- a/js/id/operations/move.js +++ b/js/id/operations/move.js @@ -1,5 +1,6 @@ -iD.operations.Move = function(entityId, mode) { - var history = mode.map.history(); +iD.operations.Move = function(selection, mode) { + var entityId = selection[0], + history = mode.map.history(); var operation = function() { mode.controller.enter(iD.modes.MoveWay(entityId)); @@ -7,7 +8,8 @@ iD.operations.Move = function(entityId, mode) { operation.available = function() { var graph = history.graph(); - return graph.entity(entityId).type === 'way'; + return selection.length === 1 && + graph.entity(entityId).type === 'way'; }; operation.enabled = function() { diff --git a/js/id/operations/reverse.js b/js/id/operations/reverse.js index ca9dd6440..78b8789dd 100644 --- a/js/id/operations/reverse.js +++ b/js/id/operations/reverse.js @@ -1,5 +1,6 @@ -iD.operations.Reverse = function(entityId, mode) { - var history = mode.map.history(); +iD.operations.Reverse = function(selection, mode) { + var entityId = selection[0], + history = mode.map.history(); var operation = function() { history.perform( @@ -10,7 +11,8 @@ iD.operations.Reverse = function(entityId, mode) { operation.available = function() { var graph = history.graph(), entity = graph.entity(entityId); - return entity.geometry(graph) === 'line'; + return selection.length === 1 && + entity.geometry(graph) === 'line'; }; operation.enabled = function() { diff --git a/js/id/operations/split.js b/js/id/operations/split.js index ff3f8af20..4274fc41b 100644 --- a/js/id/operations/split.js +++ b/js/id/operations/split.js @@ -1,5 +1,6 @@ -iD.operations.Split = function(entityId, mode) { - var history = mode.map.history(), +iD.operations.Split = function(selection, mode) { + var entityId = selection[0], + history = mode.map.history(), action = iD.actions.SplitWay(entityId); var operation = function() { @@ -9,7 +10,8 @@ iD.operations.Split = function(entityId, mode) { operation.available = function() { var graph = history.graph(), entity = graph.entity(entityId); - return entity.geometry(graph) === 'vertex'; + return selection.length === 1 && + entity.geometry(graph) === 'vertex'; }; operation.enabled = function() { diff --git a/js/id/operations/unjoin.js b/js/id/operations/unjoin.js index 175c13973..2a40ec067 100644 --- a/js/id/operations/unjoin.js +++ b/js/id/operations/unjoin.js @@ -1,5 +1,6 @@ -iD.operations.Unjoin = function(entityId, mode) { - var history = mode.map.history(), +iD.operations.Unjoin = function(selection, mode) { + var entityId = selection[0], + history = mode.map.history(), action = iD.actions.UnjoinNode(entityId); var operation = function() { @@ -9,7 +10,8 @@ iD.operations.Unjoin = function(entityId, mode) { operation.available = function() { var graph = history.graph(), entity = graph.entity(entityId); - return entity.geometry(graph) === 'vertex'; + return selection.length === 1 && + entity.geometry(graph) === 'vertex'; }; operation.enabled = function() { diff --git a/js/id/renderer/hash.js b/js/id/renderer/hash.js index 384705543..f4204531f 100644 --- a/js/id/renderer/hash.js +++ b/js/id/renderer/hash.js @@ -49,7 +49,7 @@ iD.Hash = function() { var entity = map.history().graph().entity(id); if (entity === undefined) return; else selectoff(); - controller.enter(iD.modes.Select(entity)); + controller.enter(iD.modes.Select([entity.id])); map.on('drawn.hash', null); }); controller.on('enter.hash', function() { diff --git a/js/id/ui/save.js b/js/id/ui/save.js index 8784b2ca4..b8085e21a 100644 --- a/js/id/ui/save.js +++ b/js/id/ui/save.js @@ -60,7 +60,7 @@ iD.ui.save = function() { .on('fix', function(d) { map.extent(d.entity.extent(map.history().graph())); if (map.zoom() > 19) map.zoom(19); - controller.enter(iD.modes.Select(d.entity)); + controller.enter(iD.modes.Select([d.entity.id])); modal.remove(); }) .on('save', commit)); diff --git a/test/spec/modes/add_point.js b/test/spec/modes/add_point.js index 68fe80403..a284cf682 100644 --- a/test/spec/modes/add_point.js +++ b/test/spec/modes/add_point.js @@ -28,7 +28,7 @@ describe("iD.modes.AddPoint", function () { it("selects the node", function () { happen.click(map.surface.node(), {}); expect(controller.mode.id).to.equal('select'); - expect(controller.mode.entity).to.equal(history.changes().created[0]); + expect(controller.mode.selection()).to.eql([history.changes().created[0].id]); }); }); From 26dfaf81614b521ebfc137a51bdffa0691a5d699 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Thu, 31 Jan 2013 14:43:41 -0500 Subject: [PATCH 24/32] Revise label stack --- css/map.css | 7 +------ js/id/svg/labels.js | 30 ++++++++++++++++++++++++------ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/css/map.css b/css/map.css index 7589ac042..e3e05a044 100644 --- a/css/map.css +++ b/css/map.css @@ -628,12 +628,7 @@ text.pointlabel { } -text.area.tag-leisure-park { - font-size: 16px; -} - -text.point.tag-shop, -text.point.tag-amenity { +text.point { font-size: 9px; } diff --git a/js/id/svg/labels.js b/js/id/svg/labels.js index 3962c4915..774fc264e 100644 --- a/js/id/svg/labels.js +++ b/js/id/svg/labels.js @@ -2,18 +2,36 @@ iD.svg.Labels = function(projection) { // Replace with dict and iterate over entities tags instead? var label_stack = [ + ['line', 'aeroway'], ['line', 'highway'], - ['area', 'building', 'yes'], - ['area', 'leisure', 'park'], + ['line', 'railway'], + ['line', 'waterway'], + ['area', 'aeroway'], + ['area', 'amenity'], + ['area', 'building'], + ['area', 'historic'], + ['area', 'leisure'], + ['area', 'man_made'], ['area', 'natural'], + ['area', 'shop'], + ['area', 'tourism'], + ['point', 'aeroway'], ['point', 'amenity'], - ['point', 'shop'] + ['point', 'building'], + ['point', 'historic'], + ['point', 'leisure'], + ['point', 'man_made'], + ['point', 'natural'], + ['point', 'shop'], + ['point', 'tourism'], + ['line', 'name'], + ['area', 'name'], + ['point', 'name'] ]; var default_size = 12; var font_sizes = label_stack.map(function(d) { - var style = iD.util.getStyle( - 'text.' + d[0] + '.tag-' + d.slice(1).join('-')); + var style = iD.util.getStyle('text.' + d[0] + '.tag-' + d[1]); var m = style && style.cssText.match("font-size: ([0-9]{1,2})px;"); if (!m) return default_size; return parseInt(m[1], 10); @@ -210,7 +228,7 @@ iD.svg.Labels = function(projection) { if (hidePoints && entity.geometry(graph) === 'point') continue; for (k = 0; k < label_stack.length; k ++) { if (entity.geometry(graph) === label_stack[k][0] && - entity.tags[label_stack[k][1]] && !entity.tags[label_stack[k][2]]) { + entity.tags[label_stack[k][1]]) { labelable[k].push(entity); break; } From 8dcb215fe31fa7a2ff65ee81a49ab464ba04d10f Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Thu, 31 Jan 2013 15:40:17 -0500 Subject: [PATCH 25/32] Hide labels on mouseover --- css/map.css | 8 ++++++++ js/id/svg/labels.js | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/css/map.css b/css/map.css index e3e05a044..8ad55c790 100644 --- a/css/map.css +++ b/css/map.css @@ -616,6 +616,14 @@ text.pointlabel { pointer-events: none; } +.layer-halo rect, +.layer-halo path, +.layer-label text { + -webkit-transition: opacity 100ms linear; + transition: opacity 100ms linear; + -moz-transition: opacity 100ms linear; +} + .pathlabel .textpath { dominant-baseline: middle; } diff --git a/js/id/svg/labels.js b/js/id/svg/labels.js index 774fc264e..eb4297bca 100644 --- a/js/id/svg/labels.js +++ b/js/id/svg/labels.js @@ -200,12 +200,31 @@ iD.svg.Labels = function(projection) { } + function hideOnMouseover() { + var mouse = d3.mouse(this), + pad = 50, + rect = new RTree.Rectangle(mouse[0] - pad, mouse[1] - pad, 2*pad, 2*pad), + labels = _.pluck(rtree.search(rect, this), 'leaf'), + selection = d3.select(this); + + selection.selectAll('.layer-label text, .layer-halo path, .layer-halo rect') + .style('opacity', ''); + + if (!labels.length) return; + selection.selectAll('.layer-label text, .layer-halo path, .layer-halo rect') + .filter(function(d) { + return _.contains(labels, d.id); + }) + .style('opacity', 0); + } var rtree = new RTree(), rectangles = {}; return function drawLabels(surface, graph, entities, filter, dimensions, fullRedraw) { + d3.select(surface.node().parentNode) + .on('mousemove.hidelabels', hideOnMouseover); var hidePoints = !d3.select('.node.point').node(); From 7ea7326f9227198df3e846115019af222d08cb18 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 31 Jan 2013 14:11:53 -0500 Subject: [PATCH 26/32] Extract Select behavior --- index.html | 1 + js/id/behavior/select.js | 22 ++++++++++++++++++++++ js/id/modes/browse.js | 10 +--------- js/id/modes/select.js | 22 +++++----------------- test/index.html | 1 + 5 files changed, 30 insertions(+), 26 deletions(-) create mode 100644 js/id/behavior/select.js diff --git a/index.html b/index.html index f286e8a52..4fe1bd621 100644 --- a/index.html +++ b/index.html @@ -94,6 +94,7 @@ + diff --git a/js/id/behavior/select.js b/js/id/behavior/select.js new file mode 100644 index 000000000..cee2cc940 --- /dev/null +++ b/js/id/behavior/select.js @@ -0,0 +1,22 @@ +iD.behavior.Select = function(mode) { + var controller = mode.controller; + + function click() { + var datum = d3.select(d3.event.target).datum(); + if (datum instanceof iD.Entity) { + controller.enter(iD.modes.Select([datum.id])); + } else { + controller.enter(iD.modes.Browse()); + } + } + + var behavior = function(selection) { + selection.on('click.select', click); + }; + + behavior.off = function(selection) { + selection.on('click.select', null); + }; + + return behavior; +}; diff --git a/js/id/modes/browse.js b/js/id/modes/browse.js index b1fb1c8ae..7652576ea 100644 --- a/js/id/modes/browse.js +++ b/js/id/modes/browse.js @@ -14,19 +14,13 @@ iD.modes.Browse = function() { behaviors = [ iD.behavior.Hover(), + iD.behavior.Select(mode), iD.behavior.DragNode(mode), iD.behavior.DragMidpoint(mode)]; behaviors.forEach(function(behavior) { behavior(surface); }); - - surface.on('click.browse', function () { - var datum = d3.select(d3.event.target).datum(); - if (datum instanceof iD.Entity) { - mode.controller.enter(iD.modes.Select([datum.id])); - } - }); }; mode.exit = function() { @@ -35,8 +29,6 @@ iD.modes.Browse = function() { behaviors.forEach(function(behavior) { behavior.off(surface); }); - - surface.on('click.browse', null); }; return mode; diff --git a/js/id/modes/select.js b/js/id/modes/select.js index 37b2dee1d..b369bfca7 100644 --- a/js/id/modes/select.js +++ b/js/id/modes/select.js @@ -36,6 +36,7 @@ iD.modes.Select = function(selection, initial) { behaviors = [ iD.behavior.Hover(), + iD.behavior.Select(mode), iD.behavior.DragNode(mode), iD.behavior.DragMidpoint(mode)]; @@ -106,15 +107,6 @@ iD.modes.Select = function(selection, initial) { surface.call(radialMenu.close); }); - function click() { - var datum = d3.select(d3.event.target).datum(); - if (datum instanceof iD.Entity) { - mode.controller.enter(iD.modes.Select([datum.id])); - } else { - mode.controller.enter(iD.modes.Browse()); - } - } - function dblclick() { var target = d3.select(d3.event.target), datum = target.datum(); @@ -134,13 +126,11 @@ iD.modes.Select = function(selection, initial) { } } - surface.on('click.select', click) - .on('dblclick.select', dblclick); - d3.select(document) .call(keybinding); - surface.selectAll("*") + surface.on('dblclick.select', dblclick) + .selectAll("*") .filter(function (d) { return d && selection.indexOf(d.id) >= 0; }) .classed('selected', true); @@ -182,12 +172,10 @@ iD.modes.Select = function(selection, initial) { keybinding.off(); - surface.on('click.select', null) - .on('dblclick.select', null); - history.on('change.select', null); - surface.selectAll(".selected") + surface.on('dblclick.select', null) + .selectAll(".selected") .classed('selected', false); surface.call(radialMenu.close); diff --git a/test/index.html b/test/index.html index 52070c414..370b238fe 100644 --- a/test/index.html +++ b/test/index.html @@ -90,6 +90,7 @@ + From 5f41b74955e981e4265c66875c284daa044487d7 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 31 Jan 2013 16:00:02 -0500 Subject: [PATCH 27/32] Remove controller.exit --- js/id/behavior/add_way.js | 2 +- js/id/controller.js | 4 ---- js/id/modes/add_point.js | 2 +- js/id/modes/select.js | 2 +- 4 files changed, 3 insertions(+), 7 deletions(-) diff --git a/js/id/behavior/add_way.js b/js/id/behavior/add_way.js index fa038d201..89ba7f1cd 100644 --- a/js/id/behavior/add_way.js +++ b/js/id/behavior/add_way.js @@ -32,7 +32,7 @@ iD.behavior.AddWay = function(mode) { }; addWay.cancel = function() { - controller.exit(); + controller.enter(iD.modes.Browse()); }; return d3.rebind(addWay, event, 'on'); diff --git a/js/id/controller.js b/js/id/controller.js index 7e74c56d4..6c4e0fd1e 100644 --- a/js/id/controller.js +++ b/js/id/controller.js @@ -19,9 +19,5 @@ iD.Controller = function(map, history) { event.enter(mode); }; - controller.exit = function() { - controller.enter(iD.modes.Browse()); - }; - return d3.rebind(controller, event, 'on'); }; diff --git a/js/id/modes/add_point.js b/js/id/modes/add_point.js index feff66f43..6dd524bb5 100644 --- a/js/id/modes/add_point.js +++ b/js/id/modes/add_point.js @@ -32,7 +32,7 @@ iD.modes.AddPoint = function() { } function cancel() { - controller.exit(); + controller.enter(iD.modes.Browse()); } behavior = iD.behavior.Draw(map) diff --git a/js/id/modes/select.js b/js/id/modes/select.js index b369bfca7..8d29450d6 100644 --- a/js/id/modes/select.js +++ b/js/id/modes/select.js @@ -86,7 +86,7 @@ iD.modes.Select = function(selection, initial) { inspector .on('changeTags', changeTags) - .on('close', function() { mode.controller.exit(); }); + .on('close', function() { mode.controller.enter(iD.modes.Browse()); }); history.on('change.select', function() { // Exit mode if selected entity gets undone From 7ca6934f8a51888705a42c3bd05c0b8d0c48d5c2 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Thu, 31 Jan 2013 16:42:28 -0500 Subject: [PATCH 28/32] Fix #580 --- js/id/svg/lines.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/id/svg/lines.js b/js/id/svg/lines.js index 65cfccd27..83c533255 100644 --- a/js/id/svg/lines.js +++ b/js/id/svg/lines.js @@ -35,7 +35,7 @@ iD.svg.Lines = function(projection) { return function drawLines(surface, graph, entities, filter) { function drawPaths(group, lines, filter, classes, lineString) { - var paths = group.selectAll('path') + var paths = group.selectAll('path.line') .filter(filter) .data(lines, iD.Entity.key); From f430ecd6223d967f91ec710c61cf9d8f2f52b64a Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Thu, 31 Jan 2013 17:12:37 -0500 Subject: [PATCH 29/32] Fix keyboard-initiated way moving --- js/id/modes/move_way.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/js/id/modes/move_way.js b/js/id/modes/move_way.js index 50c228d8e..5c262e259 100644 --- a/js/id/modes/move_way.js +++ b/js/id/modes/move_way.js @@ -16,14 +16,18 @@ iD.modes.MoveWay = function(wayId) { origin = d3.mouse(selection.node()), annotation = t('operations.move.annotation.' + way.geometry(graph)); + // If intiated via keyboard + if (!origin[0] && !origin[1]) origin = null; + history.perform( iD.actions.Noop(), annotation); function move() { var p = d3.mouse(selection.node()), - delta = [p[0] - origin[0], - p[1] - origin[1]]; + delta = origin ? + [p[0] - origin[0], p[1] - origin[1]] : + [0, 0]; origin = p; From b9d77a8de6bab1c43396df97e70911f7cf3bf842 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Thu, 31 Jan 2013 17:44:14 -0500 Subject: [PATCH 30/32] Set data on midpoint circles --- js/id/svg/midpoints.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/js/id/svg/midpoints.js b/js/id/svg/midpoints.js index ee8d2c5e2..16cccd7f3 100644 --- a/js/id/svg/midpoints.js +++ b/js/id/svg/midpoints.js @@ -47,6 +47,9 @@ iD.svg.Midpoints = function(projection) { groups.attr('transform', iD.svg.PointTransform(projection)); + groups.selectAll('circle') + .data(_.values(midpoints), function (d) { return d.id; }); + groups.exit() .remove(); }; From 9cb0879818cc8c4fae3d04a8c6065fb34ad914c0 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Thu, 31 Jan 2013 17:47:24 -0500 Subject: [PATCH 31/32] Selecting implicitly sets data --- js/id/svg/midpoints.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/js/id/svg/midpoints.js b/js/id/svg/midpoints.js index 16cccd7f3..935f84719 100644 --- a/js/id/svg/midpoints.js +++ b/js/id/svg/midpoints.js @@ -47,8 +47,7 @@ iD.svg.Midpoints = function(projection) { groups.attr('transform', iD.svg.PointTransform(projection)); - groups.selectAll('circle') - .data(_.values(midpoints), function (d) { return d.id; }); + groups.select('circle'); groups.exit() .remove(); From bbccec75be436b5a32ef93a6578fc80d07fafa66 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 31 Jan 2013 18:20:57 -0500 Subject: [PATCH 32/32] Convert Hash to a behavior --- index.html | 2 +- js/id/{renderer => behavior}/hash.js | 52 ++++++++++------------- js/id/id.js | 4 +- test/index.html | 4 +- test/index_packaged.html | 2 +- test/spec/{renderer => behavior}/hash.js | 53 ++++++++---------------- 6 files changed, 47 insertions(+), 70 deletions(-) rename js/id/{renderer => behavior}/hash.js (68%) rename test/spec/{renderer => behavior}/hash.js (51%) diff --git a/index.html b/index.html index 4fe1bd621..870436dd1 100644 --- a/index.html +++ b/index.html @@ -38,7 +38,6 @@ - @@ -93,6 +92,7 @@ + diff --git a/js/id/renderer/hash.js b/js/id/behavior/hash.js similarity index 68% rename from js/id/renderer/hash.js rename to js/id/behavior/hash.js index f4204531f..65e748e28 100644 --- a/js/id/renderer/hash.js +++ b/js/id/behavior/hash.js @@ -1,9 +1,6 @@ -iD.Hash = function() { - var hash = { hadHash: false }, - s0 = null, // cached location.hash - lat = 90 - 1e-8, // allowable latitude range - controller, - map; +iD.behavior.Hash = function(controller, map) { + var s0 = null, // cached location.hash + lat = 90 - 1e-8; // allowable latitude range var parser = function(map, s) { var q = iD.util.stringQs(s); @@ -61,32 +58,29 @@ iD.Hash = function() { map.on('drawn.hash', null); } - hash.controller = function(_) { - if (!arguments.length) return controller; - controller = _; - return hash; - }; + function hash() { + map.on('move.hash', move); - hash.map = function(x) { - if (!arguments.length) return map; - if (map) { - map.on("move.hash", null); - window.removeEventListener("hashchange", hashchange, false); - } - map = x; - if (x) { - map.on("move.hash", move); - window.addEventListener("hashchange", hashchange, false); - if (location.hash) { - var q = iD.util.stringQs(location.hash.substring(1)); - if (q.id) { - willselect(q.id); - } - hashchange(); - hash.hadHash = true; + d3.select(window) + .on('hashchange.hash', hashchange); + + if (location.hash) { + var q = iD.util.stringQs(location.hash.substring(1)); + if (q.id) { + willselect(q.id); } + hashchange(); + hash.hadHash = true; } - return hash; + } + + hash.off = function() { + map.on('move.hash', null); + + d3.select(window) + .on('hashchange.hash', null); + + location.hash = ""; }; return hash; diff --git a/js/id/id.js b/js/id/id.js index 69e64e5fe..7fa1d76e4 100644 --- a/js/id/id.js +++ b/js/id/id.js @@ -234,7 +234,9 @@ window.iD = function(container) { d3.select(document) .call(keybinding); - var hash = iD.Hash().controller(controller).map(map); + var hash = iD.behavior.Hash(controller, map); + + hash(); if (!hash.hadHash) { map.centerZoom([-77.02271, 38.90085], 20); diff --git a/test/index.html b/test/index.html index 370b238fe..d03c5a6c7 100644 --- a/test/index.html +++ b/test/index.html @@ -41,7 +41,6 @@ - @@ -89,6 +88,7 @@ + @@ -149,6 +149,7 @@ + @@ -163,7 +164,6 @@ - diff --git a/test/index_packaged.html b/test/index_packaged.html index 007392f3b..60979e236 100644 --- a/test/index_packaged.html +++ b/test/index_packaged.html @@ -44,6 +44,7 @@ + @@ -58,7 +59,6 @@ - diff --git a/test/spec/renderer/hash.js b/test/spec/behavior/hash.js similarity index 51% rename from test/spec/renderer/hash.js rename to test/spec/behavior/hash.js index b0e5b567f..7616bf536 100644 --- a/test/spec/renderer/hash.js +++ b/test/spec/behavior/hash.js @@ -1,60 +1,41 @@ -describe("iD.Hash", function () { +describe("iD.behavior.Hash", function () { var hash, map, controller; beforeEach(function () { - hash = iD.Hash(); map = { on: function () { return map; }, zoom: function () { return arguments.length ? map : 0; }, center: function () { return arguments.length ? map : [0, 0]; }, centerZoom: function () { return arguments.length ? map : [0, 0]; } }; + controller = { on: function () { return controller; } }; + + hash = iD.behavior.Hash(controller, map); }); afterEach(function () { - hash.map(null); - location.hash = ""; + hash.off(); }); - describe("#map()", function () { - it("gets and sets map", function () { - expect(hash.controller(controller).map(map)).to.equal(hash); - expect(hash.map()).to.equal(map); - }); + it("sets hadHash if location.hash is present", function () { + location.hash = "map=20.00/38.87952/-77.02405"; + hash(); + expect(hash.hadHash).to.be.true; + }); - it("sets hadHash if location.hash is present", function () { - location.hash = "map=20.00/38.87952/-77.02405"; - hash.map(map); - expect(hash.hadHash).to.be.true; - }); - - it("centerZooms map to requested level", function () { - location.hash = "map=20.00/38.87952/-77.02405"; - sinon.spy(map, 'centerZoom'); - hash.map(map); - expect(map.centerZoom).to.have.been.calledWith([-77.02405,38.87952], 20.0); - }); - - it("binds the map's move event", function () { - sinon.spy(map, 'on'); - hash.map(map); - expect(map.on).to.have.been.calledWith('move.hash', sinon.match.instanceOf(Function)); - }); - - it("unbinds the map's move event", function () { - sinon.spy(map, 'on'); - hash.map(map); - hash.map(null); - expect(map.on).to.have.been.calledWith('move.hash', null); - }); + it("centerZooms map to requested level", function () { + location.hash = "map=20.00/38.87952/-77.02405"; + sinon.spy(map, 'centerZoom'); + hash(); + expect(map.centerZoom).to.have.been.calledWith([-77.02405,38.87952], 20.0); }); describe("on window hashchange events", function () { beforeEach(function () { - hash.map(map); + hash(); }); function onhashchange(fn) { @@ -77,7 +58,7 @@ describe("iD.Hash", function () { sinon.stub(map, 'on') .withArgs("move.hash", sinon.match.instanceOf(Function)) .yields(); - hash.map(map); + hash(); expect(location.hash).to.equal("#map=0.00/0/0"); }); });