diff --git a/js/id/actions/modes.js b/js/id/actions/modes.js index d30441b85..eaee613c1 100644 --- a/js/id/actions/modes.js +++ b/js/id/actions/modes.js @@ -9,7 +9,7 @@ iD.modes._node = function(ll) { }; iD.modes.chooseIndex = function(way, point, map) { - var dist = iD.Util.dist; + var dist = iD.util.geo.dist; var projNodes = way.nodes.map(function(n) { return map.projection([n.lon, n.lat]); }); diff --git a/js/id/graph/entity.js b/js/id/graph/entity.js index 5ca2cfc9c..3c7749411 100644 --- a/js/id/graph/entity.js +++ b/js/id/graph/entity.js @@ -8,7 +8,7 @@ iD.Entity = function(a, b) { } if (!this.id) { - this.id = iD.Util.id(this.type); + this.id = iD.util.id(this.type); this._updated = true; } diff --git a/js/id/renderer/map.js b/js/id/renderer/map.js index 05f6aeffa..cacf85f02 100644 --- a/js/id/renderer/map.js +++ b/js/id/renderer/map.js @@ -30,7 +30,7 @@ iD.Map = function() { d3.event.sourceEvent.stopPropagation(); if (!dragging) { - dragging = iD.Util.trueObj([entity.id].concat( + dragging = iD.util.trueObj([entity.id].concat( _.pluck(history.graph().parents(entity.id), 'id'))); history.perform(iD.actions.noop()); } @@ -55,7 +55,7 @@ iD.Map = function() { d3.event.sourceEvent.stopPropagation(); if (!dragging) { - dragging = iD.Util.trueObj([entity.id].concat( + dragging = iD.util.trueObj([entity.id].concat( _.pluck(history.graph().parents(entity.id), 'id'))); history.perform(iD.actions.noop()); } @@ -75,7 +75,7 @@ iD.Map = function() { } }), nodeline = function(d) { - return 'M' + d.nodes.map(ll2a).map(projection).map(roundCoords).join('L'); + return 'M' + d.nodes.map(ll2a).map(projection).map(iD.util.geo.roundCoords).join('L'); }, getline = function(d) { return d._line; }, key = function(d) { return d.id; }, @@ -86,8 +86,7 @@ iD.Map = function() { class_fill = iD.Style.styleClasses('stroke'), class_area = iD.Style.styleClasses('area'), class_casing = iD.Style.styleClasses('casing'), - prefix = prefixMatch(['webkit', 'ms', 'Moz', 'O']), - transformProp = prefix + 'transform', + transformProp = iD.util.prefix() + 'transform', supersurface, surface, defs, tilegroup, r, g, alength; function map() { @@ -126,13 +125,7 @@ iD.Map = function() { map.surface = surface; } - function prefixMatch(p) { // via mbostock - var i = -1, n = p.length, s = document.body.style; - while (++i < n) if (p[i] + 'Transform' in s) return '-' + p[i].toLowerCase() + '-'; - return ''; - } function ll2a(o) { return [o.lon, o.lat]; } - function roundCoords(c) { return [Math.floor(c[0]), Math.floor(c[1])]; } function hideInspector() { d3.select('.inspector-wrap').style('display', 'none'); @@ -140,13 +133,6 @@ iD.Map = function() { function classActive(d) { return d.id === selection; } - function nodeIntersect(entity, extent) { - return entity.lon > extent[0][0] && - entity.lon < extent[1][0] && - entity.lat < extent[0][1] && - entity.lat > extent[1][1]; - } - function isArea(a) { return iD.Way.isClosed(a) || (a.tags.area && a.tags.area === 'yes'); } @@ -178,7 +164,7 @@ iD.Map = function() { else ways.push(a); } else if (a._poi) { points.push(a); - } else if (!a._poi && a.type === 'node' && nodeIntersect(a, extent)) { + } else if (!a._poi && a.type === 'node' && iD.util.geo.nodeIntersect(a, extent)) { waynodes.push(a); } } @@ -196,7 +182,7 @@ iD.Map = function() { function accuracyHandles(way) { var handles = []; for (var i = 0; i < way.nodes.length - 1; i++) { - handles[i] = iD.Node(iD.Util.interp(way.nodes[i], way.nodes[i + 1], 0.5)); + handles[i] = iD.Node(iD.util.geo.interp(way.nodes[i], way.nodes[i + 1], 0.5)); handles[i].way = way.id; handles[i].index = i + 1; handles[i].accuracy = true; @@ -340,7 +326,7 @@ iD.Map = function() { function connectionLoad(err, result) { history.merge(result); - drawVector(iD.Util.trueObj(Object.keys(result.entities))); + drawVector(iD.util.trueObj(Object.keys(result.entities))); } function nameHoverIn() { diff --git a/js/id/renderer/style.js b/js/id/renderer/style.js index 120c0445f..3dc4b5cc0 100644 --- a/js/id/renderer/style.js +++ b/js/id/renderer/style.js @@ -48,7 +48,7 @@ iD.Style.markerimage = function(d) { return 'icons/unknown.png'; }; -iD.Style.TAG_CLASSES = iD.Util.trueObj([ +iD.Style.TAG_CLASSES = iD.util.trueObj([ 'highway', 'railway', 'motorway', 'amenity', 'landuse', 'building', 'oneway', 'bridge', 'elastic' ]); diff --git a/js/id/taginfo.js b/js/id/taginfo.js index 4444bf52b..298c48e1e 100644 --- a/js/id/taginfo.js +++ b/js/id/taginfo.js @@ -4,7 +4,7 @@ iD.taginfo = function() { taginfo.values = function(key, callback) { d3.json(endpoint + 'db/keys/values?' + - iD.Util.qsString({ + iD.util.qsString({ key: key, rp: 20, sortname: 'count_all', diff --git a/js/id/ui/commit.js b/js/id/ui/commit.js index 41b577787..3a401d2f8 100644 --- a/js/id/ui/commit.js +++ b/js/id/ui/commit.js @@ -30,9 +30,9 @@ iD.commit = function() { li.append('strong').text(function(d) { return d.type + ' '; }); li.append('span') .text(function(d) { - return iD.Util.friendlyName(d); + return iD.util.friendlyName(d); }) - .attr('title', iD.Util.tagText); + .attr('title', iD.util.tagText); body.append('textarea') .attr('class', 'changeset-comment') diff --git a/js/id/ui/inspector.js b/js/id/ui/inspector.js index 45d8e6df9..68db9424b 100644 --- a/js/id/ui/inspector.js +++ b/js/id/ui/inspector.js @@ -5,7 +5,7 @@ iD.Inspector = function() { function drawhead(selection) { selection.html(''); selection.append('h2') - .text(iD.Util.friendlyName(selection.datum())); + .text(iD.util.friendlyName(selection.datum())); selection.append('a') .attr('class', 'permalink') .attr('href', function(d) { @@ -17,13 +17,13 @@ iD.Inspector = function() { .attr({ 'class': 'permalink', href: '#' }).text('XML') .on('click', function(d) { d3.event.stopPropagation(); - iD.Util.codeWindow(iD.format.XML.mapping(d)); + iD.util.codeWindow(iD.format.XML.mapping(d)); }); selection.append('a') .attr({ 'class': 'permalink', href: '#' }).text('GeoJSON') .on('click', function(d) { d3.event.stopPropagation(); - iD.Util.codeWindow(JSON.stringify( + iD.util.codeWindow(JSON.stringify( iD.format.GeoJSON.mapping(d), null, 2)); }); if (selection.datum().type === 'way') { diff --git a/js/id/util.js b/js/id/util.js index 4e4b1fce5..4d297d2a7 100644 --- a/js/id/util.js +++ b/js/id/util.js @@ -1,20 +1,20 @@ -iD.Util = {}; +iD.util = {}; -iD.Util._counters = {}; +iD.util._counters = {}; -iD.Util.id = function(counter) { +iD.util.id = function(counter) { counter = counter || 'default'; - if (!iD.Util._counters[counter]) iD.Util._counters[counter] = 0; - return counter[0] + (--iD.Util._counters[counter]); + if (!iD.util._counters[counter]) iD.util._counters[counter] = 0; + return counter[0] + (--iD.util._counters[counter]); }; -iD.Util.trueObj = function(arr) { +iD.util.trueObj = function(arr) { var o = {}; for (var i = 0, l = arr.length; i < l; i++) o[arr[i]] = true; return o; }; -iD.Util.friendlyName = function(entity) { +iD.util.friendlyName = function(entity) { // Generate a string such as 'river' or 'Fred's House' for an entity. if (!entity.tags || !Object.keys(entity.tags).length) { return ''; } @@ -36,7 +36,7 @@ iD.Util.friendlyName = function(entity) { return n.length === 0 ? 'unknown' : n.join('; '); }; -iD.Util.codeWindow = function(content) { +iD.util.codeWindow = function(content) { top.win = window.open('','contentWindow', 'width=350,height=350,menubar=0' + ',toolbar=1,status=0,scrollbars=1,resizable=1'); @@ -44,25 +44,47 @@ iD.Util.codeWindow = function(content) { top.win.document.close(); }; -iD.Util.tagText = function(entity) { +iD.util.tagText = function(entity) { return d3.entries(entity.tags).map(function(e) { return e.key + ': ' + e.value; }).join('\n'); }; -iD.Util.qsString = function(obj) { +iD.util.qsString = function(obj) { return Object.keys(obj).sort().map(function(key) { return encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]); }).join('&'); }; -iD.Util.interp = function(p1, p2, t) { +iD.util.prefix = function() { + return (function prefixMatch(p) { // via mbostock + var i = -1, n = p.length, s = document.body.style; + while (++i < n) if (p[i] + 'Transform' in s) return '-' + p[i].toLowerCase() + '-'; + return ''; + })(['webkit', 'ms', 'Moz', 'O']); +}; + +iD.util.geo = {}; + +iD.util.geo.roundCoords = function(c) { + return [Math.floor(c[0]), Math.floor(c[1])]; +}; + +iD.util.geo.interp = function(p1, p2, t) { return { lon: p1.lon + (p2.lon - p1.lon) * t, lat: p1.lat + (p2.lat - p1.lat) * t }; }; -iD.Util.dist = function(a, b) { - return Math.sqrt(Math.pow(a[0] - b[0], 2) + Math.pow(a[1] - b[1], 2)); +iD.util.geo.dist = function(a, b) { + return Math.sqrt(Math.pow(a[0] - b[0], 2) + + Math.pow(a[1] - b[1], 2)); +}; + +iD.util.geo.nodeIntersect = function(entity, extent) { + return entity.lon > extent[0][0] && + entity.lon < extent[1][0] && + entity.lat < extent[0][1] && + entity.lat > extent[1][1]; }; diff --git a/test/spec/util.js b/test/spec/util.js index 75e7cc170..3ed2127d9 100644 --- a/test/spec/util.js +++ b/test/spec/util.js @@ -1,24 +1,37 @@ describe('Util', function() { - var util; + var util; - it('#id', function() { - var a = iD.Util.id(), - b = iD.Util.id(), - c = iD.Util.id(), - d = iD.Util.id(); - expect(a === b).to.equal(false); - expect(b === c).to.equal(false); - expect(c === d).to.equal(false); - }); + it('#id', function() { + var a = iD.util.id(), + b = iD.util.id(), + c = iD.util.id(), + d = iD.util.id(); + expect(a === b).to.equal(false); + expect(b === c).to.equal(false); + expect(c === d).to.equal(false); + }); - 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('#trueObj', function() { + expect(iD.util.trueObj(['a', 'b', 'c'])).to.eql({ a: true, b: true, c: true }); + expect(iD.util.trueObj([])).to.eql({}); + }); - it('#friendlyName', function() { - expect(iD.Util.friendlyName({ tags: { name: 'hi' }})).to.equal('hi'); - expect(iD.Util.friendlyName({ tags: { highway: 'Route 5' }})).to.equal('Route 5'); - expect(iD.Util.friendlyName({ tags: { name: 'hi', highway: 'Route 5' }})).to.equal('hi'); - }); + it('#friendlyName', function() { + expect(iD.util.friendlyName({ tags: { name: 'hi' }})).to.equal('hi'); + expect(iD.util.friendlyName({ tags: { highway: 'Route 5' }})).to.equal('Route 5'); + expect(iD.util.friendlyName({ tags: { name: 'hi', highway: 'Route 5' }})).to.equal('hi'); + }); + + describe('#interp', function() { + it('interpolates halfway', function() { + var a = { lat: 0, lon: 0 }, + b = { lat: 10, lon: 10 }; + expect(iD.util.geo.interp(a, b, 0.5)).to.eql({ lat: 5, lon: 5}); + }); + it('interpolates to one side', function() { + var a = { lat: 0, lon: 0 }, + b = { lat: 10, lon: 10 }; + expect(iD.util.geo.interp(a, b, 0)).to.eql({ lat: 0, lon: 0}); + }); + }); });