diff --git a/Makefile b/Makefile index 826337109..bb6844399 100644 --- a/Makefile +++ b/Makefile @@ -52,8 +52,8 @@ all: \ js/id/ui/*.js \ js/id/validate.js \ js/id/end.js \ - locale/locale.js \ - locale/en.js + js/lib/locale.js \ + locale/*.js iD.js: Makefile @rm -f $@ diff --git a/css/app.css b/css/app.css index f42fbaf26..0e5651c9a 100644 --- a/css/app.css +++ b/css/app.css @@ -322,7 +322,7 @@ button.centered { border-radius:0 4px 4px 0; } -button.Browse .label { display: none;} +button.browse .label { display: none;} button.action { background: #7092ff; @@ -848,7 +848,7 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;} overflow-y: auto; } -.geocode-control div span { +.geocode-control div.content span { display: inline-block; border-bottom: 1px solid #333; padding: 5px 10px; diff --git a/index.html b/index.html index 4ea9d9721..e79c178e4 100644 --- a/index.html +++ b/index.html @@ -82,6 +82,7 @@ + @@ -146,14 +147,15 @@ - - - - + + + + + + - diff --git a/js/id/behavior/lasso.js b/js/id/behavior/lasso.js index 0a26f311d..6196cbf2e 100644 --- a/js/id/behavior/lasso.js +++ b/js/id/behavior/lasso.js @@ -12,7 +12,7 @@ iD.behavior.Lasso = function(context) { pos = [d3.event.clientX, d3.event.clientY]; - lasso = iD.ui.lasso().a(d3.mouse(context.surface().node())); + lasso = iD.ui.Lasso().a(d3.mouse(context.surface().node())); context.surface().call(lasso); diff --git a/js/id/behavior/select.js b/js/id/behavior/select.js index 7369af97c..162535764 100644 --- a/js/id/behavior/select.js +++ b/js/id/behavior/select.js @@ -1,78 +1,32 @@ iD.behavior.Select = function(context) { - var behavior = function(selection) { - - var timeout = null, - // the position of the first mousedown - pos = null; - - function click(event) { - d3.event = event; + function click() { var datum = d3.event.target.__data__; - if (datum instanceof iD.Entity) { - if (d3.event.shiftKey) { - context.enter(iD.modes.Select(context, context.selection().concat([datum.id]))); - } else { - context.enter(iD.modes.Select(context, [datum.id])); - } + if (!(datum instanceof iD.Entity)) { + if (!d3.event.shiftKey) + context.enter(iD.modes.Browse(context)); + } else if (!d3.event.shiftKey) { - context.enter(iD.modes.Browse(context)); + // Avoid re-entering Select mode with same entity. + if (context.selection().length !== 1 || context.selection()[0] !== datum.id) + context.enter(iD.modes.Select(context, [datum.id])); + + } else if (context.selection().indexOf(datum.id) >= 0) { + var selection = _.without(context.selection(), datum.id); + context.enter(selection.length ? + iD.modes.Select(context, selection) : + iD.modes.Browse(context)); + + } else { + context.enter(iD.modes.Select(context, context.selection().concat([datum.id]))); } } - function mousedown() { - var datum = d3.event.target.__data__; - pos = [d3.event.clientX, d3.event.clientY]; - if (datum instanceof iD.Entity || (datum && datum.type === 'midpoint')) { - selection - .on('mousemove.select', mousemove) - .on('touchmove.select', mousemove); - - // we've seen a mousedown within 400ms of this one, so ignore - // both because they will be a double click - if (timeout !== null) { - window.clearTimeout(timeout); - selection.on('mousemove.select', null); - timeout = null; - } else { - // queue the click handler to fire in 400ms if no other clicks - // are detected - timeout = window.setTimeout((function(event) { - return function() { - click(event); - timeout = null; - selection.on('mousemove.select', null); - }; - // save the event for the click handler - })(d3.event), 200); - } - } - } - - // allow mousemoves to cancel the click - function mousemove() { - if (iD.geo.dist([d3.event.clientX, d3.event.clientY], pos) > 4) { - window.clearTimeout(timeout); - timeout = null; - } - } - - function mouseup() { - selection.on('mousemove.select', null); - if (pos && d3.event.clientX === pos[0] && d3.event.clientY === pos[1] && - !(d3.event.target.__data__ instanceof iD.Entity)) { - context.enter(iD.modes.Browse(context)); - } - } - - selection - .on('mousedown.select', mousedown) - .on('mouseup.select', mouseup) - .on('touchstart.select', mousedown); + selection.on('click.select', click); }; behavior.off = function(selection) { - selection.on('mousedown.select', null); + selection.on('click.select', null); }; return behavior; diff --git a/js/id/id.js b/js/id/id.js index f0747ad02..5db609593 100644 --- a/js/id/id.js +++ b/js/id/id.js @@ -85,6 +85,8 @@ window.iD = function () { context.projection = map.projection; context.tail = map.tail; context.redraw = map.redraw; + context.zoomIn = map.zoomIn; + context.zoomOut = map.zoomOut; context.container = function(_) { if (!arguments.length) return container; diff --git a/js/id/modes/select.js b/js/id/modes/select.js index 9b12c8134..ac6ad4943 100644 --- a/js/id/modes/select.js +++ b/js/id/modes/select.js @@ -4,8 +4,9 @@ iD.modes.Select = function(context, selection, initial) { button: 'browse' }; - var inspector = iD.ui.inspector().initial(!!initial), + var inspector = iD.ui.Inspector().initial(!!initial), keybinding = d3.keybinding('select'), + timeout = null, behaviors = [ iD.behavior.Hover(), iD.behavior.Select(context), @@ -160,22 +161,27 @@ iD.modes.Select = function(context, selection, initial) { .call(keybinding); context.surface() - .on('dblclick.select', dblclick) .selectAll("*") .filter(selected) .classed('selected', true); radialMenu = iD.ui.RadialMenu(operations); + var showMenu = d3.event && !initial; - if (d3.event && !initial) { - var loc = context.map().mouseCoordinates(); - + if (showMenu) { if (entity && entity.type === 'node') { - loc = entity.loc; + radialMenu.center(context.projection(entity.loc)); + } else { + radialMenu.center(d3.mouse(context.surface().node())); } - - context.surface().call(radialMenu, context.projection(loc)); } + + timeout = window.setTimeout(function() { + if (showMenu) context.surface().call(radialMenu); + + context.surface() + .on('dblclick.select', dblclick) + }, 200); }; mode.exit = function() { @@ -183,6 +189,8 @@ iD.modes.Select = function(context, selection, initial) { changeTags(singular(), inspector.tags()); } + if (timeout) window.clearTimeout(timeout); + context.container() .select('.inspector-wrap') .style('display', 'none') diff --git a/js/id/ui.js b/js/id/ui.js index 535c825eb..48e5682bf 100644 --- a/js/id/ui.js +++ b/js/id/ui.js @@ -37,31 +37,21 @@ iD.ui = function(context) { .attr('class', 'button-wrap col1') .call(iD.ui.Save(context)); - var zoom = container.append('div') - .attr('class', 'zoombuttons map-control') - .selectAll('button') - .data([['zoom-in', '+', map.zoomIn, t('zoom-in')], ['zoom-out', '-', map.zoomOut, t('zoom-out')]]) - .enter() - .append('button') - .attr('tabindex', -1) - .attr('class', function(d) { return d[0]; }) - .attr('title', function(d) { return d[3]; }) - .on('click.editor', function(d) { return d[2](); }) - .append('span') - .attr('class', function(d) { - return d[0] + ' icon'; - }); + container.append('div') + .attr('class', 'map-control zoombuttons') + .call(iD.ui.Zoom(context)); - if (navigator.geolocation) { - container.append('div') - .call(iD.ui.geolocate(map)); - } + container.append('div') + .attr('class', 'map-control geocode-control') + .call(iD.ui.Geocoder(context)); - container.append('div').attr('class', 'geocode-control map-control') - .call(iD.ui.geocoder(context)); + container.append('div') + .attr('class', 'map-control layerswitcher-control') + .call(iD.ui.LayerSwitcher(context)); - container.append('div').attr('class', 'map-control layerswitcher-control') - .call(iD.ui.layerswitcher(context)); + container.append('div') + .attr('class', 'map-control geolocate-control') + .call(iD.ui.Geolocate(map)); container.append('div') .style('display', 'none') @@ -113,7 +103,7 @@ iD.ui = function(context) { linkList.append('li') .attr('id', 'user-list') - .call(iD.ui.contributors(context)); + .call(iD.ui.Contributors(context)); window.onbeforeunload = function() { history.save(); @@ -139,11 +129,7 @@ iD.ui = function(context) { .on('←', pan([pa, 0])) .on('↑', pan([0, pa])) .on('→', pan([-pa, 0])) - .on('↓', pan([0, -pa])) - .on('⇧=', function() { map.zoomIn(); }) - .on('+', function() { map.zoomIn(); }) - .on('-', function() { map.zoomOut(); }) - .on('dash', function() { map.zoomOut(); }); + .on('↓', pan([0, -pa])); d3.select(document) .call(keybinding); @@ -156,7 +142,7 @@ iD.ui = function(context) { map.centerZoom([-77.02271, 38.90085], 20); } - userContainer.call(iD.ui.userpanel(connection) + userContainer.call(iD.ui.UserPanel(connection) .on('logout.editor', connection.logout) .on('login.editor', connection.authenticate)); diff --git a/js/id/ui/commit.js b/js/id/ui/commit.js index 8d724a732..6708ece49 100644 --- a/js/id/ui/commit.js +++ b/js/id/ui/commit.js @@ -1,4 +1,4 @@ -iD.ui.commit = function(context) { +iD.ui.Commit = function(context) { var event = d3.dispatch('cancel', 'save', 'fix'); function zipSame(d) { diff --git a/js/id/ui/contributors.js b/js/id/ui/contributors.js index 596c576ad..2389f266a 100644 --- a/js/id/ui/contributors.js +++ b/js/id/ui/contributors.js @@ -1,4 +1,4 @@ -iD.ui.contributors = function(context) { +iD.ui.Contributors = function(context) { function update(selection) { var users = {}, limit = 3, diff --git a/js/id/ui/geocoder.js b/js/id/ui/geocoder.js index 7b79c2158..cc0ce205c 100644 --- a/js/id/ui/geocoder.js +++ b/js/id/ui/geocoder.js @@ -1,4 +1,4 @@ -iD.ui.geocoder = function(context) { +iD.ui.Geocoder = function(context) { function resultExtent(bounds) { return new iD.geo.Extent( [parseFloat(bounds[3]), parseFloat(bounds[0])], @@ -64,7 +64,7 @@ iD.ui.geocoder = function(context) { function setVisible(show) { if (show !== shown) { button.classed('active', show); - gcForm.call(iD.ui.toggle(show)); + gcForm.call(iD.ui.Toggle(show)); if (!show) resultsList.classed('hide', !show); if (show) inputNode.node().focus(); else inputNode.node().blur(); @@ -75,8 +75,12 @@ iD.ui.geocoder = function(context) { var button = selection.append('button') .attr('tabindex', -1) .attr('title', t('geocoder.title')) - .html('') - .on('click', toggle); + .on('click', toggle) + .call(bootstrap.tooltip() + .placement('right')); + + button.append('span') + .attr('class', 'icon geocode'); var gcForm = selection.append('form'); diff --git a/js/id/ui/geolocate.js b/js/id/ui/geolocate.js index 14b060e8a..d1d3f3772 100644 --- a/js/id/ui/geolocate.js +++ b/js/id/ui/geolocate.js @@ -1,4 +1,8 @@ -iD.ui.geolocate = function(map) { +iD.ui.Geolocate = function(map) { + function click() { + navigator.geolocation.getCurrentPosition( + success, error); + } function success(position) { map.center([position.coords.longitude, position.coords.latitude]); @@ -7,17 +11,16 @@ iD.ui.geolocate = function(map) { function error() { } return function(selection) { - selection - .attr('class', 'geolocate-control map-control') - .append('button') - .attr('tabindex', -1) - .attr('title', 'Show My Location') - .on('click', function() { - navigator.geolocation.getCurrentPosition( - success, error); - }) - .append('span') - .attr('class','icon geolocate'); - }; + if (!navigator.geolocation) return; + var button = selection.append('button') + .attr('tabindex', -1) + .attr('title', t('geolocate.title')) + .on('click', click) + .call(bootstrap.tooltip() + .placement('right')); + + button.append('span') + .attr('class', 'icon geolocate'); + }; }; diff --git a/js/id/ui/inspector.js b/js/id/ui/inspector.js index 836f73cff..173594101 100644 --- a/js/id/ui/inspector.js +++ b/js/id/ui/inspector.js @@ -1,4 +1,4 @@ -iD.ui.inspector = function() { +iD.ui.Inspector = function() { var event = d3.dispatch('changeTags', 'close'), taginfo = iD.taginfo(), initial = false, @@ -43,7 +43,7 @@ iD.ui.inspector = function() { .attr('class', 'inspector-buttons pad1 fillD') .call(drawButtons); - inspector.call(iD.ui.toggle(true)); + inspector.call(iD.ui.Toggle(true)); } function drawHead(selection) { diff --git a/js/id/ui/lasso.js b/js/id/ui/lasso.js index 511df2a7e..4644364c3 100644 --- a/js/id/ui/lasso.js +++ b/js/id/ui/lasso.js @@ -1,4 +1,4 @@ -iD.ui.lasso = function() { +iD.ui.Lasso = function() { var center, box, group, @@ -13,7 +13,7 @@ iD.ui.lasso = function() { box = group.append('rect') .attr('class', 'lasso-box'); - group.call(iD.ui.toggle(true)); + group.call(iD.ui.Toggle(true)); } @@ -50,7 +50,7 @@ iD.ui.lasso = function() { lasso.close = function(selection) { if (group) { - group.call(iD.ui.toggle(false, function() { + group.call(iD.ui.Toggle(false, function() { d3.select(this).remove(); })); } diff --git a/js/id/ui/layerswitcher.js b/js/id/ui/layerswitcher.js index 312605f54..f4d57a422 100644 --- a/js/id/ui/layerswitcher.js +++ b/js/id/ui/layerswitcher.js @@ -1,4 +1,4 @@ -iD.ui.layerswitcher = function(context) { +iD.ui.LayerSwitcher = function(context) { var event = d3.dispatch('cancel', 'save'), opacities = [1, 0.5, 0]; @@ -23,17 +23,20 @@ iD.ui.layerswitcher = function(context) { .attr('tabindex', -1) .attr('class', 'fillD') .attr('title', t('layerswitcher.description')) - .html("") - .on('click.layerswitcher-toggle', toggle); + .on('click.layerswitcher-toggle', toggle) + .call(bootstrap.tooltip() + .placement('right')); + + button.append('span') + .attr('class', 'layers icon'); - function show() { setVisible(true); } function hide() { setVisible(false); } function toggle() { setVisible(content.classed('hide')); } function setVisible(show) { if (show !== shown) { button.classed('active', show); - content.call(iD.ui.toggle(show)); + content.call(iD.ui.Toggle(show)); shown = show; } } diff --git a/js/id/ui/modes.js b/js/id/ui/modes.js index b382ab295..d3db0074a 100644 --- a/js/id/ui/modes.js +++ b/js/id/ui/modes.js @@ -11,7 +11,7 @@ iD.ui.Modes = function(context) { buttons.enter().append('button') .attr('tabindex', -1) - .attr('class', function(mode) { return mode.title + ' add-button col3'; }) + .attr('class', function(mode) { return mode.id + ' add-button col3'; }) .on('click.mode-buttons', function(mode) { context.enter(mode); }) .call(bootstrap.tooltip() .placement('bottom') diff --git a/js/id/ui/radial_menu.js b/js/id/ui/radial_menu.js index 106a48196..e718cfe51 100644 --- a/js/id/ui/radial_menu.js +++ b/js/id/ui/radial_menu.js @@ -1,7 +1,8 @@ iD.ui.RadialMenu = function(operations) { - var menu; + var menu, + center = [0, 0]; - var radialMenu = function(selection, center) { + var radialMenu = function(selection) { if (!operations.length) return; @@ -94,5 +95,11 @@ iD.ui.RadialMenu = function(operations) { } }; + radialMenu.center = function(_) { + if (!arguments.length) return center; + center = _; + return radialMenu; + }; + return radialMenu; }; diff --git a/js/id/ui/save.js b/js/id/ui/save.js index b8f9d619a..b4eed1dd0 100644 --- a/js/id/ui/save.js +++ b/js/id/ui/save.js @@ -17,7 +17,7 @@ iD.ui.Save = function(context) { modal.select('.content') .classed('commit-modal', true) .datum(changes) - .call(iD.ui.commit(context) + .call(iD.ui.Commit(context) .on('cancel', function() { modal.remove(); }) @@ -60,7 +60,7 @@ iD.ui.Save = function(context) { id: changeset_id, comment: e.comment }) - .call(iD.ui.success(connection) + .call(iD.ui.Success(connection) .on('cancel', function() { modal.remove(); })); diff --git a/js/id/ui/success.js b/js/id/ui/success.js index fffa7b6ab..17a577fb3 100644 --- a/js/id/ui/success.js +++ b/js/id/ui/success.js @@ -1,4 +1,4 @@ -iD.ui.success = function(connection) { +iD.ui.Success = function(connection) { var event = d3.dispatch('cancel', 'save'); function success(selection) { diff --git a/js/id/ui/tag_reference.js b/js/id/ui/tag_reference.js index cdb22b505..6b7b9fb9f 100644 --- a/js/id/ui/tag_reference.js +++ b/js/id/ui/tag_reference.js @@ -19,7 +19,7 @@ iD.ui.tagReference = function(selection) { header.append('span') .text(g('title')); - referenceBody = selection.append('div') + var referenceBody = selection.append('div') .attr('class','modal-section fillL2'); referenceBody diff --git a/js/id/ui/toggle.js b/js/id/ui/toggle.js index 3a7500023..c3c299905 100644 --- a/js/id/ui/toggle.js +++ b/js/id/ui/toggle.js @@ -2,7 +2,7 @@ // hide class, which sets display=none, and a d3 transition for opacity. // this will cause blinking when called repeatedly, so check that the // value actually changes between calls. -iD.ui.toggle = function(show, callback) { +iD.ui.Toggle = function(show, callback) { return function(selection) { selection.style('opacity', show ? 0 : 1) .classed('hide', false) diff --git a/js/id/ui/userpanel.js b/js/id/ui/userpanel.js index fda2fc463..3dab2a5bd 100644 --- a/js/id/ui/userpanel.js +++ b/js/id/ui/userpanel.js @@ -1,4 +1,4 @@ -iD.ui.userpanel = function(connection) { +iD.ui.UserPanel = function(connection) { var event = d3.dispatch('logout', 'login'); function user(selection) { diff --git a/js/id/ui/zoom.js b/js/id/ui/zoom.js new file mode 100644 index 000000000..823bc120f --- /dev/null +++ b/js/id/ui/zoom.js @@ -0,0 +1,40 @@ +iD.ui.Zoom = function(context) { + var zooms = [{ + id: 'zoom-in', + title: t('zoom.in'), + action: context.zoomIn, + key: '+' + }, { + id: 'zoom-out', + title: t('zoom.out'), + action: context.zoomOut, + key: '-' + }]; + + return function(selection) { + var button = selection.selectAll('button') + .data(zooms) + .enter().append('button') + .attr('tabindex', -1) + .attr('class', function(d) { return d.id; }) + .on('click.editor', function(d) { d.action(); }) + .call(bootstrap.tooltip() + .placement('right') + .html(true) + .title(function(d) { + return iD.ui.tooltipHtml(d.title, d.key); + })); + + button.append('span') + .attr('class', function(d) { return d.id + ' icon'; }); + + var keybinding = d3.keybinding('zoom') + .on('+', function() { context.zoomIn(); }) + .on('-', function() { context.zoomOut(); }) + .on('⇧=', function() { context.zoomIn(); }) + .on('dash', function() { context.zoomOut(); }); + + d3.select(document) + .call(keybinding); + } +}; diff --git a/locale/locale.js b/js/lib/locale.js similarity index 100% rename from locale/locale.js rename to js/lib/locale.js diff --git a/locale/README.md b/locale/README.md index b1610b311..0feb1f631 100644 --- a/locale/README.md +++ b/locale/README.md @@ -22,6 +22,10 @@ Let's look at an example line from `en.js`: no_results: "Couldn't locate a place named '{name}'" ``` +`no_results` is the translation _key_, and should not be translated. +The text to the right of the colon, `"Couldn't locate a place named '{name}'"`, +is the string to be translated. + The word in brackets, `{name}`, should **not** be translated into a new language: it's replaced with a place name when iD presents the text. So a French translation would look like @@ -30,6 +34,15 @@ a French translation would look like no_results: "Impossible de localiser l'endroit nommé '{name}'" ``` +For technical reasons, a few translation keys are quoted. For example: + +``` +'delete': "Delete" +``` + +Only translate the value to the right of the colon, not the quoted key on +the left. + ## License Contributions to translations are under the same liberal diff --git a/locale/da.js b/locale/da.js index 217f597f6..29e23c6f2 100644 --- a/locale/da.js +++ b/locale/da.js @@ -34,27 +34,27 @@ locale.da = { operations: { add: { annotation: { - point: "Added a point.", - vertex: "Added a node to a way." + point: "Tilføjede et punkt.", + vertex: "Tilføjede en node til en vej." } }, start: { annotation: { - line: "Started a line.", - area: "Started an area." + line: "Startede en linje.", + area: "Startede et område." } }, 'continue': { annotation: { - line: "Continued a line.", - area: "Continued an area." + line: "Forsatte en linje.", + area: "Forsatte et område." } }, cancel_draw: { - annotation: "Cancelled drawing." + annotation: "Annulleret indtegning." }, change_tags: { - annotation: "Changed tags." + annotation: "Ændret tags." }, circularize: { title: "Circularize", @@ -75,16 +75,16 @@ locale.da = { } }, 'delete': { - title: "Delete", - description: "Remove this from the map.", + title: "Slet", + description: "Fjern dette fra kortet.", key: "⌫", annotation: { - point: "Deleted a point.", - vertex: "Deleted a node from a way.", - line: "Deleted a line.", - area: "Deleted an area.", - relation: "Deleted a relation.", - multiple: "Deleted {n} objects." + point: "Slettede et punkt.", + vertex: "Slettede en node fra en vej.", + line: "Slettede en linje.", + area: "Slettede et område.", + relation: "Sletede en relation.", + multiple: "Slettede {n} objekter." } }, connect: { @@ -108,14 +108,14 @@ locale.da = { annotation: "Merged {n} lines." }, move: { - title: "Move", - description: "Move this to a different location.", + title: "Flyt", + description: "Flyt dette til anden lokation.", key: "M", annotation: { - point: "Moved a point.", - vertex: "Moved a node in a way.", - line: "Moved a line.", - area: "Moved an area." + point: "Flyttede et punktMoved.", + vertex: "Flyttede en node i en vej.", + line: "Flyttede en linje.", + area: "Flyttede et område." } }, reverse: { @@ -125,10 +125,10 @@ locale.da = { annotation: "Reversed a line." }, split: { - title: "Split", - description: "Split this into two ways at this point.", + title: "Del op", + description: "Del op i to vej ved dette punkt.", key: "X", - annotation: "Split a way." + annotation: "Del op en vej." } }, @@ -140,17 +140,14 @@ locale.da = { deprecated_tags: "Deprecated tags: {tags}" }, - save: "Save", - unsaved_changes: "You have unsaved changes", - save_help: "Save changes to OpenStreetMap, making them visible to other users", - no_changes: "You don't have any changes to save.", - save_error: "An error occurred while trying to save", - uploading_changes: "Uploading changes to OpenStreetMap.", - just_edited: "You Just Edited OpenStreetMap!", - okay: "Okay", - - "zoom-in": "Zoom ind", - "zoom-out": "Zoom ud", + save: "Gem", + unsaved_changes: "Du har ændringer der ikke er gemt endnu", + save_help: "Gem ændringer til OpenStreetMap gør dem synlige for andre brugere", + no_changes: "Du har ingen ændringer til at gemme endnu.", + save_error: "Der skete en fejl da du prøvede at gemme", + uploading_changes: "Gemmer nu ændringer til OpenStreetMap.", + just_edited: "Du har lige rettede i OpenStreetMap!", + okay: "Ok", nothing_to_undo: "Nothing to undo.", nothing_to_redo: "Nothing to redo.", @@ -158,8 +155,8 @@ locale.da = { browser_notice: "This editor is supported in Firefox, Chrome, Safari, Opera, and Internet Explorer 9 and above. Please upgrade your browser or use Potlatch 2 to edit the map.", inspector: { - no_documentation_combination: "This is no documentation available for this tag combination", - no_documentation_key: "This is no documentation available for this key", + no_documentation_combination: "Der er ingen dokumentation for denne tag kombination", + no_documentation_key: "Der er ingen dokumenation tilgængelig for denne nøgle", new_tag: "Nyt Tag" }, @@ -197,5 +194,10 @@ locale.da = { source_switch: { live: "live", dev: "dev" + }, + + zoom: { + in: "Zoom ind", + out: "Zoom ud" } }; diff --git a/locale/de.js b/locale/de.js index 543eaab2d..f1f3ef850 100644 --- a/locale/de.js +++ b/locale/de.js @@ -145,9 +145,6 @@ locale.de = { just_edited: "Sie haben gerade OpenStreetMap editiert!", okay: "OK", - "zoom-in": "Hineinzoomen", - "zoom-out": "Herauszoomen", - nothing_to_undo: "Nichts zum Rückgängigmachen.", nothing_to_redo: "Nichts zum Wiederherstellen.", @@ -193,5 +190,10 @@ locale.de = { source_switch: { live: "live", dev: "dev" + }, + + zoom: { + in: "Hineinzoomen", + out: "Herauszoomen" } }; diff --git a/locale/en.js b/locale/en.js index 007c8e5be..7581b5fcb 100644 --- a/locale/en.js +++ b/locale/en.js @@ -145,9 +145,6 @@ locale.en = { just_edited: "You Just Edited OpenStreetMap!", okay: "Okay", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - nothing_to_undo: "Nothing to undo.", nothing_to_redo: "Nothing to redo.", @@ -171,6 +168,10 @@ locale.en = { no_results: "Couldn't locate a place named '{name}'" }, + geolocate: { + title: "Show My Location" + }, + description: "Description", logout: "logout", @@ -193,5 +194,10 @@ locale.en = { source_switch: { live: "live", dev: "dev" + }, + + zoom: { + in: "Zoom In", + out: "Zoom Out" } }; diff --git a/locale/es.js b/locale/es.js index 4bb5f3959..0468405b5 100644 --- a/locale/es.js +++ b/locale/es.js @@ -145,9 +145,6 @@ locale.es = { just_edited: "Acabas de editar OpenStreetMap!", //"You Just Edited OpenStreetMap!", okay: "OK", //"Okay", - "zoom-in": "Aumentar", // "Zoom In", - "zoom-out": "Alejar", //"Zoom Out", - nothing_to_undo: "Nada para deshacer", //"Nothing to undo.", nothing_to_redo: "Nada para rehacer", //"Nothing to redo.", @@ -193,5 +190,10 @@ locale.es = { source_switch: { live: "en vivo", //"live", dev: "dev" + }, + + zoom: { + in: "Aumentar", // "Zoom In", + out: "Alejar" //"Zoom Out", } }; diff --git a/locale/fr.js b/locale/fr.js index adf4a2d26..4530924a0 100644 --- a/locale/fr.js +++ b/locale/fr.js @@ -145,9 +145,6 @@ locale.fr = { just_edited: "Vous venez de participer à OpenStreetMap!", okay: "Okay", - "zoom-in": "Zoomer", - "zoom-out": "Dézoomer", - nothing_to_undo: "Rien à annuler.", nothing_to_redo: "Rien à refaire.", @@ -193,5 +190,10 @@ locale.fr = { source_switch: { live: "live", dev: "dev" + }, + + zoom: { + in: "Zoomer", + out: "Dézoomer" } }; diff --git a/locale/ja.js b/locale/ja.js index b002f54bf..ada737bd1 100644 --- a/locale/ja.js +++ b/locale/ja.js @@ -145,9 +145,6 @@ locale.ja = { just_edited: "OpenStreetMap編集完了!", okay: "OK", - "zoom-in": "ズームイン", - "zoom-out": "ズームアウト", - nothing_to_undo: "やり直す変更点がありません", nothing_to_redo: "やり直した変更点がありません", @@ -193,5 +190,10 @@ locale.ja = { source_switch: { live: "本番サーバ", dev: "開発サーバ" + }, + + zoom: { + in: "ズームイン", + out: "ズームアウト" } }; diff --git a/locale/lv.js b/locale/lv.js index 1d55450f8..fd8be7cfe 100644 --- a/locale/lv.js +++ b/locale/lv.js @@ -145,9 +145,6 @@ locale.lv = { just_edited: "Jūs nupat rediģējāt OpenStreetMap", okay: "Labi", - "zoom-in": "Pietuvināt", - "zoom-out": "Attālināt", - nothing_to_undo: "Nav nekā, ko atcelt", nothing_to_redo: "Nav nekā, ko atsaukt", @@ -193,5 +190,10 @@ locale.lv = { source_switch: { live: "live", dev: "dev" + }, + + zoom: { + in: "Pietuvināt", + out: "Attālināt" } }; diff --git a/locale/tr.js b/locale/tr.js index d14f08ecb..a9b3e4b47 100644 --- a/locale/tr.js +++ b/locale/tr.js @@ -145,9 +145,6 @@ locale.tr = { just_edited: "Şu an OpenStreetMap'de bir değişiklik yaptınız!", okay: "Tamam", - "zoom-in": "Yaklaş", - "zoom-out": "Uzaklaş", - nothing_to_undo: "Geri alınacak birşey yok.", nothing_to_redo: "Tekrar yapılacak birşey yok.", @@ -193,5 +190,10 @@ locale.tr = { source_switch: { live: "canlı", dev: "geliştirme" + }, + + zoom: { + in: "Yaklaş", + out: "Uzaklaş" } }; diff --git a/test/spec/behavior/select.js b/test/spec/behavior/select.js index 5e9bf9ea3..ecbb7e7b4 100644 --- a/test/spec/behavior/select.js +++ b/test/spec/behavior/select.js @@ -20,6 +20,8 @@ describe("iD.behavior.Select", function() { .enter().append('circle') .attr('class', function(d) { return d.id; }); + context.enter(iD.modes.Browse(context)); + behavior = iD.behavior.Select(context); context.install(behavior); }); @@ -30,32 +32,33 @@ describe("iD.behavior.Select", function() { container.remove(); }); - specify("click on entity selects the entity", function(done) { - happen.mousedown(context.surface().select('.' + a.id).node()); - window.setTimeout(function() { - expect(context.selection()).to.eql([a.id]); - done(); - }, 600); + specify("click on entity selects the entity", function() { + happen.click(context.surface().select('.' + a.id).node()); + expect(context.selection()).to.eql([a.id]); }); - specify("click on empty space clears the selection", function(done) { + specify("click on empty space clears the selection", function() { context.enter(iD.modes.Select(context, [a.id])); happen.click(context.surface().node()); - happen.mousedown(context.surface().node()); - happen.mouseup(context.surface().node()); - window.setTimeout(function() { - expect(context.selection()).to.eql([]); - done(); - }, 600); + expect(context.mode().id).to.eql('browse'); }); - specify("shift-click on entity adds the entity to the selection", function(done) { + specify("shift-click on unselected entity adds it to the selection", function() { context.enter(iD.modes.Select(context, [a.id])); - happen.mousedown(context.surface().select('.' + b.id).node(), {shiftKey: true}); - window.setTimeout(function() { - expect(context.selection()).to.eql([a.id, b.id]); - done(); - }, 600); + happen.click(context.surface().select('.' + b.id).node(), {shiftKey: true}); + expect(context.selection()).to.eql([a.id, b.id]); + }); + + specify("shift-click on selected entity removes it from the selection", function() { + context.enter(iD.modes.Select(context, [a.id, b.id])); + happen.click(context.surface().select('.' + b.id).node(), {shiftKey: true}); + expect(context.selection()).to.eql([a.id]); + }); + + specify("shift-click on last selected entity clears the selection", function() { + context.enter(iD.modes.Select(context, [a.id])); + happen.click(context.surface().select('.' + a.id).node(), {shiftKey: true}); + expect(context.mode().id).to.eql('browse'); }); specify("shift-click on empty space leaves the selection unchanged", function() { diff --git a/test/spec/ui/geocoder.js b/test/spec/ui/geocoder.js index 54a7e571c..91e107ee2 100644 --- a/test/spec/ui/geocoder.js +++ b/test/spec/ui/geocoder.js @@ -1,6 +1,6 @@ -describe("iD.ui.geocoder", function () { +describe("iD.ui.Geocoder", function () { it('can be instantiated', function () { - var geocoder = iD.ui.geocoder(); + var geocoder = iD.ui.Geocoder(); expect(geocoder).to.be.ok; }); }); diff --git a/test/spec/ui/inspector.js b/test/spec/ui/inspector.js index e92604a7a..17160ddb4 100644 --- a/test/spec/ui/inspector.js +++ b/test/spec/ui/inspector.js @@ -1,10 +1,10 @@ -describe("iD.ui.inspector", function () { +describe("iD.ui.Inspector", function () { var inspector, element, tags = {highway: 'residential'}, entity, graph, context; function render() { - inspector = iD.ui.inspector().context(context); + inspector = iD.ui.Inspector().context(context); element = d3.select('body') .append('div') .attr('id', 'inspector-wrap')