mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-18 14:45:12 +02:00
Merge branch 'presets'
This commit is contained in:
+7
-9
@@ -139,21 +139,19 @@
|
||||
<body>
|
||||
<div id='foo'><input /></div>
|
||||
<div id='bar'><input /></div>
|
||||
<div id="iD"></div><script>
|
||||
<input />
|
||||
<div id="iD"><script>
|
||||
var options = d3.range(0, 50).map(function(i) {
|
||||
return {
|
||||
value: i * 10,
|
||||
title: i * 10
|
||||
value: '' + (i * 10),
|
||||
title: '' + (i * 10)
|
||||
};
|
||||
});
|
||||
|
||||
d3.select('#foo').call(d3.combobox()
|
||||
.data(function(selection, cb) {
|
||||
cb(options);
|
||||
}));
|
||||
.data(options));
|
||||
d3.select('#bar').call(d3.combobox()
|
||||
.data(function(selection, cb) {
|
||||
cb(options);
|
||||
}));
|
||||
.data(options));
|
||||
</script></body>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
+106
-27
@@ -95,7 +95,10 @@ a:hover {
|
||||
}
|
||||
|
||||
textarea,
|
||||
input[type=text] {
|
||||
input[type=text],
|
||||
input[type=url],
|
||||
input[type=tel],
|
||||
input[type=email] {
|
||||
background-color: white;
|
||||
border:1px solid #ccc;
|
||||
padding:10px;
|
||||
@@ -508,7 +511,6 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;}
|
||||
.inspector-wrap {
|
||||
opacity:0;
|
||||
display:none;
|
||||
padding-left: 10px;
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
@@ -522,6 +524,26 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;}
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.inspector-inner.message {
|
||||
padding: 20px;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.inspector-inner.type {
|
||||
z-index:1;
|
||||
position:relative;
|
||||
}
|
||||
|
||||
.inspector-inner.type .preset-icon {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.inspector-inner.type .preset-name {
|
||||
display: inline-block;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.inspector-inner.head {
|
||||
z-index:1;
|
||||
position:relative;
|
||||
@@ -533,11 +555,6 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;}
|
||||
display: inline-block
|
||||
}
|
||||
|
||||
.inspector-inner.tag-wrap {
|
||||
max-height: 200px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.inspector-toggle {
|
||||
color:#fff;
|
||||
width: 100%;
|
||||
@@ -548,6 +565,8 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;}
|
||||
|
||||
.inspector-body {
|
||||
position:relative;
|
||||
max-height: 400px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.tag-row {
|
||||
@@ -562,6 +581,10 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;}
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
.input-wrap-position {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tag-row input {
|
||||
width: 50%;
|
||||
border-left: 0;
|
||||
@@ -579,18 +602,6 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;}
|
||||
border-left: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.input-wrap::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 9px;
|
||||
top: 14px;
|
||||
height: 0;
|
||||
width: 0;
|
||||
border-top: 5px solid #ccc;
|
||||
border-left: 5px solid transparent;
|
||||
border-right: 5px solid transparent;
|
||||
}
|
||||
|
||||
.tag-row button {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
@@ -632,6 +643,31 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;}
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Preset grid */
|
||||
/* temp */
|
||||
|
||||
.preset-grid {
|
||||
max-height: 360px;
|
||||
}
|
||||
|
||||
.preset-grid .grid-entry {
|
||||
float: left;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background: red;
|
||||
color: black;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.preset-grid-search-wrap {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.preset-grid-search {
|
||||
width: 100%;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
/* Map Controls */
|
||||
|
||||
.map-control {
|
||||
@@ -1419,6 +1455,41 @@ a.success-action {
|
||||
.save .label, .apply .label, .cancel .label { display: block;}
|
||||
}
|
||||
|
||||
.preset-section.cf,
|
||||
.inspector-preset.cf,
|
||||
.preset-section-input.cf {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.preset-search-input {
|
||||
width:100%;
|
||||
}
|
||||
|
||||
.preset-search-input input {
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.preset-search-result {
|
||||
padding: 0px 10px;
|
||||
height:30px;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.preset-label {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.preset-fav button.fav {
|
||||
height: 30px;
|
||||
margin: 5px;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.preset-input input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.combobox {
|
||||
width:155px;
|
||||
z-index: 9999;
|
||||
@@ -1431,7 +1502,7 @@ div.combobox {
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
div.combobox a {
|
||||
.combobox a {
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
cursor: pointer;
|
||||
@@ -1442,18 +1513,26 @@ div.combobox a {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
div.combobox a:hover,
|
||||
div.combobox a.selected {
|
||||
.combobox a:hover,
|
||||
.combobox a.selected {
|
||||
background: #e1e8ff;
|
||||
color: #154dff;
|
||||
}
|
||||
|
||||
div.combobox a:first-child {
|
||||
.combobox a:first-child {
|
||||
border-top: 0;
|
||||
}
|
||||
|
||||
div.combobox-carat {
|
||||
cursor: pointer;
|
||||
padding:0 5px;
|
||||
vertical-align:middle;
|
||||
.combobox-carat::after {
|
||||
display:block;
|
||||
content: '';
|
||||
cursor:url(../img/cursor-pointer.png) 6 1, auto;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 5px;
|
||||
height: 0;
|
||||
width: 0;
|
||||
border-top: 5px solid #ccc;
|
||||
border-left: 5px solid transparent;
|
||||
border-right: 5px solid transparent;
|
||||
}
|
||||
|
||||
+15
-4
@@ -18,6 +18,7 @@
|
||||
<script src='js/lib/ohauth.js'></script>
|
||||
<script src='js/lib/jxon.js'></script>
|
||||
<script src='js/lib/d3.typeahead.js'></script>
|
||||
<script src='js/lib/d3.combobox.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>
|
||||
@@ -30,6 +31,7 @@
|
||||
<script src='js/id/id.js'></script>
|
||||
<script src='js/id/util.js'></script>
|
||||
<script src='js/id/oauth.js'></script>
|
||||
<script src='js/id/presetdata.js'></script>
|
||||
<script src='js/id/services/taginfo.js'></script>
|
||||
|
||||
<script src='data/data.js'></script>
|
||||
@@ -79,11 +81,16 @@
|
||||
<script src='js/id/ui/restore.js'></script>
|
||||
<script src='js/id/ui/tag_reference.js'></script>
|
||||
<script src='js/id/ui/key_reference.js'></script>
|
||||
<script src='js/id/ui/preset.js'></script>
|
||||
<script src='js/id/ui/presetsearch.js'></script>
|
||||
<script src='js/id/ui/presetfavs.js'></script>
|
||||
<script src='js/id/ui/lasso.js'></script>
|
||||
<script src='js/id/ui/source_switch.js'></script>
|
||||
<script src='js/id/ui/toggle.js'></script>
|
||||
<script src='js/id/ui/undo_redo.js'></script>
|
||||
<script src='js/id/ui/zoom.js'></script>
|
||||
<script src='js/id/ui/taglist.js'></script>
|
||||
<script src='js/id/ui/presetgrid.js'></script>
|
||||
|
||||
<script src='js/id/actions.js'></script>
|
||||
<script src="js/id/actions/add_midpoint.js"></script>
|
||||
@@ -171,11 +178,15 @@
|
||||
var id = iD();
|
||||
|
||||
d3.json('keys.json', function(err, keys) {
|
||||
id.connection()
|
||||
.keys(keys);
|
||||
d3.json('presets/presets_josm.json', function(err, presets_data) {
|
||||
|
||||
d3.select("#iD")
|
||||
.call(id.ui())
|
||||
id.connection()
|
||||
.keys(keys)
|
||||
.presetData(iD.presetData().data(presets_data));
|
||||
|
||||
d3.select("#iD")
|
||||
.call(id.ui())
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ iD.Connection = function(context) {
|
||||
url = 'http://www.openstreetmap.org',
|
||||
connection = {},
|
||||
user = {},
|
||||
version,
|
||||
presetData = iD.presetData(),
|
||||
keys,
|
||||
inflight = {},
|
||||
loadedTiles = {},
|
||||
@@ -327,6 +329,12 @@ iD.Connection = function(context) {
|
||||
return connection;
|
||||
};
|
||||
|
||||
connection.presetData = function(_) {
|
||||
if (!arguments.length) return presetData;
|
||||
presetData = _;
|
||||
return connection;
|
||||
};
|
||||
|
||||
connection.authenticate = function(callback) {
|
||||
function done(err, res) {
|
||||
event.auth();
|
||||
|
||||
@@ -83,7 +83,9 @@ iD.modes.Select = function(context, selection, initial) {
|
||||
}), true));
|
||||
|
||||
if (entity) {
|
||||
inspector.context(context);
|
||||
inspector
|
||||
.context(context)
|
||||
.presetData(context.connection().presetData());
|
||||
|
||||
context.container()
|
||||
.select('.inspector-wrap')
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
iD.presetData = function() {
|
||||
var presets = {},
|
||||
data = [];
|
||||
|
||||
presets.data = function(_) {
|
||||
if (!arguments.length) return data;
|
||||
data = _;
|
||||
return presets;
|
||||
};
|
||||
|
||||
presets.favs = function() {
|
||||
return data.filter(function(d) {
|
||||
return d.favorite;
|
||||
});
|
||||
};
|
||||
|
||||
presets.match = function(entity) {
|
||||
var type = entity.type == 'node' ? 'node' : entity.geometry();
|
||||
return data.filter(function(d) {
|
||||
return _.contains(d.type, type);
|
||||
});
|
||||
};
|
||||
|
||||
presets.matchTags = function(entity) {
|
||||
var tags, count, best,
|
||||
maxcount = 0,
|
||||
type = entity.type == 'node' ? 'node' : entity.geometry();
|
||||
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
count = 0;
|
||||
tags = data[i].tags;
|
||||
if (!_.contains(data[i].type, type)) continue;
|
||||
for (var k in tags) {
|
||||
if (entity.tags[k] == tags[k]) count++;
|
||||
}
|
||||
if (count > maxcount) best = data[i], maxcount = count;
|
||||
}
|
||||
return best;
|
||||
};
|
||||
|
||||
return presets;
|
||||
};
|
||||
+113
-249
@@ -1,53 +1,112 @@
|
||||
iD.ui.Inspector = function() {
|
||||
var event = d3.dispatch('changeTags', 'close'),
|
||||
var event = d3.dispatch('changeTags', 'close', 'change'),
|
||||
taginfo = iD.taginfo(),
|
||||
presetData = iD.presetData(),
|
||||
initial = false,
|
||||
context,
|
||||
tagList;
|
||||
expert = false,
|
||||
inspectorbody,
|
||||
presetUI,
|
||||
tagList,
|
||||
context;
|
||||
|
||||
function inspector(selection) {
|
||||
|
||||
var entity = selection.datum();
|
||||
presetMatch = presetData.matchTags(entity);
|
||||
|
||||
var inspector = selection.append('div')
|
||||
.attr('class','inspector content hide');
|
||||
var iwrap = selection.append('div')
|
||||
.attr('class','inspector content hide'),
|
||||
messagewrap = iwrap.append('div')
|
||||
.attr('class', 'message inspector-inner fillL2'),
|
||||
message = messagewrap.append('h4');
|
||||
|
||||
inspector.append('div')
|
||||
.attr('class', 'head inspector-inner fillL')
|
||||
.call(drawHead);
|
||||
|
||||
var inspectorbody = inspector.append('div')
|
||||
.attr('class', 'inspector-body');
|
||||
|
||||
var inspectorwrap = inspectorbody.append('div')
|
||||
.attr('class', 'inspector-inner tag-wrap fillL2');
|
||||
|
||||
inspectorwrap.append('h4')
|
||||
.text(t('inspector.edit_tags'));
|
||||
|
||||
tagList = inspectorwrap.append('ul');
|
||||
|
||||
var newTag = inspectorwrap.append('button')
|
||||
.attr('class', 'add-tag');
|
||||
|
||||
newTag.on('click', function () {
|
||||
addTag();
|
||||
focusNewKey();
|
||||
});
|
||||
|
||||
newTag.append('span')
|
||||
.attr('class', 'icon icon-pre-text plus');
|
||||
|
||||
newTag.append('span')
|
||||
.attr('class', 'label')
|
||||
.text(t('inspector.new_tag'));
|
||||
|
||||
drawTags(entity.tags);
|
||||
|
||||
inspectorbody.append('div')
|
||||
inspectorbody = iwrap.append('div')
|
||||
.attr('class', 'inspector-body'),
|
||||
iwrap.append('div')
|
||||
.attr('class', 'inspector-buttons pad1 fillD')
|
||||
.call(drawButtons);
|
||||
|
||||
inspector.call(iD.ui.Toggle(true));
|
||||
if (initial) {
|
||||
inspectorbody.call(iD.ui.PresetGrid()
|
||||
.presetData(presetData)
|
||||
.entity(selection.datum())
|
||||
.on('choose', function(preset) {
|
||||
inspectorbody.call(drawEditor, entity, preset);
|
||||
}));
|
||||
} else {
|
||||
inspectorbody.call(drawEditor, entity, presetMatch);
|
||||
}
|
||||
|
||||
iwrap.call(iD.ui.Toggle(true));
|
||||
}
|
||||
|
||||
function drawEditor(selection, entity, presetMatch) {
|
||||
selection.html('');
|
||||
|
||||
var editorwrap = selection.append('div')
|
||||
.attr('class', 'inspector-inner tag-wrap fillL2');
|
||||
|
||||
var typewrap = editorwrap.append('div')
|
||||
.attr('class', 'type inspector-inner fillL');
|
||||
|
||||
typewrap.append('h4')
|
||||
.text('Type');
|
||||
|
||||
typewrap.append('img')
|
||||
.attr('class', 'preset-icon');
|
||||
|
||||
typewrap.append('h3')
|
||||
.attr('class', 'preset-name')
|
||||
.text(presetMatch ? presetMatch.name : '');
|
||||
|
||||
|
||||
var namewrap = editorwrap.append('div')
|
||||
.attr('class', 'head inspector-inner fillL'),
|
||||
h2 = namewrap.append('h2');
|
||||
|
||||
h2.append('span')
|
||||
.attr('class', 'icon big icon-pre-text big-' + entity.geometry(context.graph()));
|
||||
|
||||
var name = h2.append('input')
|
||||
.attr('placeholder', 'name')
|
||||
.property('value', function() {
|
||||
return entity.tags.name || '';
|
||||
})
|
||||
.on('keyup', function() {
|
||||
var tags = inspector.tags();
|
||||
tags.name = this.value;
|
||||
inspector.tags(tags);
|
||||
event.change();
|
||||
});
|
||||
|
||||
event.on('change.name', function() {
|
||||
var tags = inspector.tags();
|
||||
name.property('value', tags.name);
|
||||
});
|
||||
|
||||
|
||||
presetUI = iD.ui.preset()
|
||||
.on('change', function(tags) {
|
||||
event.change();
|
||||
});
|
||||
|
||||
tagList = iD.ui.Taglist()
|
||||
.context(context)
|
||||
.on('change', function(tags) {
|
||||
event.change();
|
||||
});
|
||||
|
||||
var inspectorpreset = editorwrap.append('div')
|
||||
.attr('class', 'inspector-preset cf');
|
||||
|
||||
if (presetMatch && !expert) {
|
||||
inspectorpreset.call(presetUI
|
||||
.preset(presetMatch));
|
||||
}
|
||||
|
||||
var taglistwrap = editorwrap.append('div').call(tagList);
|
||||
|
||||
inspector.tags(entity.tags);
|
||||
}
|
||||
|
||||
function drawHead(selection) {
|
||||
@@ -80,210 +139,16 @@ iD.ui.Inspector = function() {
|
||||
.attr('href', 'http://www.openstreetmap.org/browse/' + entity.type + '/' + entity.osmId())
|
||||
.attr('target', '_blank')
|
||||
.text(t('inspector.view_on_osm'));
|
||||
}
|
||||
|
||||
function drawTags(tags) {
|
||||
var entity = tagList.datum();
|
||||
|
||||
tags = d3.entries(tags);
|
||||
|
||||
if (!tags.length) {
|
||||
tags = [{key: '', value: ''}];
|
||||
}
|
||||
|
||||
var li = tagList.html('')
|
||||
.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');
|
||||
|
||||
inputs.append('input')
|
||||
.property('type', 'text')
|
||||
.attr('class', 'key')
|
||||
.attr('maxlength', 255)
|
||||
.property('value', function(d) { return d.key; })
|
||||
.on('change', function(d) { d.key = this.value; });
|
||||
|
||||
inputs.append('input')
|
||||
.property('type', 'text')
|
||||
.attr('class', 'value')
|
||||
.attr('maxlength', 255)
|
||||
.property('value', function(d) { return d.value; })
|
||||
.on('change', function(d) { d.value = this.value; })
|
||||
.on('keydown.push-more', pushMore);
|
||||
|
||||
inputs.each(bindTypeahead);
|
||||
|
||||
var removeBtn = row.append('button')
|
||||
.attr('tabindex', -1)
|
||||
.attr('class','remove minor')
|
||||
.on('click', removeTag);
|
||||
|
||||
removeBtn.append('span')
|
||||
.attr('class', 'icon delete');
|
||||
|
||||
function findLocal(docs) {
|
||||
var locale = iD.detect().locale.toLowerCase(),
|
||||
localized;
|
||||
|
||||
localized = _.find(docs, function(d) {
|
||||
return d.lang.toLowerCase() === locale;
|
||||
});
|
||||
if (localized) return localized;
|
||||
|
||||
// try the non-regional version of a language, like
|
||||
// 'en' if the language is 'en-US'
|
||||
if (locale.indexOf('-') !== -1) {
|
||||
var first = locale.split('-')[0];
|
||||
localized = _.find(docs, function(d) {
|
||||
return d.lang.toLowerCase() === first;
|
||||
});
|
||||
if (localized) return localized;
|
||||
}
|
||||
|
||||
// finally fall back to english
|
||||
return _.find(docs, function(d) {
|
||||
return d.lang.toLowerCase() === 'en';
|
||||
});
|
||||
}
|
||||
|
||||
function keyValueReference(err, docs) {
|
||||
var local;
|
||||
if (!err && docs) {
|
||||
local = findLocal(docs);
|
||||
}
|
||||
if (local) {
|
||||
var types = [];
|
||||
if (local.on_area) types.push('area');
|
||||
if (local.on_node) types.push('point');
|
||||
if (local.on_way) types.push('line');
|
||||
local.types = types;
|
||||
iD.ui.modal(context.container())
|
||||
.select('.content')
|
||||
.datum(local)
|
||||
.call(iD.ui.tagReference);
|
||||
} else {
|
||||
iD.ui.flash(context.container())
|
||||
.select('.content')
|
||||
.append('h3')
|
||||
.text(t('inspector.no_documentation_combination'));
|
||||
}
|
||||
}
|
||||
|
||||
function keyReference(err, values, params) {
|
||||
if (!err && values.length) {
|
||||
iD.ui.modal(context.container())
|
||||
.select('.content')
|
||||
.datum({
|
||||
data: values,
|
||||
title: 'Key:' + params.key,
|
||||
geometry: params.geometry
|
||||
})
|
||||
.call(iD.ui.keyReference);
|
||||
} else {
|
||||
iD.ui.flash(context.container())
|
||||
.select('.content')
|
||||
.append('h3')
|
||||
.text(t('inspector.no_documentation_key'));
|
||||
}
|
||||
}
|
||||
|
||||
var helpBtn = row.append('button')
|
||||
.attr('tabindex', -1)
|
||||
.attr('class', 'tag-help minor')
|
||||
.on('click', function(d) {
|
||||
var params = _.extend({}, d, {
|
||||
geometry: entity.geometry(context.graph())
|
||||
});
|
||||
if (d.key && d.value) {
|
||||
taginfo.docs(params, keyValueReference);
|
||||
} else if (d.key) {
|
||||
taginfo.values(params, keyReference);
|
||||
}
|
||||
var expertButton = selection.append('button')
|
||||
.attr('class', 'apply')
|
||||
.text('Tag view')
|
||||
.on('click', function() {
|
||||
expert = !expert;
|
||||
expertButton.text(expert ? 'Preset view' : 'Tag view');
|
||||
inspectorbody.call(drawEditor);
|
||||
});
|
||||
|
||||
helpBtn.append('span')
|
||||
.attr('class', 'icon inspect');
|
||||
|
||||
if (initial && tags.length === 1 &&
|
||||
tags[0].key === '' && tags[0].value === '') {
|
||||
focusNewKey();
|
||||
}
|
||||
|
||||
return li;
|
||||
}
|
||||
|
||||
function pushMore() {
|
||||
if (d3.event.keyCode === 9 &&
|
||||
tagList.selectAll('li:last-child input.value').node() === this) {
|
||||
addTag();
|
||||
focusNewKey();
|
||||
d3.event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
function bindTypeahead() {
|
||||
var entity = tagList.datum(),
|
||||
geometry = entity.geometry(context.graph()),
|
||||
row = d3.select(this),
|
||||
key = row.selectAll('.key'),
|
||||
value = row.selectAll('.value');
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
key.call(d3.typeahead()
|
||||
.data(_.debounce(function(_, callback) {
|
||||
taginfo.keys({
|
||||
geometry: geometry,
|
||||
query: key.property('value')
|
||||
}, function(err, data) {
|
||||
if (!err) callback(sort(key.property('value'), data));
|
||||
});
|
||||
}, 500)));
|
||||
|
||||
value.call(d3.typeahead()
|
||||
.data(_.debounce(function(_, callback) {
|
||||
taginfo.values({
|
||||
key: key.property('value'),
|
||||
geometry: geometry,
|
||||
query: value.property('value')
|
||||
}, function(err, data) {
|
||||
if (!err) callback(sort(value.property('value'), data));
|
||||
});
|
||||
}, 500)));
|
||||
}
|
||||
|
||||
function focusNewKey() {
|
||||
tagList.selectAll('li:last-child input.key').node().focus();
|
||||
}
|
||||
|
||||
function addTag() {
|
||||
var tags = inspector.tags();
|
||||
tags[''] = '';
|
||||
drawTags(tags);
|
||||
}
|
||||
|
||||
function removeTag(d) {
|
||||
var tags = inspector.tags();
|
||||
delete tags[d.key];
|
||||
drawTags(tags);
|
||||
}
|
||||
|
||||
function apply(entity) {
|
||||
@@ -293,16 +158,10 @@ iD.ui.Inspector = function() {
|
||||
|
||||
inspector.tags = function(tags) {
|
||||
if (!arguments.length) {
|
||||
tags = {};
|
||||
tagList.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;
|
||||
return _.extend(presetUI.tags(), tagList.tags());
|
||||
} else {
|
||||
drawTags(tags);
|
||||
presetUI.change(tags);
|
||||
tagList.tags(_.omit(tags, _.keys(presetUI.tags() || {})));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -311,6 +170,11 @@ iD.ui.Inspector = function() {
|
||||
return inspector;
|
||||
};
|
||||
|
||||
inspector.presetData = function(_) {
|
||||
presetData = _;
|
||||
return inspector;
|
||||
};
|
||||
|
||||
inspector.context = function(_) {
|
||||
context = _;
|
||||
return inspector;
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
iD.ui.preset = function() {
|
||||
var event = d3.dispatch('change'),
|
||||
hidden,
|
||||
sections,
|
||||
exttags,
|
||||
preset;
|
||||
|
||||
function getTags() {
|
||||
var tags = _.clone(preset.tags);
|
||||
sections.selectAll('input,select')
|
||||
.each(function(d) {
|
||||
tags[d.key] = this.value;
|
||||
});
|
||||
return tags;
|
||||
}
|
||||
|
||||
function setTags(tags) {
|
||||
if (!sections) return;
|
||||
sections.selectAll('input,select')
|
||||
.each(function(d) {
|
||||
if (tags[d.key]) {
|
||||
this.value = tags[d.key];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function clean(o) {
|
||||
var out = {};
|
||||
for (var k in o) {
|
||||
if (o[k] !== '') out[k] = o[k];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function key() {
|
||||
var tags = clean(getTags());
|
||||
event.change(tags);
|
||||
}
|
||||
|
||||
// generate form fields for a given field.
|
||||
function input(d) {
|
||||
var i;
|
||||
switch (d.type) {
|
||||
case 'text':
|
||||
i = this.append('input')
|
||||
.attr('type', 'text')
|
||||
.attr('id', 'input-' + d.key)
|
||||
.attr('placeholder', d['default'] || '');
|
||||
break;
|
||||
case 'tel':
|
||||
i = this.append('input')
|
||||
.attr('type', 'tel')
|
||||
.attr('id', 'input-' + d.key)
|
||||
.attr('placeholder', '1-555-555-5555');
|
||||
break;
|
||||
case 'email':
|
||||
i = this.append('input')
|
||||
.attr('type', 'email')
|
||||
.attr('id', 'input-' + d.key)
|
||||
.attr('placeholder', 'email@domain.com');
|
||||
break;
|
||||
case 'url':
|
||||
i = this.append('input')
|
||||
.attr('type', 'url')
|
||||
.attr('id', 'input-' + d.key)
|
||||
.attr('placeholder', 'http://example.com/');
|
||||
break;
|
||||
case 'check':
|
||||
i = this.append('input')
|
||||
.attr('type', 'checkbox')
|
||||
.attr('id', 'input-' + d.key)
|
||||
.each(function() {
|
||||
if (d['default']) {
|
||||
this.attr('checked', 'checked');
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'select':
|
||||
var w = this.append('span').attr('class', 'input-wrap-position');
|
||||
i = w.append('input');
|
||||
w.call(d3.combobox()
|
||||
.data([''].concat(d.values.slice()).map(function(o) {
|
||||
return { value: o, title: o };
|
||||
})));
|
||||
break;
|
||||
}
|
||||
if (i) {
|
||||
i.on('change', key);
|
||||
}
|
||||
}
|
||||
|
||||
function presets(selection) {
|
||||
selection.html('');
|
||||
sections = selection.selectAll('div.preset-section')
|
||||
.data(preset.main)
|
||||
.enter()
|
||||
.append('div')
|
||||
.attr('class', 'preset-section cf');
|
||||
sections.each(function(d) {
|
||||
var s = d3.select(this);
|
||||
var wrap = s.append('div')
|
||||
.attr('class', 'preset-section-input cf');
|
||||
wrap.append('div')
|
||||
.attr('class', 'col4 preset-label')
|
||||
.append('label')
|
||||
.attr('for', 'input-' + d.key)
|
||||
.text(d.text);
|
||||
input.call(wrap.append('div')
|
||||
.attr('class', 'col8 preset-input'), d);
|
||||
});
|
||||
if (exttags) setTags(exttags);
|
||||
}
|
||||
|
||||
presets.preset = function(_) {
|
||||
if (!arguments.length) return preset;
|
||||
preset = _;
|
||||
return presets;
|
||||
};
|
||||
|
||||
presets.change = function(_) {
|
||||
exttags = _;
|
||||
setTags(_);
|
||||
return presets;
|
||||
};
|
||||
|
||||
presets.tags = function() {
|
||||
if (hidden || !preset || !sections) return {};
|
||||
return clean(getTags());
|
||||
};
|
||||
|
||||
return d3.rebind(presets, event, 'on');
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
iD.ui.presetfavs = function() {
|
||||
var event = d3.dispatch('choose'),
|
||||
presetData;
|
||||
|
||||
function favs(selection) {
|
||||
var favData = presetData.favs();
|
||||
|
||||
selection.append('div')
|
||||
.attr('class', 'preset-fav')
|
||||
.selectAll('button.fav')
|
||||
.data(favData)
|
||||
.enter()
|
||||
.append('button')
|
||||
.attr('class', 'fav')
|
||||
.text(function(d) {
|
||||
return d.name;
|
||||
})
|
||||
.on('click', function(d) {
|
||||
event.choose(d);
|
||||
});
|
||||
}
|
||||
|
||||
favs.presetData = function(_) {
|
||||
if (!arguments.length) return presetData;
|
||||
presetData = _;
|
||||
return favs;
|
||||
};
|
||||
|
||||
return d3.rebind(favs, event, 'on');
|
||||
};
|
||||
@@ -0,0 +1,71 @@
|
||||
iD.ui.PresetGrid = function() {
|
||||
var event = d3.dispatch('choose'),
|
||||
entity,
|
||||
presetData;
|
||||
|
||||
function presetgrid(selection) {
|
||||
|
||||
selection.html('');
|
||||
var wrap = selection.append('div')
|
||||
.attr('class', 'fillL');
|
||||
|
||||
var viable = presetData.match(entity);
|
||||
|
||||
var grid = wrap.append('div')
|
||||
.attr('class', 'preset-grid')
|
||||
.call(drawGrid, filter(''));
|
||||
|
||||
var searchwrap = wrap.append('div')
|
||||
.attr('class', 'preset-grid-search-wrap');
|
||||
|
||||
var search = searchwrap.append('input')
|
||||
.attr('class', 'preset-grid-search')
|
||||
.on('keyup', function() {
|
||||
grid.call(drawGrid, filter(search.property('value')));
|
||||
});
|
||||
|
||||
|
||||
function filter(value) {
|
||||
value = value.toLowerCase();
|
||||
return viable.filter(function(v) {
|
||||
return v.name.toLowerCase().indexOf(value) !== -1;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function name(d) { return d.name; }
|
||||
|
||||
function drawGrid(selection, presets) {
|
||||
|
||||
var entries = selection
|
||||
.selectAll('div.grid-entry')
|
||||
.data(presets.slice(0, 12), name);
|
||||
|
||||
entries.enter()
|
||||
.append('div')
|
||||
.attr('class', 'grid-entry')
|
||||
.text(name)
|
||||
.on('click', function(d) {
|
||||
event.choose(d);
|
||||
});
|
||||
|
||||
entries.exit().remove();
|
||||
}
|
||||
|
||||
presetgrid.presetData = function(_) {
|
||||
if (!arguments.length) return presetData;
|
||||
presetData = _;
|
||||
return presetgrid;
|
||||
};
|
||||
|
||||
presetgrid.entity = function(_) {
|
||||
if (!arguments.length) return entity;
|
||||
entity = _;
|
||||
return presetgrid;
|
||||
};
|
||||
|
||||
|
||||
|
||||
return d3.rebind(presetgrid, event, 'on');
|
||||
};
|
||||
@@ -0,0 +1,55 @@
|
||||
iD.ui.presetsearch = function() {
|
||||
var event = d3.dispatch('choose'),
|
||||
entity,
|
||||
presetData;
|
||||
|
||||
function search(selection) {
|
||||
var viable = presetData.match(entity);
|
||||
|
||||
function filter(value) {
|
||||
value = value.toLowerCase();
|
||||
return viable.filter(function(v) {
|
||||
return v.name.toLowerCase().indexOf(value) !== -1;
|
||||
}).map(function(v) {
|
||||
return {
|
||||
title: v.name,
|
||||
value: v.name
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function find(value) {
|
||||
return _.find(viable, function(v) {
|
||||
return v.name == value;
|
||||
});
|
||||
}
|
||||
|
||||
var preset_search_input = selection.append('div')
|
||||
.attr('class', 'preset-search-input')
|
||||
.append('h3')
|
||||
.append('input')
|
||||
.attr('placeholder', 'preset search')
|
||||
.call(d3.typeahead()
|
||||
.autohighlight(true)
|
||||
.data(function(_, callback) {
|
||||
callback(filter(preset_search_input.property('value')));
|
||||
})
|
||||
.on('accept', function() {
|
||||
event.choose(find(preset_search_input.property('value')));
|
||||
}));
|
||||
}
|
||||
|
||||
search.presetData = function(_) {
|
||||
if (!arguments.length) return presetData;
|
||||
presetData = _;
|
||||
return search;
|
||||
};
|
||||
|
||||
search.entity = function(_) {
|
||||
if (!arguments.length) return entity;
|
||||
entity = _;
|
||||
return search;
|
||||
};
|
||||
|
||||
return d3.rebind(search, event, 'on');
|
||||
};
|
||||
@@ -0,0 +1,263 @@
|
||||
iD.ui.Taglist = function() {
|
||||
var event = d3.dispatch('change'),
|
||||
taginfo = iD.taginfo(),
|
||||
initial = false,
|
||||
list,
|
||||
context;
|
||||
|
||||
function taglist(selection) {
|
||||
|
||||
//selection.append('h4')
|
||||
//.text(t('inspector.edit_tags'));
|
||||
|
||||
list = selection.append('ul')
|
||||
.attr('class', 'tag-list');
|
||||
|
||||
var newTag = selection.append('button')
|
||||
.attr('class', 'add-tag');
|
||||
|
||||
newTag.on('click', function() {
|
||||
addTag();
|
||||
focusNewKey();
|
||||
});
|
||||
|
||||
newTag.append('span')
|
||||
.attr('class', 'icon icon-pre-text plus');
|
||||
|
||||
newTag.append('span')
|
||||
.attr('class', 'label')
|
||||
.text(t('inspector.new_tag'));
|
||||
|
||||
}
|
||||
|
||||
function drawTags(tags) {
|
||||
var entity = list.datum();
|
||||
|
||||
tags = d3.entries(tags);
|
||||
|
||||
if (!tags.length) {
|
||||
tags = [{key: '', value: ''}];
|
||||
}
|
||||
|
||||
var li = list.html('')
|
||||
.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');
|
||||
|
||||
inputs.append('span')
|
||||
.attr('class', 'key-wrap')
|
||||
.append('input')
|
||||
.property('type', 'text')
|
||||
.attr('class', 'key')
|
||||
.attr('maxlength', 255)
|
||||
.property('value', function(d) { return d.key; })
|
||||
.on('change', function(d) { d.key = this.value; event.change(); });
|
||||
|
||||
inputs.append('span')
|
||||
.attr('class', 'input-wrap-position')
|
||||
.append('input')
|
||||
.property('type', 'text')
|
||||
.attr('class', 'value')
|
||||
.attr('maxlength', 255)
|
||||
.property('value', function(d) { return d.value; })
|
||||
.on('change', function(d) { d.value = this.value; event.change(); })
|
||||
.on('keydown.push-more', pushMore);
|
||||
|
||||
inputs.each(bindTypeahead);
|
||||
|
||||
var removeBtn = row.append('button')
|
||||
.attr('tabindex', -1)
|
||||
.attr('class','remove minor')
|
||||
.on('click', removeTag);
|
||||
|
||||
removeBtn.append('span')
|
||||
.attr('class', 'icon delete');
|
||||
|
||||
function findLocal(docs) {
|
||||
var locale = iD.detect().locale.toLowerCase(),
|
||||
localized;
|
||||
|
||||
localized = _.find(docs, function(d) {
|
||||
return d.lang.toLowerCase() === locale;
|
||||
});
|
||||
if (localized) return localized;
|
||||
|
||||
// try the non-regional version of a language, like
|
||||
// 'en' if the language is 'en-US'
|
||||
if (locale.indexOf('-') !== -1) {
|
||||
var first = locale.split('-')[0];
|
||||
localized = _.find(docs, function(d) {
|
||||
return d.lang.toLowerCase() === first;
|
||||
});
|
||||
if (localized) return localized;
|
||||
}
|
||||
|
||||
// finally fall back to english
|
||||
return _.find(docs, function(d) {
|
||||
return d.lang.toLowerCase() === 'en';
|
||||
});
|
||||
}
|
||||
|
||||
function keyValueReference(err, docs) {
|
||||
var local;
|
||||
if (!err && docs) {
|
||||
local = findLocal(docs);
|
||||
}
|
||||
if (local) {
|
||||
var types = [];
|
||||
if (local.on_area) types.push('area');
|
||||
if (local.on_node) types.push('point');
|
||||
if (local.on_way) types.push('line');
|
||||
local.types = types;
|
||||
iD.ui.modal(context.container())
|
||||
.select('.content')
|
||||
.datum(local)
|
||||
.call(iD.ui.tagReference);
|
||||
} else {
|
||||
iD.ui.flash(context.container())
|
||||
.select('.content')
|
||||
.append('h3')
|
||||
.text(t('inspector.no_documentation_combination'));
|
||||
}
|
||||
}
|
||||
|
||||
function keyReference(err, values, params) {
|
||||
if (!err && values.length) {
|
||||
iD.ui.modal(context.container())
|
||||
.select('.content')
|
||||
.datum({
|
||||
data: values,
|
||||
title: 'Key:' + params.key,
|
||||
geometry: params.geometry
|
||||
})
|
||||
.call(iD.ui.keyReference);
|
||||
} else {
|
||||
iD.ui.flash(context.container())
|
||||
.select('.content')
|
||||
.append('h3')
|
||||
.text(t('inspector.no_documentation_key'));
|
||||
}
|
||||
}
|
||||
|
||||
var helpBtn = row.append('button')
|
||||
.attr('tabindex', -1)
|
||||
.attr('class', 'tag-help minor')
|
||||
.on('click', function(d) {
|
||||
var params = _.extend({}, d, {
|
||||
geometry: entity.geometry(context.graph())
|
||||
});
|
||||
if (d.key && d.value) {
|
||||
taginfo.docs(params, keyValueReference);
|
||||
} else if (d.key) {
|
||||
taginfo.values(params, keyReference);
|
||||
}
|
||||
});
|
||||
|
||||
helpBtn.append('span')
|
||||
.attr('class', 'icon inspect');
|
||||
|
||||
if (initial && tags.length === 1 &&
|
||||
tags[0].key === '' && tags[0].value === '') {
|
||||
focusNewKey();
|
||||
}
|
||||
|
||||
return li;
|
||||
}
|
||||
|
||||
function pushMore() {
|
||||
if (d3.event.keyCode === 9 &&
|
||||
list.selectAll('li:last-child input.value').node() === this) {
|
||||
addTag();
|
||||
focusNewKey();
|
||||
d3.event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
function bindTypeahead() {
|
||||
var entity = list.datum(),
|
||||
geometry = entity.geometry(context.graph()),
|
||||
row = d3.select(this),
|
||||
key = row.selectAll('.key'),
|
||||
value = row.selectAll('.input-wrap-position');
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
key.call(d3.typeahead()
|
||||
.data(_.debounce(function(_, callback) {
|
||||
taginfo.keys({
|
||||
geometry: geometry,
|
||||
query: key.property('value')
|
||||
}, function(err, data) {
|
||||
if (!err) callback(sort(key.property('value'), data));
|
||||
});
|
||||
}, 500)));
|
||||
|
||||
var valueinput = value.select('input');
|
||||
value.call(d3.combobox()
|
||||
.fetcher(_.debounce(function(_, __, callback) {
|
||||
taginfo.values({
|
||||
key: key.property('value'),
|
||||
geometry: geometry,
|
||||
query: valueinput.property('value')
|
||||
}, function(err, data) {
|
||||
if (!err) callback(sort(valueinput.property('value'), data));
|
||||
});
|
||||
}, 500)));
|
||||
}
|
||||
|
||||
function focusNewKey() {
|
||||
list.selectAll('li:last-child input.key').node().focus();
|
||||
}
|
||||
|
||||
function addTag() {
|
||||
var tags = taglist.tags();
|
||||
tags[''] = '';
|
||||
drawTags(tags);
|
||||
}
|
||||
|
||||
function removeTag(d) {
|
||||
var tags = taglist.tags();
|
||||
delete tags[d.key];
|
||||
drawTags(tags);
|
||||
}
|
||||
|
||||
taglist.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);
|
||||
}
|
||||
};
|
||||
|
||||
taglist.context = function(_) {
|
||||
context = _;
|
||||
return taglist;
|
||||
};
|
||||
|
||||
return d3.rebind(taglist, event, 'on');
|
||||
};
|
||||
@@ -75,6 +75,26 @@ iD.util.getStyle = function(selector) {
|
||||
}
|
||||
};
|
||||
|
||||
iD.util.editDistance = function(a, b) {
|
||||
if (a.length === 0) return b.length;
|
||||
if (b.length === 0) return a.length;
|
||||
var matrix = [];
|
||||
for (var i = 0; i <= b.length; i++) { matrix[i] = [i]; }
|
||||
for (var j = 0; j <= a.length; j++) { matrix[0][j] = j; }
|
||||
for (i = 1; i <= b.length; i++) {
|
||||
for (j = 1; j <= a.length; j++) {
|
||||
if (b.charAt(i-1) == a.charAt(j-1)) {
|
||||
matrix[i][j] = matrix[i-1][j-1];
|
||||
} else {
|
||||
matrix[i][j] = Math.min(matrix[i-1][j-1] + 1, // substitution
|
||||
Math.min(matrix[i][j-1] + 1, // insertion
|
||||
matrix[i-1][j] + 1)); // deletion
|
||||
}
|
||||
}
|
||||
}
|
||||
return matrix[b.length][a.length];
|
||||
};
|
||||
|
||||
// a d3.mouse-alike which
|
||||
// 1. Only works on HTML elements, not SVG
|
||||
// 2. Does not cause style recalculation
|
||||
|
||||
+131
-68
@@ -1,16 +1,21 @@
|
||||
d3.combobox = function() {
|
||||
var event = d3.dispatch('accept'),
|
||||
autohighlight = false,
|
||||
autofilter = false,
|
||||
input,
|
||||
container,
|
||||
data;
|
||||
container, input, shown = false, data = [];
|
||||
|
||||
var fetcher = function(val, data, cb) {
|
||||
cb(data.filter(function(d) {
|
||||
return d.title
|
||||
.toString()
|
||||
.toLowerCase()
|
||||
.indexOf(val.toLowerCase()) !== -1;
|
||||
}));
|
||||
};
|
||||
|
||||
var typeahead = function(selection) {
|
||||
var hidden, idx = autohighlight ? 0 : -1;
|
||||
|
||||
var rect = selection.select('input').node().getBoundingClientRect();
|
||||
|
||||
var idx = -1,
|
||||
rect = selection.select('input')
|
||||
.node()
|
||||
.getBoundingClientRect();
|
||||
input = selection.select('input');
|
||||
|
||||
container = selection
|
||||
@@ -25,104 +30,174 @@ d3.combobox = function() {
|
||||
});
|
||||
|
||||
carat = selection
|
||||
.insert('div', ':first-child')
|
||||
.insert('a', ':first-child')
|
||||
.attr('class', 'combobox-carat')
|
||||
.text('+')
|
||||
.style({
|
||||
position: 'absolute',
|
||||
left: (rect.width - 20) + 'px',
|
||||
left: rect.width + 'px',
|
||||
top: '0px'
|
||||
})
|
||||
.on('click', function() {
|
||||
update();
|
||||
show();
|
||||
});
|
||||
.on('mousedown', stop)
|
||||
.on('click', click);
|
||||
|
||||
selection
|
||||
.on('keyup.typeahead', key);
|
||||
function stop() {
|
||||
// prevent the form element from blurring. it blurs
|
||||
// on mousedown
|
||||
d3.event.stopPropagation();
|
||||
d3.event.preventDefault();
|
||||
}
|
||||
|
||||
hidden = false;
|
||||
function click() {
|
||||
d3.event.preventDefault();
|
||||
d3.event.stopPropagation();
|
||||
update();
|
||||
show();
|
||||
// focus the node so that a click outside of the
|
||||
// combo box will hide it
|
||||
input.node().focus();
|
||||
}
|
||||
|
||||
function hide() {
|
||||
idx = autohighlight ? 0 : -1;
|
||||
hidden = true;
|
||||
function blur() {
|
||||
// hide the combobox whenever the input element
|
||||
// loses focus
|
||||
slowHide();
|
||||
}
|
||||
|
||||
function show() {
|
||||
container.style('display', 'block');
|
||||
shown = true;
|
||||
}
|
||||
|
||||
function hide() {
|
||||
idx = -1;
|
||||
container.style('display', 'none');
|
||||
shown = false;
|
||||
}
|
||||
|
||||
function slowHide() {
|
||||
if (autohighlight && container.select('a.selected').node()) {
|
||||
select(container.select('a.selected').datum());
|
||||
event.accept();
|
||||
}
|
||||
window.setTimeout(hide, 150);
|
||||
}
|
||||
|
||||
selection
|
||||
.on('focus.typeahead', show)
|
||||
.on('blur.typeahead', slowHide);
|
||||
|
||||
function key() {
|
||||
var len = container.selectAll('a').data().length;
|
||||
if (d3.event.keyCode === 40) {
|
||||
idx = Math.min(idx + 1, len - 1);
|
||||
return highlight();
|
||||
} else if (d3.event.keyCode === 38) {
|
||||
idx = Math.max(idx - 1, 0);
|
||||
return highlight();
|
||||
} else if (d3.event.keyCode === 13) {
|
||||
if (container.select('a.selected').node()) {
|
||||
select(container.select('a.selected').datum());
|
||||
}
|
||||
event.accept();
|
||||
hide();
|
||||
} else {
|
||||
update();
|
||||
function keydown() {
|
||||
if (!shown) return;
|
||||
switch (d3.event.keyCode) {
|
||||
// down arrow
|
||||
case 40:
|
||||
next();
|
||||
d3.event.preventDefault();
|
||||
break;
|
||||
// up arrow
|
||||
case 38:
|
||||
prev();
|
||||
d3.event.preventDefault();
|
||||
break;
|
||||
// escape, tab
|
||||
case 9:
|
||||
case 13:
|
||||
d3.event.preventDefault();
|
||||
break;
|
||||
}
|
||||
d3.event.stopPropagation();
|
||||
}
|
||||
|
||||
function keyup() {
|
||||
switch (d3.event.keyCode) {
|
||||
// escape
|
||||
case 27:
|
||||
hide();
|
||||
break;
|
||||
// escape, tab
|
||||
case 9:
|
||||
case 13:
|
||||
if (!shown) return;
|
||||
accept();
|
||||
break;
|
||||
default:
|
||||
update();
|
||||
d3.event.preventDefault();
|
||||
}
|
||||
d3.event.stopPropagation();
|
||||
}
|
||||
|
||||
function accept() {
|
||||
if (container.select('a.selected').node()) {
|
||||
select(container.select('a.selected').datum());
|
||||
}
|
||||
hide();
|
||||
}
|
||||
|
||||
function next() {
|
||||
var len = container.selectAll('a').data().length;
|
||||
idx = Math.min(idx + 1, len - 1);
|
||||
highlight();
|
||||
}
|
||||
|
||||
function prev() {
|
||||
idx = Math.max(idx - 1, 0);
|
||||
highlight();
|
||||
}
|
||||
|
||||
function highlight() {
|
||||
container
|
||||
.selectAll('a')
|
||||
.classed('selected', function(d, i) { return i == idx; });
|
||||
var height = container.node().offsetHeight,
|
||||
top = container.select('a.selected').node().offsetTop,
|
||||
selectedHeight = container.select('a.selected').node().offsetHeight;
|
||||
if ((top + selectedHeight) < height) {
|
||||
container.node().scrollTop = 0;
|
||||
} else {
|
||||
container.node().scrollTop = top;
|
||||
}
|
||||
}
|
||||
|
||||
function update() {
|
||||
|
||||
function run(data) {
|
||||
container.style('display', function() {
|
||||
return data.length ? 'block' : 'none';
|
||||
});
|
||||
function render(data) {
|
||||
if (data.length) show();
|
||||
else hide();
|
||||
|
||||
var options = container
|
||||
.selectAll('a')
|
||||
.selectAll('a.combobox-option')
|
||||
.data(data, function(d) { return d.value; });
|
||||
|
||||
options.enter()
|
||||
.append('a')
|
||||
.text(function(d) { return d.value; })
|
||||
.attr('class', 'combobox-option')
|
||||
.attr('title', function(d) { return d.title; })
|
||||
.on('click', select);
|
||||
|
||||
options.exit().remove();
|
||||
|
||||
options
|
||||
.classed('selected', function(d, i) { return i == idx; });
|
||||
.classed('selected', function(d, i) { return i == idx; })
|
||||
.order();
|
||||
}
|
||||
|
||||
if (typeof data === 'function') data(selection, run);
|
||||
else run(data);
|
||||
fetcher.apply(selection, [
|
||||
selection.select('input').property('value'),
|
||||
data, render]);
|
||||
}
|
||||
|
||||
// select the choice given as d
|
||||
function select(d) {
|
||||
input
|
||||
.property('value', d.value)
|
||||
.trigger('change');
|
||||
container.style('display', 'none');
|
||||
event.accept(d);
|
||||
hide();
|
||||
}
|
||||
|
||||
input
|
||||
.on('blur.typeahead', blur)
|
||||
.on('keydown.typeahead', keydown)
|
||||
.on('keyup.typeahead', keyup);
|
||||
};
|
||||
|
||||
typeahead.fetcher = function(_) {
|
||||
if (!arguments.length) return fetcher;
|
||||
fetcher = _;
|
||||
return typeahead;
|
||||
};
|
||||
|
||||
typeahead.data = function(_) {
|
||||
@@ -131,17 +206,5 @@ d3.combobox = function() {
|
||||
return typeahead;
|
||||
};
|
||||
|
||||
typeahead.autofilter = function(_) {
|
||||
if (!arguments.length) return autofilter;
|
||||
autofilter = _;
|
||||
return typeahead;
|
||||
};
|
||||
|
||||
typeahead.autohighlight = function(_) {
|
||||
if (!arguments.length) return autohighlight;
|
||||
autohighlight = _;
|
||||
return typeahead;
|
||||
};
|
||||
|
||||
return d3.rebind(typeahead, event, 'on');
|
||||
};
|
||||
|
||||
+21
-4
@@ -1,8 +1,12 @@
|
||||
d3.typeahead = function() {
|
||||
var data;
|
||||
var event = d3.dispatch('accept'),
|
||||
autohighlight = false,
|
||||
data;
|
||||
|
||||
var typeahead = function(selection) {
|
||||
var container, hidden, idx = -1;
|
||||
var container,
|
||||
hidden,
|
||||
idx = autohighlight ? 0 : -1;
|
||||
|
||||
function setup() {
|
||||
var rect = selection.node().getBoundingClientRect();
|
||||
@@ -20,11 +24,17 @@ d3.typeahead = function() {
|
||||
|
||||
function hide() {
|
||||
container.remove();
|
||||
idx = -1;
|
||||
idx = autohighlight ? 0 : -1;
|
||||
hidden = true;
|
||||
}
|
||||
|
||||
function slowHide() {
|
||||
if (autohighlight) {
|
||||
if (container.select('a.selected').node()) {
|
||||
select(container.select('a.selected').datum());
|
||||
event.accept();
|
||||
}
|
||||
}
|
||||
window.setTimeout(hide, 150);
|
||||
}
|
||||
|
||||
@@ -44,6 +54,7 @@ d3.typeahead = function() {
|
||||
if (container.select('a.selected').node()) {
|
||||
select(container.select('a.selected').datum());
|
||||
}
|
||||
event.accept();
|
||||
hide();
|
||||
} else {
|
||||
update();
|
||||
@@ -95,5 +106,11 @@ d3.typeahead = function() {
|
||||
return typeahead;
|
||||
};
|
||||
|
||||
return typeahead;
|
||||
typeahead.autohighlight = function(_) {
|
||||
if (!arguments.length) return autohighlight;
|
||||
autohighlight = _;
|
||||
return typeahead;
|
||||
};
|
||||
|
||||
return d3.rebind(typeahead, event, 'on');
|
||||
};
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
from xml.dom.minidom import parse
|
||||
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
|
||||
dirr = os.path.dirname(__file__)
|
||||
|
||||
|
||||
def relative(x):
|
||||
return os.path.join(dirr, x)
|
||||
|
||||
prefs = json.load(open(relative('prefs.json')))
|
||||
dom1 = parse(relative('./josm.xml'))
|
||||
|
||||
jsonOutput = []
|
||||
|
||||
|
||||
def isemail(x):
|
||||
return re.search('email', x, flags=re.IGNORECASE)
|
||||
|
||||
|
||||
def iswebsite(x):
|
||||
return re.search('web', x, flags=re.IGNORECASE)
|
||||
|
||||
|
||||
def istel(x):
|
||||
return re.search('phone|tel|fax', x, flags=re.IGNORECASE)
|
||||
|
||||
|
||||
def isfav(x):
|
||||
return x in prefs
|
||||
|
||||
for item in dom1.getElementsByTagName('item'):
|
||||
|
||||
tags = {}
|
||||
for elem in item.getElementsByTagName('key'):
|
||||
tags[elem.getAttribute('key')] = elem.getAttribute('value')
|
||||
|
||||
jitem = {
|
||||
"name": item.getAttribute('name'),
|
||||
"type": item.getAttribute('type').replace('closedway', 'area').replace('way', 'line').split(','),
|
||||
"tags": tags,
|
||||
"main": []
|
||||
}
|
||||
|
||||
if isfav(jitem['name']):
|
||||
jitem['favorite'] = True
|
||||
|
||||
for n in item.getElementsByTagName('text'):
|
||||
txt = n.getAttribute('text')
|
||||
type = 'text'
|
||||
if isemail(txt):
|
||||
type = 'email'
|
||||
elif iswebsite(txt):
|
||||
type = 'url'
|
||||
elif istel(txt):
|
||||
type = 'tel'
|
||||
jitem['main'].append({
|
||||
'type': type,
|
||||
'key': n.getAttribute('key'),
|
||||
'text': n.getAttribute('text')
|
||||
})
|
||||
|
||||
for n in item.getElementsByTagName('combo'):
|
||||
jitem['main'].append({
|
||||
'type': 'select',
|
||||
'key': n.getAttribute('key'),
|
||||
'text': n.getAttribute('text'),
|
||||
'values': n.getAttribute('values').split(',')
|
||||
})
|
||||
|
||||
for n in item.getElementsByTagName('check'):
|
||||
jitem['main'].append({
|
||||
'type': 'check',
|
||||
'key': n.getAttribute('key'),
|
||||
'text': n.getAttribute('text'),
|
||||
'default': (n.getAttribute('check') == 'true')
|
||||
})
|
||||
|
||||
jsonOutput.append(jitem)
|
||||
|
||||
json.dump(jsonOutput, open(relative('presets_josm.json'), 'w'), indent=4)
|
||||
@@ -0,0 +1,47 @@
|
||||
from xml.dom.minidom import parse
|
||||
import json
|
||||
|
||||
dom1 = parse('potlatch.xml')
|
||||
|
||||
inputSets = dom1.getElementsByTagName('inputSet')
|
||||
|
||||
jsonOutput = []
|
||||
|
||||
for inputSet in inputSets:
|
||||
setId = inputSet.getAttribute('id')
|
||||
inputs = inputSet.getElementsByTagName('input')
|
||||
for i in inputs:
|
||||
jsonInput = {}
|
||||
inputType = i.getAttribute('type')
|
||||
if inputType == 'choice':
|
||||
choices = i.getElementsByTagName('choice')
|
||||
jsonInput['type'] = 'choice'
|
||||
jsonInput['description'] = i.getAttribute('description')
|
||||
jsonInput['name'] = i.getAttribute('name')
|
||||
jsonInput['key'] = i.getAttribute('key')
|
||||
jsonInput['choices'] = []
|
||||
for c in choices:
|
||||
jsonInput['choices'].append({
|
||||
"value": c.getAttribute('value'),
|
||||
"text": c.getAttribute('text')
|
||||
})
|
||||
elif inputType == 'freetext':
|
||||
jsonInput['type'] = 'freetext'
|
||||
jsonInput['description'] = i.getAttribute('description')
|
||||
jsonInput['name'] = i.getAttribute('name')
|
||||
jsonInput['key'] = i.getAttribute('key')
|
||||
elif inputType == 'checkbox':
|
||||
jsonInput['type'] = 'checkbox'
|
||||
jsonInput['description'] = i.getAttribute('description')
|
||||
jsonInput['name'] = i.getAttribute('name')
|
||||
jsonInput['key'] = i.getAttribute('key')
|
||||
elif inputType == 'number':
|
||||
jsonInput['type'] = 'number'
|
||||
jsonInput['description'] = i.getAttribute('description')
|
||||
jsonInput['name'] = i.getAttribute('name')
|
||||
jsonInput['minimum'] = i.getAttribute('minimum')
|
||||
jsonInput['maximum'] = i.getAttribute('maximum')
|
||||
jsonInput['key'] = i.getAttribute('key')
|
||||
jsonOutput.append(jsonInput)
|
||||
|
||||
json.dump(jsonOutput, open('presets_potlatch.json', 'w'), indent=4)
|
||||
Executable
+5819
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,693 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
See http://wiki.openstreetmap.org/wiki/Potlatch_2/Developer_Documentation/Map_Features for documentation.
|
||||
Files can be included like this: <include file="map_features/roads.xml">
|
||||
-->
|
||||
|
||||
<mapFeatures>
|
||||
|
||||
<!-- Categories -->
|
||||
<category name="Roads" id="roads"/>
|
||||
<category name="Paths" id="paths"/>
|
||||
<category name="Shopping" id="shopping"/>
|
||||
<category name="Food and Drink" id="foodanddrink"/>
|
||||
<category name="Amenity" id="amenity"/>
|
||||
<category name="Tourism" id="tourism"/>
|
||||
<category name="Accommodation" id="accommodation"/>
|
||||
<category name="Transport" id="transport"/>
|
||||
<category name="Water" id="water"/>
|
||||
<category name="Natural" id="natural"/>
|
||||
<category name="Barrier" id="barrier"/>
|
||||
<category name="Power" id="power"/>
|
||||
<category name="Admin" id="admin"/>
|
||||
<category name="Buildings" id="buildings"/>
|
||||
<category name="Landuse" id="landuse"/>
|
||||
<category name="Agriculture" id="agriculture"/>
|
||||
<category name="Advanced" id="advanced"/>
|
||||
<category name="Places" id="places"/>
|
||||
<category name="Sport and Leisure" id="sport"/>
|
||||
<category name="Man-made" id="manmade"/>
|
||||
|
||||
<!-- Common input sets -->
|
||||
|
||||
<inputSet id="simpleName">
|
||||
<input type="freetext" presence="always" name="Name" key="name" description="The name" priority="highest"/>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="nameAndRef">
|
||||
<inputSet ref="simpleName" />
|
||||
<input type="freetext" presence="always" name="Reference number" key="ref" description="A reference number or code used to identify this thing." />
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="simpleBrand">
|
||||
<input type="freetext" category="Naming" presence="always" name="Brand" key="brand" description="Brand, i.e. Acme"/>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="simpleOperator">
|
||||
<input type="freetext" category="Naming" presence="always" name="Operator" key="operator" description="Operator, i.e. Acme Springfield Ltd"/>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="source">
|
||||
<input type="freetext" category="Details" presence="onTagMatch" name="Source" key="source" description="The primary source of information for this object (GPS, survey, Bing, ...)" priority="lowest"/>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="designation">
|
||||
<input type="freetext" category="Details" presence="onTagMatch" description="The official designation or classification (if any). Only use this if the organisation that runs it has its own classification system." name="Official classification" key="designation" priority="lowest" />
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="common">
|
||||
<inputSet ref="source"/>
|
||||
<inputSet ref="designation"/>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="names">
|
||||
<input type="freetext" presence="always"
|
||||
name="Name" category="Details" priority="highest"
|
||||
key="name" description="The most common name"/>
|
||||
<input type="freetext" presence="onTagMatch"
|
||||
name="International Name" category="Details" subcategory="Additional names"
|
||||
key="int_name" description="The internationally recognised name"/>
|
||||
<input type="freetext" presence="onTagMatch"
|
||||
name="Historical Name" category="Details" subcategory="Additional names" priority="low"
|
||||
key="old_name" description="The historic or previous name"/>
|
||||
<input type="freetext" presence="onTagMatch"
|
||||
name="Alternative Name" category="Details" subcategory="Additional names" priority="low"
|
||||
key="alt_name" description="An alternative, currently used, name"/>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="wifi">
|
||||
<input type="choice" presence="onTagMatch" category="Details" name="Wifi" key="wifi">
|
||||
<choice value="free" text="Free"/>
|
||||
<choice value="yes" text="Yes"/>
|
||||
<choice value="no" text="No"/>
|
||||
</input>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="buildingAddress">
|
||||
<input type="freetext" presence="onTagMatch" category="Address" description="The number of the house, e.g. 156 or 10-12" name="House Number" key="addr:housenumber"/>
|
||||
<input type="freetext" presence="onTagMatch" category="Address" description="The name of the house, e.g. Riverbank Cottage" name="Building Name" key="addr:housename"/>
|
||||
<input type="freetext" presence="onTagMatch" category="Address" description="The Street Name (optional)" name="Street Name" key="addr:street"/>
|
||||
<input type="freetext" presence="onTagMatch" category="Address" description="The postcode" name="Postcode" key="addr:postcode"/>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="web">
|
||||
<input type="freetext" presence="onTagMatch" category="Address" description="The URL of the website" name="Website" key="website"/>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="cuisine">
|
||||
<input type="choice" presence="always" name="Cuisine" category="Details" description="The type of food that they serve" key="cuisine">
|
||||
<!-- The 30 most popular values according to taginfo 23/12/2010 -->
|
||||
<choice value="burger" text="Burger"/>
|
||||
<choice value="chicken" text="Chicken"/>
|
||||
<choice value="chinese" text="Chinese"/>
|
||||
<choice value="coffee_shop" text="Coffee Shop"/>
|
||||
<choice value="greek" text="Greek"/>
|
||||
<choice value="pizza" text="Pizza"/>
|
||||
<choice value="sandwich" text="Sandwich"/>
|
||||
<choice value="seafood" text="Sea Food"/>
|
||||
<choice value="regional" text="Regional"/>
|
||||
<choice value="italian" text="Italian"/>
|
||||
<choice value="german" text="German"/>
|
||||
<choice value="kebab" text="Kebab/souvlaki/gyro"/>
|
||||
<choice value="indian" text="Indian"/>
|
||||
<choice value="asian" text="Asian"/>
|
||||
<choice value="mexican" text="Mexican"/>
|
||||
<choice value="thai" text="Thai"/>
|
||||
<choice value="japanese" text="Japanese"/>
|
||||
<choice value="ice_cream" text="Ice-cream"/>
|
||||
<choice value="fish_and_chips" text="Fish & Chips"/>
|
||||
<choice value="turkish" text="Turkish"/>
|
||||
<choice value="french" text="French"/>
|
||||
<choice value="sushi" text="Sushi"/>
|
||||
<choice value="american" text="American"/>
|
||||
<choice value="steak_house" text="Steak House"/>
|
||||
<choice value="international" text="International"/>
|
||||
<choice value="spanish" text="Spanish"/>
|
||||
<choice value="vietnamese" text="Vietnamese"/>
|
||||
<choice value="fish" text="Fish"/>
|
||||
<choice value="bavarian" text="Bavarian"/>
|
||||
<choice value="vegetarian" text="Vegetarian"/>
|
||||
|
||||
<help>http://wiki.openstreetmap.org/wiki/Key:cuisine</help>
|
||||
</input>
|
||||
</inputSet>
|
||||
|
||||
<!-- Roads -->
|
||||
|
||||
<inputSet id="majorRoad">
|
||||
<inputSet ref="names"/>
|
||||
<inputSet ref="roadRefs"/>
|
||||
<inputSet ref="roadRestrictions"/>
|
||||
<inputSet ref="roadPhysical"/>
|
||||
<inputSet ref="cycle"/>
|
||||
<inputSet ref="bicycle-lane"/>
|
||||
<inputSet ref="bus-route"/>
|
||||
<inputSet ref="tram-route"/>
|
||||
<inputSet ref="pedestrians"/>
|
||||
<inputSet ref="roadLanes"/>
|
||||
<inputSet ref="roadRoundabout"/>
|
||||
<inputSet ref="permissions"/>
|
||||
</inputSet>
|
||||
|
||||
|
||||
<inputSet id="minorRoad">
|
||||
<inputSet ref="names"/>
|
||||
<inputSet ref="roadRestrictions"/>
|
||||
<inputSet ref="roadPhysical"/>
|
||||
<inputSet ref="cycle"/>
|
||||
<inputSet ref="bicycle-lane"/>
|
||||
<inputSet ref="bus-route"/>
|
||||
<inputSet ref="tram-route"/>
|
||||
<inputSet ref="pedestrians"/>
|
||||
<inputSet ref="roadLanes"/>
|
||||
<inputSet ref="roadRoundabout"/>
|
||||
<inputSet ref="permissions"/>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="path">
|
||||
<inputSet ref="simpleName"/>
|
||||
<inputSet ref="roadPhysical"/>
|
||||
<inputSet ref="cycle"/>
|
||||
<inputSet ref="pedestrians"/>
|
||||
<inputSet ref="permissions"/>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="junctionNode">
|
||||
<inputSet ref="turnRestrictions"/>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="roadRefs">
|
||||
<input type="freetext" presence="always"
|
||||
name="Reference" category="Details" priority="high"
|
||||
key="ref" description="The official reference number"/>
|
||||
<input type="freetext" presence="onTagMatch"
|
||||
name="International Reference" category="Details" subcategory="Additional names"
|
||||
key="int_ref" description="The official international reference number"/>
|
||||
<input type="freetext" presence="onTagMatch"
|
||||
name="Old Reference" category="Details" subcategory="Additional names" priority="low"
|
||||
key="old_ref" description="The historic or previous reference number"/>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="roadPhysical">
|
||||
<input type="freetext" presence="onTagMatch"
|
||||
name="Width" category="Details" subcategory="Physical"
|
||||
key="width" description="Width of the road" layout="horizontal"/>
|
||||
<input type="choice" presence="onTagMatch"
|
||||
name="Surface" category="Details" description="Type of road surface"
|
||||
key="surface" layout="horizontal">
|
||||
<choice value="unpaved" text="Unpaved" description="Road surface is unsealed"/>
|
||||
<choice value="paved" text="Paved" description="Road surface is sealed"/>
|
||||
<choice value="asphalt" text="Asphalt"/>
|
||||
<choice value="concrete" text="Concrete"/>
|
||||
<choice value="paving_stones" text="Paving stones"/>
|
||||
<choice value="cobblestone" text="Cobblestone"/>
|
||||
<choice value="sand" text="Sand"/>
|
||||
<choice value="gravel" text="Gravel"/>
|
||||
<choice value="dirt" text="Dirt"/>
|
||||
<choice value="grass" text="Grass"/>
|
||||
</input>
|
||||
<inputSet ref="bridge"/>
|
||||
<inputSet ref="tunnel"/>
|
||||
<inputSet ref="embankment-cutting"/>
|
||||
<!-- not sure which category best suits put area=yes -->
|
||||
<input type="checkbox" presence="onTagMatch" category="Details" subcategory="Physical" key="area" name="Open area" description="The way is a large open space, like at a dock, where vehicles can move anywhere within the space, rather than just along the edge." />
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="roadLanes">
|
||||
<input presence="onTagMatch" type="number" name="Lanes" category="Details" description="Total number of lanes, counting both directions"
|
||||
key="lanes" minimum="1" maximum="10" layout="horizontal"/>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="bridge">
|
||||
<input type="choice" presence="onTagMatch"
|
||||
name="Bridge" category="Details" description="Road goes over a bridge"
|
||||
key="bridge" layout="horizontal">
|
||||
<choice value="yes" text="Generic Bridge" description="Generic bridge -- type unknown"/>
|
||||
<choice value="viaduct" text="Viaduct" description="Viaduct"/>
|
||||
<choice value="suspension" text="Suspension bridge"/>
|
||||
</input>
|
||||
<input type="slider" presence="onTagMatch"
|
||||
name="Layer" category="Details" description="Relative vertical positions (-5 lowest, +5 highest)"
|
||||
key="layer" minimum="-5" maximum="5" default="0" snapInterval="1" labels="Lowest,Ground,Highest"
|
||||
defaultName="Ground"/>
|
||||
</inputSet>
|
||||
<inputSet id="tunnel">
|
||||
<!-- Not ideal, used for non-roads too. -->
|
||||
<input type="choice" presence="onTagMatch"
|
||||
name="Tunnel" category="Details" subcategory="Physical" description="Road goes into a tunnel"
|
||||
key="tunnel" layout="horizontal">
|
||||
<choice value="yes" text="Tunnel" description="Generic tunnel"/>
|
||||
</input>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="embankment-cutting">
|
||||
<input type="choice"
|
||||
name="Embankment" category="Details" subcategory="Physical" description="Road supported on a raised bed of earth and rock."
|
||||
key="embankment" layout="horizontal">
|
||||
<choice value="yes" text="Embankment"/>
|
||||
</input>
|
||||
<input type="choice"
|
||||
name="Cutting" category="Details" subcategory="Physical" description="Road carved out of hill on one or both sides."
|
||||
key="cutting" layout="horizontal">
|
||||
<choice value="yes" text="Cutting"/>
|
||||
</input>
|
||||
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="rail-electrification">
|
||||
<input type="choice" name="Electrified" category="Details" subcategory="Electrification" description="Is the track electrified (whether by 3rd rail, overhead wires, etc)?"
|
||||
key="electrified">
|
||||
<choice value="yes" text="Yes"/>
|
||||
<choice value="contact_line" text="Overhead line"/>
|
||||
<choice value="rail" text="Third rail"/>
|
||||
<choice value="no" text="No"/>
|
||||
</input>
|
||||
<input type="choice" name="Voltage" category="Details" subcategory="Electrification" description="Nominal voltage of electric wires"
|
||||
key="voltage" presence="withCategory">
|
||||
<choice value="600" text="600V"/>
|
||||
<choice value="750" text="750V"/>
|
||||
<choice value="1500" text="1500V"/>
|
||||
<choice value="3000" text="3000V"/>
|
||||
<choice value="12000" text="12kV"/>
|
||||
<choice value="15000" text="15kV"/>
|
||||
<choice value="25000" text="25kV"/>
|
||||
</input>
|
||||
<input type="choice" name="Frequency" category="Details" subcategory="Electrification" description="Frequency in Hertz of alternating current power supply"
|
||||
key="frequency" presence="withCategory">
|
||||
<choice value="0" text="DC"/>
|
||||
<choice value="16.67" text="16.67 Hz"/>
|
||||
<choice value="16.7" text="16.7 Hz"/>
|
||||
<choice value="25" text="25 Hz"/>
|
||||
<choice value="50" text="50 Hz"/>
|
||||
<choice value="60" text="60 Hz"/>
|
||||
</input>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="fee">
|
||||
<input type="freetext" presence="onTagMatch" category="Restrictions" description="The charge/cost of using this amenity" name="Fee" key="fee"/>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="roadRestrictions">
|
||||
<input type="choice" presence="always"
|
||||
name="Oneway" category="Restrictions" description="Oneway roads"
|
||||
key="oneway">
|
||||
<choice value="yes" match="yes|true|1" text="One way"
|
||||
description="Road can only be travelled in direction of way" icon="features/oneway__yes.png"/>
|
||||
<choice value="no" match="no|false|0" text="Two way"
|
||||
description="Road can be travelled in both directions" icon="features/oneway__no.png"/>
|
||||
<choice value="-1" match="-1|reverse" text="One way reverse"
|
||||
description="Road can be travelled in opposite direction to way" icon="features/oneway__-1.png"/>
|
||||
</input>
|
||||
<input type="speed" presence="onTagMatch"
|
||||
name="Speed Limit" category="Restrictions" description="Maximum permitted speed on this road"
|
||||
key="maxspeed"/>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="roadRoundabout">
|
||||
<!-- review the choice of category -->
|
||||
<input type="choice" presence="onTagMatch" name="Roundabout" category="Restrictions" description="Whether this road is a roundabout. Make the way face the direction appropriate for the country."
|
||||
key="junction">
|
||||
<choice value="roundabout" text="Yes"/>
|
||||
</input>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="turnRestrictions">
|
||||
<input type="turn" name="Turn restriction" description="Turn restriction" category="Restrictions" priority="normal" presence="onTagMatch">
|
||||
<match k="type" v="restriction"/>
|
||||
<role role="via"/>
|
||||
</input>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="trafficSignals">
|
||||
<!-- can't add as standalone feature due to current limitations, would conflict with junction node feature -->
|
||||
<input type="choice" key="highway" name="Traffic signals" description="Intersection controlled by traffic lights" category="Restrictions" presence="always">
|
||||
<choice value="traffic_signals" text="Yes"/>
|
||||
</input>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="pedestrians">
|
||||
<input type="choice" name="Pedestrians permitted" description="Can pedestrians use this road, including footpaths if any?" category="Walk" key="foot">
|
||||
<choice value="yes" text="Allowed"/>
|
||||
<choice value="no" text="Prohibited"/>
|
||||
<choice value="designated" text="Designated"/>
|
||||
</input>
|
||||
<input type="choice" presence="onTagMatch"
|
||||
name="Sidewalks" category="Walk" description="Whether there is a sidewalk at the side of the street"
|
||||
key="sidewalk" layout="horizontal">
|
||||
<choice value="both" text="Both" description="There is a sidewalk on both sides of the road." match="yes"/>
|
||||
<choice value="left" text="Left" description="The sidewalk is on the left of the direction of the road."/>
|
||||
<choice value="right" text="Right" description="The sidewalk is on the right of the direction of the road."/>
|
||||
<choice value="separate" text="Separate" description="The sidewalk has been mapped as a separate line parallel."/>
|
||||
<choice value="none" text="None" description="There is no sidewalk on this section of road." match="no"/>
|
||||
</input>
|
||||
<input type="route" name="National Walking Route" description="National walking route" category="Walk" priority="low">
|
||||
<match k="type" v="route"/>
|
||||
<match k="route" v="hiking|foot"/>
|
||||
<match k="network" v="nwn"/>
|
||||
<icon image="features/route__nwn.png" background="red" foreground="white">
|
||||
<font size="14pt"><b>${ref}</b></font><br/>
|
||||
<font size="12pt">${name}</font>
|
||||
</icon>
|
||||
</input>
|
||||
<input type="route" name="Regional Walking Route" description="Regional walking route" category="Walk" priority="low">
|
||||
<match k="type" v="route"/>
|
||||
<match k="route" v="hiking|foot"/>
|
||||
<match k="network" v="rwn"/>
|
||||
<icon image="features/route__rwn.png" background="cyan" foreground="white">
|
||||
<font size="14pt"><b>${ref}</b></font><br/>
|
||||
<font size="12pt">${name}</font>
|
||||
</icon>
|
||||
</input>
|
||||
<input type="route" name="Local Walking Route" description="Local walking route" category="Walk" priority="lowest">
|
||||
<match k="type" v="route"/>
|
||||
<match k="route" v="hiking|foot"/>
|
||||
<match k="network" v="lwn"/>
|
||||
<icon image="features/route__lwn.png" background="blue" foreground="white">
|
||||
<font size="14pt"><b>${ref}</b></font><br/>
|
||||
<font size="12pt">${name}</font>
|
||||
</icon>
|
||||
</input>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="naptan">
|
||||
<input type="freetext" presence="onTagMatch" category="Transport" description="12 character internal Naptan ID" name="Atco Code" key="naptan:AtcoCode"/>
|
||||
<input type="choice" presence="onTagMatch" category="Transport" description="The eight-point compass bearning" name="Naptan Bearing" key="naptan:Bearing" >
|
||||
<choice value="N" match="N" text="N" description=""/>
|
||||
<choice value="NE" match="NE" text="NE" description=""/>
|
||||
<choice value="E" match="E" text="E" description=""/>
|
||||
<choice value="SE" match="SE" text="SE" description=""/>
|
||||
<choice value="S" match="S" text="S" description=""/>
|
||||
<choice value="SW" match="SW" text="SW" description=""/>
|
||||
<choice value="W" match="W" text="W" description=""/>
|
||||
<choice value="NW" match="NW" text="NW" description=""/>
|
||||
</input>
|
||||
<input type="freetext" presence="onTagMatch" category="Transport" description="The naptan common name" name="Naptan Common Name (read-only)" key="naptan:CommonName"/>
|
||||
<input type="freetext" presence="onTagMatch" category="Transport" description="" name="Naptan Indicator (read-only)" key="naptan:Indicator"/>
|
||||
<input type="freetext" presence="onTagMatch" category="Transport" description="" name="Naptan Street (read-only)" key="naptan:Street"/>
|
||||
<input type="freetext" presence="onTagMatch" category="Transport" description="Delete this when the details have been verified on-the-ground" name="Naptan Verified?" key="naptan:verified"/>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="buses">
|
||||
<input type="freetext" presence="always" category="Transport" name="Stop Name" key="name" description="The name of the bus stop"/>
|
||||
<input type="freetext" presence="always" category="Transport" name="Local Ref" key="local_ref" description="The local reference of the stop, usually one or two letters above the main flag, used at bus interchanges, e.g. L, BX"/>
|
||||
<inputSet ref="naptan"/>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="bus-route">
|
||||
<input type="route" name="Bus Route" description="Bus route" category="Transport" priority="low" presence="onTagMatch">
|
||||
<match k="type" v="route"/>
|
||||
<match k="route" v="bus"/>
|
||||
<icon image="features/route__bus.png">
|
||||
<font size="12pt">${operator} <b>${ref}</b></font>
|
||||
</icon>
|
||||
</input>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="tram-route">
|
||||
<input type="route" name="Tram Route" description="Tram route" category="Transport" priority="low" presence="onTagMatch">
|
||||
<match k="type" v="route"/>
|
||||
<match k="route" v="tram"/>
|
||||
<icon image="features/transport__tram.png">
|
||||
<font size="12pt">${operator} <b>${ref}</b></font>
|
||||
</icon>
|
||||
</input>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="train-route">
|
||||
<input type="route" name="Train Route" description="Train route" category="Transport" priority="low" presence="onTagMatch">
|
||||
<match k="type" v="route"/>
|
||||
<match k="route" v="train"/>
|
||||
<icon image="features/transport__railway.png">
|
||||
<font size="12pt">${name|operator} <b>(${ref})</b></font>
|
||||
</icon>
|
||||
</input>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="cycle">
|
||||
<inputSet ref="bicycle-permission"/>
|
||||
<input type="route" name="National Cycle Routes" description="A signposted route in a National Cycle Network, or nearest equivalent." category="Cycle" priority="low">
|
||||
<match k="type" v="route"/>
|
||||
<match k="route" v="bicycle"/>
|
||||
<match k="network" v="ncn"/>
|
||||
<icon image="features/route__ncn.png" background="#ff6f7a" foreground="white">
|
||||
<font size="14pt"><b>${ref}</b></font><br/>
|
||||
<font size="12pt">${name}</font>
|
||||
</icon>
|
||||
</input>
|
||||
<input type="route" name="Regional Cycle Routes" description="A signposted route in a Regional Cycle Network, or nearest equivalent." category="Cycle" priority="low">
|
||||
<match k="type" v="route"/>
|
||||
<match k="route" v="bicycle"/>
|
||||
<match k="network" v="rcn"/>
|
||||
<icon image="features/route__rcn.png" background="#6ff7ff" foreground="white">
|
||||
<font size="14pt"><b>${ref}</b></font><br/>
|
||||
<font size="12pt">${name}</font>
|
||||
</icon>
|
||||
</input>
|
||||
<input type="route" name="Local Cycle Routes" description="A signposted route in a Local Cycle Network, or nearest equivalent." category="Cycle" priority="lowest">
|
||||
<match k="type" v="route"/>
|
||||
<match k="route" v="bicycle"/>
|
||||
<match k="network" v="lcn"/>
|
||||
<icon image="features/route__lcn.png" background="#7d6fff" foreground="white">
|
||||
<font size="14pt"><b>${ref}</b></font><br/>
|
||||
<font size="12pt">${name}</font>
|
||||
</icon>
|
||||
</input>
|
||||
<input type="route" name="Mountain bike route" description="A signposted route for mountain biking." category="Cycle" priority="lowest">
|
||||
<match k="type" v="route"/>
|
||||
<match k="route" v="mtb"/>
|
||||
<icon image="features/route__mtb.png" background="#9f4404" foreground="white">
|
||||
<font size="14pt"><b>${ref}</b></font><br/>
|
||||
<font size="12pt">${name}</font>
|
||||
</icon>
|
||||
</input>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="bicycle-permission">
|
||||
<input type="choice"
|
||||
name="Bicycles permitted" category="Cycle" description="Are bicyles allowed to use this road (regardless of physical suitability)?"
|
||||
key="bicycle">
|
||||
<choice value="yes" text="Allowed"/>
|
||||
<choice value="no" text="Prohibited" desciption="Cycling is not allowed. Pushing your bicycle is not allowed either."/>
|
||||
<choice value="private" text="Private"/>
|
||||
<choice value="dismount" text="Cyclists dismount" description="Signage states that cyclists should dismount and push their bike for the selected path or road."/>
|
||||
<choice value="designated" text="Designated"/>
|
||||
<help>http://wiki.openstreetmap.org/wiki/Key:access</help>
|
||||
</input>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="bicycle-lane">
|
||||
<input type="choice"
|
||||
name="Bike lanes" category="Cycle" description="Road has bike lanes within the road surface"
|
||||
key="cycleway" layout="horizontal">
|
||||
<choice value="no" text="No bike lanes"/>
|
||||
<choice value="lane" text="On-road bike lane" description="Separated by painted line on the road from cars"/>
|
||||
<choice value="track" text="Parallel track" description="Separated by kerb or parked cars"/>
|
||||
<choice value="opposite_lane" text="Contraflow lane" description="Separated by painted line, and allowing bicycles in both directions in an otherwise one-way street."/>
|
||||
<choice value="opposite_track" text="Contraflow track" description="Separated by kerb or parked cars, and allowing bicycles in both directions in an otherwise one-way street."/>
|
||||
<choice value="opposite" text="Contraflow unmarked" description="The route may be cycled in the direction opposite of other traffic, but does not have a dedicated lane."/>
|
||||
<help>http://wiki.openstreetmap.org/wiki/Key:cycleway</help>
|
||||
</input>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="route">
|
||||
<inputSet ref="names"/>
|
||||
<inputSet ref="roadRefs"/>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="waterways">
|
||||
<inputSet ref="simpleName"/>
|
||||
<input type="freetext" presence="always" name="Width" category="Details" key="width" description="The width in metres"/>
|
||||
<inputSet ref="boatPermissions"/>
|
||||
</inputSet>
|
||||
<!-- Would be good to have a dedicated 'access' type of input -->
|
||||
<!-- all the description fields are identical at the moment for ease of maintenance, should be tailored in future. -->
|
||||
<inputSet id="boatPermissions">
|
||||
<input type="choice" name="Boat permission" category="Restrictions" key="boat" description="Are boats allowed to use this waterway?">
|
||||
<choice value="yes" text="Allowed" description="General right of way."/>
|
||||
<choice value="no" text="Prohibited" description="No access to the public."/>
|
||||
<choice value="permissive" text="Permissive" description="Access permitted through private land."/>
|
||||
<choice value="private" text="Private" description="No access to the public, except individual exceptions."/>
|
||||
<choice value="designated" text="Designated" description="Permitted, according to signs or specific local laws."/>
|
||||
</input>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="permissions">
|
||||
<input type="choice" name="General access" category="Restrictions" key="access" description="Is there a general right of access, regardless of mode of transport?">
|
||||
<choice value="yes" text="Allowed" description="General right of way."/>
|
||||
<choice value="no" text="Prohibited" description="No access to the public."/>
|
||||
<choice value="permissive" text="Permissive" description="Access permitted through private land."/>
|
||||
<choice value="private" text="Private" description="No access to the public, except individual exceptions."/>
|
||||
<choice value="designated" text="Designated" description="Permitted, according to signs or specific local laws."/>
|
||||
</input>
|
||||
|
||||
<input type="choice" name="Motor vehicles" category="Restrictions" key="motor_vehicle" description="Are cars and other private vehicles allowed?">
|
||||
<choice value="yes" text="Allowed" description="General right of way."/>
|
||||
<choice value="no" text="Prohibited" description="No access to the public."/>
|
||||
<choice value="permissive" text="Permissive" description="Access permitted through private land."/>
|
||||
<choice value="private" text="Private" description="No access to the public, except individual exceptions."/>
|
||||
<choice value="designated" text="Designated" description="Permitted, according to signs or specific local laws."/>
|
||||
</input>
|
||||
|
||||
<inputSet ref="hores-permission" />
|
||||
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="horse-permission">
|
||||
<input type="choice" name="Horses" category="Restrictions" key="horse" description="Are horses allowed?">
|
||||
<choice value="yes" text="Allowed" description="General right of way."/>
|
||||
<choice value="no" text="Prohibited" description="No access to the public."/>
|
||||
<choice value="permissive" text="Permissive" description="Access permitted through private land."/>
|
||||
<choice value="private" text="Private" description="No access to the public, except individual exceptions."/>
|
||||
<choice value="designated" text="Designated" description="Permitted, according to signs or specific local laws."/>
|
||||
</input>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="places">
|
||||
<input type="choice" name="Type of Place" presence="always" key="place">
|
||||
<choice value="locality" text="Locality"/>
|
||||
<choice value="hamlet" text="Hamlet"/>
|
||||
<choice value="village" text="Village"/>
|
||||
<choice value="suburb" text="Suburb"/>
|
||||
<choice value="town" text="Town"/>
|
||||
<choice value="city" text="City"/>
|
||||
<choice value="county" text="County"/>
|
||||
<choice value="region" text="Region"/>
|
||||
<choice value="state" text="State"/>
|
||||
<choice value="country" text="Country"/>
|
||||
<choice value="continent" text="Continent"/>
|
||||
<choice value="island" text="Island"/>
|
||||
<choice value="islet" text="Islet"/>
|
||||
</input>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="isBuilding">
|
||||
<input type="choice" presence="withCategory" category="Details" name="Building type, if it is one" key="building">
|
||||
<choice value="yes" text="Generic building"/>
|
||||
<choice value="residential" text="Generic residential"/>
|
||||
<choice value="apartments" text="Big apartments house"/>
|
||||
<choice value="terrace" text="Terraced house"/>
|
||||
<choice value="house" text="Family house"/>
|
||||
<choice value="hut" text="Small hut"/>
|
||||
<choice value="garage" text="A garage"/>
|
||||
<choice value="garages" text="Block of garages"/>
|
||||
<choice value="office" text="Office building"/>
|
||||
<choice value="public" text="Public building"/>
|
||||
<choice value="industrial" text="Generic industrial"/>
|
||||
<choice value="manufacture" text="Manufacture"/>
|
||||
<choice value="warehouse" text="Warehouse"/>
|
||||
<choice value="hangar" text="Hangar"/>
|
||||
<choice value="storage_tank" text="Fluids storage tank"/>
|
||||
<choice value="retail" text="Retail"/>
|
||||
<choice value="supermarket" text="Supermarket"/>
|
||||
<choice value="train_station" text="Train station"/>
|
||||
<choice value="church" text="Church"/>
|
||||
<choice value="school" text="School"/>
|
||||
<choice value="bunker" text="Military bunker"/>
|
||||
<choice value="collapsed" text="Collapsed building"/>
|
||||
<choice value="roof" text="Just a roof"/>
|
||||
<help>http://wiki.openstreetmap.org/wiki/Key:building</help>
|
||||
</input>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="powerCables">
|
||||
<input type="choice" name="Cables" key="cables" presence="always" category="Details">
|
||||
<choice value="2" text="2"/>
|
||||
<choice value="3" text="3"/>
|
||||
<choice value="4" text="4"/>
|
||||
<choice value="6" text="6"/>
|
||||
<choice value="8" text="8"/>
|
||||
<choice value="10" text="10"/>
|
||||
<choice value="12" text="12"/>
|
||||
</input>
|
||||
<input type="choice" name="Voltage" key="voltage" presence="always" category="Details">
|
||||
<!-- choices based on http://osmdoc.com/en/tag/voltage/#values-->
|
||||
<choice value="400" text="400 V"/>
|
||||
<choice value="600" text="600 V"/>
|
||||
<choice value="750" text="750 V"/>
|
||||
<choice value="1500" text="1500 V"/>
|
||||
<choice value="3000" text="3000 V"/>
|
||||
<choice value="15000" text="15 kV"/>
|
||||
<choice value="20000" text="20 kV"/>
|
||||
<choice value="35000" text="35 kV"/>
|
||||
<choice value="110000" text="110 kV"/>
|
||||
<choice value="132000" text="132 kV"/>
|
||||
<choice value="138000" text="138 kV"/>
|
||||
<choice value="220000" text="220 kV"/>
|
||||
<choice value="380000" text="380 kV"/>
|
||||
<choice value="500000" text="500 kV"/>
|
||||
</input>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="pitchSport">
|
||||
<input name="Sport" presence="always" category="Details" key="sport" type="choice" description="The sport that is predominantly played here.">
|
||||
<choice value="9pin" text="9 pin bowling"/>
|
||||
<choice value="10pin" text="10 pin bowling"/>
|
||||
<choice value="american_football" text="American football"/>
|
||||
<choice value="archery" text="Archery"/>
|
||||
<choice value="athletics" text="Athletics"/>
|
||||
<choice value="australian_football" text="Australian Rules Football"/>
|
||||
<choice value="baseball" text="Baseball"/>
|
||||
<choice value="basketball" text="Basketball"/>
|
||||
<choice value="beachvolleyball" text="Beach volleyball"/>
|
||||
<choice value="boules" text="Boules/petanque/bocci"/>
|
||||
<choice value="bowls" text="Lawn bowls"/>
|
||||
<choice value="canadian_football" text="Canadian football"/>
|
||||
<choice value="chess" text="Chess"/>
|
||||
<choice value="cricket" text="Cricket"/>
|
||||
<choice value="cricket_nets" text="Cricket nets"/>
|
||||
<choice value="croquet" text="Croquet"/>
|
||||
<choice value="equestrian" text="Equestrian"/>
|
||||
<choice value="gaelic_football" text="Gaelic football"/>
|
||||
<choice value="gymnastics" text="Gymnastics"/>
|
||||
<choice value="team_handball" text="(Team) handball"/>
|
||||
<choice value="hockey" text="(Field) hockey"/>
|
||||
<choice value="korfball" text="Korball"/>
|
||||
<choice value="pelota" text="Pelota"/>
|
||||
<choice value="rugby_league" text="Rugby league"/>
|
||||
<choice value="rugby_union" text="Rugby union"/>
|
||||
<choice value="shooting" text="Shooting"/>
|
||||
<choice value="skating" text="Ice skating"/>
|
||||
<choice value="skateboard" text="Skateboarding"/>
|
||||
<choice value="soccer" text="Soccer/football"/>
|
||||
<choice value="swimming" text="Swimming"/>
|
||||
<choice value="table_tennis" text="Table tennis"/>
|
||||
<choice value="tennis" text="Tennis"/>
|
||||
<choice value="volleyball" text="Volleyball"/>
|
||||
</input>
|
||||
</inputSet>
|
||||
|
||||
<inputSet id="wheelchair-basic">
|
||||
<input type="choice" name="Wheelchair" key="wheelchair" presence="onTagMatch" category="Details">
|
||||
<choice value="yes" text="Yes: ramps/elevators/etc" />
|
||||
<choice value="no" text="No: inaccessible to wheelchairs" />
|
||||
<choice value="limited" text="Limited accessibility" />
|
||||
</input>
|
||||
</inputSet>
|
||||
|
||||
<!-- Features -->
|
||||
|
||||
<include file="map_features/roads.xml" /> <!-- includes traffic calming, roundabouts, race track -->
|
||||
<include file="map_features/paths.xml" /> <!-- includes steps, highway=pedestrian, bike/hike routes -->
|
||||
<include file="map_features/water.xml" /> <!-- includes coastline -->
|
||||
<include file="map_features/transport.xml" /> <!-- includes rail, trams, bus, airports, car rental, bike parking... -->
|
||||
<include file="map_features/power.xml" /> <!-- includes power lines, pylons, stations -->
|
||||
<include file="map_features/places.xml" /> <!-- includes boundaries (inc. NP) -->
|
||||
<include file="map_features/tourism.xml" /> <!-- includes accommodation -->
|
||||
<include file="map_features/barriers.xml" />
|
||||
<include file="map_features/shopping.xml" /> <!-- no clear distinction between this, amenities and buildings -->
|
||||
<include file="map_features/amenities.xml" /> <!-- includes cafe, bar... -->
|
||||
<include file="map_features/landuse.xml" /> <!-- includes outdoor leisure/sporting stuff, agriculture, natural. -->
|
||||
<include file="map_features/man_made.xml" />
|
||||
<include file="map_features/buildings.xml" /> <!-- a bit of a dumping ground, includes sports centre, shopping centre, hospital... -->
|
||||
|
||||
|
||||
|
||||
<!-- Relations -->
|
||||
<feature name="Multipolygon">
|
||||
<category>advanced</category>
|
||||
<relation/>
|
||||
<tag k="type" v="multipolygon"/>
|
||||
<inputSet ref="common"/>
|
||||
</feature>
|
||||
|
||||
</mapFeatures>
|
||||
@@ -0,0 +1,3 @@
|
||||
[
|
||||
"Cafe", "Restaurant", "Bus Station", "Hospital", "Bar", "Place of Worship"
|
||||
]
|
||||
@@ -0,0 +1,60 @@
|
||||
[
|
||||
{
|
||||
"title": "Highway",
|
||||
"name": "highway",
|
||||
"match": {
|
||||
"type": ["line"],
|
||||
"tags": {
|
||||
"highway": "*"
|
||||
}
|
||||
},
|
||||
"form": [
|
||||
{
|
||||
"tag": "highway",
|
||||
"title": "Highway Type",
|
||||
"type": "select",
|
||||
"option": ["primary", "secondary", "tertiary"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Cafe",
|
||||
"name": "cafe",
|
||||
"match": {
|
||||
"type": ["node", "area"],
|
||||
"tags": {
|
||||
"amenity": "cafe"
|
||||
}
|
||||
},
|
||||
"form": [
|
||||
{
|
||||
"tag": "phone",
|
||||
"type": "tel"
|
||||
},
|
||||
{
|
||||
"tag": "fax",
|
||||
"type": "tel"
|
||||
},
|
||||
{
|
||||
"tag": "website",
|
||||
"type": "url"
|
||||
},
|
||||
{
|
||||
"tag": "email",
|
||||
"type": "email"
|
||||
},
|
||||
{
|
||||
"tag": "internet_access",
|
||||
"title": "Internet Access",
|
||||
"type": "select",
|
||||
"option": ["yes", "wlan","wired","terminal","no"]
|
||||
},
|
||||
{
|
||||
"tag": "internet_access:fee",
|
||||
"title": "Internet Access Fee",
|
||||
"type": "select",
|
||||
"option": ["yes", "no"]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -34,6 +34,7 @@
|
||||
<script src='../js/id/util.js'></script>
|
||||
<script src='../js/id/oauth.js'></script>
|
||||
<script src='../js/id/services/taginfo.js'></script>
|
||||
<script src='../js/id/presetdata.js'></script>
|
||||
|
||||
<script src='../data/data.js'></script>
|
||||
<script src='../data/deprecated.js'></script>
|
||||
@@ -70,6 +71,9 @@
|
||||
<script src='../js/id/ui/lasso.js'></script>
|
||||
<script src='../js/id/ui/flash.js'></script>
|
||||
<script src='../js/id/ui/confirm.js'></script>
|
||||
<script src='../js/id/ui/preset.js'></script>
|
||||
<script src='../js/id/ui/presetfavs.js'></script>
|
||||
<script src='../js/id/ui/presetsearch.js'></script>
|
||||
<script src='../js/id/ui/splash.js'></script>
|
||||
<script src='../js/id/ui/source_switch.js'></script>
|
||||
<script src='../js/id/ui/toggle.js'></script>
|
||||
|
||||
@@ -43,14 +43,14 @@ describe("iD.ui.Inspector", 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;
|
||||
expect(element.select('.tag-list').selectAll("input.value").property('value')).to.be.empty;
|
||||
expect(element.select('.tag-list').selectAll("input.key").property('value')).to.be.empty;
|
||||
});
|
||||
|
||||
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;
|
||||
expect(element.select('.tag-list').selectAll("input")[0][2].value).to.be.empty;
|
||||
expect(element.select('.tag-list').selectAll("input")[0][3].value).to.be.empty;
|
||||
});
|
||||
|
||||
it("removes tags when clicking the remove button", function () {
|
||||
|
||||
Reference in New Issue
Block a user