Merge branch 'chips' of https://github.com/kepta/iD into kepta-chips

This commit is contained in:
Bryan Housel
2016-04-22 10:39:41 -04:00
21 changed files with 271 additions and 151 deletions
+1
View File
@@ -232,6 +232,7 @@ dist/iD.js: \
js/id/ui/preset/address.js \
js/id/ui/preset/check.js \
js/id/ui/preset/combo.js \
js/id/ui/preset/multiselect.js \
js/id/ui/preset/cycleway.js \
js/id/ui/preset/input.js \
js/id/ui/preset/localized.js \
+52
View File
@@ -1193,6 +1193,58 @@ button.save.has-count .count::before {
border-bottom-right-radius: 4px;
}
/* preset form multiselect */
.form-field-multiselect {
border: 1px solid #cfcfcf;
border-top: 0px;
padding: 5px 0 5px 10px;
background: #fff;
display: block;
border-radius: 0 0 4px 4px;
overflow: hidden;
}
.form-field-multiselect:focus {
border-bottom: 0px;
}
.form-field-multiselect.active {
border-bottom-left-radius: 0px;
border-bottom-right-radius: 0px;
}
.form-field-multiselect li {
background-color: #eff2f7;
border: 1px solid #ccd5e3;
border-radius: 4px;
line-height: 25px;
display: inline-block;
padding: 2px 5px;
margin: 0 10px 5px 0;
height: 30px;
}
.form-field-multiselect a {
font-family: Arial, Helvetica, sans-serif !important;
font-size: 16px !important;
line-height: 25px;
float: right;
margin: 1px 0 0 5px;
padding: 0;
cursor: pointer;
color: #a6b4ce;
}
.form-field-multiselect input {
border: 0px;
width: 110px;
}
.form-field-multiselect input:focus {
border-radius: 4px !important;
}
/* preset form cycleway */
.form-field-cycleway .preset-input-wrap li {
+3 -26
View File
@@ -773,32 +773,9 @@ en:
railway:
# 'railway=*'
label: Type
recycling/cans:
# 'recycling:cans=*'
label: Accepts Cans
recycling/clothes:
# 'recycling:clothes=*'
label: Accepts Clothes
recycling/glass:
# 'recycling:glass=*'
label: Accepts Glass
recycling/glass_bottles:
# 'recycling:glass_bottles=*'
label: Accepts Glass Bottles
recycling/paper:
# 'recycling:paper=*'
label: Accepts Paper
recycling/plastic:
# 'recycling:plastic=*'
label: Accepts Plastic
recycling/type:
# 'recycling_type=*'
label: Recycling Type
options:
# recycling_type=centre
centre: Recycling Center
# recycling_type=container
container: Container
recycling/recycling_choices:
# 'recycling=*'
label: Accepts
ref:
# 'ref=*'
label: Reference
+6 -42
View File
@@ -653,7 +653,7 @@
},
"internet_access": {
"key": "internet_access",
"type": "combo",
"type": "multiselect",
"label": "Internet Access",
"strings": {
"options": {
@@ -1020,46 +1020,10 @@
"type": "typeCombo",
"label": "Type"
},
"recycling/cans": {
"key": "recycling:cans",
"type": "check",
"label": "Accepts Cans"
},
"recycling/clothes": {
"key": "recycling:clothes",
"type": "check",
"label": "Accepts Clothes"
},
"recycling/glass": {
"key": "recycling:glass",
"type": "check",
"label": "Accepts Glass"
},
"recycling/glass_bottles": {
"key": "recycling:glass_bottles",
"type": "check",
"label": "Accepts Glass Bottles"
},
"recycling/paper": {
"key": "recycling:paper",
"type": "check",
"label": "Accepts Paper"
},
"recycling/plastic": {
"key": "recycling:plastic",
"type": "check",
"label": "Accepts Plastic"
},
"recycling/type": {
"key": "recycling_type",
"type": "combo",
"label": "Recycling Type",
"strings": {
"options": {
"container": "Container",
"centre": "Recycling Center"
}
}
"recycling/recycling_choices": {
"key": "recycling",
"type": "multiselect",
"label": "Accepts"
},
"ref": {
"key": "ref",
@@ -1270,7 +1234,7 @@
},
"sport_ice": {
"key": "sport",
"type": "combo",
"type": "multiselect",
"label": "Sport",
"options": [
"skating",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"key": "internet_access",
"type": "combo",
"type": "multiselect",
"label": "Internet Access",
"strings": {
"options": {
-5
View File
@@ -1,5 +0,0 @@
{
"key": "recycling:cans",
"type": "check",
"label": "Accepts Cans"
}
@@ -1,5 +0,0 @@
{
"key": "recycling:clothes",
"type": "check",
"label": "Accepts Clothes"
}
-5
View File
@@ -1,5 +0,0 @@
{
"key": "recycling:glass",
"type": "check",
"label": "Accepts Glass"
}
@@ -1,5 +0,0 @@
{
"key": "recycling:glass_bottles",
"type": "check",
"label": "Accepts Glass Bottles"
}
-5
View File
@@ -1,5 +0,0 @@
{
"key": "recycling:paper",
"type": "check",
"label": "Accepts Paper"
}
@@ -1,5 +0,0 @@
{
"key": "recycling:plastic",
"type": "check",
"label": "Accepts Plastic"
}
@@ -0,0 +1,5 @@
{
"key": "recycling",
"type": "multiselect",
"label": "Accepts"
}
-11
View File
@@ -1,11 +0,0 @@
{
"key": "recycling_type",
"type": "combo",
"label": "Recycling Type",
"strings": {
"options": {
"container": "Container",
"centre": "Recycling Center"
}
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"key": "sport",
"type": "combo",
"type": "multiselect",
"label": "Sport",
"options": [
"skating",
+1 -7
View File
@@ -1581,13 +1581,7 @@
"fields": [
"operator",
"address",
"recycling/type",
"recycling/cans",
"recycling/glass_bottles",
"recycling/paper",
"recycling/glass",
"recycling/plastic",
"recycling/clothes"
"recycling/recycling_choices"
],
"geometry": [
"point",
+1 -7
View File
@@ -3,13 +3,7 @@
"fields": [
"operator",
"address",
"recycling/type",
"recycling/cans",
"recycling/glass_bottles",
"recycling/paper",
"recycling/glass",
"recycling/plastic",
"recycling/clothes"
"recycling/recycling_choices"
],
"geometry": [
"point",
+1
View File
@@ -56,6 +56,7 @@
"defaultcheck",
"text",
"maxspeed",
"multiselect",
"number",
"tel",
"email",
+2 -24
View File
@@ -1280,30 +1280,8 @@
"railway": {
"label": "Type"
},
"recycling/cans": {
"label": "Accepts Cans"
},
"recycling/clothes": {
"label": "Accepts Clothes"
},
"recycling/glass": {
"label": "Accepts Glass"
},
"recycling/glass_bottles": {
"label": "Accepts Glass Bottles"
},
"recycling/paper": {
"label": "Accepts Paper"
},
"recycling/plastic": {
"label": "Accepts Plastic"
},
"recycling/type": {
"label": "Recycling Type",
"options": {
"container": "Container",
"centre": "Recycling Center"
}
"recycling/recycling_choices": {
"label": "Accepts"
},
"ref": {
"label": "Reference"
+1
View File
@@ -129,6 +129,7 @@
<script src='js/id/ui/preset/access.js'></script>
<script src='js/id/ui/preset/address.js'></script>
<script src='js/id/ui/preset/check.js'></script>
<script src='js/id/ui/preset/multiselect.js'></script>
<script src='js/id/ui/preset/combo.js'></script>
<script src='js/id/ui/preset/cycleway.js'></script>
<script src='js/id/ui/preset/input.js'></script>
+194
View File
@@ -0,0 +1,194 @@
iD.ui.preset.multiselect = function(field, context) {
var dispatch = d3.dispatch('init', 'change'),
optstrings = field.strings && field.strings.options,
optarray = field.options,
strings = {},
multiselectContainer,
combobox,
comboboxData,
input,
isInitialized;
field.key += ':';
function getOptStringKey(val) {
if (optstrings) {
var match = _.find(strings, function(o) {
return o.value === val;
});
return match && match.key;
}
}
function getOptStringVal(key) {
if (optstrings) {
var match = _.find(strings, function(o) {
return o.key === key;
});
return match && match.value;
}
}
function objectDifference(a, b) {
var bObj = {};
b.forEach(function(obj){
bObj[obj.key] = obj;
});
// Return all elements in a, unless in b
return a.filter(function(obj){
return !(obj.key in bObj);
});
}
function multiselect(selection) {
isInitialized = false;
combobox = d3.combobox();
multiselectContainer = selection.selectAll('ul').data([0]);
multiselectContainer.enter()
.append('ul')
.on('click', function() {
window.setTimeout(function(){input.node().focus();}, 100);
})
.attr('class', 'form-field-multiselect');
input = multiselectContainer.selectAll('input')
.data([0]);
var enter = input.enter()
.append('input')
.attr('type', 'text')
.attr('id', 'preset-input-' + field.id);
if (optstrings) { enter.attr('readonly', 'readonly'); }
input
.call(function() {combobox(input, selection);})
.on('change', change)
.on('blur', change)
.on('focus', function() {multiselectContainer.classed('active', true);})
.each(function() {
if (optstrings) {
strings = Object.keys(optstrings).map(function(k) {
return {
key: k,
value: field.t('options.' + k, { 'default': optstrings[k] })
};
});
dispatch.init();
isInitialized = true;
} else if (optarray) {
strings = optarray.map(function(k) {return {key: k, value: k};});
dispatch.init();
isInitialized = true;
} else if (context.taginfo()) {
context.taginfo().keys({query: field.key}, function(err, data) {
if (!err) {
strings = data.map(function(k) {
var d = k.value.replace(field.key, '');
return {
key: d,
value: d
};
});
dispatch.init();
isInitialized = true;
}
});
}
});
}
function updateStrings(tagsData) {
comboboxData = objectDifference(strings, tagsData);
combobox.data(comboboxData.map(comboValues));
input.attr('placeholder', field.placeholder() ||
( 'Type here'));
}
function update(data) {
var chips = multiselectContainer.selectAll('.chips').data(data);
var chip = chips.enter()
.insert('li', 'input')
.attr('class', 'chips');
chip.append('span');
chip.append('a');
chips.select('span').text(function(d) {return d.value;});
chips.select('a')
.on('click', removeKey)
.attr('class', 'remove')
.text('×');
chips.exit().remove();
}
function comboValues(d) {
return {
value: d.value,
title: d.value
};
}
function change() {
multiselectContainer.classed('active', false);
var key = getOptStringKey(input.value()) || input.value();
if (key && key !== '') {
var t = {};
t[field.key + key] = 'yes';
input.value('');
dispatch.change(t);
}
}
function removeKey(d) {
d3.event.stopPropagation();
var t = {};
t[field.key + d.key] = undefined;
dispatch.change(t);
}
multiselect.tags = function(tags) {
var tagsData = [];
Object.keys(tags).forEach(function(d) {
if (d.indexOf(field.key) > -1 && tags[d] === 'yes') {
var datum = d.replace(field.key, '');
if (!optstrings) {
return tagsData.push({
key: datum,
value: datum
});
}
// discards any pair not found in optstrings
if (optstrings && getOptStringVal(datum)) {
return tagsData.push({
key: datum,
value: getOptStringVal(datum)
});
}
}
});
update(tagsData);
if (isInitialized) {
updateStrings(tagsData);
} else {
dispatch.on('init', function () {
updateStrings(tagsData);
});
}
};
multiselect.focus = function() {
input.node().focus();
};
return d3.rebind(multiselect, dispatch, 'on');
};
+2 -2
View File
@@ -14,7 +14,7 @@ d3.combobox = function() {
}));
};
var combobox = function(input) {
var combobox = function(input, customBoundingRect) {
var idx = -1,
container = d3.select(document.body)
.selectAll('div.combobox')
@@ -223,7 +223,7 @@ d3.combobox = function() {
options.exit()
.remove();
var rect = input.node().getBoundingClientRect();
var rect = customBoundingRect ? customBoundingRect.node().getBoundingClientRect() : input.node().getBoundingClientRect();
container.style({
'left': rect.left + 'px',