Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add 'Add Tag' button (#314), needs style

Fixes #281.
  • Loading branch information...
commit 4a7bd26be8c4cd04ec1243e96acb6307e66c73e4 1 parent 0cb5fbe
@jfirebaugh jfirebaugh authored
View
1  Makefile
@@ -17,6 +17,7 @@ all: \
js/lib/d3.keybinding.js \
js/lib/d3.one.js \
js/lib/d3.size.js \
+ js/lib/d3.trigger.js \
js/lib/d3.typeahead.js \
js/lib/jxon.js \
js/lib/lodash.js \
View
19 css/app.css
@@ -489,7 +489,7 @@ button.Browse .label {
.tag-row input {
width: 50%;
- border-right: 0;
+ border-left: 0;
}
.tag-row input.key {
@@ -500,9 +500,8 @@ button.Browse .label {
border-top: 1px solid #ccc;
}
-.tag-row input.value {
- position: relative;
- border-right: 1px solid #ccc;
+.tag-row input.key {
+ border-left: 1px solid #ccc;
}
.input-wrap::after {
@@ -531,8 +530,16 @@ button.Browse .label {
border-top: 1px solid #ccc;
}
-.tag-row-empty button {
- display: none;
+.inspector-inner .add-tag-row {
+ width: 100%;
+ padding-right: 70px;
+}
+
+.inspector-inner .add-tag {
+ width: 50%;
+ height: 30px;
+ border: 1px solid #ccc;
+ border-top: 0;
}
/* Map Controls */
View
1  index.html
@@ -20,6 +20,7 @@
<script src='js/lib/d3.typeahead.js'></script>
<script src='js/lib/d3.geo.tile.js'></script>
<script src='js/lib/d3.size.js'></script>
+ <script src='js/lib/d3.trigger.js'></script>
<script src='js/lib/d3.keybinding.js'></script>
<script src='js/lib/d3-compat.js'></script>
<script src='js/lib/queue.js'></script>
View
50 js/id/ui/inspector.js
@@ -2,7 +2,7 @@ iD.Inspector = function() {
var event = d3.dispatch('changeTags', 'changeWayDirection',
'update', 'remove', 'close', 'splitWay'),
taginfo = iD.taginfo(),
- inspectorwrap;
+ tagList;
function inspector(selection) {
var entity = selection.datum();
@@ -21,12 +21,22 @@ iD.Inspector = function() {
var inspectorbody = selection.append('div')
.attr('class', 'inspector-body');
- inspectorwrap = inspectorbody.append('ul')
+ var inspectorwrap = inspectorbody.append('div')
.attr('class', 'inspector-inner tag-wrap fillL2');
inspectorwrap.append('h4')
.text('Edit tags');
+ tagList = inspectorwrap.append('ul');
+
+ inspectorwrap.append('div').attr('class', 'add-tag-row').append('button')
+ .attr('class', 'add-tag')
+ .text('+ Add New Tag')
+ .on('click', function() {
+ addTag();
+ tagList.selectAll('li:last-child input.key').node().focus();
+ });
+
var formsel = drawTags(entity.tags);
inspectorbody.append('div')
@@ -99,27 +109,33 @@ iD.Inspector = function() {
function drawTags(tags) {
tags = d3.entries(tags);
- tags.push({ key: '', value: ''});
- var li = inspectorwrap.selectAll('li')
+ if (!tags.length) {
+ tags = [{key: '', value: ''}];
+ }
+
+ var li = tagList.selectAll('li')
.data(tags, function(d) { return d.key; });
li.exit().remove();
- var row = li.enter().append('li').attr('class','tag-row');
- var inputs = row.append('div').attr('class','input-wrap');
+ var row = li.enter().append('li')
+ .attr('class', 'tag-row');
- li.classed('tag-row-empty', function(d) { return d.key === ''; });
+ var inputs = row.append('div')
+ .attr('class', 'input-wrap');
inputs.append('input')
.property('type', 'text')
.attr('class', 'key')
- .property('value', function(d) { return d.key; });
+ .property('value', function(d) { return d.key; })
+ .on('change', function(d) { d.key = this.value; });
inputs.append('input')
.property('type', 'text')
.attr('class', 'value')
.property('value', function(d) { return d.value; })
+ .on('change', function(d) { d.value = this.value; })
.on('keydown.push-more', pushMore);
inputs.each(bindTypeahead);
@@ -129,7 +145,8 @@ iD.Inspector = function() {
.attr('class','remove minor')
.on('click', removeTag);
- removeBtn.append('span').attr('class', 'icon remove');
+ removeBtn.append('span')
+ .attr('class', 'icon remove');
var helpBtn = row.append('button')
.attr('tabindex', -1)
@@ -160,14 +177,15 @@ iD.Inspector = function() {
return 'http://taginfo.openstreetmap.org/keys/' + d.key;
});
- helpBtn.append('span').attr('class', 'icon inspect');
+ helpBtn.append('span')
+ .attr('class', 'icon inspect');
return li;
}
function pushMore() {
- if (d3.event.keyCode === 9) {
- drawTags(inspector.tags());
+ if (d3.event.keyCode === 9 && tagList.selectAll('li:last-child input.value').node() === this) {
+ addTag();
}
}
@@ -195,6 +213,12 @@ iD.Inspector = function() {
}));
}
+ function addTag() {
+ var tags = inspector.tags();
+ tags[''] = '';
+ drawTags(tags);
+ }
+
function removeTag(d) {
var tags = inspector.tags();
delete tags[d.key];
@@ -208,7 +232,7 @@ iD.Inspector = function() {
inspector.tags = function () {
var tags = {};
- inspectorwrap.selectAll('li').each(function() {
+ tagList.selectAll('li').each(function() {
var row = d3.select(this),
key = row.selectAll('.key').property('value'),
value = row.selectAll('.value').property('value');
View
7 js/lib/d3.trigger.js
@@ -0,0 +1,7 @@
+d3.selection.prototype.trigger = function (type) {
+ this.each(function() {
+ var evt = document.createEvent('HTMLEvents');
+ evt.initEvent(type, true, true);
+ this.dispatchEvent(evt);
+ });
+};
View
9 js/lib/d3.typeahead.js
@@ -36,7 +36,7 @@ d3.typeahead = function() {
if (d3.event.keyCode === 40) idx++;
if (d3.event.keyCode === 38) idx--;
if (d3.event.keyCode === 13) {
- selection.property('value', container.select('a.selected').datum().value);
+ select(container.select('a.selected').datum());
hide();
}
@@ -57,11 +57,16 @@ d3.typeahead = function() {
.append('a')
.text(function(d) { return d.value; })
.attr('title', function(d) { return d.title; })
- .on('click', function(d) { selection.property('value', d.value); });
+ .on('click', select);
options.exit().remove();
});
}
+
+ function select(d) {
+ selection.property('value', d.value)
+ .trigger('change');
+ }
};
typeahead.data = function(_) {
View
1  test/index.html
@@ -22,6 +22,7 @@
<script src='../js/lib/d3.geo.tile.js'></script>
<script src='../js/lib/d3.keybinding.js'></script>
<script src='../js/lib/d3.size.js'></script>
+ <script src='../js/lib/d3.trigger.js'></script>
<script src='../js/lib/d3.typeahead.js'></script>
<script src='../js/lib/d3.one.js'></script>
<script src='../js/lib/ohauth.js'></script>
View
38 test/spec/ui/inspector.js
@@ -1,15 +1,20 @@
describe("iD.Inspector", function () {
var inspector, element,
tags = {highway: 'residential'},
- entity = iD.Entity({type: 'node', id: "n12345", tags: tags});
+ entity;
- beforeEach(function () {
+ function render() {
inspector = iD.Inspector();
element = d3.select('body')
.append('div')
.attr('id', 'inspector-wrap')
.datum(entity)
.call(inspector);
+ }
+
+ beforeEach(function () {
+ entity = iD.Entity({type: 'node', id: "n12345", tags: tags});
+ render();
});
afterEach(function () {
@@ -22,9 +27,9 @@ describe("iD.Inspector", function () {
});
it("returns updated tags when input values have changed", function () {
- element.selectAll(".tag-row-empty input.key").property('value', 'k');
- element.selectAll(".tag-row-empty input.value").property('value', 'v');
- expect(inspector.tags()).to.eql({highway: 'residential', k: 'v'});
+ element.selectAll("input.key").property('value', 'k');
+ element.selectAll("input.value").property('value', 'v');
+ expect(inspector.tags()).to.eql({k: 'v'});
});
});
@@ -33,17 +38,22 @@ describe("iD.Inspector", function () {
expect(element.selectAll("input[value=residential]")).not.to.be.empty;
});
- it("creates one trailing pair of empty input elements", function () {
- expect(element.selectAll("input")[0][2].value).to.be.empty;
- expect(element.selectAll("input")[0][3].value).to.be.empty;
+ it("creates a pair of empty input elements if the entity has no tags", function () {
+ element.remove();
+ entity = entity.update({tags: {}});
+ render();
+ expect(element.selectAll("input.value").property('value')).to.be.empty;
+ expect(element.selectAll("input.key").property('value')).to.be.empty;
});
- it("sets the 'tag-row-empty' class on the placeholder row", function () {
- expect(element.selectAll(".tag-row:last-child").classed('tag-row-empty')).to.be.true;
+ it("adds tags when clicking the add button", function () {
+ element.selectAll("button.add-tag").trigger('click');
+ expect(element.selectAll("input")[0][2].value).to.be.empty;
+ expect(element.selectAll("input")[0][3].value).to.be.empty;
});
it("removes tags when clicking the remove button", function () {
- happen.click(element.selectAll("button.remove").node());
+ element.selectAll("button.remove").trigger('click');
expect(inspector.tags()).to.eql({});
});
@@ -51,7 +61,7 @@ describe("iD.Inspector", function () {
var spy = sinon.spy();
inspector.on('close', spy);
- happen.click(element.select('.close').node());
+ element.select('.close').trigger('click');
expect(spy).to.have.been.calledWith(entity);
});
@@ -60,7 +70,7 @@ describe("iD.Inspector", function () {
var spy = sinon.spy();
inspector.on('changeTags', spy);
- happen.click(element.select('.apply').node());
+ element.select('.apply').trigger('click');
expect(spy).to.have.been.calledWith(entity, tags);
});
@@ -69,7 +79,7 @@ describe("iD.Inspector", function () {
var spy = sinon.spy();
inspector.on('remove', spy);
- happen.click(element.select('.delete').node());
+ element.select('.delete').trigger('click');
expect(spy).to.have.been.calledWith(entity);
});
Please sign in to comment.
Something went wrong with that request. Please try again.