From 36f4ef25332a986b264541143d738841ce8883c2 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Wed, 5 Dec 2012 12:22:57 -0500 Subject: [PATCH] Extract iD.modes.Select (fixes #188) --- js/id/actions/modes.js | 138 ++++++++++++++++++++++++++++++--- js/id/controller/controller.js | 4 +- js/id/id.js | 2 + js/id/renderer/map.js | 96 ++--------------------- 4 files changed, 134 insertions(+), 106 deletions(-) diff --git a/js/id/actions/modes.js b/js/id/actions/modes.js index 5af9b59e8..37886649f 100644 --- a/js/id/actions/modes.js +++ b/js/id/actions/modes.js @@ -1,5 +1,127 @@ iD.modes = {}; +iD.modes.Browse = function() { + var mode = {}; + + mode.enter = function() { + mode.map.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.exit = function() { + mode.map.surface.on('click.browse', null); + }; + + return mode; +}; + +iD.modes.Select = function (entity) { + var mode = {}, + inspector = iD.Inspector(), + dragging, target; + + var dragWay = d3.behavior.drag() + .origin(function(entity) { + var p = mode.map.projection(entity.nodes[0].loc); + return { x: p[0], y: p[1] }; + }) + .on('drag', function(entity) { + if (!mode.map.dragEnable()) return; + + d3.event.sourceEvent.stopPropagation(); + + if (!dragging) { + dragging = iD.util.trueObj([entity.id].concat( + _.pluck(mode.history.graph().parents(entity.id), 'id'))); + mode.history.perform(iD.actions.noop()); + } + + entity.nodes.forEach(function(node) { + var start = mode.map.projection(node.loc); + var end = mode.map.projection.invert([start[0] + d3.event.dx, start[1] + d3.event.dy]); + node.loc = end; + mode.history.replace(iD.actions.move(node, end)); + }); + }) + .on('dragend', function () { + if (!mode.map.dragEnable() || !dragging) return; + dragging = undefined; + mode.map.redraw(); + }); + + function remove() { + // Remove this node from any ways that is a member of + mode.history.graph().parents(entity.id) + .filter(function(d) { return d.type === 'way'; }) + .forEach(function(parent) { + mode.history.perform(iD.actions.removeWayNode(parent, entity)); + }); + mode.history.perform(iD.actions.remove(entity)); + mode.controller.exit(); + } + + mode.enter = function () { + target = mode.map.surface.selectAll("*") + .filter(function (d) { return d === entity; }); + + d3.select('.inspector-wrap') + .style('display', 'block') + .datum(entity) + .call(inspector); + + inspector.on('changeTags', function(d, tags) { + mode.history.perform(iD.actions.changeTags(history.graph().entity(d.id), tags)); + }).on('changeWayDirection', function(d) { + mode.history.perform(iD.actions.changeWayDirection(d)); + }).on('remove', function() { + remove(); + }).on('close', function() { + mode.controller.exit(); + }); + + if (entity.type === 'way') { + target.call(dragWay); + } + + mode.map.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)); + } else { + mode.controller.enter(iD.modes.Browse()); + } + }); + + mode.map.keybinding().on('⌫.browse', function(e) { + remove(); + e.preventDefault(); + }); + + mode.map.selection(entity.id); + }; + + mode.exit = function () { + d3.select('.inspector-wrap') + .style('display', 'none'); + + if (entity.type === 'way') { + target.on('mousedown.drag', null) + .on('touchstart.drag', null); + } + + mode.map.surface.on("click.browse", null); + mode.map.keybinding().on('⌫.browse', null); + + mode.map.selection(null); + }; + + return mode; +}; + iD.modes.AddPlace = { id: 'add-place', title: '+ Place', @@ -10,9 +132,7 @@ iD.modes.AddPlace = { function click() { var node = iD.Node({loc: this.map.mouseCoordinates(), _poi: true}); this.history.perform(iD.actions.addNode(node)); - this.map.selectEntity(node); - this.controller.exit(); - this.exit(); + this.controller.enter(iD.modes.Select(node)); } surface.on('click.addplace', click.bind(this)); @@ -136,10 +256,9 @@ iD.modes.DrawRoad = function(way_id, direction) { delete way.tags.elastic; this.history.perform(iD.actions.changeTags(way, way.tags)); - this.map.selectEntity(way); // End by clicking on own tail - return this.controller.exit(); + return this.controller.enter(iD.modes.Select(way)); } else { // connect a way to an existing way this.history.replace(iD.actions.addWayNode(way, datum, index)); @@ -207,7 +326,7 @@ iD.modes.AddArea = { this.history.perform(iD.actions.startWay(way)); this.history.perform(iD.actions.addWayNode(way, node)); - this.map.selectEntity(way); + this.controller.enter(iD.modes.DrawArea(way.id)); } @@ -257,7 +376,7 @@ iD.modes.DrawArea = function(way_id) { this.history.perform(iD.actions.changeTags(way, way.tags)); // End by clicking on own tail - return this.controller.exit(); + return this.controller.enter(iD.modes.Select(way)); } else { // connect a way to an existing way this.history.replace(iD.actions.addWayNode(way, datum)); @@ -288,8 +407,3 @@ iD.modes.DrawArea = function(way_id) { } }; }; - -iD.modes.Move = { - enter: function() { }, - exit: function() { } -}; diff --git a/js/id/controller/controller.js b/js/id/controller/controller.js index ac204b753..7e74c56d4 100644 --- a/js/id/controller/controller.js +++ b/js/id/controller/controller.js @@ -20,10 +20,8 @@ iD.Controller = function(map, history) { }; controller.exit = function() { - controller.enter(iD.modes.Move); + controller.enter(iD.modes.Browse()); }; - controller.exit(); - return d3.rebind(controller, event, 'on'); }; diff --git a/js/id/id.js b/js/id/id.js index 2e6840440..d7211d593 100644 --- a/js/id/id.js +++ b/js/id/id.js @@ -165,6 +165,8 @@ window.iD = function(container) { d3.select('.user').call(iD.userpanel(connection) .on('logout', connection.logout) .on('login', connection.authenticate)); + + controller.enter(iD.modes.Browse()); } editor.connection = function(_) { diff --git a/js/id/renderer/map.js b/js/id/renderer/map.js index 6ca9db3bd..802d90d87 100644 --- a/js/id/renderer/map.js +++ b/js/id/renderer/map.js @@ -2,7 +2,6 @@ iD.Map = function() { var connection, history, dimensions = [], dispatch = d3.dispatch('move'), - inspector = iD.Inspector(), selection = null, translateStart, keybinding, @@ -45,34 +44,6 @@ iD.Map = function() { dragging = undefined; redraw(); }), - waydragbehavior = d3.behavior.drag() - .origin(function(entity) { - var p = projection(entity.nodes[0].loc); - return { x: p[0], y: p[1] }; - }) - .on('drag', function(entity) { - console.log(dragEnabled); - if (!dragEnabled) return; - d3.event.sourceEvent.stopPropagation(); - - if (!dragging) { - dragging = iD.util.trueObj([entity.id].concat( - _.pluck(history.graph().parents(entity.id), 'id'))); - history.perform(iD.actions.noop()); - } - - entity.nodes.forEach(function(node) { - var start = projection(node.loc); - var end = projection.invert([start[0] + d3.event.dx, start[1] + d3.event.dy]); - node.loc = end; - history.replace(iD.actions.move(node, end)); - }); - }) - .on('dragend', function () { - if (!dragEnabled || !dragging) return; - dragging = undefined; - redraw(); - }), background = iD.Background() .projection(projection) .scaleExtent([0, 20]), @@ -98,11 +69,9 @@ iD.Map = function() { .attr({ x: 0, y: 0 }); tilegroup = surface.append('g') - .attr('clip-path', 'url(#clip)') - .on('click', deselectClick); + .attr('clip-path', 'url(#clip)'); r = surface.append('g') - .on('click', selectClick) .on('mouseover', nameHoverIn) .on('mouseout', nameHoverOut) .attr('clip-path', 'url(#clip)'); @@ -115,19 +84,6 @@ iD.Map = function() { alength = arrow.node().getComputedTextLength(); arrow.remove(); - inspector.on('changeTags', function(d, tags) { - var entity = history.graph().entity(d.id); - history.perform(iD.actions.changeTags(entity, tags)); - }).on('changeWayDirection', function(d) { - history.perform(iD.actions.changeWayDirection(d)); - }).on('remove', function(d) { - removeEntity(d); - hideInspector(); - }).on('close', function() { - deselectClick(); - hideInspector(); - }); - map.size(this.size()); map.surface = surface; } @@ -140,10 +96,6 @@ iD.Map = function() { return 'M' + _.pluck(d.nodes, 'loc').map(projection).map(iD.util.geo.roundCoords).join('L'); } - function hideInspector() { - d3.select('.inspector-wrap').style('display', 'none'); - } - function drawVector(only) { if (surface.style(transformProp) != 'none') return; var all = [], ways = [], areas = [], points = [], waynodes = [], @@ -335,41 +287,6 @@ iD.Map = function() { function nameHoverOut() { d3.select('.messages').text(''); } - function selectClick() { - var entity = d3.select(d3.event.target).data(); - if (entity) entity = entity[0]; - if (!entity || selection === entity.id || (entity.tags && entity.tags.elastic)) return; - if (entity.type === 'way') d3.select(d3.event.target).call(waydragbehavior); - map.selectEntity(entity); - keybinding.on('⌫.deletefeature', function(e) { - removeEntity(entity); - e.preventDefault(); - }); - } - - function deselectClick() { - if (selection && selection.type === 'way') { - d3.select(d3.event.target) - .on('mousedown.drag', null) - .on('touchstart.drag', null); - } - selection = null; - redraw(); - hideInspector(); - keybinding.on('⌫.deletefeature', null); - } - - function removeEntity(entity) { - // Remove this node from any ways that is a member of - history.graph().parents(entity.id) - .filter(function(d) { return d.type === 'way'; }) - .forEach(function(parent) { - history.perform(iD.actions.removeWayNode(parent, entity)); - }); - deselectClick(); - history.perform(iD.actions.remove(entity)); - } - function zoomPan() { if (d3.event && d3.event.sourceEvent.type === 'dblclick') { if (!dblclickEnabled) return; @@ -515,13 +432,10 @@ iD.Map = function() { return map; }; - map.selectEntity = function(entity) { - selection = entity.id; - d3.select('.inspector-wrap') - .style('display', 'block') - .datum(history.graph().fetch(entity.id)) - .call(inspector); - redraw(); + map.selection = function (_) { + if (!arguments.length) return selection; + selection = _; + return redraw(); }; map.background = background;