Add snake_case field property (closes #2867)

The vast majority of tag values in OSM should be automatically snake_cased
(e.g. `amenity=place_of_worship`)
But there are a few exceptions, e.g. fields expected to include a unit
(e.g. `maxstay=1 day`)
So this allows a ui field to set whether or not to automatically snake_case
This commit is contained in:
Bryan Housel
2015-12-09 13:35:06 -08:00
parent 56f286a549
commit 00b426e951
2 changed files with 50 additions and 11 deletions

View File

@@ -70,23 +70,27 @@
"required": true
},
"label": {
"description": "English label for the form",
"description": "English label for the field caption",
"type": "string",
"required": true
},
"geometry": {
"description": "If specified, only show the field for this kind of geometry",
"type": "string"
},
"default": {
"description": "The default value for this field",
"type": "string"
},
"options": {
"description": "List of untranslatable string suggestions (combo type fields)",
"type": "array",
"items": {
"type": "string"
}
},
"universal": {
"description": "If true, this field will appear in the Add Field list for all presets",
"type": "boolean",
"default": false
},
@@ -94,10 +98,17 @@
"type": "string"
},
"placeholder": {
"description": "Placeholder text for this field",
"type": "string"
},
"strings": {
"description": "Translatable strings options (combo type fields)",
"type": "object"
},
"snake_case": {
"description": "If true, replace spaces with underscores in the tag value (combo type fields)",
"type": "boolean",
"default": true
}
},
"additionalProperties": false

View File

@@ -3,9 +3,30 @@ iD.ui.preset.typeCombo = function(field, context) {
var event = d3.dispatch('change'),
optstrings = field.strings && field.strings.options,
optarray = field.options,
snake_case = (field.snake_case || (field.snake_case === undefined)),
strings = {},
input;
function snake(s) {
return s.replace(/\s+/g, '_');
}
function unsnake(s) {
return s.replace(/_+/g, ' ');
}
function clean(s) {
return s.split(';')
.map(function(s) { return s.trim(); })
.join(';');
}
function optString() {
return _.find(_.keys(strings), function(k) {
return strings[k] === input.value();
});
}
function combo(selection) {
var combobox = d3.combobox();
@@ -31,14 +52,14 @@ iD.ui.preset.typeCombo = function(field, context) {
stringsLoaded();
} else if (optarray) {
_.each(optarray, function(k) {
strings[k] = k.replace(/_+/g, ' ');
strings[k] = (snake_case ? unsnake(k) : k);
});
stringsLoaded();
} else if (context.taginfo()) {
context.taginfo().values({key: field.key}, function(err, data) {
if (!err) {
_.each(_.pluck(data, 'value'), function(k) {
strings[k] = k.replace(/_+/g, ' ');
strings[k] = (snake_case ? unsnake(k) : k);
});
stringsLoaded();
}
@@ -66,14 +87,14 @@ iD.ui.preset.typeCombo = function(field, context) {
}
function change() {
var optstring = _.find(_.keys(strings), function(k) { return strings[k] === input.value(); }),
value = optstring || (input.value()
.split(';')
.map(function(s) { return s.trim(); })
.join(';')
.replace(/\s+/g, '_'));
var value = optString() || clean(input.value());
if (field.type === 'typeCombo' && !value) value = 'yes';
if (snake_case) {
value = snake(value);
}
if (field.type === 'typeCombo' && !value) {
value = 'yes';
}
var t = {};
t[field.key] = value || undefined;
@@ -82,8 +103,15 @@ iD.ui.preset.typeCombo = function(field, context) {
combo.tags = function(tags) {
var key = tags[field.key],
optstring = optString(),
value = strings[key] || key || '';
if (field.type === 'typeCombo' && value.toLowerCase() === 'yes') value = '';
if (field.type === 'typeCombo' && value.toLowerCase() === 'yes') {
value = '';
}
if (!optstring && snake_case) {
value = unsnake(value);
}
input.value(value);
};