From d97358020362e36f616707d93f688ad283eb7b41 Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Thu, 22 May 2014 13:44:45 -0400 Subject: [PATCH 1/9] Add to .gitignore: .DS_Store, node_modules --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index f960c0be3..f3c254660 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +.DS_Store +node_modules dist/iD.js dist/iD.min.js dist/iD.css From e3e2ea602a410ccff704fec6c74a4871c3eb0d31 Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Thu, 22 May 2014 13:48:04 -0400 Subject: [PATCH 2/9] Checkmark fields now support custom string options oneway fields now show "Assumed to be No" or "Assumed to be Yes" instead of "Unknown" #2220 --- data/presets.yaml | 8 ++++++ data/presets/fields.json | 18 +++++++++++-- data/presets/fields/oneway.json | 9 ++++++- data/presets/fields/oneway_yes.json | 9 ++++++- data/presets/presets.json | 2 +- data/presets/presets/highway/motorway.json | 4 +-- dist/locales/en.json | 14 ++++++++-- js/id/ui/preset/check.js | 30 ++++++++++++++-------- 8 files changed, 75 insertions(+), 19 deletions(-) diff --git a/data/presets.yaml b/data/presets.yaml index 5bb6ecda0..af1b0937e 100644 --- a/data/presets.yaml +++ b/data/presets.yaml @@ -240,8 +240,16 @@ en: label: Type oneway: label: One Way + options: + undefined: Assumed to be No + yes: Yes + no: No oneway_yes: label: One Way + options: + undefined: Assumed to be Yes + yes: Yes + no: No opening_hours: label: Hours operator: diff --git a/data/presets/fields.json b/data/presets/fields.json index bbdbc6ac6..96fe0ef41 100644 --- a/data/presets/fields.json +++ b/data/presets/fields.json @@ -570,13 +570,27 @@ "oneway": { "key": "oneway", "type": "check", - "label": "One Way" + "label": "One Way", + "strings": { + "options": { + "undefined": "Assumed to be No", + "yes": "Yes", + "no": "No" + } + } }, "oneway_yes": { "key": "oneway", "type": "check", "default": "yes", - "label": "One Way" + "label": "One Way", + "strings": { + "options": { + "undefined": "Assumed to be Yes", + "yes": "Yes", + "no": "No" + } + } }, "opening_hours": { "key": "opening_hours", diff --git a/data/presets/fields/oneway.json b/data/presets/fields/oneway.json index cdf746e4e..2b9b0fe02 100644 --- a/data/presets/fields/oneway.json +++ b/data/presets/fields/oneway.json @@ -1,5 +1,12 @@ { "key": "oneway", "type": "check", - "label": "One Way" + "label": "One Way", + "strings": { + "options": { + "undefined": "Assumed to be No", + "yes": "Yes", + "no": "No" + } + } } diff --git a/data/presets/fields/oneway_yes.json b/data/presets/fields/oneway_yes.json index b73d5a366..3e212eef1 100644 --- a/data/presets/fields/oneway_yes.json +++ b/data/presets/fields/oneway_yes.json @@ -2,5 +2,12 @@ "key": "oneway", "type": "check", "default": "yes", - "label": "One Way" + "label": "One Way", + "strings": { + "options": { + "undefined": "Assumed to be Yes", + "yes": "Yes", + "no": "No" + } + } } diff --git a/data/presets/presets.json b/data/presets/presets.json index e6665a9d5..b17249d29 100644 --- a/data/presets/presets.json +++ b/data/presets/presets.json @@ -3822,7 +3822,7 @@ "highway/motorway": { "icon": "highway-motorway", "fields": [ - "oneway", + "oneway_yes", "maxspeed", "structure", "access", diff --git a/data/presets/presets/highway/motorway.json b/data/presets/presets/highway/motorway.json index d33aa952a..c05ac6e54 100644 --- a/data/presets/presets/highway/motorway.json +++ b/data/presets/presets/highway/motorway.json @@ -1,7 +1,7 @@ { "icon": "highway-motorway", "fields": [ - "oneway", + "oneway_yes", "maxspeed", "structure", "access", @@ -17,4 +17,4 @@ }, "terms": [], "name": "Motorway" -} \ No newline at end of file +} diff --git a/dist/locales/en.json b/dist/locales/en.json index 04b1b3571..5fd3f8323 100644 --- a/dist/locales/en.json +++ b/dist/locales/en.json @@ -743,10 +743,20 @@ "label": "Type" }, "oneway": { - "label": "One Way" + "label": "One Way", + "options": { + "undefined": "Assumed to be No", + "yes": "Yes", + "no": "No" + } }, "oneway_yes": { - "label": "One Way" + "label": "One Way", + "options": { + "undefined": "Assumed to be Yes", + "yes": "Yes", + "no": "No" + } }, "opening_hours": { "label": "Hours" diff --git a/js/id/ui/preset/check.js b/js/id/ui/preset/check.js index 2badb14fc..010060953 100644 --- a/js/id/ui/preset/check.js +++ b/js/id/ui/preset/check.js @@ -1,13 +1,24 @@ iD.ui.preset.check = iD.ui.preset.defaultcheck = function(field) { var event = d3.dispatch('change'), - values = field.type === 'check' ? - [undefined, 'yes', 'no'] : - [undefined, 'yes'], - value, - box, - text, - label; + options = field.strings && field.strings.options, + values = [], + texts = [], + value, box, text, label; + + if (options) { + for (var k in options) { + values.push(k === 'undefined' ? undefined : k); + texts.push(field.t('check.' + k, { 'default': options[k] })); + } + } else { + values = [undefined, 'yes']; + texts = [t('inspector.unknown'), t('inspector.check.yes')]; + if (field.type === 'check') { + values.push('no'); + texts.push(t('inspector.check.no')); + } + } var check = function(selection) { selection.classed('checkselect', 'true'); @@ -24,7 +35,7 @@ iD.ui.preset.defaultcheck = function(field) { .attr('id', 'preset-input-' + field.id); enter.append('span') - .text(t('inspector.unknown')) + .text(texts[0]) .attr('class', 'value'); box = label.select('input') @@ -42,8 +53,7 @@ iD.ui.preset.defaultcheck = function(field) { value = tags[field.key]; box.property('indeterminate', field.type === 'check' && !value); box.property('checked', value === 'yes'); - text.text(value ? t('inspector.check.' + value, {default: value}) : - field.type === 'check' ? t('inspector.unknown') : t('inspector.check.no')); + text.text(texts[values.indexOf(value)]); label.classed('set', !!value); }; From 8380981ac388fdb4d0e14bf48e4c0883c3741694 Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Thu, 22 May 2014 15:47:54 -0400 Subject: [PATCH 3/9] Pretend oneway field is a oneway_yes field if `junction=roundabout` is set. --- js/id/ui/preset/check.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/js/id/ui/preset/check.js b/js/id/ui/preset/check.js index 010060953..d7159d29f 100644 --- a/js/id/ui/preset/check.js +++ b/js/id/ui/preset/check.js @@ -1,5 +1,5 @@ iD.ui.preset.check = -iD.ui.preset.defaultcheck = function(field) { +iD.ui.preset.defaultcheck = function(field, context) { var event = d3.dispatch('change'), options = field.strings && field.strings.options, values = [], @@ -20,6 +20,15 @@ iD.ui.preset.defaultcheck = function(field) { } } + // hack: pretend oneway field is a oneway_yes field if `junction=roundabout` is set. + if (field.id === 'oneway') { + var way = context.entity(context.selectedIDs()[0]); + if (way.tags.junction === 'roundabout') { + texts.shift(); + texts.unshift(t('presets.fields.oneway_yes.check.undefined', { 'default': 'Assumed to be Yes' })); + } + } + var check = function(selection) { selection.classed('checkselect', 'true'); From 191c7002f4d9dad506a985db59eae82aa7bd0da4 Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Thu, 22 May 2014 16:20:52 -0400 Subject: [PATCH 4/9] Handle empty selectedIDs.. --- js/id/ui/preset/check.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/js/id/ui/preset/check.js b/js/id/ui/preset/check.js index d7159d29f..56cd2a69b 100644 --- a/js/id/ui/preset/check.js +++ b/js/id/ui/preset/check.js @@ -22,8 +22,9 @@ iD.ui.preset.defaultcheck = function(field, context) { // hack: pretend oneway field is a oneway_yes field if `junction=roundabout` is set. if (field.id === 'oneway') { - var way = context.entity(context.selectedIDs()[0]); - if (way.tags.junction === 'roundabout') { + var ids = context.selectedIDs(), + way = ids.length && context.entity(ids[0]); + if (way && way.tags.junction === 'roundabout') { texts.shift(); texts.unshift(t('presets.fields.oneway_yes.check.undefined', { 'default': 'Assumed to be Yes' })); } From 5fdbd6f9f4ac556c3d0e050ac325ce94085577cd Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Fri, 23 May 2014 11:27:27 -0400 Subject: [PATCH 5/9] Instead of using context.selectedIDs(), define a check.entity setter function --- js/id/ui/preset/check.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/js/id/ui/preset/check.js b/js/id/ui/preset/check.js index 56cd2a69b..264a6bbd0 100644 --- a/js/id/ui/preset/check.js +++ b/js/id/ui/preset/check.js @@ -4,7 +4,7 @@ iD.ui.preset.defaultcheck = function(field, context) { options = field.strings && field.strings.options, values = [], texts = [], - value, box, text, label; + entity, value, box, text, label; if (options) { for (var k in options) { @@ -20,17 +20,13 @@ iD.ui.preset.defaultcheck = function(field, context) { } } - // hack: pretend oneway field is a oneway_yes field if `junction=roundabout` is set. - if (field.id === 'oneway') { - var ids = context.selectedIDs(), - way = ids.length && context.entity(ids[0]); - if (way && way.tags.junction === 'roundabout') { + var check = function(selection) { + // hack: pretend oneway field is a oneway_yes field if `junction=roundabout` is set. #2220, #1841 + if (field.id === 'oneway' && entity.tags.junction === 'roundabout') { texts.shift(); texts.unshift(t('presets.fields.oneway_yes.check.undefined', { 'default': 'Assumed to be Yes' })); } - } - var check = function(selection) { selection.classed('checkselect', 'true'); label = selection.selectAll('.preset-input-wrap') @@ -59,6 +55,12 @@ iD.ui.preset.defaultcheck = function(field, context) { text = label.select('span.value'); }; + check.entity = function(_) { + if (!arguments.length) return entity; + entity = _; + return check; + }; + check.tags = function(tags) { value = tags[field.key]; box.property('indeterminate', field.type === 'check' && !value); From 126f334c96f6fd619f21c7df369ac88831a29bc6 Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Fri, 23 May 2014 14:57:52 -0400 Subject: [PATCH 6/9] eliminate warning: 'context' is defined but never used --- js/id/ui/preset/check.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/id/ui/preset/check.js b/js/id/ui/preset/check.js index 264a6bbd0..5bfeb4625 100644 --- a/js/id/ui/preset/check.js +++ b/js/id/ui/preset/check.js @@ -1,5 +1,5 @@ iD.ui.preset.check = -iD.ui.preset.defaultcheck = function(field, context) { +iD.ui.preset.defaultcheck = function(field) { var event = d3.dispatch('change'), options = field.strings && field.strings.options, values = [], From 1c3d0dacee577b51421dbd7cc37293d9b1846b7a Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Fri, 23 May 2014 15:04:35 -0400 Subject: [PATCH 7/9] Replace all matches, not just the first one.. --- js/id/ui/preset/combo.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/id/ui/preset/combo.js b/js/id/ui/preset/combo.js index c6f1e4e63..18f4a38af 100644 --- a/js/id/ui/preset/combo.js +++ b/js/id/ui/preset/combo.js @@ -32,7 +32,7 @@ iD.ui.preset.typeCombo = function(field) { function options(opts) { combobox.data(opts.map(function(d) { var o = {}; - o.title = o.value = d.replace('_', ' '); + o.title = o.value = d.replace(/_+/g, ' '); return o; })); @@ -44,7 +44,7 @@ iD.ui.preset.typeCombo = function(field) { } function change() { - var value = input.value().replace(' ', '_'); + var value = input.value().replace(/\s+/g, '_'); if (field.type === 'typeCombo' && !value) value = 'yes'; var t = {}; From 40810dab04051185acea79e209a0c69b915818c3 Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Fri, 23 May 2014 15:06:10 -0400 Subject: [PATCH 8/9] Correctly trim whitespace in semicolon-separated multivalues #2236 --- js/id/ui/entity_editor.js | 4 +++- js/id/ui/preset/combo.js | 7 ++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/js/id/ui/entity_editor.js b/js/id/ui/entity_editor.js index 4f59f209e..24fecc682 100644 --- a/js/id/ui/entity_editor.js +++ b/js/id/ui/entity_editor.js @@ -133,11 +133,13 @@ iD.ui.EntityEditor = function(context) { function clean(o) { var out = {}, k, v; + /*jshint -W083 */ for (k in o) { if (k && (v = o[k]) !== undefined) { - out[k] = v.trim(); + out[k] = v.split(';').map(function(s) { return s.trim(); }).join(';'); } } + /*jshint +W083 */ return out; } diff --git a/js/id/ui/preset/combo.js b/js/id/ui/preset/combo.js index 18f4a38af..3d2149bf2 100644 --- a/js/id/ui/preset/combo.js +++ b/js/id/ui/preset/combo.js @@ -44,7 +44,12 @@ iD.ui.preset.typeCombo = function(field) { } function change() { - var value = input.value().replace(/\s+/g, '_'); + var value = input.value() + .split(';') + .map(function(s) { return s.trim(); }) + .join(';') + .replace(/\s+/g, '_'); + if (field.type === 'typeCombo' && !value) value = 'yes'; var t = {}; From 10bd86cb452331e0c5ffc706f4176533ed16cc4a Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Fri, 23 May 2014 17:07:11 -0400 Subject: [PATCH 9/9] Check single source for implied onewayness #2220 --- index.html | 1 + js/id/core/oneway_tags.js | 32 ++++++++++++++++++++++++++++++++ js/id/core/way.js | 10 +++++----- js/id/ui/preset/check.js | 14 ++++++++++---- test/index.html | 1 + 5 files changed, 49 insertions(+), 9 deletions(-) create mode 100644 js/id/core/oneway_tags.js diff --git a/index.html b/index.html index fec78cf5c..786668e8f 100644 --- a/index.html +++ b/index.html @@ -204,6 +204,7 @@ + diff --git a/js/id/core/oneway_tags.js b/js/id/core/oneway_tags.js new file mode 100644 index 000000000..0e8f7db35 --- /dev/null +++ b/js/id/core/oneway_tags.js @@ -0,0 +1,32 @@ +iD.oneWayTags = { + 'aerialway': { + 'chair_lift': true, + 'mixed_lift': true, + 't-bar': true, + 'j-bar': true, + 'platter': true, + 'rope_tow': true, + 'magic_carpet': true, + 'yes': true + }, + 'highway': { + 'motorway': true, + 'motorway_link': true + }, + 'junction': { + 'roundabout': true + }, + 'man_made': { + 'piste:halfpipe': true, + 'pipeline': true + }, + 'piste:type': { + 'downhill': true, + 'sled': true, + 'yes': true + }, + 'waterway': { + 'river': true, + 'stream': true + } +}; diff --git a/js/id/core/way.js b/js/id/core/way.js index 530185fc9..3a6e6d6ec 100644 --- a/js/id/core/way.js +++ b/js/id/core/way.js @@ -48,11 +48,11 @@ _.extend(iD.Way.prototype, { if (['no', '0'].indexOf(this.tags.oneway) !== -1) { return false; } // implied oneway tag.. - return this.tags.waterway === 'river' || - this.tags.waterway === 'stream' || - this.tags.highway === 'motorway' || - this.tags.highway === 'motorway_link' || - this.tags.junction === 'roundabout'; + for (var key in this.tags) { + if (key in iD.oneWayTags && (this.tags[key] in iD.oneWayTags[key])) + return true; + } + return false; }, isClosed: function() { diff --git a/js/id/ui/preset/check.js b/js/id/ui/preset/check.js index 5bfeb4625..a8c145944 100644 --- a/js/id/ui/preset/check.js +++ b/js/id/ui/preset/check.js @@ -21,10 +21,16 @@ iD.ui.preset.defaultcheck = function(field) { } var check = function(selection) { - // hack: pretend oneway field is a oneway_yes field if `junction=roundabout` is set. #2220, #1841 - if (field.id === 'oneway' && entity.tags.junction === 'roundabout') { - texts.shift(); - texts.unshift(t('presets.fields.oneway_yes.check.undefined', { 'default': 'Assumed to be Yes' })); + // hack: pretend oneway field is a oneway_yes field + // where implied oneway tag exists (e.g. `junction=roundabout`) #2220, #1841 + if (field.id === 'oneway') { + for (var key in entity.tags) { + if (key in iD.oneWayTags && (entity.tags[key] in iD.oneWayTags[key])) { + texts.shift(); + texts.unshift(t('presets.fields.oneway_yes.check.undefined', { 'default': 'Assumed to be Yes' })); + break; + } + } } selection.classed('checkselect', 'true'); diff --git a/test/index.html b/test/index.html index 8fe2bc698..ef3b0ae22 100644 --- a/test/index.html +++ b/test/index.html @@ -185,6 +185,7 @@ +