mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-14 09:42:56 +00:00
349 lines
9.0 KiB
JavaScript
349 lines
9.0 KiB
JavaScript
import * as d3 from 'd3';
|
|
import { t } from '../../util/locale';
|
|
import { d3combobox } from '../../lib/d3.combobox.js';
|
|
import { services } from '../../services/index';
|
|
|
|
import {
|
|
utilGetSetValue,
|
|
utilNoAuto,
|
|
utilRebind
|
|
} from '../../util';
|
|
|
|
|
|
export { uiFieldRadio as uiFieldStructureRadio };
|
|
|
|
|
|
export function uiFieldRadio(field, context) {
|
|
var dispatch = d3.dispatch('change'),
|
|
taginfo = services.taginfo,
|
|
placeholder = d3.select(null),
|
|
wrap = d3.select(null),
|
|
labels = d3.select(null),
|
|
radios = d3.select(null),
|
|
typeInput = d3.select(null),
|
|
layerInput = d3.select(null),
|
|
oldType = {},
|
|
entity;
|
|
|
|
|
|
function selectedKey() {
|
|
var selector = '.form-field-structure .toggle-list label.active input',
|
|
node = d3.selectAll(selector);
|
|
return !node.empty() && node.datum();
|
|
}
|
|
|
|
// returns the tag value for a display value
|
|
function tagValue(dispVal) {
|
|
dispVal = snake(clean(dispVal || ''));
|
|
return dispVal.toLowerCase() || 'yes';
|
|
}
|
|
|
|
// returns the display value for a tag value
|
|
function displayValue(tagVal) {
|
|
tagVal = tagVal || '';
|
|
return tagVal.toLowerCase() === 'yes' ? '' : unsnake(tagVal);
|
|
}
|
|
|
|
function snake(s) {
|
|
return s.replace(/\s+/g, '_');
|
|
}
|
|
|
|
function unsnake(s) {
|
|
return s.replace(/_+/g, ' ');
|
|
}
|
|
|
|
function clean(s) {
|
|
return s.split(';')
|
|
.map(function(s) { return s.trim(); })
|
|
.join(';');
|
|
}
|
|
|
|
|
|
function radio(selection) {
|
|
selection.classed('preset-radio', true);
|
|
|
|
wrap = selection.selectAll('.preset-input-wrap')
|
|
.data([0]);
|
|
|
|
var enter = wrap.enter()
|
|
.append('div')
|
|
.attr('class', 'preset-input-wrap toggle-list');
|
|
|
|
enter
|
|
.append('span')
|
|
.attr('class', 'placeholder');
|
|
|
|
wrap = wrap
|
|
.merge(enter);
|
|
|
|
|
|
placeholder = wrap.selectAll('.placeholder');
|
|
|
|
labels = wrap.selectAll('label')
|
|
.data(field.options || field.keys);
|
|
|
|
enter = labels.enter()
|
|
.append('label');
|
|
|
|
enter
|
|
.append('input')
|
|
.attr('type', 'radio')
|
|
.attr('name', field.id)
|
|
.attr('value', function(d) { return field.t('options.' + d, { 'default': d }); })
|
|
.attr('checked', false);
|
|
|
|
enter
|
|
.append('span')
|
|
.text(function(d) { return field.t('options.' + d, { 'default': d }); });
|
|
|
|
labels = labels
|
|
.merge(enter);
|
|
|
|
radios = labels.selectAll('input')
|
|
.on('change', changeRadio);
|
|
}
|
|
|
|
|
|
function structureExtras(selection) {
|
|
var selected = selectedKey();
|
|
|
|
var extrasWrap = selection.selectAll('.structure-extras-wrap')
|
|
.data(selected ? [0] : []);
|
|
|
|
extrasWrap.exit()
|
|
.remove();
|
|
|
|
extrasWrap = extrasWrap.enter()
|
|
.append('div')
|
|
.attr('class', 'structure-extras-wrap')
|
|
.merge(extrasWrap);
|
|
|
|
var list = extrasWrap.selectAll('ul')
|
|
.data([0]);
|
|
|
|
list = list.enter()
|
|
.append('ul')
|
|
.merge(list);
|
|
|
|
|
|
// Type
|
|
var typeItem = list.selectAll('.structure-type-item')
|
|
.data([0]);
|
|
|
|
var typeEnter = typeItem.enter()
|
|
.append('li')
|
|
.attr('class', 'cf structure-type-item');
|
|
|
|
typeEnter
|
|
.append('span')
|
|
.attr('class', 'col6 label structure-label-type')
|
|
.attr('for', 'structure-input-type')
|
|
.text(t('inspector.radio.structure.type'));
|
|
|
|
typeEnter
|
|
.append('div')
|
|
.attr('class', 'col6 structure-input-type-wrap')
|
|
.append('input')
|
|
.attr('type', 'text')
|
|
.attr('class', 'structure-input-type')
|
|
.attr('placeholder', t('inspector.radio.structure.default'))
|
|
.call(utilNoAuto);
|
|
|
|
typeItem = typeItem
|
|
.merge(typeEnter);
|
|
|
|
typeInput = typeItem.selectAll('.structure-input-type');
|
|
|
|
if (taginfo) {
|
|
typeInput
|
|
.call(d3combobox()
|
|
.container(context.container())
|
|
.fetcher(typeFetcher)
|
|
);
|
|
}
|
|
|
|
typeInput
|
|
.on('change', changeType)
|
|
.on('blur', changeType);
|
|
|
|
|
|
// Layer
|
|
var showLayer = (selected === 'bridge' || selected === 'tunnel');
|
|
|
|
var layerItem = list.selectAll('.structure-layer-item')
|
|
.data(showLayer ? [0] : []);
|
|
|
|
layerItem.exit()
|
|
.remove();
|
|
|
|
var layerEnter = layerItem.enter()
|
|
.append('li')
|
|
.attr('class', 'cf structure-layer-item');
|
|
|
|
layerEnter
|
|
.append('span')
|
|
.attr('class', 'col6 label structure-label-layer')
|
|
.attr('for', 'structure-input-layer')
|
|
.text(t('inspector.radio.structure.layer'));
|
|
|
|
layerEnter
|
|
.append('div')
|
|
.attr('class', 'col6 structure-input-layer-wrap')
|
|
.append('input')
|
|
.attr('type', 'text')
|
|
.attr('class', 'structure-input-layer')
|
|
.attr('placeholder', '0')
|
|
.call(utilNoAuto);
|
|
|
|
var spin = layerEnter
|
|
.append('div')
|
|
.attr('class', 'spin-control');
|
|
|
|
spin
|
|
.append('button')
|
|
.datum(-1)
|
|
.attr('class', 'decrement')
|
|
.attr('tabindex', -1);
|
|
|
|
spin
|
|
.append('button')
|
|
.datum(1)
|
|
.attr('class', 'increment')
|
|
.attr('tabindex', -1);
|
|
|
|
layerItem = layerItem
|
|
.merge(layerEnter);
|
|
|
|
layerInput = layerItem.selectAll('.structure-input-layer')
|
|
.on('change', changeLayer)
|
|
.on('blur', changeLayer);
|
|
|
|
layerItem.selectAll('button')
|
|
.on('click', function(d) {
|
|
d3.event.preventDefault();
|
|
var num = parseInt(layerInput.node().value || 0, 10);
|
|
if (!isNaN(num)) layerInput.node().value = num + d;
|
|
changeLayer();
|
|
});
|
|
|
|
}
|
|
|
|
|
|
function typeFetcher(q, callback) {
|
|
taginfo.values({
|
|
debounce: true,
|
|
key: selectedKey(),
|
|
query: q
|
|
}, function(err, data) {
|
|
if (err) return;
|
|
var comboData = data.map(function(d) {
|
|
return {
|
|
key: d.value,
|
|
value: unsnake(d.value),
|
|
title: d.title
|
|
};
|
|
});
|
|
if (callback) callback(comboData);
|
|
});
|
|
}
|
|
|
|
|
|
function changeType() {
|
|
var key = selectedKey(),
|
|
t = {};
|
|
|
|
if (!key) return;
|
|
var val = tagValue(utilGetSetValue(typeInput));
|
|
t[key] = val;
|
|
if (val !== 'no') oldType[key] = val;
|
|
dispatch.call('change', this, t);
|
|
}
|
|
|
|
|
|
function changeLayer() {
|
|
// note: don't use utilGetSetValue here because we want 0 to be falsy.
|
|
var t = { layer: layerInput.node().value || undefined };
|
|
dispatch.call('change', this, t);
|
|
}
|
|
|
|
|
|
function changeRadio() {
|
|
var t = {},
|
|
activeKey;
|
|
|
|
if (field.key) {
|
|
t[field.key] = undefined;
|
|
}
|
|
|
|
radios.each(function(d) {
|
|
var active = d3.select(this).property('checked');
|
|
if (active) activeKey = d;
|
|
|
|
if (field.key) {
|
|
if (active) t[field.key] = d;
|
|
} else {
|
|
var val = oldType[activeKey] || 'yes';
|
|
t[d] = active ? val : undefined;
|
|
}
|
|
});
|
|
|
|
if (field.type === 'structureRadio') {
|
|
if (activeKey === 'bridge') {
|
|
t.layer = '1';
|
|
} else if (activeKey === 'tunnel') {
|
|
t.layer = '-1';
|
|
} else {
|
|
t.layer = undefined;
|
|
}
|
|
}
|
|
|
|
dispatch.call('change', this, t);
|
|
}
|
|
|
|
|
|
radio.tags = function(tags) {
|
|
function checked(d) {
|
|
if (field.key) {
|
|
return tags[field.key] === d;
|
|
} else {
|
|
return !!(tags[d] && tags[d].toLowerCase() !== 'no');
|
|
}
|
|
}
|
|
|
|
labels.classed('active', checked);
|
|
radios.property('checked', checked);
|
|
|
|
var selection = radios.filter(function() { return this.checked; });
|
|
var typeVal = '';
|
|
|
|
if (selection.empty()) {
|
|
placeholder.text(t('inspector.none'));
|
|
} else {
|
|
placeholder.text(selection.attr('value'));
|
|
typeVal = oldType[selection.datum()] = tags[selection.datum()];
|
|
}
|
|
|
|
if (field.type === 'structureRadio') {
|
|
wrap.call(structureExtras);
|
|
utilGetSetValue(typeInput, displayValue(typeVal) || '');
|
|
utilGetSetValue(layerInput, tags.layer || '');
|
|
}
|
|
};
|
|
|
|
|
|
radio.focus = function() {
|
|
radios.node().focus();
|
|
};
|
|
|
|
|
|
radio.entity = function(_) {
|
|
if (!arguments.length) return entity;
|
|
entity = _;
|
|
oldType = {};
|
|
return radio;
|
|
};
|
|
|
|
|
|
return utilRebind(radio, dispatch, 'on');
|
|
}
|