in modules/ui/sections/raw_tag_editor.js [49:281]
function renderDisclosureContent(wrap) {
// remove deleted keys
_orderedKeys = _orderedKeys.filter(function(key) {
return _tags[key] !== undefined;
});
// When switching to a different entity or changing the state (hover/select)
// reorder the keys alphabetically.
// We trigger this by emptying the `_orderedKeys` array, then it will be rebuilt here.
// Otherwise leave their order alone - #5857, #5927
var all = Object.keys(_tags).sort();
var missingKeys = utilArrayDifference(all, _orderedKeys);
for (var i in missingKeys) {
_orderedKeys.push(missingKeys[i]);
}
// assemble row data
var rowData = _orderedKeys.map(function(key, i) {
return { index: i, key: key, value: _tags[key] };
});
// append blank row last, if necessary
if (!rowData.length || _showBlank) {
_showBlank = false;
rowData.push({ index: rowData.length, key: '', value: '' });
}
// View Options
var options = wrap.selectAll('.raw-tag-options')
.data([0]);
options.exit()
.remove();
var optionsEnter = options.enter()
.insert('div', ':first-child')
.attr('class', 'raw-tag-options');
var optionEnter = optionsEnter.selectAll('.raw-tag-option')
.data(availableViews, function(d) { return d.id; })
.enter();
optionEnter
.append('button')
.attr('class', function(d) {
return 'raw-tag-option raw-tag-option-' + d.id + (_tagView === d.id ? ' selected' : '');
})
.attr('title', function(d) { return t('icons.' + d.id); })
.on('click', function(d3_event, d) {
_tagView = d.id;
prefs('raw-tag-editor-view', d.id);
wrap.selectAll('.raw-tag-option')
.classed('selected', function(datum) { return datum === d; });
wrap.selectAll('.tag-text')
.classed('hide', (d.id !== 'text'))
.each(setTextareaHeight);
wrap.selectAll('.tag-list, .add-row')
.classed('hide', (d.id !== 'list'));
})
.each(function(d) {
d3_select(this)
.call(svgIcon(d.icon));
});
// View as Text
var textData = rowsToText(rowData);
var textarea = wrap.selectAll('.tag-text')
.data([0]);
textarea = textarea.enter()
.append('textarea')
.attr('class', 'tag-text' + (_tagView !== 'text' ? ' hide' : ''))
.call(utilNoAuto)
.attr('placeholder', t('inspector.key_value'))
.attr('spellcheck', 'false')
.merge(textarea);
textarea
.call(utilGetSetValue, textData)
.each(setTextareaHeight)
.on('input', setTextareaHeight)
.on('focus', interacted)
.on('blur', textChanged)
.on('change', textChanged);
// View as List
var list = wrap.selectAll('.tag-list')
.data([0]);
list = list.enter()
.append('ul')
.attr('class', 'tag-list' + (_tagView !== 'list' ? ' hide' : ''))
.merge(list);
// Container for the Add button
var addRowEnter = wrap.selectAll('.add-row')
.data([0])
.enter()
.append('div')
.attr('class', 'add-row' + (_tagView !== 'list' ? ' hide' : ''));
addRowEnter
.append('button')
.attr('class', 'add-tag')
.call(svgIcon('#iD-icon-plus', 'light'))
.on('click', addTag);
addRowEnter
.append('div')
.attr('class', 'space-value'); // preserve space
addRowEnter
.append('div')
.attr('class', 'space-buttons'); // preserve space
// Tag list items
var items = list.selectAll('.tag-row')
.data(rowData, function(d) { return d.key; });
items.exit()
.each(unbind)
.remove();
// Enter
var itemsEnter = items.enter()
.append('li')
.attr('class', 'tag-row')
.classed('readonly', isReadOnly);
var innerWrap = itemsEnter.append('div')
.attr('class', 'inner-wrap');
innerWrap
.append('div')
.attr('class', 'key-wrap')
.append('input')
.property('type', 'text')
.attr('class', 'key')
.call(utilNoAuto)
.on('focus', interacted)
.on('blur', keyChange)
.on('change', keyChange);
innerWrap
.append('div')
.attr('class', 'value-wrap')
.append('input')
.property('type', 'text')
.attr('class', 'value')
.call(utilNoAuto)
.on('focus', interacted)
.on('blur', valueChange)
.on('change', valueChange)
.on('keydown.push-more', pushMore);
innerWrap
.append('button')
.attr('class', 'form-field-button remove')
.attr('title', t('icons.remove'))
.call(svgIcon('#iD-operation-delete'));
// Update
items = items
.merge(itemsEnter)
.sort(function(a, b) { return a.index - b.index; });
items
.each(function(d) {
var row = d3_select(this);
var key = row.select('input.key'); // propagate bound data
var value = row.select('input.value'); // propagate bound data
if (_entityIDs && taginfo && _state !== 'hover') {
bindTypeahead(key, value);
}
var referenceOptions = { key: d.key };
if (typeof d.value === 'string') {
referenceOptions.value = d.value;
}
var reference = uiTagReference(referenceOptions, context);
if (_state === 'hover') {
reference.showing(false);
}
row.select('.inner-wrap') // propagate bound data
.call(reference.button);
row.call(reference.body);
row.select('button.remove'); // propagate bound data
});
items.selectAll('input.key')
.attr('title', function(d) { return d.key; })
.call(utilGetSetValue, function(d) { return d.key; })
.attr('readonly', function(d) {
return (isReadOnly(d) || (typeof d.value !== 'string')) || null;
});
items.selectAll('input.value')
.attr('title', function(d) {
return Array.isArray(d.value) ? d.value.filter(Boolean).join('\n') : d.value;
})
.classed('mixed', function(d) {
return Array.isArray(d.value);
})
.attr('placeholder', function(d) {
return typeof d.value === 'string' ? null : t('inspector.multiple_values');
})
.call(utilGetSetValue, function(d) {
return typeof d.value === 'string' ? d.value : '';
})
.attr('readonly', function(d) {
return isReadOnly(d) || null;
});
items.selectAll('button.remove')
.on(('PointerEvent' in window ? 'pointer' : 'mouse') + 'down', removeTag); // 'click' fires too late - #5878
}