mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-14 01:33:03 +00:00
resolved conflict.
This commit is contained in:
@@ -53,7 +53,8 @@
|
||||
<script src='js/id/actions/change_entity_tags.js'></script>
|
||||
<script src="js/id/actions/delete_node.js"></script>
|
||||
<script src="js/id/actions/delete_way.js"></script>
|
||||
<script src='js/id/actions/move.js'></script>
|
||||
<script src='js/id/actions/move_node.js'></script>
|
||||
<script src='js/id/actions/move_way.js'></script>
|
||||
<script src='js/id/actions/noop.js'></script>
|
||||
<script src='js/id/actions/remove_relation_member.js'></script>
|
||||
<script src='js/id/actions/remove_way_node.js'></script>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/MoveCommand.java
|
||||
// https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as
|
||||
iD.actions.Move = function(entityId, loc) {
|
||||
iD.actions.MoveNode = function(nodeId, loc) {
|
||||
return function(graph) {
|
||||
var entity = graph.entity(entityId);
|
||||
return graph.replace(entity.update({loc: loc}));
|
||||
var node = graph.entity(nodeId);
|
||||
return graph.replace(node.update({loc: loc}));
|
||||
};
|
||||
};
|
||||
14
js/id/actions/move_way.js
Normal file
14
js/id/actions/move_way.js
Normal file
@@ -0,0 +1,14 @@
|
||||
iD.actions.MoveWay = function(wayId, dxdy, projection) {
|
||||
return function(graph) {
|
||||
var way = graph.entity(wayId);
|
||||
|
||||
_.uniq(way.nodes).forEach(function(id) {
|
||||
var node = graph.entity(id),
|
||||
start = projection(node.loc),
|
||||
end = projection.invert([start[0] + dxdy[0], start[1] + dxdy[1]]);
|
||||
graph = iD.actions.MoveNode(id, end)(graph);
|
||||
});
|
||||
|
||||
return graph;
|
||||
};
|
||||
};
|
||||
35
js/id/id.js
35
js/id/id.js
@@ -36,14 +36,36 @@ window.iD = function(container) {
|
||||
.call(bootstrap.tooltip().placement('bottom'))
|
||||
.on('click', function (mode) { controller.enter(mode); });
|
||||
|
||||
map.on('move.disable-buttons', function() {
|
||||
function disableTooHigh() {
|
||||
if (map.zoom() < 16) {
|
||||
buttons.attr('disabled', 'disabled');
|
||||
controller.enter(iD.modes.Browse());
|
||||
} else {
|
||||
buttons.attr('disabled', null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var showUsers = _.debounce(function() {
|
||||
var users = {},
|
||||
entities = map.history().graph().entities;
|
||||
for (var i in entities) {
|
||||
users[entities[i].user] = true;
|
||||
if (Object.keys(users).length > 10) break;
|
||||
}
|
||||
var u = Object.keys(users);
|
||||
var l = d3.select('#user-list')
|
||||
.selectAll('a.user-link').data(u);
|
||||
l.enter().append('a')
|
||||
.attr('class', 'user-link')
|
||||
.attr('href', function(d) {
|
||||
return 'http://api06.dev.openstreetmap.org/user/' + d;
|
||||
})
|
||||
.text(String);
|
||||
l.exit().remove();
|
||||
}, 1000);
|
||||
|
||||
map.on('move.disable-buttons', disableTooHigh)
|
||||
.on('move.show-users', showUsers);
|
||||
|
||||
buttons.append('span')
|
||||
.attr('class', function(d) {
|
||||
@@ -143,12 +165,15 @@ window.iD = function(container) {
|
||||
.attr('class', 'inspector-wrap fillL')
|
||||
.style('display', 'none');
|
||||
|
||||
this.append('div')
|
||||
var about = this.append('div')
|
||||
.attr('id', 'about')
|
||||
.html("<a href='http://github.com/systemed/iD'>code</a> " +
|
||||
"<a href='http://github.com/systemed/iD/issues'>report a bug</a>" +
|
||||
" <a href='http://opengeodata.org/microsoft-imagery-details'><img src='img/bing.png' /></a>");
|
||||
|
||||
about.append('div')
|
||||
.attr('id', 'user-list');
|
||||
|
||||
history.on('change.buttons', function() {
|
||||
var undo = history.undoAnnotation(),
|
||||
redo = history.redoAnnotation();
|
||||
@@ -166,7 +191,7 @@ window.iD = function(container) {
|
||||
map.size(m.size());
|
||||
};
|
||||
|
||||
var keybinding = d3.keybinding()
|
||||
map.keybinding()
|
||||
.on('a', function(evt, mods) {
|
||||
controller.enter(iD.modes.AddArea());
|
||||
})
|
||||
@@ -180,8 +205,6 @@ window.iD = function(container) {
|
||||
if (mods === '⇧⌘') history.redo();
|
||||
if (mods === '⌘') history.undo();
|
||||
});
|
||||
d3.select(document).call(keybinding);
|
||||
map.keybinding(keybinding);
|
||||
|
||||
var hash = iD.Hash().map(map);
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ iD.modes.AddLine = function() {
|
||||
map.dblclickEnable(false)
|
||||
.hint('Click on the map to start drawing an road, path, or route.');
|
||||
|
||||
map.surface.on('click.addroad', function() {
|
||||
map.surface.on('click.addline', function() {
|
||||
var datum = d3.select(d3.event.target).datum() || {},
|
||||
way = iD.Way({ tags: { highway: 'residential' } }),
|
||||
direction = 'forward';
|
||||
@@ -62,7 +62,7 @@ iD.modes.AddLine = function() {
|
||||
controller.enter(iD.modes.DrawLine(way.id, direction));
|
||||
});
|
||||
|
||||
map.keybinding().on('⎋.addroad', function() {
|
||||
map.keybinding().on('⎋.addline', function() {
|
||||
controller.exit();
|
||||
});
|
||||
};
|
||||
@@ -70,8 +70,8 @@ iD.modes.AddLine = function() {
|
||||
mode.exit = function() {
|
||||
mode.map.dblclickEnable(true);
|
||||
mode.map.hint(false);
|
||||
mode.map.surface.on('click.addroad', null);
|
||||
mode.map.keybinding().on('⎋.addroad', null);
|
||||
mode.map.surface.on('click.addline', null);
|
||||
mode.map.keybinding().on('⎋.addline', null);
|
||||
};
|
||||
|
||||
return mode;
|
||||
|
||||
@@ -4,6 +4,7 @@ iD.modes._dragFeatures = function(mode) {
|
||||
var dragbehavior = d3.behavior.drag()
|
||||
.origin(function(entity) {
|
||||
var p = mode.map.projection(entity.loc);
|
||||
d3.event.sourceEvent.stopPropagation();
|
||||
return { x: p[0], y: p[1] };
|
||||
})
|
||||
.on('drag', function(entity) {
|
||||
@@ -20,11 +21,11 @@ iD.modes._dragFeatures = function(mode) {
|
||||
} else {
|
||||
dragging = entity;
|
||||
mode.history.perform(
|
||||
iD.actions.Move(dragging.id, loc));
|
||||
iD.actions.MoveNode(dragging.id, loc));
|
||||
}
|
||||
}
|
||||
|
||||
mode.history.replace(iD.actions.Move(dragging.id, loc));
|
||||
mode.history.replace(iD.actions.MoveNode(dragging.id, loc));
|
||||
})
|
||||
.on('dragend', function (entity) {
|
||||
if (!dragging) return;
|
||||
|
||||
@@ -24,7 +24,7 @@ iD.modes.DrawArea = function(wayId) {
|
||||
iD.actions.AddWayNode(way.id, node.id, -1));
|
||||
|
||||
function mousemove() {
|
||||
history.replace(iD.actions.Move(node.id, map.mouseCoordinates()));
|
||||
history.replace(iD.actions.MoveNode(node.id, map.mouseCoordinates()));
|
||||
}
|
||||
|
||||
function click() {
|
||||
@@ -95,24 +95,32 @@ iD.modes.DrawArea = function(wayId) {
|
||||
controller.enter(iD.modes.Browse());
|
||||
}
|
||||
|
||||
map.surface.on('mousemove.drawarea', mousemove);
|
||||
map.surface.on('click.drawarea', click);
|
||||
map.keybinding().on('⎋.drawarea', esc)
|
||||
map.surface
|
||||
.on('mousemove.drawarea', mousemove)
|
||||
.on('click.drawarea', click);
|
||||
|
||||
map.keybinding()
|
||||
.on('⎋.drawarea', esc)
|
||||
.on('⌫.drawarea', backspace)
|
||||
.on('delete.drawarea', del)
|
||||
.on('⌦.drawarea', del)
|
||||
.on('↩.drawarea', ret);
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
mode.map.hint(false);
|
||||
mode.map.fastEnable(true);
|
||||
mode.map
|
||||
.hint(false)
|
||||
.fastEnable(true);
|
||||
|
||||
mode.map.surface
|
||||
.on('mousemove.drawarea', null)
|
||||
.on('click.drawarea', null);
|
||||
mode.map.keybinding().on('⎋.drawarea', null)
|
||||
|
||||
mode.map.keybinding()
|
||||
.on('⎋.drawarea', null)
|
||||
.on('⌫.drawarea', null)
|
||||
.on('delete.drawarea', null)
|
||||
.on('⌦.drawarea', null)
|
||||
.on('↩.drawarea', null);
|
||||
|
||||
window.setTimeout(function() {
|
||||
mode.map.dblclickEnable(true);
|
||||
}, 1000);
|
||||
|
||||
@@ -24,11 +24,11 @@ iD.modes.DrawLine = function(wayId, direction) {
|
||||
iD.actions.AddNode(node),
|
||||
iD.actions.AddWayNode(wayId, node.id, index));
|
||||
|
||||
map.surface.on('mousemove.drawline', function() {
|
||||
history.replace(iD.actions.Move(node.id, map.mouseCoordinates()));
|
||||
});
|
||||
function mousemove() {
|
||||
history.replace(iD.actions.MoveNode(node.id, map.mouseCoordinates()));
|
||||
}
|
||||
|
||||
map.surface.on('click.drawline', function() {
|
||||
function click() {
|
||||
var datum = d3.select(d3.event.target).datum() || {};
|
||||
|
||||
if (datum.id === tailId) {
|
||||
@@ -72,7 +72,7 @@ iD.modes.DrawLine = function(wayId, direction) {
|
||||
|
||||
controller.enter(iD.modes.DrawLine(wayId, direction));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function esc() {
|
||||
history.replace(
|
||||
@@ -108,23 +108,32 @@ iD.modes.DrawLine = function(wayId, direction) {
|
||||
controller.enter(iD.modes.Browse());
|
||||
}
|
||||
|
||||
map.keybinding().on('⎋.drawline', esc)
|
||||
map.surface
|
||||
.on('mousemove.drawline', mousemove)
|
||||
.on('click.drawline', click);
|
||||
|
||||
map.keybinding()
|
||||
.on('⎋.drawline', esc)
|
||||
.on('⌫.drawline', backspace)
|
||||
.on('delete.drawline', del)
|
||||
.on('⌦.drawline', del)
|
||||
.on('↩.drawline', ret);
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
mode.map.hint(false);
|
||||
mode.map.fastEnable(true);
|
||||
mode.map
|
||||
.hint(false)
|
||||
.fastEnable(true);
|
||||
|
||||
mode.map.surface
|
||||
.on('mousemove.drawline', null)
|
||||
.on('click.drawline', null);
|
||||
mode.map.keybinding().on('⎋.drawline', null)
|
||||
|
||||
mode.map.keybinding()
|
||||
.on('⎋.drawline', null)
|
||||
.on('⌫.drawline', null)
|
||||
.on('delete.drawline', null)
|
||||
.on('⌦.drawline', null)
|
||||
.on('↩.drawline', null);
|
||||
|
||||
window.setTimeout(function() {
|
||||
mode.map.dblclickEnable(true);
|
||||
}, 1000);
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
iD.modes.Select = function (entity) {
|
||||
var mode = {
|
||||
button: ''
|
||||
},
|
||||
inspector = iD.Inspector(),
|
||||
id: 'select',
|
||||
button: 'browse',
|
||||
entity: entity
|
||||
};
|
||||
|
||||
var inspector = iD.Inspector(),
|
||||
dragging, target;
|
||||
|
||||
var dragWay = d3.behavior.drag()
|
||||
@@ -11,48 +14,45 @@ iD.modes.Select = function (entity) {
|
||||
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().parentWays(entity.id), 'id')));
|
||||
dragging = true;
|
||||
mode.history.perform(iD.actions.Noop());
|
||||
}
|
||||
|
||||
_.uniq(_.pluck(entity.nodes, 'id'))
|
||||
.forEach(function(id) {
|
||||
var node = mode.history.graph().entity(id),
|
||||
start = mode.map.projection(node.loc),
|
||||
end = mode.map.projection.invert([
|
||||
start[0] + d3.event.dx,
|
||||
start[1] + d3.event.dy]);
|
||||
mode.history.replace(iD.actions.Move(id, end));
|
||||
});
|
||||
mode.history.replace(iD.actions.MoveWay(entity.id, [d3.event.dx, d3.event.dy], mode.map.projection));
|
||||
})
|
||||
.on('dragend', function () {
|
||||
if (!mode.map.dragEnable() || !dragging) return;
|
||||
if (!dragging) return;
|
||||
dragging = undefined;
|
||||
mode.map.redraw();
|
||||
});
|
||||
|
||||
function remove() {
|
||||
switch (entity.type) {
|
||||
case 'way':
|
||||
mode.history.perform(iD.actions.DeleteWay(entity.id));
|
||||
break;
|
||||
case 'node':
|
||||
mode.history.perform(iD.actions.DeleteNode(entity.id));
|
||||
if (entity.type === 'way') {
|
||||
mode.history.perform(
|
||||
iD.actions.DeleteWay(entity.id),
|
||||
'deleted a way');
|
||||
} else if (entity.type === 'node') {
|
||||
var parents = mode.history.graph().parentWays(entity.id),
|
||||
operations = [iD.actions.DeleteNode(entity.id)];
|
||||
parents.forEach(function(parent) {
|
||||
if (_.uniq(parent.nodes).length === 1) operations.push(iD.actions.DeleteWay(parent.id));
|
||||
});
|
||||
mode.history.perform.apply(mode.history,
|
||||
operations.concat(['deleted a node']));
|
||||
}
|
||||
|
||||
mode.controller.exit();
|
||||
}
|
||||
|
||||
mode.enter = function () {
|
||||
target = mode.map.surface.selectAll("*")
|
||||
target = mode.map.surface.selectAll('*')
|
||||
.filter(function (d) { return d === entity; });
|
||||
|
||||
iD.modes._dragFeatures(mode);
|
||||
|
||||
d3.select('.inspector-wrap')
|
||||
.style('display', 'block')
|
||||
.style('opacity', 1)
|
||||
@@ -60,11 +60,23 @@ iD.modes.Select = function (entity) {
|
||||
.call(inspector);
|
||||
|
||||
inspector.on('changeTags', function(d, tags) {
|
||||
mode.history.perform(iD.actions.ChangeEntityTags(d.id, tags));
|
||||
mode.history.perform(
|
||||
iD.actions.ChangeEntityTags(d.id, tags),
|
||||
'changed tags');
|
||||
|
||||
}).on('changeWayDirection', function(d) {
|
||||
mode.history.perform(iD.actions.ReverseWay(d));
|
||||
mode.history.perform(
|
||||
iD.actions.ReverseWay(d.id),
|
||||
'reversed a way');
|
||||
|
||||
}).on('splitWay', function(d) {
|
||||
mode.history.perform(
|
||||
iD.actions.SplitWay(d.id),
|
||||
'split a way on a node');
|
||||
|
||||
}).on('remove', function() {
|
||||
remove();
|
||||
|
||||
}).on('close', function() {
|
||||
mode.controller.exit();
|
||||
});
|
||||
@@ -73,7 +85,7 @@ iD.modes.Select = function (entity) {
|
||||
target.call(dragWay);
|
||||
}
|
||||
|
||||
mode.map.surface.on("click.browse", 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));
|
||||
@@ -100,6 +112,7 @@ iD.modes.Select = function (entity) {
|
||||
}
|
||||
|
||||
mode.map.surface.on("click.browse", null);
|
||||
mode.map.surface.on('mousedown.latedrag', null);
|
||||
mode.map.keybinding().on('⌫.browse', null);
|
||||
|
||||
mode.map.selection(null);
|
||||
|
||||
@@ -4,7 +4,7 @@ iD.Map = function() {
|
||||
dispatch = d3.dispatch('move'),
|
||||
selection = null, hover = null,
|
||||
translateStart,
|
||||
keybinding,
|
||||
keybinding = d3.keybinding(),
|
||||
projection = d3.geo.mercator().scale(1024),
|
||||
zoom = d3.behavior.zoom()
|
||||
.translate(projection.translate())
|
||||
@@ -12,7 +12,6 @@ iD.Map = function() {
|
||||
.scaleExtent([1024, 256 * Math.pow(2, 24)])
|
||||
.on('zoom', zoomPan),
|
||||
dblclickEnabled = true,
|
||||
dragging = false,
|
||||
fastEnabled = true,
|
||||
notice,
|
||||
background = iD.Background()
|
||||
@@ -63,6 +62,8 @@ iD.Map = function() {
|
||||
|
||||
map.size(this.size());
|
||||
map.surface = surface;
|
||||
|
||||
d3.select(document).call(keybinding);
|
||||
}
|
||||
|
||||
function pxCenter() { return [dimensions[0] / 2, dimensions[1] / 2]; }
|
||||
|
||||
@@ -48,103 +48,109 @@ iD.Inspector = function() {
|
||||
var inspectorwrap = selection
|
||||
.append('ul').attr('class', 'inspector-inner tag-wrap fillL2');
|
||||
|
||||
inspectorwrap.append('h4').text('Edit tags')
|
||||
inspectorwrap.append('h4').text('Edit tags');
|
||||
|
||||
inspectorwrap
|
||||
.data(['tag', 'value', ''])
|
||||
.enter();
|
||||
|
||||
function removeTag(d) {
|
||||
var tags = pad(grabtags());
|
||||
delete tags[d.key];
|
||||
draw(tags);
|
||||
draw(grabtags().filter(function(t) { return t.key !== d.key; }));
|
||||
}
|
||||
|
||||
function draw(data) {
|
||||
var tr = inspectorwrap.selectAll('li')
|
||||
.data(d3.entries(data), function(d) { return [d.key, d.value]; });
|
||||
tr.exit().remove();
|
||||
var row = tr.enter().append('li').attr('class','tag-row');
|
||||
var inputs = row.append('div').attr('class','input-wrap').selectAll('input')
|
||||
.data(function(d) { return [d, d]; });
|
||||
inputs.enter().append('input')
|
||||
|
||||
var li = inspectorwrap.selectAll('li')
|
||||
.data(data, function(d) { return [d.key, d.value]; });
|
||||
|
||||
li.exit().remove();
|
||||
|
||||
var row = li.enter().append('li').attr('class','tag-row');
|
||||
var inputs = row.append('div').attr('class','input-wrap');
|
||||
|
||||
function setValue(d, i) { d.value = this.value; }
|
||||
|
||||
function emptyTag(d) { return d.key === ''; }
|
||||
|
||||
function pushMore(d, i) {
|
||||
if (d3.event.keyCode === 9) {
|
||||
var tags = grabtags();
|
||||
if (i == tags.length - 1 && !tags.filter(emptyTag).length) {
|
||||
draw(tags.concat([{ key: '', value: '' }]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function bindTypeahead(d, i) {
|
||||
var selection = d3.select(this);
|
||||
selection.call(d3.typeahead()
|
||||
.data(function(selection, callback) {
|
||||
taginfo.values(selection.datum().key, function(err, data) {
|
||||
callback(data.data);
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
inputs.append('input')
|
||||
.property('type', 'text')
|
||||
.attr('class', function(d, i) {
|
||||
return i ? 'value' : 'key';
|
||||
})
|
||||
.property('value', function(d, i) { return d[i ? 'value' : 'key']; })
|
||||
.on('keyup.update', function(d, i) {
|
||||
d[i ? 'value' : 'key'] = this.value;
|
||||
update();
|
||||
})
|
||||
.each(function(d, i) {
|
||||
if (!i) return;
|
||||
var selection = d3.select(this);
|
||||
selection.call(d3.typeahead()
|
||||
.data(function(selection, callback) {
|
||||
update();
|
||||
taginfo.values(selection.datum().key, function(err, data) {
|
||||
callback(data.data);
|
||||
});
|
||||
}));
|
||||
});
|
||||
row.append('button')
|
||||
.html("<span class='icon remove'></span>")
|
||||
.attr('class', 'key')
|
||||
.property('value', function(d, i) { return d.key; })
|
||||
.on('keyup.update', setValue);
|
||||
|
||||
inputs.append('input')
|
||||
.property('type', 'text')
|
||||
.attr('class', 'value')
|
||||
.property('value', function(d, i) { return d.value; })
|
||||
.on('keyup.update', setValue)
|
||||
.on('keydown.push-more', pushMore)
|
||||
.each(bindTypeahead);
|
||||
|
||||
removeBtn = row.append('button')
|
||||
.attr('class','remove minor')
|
||||
.on('click', removeTag);
|
||||
row.append('button').attr('class', 'tag-help minor').append('a')
|
||||
.html("<span class='icon inspect'></span>")
|
||||
|
||||
removeBtn.append('span').attr('class', 'icon remove')
|
||||
|
||||
helpBtn = row.append('button').attr('class', 'tag-help minor').append('a')
|
||||
.attr('target', '_blank')
|
||||
.attr('tabindex', -1)
|
||||
.attr('href', function(d) {
|
||||
return 'http://taginfo.openstreetmap.org/keys/' + d.key;
|
||||
});
|
||||
}
|
||||
|
||||
// Remove any blank key-values
|
||||
function clean(x) {
|
||||
for (var i in x) {
|
||||
// undefined is cast to a string as an object key
|
||||
if (!i || i === 'undefined') delete x[i];
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
// Add a blank row for new tags
|
||||
function pad(x) {
|
||||
if (!x['']) x[''] = '';
|
||||
return x;
|
||||
helpBtn.append('span').attr('class', 'icon inspect')
|
||||
}
|
||||
|
||||
function grabtags() {
|
||||
var grabbed = {};
|
||||
function grab(d) { if (d.key !== undefined) grabbed[d.key] = d.value; }
|
||||
inspectorwrap.selectAll('input').each(grab);
|
||||
var grabbed = [];
|
||||
function grab(d) { grabbed.push(d); }
|
||||
inspectorwrap.selectAll('li').each(grab);
|
||||
return grabbed;
|
||||
}
|
||||
|
||||
// fill values and add blank field if necessary
|
||||
function update() {
|
||||
draw(pad(grabtags()));
|
||||
function unentries(entries) {
|
||||
return d3.nest()
|
||||
.key(function(d) { return d.key; })
|
||||
.rollup(function(v) { return v[0].value; })
|
||||
.map(entries);
|
||||
}
|
||||
|
||||
var data = _.clone(entity.tags);
|
||||
draw(data);
|
||||
update();
|
||||
draw(d3.entries(_.clone(entity.tags)));
|
||||
|
||||
selection.select('input').node().focus();
|
||||
|
||||
selection.append('div')
|
||||
.attr('class', 'inspector-buttons').call(drawbuttons);
|
||||
|
||||
function apply(entity) {
|
||||
event.changeTags(entity, unentries(grabtags()));
|
||||
event.close(entity);
|
||||
}
|
||||
|
||||
function drawbuttons(selection) {
|
||||
selection.append('button')
|
||||
.attr('class', 'apply wide action')
|
||||
.html("<span class='icon icon-pre-text apply'></span><span class='label'>Apply</span>")
|
||||
.on('click', function(entity) {
|
||||
event.changeTags(entity, clean(grabtags()));
|
||||
event.close(entity);
|
||||
});
|
||||
.on('click', apply);
|
||||
selection.append('button')
|
||||
.attr('class', 'delete wide action fr')
|
||||
.html("<span class='icon icon-pre-text delete'></span><span class='label'>Delete</span>")
|
||||
|
||||
@@ -48,36 +48,36 @@ iD.layerswitcher = function(map) {
|
||||
|
||||
var opa = content
|
||||
.append('div')
|
||||
.attr('class', 'opacity-options-wrapper fillL2')
|
||||
.attr('class', 'opacity-options-wrapper fillL2');
|
||||
|
||||
opa.append('h4').text('Layers')
|
||||
opa.append('h4').text('Layers');
|
||||
|
||||
opa.append('ul')
|
||||
.attr('class', 'opacity-options')
|
||||
.selectAll('div.opacity')
|
||||
.data(opacities)
|
||||
.enter()
|
||||
.append('li')
|
||||
.attr('data-original-title', function(d) {
|
||||
return (d * 100) + "% opacity";
|
||||
})
|
||||
.on('click.set-opacity', function(d) {
|
||||
d3.select('#tile-g')
|
||||
.transition()
|
||||
.style('opacity', d)
|
||||
.attr('data-opacity', d);
|
||||
d3.selectAll('.opacity-options li')
|
||||
.classed('selected', false);
|
||||
d3.select(this)
|
||||
.classed('selected', true);
|
||||
})
|
||||
.html("<div class='select-box'></div>")
|
||||
.call(bootstrap.tooltip().placement('top'))
|
||||
.append('div')
|
||||
.attr('class', 'opacity')
|
||||
.style('opacity', function(d) {
|
||||
return d;
|
||||
});
|
||||
opa.append('ul')
|
||||
.attr('class', 'opacity-options')
|
||||
.selectAll('div.opacity')
|
||||
.data(opacities)
|
||||
.enter()
|
||||
.append('li')
|
||||
.attr('data-original-title', function(d) {
|
||||
return (d * 100) + "% opacity";
|
||||
})
|
||||
.on('click.set-opacity', function(d) {
|
||||
d3.select('#tile-g')
|
||||
.transition()
|
||||
.style('opacity', d)
|
||||
.attr('data-opacity', d);
|
||||
d3.selectAll('.opacity-options li')
|
||||
.classed('selected', false);
|
||||
d3.select(this)
|
||||
.classed('selected', true);
|
||||
})
|
||||
.html("<div class='select-box'></div>")
|
||||
.call(bootstrap.tooltip().placement('top'))
|
||||
.append('div')
|
||||
.attr('class', 'opacity')
|
||||
.style('opacity', function(d) {
|
||||
return d;
|
||||
});
|
||||
|
||||
// Make sure there is an active selection by default
|
||||
d3.select('.opacity-options li').classed('selected', true);
|
||||
|
||||
@@ -39,8 +39,8 @@ d3.keybinding = function() {
|
||||
'⇞': 36, home: 36,
|
||||
// Insert key, or ins
|
||||
ins: 45, insert: 45,
|
||||
// Delete key, on Mac: ⌫ (Delete)
|
||||
del: 46, 'delete': 46,
|
||||
// Delete key, on Mac: ⌦ (Delete)
|
||||
'⌦': 46, del: 46, 'delete': 46,
|
||||
// Left Arrow Key, or ←
|
||||
'←': 37, left: 37, 'arrow-left': 37,
|
||||
// Up Arrow Key, or ↑
|
||||
@@ -93,42 +93,27 @@ d3.keybinding = function() {
|
||||
while(++i < 91) _keys.keys[String.fromCharCode(i).toLowerCase()] = i;
|
||||
|
||||
var pairs = d3.entries(_keys.keys),
|
||||
key_shortcuts = pairs.map(function(d) {
|
||||
return d.key;
|
||||
}),
|
||||
mods = d3.entries(_keys.mods),
|
||||
mod_shortcuts = mods.map(function(d) {
|
||||
return d.key;
|
||||
}),
|
||||
event = d3.dispatch.apply(d3, key_shortcuts),
|
||||
modifiers = [];
|
||||
|
||||
function keydown() {
|
||||
var tagName = d3.select(d3.event.target).node().tagName;
|
||||
if (tagName == 'INPUT' || tagName == 'SELECT' || tagName == 'TEXTAREA') {
|
||||
return;
|
||||
}
|
||||
|
||||
modifiers = modifiers.concat(mods.filter(function(d) {
|
||||
return d.value === d3.event.keyCode;
|
||||
}).map(function(d) { return d.key; }));
|
||||
|
||||
pairs.filter(function(d) {
|
||||
return d.value === d3.event.keyCode;
|
||||
}).forEach(function(d) {
|
||||
event[d.key](d3.event, modifiers.slice().sort().join(''));
|
||||
});
|
||||
}
|
||||
|
||||
function keyup() {
|
||||
modifiers = [];
|
||||
}
|
||||
event = d3.dispatch.apply(d3, d3.keys(_keys.keys));
|
||||
|
||||
function keys(selection) {
|
||||
d3.select(window).on('focus', keyup);
|
||||
selection
|
||||
.on('keyup', keyup)
|
||||
.on('keydown', keydown);
|
||||
selection.on('keydown', function () {
|
||||
var tagName = d3.select(d3.event.target).node().tagName;
|
||||
if (tagName == 'INPUT' || tagName == 'SELECT' || tagName == 'TEXTAREA') {
|
||||
return;
|
||||
}
|
||||
|
||||
var modifiers = '';
|
||||
if (d3.event.shiftKey) modifiers += '⇧';
|
||||
if (d3.event.ctrlKey) modifiers += '⌃';
|
||||
if (d3.event.altKey) modifiers += '⌥';
|
||||
if (d3.event.metaKey) modifiers += '⌘';
|
||||
|
||||
pairs.filter(function(d) {
|
||||
return d.value === d3.event.keyCode;
|
||||
}).forEach(function(d) {
|
||||
event[d.key](d3.event, modifiers);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return d3.rebind(keys, event, 'on');
|
||||
|
||||
26
package.json
Normal file
26
package.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "iD",
|
||||
"version": "0.0.0",
|
||||
"description": "a new editor for openstreetmap",
|
||||
"main": "iD.js",
|
||||
"directories": {
|
||||
"doc": "docs",
|
||||
"test": "test"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "mocha-phantomjs test/index.html"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/systemed/iD.git"
|
||||
},
|
||||
"keywords": [
|
||||
"editor",
|
||||
"openstreetmap"
|
||||
],
|
||||
"license": "BSD",
|
||||
"devDependencies": {
|
||||
"uglify-js": "~2.2.2",
|
||||
"mocha-phantomjs": "~1.1.1"
|
||||
}
|
||||
}
|
||||
5449
test/data/map.xml
5449
test/data/map.xml
File diff suppressed because it is too large
Load Diff
13
test/data/node.xml
Normal file
13
test/data/node.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<osm version="0.6" generator="OpenStreetMap server" copyright="OpenStreetMap and contributors" attribution="http://www.openstreetmap.org/copyright" license="http://opendatacommons.org/licenses/odbl/1-0/">
|
||||
<node id="356552551" version="1" changeset="747176" lat="44.6636172" lon="-73.0132525" user="iandees" uid="4732" visible="true" timestamp="2009-03-07T03:26:33Z">
|
||||
<tag k="ele" v="114"/>
|
||||
<tag k="gnis:edited" v="05/27/2008"/>
|
||||
<tag k="gnis:state_id" v="50"/>
|
||||
<tag k="gnis:feature_id" v="1456383"/>
|
||||
<tag k="amenity" v="school"/>
|
||||
<tag k="name" v="Bellows Free Academy"/>
|
||||
<tag k="gnis:county_id" v="011"/>
|
||||
<tag k="gnis:created" v="10/29/1980"/>
|
||||
</node>
|
||||
</osm>
|
||||
58
test/data/way.xml
Normal file
58
test/data/way.xml
Normal file
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<osm version="0.6" generator="OpenStreetMap server" copyright="OpenStreetMap and contributors" attribution="http://www.openstreetmap.org/copyright" license="http://opendatacommons.org/licenses/odbl/1-0/">
|
||||
<node id="204595896" version="2" changeset="2817006" lat="44.665883" lon="-72.923053" user="woodpeck_fixbot" uid="147510" visible="true" timestamp="2009-10-11T18:03:23Z"/>
|
||||
<node id="204595901" version="2" changeset="2817006" lat="44.66597" lon="-72.922201" user="woodpeck_fixbot" uid="147510" visible="true" timestamp="2009-10-11T18:03:23Z"/>
|
||||
<node id="204595904" version="2" changeset="2817006" lat="44.665989" lon="-72.921986" user="woodpeck_fixbot" uid="147510" visible="true" timestamp="2009-10-11T18:03:23Z"/>
|
||||
<node id="204595911" version="2" changeset="3138486" lat="44.666015" lon="-72.921474" user="woodpeck_fixbot" uid="147510" visible="true" timestamp="2009-11-17T05:45:06Z"/>
|
||||
<node id="204595915" version="2" changeset="2817006" lat="44.666015" lon="-72.921254" user="woodpeck_fixbot" uid="147510" visible="true" timestamp="2009-10-11T18:03:23Z"/>
|
||||
<node id="204595919" version="2" changeset="2817006" lat="44.666007" lon="-72.921033" user="woodpeck_fixbot" uid="147510" visible="true" timestamp="2009-10-11T18:03:23Z"/>
|
||||
<node id="204587613" version="2" changeset="2817006" lat="44.665983" lon="-72.920587" user="woodpeck_fixbot" uid="147510" visible="true" timestamp="2009-10-11T18:01:27Z"/>
|
||||
<node id="204595923" version="2" changeset="2817006" lat="44.665938" lon="-72.920089" user="woodpeck_fixbot" uid="147510" visible="true" timestamp="2009-10-11T18:03:23Z"/>
|
||||
<node id="204595927" version="2" changeset="2817006" lat="44.665901" lon="-72.919727" user="woodpeck_fixbot" uid="147510" visible="true" timestamp="2009-10-11T18:03:23Z"/>
|
||||
<node id="204595932" version="2" changeset="3138486" lat="44.665837" lon="-72.919284" user="woodpeck_fixbot" uid="147510" visible="true" timestamp="2009-11-17T05:45:06Z"/>
|
||||
<node id="204595935" version="2" changeset="2817006" lat="44.665821" lon="-72.91914" user="woodpeck_fixbot" uid="147510" visible="true" timestamp="2009-10-11T18:03:23Z"/>
|
||||
<node id="204595939" version="2" changeset="2817006" lat="44.66581" lon="-72.918999" user="woodpeck_fixbot" uid="147510" visible="true" timestamp="2009-10-11T18:03:23Z"/>
|
||||
<node id="204595943" version="2" changeset="2817006" lat="44.665814" lon="-72.918855" user="woodpeck_fixbot" uid="147510" visible="true" timestamp="2009-10-11T18:03:23Z"/>
|
||||
<node id="204595947" version="2" changeset="3346870" lat="44.665823" lon="-72.918783" user="woodpeck_fixbot" uid="147510" visible="true" timestamp="2009-12-11T06:32:30Z"/>
|
||||
<node id="204595950" version="2" changeset="2817006" lat="44.665839" lon="-72.91871" user="woodpeck_fixbot" uid="147510" visible="true" timestamp="2009-10-11T18:03:23Z"/>
|
||||
<node id="204595953" version="2" changeset="2817006" lat="44.66587" lon="-72.918641" user="woodpeck_fixbot" uid="147510" visible="true" timestamp="2009-10-11T18:03:23Z"/>
|
||||
<node id="204595955" version="2" changeset="2817006" lat="44.665923" lon="-72.918586" user="woodpeck_fixbot" uid="147510" visible="true" timestamp="2009-10-11T18:03:23Z"/>
|
||||
<node id="204595957" version="2" changeset="2817006" lat="44.665985" lon="-72.918559" user="woodpeck_fixbot" uid="147510" visible="true" timestamp="2009-10-11T18:03:23Z"/>
|
||||
<node id="204595961" version="2" changeset="3138486" lat="44.666193" lon="-72.918523" user="woodpeck_fixbot" uid="147510" visible="true" timestamp="2009-11-17T05:45:06Z"/>
|
||||
<node id="204595963" version="2" changeset="2817006" lat="44.666342" lon="-72.918513" user="woodpeck_fixbot" uid="147510" visible="true" timestamp="2009-10-11T18:03:23Z"/>
|
||||
<way id="19698713" visible="true" timestamp="2008-01-03T05:24:43Z" version="1" changeset="522559" user="DaveHansenTiger" uid="7168">
|
||||
<nd ref="204595896"/>
|
||||
<nd ref="204595901"/>
|
||||
<nd ref="204595904"/>
|
||||
<nd ref="204595911"/>
|
||||
<nd ref="204595915"/>
|
||||
<nd ref="204595919"/>
|
||||
<nd ref="204587613"/>
|
||||
<nd ref="204595923"/>
|
||||
<nd ref="204595927"/>
|
||||
<nd ref="204595932"/>
|
||||
<nd ref="204595935"/>
|
||||
<nd ref="204595939"/>
|
||||
<nd ref="204595943"/>
|
||||
<nd ref="204595947"/>
|
||||
<nd ref="204595950"/>
|
||||
<nd ref="204595953"/>
|
||||
<nd ref="204595955"/>
|
||||
<nd ref="204595957"/>
|
||||
<nd ref="204595961"/>
|
||||
<nd ref="204595963"/>
|
||||
<tag k="highway" v="residential"/>
|
||||
<tag k="name" v="Oustinoff Rd"/>
|
||||
<tag k="tiger:cfcc" v="A41"/>
|
||||
<tag k="tiger:county" v="Franklin, VT"/>
|
||||
<tag k="tiger:name_base" v="Oustinoff"/>
|
||||
<tag k="tiger:name_type" v="Rd"/>
|
||||
<tag k="tiger:reviewed" v="no"/>
|
||||
<tag k="tiger:separated" v="no"/>
|
||||
<tag k="tiger:source" v="tiger_import_dch_v0.6_20070830"/>
|
||||
<tag k="tiger:tlid" v="136533324:136533325"/>
|
||||
<tag k="tiger:upload_uuid" v="bulk_upload.pl-62def9fe-abee-42f3-ac1f-9d9f4b4ee78b"/>
|
||||
<tag k="tiger:zip_left" v="05444"/>
|
||||
<tag k="tiger:zip_right" v="05444"/>
|
||||
</way>
|
||||
</osm>
|
||||
@@ -20,6 +20,8 @@
|
||||
<script src='../js/lib/d3.v3.js'></script>
|
||||
<script src='../js/lib/sha.js'></script>
|
||||
<script src='../js/lib/d3.geo.tile.js'></script>
|
||||
<script src='../js/lib/d3.keybinding.js'></script>
|
||||
<script src='../js/lib/d3.latedrag.js'></script>
|
||||
<script src='../js/lib/d3.size.js'></script>
|
||||
<script src='../js/lib/d3.typeahead.js'></script>
|
||||
<script src='../js/lib/d3.one.js'></script>
|
||||
@@ -52,7 +54,8 @@
|
||||
<script src='../js/id/actions/change_entity_tags.js'></script>
|
||||
<script src="../js/id/actions/delete_node.js"></script>
|
||||
<script src="../js/id/actions/delete_way.js"></script>
|
||||
<script src='../js/id/actions/move.js'></script>
|
||||
<script src='../js/id/actions/move_node.js'></script>
|
||||
<script src='../js/id/actions/move_way.js'></script>
|
||||
<script src='../js/id/actions/noop.js'></script>
|
||||
<script src='../js/id/actions/remove_relation_member.js'></script>
|
||||
<script src='../js/id/actions/remove_way_node.js'></script>
|
||||
@@ -63,6 +66,7 @@
|
||||
<script src='../js/id/modes/add_place.js'></script>
|
||||
<script src='../js/id/modes/add_line.js'></script>
|
||||
<script src='../js/id/modes/browse.js'></script>
|
||||
<script src='../js/id/modes/drag_features.js'></script>
|
||||
<script src='../js/id/modes/draw_area.js'></script>
|
||||
<script src='../js/id/modes/draw_line.js'></script>
|
||||
<script src='../js/id/modes/select.js'></script>
|
||||
@@ -91,7 +95,8 @@
|
||||
<script src="spec/actions/change_entity_tags.js"></script>
|
||||
<script src="spec/actions/delete_node.js"></script>
|
||||
<script src="spec/actions/delete_way.js"></script>
|
||||
<script src="spec/actions/move.js"></script>
|
||||
<script src="spec/actions/move_node.js"></script>
|
||||
<script src="spec/actions/move_way.js"></script>
|
||||
<script src="spec/actions/noop.js"></script>
|
||||
<script src="spec/actions/remove_way_node.js"></script>
|
||||
<script src="spec/actions/remove_relation_member.js"></script>
|
||||
@@ -99,14 +104,19 @@
|
||||
|
||||
<script src="spec/format/geojson.js"></script>
|
||||
<script src="spec/format/xml.js"></script>
|
||||
|
||||
<script src="spec/graph/graph.js"></script>
|
||||
<script src="spec/graph/entity.js"></script>
|
||||
<script src="spec/graph/history.js"></script>
|
||||
<script src="spec/graph/way.js"></script>
|
||||
|
||||
<script src="spec/modes/add_place.js"></script>
|
||||
|
||||
<script src="spec/renderer/background.js"></script>
|
||||
<script src="spec/renderer/hash.js"></script>
|
||||
<script src="spec/renderer/map.js"></script>
|
||||
<script src="spec/renderer/style.js"></script>
|
||||
|
||||
<script src="spec/ui/inspector.js"></script>
|
||||
<script src="spec/ui/geocoder.js"></script>
|
||||
<script src="spec/connection.js"></script>
|
||||
|
||||
@@ -31,7 +31,8 @@
|
||||
<script src="spec/actions/change_entity_tags.js"></script>
|
||||
<script src="spec/actions/delete_node.js"></script>
|
||||
<script src="spec/actions/delete_way.js"></script>
|
||||
<script src="spec/actions/move.js"></script>
|
||||
<script src="spec/actions/move_node.js"></script>
|
||||
<script src="spec/actions/move_way.js"></script>
|
||||
<script src="spec/actions/noop.js"></script>
|
||||
<script src="spec/actions/remove_way_node.js"></script>
|
||||
<script src="spec/actions/remove_relation_member.js"></script>
|
||||
@@ -39,14 +40,19 @@
|
||||
|
||||
<script src="spec/format/geojson.js"></script>
|
||||
<script src="spec/format/xml.js"></script>
|
||||
|
||||
<script src="spec/graph/graph.js"></script>
|
||||
<script src="spec/graph/entity.js"></script>
|
||||
<script src="spec/graph/history.js"></script>
|
||||
<script src="spec/graph/way.js"></script>
|
||||
|
||||
<script src="spec/modes/add_place.js"></script>
|
||||
|
||||
<script src="spec/renderer/background.js"></script>
|
||||
<script src="spec/renderer/hash.js"></script>
|
||||
<script src="spec/renderer/map.js"></script>
|
||||
<script src="spec/renderer/style.js"></script>
|
||||
|
||||
<script src="spec/ui/inspector.js"></script>
|
||||
<script src="spec/connection.js"></script>
|
||||
<script src="spec/oauth.js"></script>
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
describe("iD.actions.Move", function () {
|
||||
it("changes an entity's location", function () {
|
||||
var entity = iD.Entity(),
|
||||
loc = [2, 3],
|
||||
graph = iD.actions.Move(entity.id, loc)(iD.Graph([entity]));
|
||||
expect(graph.entity(entity.id).loc).to.eql(loc);
|
||||
});
|
||||
});
|
||||
8
test/spec/actions/move_node.js
Normal file
8
test/spec/actions/move_node.js
Normal file
@@ -0,0 +1,8 @@
|
||||
describe("iD.actions.MoveNode", function () {
|
||||
it("changes a node's location", function () {
|
||||
var node = iD.Node(),
|
||||
loc = [2, 3],
|
||||
graph = iD.actions.MoveNode(node.id, loc)(iD.Graph([node]));
|
||||
expect(graph.entity(node.id).loc).to.eql(loc);
|
||||
});
|
||||
});
|
||||
21
test/spec/actions/move_way.js
Normal file
21
test/spec/actions/move_way.js
Normal file
@@ -0,0 +1,21 @@
|
||||
describe("iD.actions.MoveWay", function () {
|
||||
it("moves all nodes in a way by the given amount", function () {
|
||||
var node1 = iD.Node({loc: [0, 0]}),
|
||||
node2 = iD.Node({loc: [5, 10]}),
|
||||
way = iD.Way({nodes: [node1.id, node2.id]}),
|
||||
dxdy = [2, 3],
|
||||
projection = d3.geo.mercator(),
|
||||
graph = iD.actions.MoveWay(way.id, dxdy, projection)(iD.Graph([node1, node2, way]));
|
||||
expect(graph.entity(node1.id).loc).to.eql([1.4400000000000002, -2.1594885414215783]);
|
||||
expect(graph.entity(node2.id).loc).to.eql([6.440000000000008, 7.866329874099955]);
|
||||
});
|
||||
|
||||
it("moves repeated nodes only once", function () {
|
||||
var node = iD.Node({loc: [0, 0]}),
|
||||
way = iD.Way({nodes: [node.id, node.id]}),
|
||||
dxdy = [2, 3],
|
||||
projection = d3.geo.mercator(),
|
||||
graph = iD.actions.MoveWay(way.id, dxdy, projection)(iD.Graph([node, way]));
|
||||
expect(graph.entity(node.id).loc).to.eql([1.4400000000000002, -2.1594885414215783]);
|
||||
});
|
||||
});
|
||||
@@ -24,11 +24,11 @@ describe('Connection', function() {
|
||||
describe('#loadFromURL', function() {
|
||||
|
||||
it('loads test data', function(done) {
|
||||
c.loadFromURL('data/map.xml', done);
|
||||
c.loadFromURL('data/node.xml', done);
|
||||
});
|
||||
|
||||
it('returns a graph', function(done) {
|
||||
c.loadFromURL('data/map.xml', function(err, graph) {
|
||||
c.loadFromURL('data/node.xml', function(err, graph) {
|
||||
expect(err).to.not.be.ok;
|
||||
expect(graph).to.be.instanceOf(iD.Graph);
|
||||
done();
|
||||
@@ -36,15 +36,15 @@ describe('Connection', function() {
|
||||
});
|
||||
|
||||
it('parses a node', function(done) {
|
||||
c.loadFromURL('data/map.xml', function(err, graph) {
|
||||
expect(graph.entity('n1193811')).to.be.instanceOf(iD.Entity);
|
||||
c.loadFromURL('data/node.xml', function(err, graph) {
|
||||
expect(graph.entity('n356552551')).to.be.instanceOf(iD.Entity);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('parses a way', function(done) {
|
||||
c.loadFromURL('data/map.xml', function(err, graph) {
|
||||
expect(graph.entity('w53471')).to.be.instanceOf(iD.Entity);
|
||||
c.loadFromURL('data/way.xml', function(err, graph) {
|
||||
expect(graph.entity('w19698713')).to.be.instanceOf(iD.Entity);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
39
test/spec/modes/add_place.js
Normal file
39
test/spec/modes/add_place.js
Normal file
@@ -0,0 +1,39 @@
|
||||
describe("iD.modes.AddPlace", function () {
|
||||
var container, map, history, controller, mode;
|
||||
|
||||
beforeEach(function () {
|
||||
container = d3.select('body').append('div');
|
||||
map = iD.Map();
|
||||
history = iD.History();
|
||||
controller = iD.Controller(map, history);
|
||||
|
||||
container.call(map);
|
||||
|
||||
mode = iD.modes.AddPlace();
|
||||
controller.enter(mode);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
container.remove();
|
||||
});
|
||||
|
||||
describe("clicking the map", function () {
|
||||
it("adds a node", function () {
|
||||
happen.click(map.surface.node(), {});
|
||||
expect(history.changes().created).to.have.length(1);
|
||||
});
|
||||
|
||||
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]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("pressing ⎋", function () {
|
||||
it("exits to browse mode", function () {
|
||||
happen.keydown(document, {keyCode: 27});
|
||||
expect(controller.mode.id).to.equal('browse');
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user