From 00b426e951c8fe7160cfd6bf8f93407119e63667 Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Wed, 9 Dec 2015 13:35:06 -0800 Subject: [PATCH] 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 --- data/presets/schema/field.json | 13 ++++++++- js/id/ui/preset/combo.js | 48 +++++++++++++++++++++++++++------- 2 files changed, 50 insertions(+), 11 deletions(-) diff --git a/data/presets/schema/field.json b/data/presets/schema/field.json index b3733eaa2..e43366ce5 100644 --- a/data/presets/schema/field.json +++ b/data/presets/schema/field.json @@ -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 diff --git a/js/id/ui/preset/combo.js b/js/id/ui/preset/combo.js index e6c6e17b0..a6e6dddf4 100644 --- a/js/id/ui/preset/combo.js +++ b/js/id/ui/preset/combo.js @@ -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); };