Fields mostly working (but not dispatch/update)

This commit is contained in:
Bryan Housel
2016-09-20 22:41:05 -04:00
parent c5a8bcc3a6
commit 0ea59a043d
13 changed files with 227 additions and 82 deletions
+4 -2
View File
@@ -1163,8 +1163,10 @@ button.save.has-count .count::before {
font-weight: bold;
}
.more-fields label { padding: 5px 10px 5px 0; }
.more-fields input { width: 50%;}
.more-fields input {
margin-left: 10px;
width: 50%;
}
/* preset form access */
+2 -2
View File
@@ -223,10 +223,10 @@ export function d3combobox() {
.remove();
options.enter()
.append('a')
.append('a')
.attr('class', 'combobox-option')
.text(function(d) { return d.value; })
.merge(options)
.merge(options)
.attr('title', function(d) { return d.title; })
.classed('selected', function(d, i) { return i === idx; })
.on('mouseover', select)
+9 -1
View File
@@ -19,7 +19,15 @@ export function access(field) {
.append('ul')
.merge(wrap);
items = wrap.select('ul').selectAll('li')
var list = wrap.selectAll('ul')
.data([0]);
list = list.enter()
.append('ul')
.merge(list);
items = list.selectAll('li')
.data(field.keys);
// Enter
+6 -4
View File
@@ -223,12 +223,13 @@ export function combo(field, context) {
if (isMulti) {
container = selection.selectAll('ul').data([0]);
container.enter()
container = container.enter()
.append('ul')
.attr('class', 'form-field-multicombo')
.on('click', function() {
window.setTimeout(function() { input.node().focus(); }, 10);
});
})
.merge(container);
} else {
container = selection;
@@ -237,11 +238,12 @@ export function combo(field, context) {
input = container.selectAll('input')
.data([0]);
input.enter()
input = input.enter()
.append('input')
.attr('type', 'text')
.attr('id', 'preset-input-' + field.id)
.call(initCombo, selection);
.call(initCombo, selection)
.merge(input);
if (isNetwork) {
var center = entity.extent(context.graph()).center();
+29 -11
View File
@@ -3,48 +3,62 @@ import { rebind } from '../../util/rebind';
import { getSetValue } from '../../util/get_set_value';
import { d3combobox } from '../../lib/d3.combobox.js';
export function cycleway(field) {
var dispatch = d3.dispatch('change'),
items;
items = d3.select(null);
function cycleway(selection) {
var wrap = selection.selectAll('.preset-input-wrap')
.data([0]);
wrap.enter().append('div')
wrap = wrap.enter()
.append('div')
.attr('class', 'cf preset-input-wrap')
.append('ul');
.merge(wrap);
items = wrap.select('ul').selectAll('li')
var div = wrap.selectAll('ul')
.data([0]);
div = div.enter()
.append('ul')
.merge(div);
items = div.selectAll('li')
.data(field.keys);
// Enter
var enter = items.enter().append('li')
var enter = items.enter()
.append('li')
.attr('class', function(d) { return 'cf preset-cycleway-' + d; });
enter.append('span')
enter
.append('span')
.attr('class', 'col6 label preset-label-cycleway')
.attr('for', function(d) { return 'preset-input-cycleway-' + d; })
.text(function(d) { return field.t('types.' + d); });
enter.append('div')
enter
.append('div')
.attr('class', 'col6 preset-input-cycleway-wrap')
.append('input')
.attr('type', 'text')
.attr('class', 'preset-input-cycleway')
.attr('id', function(d) { return 'preset-input-cycleway-' + d; })
.each(function(d) {
d3.select(this)
.call(d3combobox()
.data(cycleway.options(d)));
d3.select(this).call(d3combobox().data(cycleway.options(d)));
});
// Update
wrap.selectAll('.preset-input-cycleway')
.on('change', change)
.on('blur', change);
}
function change() {
var inputs = d3.selectAll('.preset-input-cycleway')[0],
left = getSetValue(d3.select(inputs[0])),
@@ -74,6 +88,7 @@ export function cycleway(field) {
dispatch.call('change', this, tag);
}
cycleway.options = function() {
return d3.keys(field.strings.options).map(function(option) {
return {
@@ -83,6 +98,7 @@ export function cycleway(field) {
});
};
cycleway.tags = function(tags) {
getSetValue(items.selectAll('.preset-input-cycleway'), function(d) {
// If cycleway is set, always return that
@@ -94,10 +110,12 @@ export function cycleway(field) {
.attr('placeholder', field.placeholder());
};
cycleway.focus = function() {
items.selectAll('.preset-input-cycleway')
.node().focus();
};
return rebind(cycleway, dispatch, 'on');
}
+18 -6
View File
@@ -13,21 +13,23 @@ export {
};
export function url(field, context) {
var dispatch = d3.dispatch('change'),
input,
entity;
function i(selection) {
var fieldId = 'preset-input-' + field.id;
input = selection.selectAll('input')
.data([0]);
input.enter().append('input')
input = input.enter()
.append('input')
.attr('type', field.type)
.attr('id', fieldId)
.attr('placeholder', field.placeholder() || t('inspector.unknown'));
.attr('placeholder', field.placeholder() || t('inspector.unknown'))
.merge(input);
input
.on('input', change(true))
@@ -49,19 +51,25 @@ export function url(field, context) {
var spinControl = selection.selectAll('.spin-control')
.data([0]);
var enter = spinControl.enter().append('div')
var enter = spinControl.enter()
.append('div')
.attr('class', 'spin-control');
enter.append('button')
enter
.append('button')
.datum(1)
.attr('class', 'increment')
.attr('tabindex', -1);
enter.append('button')
enter
.append('button')
.datum(-1)
.attr('class', 'decrement')
.attr('tabindex', -1);
spinControl = spinControl
.merge(enter);
spinControl.selectAll('button')
.on('click', function(d) {
d3.event.preventDefault();
@@ -72,6 +80,7 @@ export function url(field, context) {
}
}
function change(onInput) {
return function() {
var t = {};
@@ -80,16 +89,19 @@ export function url(field, context) {
};
}
i.entity = function(_) {
if (!arguments.length) return entity;
entity = _;
return i;
};
i.tags = function(tags) {
getSetValue(input, tags[field.key] || '');
};
i.focus = function() {
var node = input.node();
if (node) node.focus();
+17 -7
View File
@@ -20,9 +20,10 @@ export function lanes(field, context) {
var wrap = selection.selectAll('.preset-input-wrap')
.data([0]);
wrap.enter()
wrap = wrap.enter()
.append('div')
.attr('class', 'preset-input-wrap');
.attr('class', 'preset-input-wrap')
.merge(wrap);
var surface = wrap.selectAll('.surface')
.data([0]);
@@ -30,27 +31,34 @@ export function lanes(field, context) {
var d = getDimensions(wrap);
var freeSpace = d[0] - lanesData.lanes.length * LANE_WIDTH * 1.5 + LANE_WIDTH * 0.5;
surface.enter()
surface = surface.enter()
.append('svg')
.attr('width', d[0])
.attr('height', 300)
.attr('class', 'surface');
.attr('class', 'surface')
.merge(surface);
var lanesSelection = surface.selectAll('.lanes')
.data([0]);
lanesSelection.enter()
lanesSelection = lanesSelection.enter()
.append('g')
.attr('class', 'lanes');
.attr('class', 'lanes')
.merge(lanesSelection);
lanesSelection
.attr('transform', function () {
return 'translate(' + (freeSpace / 2) + ', 0)';
});
var lane = lanesSelection.selectAll('.lane')
.data(lanesData.lanes);
lane.exit()
.remove();
var enter = lane.enter()
.append('g')
.attr('class', 'lane');
@@ -86,7 +94,9 @@ export function lanes(field, context) {
.attr('x', 14)
.text('▼');
lane.exit().remove();
lane = lane
.merge(enter);
lane
.attr('transform', function(d) {
+39 -15
View File
@@ -11,17 +11,22 @@ import { SuggestNames } from '../../util/index';
import { wikipedia as wikipediaService } from '../../services/index';
import { suggestions, wikipedia as wikipediaData } from '../../../data/index';
export function localized(field, context) {
var dispatch = d3.dispatch('change', 'input'),
wikipedia = wikipediaService.init(),
input, localizedInputs, wikiTitles,
input = d3.select(null),
localizedInputs = d3.select(null),
wikiTitles,
entity;
function localized(selection) {
input = selection.selectAll('.localized-main')
.data([0]);
input = input.enter().append('input')
input = input.enter()
.append('input')
.attr('type', 'text')
.attr('id', 'preset-input-' + field.id)
.attr('class', 'localized-main')
@@ -40,6 +45,7 @@ export function localized(field, context) {
.on('blur', change())
.on('change', change());
var translateButton = selection.selectAll('.localized-add')
.data([0]);
@@ -56,6 +62,7 @@ export function localized(field, context) {
translateButton
.on('click', addNew);
localizedInputs = selection.selectAll('.localized-wrap')
.data([0]);
@@ -64,6 +71,7 @@ export function localized(field, context) {
.merge(localizedInputs);
}
function addNew() {
d3.event.preventDefault();
var data = localizedInputs.selectAll('div.entry').data();
@@ -71,12 +79,13 @@ export function localized(field, context) {
var langExists = _.find(data, function(datum) { return datum.lang === defaultLang;});
var isLangEn = defaultLang.indexOf('en') > -1;
if (isLangEn || langExists) {
defaultLang = '';
defaultLang = '';
}
data.push({ lang: defaultLang, value: '' });
localizedInputs.call(render, data);
}
function change(onInput) {
return function() {
var t = {};
@@ -85,7 +94,11 @@ export function localized(field, context) {
};
}
function key(lang) { return field.key + ':' + lang; }
function key(lang) {
return field.key + ':' + lang;
}
function changeLang(d) {
var lang = getSetValue(d3.select(this)),
@@ -114,6 +127,7 @@ export function localized(field, context) {
dispatch.call('change', this, t);
}
function changeValue(d) {
if (!d.lang) return;
var t = {};
@@ -121,6 +135,7 @@ export function localized(field, context) {
dispatch.call('change', this, t);
}
function fetcher(value, cb) {
var v = value.toLowerCase();
@@ -133,10 +148,19 @@ export function localized(field, context) {
}));
}
function render(selection, data) {
var wraps = selection.selectAll('div.entry').
data(data, function(d) { return d.lang; });
wraps.exit()
.transition()
.duration(200)
.style('max-height','0px')
.style('opacity', '0')
.style('top','-10px')
.remove();
var innerWrap = wraps.enter()
.insert('div', ':first-child');
@@ -145,12 +169,14 @@ export function localized(field, context) {
var wrap = d3.select(this);
var langcombo = d3combobox().fetcher(fetcher).minItems(0);
var label = wrap.append('label')
var label = wrap
.append('label')
.attr('class','form-label')
.text(t('translate.localized_translation_label'))
.attr('for','localized-lang');
label.append('button')
label
.append('button')
.attr('class', 'minor remove')
.on('click', function(d){
d3.event.preventDefault();
@@ -167,7 +193,8 @@ export function localized(field, context) {
})
.call(Icon('#operation-delete'));
wrap.append('input')
wrap
.append('input')
.attr('class', 'localized-lang')
.attr('type', 'text')
.attr('placeholder',t('translate.localized_translation_language'))
@@ -175,7 +202,8 @@ export function localized(field, context) {
.on('change', changeLang)
.call(langcombo);
wrap.append('input')
wrap
.append('input')
.on('blur', changeValue)
.on('change', changeValue)
.attr('type', 'text')
@@ -198,13 +226,6 @@ export function localized(field, context) {
.style('overflow', 'visible');
});
wraps.exit()
.transition()
.duration(200)
.style('max-height','0px')
.style('opacity', '0')
.style('top','-10px')
.remove();
var entry = selection.selectAll('.entry');
@@ -217,6 +238,7 @@ export function localized(field, context) {
function(d) { return d.value; });
}
localized.tags = function(tags) {
// Fetch translations from wikipedia
if (tags.wikipedia && !wikiTitles) {
@@ -242,10 +264,12 @@ export function localized(field, context) {
localizedInputs.call(render, postfixed.reverse());
};
localized.focus = function() {
input.node().focus();
};
localized.entity = function(_) {
if (!arguments.length) return entity;
entity = _;
+32 -21
View File
@@ -9,14 +9,15 @@ import { imperial as imperialData } from '../../../data/index';
export function maxspeed(field, context) {
var dispatch = d3.dispatch('change'),
entity,
imperial,
unitInput,
combobox,
input;
isImperial,
unitInput = d3.select(null),
input = d3.select(null),
combobox;
var metricValues = [20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120],
imperialValues = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80];
function maxspeed(selection) {
combobox = d3combobox();
var unitCombobox = d3combobox().data(['km/h', 'mph'].map(comboValues));
@@ -24,20 +25,22 @@ export function maxspeed(field, context) {
input = selection.selectAll('#preset-input-' + field.id)
.data([0]);
input.enter().append('input')
input = input.enter()
.append('input')
.attr('type', 'text')
.attr('id', 'preset-input-' + field.id)
.attr('placeholder', field.placeholder());
.attr('placeholder', field.placeholder())
.call(combobox)
.merge(input);
input
.call(combobox)
.on('change', change)
.on('blur', change);
var childNodes = context.graph().childNodes(context.entity(entity.id)),
loc = childNodes[~~(childNodes.length/2)].loc;
imperial = _.some(imperialData.features, function(f) {
isImperial = _.some(imperialData.features, function(f) {
return _.some(f.geometry.coordinates, function(d) {
return pointInPolygon(loc, d);
});
@@ -46,29 +49,33 @@ export function maxspeed(field, context) {
unitInput = selection.selectAll('input.maxspeed-unit')
.data([0]);
unitInput.enter().append('input')
unitInput = unitInput.enter()
.append('input')
.attr('type', 'text')
.attr('class', 'maxspeed-unit');
.attr('class', 'maxspeed-unit')
.call(unitCombobox)
.merge(unitInput);
unitInput
.on('blur', changeUnits)
.on('change', changeUnits)
.call(unitCombobox);
.on('change', changeUnits);
function changeUnits() {
imperial = getSetValue(unitInput) === 'mph';
getSetValue(unitInput, imperial ? 'mph' : 'km/h');
isImperial = getSetValue(unitInput) === 'mph';
getSetValue(unitInput, isImperial ? 'mph' : 'km/h');
setSuggestions();
change();
}
}
function setSuggestions() {
combobox.data((imperial ? imperialValues : metricValues).map(comboValues));
getSetValue(unitInput, imperial ? 'mph' : 'km/h');
combobox.data((isImperial ? imperialValues : metricValues).map(comboValues));
getSetValue(unitInput, isImperial ? 'mph' : 'km/h');
}
function comboValues(d) {
return {
value: d.toString(),
@@ -76,13 +83,14 @@ export function maxspeed(field, context) {
};
}
function change() {
var tag = {},
value = getSetValue(input);
if (!value) {
tag[field.key] = undefined;
} else if (isNaN(value) || !imperial) {
} else if (isNaN(value) || !isImperial) {
tag[field.key] = value;
} else {
tag[field.key] = value + ' mph';
@@ -91,28 +99,31 @@ export function maxspeed(field, context) {
dispatch.call('change', this, tag);
}
maxspeed.tags = function(tags) {
var value = tags[field.key];
if (value && value.indexOf('mph') >= 0) {
value = parseInt(value, 10);
imperial = true;
isImperial = true;
} else if (value) {
imperial = false;
isImperial = false;
}
setSuggestions();
getSetValue(input, value || '');
};
maxspeed.focus = function() {
input.node().focus();
};
maxspeed.entity = function(_) {
entity = _;
};
return rebind(maxspeed, dispatch, 'on');
}
+23 -5
View File
@@ -2,9 +2,13 @@ import * as d3 from 'd3';
import { rebind } from '../../util/rebind';
import { t } from '../../util/locale';
export function radio(field) {
var dispatch = d3.dispatch('change'),
labels, radios, placeholder;
placeholder = d3.select(null),
labels = d3.select(null),
radios = d3.select(null);
function radio(selection) {
selection.classed('preset-radio', true);
@@ -12,18 +16,25 @@ export function radio(field) {
var wrap = selection.selectAll('.preset-input-wrap')
.data([0]);
var buttonWrap = wrap.enter().append('div')
var enter = wrap.enter()
.append('div')
.attr('class', 'preset-input-wrap toggle-list');
buttonWrap.append('span')
enter
.append('span')
.attr('class', 'placeholder');
placeholder = selection.selectAll('.placeholder');
wrap = wrap
.merge(enter);
placeholder = wrap.selectAll('.placeholder');
labels = wrap.selectAll('label')
.data(field.options || field.keys);
var enter = labels.enter().append('label');
enter = labels.enter()
.append('label');
enter.append('input')
.attr('type', 'radio')
@@ -34,10 +45,14 @@ export function radio(field) {
enter.append('span')
.text(function(d) { return field.t('options.' + d, { 'default': d }); });
labels = labels
.merge(enter);
radios = labels.selectAll('input')
.on('change', change);
}
function change() {
var t = {};
if (field.key) t[field.key] = undefined;
@@ -52,6 +67,7 @@ export function radio(field) {
dispatch.call('change', this, t);
}
radio.tags = function(tags) {
function checked(d) {
if (field.key) {
@@ -71,9 +87,11 @@ export function radio(field) {
}
};
radio.focus = function() {
radios.node().focus();
};
return rebind(radio, dispatch, 'on');
}
+14 -1
View File
@@ -9,12 +9,14 @@ import { RestrictTurn, UnrestrictTurn, } from '../../actions/index';
import { Entity } from '../../core/index';
import { Hover } from '../../behavior/index';
export function restrictions(field, context) {
var dispatch = d3.dispatch('change'),
hover = Hover(context),
vertexID,
fromNodeID;
function restrictions(selection) {
// if form field is hidden or has detached from dom, clean up.
if (!d3.select('.inspector-wrap.inspector-hidden').empty() || !selection.node().parentNode) {
@@ -65,6 +67,9 @@ export function restrictions(field, context) {
.call(hover);
wrap = wrap
.merge(enter);
var surface = wrap.selectAll('.surface')
.call(setDimensions, d)
.call(drawVertices, graph, [vertex], filter, extent, z)
@@ -97,6 +102,7 @@ export function restrictions(field, context) {
render();
});
function click() {
var datum = d3.event.target.__data__;
if (datum instanceof Entity) {
@@ -115,6 +121,7 @@ export function restrictions(field, context) {
}
}
function mouseover() {
var datum = d3.event.target.__data__;
if (datum instanceof Turn) {
@@ -137,16 +144,18 @@ export function restrictions(field, context) {
wrap.selectAll('.restriction-help')
.text(t('operations.restriction.help.' +
(datum.restriction ? 'toggle_off' : 'toggle_on'),
{restriction: preset.name()}));
{ restriction: preset.name() }));
}
}
function mouseout() {
wrap.selectAll('.restriction-help')
.text(t('operations.restriction.help.' +
(fromNodeID ? 'toggle' : 'select')));
}
function render() {
if (context.hasEntity(vertexID)) {
restrictions(selection);
@@ -154,6 +163,7 @@ export function restrictions(field, context) {
}
}
restrictions.entity = function(_) {
if (!vertexID || vertexID !== _.id) {
fromNodeID = null;
@@ -161,9 +171,11 @@ export function restrictions(field, context) {
}
};
restrictions.tags = function() {};
restrictions.focus = function() {};
restrictions.off = function(selection) {
selection.selectAll('.surface')
.call(hover.off)
@@ -178,5 +190,6 @@ export function restrictions(field, context) {
.on('resize.restrictions', null);
};
return rebind(restrictions, dispatch, 'on');
}
+11 -3
View File
@@ -3,18 +3,22 @@ import { getSetValue } from '../../util/get_set_value';
import { rebind } from '../../util/rebind';
import { t } from '../../util/locale';
export function textarea(field) {
var dispatch = d3.dispatch('change'),
input;
input = d3.select(null);
function textarea(selection) {
input = selection.selectAll('textarea')
.data([0]);
input.enter().append('textarea')
input.enter()
.append('textarea')
.attr('id', 'preset-input-' + field.id)
.attr('placeholder', field.placeholder() || t('inspector.unknown'))
.attr('maxlength', 255);
.attr('maxlength', 255)
.merge(input);
input
.on('input', change(true))
@@ -22,6 +26,7 @@ export function textarea(field) {
.on('change', change());
}
function change(onInput) {
return function() {
var t = {};
@@ -30,13 +35,16 @@ export function textarea(field) {
};
}
textarea.tags = function(tags) {
getSetValue(input, tags[field.key] || '');
};
textarea.focus = function() {
input.node().focus();
};
return rebind(textarea, dispatch, 'on');
}
+23 -4
View File
@@ -14,11 +14,16 @@ import {
wikidata as wikidataService
} from '../../services/index';
export function wikipedia(field, context) {
var dispatch = d3.dispatch('change'),
wikipedia = wikipediaService.init(),
wikidata = wikidataService.init(),
link, entity, lang, title;
link = d3.select(null),
lang = d3.select(null),
title = d3.select(null),
entity;
function wiki(selection) {
var langcombo = d3combobox()
@@ -47,10 +52,12 @@ export function wikipedia(field, context) {
});
});
lang = selection.selectAll('input.wiki-lang')
.data([0]);
lang = lang.enter().append('input')
lang = lang.enter()
.append('input')
.attr('type', 'text')
.attr('class', 'wiki-lang')
.attr('placeholder', t('translate.localized_translation_language'))
@@ -63,10 +70,12 @@ export function wikipedia(field, context) {
.on('blur', changeLang)
.on('change', changeLang);
title = selection.selectAll('input.wiki-title')
.data([0]);
title = title.enter().append('input')
title = title.enter()
.append('input')
.attr('type', 'text')
.attr('class', 'wiki-title')
.attr('id', 'preset-input-' + field.id)
@@ -77,10 +86,12 @@ export function wikipedia(field, context) {
.on('blur', blur)
.on('change', change);
link = selection.selectAll('a.wiki-link')
.data([0]);
link = link.enter().append('a')
link = link.enter()
.append('a')
.attr('class', 'wiki-link button-input-action minor')
.attr('tabindex', -1)
.attr('target', '_blank')
@@ -88,6 +99,7 @@ export function wikipedia(field, context) {
.merge(link);
}
function language() {
var value = getSetValue(lang).toLowerCase();
var locale = Detect().locale.toLowerCase();
@@ -100,15 +112,18 @@ export function wikipedia(field, context) {
}) || localeLanguage || ['English', 'English', 'en'];
}
function changeLang() {
getSetValue(lang, language()[1]);
change(true);
}
function blur() {
change(true);
}
function change(skipWikidata) {
var value = getSetValue(title),
m = value.match(/https?:\/\/([-a-z]+)\.wikipedia\.org\/(?:wiki|\1-[-a-z]+)\/([^#]+)(?:#(.+))?/),
@@ -173,6 +188,7 @@ export function wikipedia(field, context) {
});
}
wiki.tags = function(tags) {
var value = tags[field.key] || '',
m = value.match(/([^:]+):([^#]+)(?:#(.+))?/),
@@ -204,15 +220,18 @@ export function wikipedia(field, context) {
}
};
wiki.entity = function(_) {
if (!arguments.length) return entity;
entity = _;
return wiki;
};
wiki.focus = function() {
title.node().focus();
};
return rebind(wiki, dispatch, 'on');
}