Work toward making inspector persistent

This commit is contained in:
John Firebaugh
2013-05-22 16:02:21 -07:00
parent da00413632
commit 79737d2cd0
23 changed files with 871 additions and 727 deletions
+27 -23
View File
@@ -1,47 +1,51 @@
iD.ui.Disclosure = function() {
var title,
var dispatch = d3.dispatch('toggled'),
title,
expanded = false,
content = function () {},
dispatch = d3.dispatch('toggled'),
link, container;
function toggle() {
expanded = !expanded;
link.classed('expanded', expanded);
container.call(iD.ui.Toggle(expanded));
dispatch.toggled(expanded);
}
content = function () {};
var disclosure = function(selection) {
link = selection.append('a')
var $link = selection.selectAll('.hide-toggle')
.data([0]);
$link.enter().append('a')
.attr('href', '#')
.attr('class', 'hide-toggle')
.text(title)
.attr('class', 'hide-toggle');
$link.text(title)
.on('click', toggle)
.classed('expanded', expanded);
container = selection.append('div')
.classed('hide', !expanded);
var $body = selection.selectAll('div')
.data([0]);
container.call(content);
$body.enter().append('div');
$body.classed('hide', !expanded)
.call(content);
function toggle() {
expanded = !expanded;
$link.classed('expanded', expanded);
$body.call(iD.ui.Toggle(expanded));
dispatch.toggled(expanded);
}
};
disclosure.title = function(_) {
if (!arguments.length) return title;
title = _;
if (link) link.text(_);
return disclosure;
};
disclosure.expanded = function(_) {
if (link && expanded !== _) {
toggle();
} else {
expanded = _;
}
if (!arguments.length) return expanded;
expanded = _;
return disclosure;
};
disclosure.content = function(_) {
if (!arguments.length) return content;
content = _;
return disclosure;
};
+119 -97
View File
@@ -1,127 +1,124 @@
iD.ui.EntityEditor = function(context, entity) {
iD.ui.EntityEditor = function(context) {
var event = d3.dispatch('choose'),
presets = context.presets(),
id = entity.id,
tags = _.clone(entity.tags),
preset,
selection_,
presetUI,
rawTagEditor,
rawMemberEditor,
rawMembershipEditor;
id,
preset;
function browse() {
context.enter(iD.modes.Browse(context));
}
function entityEditor(selection) {
var entity = context.entity(id),
tags = _.clone(entity.tags);
function update() {
var entity = context.hasEntity(id);
if (!entity) return;
var $header = selection.selectAll('.header')
.data([0]);
tags = _.clone(entity.tags);
// Enter
// change preset if necessary (undos/redos)
var newmatch = presets.match(entity, context.graph());
if (newmatch !== preset) {
entityEditor(selection_, newmatch);
return;
}
presetUI.change(tags);
rawTagEditor.tags(tags);
if (rawMemberEditor) rawMemberEditor.change();
rawMembershipEditor.change();
}
function entityEditor(selection, newpreset) {
selection_ = selection;
var geometry = entity.geometry(context.graph());
if (!preset) preset = presets.match(entity, context.graph());
// preset was explicitly chosen
if (newpreset) {
tags = preset.removeTags(tags, geometry);
newpreset.applyTags(tags, geometry);
preset = newpreset;
}
selection.html('');
var messagewrap = selection.append('div')
var $enter = $header.enter().append('div')
.attr('class', 'header fillL cf');
messagewrap.append('button')
$enter.append('button')
.attr('class', 'preset-reset fl ')
.on('click', function() {
event.choose(preset);
})
.append('span')
.attr('class', 'icon back');
messagewrap.append('h3')
.attr('class', 'inspector-inner')
.text(t('inspector.editing_feature', { feature: preset.name() }));
$enter.append('h3')
.attr('class', 'inspector-inner');
messagewrap.append('button')
$enter.append('button')
.attr('class', 'preset-close fr')
.on('click', browse)
.append('span')
.attr('class', 'icon close');
var editorwrap = selection.append('div')
// Update
$header.select('h3')
.text(t('inspector.editing_feature', {feature: preset.name()}));
$header.select('.preset-reset')
.on('click', function() {
event.choose(preset);
});
$header.select('.preset-close')
.on('click', function() {
context.enter(iD.modes.Browse(context));
});
var $body = selection.selectAll('.inspector-body')
.data([0]);
// Enter
$enter = $body.enter().append('div')
.attr('class', 'tag-wrap inspector-body fillL2');
editorwrap.append('div')
.attr('class', 'col12 inspector-inner preset-icon-wrap')
$enter.append('div')
.attr('class', 'preset-icon-wrap inspector-inner col12')
.append('div')
.attr('class','fillL')
.attr('class', 'fillL');
$enter.append('div')
.attr('class', 'inspector-preset cf fillL col12');
$enter.append('div')
.attr('class', 'raw-tag-editor inspector-inner col12');
$enter.append('div')
.attr('class', 'raw-member-editor inspector-inner col12');
$enter.append('div')
.attr('class', 'raw-membership-editor inspector-inner col12');
$enter.append('div')
.attr('class', 'inspector-external-links inspector-inner col12');
// Update
$body.select('.preset-icon-wrap .fillL')
.call(iD.ui.PresetIcon()
.geometry(context.geometry(entity.id))
.geometry(context.geometry(id))
.preset(preset));
presetUI = iD.ui.preset(context, entity, preset)
.on('change', changeTags);
$body.select('.inspector-preset')
.call(iD.ui.preset(context)
.preset(preset)
.entityID(id)
.tags(tags)
.on('change', changeTags));
var tageditorpreset = editorwrap.append('div')
.attr('class', 'inspector-preset cf fillL col12')
.call(presetUI);
rawTagEditor = iD.ui.RawTagEditor(context, entity)
.on('change', changeTags);
editorwrap.append('div')
.attr('class', 'inspector-inner raw-tag-editor col12')
.call(rawTagEditor, preset.id === 'other');
$body.select('.raw-tag-editor')
.call(iD.ui.RawTagEditor(context)
.preset(preset)
.entityID(id)
.tags(tags)
.on('change', changeTags));
if (entity.type === 'relation') {
rawMemberEditor = iD.ui.RawMemberEditor(context, entity);
editorwrap.append('div')
.attr('class', 'inspector-inner raw-membership-editor col12')
.call(rawMemberEditor);
$body.select('.raw-member-editor')
.style('display', 'block')
.call(iD.ui.RawMemberEditor(context)
.entityID(id));
} else {
$body.select('.raw-member-editor')
.style('display', 'none')
}
rawMembershipEditor = iD.ui.RawMembershipEditor(context, entity);
$body.select('.raw-membership-editor')
.call(iD.ui.RawMembershipEditor(context)
.entityID(id));
editorwrap.append('div')
.attr('class', 'inspector-inner raw-membership-editor col12')
.call(rawMembershipEditor);
$body.select('.inspector-external-links')
.call(iD.ui.ViewOnOSM(context)
.entityID(id));
var viewOnOSM = iD.ui.ViewOnOSM(context);
editorwrap.append('div')
.attr('class', 'col12 inspector-inner inspector-external-links')
.call(viewOnOSM, entity);
presetUI.change(tags);
rawTagEditor.tags(tags);
changeTags();
function historyChanged() {
var entity = context.hasEntity(id);
if (!entity) return;
preset = context.presets().match(entity, context.graph());
entityEditor(selection);
}
context.history()
.on('change.entity-editor', update);
.on('change.entity-editor', historyChanged);
}
function clean(o) {
@@ -134,15 +131,40 @@ iD.ui.EntityEditor = function(context, entity) {
}
function changeTags(changed) {
tags = clean(_.extend(tags, changed));
var entity = context.hasEntity(id);
if (entity && !_.isEqual(entity.tags, tags)) {
var entity = context.entity(id),
tags = clean(_.extend({}, entity.tags, changed));
if (!_.isEqual(entity.tags, tags)) {
context.perform(
iD.actions.ChangeTags(entity.id, tags),
iD.actions.ChangeTags(id, tags),
t('operations.change_tags.annotation'));
}
}
entityEditor.entityID = function(_) {
if (!arguments.length) return id;
id = _;
preset = context.presets().match(context.entity(id), context.graph());
return entityEditor;
};
entityEditor.preset = function(_) {
if (!arguments.length) return preset;
var entity = context.entity(id),
geometry = context.geometry(id),
tags = preset.removeTags(entity.tags, geometry);
preset = _;
tags = preset.applyTags(tags, geometry);
context.perform(
iD.actions.ChangeTags(id, tags),
t('operations.change_tags.annotation'));
return entityEditor;
};
entityEditor.close = function() {
// Blur focused element so that tag changes are dispatched
// See #1295
+35 -46
View File
@@ -1,70 +1,59 @@
iD.ui.Inspector = function(context) {
var presetList,
entityEditor,
var presetList = iD.ui.PresetList(context),
entityEditor = iD.ui.EntityEditor(context),
entityID,
newFeature = false;
function inspector(selection) {
selection.style('display', 'block');
var reselect = selection.html(),
entity = context.entity(entityID);
var $wrap = selection.selectAll('.panewrap')
.data([0]);
selection
.html('')
.style('display', 'block')
.style('right', '-500px')
.style('opacity', 1)
.transition()
.duration(reselect ? 0 : 200)
.style('right', '0px');
var $enter = $wrap.enter().append('div')
.attr('class', 'panewrap');
var panewrap = selection
.append('div')
.classed('panewrap', true);
$enter.append('div')
.attr('class', 'grid-pane pane');
var presetLayer = panewrap
.append('div')
.classed('pane grid-pane', true);
$enter.append('div')
.attr('class', 'tag-pane pane');
var tagLayer = panewrap
.append('div')
.classed('pane tag-pane', true);
var $presetPane = $wrap.select('.grid-pane')
.call(presetList
.entityID(entityID)
.autofocus(newFeature)
.on('choose', setPreset));
presetList = iD.ui.PresetList(context, entity)
.autofocus(newFeature)
.on('choose', function(preset) {
panewrap
.transition()
.style('right', '0%');
var $editorPane = $wrap.select('.tag-pane')
.call(entityEditor
.entityID(entityID)
.on('choose', showList));
tagLayer.call(entityEditor, preset);
});
$wrap.style('right', context.entity(entityID).isUsed(context.graph()) ? '-0%' : '-100%');
entityEditor = iD.ui.EntityEditor(context, entity)
.on('choose', function(preset) {
panewrap
.transition()
.style('right', '-100%');
function showList(preset) {
$wrap.transition()
.style('right', '-100%');
presetList
.current(preset)
.autofocus(true);
$presetPane.call(presetList
.preset(preset)
.autofocus(true));
}
presetLayer.call(presetList);
});
function setPreset(preset) {
$wrap.transition()
.style('right', '0%');
if (entity.isUsed(context.graph())) {
panewrap.style('right', '-0%');
tagLayer.call(entityEditor);
} else {
panewrap.style('right', '-100%');
presetLayer.call(presetList);
$editorPane.call(entityEditor
.preset(preset));
}
}
inspector.close = function(selection) {
entityEditor.close();
selection.html('');
selection.style('display', 'none');
};
inspector.entityID = function(_) {
+98 -104
View File
@@ -1,12 +1,11 @@
iD.ui.preset = function(context, entity, preset) {
var original = context.graph().base().entities[entity.id],
event = d3.dispatch('change'),
fields = [],
tags = {},
formwrap,
formbuttonwrap;
iD.ui.preset = function(context) {
var event = d3.dispatch('change'),
fields,
preset,
tags,
id;
function UIField(field, show) {
function UIField(field, entity, show) {
field = _.clone(field);
field.input = iD.ui.preset[field.type](field, context)
@@ -29,160 +28,155 @@ iD.ui.preset = function(context, entity, preset) {
};
field.modified = function() {
var original = context.graph().base().entities[entity.id];
return _.any(field.keys, function(key) {
return original ? tags[key] !== original.tags[key] : tags[key];
});
};
field.revert = function() {
var original = context.graph().base().entities[entity.id],
t = {};
field.keys.forEach(function(key) {
t[key] = original ? original.tags[key] : undefined;
});
return t;
};
return field;
}
fields.push(UIField(context.presets().field('name')));
var geometry = entity.geometry(context.graph());
preset.fields.forEach(function(field) {
if (field.matchGeometry(geometry)) {
fields.push(UIField(field, true));
}
});
context.presets().universal().forEach(function(field) {
if (preset.fields.indexOf(field) < 0) {
fields.push(UIField(field));
}
});
function fieldKey(field) {
return field.id;
}
function shown() {
return fields.filter(function(field) { return field.shown(); });
}
function presets(selection) {
if (!fields) {
var entity = context.entity(id),
geometry = context.geometry(id);
function notShown() {
return fields.filter(function(field) { return !field.shown(); });
}
fields = [UIField(context.presets().field('name'), entity)];
function show(field) {
field.show = true;
render();
field.input.focus();
}
preset.fields.forEach(function(field) {
if (field.matchGeometry(geometry)) {
fields.push(UIField(field, entity, true));
}
});
function revert(field) {
d3.event.stopPropagation();
d3.event.preventDefault();
var t = {};
field.keys.forEach(function(key) {
t[key] = original ? original.tags[key] || '' : '';
});
event.change(t);
}
context.presets().universal().forEach(function(field) {
if (preset.fields.indexOf(field) < 0) {
fields.push(UIField(field, entity));
}
});
}
function render() {
var selection = formwrap.selectAll('.form-field')
.data(shown(), fieldKey);
var shown = fields.filter(function(field) { return field.shown(); }),
notShown = fields.filter(function(field) { return !field.shown(); });
var enter = selection.enter()
var $fields = selection.selectAll('.form-field')
.data(shown, fieldKey);
// Enter
var $enter = $fields.enter()
.insert('div', '.more-buttons')
.style('opacity', 0)
.attr('class', function(field) {
return 'form-field form-field-' + field.id + ' fillL col12';
});
enter.transition()
.style('max-height', '0px')
.style('padding-top', '0px')
.style('opacity', '0')
.transition()
.duration(200)
.style('padding-top', '10px')
.style('max-height', '240px')
.style('opacity', '1')
.each('end', function(d) {
d3.select(this).style('max-height', '');
});
var label = enter.append('label')
var $label = $enter.append('label')
.attr('class', 'form-label')
.attr('for', function(field) { return 'preset-input-' + field.id; })
.text(function(field) { return field.label(); });
label.each(function(field) {
d3.select(this)
.call(field.reference.button);
});
label.append('button')
$label.append('button')
.attr('class', 'modified-icon minor')
.attr('tabindex', -1)
.on('click', revert)
.append('div')
.attr('class','icon undo');
.attr('class', 'icon undo');
enter.each(function(field) {
d3.select(this)
.call(field.input)
.call(field.reference.body);
});
// Update
selection
$fields.select('.modified-icon')
.on('click', revert);
$fields.select('.form-label')
.each(function(field) {
field.input.tags(tags);
})
.classed('modified', function(field) {
return field.modified();
d3.select(this)
.call(field.reference.button);
});
selection.exit()
$fields
.classed('modified', function(field) {
return field.modified();
})
.each(function(field) {
d3.select(this)
.call(field.input)
.call(field.reference.body);
field.input.tags(tags);
});
$fields.exit()
.remove();
var addFields = formbuttonwrap.selectAll('.preset-add-field')
.data(notShown(), fieldKey);
var $more = selection.selectAll('.more-buttons')
.data([0]);
addFields.enter()
$more.enter().append('div')
.attr('class', 'more-buttons inspector-inner col12');
var $buttons = $more.selectAll('.preset-add-field')
.data(notShown, fieldKey);
$buttons.enter()
.append('button')
.attr('class', 'preset-add-field')
.on('click', show)
.call(bootstrap.tooltip()
.placement('top')
.title(function(d) { return d.label(); }))
.append('span')
.attr('class', function(d) { return 'icon ' + d.icon; });
addFields.exit()
$buttons.on('click', show);
$buttons.exit()
.transition()
.style('opacity', 0)
.remove();
return selection;
function show(field) {
field.show = true;
presets(selection);
field.input.focus();
}
function revert(field) {
d3.event.stopPropagation();
d3.event.preventDefault();
event.change(field.revert());
}
}
function presets(selection) {
selection.html('');
formwrap = selection;
formbuttonwrap = selection.append('div')
.attr('class', 'col12 more-buttons inspector-inner');
render();
}
presets.rendered = function() {
return _.flatten(shown().map(function(field) { return field.keys; }));
};
presets.preset = function(_) {
if (!arguments.length) return preset;
preset = _;
fields = null;
return presets;
};
presets.change = function(_) {
presets.tags = function(_) {
if (!arguments.length) return tags;
tags = _;
render();
// Don't reset fields here.
return presets;
};
presets.entityID = function(_) {
if (!arguments.length) return id;
id = _;
fields = null;
return presets;
};
+16 -7
View File
@@ -4,14 +4,19 @@ iD.ui.preset.access = function(field, context) {
items;
function access(selection) {
var wrap = selection.append('div')
.attr('class', 'cf preset-input-wrap');
var wrap = selection.selectAll('.preset-input-wrap')
.data([0]);
items = wrap.append('ul').selectAll('li')
wrap.enter().append('div')
.attr('class', 'cf preset-input-wrap')
.append('ul');
items = wrap.select('ul').selectAll('li')
.data(field.keys);
var enter = items.enter()
.append('li')
// Enter
var enter = items.enter().append('li')
.attr('class', function(d) { return 'cf preset-access-' + d; });
enter.append('span')
@@ -25,13 +30,17 @@ iD.ui.preset.access = function(field, context) {
.attr('type', 'text')
.attr('class', 'preset-input-access')
.attr('id', function(d) { return 'preset-input-access-' + d; })
.on('change', change)
.on('blur', change)
.each(function(d) {
d3.select(this)
.call(d3.combobox()
.data(access.options(d)));
});
// Update
wrap.selectAll('.preset-input-access')
.on('change', change)
.on('blur', change);
}
function change(d) {
+31 -23
View File
@@ -1,5 +1,4 @@
iD.ui.preset.address = function(field, context) {
var event = d3.dispatch('change'),
housename,
housenumber,
@@ -36,45 +35,54 @@ iD.ui.preset.address = function(field, context) {
}
function address(selection) {
var wrap = selection.append('div')
var wrap = selection.selectAll('.preset-input-wrap')
.data([0]);
// Enter
var enter = wrap.enter().append('div')
.attr('class', 'preset-input-wrap');
housename = wrap.append('input')
enter.append('input')
.property('type', 'text')
.attr('placeholder', field.t('placeholders.housename'))
.attr('class', 'addr-housename')
.attr('id', 'preset-input-' + field.id)
.on('blur', change)
.on('change', change);
.attr('id', 'preset-input-' + field.id);
housenumber = wrap.append('input')
enter.append('input')
.property('type', 'text')
.attr('placeholder', field.t('placeholders.number'))
.attr('class', 'addr-number')
.on('blur', change)
.on('change', change);
.attr('class', 'addr-number');
street = wrap.append('input')
enter.append('input')
.property('type', 'text')
.attr('placeholder', field.t('placeholders.street'))
.attr('class', 'addr-street')
.on('blur', change)
.on('change', change)
.call(d3.combobox().data(getStreets()));
.attr('class', 'addr-street');
city = wrap.append('input')
enter.append('input')
.property('type', 'text')
.attr('placeholder', field.t('placeholders.city'))
.attr('class', 'addr-city')
.attr('class', 'addr-city');
enter.append('input')
.property('type', 'text')
.attr('placeholder', field.t('placeholders.postcode'))
.attr('class', 'addr-postcode');
// Update
housename = wrap.select('.addr-housename');
housenumber = wrap.select('.addr-number');
street = wrap.select('.addr-street');
city = wrap.select('.addr-city');
postcode = wrap.select('.addr-postcode');
wrap.selectAll('input')
.on('blur', change)
.on('change', change);
postcode = wrap.append('input')
.property('type', 'text')
.attr('placeholder', field.t('placeholders.postcode'))
.attr('class', 'addr-postcode')
.on('blur', change)
.on('change', change);
street
.call(d3.combobox().data(getStreets()));
}
function change() {
+16 -12
View File
@@ -1,5 +1,4 @@
iD.ui.preset.check = function(field) {
var event = d3.dispatch('change'),
values = ['', 'yes', 'no'],
value = '',
@@ -8,28 +7,33 @@ iD.ui.preset.check = function(field) {
label;
var check = function(selection) {
selection.classed('checkselect', 'true');
label = selection.append('label')
label = selection.selectAll('.preset-input-wrap')
.data([0]);
var enter = label.enter().append('label')
.attr('class', 'preset-input-wrap');
box = label.append('input')
enter.append('input')
.property('indeterminate', true)
.attr('type', 'checkbox')
.attr('id', 'preset-input-' + field.id);
text = label.append('span')
enter.append('span')
.text('unknown')
.attr('class', 'value');
box.on('click', function() {
var t = {};
t[field.key] = values[(values.indexOf(value) + 1) % 3];
check.tags(t);
event.change(t);
d3.event.stopPropagation();
});
box = label.select('input')
.on('click', function() {
var t = {};
t[field.key] = values[(values.indexOf(value) + 1) % 3];
check.tags(t);
event.change(t);
d3.event.stopPropagation();
});
text = label.select('span.value');
};
check.tags = function(tags) {
+7 -4
View File
@@ -1,14 +1,18 @@
iD.ui.preset.combo = function(field) {
var event = d3.dispatch('change'),
input;
function combo(selection) {
var combobox = d3.combobox();
input = selection.append('input')
input = selection.selectAll('input')
.data([0]);
input.enter().append('input')
.attr('type', 'text')
.attr('id', 'preset-input-' + field.id)
.attr('id', 'preset-input-' + field.id);
input
.on('change', change)
.on('blur', change)
.call(combobox);
@@ -37,7 +41,6 @@ iD.ui.preset.combo = function(field) {
}
}
function change() {
var t = {};
t[field.key] = input.property('value').replace(' ', '_');
+8 -5
View File
@@ -1,19 +1,22 @@
iD.ui.preset.defaultcheck = function(field) {
var event = d3.dispatch('change'),
input;
var check = function(selection) {
function check(selection) {
input = selection.selectAll('input')
.data([0]);
input = selection.append('input')
input.enter().append('input')
.attr('type', 'checkbox')
.attr('id', 'preset-input-' + field.id)
.attr('id', 'preset-input-' + field.id);
input
.on('change', function() {
var t = {};
t[field.key] = input.property('checked') ? field.value || 'yes' : undefined;
event.change(t);
});
};
}
check.tags = function(tags) {
input.property('checked', !!tags[field.key] && tags[field.key] !== 'no');
+22 -15
View File
@@ -8,10 +8,15 @@ iD.ui.preset.url = function(field) {
input;
function i(selection) {
input = selection.append('input')
input = selection.selectAll('input')
.data([0]);
input.enter().append('input')
.attr('type', field.type)
.attr('id', 'preset-input-' + field.id)
.attr('placeholder', field.placeholder || '')
.attr('placeholder', field.placeholder || '');
input
.on('blur', change)
.on('change', change);
@@ -23,23 +28,25 @@ iD.ui.preset.url = function(field) {
}
if (field.type == 'number') {
input.attr('type', 'text');
var numbercontrols = selection.append('div')
var spinControl = selection.selectAll('.spin-control')
.data([0]);
var enter = spinControl.enter().append('div')
.attr('class', 'spin-control');
numbercontrols
.append('button')
.attr('class', 'increment')
.on('click', function() {
pm(input.node(), 1);
});
numbercontrols
.append('button')
.attr('class', 'decrement')
.on('click', function() {
pm(input.node(), -1);
enter.append('button')
.datum(1)
.attr('class', 'increment');
enter.append('button')
.datum(-1)
.attr('class', 'decrement');
spinControl.selectAll('button')
.on('click', function(d) {
pm(input.node(), d);
});
}
}
+20 -11
View File
@@ -5,29 +5,38 @@ iD.ui.preset.localized = function(field, context) {
input, localizedInputs, wikiTitles;
function i(selection) {
input = selection.selectAll('.localized-main')
.data([0]);
input = selection.append('input')
input.enter().append('input')
.attr('type', 'text')
.attr('id', 'preset-input-' + field.id)
.attr('class', 'localized-main')
.attr('placeholder', field.placeholder || '')
.attr('placeholder', field.placeholder || '');
input
.on('blur', change)
.on('change', change);
var translateButton = selection.append('button')
.attr('class', 'button-input-action localized-add minor')
.on('click', addBlank);
var translateButton = selection.selectAll('.localized-add')
.data([0]);
translateButton.append('span')
translateButton.enter().append('button')
.attr('class', 'button-input-action localized-add minor')
.call(bootstrap.tooltip()
.title(t('translate.translate'))
.placement('left'))
.append('span')
.attr('class', 'icon plus');
translateButton.call(bootstrap.tooltip()
.title(t('translate.translate'))
.placement('left'));
translateButton
.on('click', addBlank);
localizedInputs = selection.append('div')
localizedInputs = selection.selectAll('.localized-wrap')
.data([0]);
localizedInputs.enter().append('div')
.attr('class', 'localized-wrap');
}
function addBlank() {
+14 -4
View File
@@ -14,9 +14,14 @@ iD.ui.preset.maxspeed = function(field, context) {
combobox = d3.combobox();
var unitCombobox = d3.combobox().data(['km/h', 'mph'].map(comboValues));
input = selection.append('input')
input = selection.selectAll('#preset-input-' + field.id)
.data([0]);
input.enter().append('input')
.attr('type', 'text')
.attr('id', 'preset-input-' + field.id)
.attr('id', 'preset-input-' + field.id);
input
.on('change', change)
.on('blur', change)
.call(combobox);
@@ -30,9 +35,14 @@ iD.ui.preset.maxspeed = function(field, context) {
});
});
unitInput = selection.append('input')
unitInput = selection.selectAll('input.maxspeed-unit')
.data([0]);
unitInput.enter().append('input')
.attr('type', 'text')
.attr('class', 'maxspeed-unit')
.attr('class', 'maxspeed-unit');
unitInput
.on('blur', changeUnits)
.on('change', changeUnits)
.call(unitCombobox);
+22 -12
View File
@@ -6,28 +6,38 @@ iD.ui.preset.radio = function(field) {
function radio(selection) {
selection.classed('preset-radio', true);
var buttonwrap = selection.append('div')
var wrap = selection.selectAll('.preset-input-wrap')
.data([0]);
wrap.enter().append('div')
.attr('class', 'preset-input-wrap toggle-list radio-wrap');
buttons = buttonwrap.selectAll('button')
.data(field.options || field.keys)
.enter()
.append('button')
.text(function(d) { return field.t('options.' + d, { 'default': d }); })
buttons = wrap.selectAll('button')
.data(field.options || field.keys);
buttons.enter().append('button')
.text(function(d) { return field.t('options.' + d, { 'default': d }); });
buttons
.on('click', function(d) {
buttons.classed('active', function(e) { return d === e; });
change();
});
buttonwrap.append('button')
.attr('class','remove')
.on('click', function() {
buttons.classed('active', false);
change();
})
var remove = wrap.selectAll('button.remove')
.data([0]);
remove.enter().append('button')
.attr('class', 'remove')
.text(t('inspector.remove'))
.append('span')
.attr('class', 'icon remove');
remove
.on('click', function() {
buttons.classed('active', false);
change();
});
}
function change() {
+7 -2
View File
@@ -4,10 +4,15 @@ iD.ui.preset.textarea = function(field) {
input;
function i(selection) {
input = selection.append('textarea')
input = selection.selectAll('textarea')
.data([0]);
input.enter().append('textarea')
.attr('id', 'preset-input-' + field.id)
.attr('placeholder', field.placeholder || '')
.attr('maxlength', 255)
.attr('maxlength', 255);
input
.on('blur', change)
.on('change', change);
}
+21 -8
View File
@@ -33,26 +33,39 @@ iD.ui.preset.wikipedia = function(field, context) {
});
});
lang = selection.append('input')
lang = selection.selectAll('input.wiki-lang')
.data([0]);
lang.enter().append('input')
.attr('type', 'text')
.attr('class', 'wiki-lang')
.attr('class', 'wiki-lang');
lang
.on('blur', changeLang)
.on('change', changeLang)
.call(langcombo);
title = selection.append('input')
title = selection.selectAll('input.wiki-title')
.data([0]);
title.enter().append('input')
.attr('type', 'text')
.attr('class', 'wiki-title')
.attr('id', 'preset-input-' + field.id)
.attr('id', 'preset-input-' + field.id);
title
.on('blur', change)
.on('change', change)
.call(titlecombo);
link = selection.append('a')
link = selection.selectAll('a.wiki-link')
.data([0]);
link.enter().append('a')
.attr('class', 'wiki-link button-input-action minor')
.attr('target', '_blank');
link.append('span')
.attr('class','icon out-link');
.attr('target', '_blank')
.append('span')
.attr('class', 'icon out-link');
}
function changeLang() {
+29 -21
View File
@@ -2,32 +2,40 @@ iD.ui.PresetIcon = function() {
var preset, geometry;
function presetIcon(selection) {
selection.append('div')
.attr('class', function() {
var s = 'preset-icon-fill icon-' + geometry;
for (var i in preset.tags) {
s += ' tag-' + i + ' tag-' + i + '-' + preset.tags[i];
}
return s;
});
var $fill = selection.selectAll('.preset-icon-fill')
.data([0]);
$fill.enter().append('div');
$fill.attr('class', function() {
var s = 'preset-icon-fill icon-' + geometry;
for (var i in preset.tags) {
s += ' tag-' + i + ' tag-' + i + '-' + preset.tags[i];
}
return s;
});
var fallbackIcon = geometry === 'line' ? 'other-line' : 'marker-stroked';
selection.append('div')
.attr('class', function() {
var icon = preset.icon || fallbackIcon,
klass = 'feature-' + icon + ' preset-icon';
var $icon = selection.selectAll('.preset-icon')
.data([0]);
var featureicon = iD.data.featureIcons[icon];
if (featureicon && featureicon[geometry]) {
klass += ' preset-icon-' + geometry;
} else if (icon === 'multipolygon') {
// Special case (geometry === 'area')
klass += ' preset-icon-relation';
}
$icon.enter().append('div');
return klass;
});
$icon.attr('class', function() {
var icon = preset.icon || fallbackIcon,
klass = 'feature-' + icon + ' preset-icon';
var featureicon = iD.data.featureIcons[icon];
if (featureicon && featureicon[geometry]) {
klass += ' preset-icon-' + geometry;
} else if (icon === 'multipolygon') {
// Special case (geometry === 'area')
klass += ' preset-icon-relation';
}
return klass;
});
}
presetIcon.preset = function(_) {
+22 -17
View File
@@ -1,15 +1,12 @@
iD.ui.PresetList = function(context, entity) {
iD.ui.PresetList = function(context) {
var event = d3.dispatch('choose'),
presets, current,
id,
preset,
autofocus = false;
function browse() {
context.enter(iD.modes.Browse(context));
}
function presetList(selection) {
var geometry = entity.geometry(context.graph());
presets = context.presets().matchGeometry(geometry);
var geometry = context.geometry(id),
presets = context.presets().matchGeometry(geometry);
selection.html('');
@@ -20,7 +17,7 @@ iD.ui.PresetList = function(context, entity) {
.attr('class', 'inspector-inner')
.text(t('inspector.choose'));
if (current) {
if (preset) {
messagewrap.append('button')
.attr('class', 'preset-choose')
.on('click', event.choose)
@@ -29,7 +26,9 @@ iD.ui.PresetList = function(context, entity) {
} else {
messagewrap.append('button')
.attr('class', 'close')
.on('click', browse)
.on('click', function() {
context.enter(iD.modes.Browse(context));
})
.append('span')
.attr('class', 'icon close');
}
@@ -41,7 +40,7 @@ iD.ui.PresetList = function(context, entity) {
d3.event.keyCode === d3.keybinding.keyCodes['⌦'])) {
d3.event.preventDefault();
d3.event.stopPropagation();
iD.operations.Delete([entity.id], context)();
iD.operations.Delete([id], context)();
} else if (search.property('value').length === 0 &&
(d3.event.ctrlKey || d3.event.metaKey) &&
d3.event.keyCode === d3.keybinding.keyCodes.z) {
@@ -108,7 +107,7 @@ iD.ui.PresetList = function(context, entity) {
items.enter().append('div')
.attr('class', function(item) { return 'preset-list-item preset-' + item.preset.id.replace('/', '-'); })
.classed('current', function(item) { return item.preset === current; })
.classed('current', function(item) { return item.preset === preset; })
.each(function(item) {
d3.select(this).call(item);
})
@@ -132,7 +131,7 @@ iD.ui.PresetList = function(context, entity) {
wrap.append('button')
.attr('class', 'preset-list-button')
.call(iD.ui.PresetIcon()
.geometry(context.geometry(entity.id))
.geometry(context.geometry(id))
.preset(preset))
.on('click', item.choose)
.append('div')
@@ -182,7 +181,7 @@ iD.ui.PresetList = function(context, entity) {
wrap.append('button')
.attr('class', 'preset-list-button')
.call(iD.ui.PresetIcon()
.geometry(context.geometry(entity.id))
.geometry(context.geometry(id))
.preset(preset))
.on('click', item.choose)
.append('div')
@@ -215,9 +214,15 @@ iD.ui.PresetList = function(context, entity) {
return presetList;
};
presetList.current = function(_) {
if (!arguments.length) return current;
current = _;
presetList.entityID = function(_) {
if (!arguments.length) return id;
id = _;
return presetList;
};
presetList.preset = function(_) {
if (!arguments.length) return preset;
preset = _;
return presetList;
};
+74 -79
View File
@@ -1,32 +1,5 @@
iD.ui.RawMemberEditor = function(context, entity) {
var list, disclosure;
var rawMemberEditor = function(selection) {
function toggled(expanded) {
if (expanded) {
selection.node().parentNode.scrollTop += 200;
}
}
disclosure = iD.ui.Disclosure()
.title(t('inspector.all_members'))
.expanded(true)
.on('toggled', toggled)
.content(content);
selection.call(disclosure);
};
rawMemberEditor.change = function() {
drawMembers();
};
function content(wrap) {
list = wrap.append('ul')
.attr('class', 'member-list');
drawMembers();
}
iD.ui.RawMemberEditor = function(context) {
var id;
function selectMember(d) {
context.enter(iD.modes.Select(context, [d.member.id]));
@@ -35,75 +8,97 @@ iD.ui.RawMemberEditor = function(context, entity) {
function changeRole(d) {
var role = d3.select(this).property('value');
context.perform(
iD.actions.ChangeMember(entity.id, _.extend({}, d.member, {role: role}), d.index),
iD.actions.ChangeMember(id, _.extend({}, d.member, {role: role}), d.index),
t('operations.change_role.annotation'));
}
function deleteMember(d) {
context.perform(
iD.actions.DeleteMember(entity.id, d.index),
iD.actions.DeleteMember(id, d.index),
t('operations.delete_member.annotation.' + context.geometry(d.member.id)));
}
function drawMembers() {
var memberships = [];
entity = context.hasEntity(entity.id);
if (!entity) return;
function rawMemberEditor(selection) {
var entity = context.entity(id),
memberships = [];
entity.members.forEach(function(member, index) {
memberships.push({member: member, index: index, entity: context.hasEntity(member.id)});
});
disclosure.title(t('inspector.all_members') + ' (' + memberships.length + ')');
selection.call(iD.ui.Disclosure()
.title(t('inspector.all_members') + ' (' + memberships.length + ')')
.expanded(true)
.on('toggled', toggled)
.content(content));
var li = list.selectAll('li')
.data(memberships, function(d) { return iD.Entity.key(entity) + ',' + d.index; });
var row = li.enter().append('li')
.attr('class', 'member-row form-field');
row.each(function(d) {
if (d.entity) {
var member = d3.select(this).append('label')
.attr('class', 'form-label')
.append('a')
.attr('href', '#')
.on('click', selectMember);
member.append('span')
.attr('class', 'member-entity-type')
.text(function(d) { return context.presets().match(d.entity, context.graph()).name(); });
member.append('span')
.attr('class', 'member-entity-name')
.text(function(d) { return iD.util.localeName(d.entity); });
} else {
d3.select(this).append('label')
.attr('class', 'form-label member-incomplete')
.text(t('inspector.incomplete'));
function toggled(expanded) {
if (expanded) {
selection.node().parentNode.scrollTop += 200;
}
});
}
row.append('input')
.attr('class', 'member-role')
.property('type', 'text')
.attr('maxlength', 255)
.attr('placeholder', t('inspector.role'))
.property('value', function(d) { return d.member.role; })
.on('change', changeRole);
function content($wrap) {
var $list = $wrap.selectAll('.member-list')
.data([0]);
row.append('button')
.attr('tabindex', -1)
.attr('class', 'remove button-input-action member-delete minor')
.on('click', deleteMember)
.append('span')
.attr('class', 'icon delete');
$list.enter().append('ul')
.attr('class', 'member-list');
li.exit()
.remove();
var $items = $list.selectAll('li')
.data(memberships, function(d) { return iD.Entity.key(entity) + ',' + d.index; });
var $enter = $items.enter().append('li')
.attr('class', 'member-row form-field');
$enter.each(function(d) {
if (d.entity) {
var $label = d3.select(this).append('label')
.attr('class', 'form-label')
.append('a')
.attr('href', '#')
.on('click', selectMember);
$label.append('span')
.attr('class', 'member-entity-type')
.text(function(d) { return context.presets().match(d.entity, context.graph()).name(); });
$label.append('span')
.attr('class', 'member-entity-name')
.text(function(d) { return iD.util.localeName(d.entity); });
} else {
d3.select(this).append('label')
.attr('class', 'form-label member-incomplete')
.text(t('inspector.incomplete'));
}
});
$enter.append('input')
.attr('class', 'member-role')
.property('type', 'text')
.attr('maxlength', 255)
.attr('placeholder', t('inspector.role'))
.property('value', function(d) { return d.member.role; })
.on('change', changeRole);
$enter.append('button')
.attr('tabindex', -1)
.attr('class', 'remove button-input-action member-delete minor')
.on('click', deleteMember)
.append('span')
.attr('class', 'icon delete');
$items.exit()
.remove();
}
}
rawMemberEditor.entityID = function(_) {
if (!arguments.length) return id;
id = _;
return rawMemberEditor;
};
return rawMemberEditor;
};
+60 -62
View File
@@ -1,32 +1,5 @@
iD.ui.RawMembershipEditor = function(context, entity) {
var list, disclosure;
var rawMembershipEditor = function(selection) {
function toggled(expanded) {
if (expanded) {
selection.node().parentNode.scrollTop += 200;
}
}
disclosure = iD.ui.Disclosure()
.title(t('inspector.all_relations'))
.expanded(true)
.on('toggled', toggled)
.content(content);
selection.call(disclosure);
};
rawMembershipEditor.change = function() {
drawMemberships();
};
function content(wrap) {
list = wrap.append('ul')
.attr('class', 'member-list');
drawMemberships();
}
iD.ui.RawMembershipEditor = function(context) {
var id;
function selectRelation(d) {
context.enter(iD.modes.Select(context, [d.relation.id]));
@@ -45,8 +18,9 @@ iD.ui.RawMembershipEditor = function(context, entity) {
t('operations.delete_member.annotation.' + context.geometry(d.member.id)));
}
function drawMemberships() {
var memberships = [];
function rawMembershipEditor(selection) {
var entity = context.entity(id),
memberships = [];
context.graph().parentRelations(entity).forEach(function(relation) {
relation.members.forEach(function(member, index) {
@@ -56,46 +30,70 @@ iD.ui.RawMembershipEditor = function(context, entity) {
})
});
disclosure.title(t('inspector.all_relations') + ' (' + memberships.length + ')');
selection.call(iD.ui.Disclosure()
.title(t('inspector.all_relations') + ' (' + memberships.length + ')')
.expanded(true)
.on('toggled', toggled)
.content(content));
var li = list.selectAll('li')
.data(memberships, function(d) { return iD.Entity.key(d.relation) + ',' + d.index; });
function toggled(expanded) {
if (expanded) {
selection.node().parentNode.scrollTop += 200;
}
}
var row = li.enter().append('li')
.attr('class', 'member-row form-field');
function content($wrap) {
var $list = $wrap.selectAll('.member-list')
.data([0]);
relationLabel = row.append('label')
.attr('class', 'form-label')
.append('a')
.attr('href', '#')
.on('click', selectRelation);
$list.enter().append('ul')
.attr('class', 'member-list');
relationLabel.append('span')
.attr('class','member-entity-type')
.text(function(d) { return context.presets().match(d.relation, context.graph()).name(); });
var $items = $list.selectAll('li')
.data(memberships, function(d) { return iD.Entity.key(d.relation) + ',' + d.index; });
relationLabel.append('span')
.attr('class', 'member-entity-name')
.text(function(d) { return iD.util.localeName(d.relation); });
var $enter = $items.enter().append('li')
.attr('class', 'member-row form-field');
row.append('input')
.attr('class', 'member-role')
.property('type', 'text')
.attr('maxlength', 255)
.attr('placeholder', t('inspector.role'))
.property('value', function(d) { return d.member.role; })
.on('change', changeRole);
var $label = $enter.append('label')
.attr('class', 'form-label')
.append('a')
.attr('href', '#')
.on('click', selectRelation);
row.append('button')
.attr('tabindex', -1)
.attr('class', 'remove button-input-action member-delete minor')
.on('click', deleteMembership)
.append('span')
.attr('class', 'icon delete');
$label.append('span')
.attr('class','member-entity-type')
.text(function(d) { return context.presets().match(d.relation, context.graph()).name(); });
li.exit()
.remove();
$label.append('span')
.attr('class', 'member-entity-name')
.text(function(d) { return iD.util.localeName(d.relation); });
$enter.append('input')
.attr('class', 'member-role')
.property('type', 'text')
.attr('maxlength', 255)
.attr('placeholder', t('inspector.role'))
.property('value', function(d) { return d.member.role; })
.on('change', changeRole);
$enter.append('button')
.attr('tabindex', -1)
.attr('class', 'remove button-input-action member-delete minor')
.on('click', deleteMembership)
.append('span')
.attr('class', 'icon delete');
$items.exit()
.remove();
}
}
rawMembershipEditor.entityID = function(_) {
if (!arguments.length) return id;
id = _;
return rawMembershipEditor;
};
return rawMembershipEditor;
};
+158 -142
View File
@@ -1,195 +1,211 @@
iD.ui.RawTagEditor = function(context, entity) {
iD.ui.RawTagEditor = function(context) {
var event = d3.dispatch('change'),
taginfo = iD.taginfo(),
disclosure,
list;
preset,
tags,
id;
function rawTagEditor(selection) {
var count = Object.keys(tags).filter(function(d) { return d; }).length;
selection.call(iD.ui.Disclosure()
.title(t('inspector.all_tags') + ' (' + count + ')')
.expanded(iD.ui.RawTagEditor.expanded || preset.isFallback())
.on('toggled', toggled)
.content(content));
function rawTagEditor(selection, other) {
function toggled(expanded) {
iD.ui.RawTagEditor.expanded = expanded;
if (expanded) {
selection.node().parentNode.scrollTop += 200;
}
}
disclosure = iD.ui.Disclosure()
.title(t('inspector.all_tags'))
.expanded(iD.ui.RawTagEditor.expanded || other)
.on('toggled', toggled)
.content(content);
selection.call(disclosure);
}
function content(wrap) {
list = wrap.append('ul')
.attr('class', 'tag-list');
function content($wrap) {
var entries = d3.entries(tags);
var newTag = wrap.append('button')
.attr('class', 'add-tag col6')
.on('click', addTag);
newTag.append('span')
.attr('class', 'icon plus light');
newTag.append('span')
.attr('class', 'label')
.text(t('inspector.new_tag'));
}
function drawTags(tags) {
var count = Object.keys(tags).filter(function(d) { return d; }).length;
disclosure.title(t('inspector.all_tags') + ' (' + count + ')');
tags = d3.entries(tags);
if (!tags.length) {
tags = [{key: '', value: ''}];
if (!entries.length) {
entries = [{key: '', value: ''}];
}
tags.forEach(function(tag) {
tag.reference = iD.ui.TagReference({key: tag.key});
entries.forEach(function(entry) {
entry.reference = iD.ui.TagReference({key: entry.key});
});
var li = list.html('')
.selectAll('li')
.data(tags, function(d) { return d.key; });
var $list = $wrap.selectAll('.tag-list')
.data([0]);
li.exit().remove();
$list.enter().append('ul')
.attr('class', 'tag-list');
var row = li.enter().append('li')
var $newTag = $wrap.selectAll('.add-tag')
.data([0]);
var $enter = $newTag.enter().append('button')
.attr('class', 'add-tag col6');
$enter.append('span')
.attr('class', 'icon plus light');
$enter.append('span')
.attr('class', 'label')
.text(t('inspector.new_tag'));
$newTag.on('click', addTag);
var $items = $list.selectAll('li')
.data(entries, function(d) { return d.key; });
// Enter
$enter = $items.enter().append('li')
.attr('class', 'tag-row cf');
row.append('div')
$enter.append('div')
.attr('class', 'key-wrap')
.append('input')
.property('type', 'text')
.attr('class', 'key')
.attr('maxlength', 255)
.property('value', function(d) { return d.key; })
.on('blur', keyChange)
.on('change', keyChange);
.attr('maxlength', 255);
function keyChange(d) {
d.key = this.value;
event.change(rawTagEditor.tags());
}
row.append('div')
$enter.append('div')
.attr('class', 'input-wrap-position col6')
.append('input')
.property('type', 'text')
.attr('class', 'value')
.attr('maxlength', 255)
.property('value', function(d) { return d.value; })
.attr('maxlength', 255);
$enter.append('button')
.attr('tabindex', -1)
.attr('class', 'remove minor')
.append('span')
.attr('class', 'icon delete');
// Update
$items.order();
$items.select('input.key')
.property('value', function(d) {
return d.key;
})
.on('blur', keyChange)
.on('change', keyChange);
$items.select('input.value')
.property('value', function(d) {
return d.value;
})
.on('blur', valueChange)
.on('change', valueChange)
.on('keydown.push-more', pushMore);
function valueChange(d) {
d.value = this.value;
event.change(rawTagEditor.tags());
}
$items.select('button.remove')
.on('click', removeTag);
row.each(bindTypeahead);
row.append('button')
.attr('tabindex', -1)
.attr('class','remove minor')
.on('click', removeTag)
.append('span')
.attr('class', 'icon delete');
row.each(function(tag) {
$items.each(function(tag) {
d3.select(this)
.each(bindTypeahead)
.call(tag.reference.button)
.call(tag.reference.body);
});
return li;
}
$items.exit()
.remove();
function pushMore() {
if (d3.event.keyCode === 9 &&
list.selectAll('li:last-child input.value').node() === this &&
!d3.event.shiftKey) {
addTag();
d3.event.preventDefault();
function keyChange(d) {
var tag = {};
tag[this.value] = d.value;
d.key = this.value; // Maintain DOM identity through the subsequent update.
event.change(tag);
}
}
function bindTypeahead() {
var geometry = entity.geometry(context.graph()),
row = d3.select(this),
key = row.selectAll('input.key'),
value = row.selectAll('input.value');
function valueChange(d) {
var tag = {};
tag[d.key] = this.value;
event.change(tag);
}
function sort(value, data) {
var sameletter = [],
other = [];
for (var i = 0; i < data.length; i++) {
if (data[i].value.substring(0, value.length) === value) {
sameletter.push(data[i]);
} else {
other.push(data[i]);
}
function pushMore() {
if (d3.event.keyCode === 9 && !d3.event.shiftKey &&
$list.selectAll('li:last-child input.value').node() === this) {
addTag();
d3.event.preventDefault();
}
return sameletter.concat(other);
}
key.call(d3.combobox()
.fetcher(function(value, __, callback) {
taginfo.keys({
debounce: true,
geometry: geometry,
query: value
}, function(err, data) {
if (!err) callback(sort(value, data));
});
}));
function bindTypeahead() {
var geometry = context.geometry(id),
row = d3.select(this),
key = row.selectAll('input.key'),
value = row.selectAll('input.value');
value.call(d3.combobox()
.fetcher(function(value, __, callback) {
taginfo.values({
debounce: true,
key: key.property('value'),
geometry: geometry,
query: value
}, function(err, data) {
if (!err) callback(sort(value, data));
});
}));
}
function sort(value, data) {
var sameletter = [],
other = [];
for (var i = 0; i < data.length; i++) {
if (data[i].value.substring(0, value.length) === value) {
sameletter.push(data[i]);
} else {
other.push(data[i]);
}
}
return sameletter.concat(other);
}
function addTag() {
var tags = rawTagEditor.tags();
tags[''] = '';
drawTags(tags);
list.selectAll('li:last-child input.key').node().focus();
}
key.call(d3.combobox()
.fetcher(function(value, __, callback) {
taginfo.keys({
debounce: true,
geometry: geometry,
query: value
}, function(err, data) {
if (!err) callback(sort(value, data));
});
}));
function removeTag(d) {
var tags = rawTagEditor.tags();
tags[d.key] = '';
event.change(tags);
delete tags[d.key];
drawTags(tags);
}
rawTagEditor.tags = function(tags) {
if (!arguments.length) {
tags = {};
list.selectAll('li').each(function() {
var row = d3.select(this),
key = row.selectAll('.key').property('value'),
value = row.selectAll('.value').property('value');
if (key !== '') tags[key] = value;
});
return tags;
} else {
drawTags(tags);
value.call(d3.combobox()
.fetcher(function(value, __, callback) {
taginfo.values({
debounce: true,
key: key.property('value'),
geometry: geometry,
query: value
}, function(err, data) {
if (!err) callback(sort(value, data));
});
}));
}
function addTag() {
tags[''] = '';
content($wrap);
$list.selectAll('li:last-child input.key').node().focus();
}
function removeTag(d) {
tags[d.key] = '';
event.change(tags);
}
}
rawTagEditor.preset = function(_) {
if (!arguments.length) return preset;
preset = _;
return rawTagEditor;
};
rawTagEditor.tags = function(_) {
if (!arguments.length) return tags;
tags = _;
return rawTagEditor;
};
rawTagEditor.entityID = function(_) {
if (!arguments.length) return id;
id = _;
return rawTagEditor;
};
return d3.rebind(rawTagEditor, event, 'on');
+23 -14
View File
@@ -31,25 +31,32 @@ iD.ui.TagReference = function(tag) {
}
tagReference.button = function(selection) {
button = selection.append('button')
.attr('tabindex', -1)
.attr('class', 'tag-reference-button minor')
.on('click', function() {
d3.event.stopPropagation();
d3.event.preventDefault();
if (showing) {
tagReference.hide();
} else {
tagReference.load();
}
});
button = selection.selectAll('.tag-reference-button')
.data([0]);
button.append('span')
var enter = button.enter().append('button')
.attr('tabindex', -1)
.attr('class', 'tag-reference-button minor');
enter.append('span')
.attr('class', 'icon inspect');
button.on('click', function () {
d3.event.stopPropagation();
d3.event.preventDefault();
if (showing) {
tagReference.hide();
} else {
tagReference.load();
}
});
};
tagReference.body = function(selection) {
body = selection.append('div')
body = selection.selectAll('.tag-reference-body')
.data([0]);
body.enter().append('div')
.attr('class', 'tag-reference-body cf')
.style('max-height', '0')
.style('opacity', '0');
@@ -68,6 +75,8 @@ iD.ui.TagReference = function(tag) {
docs = findLocal(docs);
}
body.html('');
if (!docs || !docs.description) {
body.append('p').text(t('inspector.no_documentation_key'));
tagReference.show();
+20 -7
View File
@@ -1,19 +1,32 @@
iD.ui.ViewOnOSM = function(context) {
return function(selection, entity) {
var id;
function viewOnOSM(selection) {
var entity = context.entity(id);
selection.style('display', entity.isNew() ? 'none' : null);
var osmLink = selection.selectAll('.view-on-osm')
.data([entity]);
var $link = selection.selectAll('.view-on-osm')
.data([0]);
var enter = osmLink.enter().append('a')
var $enter = $link.enter().append('a')
.attr('class', 'view-on-osm')
.attr('target', '_blank');
enter.append('span')
$enter.append('span')
.attr('class', 'icon icon-pre-text out-link');
enter.append('span')
$enter.append('span')
.text(t('inspector.view_on_osm'));
osmLink.attr('href', context.connection().entityURL(entity));
$link.attr('href', context.connection().entityURL(entity));
}
viewOnOSM.entityID = function(_) {
if (!arguments.length) return id;
id = _;
return viewOnOSM;
};
return viewOnOSM;
};
+22 -12
View File
@@ -12,16 +12,25 @@ d3.combobox = function() {
};
var combobox = function(input) {
var idx = -1, container, shown = false;
var idx = -1,
container = d3.select(document.body)
.selectAll('div.combobox')
.filter(function(d) { return d === input.node(); }),
shown = !container.empty();
input
.classed('combobox-input', true)
.each(function() {
var parent = this.parentNode,
sibling = this.nextSibling;
d3.select(parent)
.insert('div', function() { return sibling; })
.attr('class', 'combobox-carat')
var carat = d3.select(parent).selectAll('.combobox-carat')
.data([0]);
carat.enter().insert('div', function() { return sibling; })
.attr('class', 'combobox-carat');
carat
.on('mousedown', function () {
// prevent the form element from blurring. it blurs
// on mousedown
@@ -50,6 +59,7 @@ d3.combobox = function() {
if (!shown) {
container = d3.select(document.body)
.insert('div', ':first-child')
.datum(input.node())
.attr('class', 'combobox')
.style({
position: 'absolute',
@@ -201,18 +211,18 @@ d3.combobox = function() {
.selectAll('a.combobox-option')
.data(data, function(d) { return d.value; });
options.enter()
.append('a')
.text(function(d) { return d.value; })
options.enter().append('a')
.attr('class', 'combobox-option')
.attr('title', function(d) { return d.title; })
.on('click', select);
options.exit().remove();
.text(function(d) { return d.value; });
options
.attr('title', function(d) { return d.title; })
.classed('selected', function(d, i) { return i == idx; })
.on('click', select)
.order();
options.exit()
.remove();
}
fetcher.apply(input, [value, data, render]);
@@ -234,7 +244,7 @@ d3.combobox = function() {
input.node().focus();
update('');
if (!container) return;
if (container.empty()) return;
var entries = container.selectAll('a'),
height = container.node().scrollHeight / entries[0].length,