mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-24 00:54:03 +02:00
Merge branch 'field_refactor'
This commit is contained in:
+67
-33
@@ -968,7 +968,7 @@ button.save.has-count .count::before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 10%;
|
||||
width: 32px;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
@@ -1024,22 +1024,22 @@ button.save.has-count .count::before {
|
||||
|
||||
/* preset form basics */
|
||||
|
||||
.inspector-preset {
|
||||
.preset-editor {
|
||||
overflow: hidden;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.inspector-preset a.hide-toggle {
|
||||
.preset-editor a.hide-toggle {
|
||||
margin: 0 20px 10px 20px;
|
||||
}
|
||||
|
||||
.inspector-preset .preset-form {
|
||||
.preset-editor .preset-form {
|
||||
padding: 10px;
|
||||
margin: 0 10px 10px 10px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.inspector-preset .preset-form:empty {
|
||||
.preset-editor .preset-form:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -1056,7 +1056,8 @@ button.save.has-count .count::before {
|
||||
transition: margin-bottom 200ms;
|
||||
}
|
||||
|
||||
.form-field:last-child {
|
||||
.form-field.nowrap,
|
||||
.wrap-form-field:last-child .form-field {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
@@ -1097,7 +1098,7 @@ button.save.has-count .count::before {
|
||||
|
||||
.form-label button {
|
||||
border-left: 1px solid #ccc;
|
||||
width: 10%;
|
||||
width: 32px;
|
||||
height: 100%;
|
||||
border-radius: 0;
|
||||
background: #f6f6f6;
|
||||
@@ -1106,6 +1107,7 @@ button.save.has-count .count::before {
|
||||
border-left: none;
|
||||
border-right: 1px solid #CCC;
|
||||
border-radius: 4px 0 0 0;
|
||||
width: 31px;
|
||||
}
|
||||
.form-label button:hover {
|
||||
background: #f1f1f1;
|
||||
@@ -1146,6 +1148,7 @@ button.save.has-count .count::before {
|
||||
.inspector-hover .form-field-multicombo,
|
||||
.inspector-hover .structure-extras-wrap,
|
||||
.inspector-hover input,
|
||||
.inspector-hover textarea,
|
||||
.inspector-hover label {
|
||||
background: #ececec;
|
||||
}
|
||||
@@ -1296,6 +1299,7 @@ button.save.has-count .count::before {
|
||||
|
||||
/* preset form access */
|
||||
/* preset form cycleway */
|
||||
/* preset form structure extras */
|
||||
|
||||
.form-field-structure .structure-extras-wrap li,
|
||||
.form-field-cycleway .preset-input-wrap li,
|
||||
@@ -1335,6 +1339,34 @@ button.save.has-count .count::before {
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.structure-extras-wrap li:first-child span {
|
||||
border-top-left-radius: 4px;
|
||||
}
|
||||
.structure-extras-wrap li:first-child input {
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
.structure-extras-wrap li:last-child span {
|
||||
border-bottom-left-radius: 4px;
|
||||
}
|
||||
.structure-extras-wrap li:last-child input {
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
[dir='rtl'] .structure-extras-wrap li:first-child span {
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
[dir='rtl'] .structure-extras-wrap li:first-child input {
|
||||
border-top-right-radius: 0;
|
||||
border-top-left-radius: 4px;
|
||||
}
|
||||
[dir='rtl'] .structure-extras-wrap li:last-child span {
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
[dir='rtl'] .structure-extras-wrap li:last-child input {
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom-left-radius: 4px;
|
||||
}
|
||||
|
||||
|
||||
/* preset form multicombo */
|
||||
@@ -1403,28 +1435,43 @@ input[type=number] {
|
||||
}
|
||||
|
||||
.spin-control {
|
||||
width: 20%;
|
||||
height: 29px;
|
||||
width: 64px;
|
||||
height: 30px;
|
||||
display: inline-block;
|
||||
margin-left: -20%;
|
||||
margin-left: -64px;
|
||||
margin-bottom: -11px;
|
||||
position: relative;
|
||||
}
|
||||
[dir='rtl'] .spin-control{
|
||||
margin-left: 0;
|
||||
margin-right: -64px;
|
||||
}
|
||||
|
||||
.spin-control button {
|
||||
right: 1px;
|
||||
position: relative;
|
||||
float: left;
|
||||
height: 100%;
|
||||
width: 50%;
|
||||
width: 32px;
|
||||
border-left: 1px solid #CCC;
|
||||
border-radius: 0;
|
||||
background: rgba(0, 0, 0, 0);
|
||||
}
|
||||
[dir='rtl'] .spin-control button{
|
||||
border-left: 0;
|
||||
border-right: 1px solid #CCC;
|
||||
}
|
||||
|
||||
.spin-control button.decrement {
|
||||
border-bottom-right-radius: 3px;
|
||||
}
|
||||
[dir='rtl'] .spin-control button.decrement {
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
[dir='rtl'] .spin-control button.increment {
|
||||
border-bottom-left-radius: 3px;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.spin-control button.decrement::after,
|
||||
.spin-control button.increment::after {
|
||||
@@ -1447,6 +1494,7 @@ input[type=number] {
|
||||
border-right: 5px solid transparent;
|
||||
}
|
||||
|
||||
|
||||
/* preset form checkbox */
|
||||
|
||||
.checkselect label:last-of-type {
|
||||
@@ -1530,11 +1578,11 @@ input[type=number] {
|
||||
}
|
||||
|
||||
.form-field .wiki-title ~ .combobox-caret {
|
||||
right: 10%;
|
||||
right: 32px;
|
||||
}
|
||||
[dir='rtl'] .form-field .wiki-title ~ .combobox-caret {
|
||||
right: auto;
|
||||
left: 10%;
|
||||
left: 32px;
|
||||
}
|
||||
|
||||
/* Localized field */
|
||||
@@ -1549,8 +1597,8 @@ input[type=number] {
|
||||
.form-field .button-input-action {
|
||||
position: relative;
|
||||
right: 1px;
|
||||
width: 10%;
|
||||
margin-left: -10%;
|
||||
width: 32px;
|
||||
margin-left: -32px;
|
||||
border: 1px solid #CCC;
|
||||
border-top-width: 0;
|
||||
border-right-width: 0;
|
||||
@@ -1560,7 +1608,7 @@ input[type=number] {
|
||||
}
|
||||
[dir='rtl'] .form-field .button-input-action {
|
||||
margin-left: 0;
|
||||
margin-right: -10%;
|
||||
margin-right: -32px;
|
||||
border-right-width: 1px;
|
||||
border-radius: 0 0 0 4px;
|
||||
}
|
||||
@@ -2708,6 +2756,9 @@ img.tile-removing {
|
||||
background: none;
|
||||
color: #ddd;
|
||||
}
|
||||
[dir='rtl'] .panel-title button.close {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.panel-title button.close:hover {
|
||||
color: #fff;
|
||||
@@ -4165,23 +4216,6 @@ li.hide + li.version .badge .tooltip .tooltip-arrow {
|
||||
border-radius: 4px 0 0 4px;
|
||||
}
|
||||
|
||||
|
||||
/* increment / decrement control - code by Naoufel Razouane */
|
||||
|
||||
[dir='rtl'] .spin-control{
|
||||
margin-left: 0;
|
||||
margin-right: -20%;
|
||||
}
|
||||
[dir='rtl'] .spin-control button{
|
||||
border-left: 0;
|
||||
border-right: 1px solid #CCC;
|
||||
}
|
||||
[dir='rtl'] .spin-control button.decrement{
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
[dir='rtl'] .spin-control button.increment{
|
||||
border-bottom-left-radius: 3px;
|
||||
}
|
||||
/* modal */
|
||||
[dir='rtl'] .modal > button {
|
||||
position: absolute;
|
||||
|
||||
@@ -246,6 +246,11 @@ en:
|
||||
brand:
|
||||
# brand=*
|
||||
label: Brand
|
||||
bridge:
|
||||
# bridge=*
|
||||
label: Type
|
||||
# bridge field placeholder
|
||||
placeholder: Default
|
||||
building:
|
||||
# building=*
|
||||
label: Building
|
||||
@@ -369,6 +374,11 @@ en:
|
||||
currency_multi:
|
||||
# 'currency:=*'
|
||||
label: Currency Types
|
||||
cutting:
|
||||
# cutting=*
|
||||
label: Type
|
||||
# cutting field placeholder
|
||||
placeholder: Default
|
||||
cycle_network:
|
||||
# cycle_network=*
|
||||
label: Network
|
||||
@@ -458,6 +468,11 @@ en:
|
||||
label: Email
|
||||
# email field placeholder
|
||||
placeholder: example@example.com
|
||||
embankment:
|
||||
# embankment=*
|
||||
label: Type
|
||||
# embankment field placeholder
|
||||
placeholder: Default
|
||||
emergency:
|
||||
# emergency=*
|
||||
label: Emergency
|
||||
@@ -505,6 +520,11 @@ en:
|
||||
fixme:
|
||||
# fixme=*
|
||||
label: Fix Me
|
||||
ford:
|
||||
# ford=*
|
||||
label: Type
|
||||
# ford field placeholder
|
||||
placeholder: Default
|
||||
fuel:
|
||||
# fuel=*
|
||||
label: Fuel
|
||||
@@ -634,6 +654,8 @@ en:
|
||||
layer:
|
||||
# layer=*
|
||||
label: Layer
|
||||
# layer field placeholder
|
||||
placeholder: '0'
|
||||
leaf_cycle:
|
||||
# leaf_cycle=*
|
||||
label: Leaf Cycle
|
||||
@@ -1361,6 +1383,11 @@ en:
|
||||
# trees=*
|
||||
label: Trees
|
||||
tunnel:
|
||||
# tunnel=*
|
||||
label: Type
|
||||
# tunnel field placeholder
|
||||
placeholder: Default
|
||||
tunnel_waterway:
|
||||
# tunnel=*
|
||||
label: Tunnel
|
||||
vending:
|
||||
|
||||
@@ -329,6 +329,12 @@
|
||||
"type": "text",
|
||||
"label": "Brand"
|
||||
},
|
||||
"bridge": {
|
||||
"key": "bridge",
|
||||
"type": "typeCombo",
|
||||
"label": "Type",
|
||||
"placeholder": "Default"
|
||||
},
|
||||
"building_area": {
|
||||
"key": "building",
|
||||
"type": "combo",
|
||||
@@ -488,6 +494,12 @@
|
||||
"type": "multiCombo",
|
||||
"label": "Currency Types"
|
||||
},
|
||||
"cutting": {
|
||||
"key": "cutting",
|
||||
"type": "typeCombo",
|
||||
"label": "Type",
|
||||
"placeholder": "Default"
|
||||
},
|
||||
"cycle_network": {
|
||||
"key": "cycle_network",
|
||||
"type": "networkCombo",
|
||||
@@ -631,6 +643,12 @@
|
||||
"universal": true,
|
||||
"label": "Email"
|
||||
},
|
||||
"embankment": {
|
||||
"key": "embankment",
|
||||
"type": "typeCombo",
|
||||
"label": "Type",
|
||||
"placeholder": "Default"
|
||||
},
|
||||
"emergency": {
|
||||
"key": "emergency",
|
||||
"type": "check",
|
||||
@@ -695,6 +713,12 @@
|
||||
"label": "Fix Me",
|
||||
"universal": true
|
||||
},
|
||||
"ford": {
|
||||
"key": "ford",
|
||||
"type": "typeCombo",
|
||||
"label": "Type",
|
||||
"placeholder": "Default"
|
||||
},
|
||||
"fuel_multi": {
|
||||
"key": "fuel:",
|
||||
"type": "multiCombo",
|
||||
@@ -883,8 +907,9 @@
|
||||
},
|
||||
"layer": {
|
||||
"key": "layer",
|
||||
"type": "combo",
|
||||
"label": "Layer"
|
||||
"type": "number",
|
||||
"label": "Layer",
|
||||
"placeholder": "0"
|
||||
},
|
||||
"leaf_cycle_singular": {
|
||||
"key": "leaf_cycle",
|
||||
@@ -1842,11 +1867,17 @@
|
||||
"type": "semiCombo",
|
||||
"label": "Trees"
|
||||
},
|
||||
"tunnel": {
|
||||
"tunnel_waterway": {
|
||||
"key": "tunnel",
|
||||
"type": "combo",
|
||||
"label": "Tunnel"
|
||||
},
|
||||
"tunnel": {
|
||||
"key": "tunnel",
|
||||
"type": "typeCombo",
|
||||
"label": "Type",
|
||||
"placeholder": "Default"
|
||||
},
|
||||
"vending": {
|
||||
"key": "vending",
|
||||
"type": "combo",
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"key": "bridge",
|
||||
"type": "typeCombo",
|
||||
"label": "Type",
|
||||
"placeholder": "Default"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"key": "cutting",
|
||||
"type": "typeCombo",
|
||||
"label": "Type",
|
||||
"placeholder": "Default"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"key": "embankment",
|
||||
"type": "typeCombo",
|
||||
"label": "Type",
|
||||
"placeholder": "Default"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"key": "ford",
|
||||
"type": "typeCombo",
|
||||
"label": "Type",
|
||||
"placeholder": "Default"
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"key": "layer",
|
||||
"type": "combo",
|
||||
"label": "Layer"
|
||||
}
|
||||
"type": "number",
|
||||
"label": "Layer",
|
||||
"placeholder": "0"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"key": "tunnel",
|
||||
"type": "combo",
|
||||
"label": "Tunnel"
|
||||
"type": "typeCombo",
|
||||
"label": "Type",
|
||||
"placeholder": "Default"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"key": "tunnel",
|
||||
"type": "combo",
|
||||
"label": "Tunnel"
|
||||
}
|
||||
@@ -14776,7 +14776,7 @@
|
||||
"waterway/ditch": {
|
||||
"icon": "waterway-ditch",
|
||||
"fields": [
|
||||
"tunnel"
|
||||
"tunnel_waterway"
|
||||
],
|
||||
"geometry": [
|
||||
"line"
|
||||
@@ -14812,7 +14812,7 @@
|
||||
"waterway/drain": {
|
||||
"icon": "waterway-stream",
|
||||
"fields": [
|
||||
"tunnel"
|
||||
"tunnel_waterway"
|
||||
],
|
||||
"geometry": [
|
||||
"line"
|
||||
@@ -14850,7 +14850,7 @@
|
||||
"icon": "waterway-river",
|
||||
"fields": [
|
||||
"name",
|
||||
"tunnel",
|
||||
"tunnel_waterway",
|
||||
"width"
|
||||
],
|
||||
"geometry": [
|
||||
@@ -14921,7 +14921,7 @@
|
||||
"icon": "waterway-stream",
|
||||
"fields": [
|
||||
"name",
|
||||
"tunnel",
|
||||
"tunnel_waterway",
|
||||
"width"
|
||||
],
|
||||
"geometry": [
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"icon": "waterway-ditch",
|
||||
"fields": [
|
||||
"tunnel"
|
||||
"tunnel_waterway"
|
||||
],
|
||||
"geometry": [
|
||||
"line"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"icon": "waterway-stream",
|
||||
"fields": [
|
||||
"tunnel"
|
||||
"tunnel_waterway"
|
||||
],
|
||||
"geometry": [
|
||||
"line"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"icon": "waterway-river",
|
||||
"fields": [
|
||||
"name",
|
||||
"tunnel",
|
||||
"tunnel_waterway",
|
||||
"width"
|
||||
],
|
||||
"geometry": [
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"icon": "waterway-stream",
|
||||
"fields": [
|
||||
"name",
|
||||
"tunnel",
|
||||
"tunnel_waterway",
|
||||
"width"
|
||||
],
|
||||
"geometry": [
|
||||
|
||||
Vendored
+23
-2
@@ -1282,6 +1282,10 @@
|
||||
"brand": {
|
||||
"label": "Brand"
|
||||
},
|
||||
"bridge": {
|
||||
"label": "Type",
|
||||
"placeholder": "Default"
|
||||
},
|
||||
"building_area": {
|
||||
"label": "Building"
|
||||
},
|
||||
@@ -1384,6 +1388,10 @@
|
||||
"currency_multi": {
|
||||
"label": "Currency Types"
|
||||
},
|
||||
"cutting": {
|
||||
"label": "Type",
|
||||
"placeholder": "Default"
|
||||
},
|
||||
"cycle_network": {
|
||||
"label": "Network"
|
||||
},
|
||||
@@ -1469,6 +1477,10 @@
|
||||
"label": "Email",
|
||||
"placeholder": "example@example.com"
|
||||
},
|
||||
"embankment": {
|
||||
"label": "Type",
|
||||
"placeholder": "Default"
|
||||
},
|
||||
"emergency": {
|
||||
"label": "Emergency"
|
||||
},
|
||||
@@ -1509,6 +1521,10 @@
|
||||
"fixme": {
|
||||
"label": "Fix Me"
|
||||
},
|
||||
"ford": {
|
||||
"label": "Type",
|
||||
"placeholder": "Default"
|
||||
},
|
||||
"fuel_multi": {
|
||||
"label": "Fuel Types"
|
||||
},
|
||||
@@ -1624,7 +1640,8 @@
|
||||
"placeholder": "1, 2, 3..."
|
||||
},
|
||||
"layer": {
|
||||
"label": "Layer"
|
||||
"label": "Layer",
|
||||
"placeholder": "0"
|
||||
},
|
||||
"leaf_cycle_singular": {
|
||||
"label": "Leaf Cycle",
|
||||
@@ -2216,9 +2233,13 @@
|
||||
"trees": {
|
||||
"label": "Trees"
|
||||
},
|
||||
"tunnel": {
|
||||
"tunnel_waterway": {
|
||||
"label": "Tunnel"
|
||||
},
|
||||
"tunnel": {
|
||||
"label": "Type",
|
||||
"placeholder": "Default"
|
||||
},
|
||||
"vending": {
|
||||
"label": "Type of Goods"
|
||||
},
|
||||
|
||||
@@ -37,6 +37,7 @@ export { rendererFeatures as Features } from './renderer/features';
|
||||
export { rendererMap as Map } from './renderer/map';
|
||||
export { rendererTileLayer as TileLayer } from './renderer/tile_layer';
|
||||
export { utilDetect as Detect } from './util/detect';
|
||||
export { uiPresetEditor as uiPreset } from './ui/preset_editor';
|
||||
|
||||
export var debug = false;
|
||||
|
||||
|
||||
+33
-24
@@ -10,7 +10,7 @@ import { uiRawMemberEditor } from './raw_member_editor';
|
||||
import { uiRawMembershipEditor } from './raw_membership_editor';
|
||||
import { uiRawTagEditor } from './raw_tag_editor';
|
||||
import { uiTagReference } from './tag_reference';
|
||||
import { uiPreset } from './preset';
|
||||
import { uiPresetEditor } from './preset_editor';
|
||||
import { utilRebind } from '../util';
|
||||
|
||||
|
||||
@@ -20,18 +20,18 @@ export function uiEntityEditor(context) {
|
||||
coalesceChanges = false,
|
||||
modified = false,
|
||||
base,
|
||||
id,
|
||||
entityId,
|
||||
activePreset,
|
||||
reference;
|
||||
|
||||
var presetEditor = uiPreset(context)
|
||||
var presetEditor = uiPresetEditor(context)
|
||||
.on('change', changeTags);
|
||||
var rawTagEditor = uiRawTagEditor(context)
|
||||
.on('change', changeTags);
|
||||
|
||||
|
||||
function entityEditor(selection) {
|
||||
var entity = context.entity(id),
|
||||
var entity = context.entity(entityId),
|
||||
tags = _.clone(entity.tags);
|
||||
|
||||
// Header
|
||||
@@ -63,7 +63,9 @@ export function uiEntityEditor(context) {
|
||||
.merge(enter);
|
||||
|
||||
header.selectAll('.preset-reset')
|
||||
.on('click', function() { dispatch.call('choose', this, activePreset); });
|
||||
.on('click', function() {
|
||||
dispatch.call('choose', this, activePreset);
|
||||
});
|
||||
|
||||
|
||||
// Body
|
||||
@@ -88,7 +90,7 @@ export function uiEntityEditor(context) {
|
||||
|
||||
enter
|
||||
.append('div')
|
||||
.attr('class', 'inspector-border inspector-preset');
|
||||
.attr('class', 'inspector-border preset-editor');
|
||||
|
||||
enter
|
||||
.append('div')
|
||||
@@ -119,35 +121,41 @@ export function uiEntityEditor(context) {
|
||||
.call(reference.body);
|
||||
|
||||
body.selectAll('.preset-reset')
|
||||
.on('click', function() { dispatch.call('choose', this, activePreset); });
|
||||
.on('click', function() {
|
||||
dispatch.call('choose', this, activePreset);
|
||||
});
|
||||
|
||||
body.select('.preset-list-item button')
|
||||
.call(uiPresetIcon()
|
||||
.geometry(context.geometry(id))
|
||||
.preset(activePreset));
|
||||
.geometry(context.geometry(entityId))
|
||||
.preset(activePreset)
|
||||
);
|
||||
|
||||
body.select('.preset-list-item .label')
|
||||
.text(activePreset.name());
|
||||
|
||||
body.select('.inspector-preset')
|
||||
body.select('.preset-editor')
|
||||
.call(presetEditor
|
||||
.preset(activePreset)
|
||||
.entityID(id)
|
||||
.entityID(entityId)
|
||||
.tags(tags)
|
||||
.state(state));
|
||||
.state(state)
|
||||
);
|
||||
|
||||
body.select('.raw-tag-editor')
|
||||
.call(rawTagEditor
|
||||
.preset(activePreset)
|
||||
.entityID(id)
|
||||
.entityID(entityId)
|
||||
.tags(tags)
|
||||
.state(state));
|
||||
.state(state)
|
||||
);
|
||||
|
||||
if (entity.type === 'relation') {
|
||||
body.select('.raw-member-editor')
|
||||
.style('display', 'block')
|
||||
.call(uiRawMemberEditor(context)
|
||||
.entityID(id));
|
||||
.entityID(entityId)
|
||||
);
|
||||
} else {
|
||||
body.select('.raw-member-editor')
|
||||
.style('display', 'none');
|
||||
@@ -155,7 +163,8 @@ export function uiEntityEditor(context) {
|
||||
|
||||
body.select('.raw-membership-editor')
|
||||
.call(uiRawMembershipEditor(context)
|
||||
.entityID(id));
|
||||
.entityID(entityId)
|
||||
);
|
||||
|
||||
body.select('.key-trap')
|
||||
.on('keydown.key-trap', function() {
|
||||
@@ -174,7 +183,7 @@ export function uiEntityEditor(context) {
|
||||
function historyChanged() {
|
||||
if (state === 'hide') return;
|
||||
|
||||
var entity = context.hasEntity(id),
|
||||
var entity = context.hasEntity(entityId),
|
||||
graph = context.graph();
|
||||
if (!entity) return;
|
||||
|
||||
@@ -226,7 +235,7 @@ export function uiEntityEditor(context) {
|
||||
// Tag changes that fire on input can all get coalesced into a single
|
||||
// history operation when the user leaves the field. #2342
|
||||
function changeTags(changed, onInput) {
|
||||
var entity = context.entity(id),
|
||||
var entity = context.entity(entityId),
|
||||
annotation = t('operations.change_tags.annotation'),
|
||||
tags = _.clone(entity.tags);
|
||||
|
||||
@@ -242,9 +251,9 @@ export function uiEntityEditor(context) {
|
||||
|
||||
if (!_.isEqual(entity.tags, tags)) {
|
||||
if (coalesceChanges) {
|
||||
context.overwrite(actionChangeTags(id, tags), annotation);
|
||||
context.overwrite(actionChangeTags(entityId, tags), annotation);
|
||||
} else {
|
||||
context.perform(actionChangeTags(id, tags), annotation);
|
||||
context.perform(actionChangeTags(entityId, tags), annotation);
|
||||
coalesceChanges = !!onInput;
|
||||
}
|
||||
}
|
||||
@@ -267,10 +276,10 @@ export function uiEntityEditor(context) {
|
||||
|
||||
|
||||
entityEditor.entityID = function(_) {
|
||||
if (!arguments.length) return id;
|
||||
id = _;
|
||||
if (!arguments.length) return entityId;
|
||||
entityId = _;
|
||||
base = context.graph();
|
||||
entityEditor.preset(context.presets().match(context.entity(id), base));
|
||||
entityEditor.preset(context.presets().match(context.entity(entityId), base));
|
||||
entityEditor.modified(false);
|
||||
coalesceChanges = false;
|
||||
return entityEditor;
|
||||
@@ -281,7 +290,7 @@ export function uiEntityEditor(context) {
|
||||
if (!arguments.length) return activePreset;
|
||||
if (_ !== activePreset) {
|
||||
activePreset = _;
|
||||
reference = uiTagReference(activePreset.reference(context.geometry(id)), context)
|
||||
reference = uiTagReference(activePreset.reference(context.geometry(entityId)), context)
|
||||
.showing(false);
|
||||
}
|
||||
return entityEditor;
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
import * as d3 from 'd3';
|
||||
import _ from 'lodash';
|
||||
import { textDirection } from '../util/locale';
|
||||
import { svgIcon } from '../svg';
|
||||
import { uiFields } from './fields';
|
||||
import { uiTagReference } from './tag_reference';
|
||||
import { utilRebind } from '../util';
|
||||
|
||||
|
||||
export function uiField(context, presetField, entity, options) {
|
||||
options = _.extend({
|
||||
show: true,
|
||||
wrap: true
|
||||
}, options);
|
||||
|
||||
var dispatch = d3.dispatch('change'),
|
||||
field = _.clone(presetField),
|
||||
state = '',
|
||||
tags = {};
|
||||
|
||||
|
||||
field.impl = uiFields[field.type](field, context)
|
||||
.on('change', function(t, onInput) {
|
||||
dispatch.call('change', field, t, onInput);
|
||||
});
|
||||
|
||||
if (field.impl.entity) {
|
||||
field.impl.entity(entity);
|
||||
}
|
||||
|
||||
field.keys = field.keys || [field.key];
|
||||
|
||||
field.show = options.show;
|
||||
|
||||
|
||||
function isModified() {
|
||||
var original = context.graph().base().entities[entity.id];
|
||||
return _.some(field.keys, function(key) {
|
||||
return original ? tags[key] !== original.tags[key] : tags[key];
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function isPresent() {
|
||||
return _.some(field.keys, function(key) {
|
||||
return tags[key];
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function revert(d) {
|
||||
d3.event.stopPropagation();
|
||||
d3.event.preventDefault();
|
||||
|
||||
var original = context.graph().base().entities[entity.id],
|
||||
t = {};
|
||||
d.keys.forEach(function(key) {
|
||||
t[key] = original ? original.tags[key] : undefined;
|
||||
});
|
||||
|
||||
dispatch.call('change', d, t);
|
||||
}
|
||||
|
||||
|
||||
function remove(d) {
|
||||
d3.event.stopPropagation();
|
||||
d3.event.preventDefault();
|
||||
|
||||
var t = {};
|
||||
d.keys.forEach(function(key) {
|
||||
t[key] = undefined;
|
||||
});
|
||||
|
||||
dispatch.call('change', d, t);
|
||||
}
|
||||
|
||||
|
||||
field.render = function(selection) {
|
||||
var container = selection.selectAll('.form-field')
|
||||
.data([field]);
|
||||
|
||||
// Enter
|
||||
var enter = container.enter()
|
||||
.append('div')
|
||||
.attr('class', function(d) { return 'form-field form-field-' + d.id; })
|
||||
.classed('nowrap', !options.wrap);
|
||||
|
||||
if (options.wrap) {
|
||||
var label = enter
|
||||
.append('label')
|
||||
.attr('class', 'form-label')
|
||||
.attr('for', function(d) { return 'preset-input-' + d.id; })
|
||||
.text(function(d) { return d.label(); });
|
||||
|
||||
var wrap = label
|
||||
.append('div')
|
||||
.attr('class', 'form-label-button-wrap');
|
||||
|
||||
wrap
|
||||
.append('button')
|
||||
.attr('class', 'remove-icon')
|
||||
.attr('tabindex', -1)
|
||||
.call(svgIcon('#operation-delete'));
|
||||
|
||||
wrap
|
||||
.append('button')
|
||||
.attr('class', 'modified-icon')
|
||||
.attr('tabindex', -1)
|
||||
.call(
|
||||
(textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo')
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Update
|
||||
container = container
|
||||
.merge(enter);
|
||||
|
||||
container.selectAll('.form-label-button-wrap .remove-icon')
|
||||
.on('click', remove);
|
||||
|
||||
container.selectAll('.form-label-button-wrap .modified-icon')
|
||||
.on('click', revert);
|
||||
|
||||
container
|
||||
.classed('modified', isModified())
|
||||
.classed('present', isPresent())
|
||||
.each(function(d) {
|
||||
if (options.wrap) {
|
||||
var referenceKey = d.key;
|
||||
if (d.type === 'multiCombo') { // lookup key without the trailing ':'
|
||||
referenceKey = referenceKey.replace(/:$/, '');
|
||||
}
|
||||
var reference = uiTagReference(d.reference || { key: referenceKey }, context);
|
||||
|
||||
if (state === 'hover') {
|
||||
reference.showing(false);
|
||||
}
|
||||
}
|
||||
|
||||
d3.select(this)
|
||||
.call(d.impl);
|
||||
|
||||
if (options.wrap) {
|
||||
d3.select(this)
|
||||
.call(reference.body)
|
||||
.select('.form-label-button-wrap')
|
||||
.call(reference.button);
|
||||
}
|
||||
|
||||
d.impl.tags(tags);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
field.state = function(_) {
|
||||
if (!arguments.length) return state;
|
||||
state = _;
|
||||
return field;
|
||||
};
|
||||
|
||||
|
||||
field.tags = function(_) {
|
||||
if (!arguments.length) return tags;
|
||||
tags = _;
|
||||
return field;
|
||||
};
|
||||
|
||||
|
||||
field.isShown = function() {
|
||||
return field.show || _.some(field.keys, function(key) { return !!tags[key]; });
|
||||
};
|
||||
|
||||
|
||||
field.focus = function() {
|
||||
field.impl.focus();
|
||||
};
|
||||
|
||||
|
||||
return utilRebind(field, dispatch, 'on');
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as d3 from 'd3';
|
||||
import { t } from '../../util/locale';
|
||||
import { dataPhoneFormats } from '../../../data/index';
|
||||
import { services } from '../../services/index';
|
||||
import { t, textDirection } from '../../util/locale';
|
||||
import { dataPhoneFormats } from '../../../data';
|
||||
import { services } from '../../services';
|
||||
import {
|
||||
utilGetSetValue,
|
||||
utilNoAuto,
|
||||
@@ -52,6 +52,8 @@ export function uiFieldText(field, context) {
|
||||
});
|
||||
|
||||
} else if (field.type === 'number') {
|
||||
var rtl = (textDirection === 'rtl');
|
||||
|
||||
input.attr('type', 'text');
|
||||
|
||||
var spinControl = selection.selectAll('.spin-control')
|
||||
@@ -63,14 +65,14 @@ export function uiFieldText(field, context) {
|
||||
|
||||
enter
|
||||
.append('button')
|
||||
.datum(-1)
|
||||
.attr('class', 'decrement')
|
||||
.datum(rtl ? 1 : -1)
|
||||
.attr('class', rtl ? 'increment' : 'decrement')
|
||||
.attr('tabindex', -1);
|
||||
|
||||
enter
|
||||
.append('button')
|
||||
.datum(1)
|
||||
.attr('class', 'increment')
|
||||
.datum(rtl ? -1 : 1)
|
||||
.attr('class', rtl ? 'decrement' : 'increment')
|
||||
.attr('tabindex', -1);
|
||||
|
||||
spinControl = spinControl
|
||||
|
||||
+66
-133
@@ -1,13 +1,7 @@
|
||||
import * as d3 from 'd3';
|
||||
import { t } from '../../util/locale';
|
||||
import { d3combobox } from '../../lib/d3.combobox.js';
|
||||
import { services } from '../../services/index';
|
||||
|
||||
import {
|
||||
utilGetSetValue,
|
||||
utilNoAuto,
|
||||
utilRebind
|
||||
} from '../../util';
|
||||
import { uiField } from '../field';
|
||||
import { utilRebind } from '../../util';
|
||||
|
||||
|
||||
export { uiFieldRadio as uiFieldStructureRadio };
|
||||
@@ -15,13 +9,12 @@ export { uiFieldRadio as uiFieldStructureRadio };
|
||||
|
||||
export function uiFieldRadio(field, context) {
|
||||
var dispatch = d3.dispatch('change'),
|
||||
taginfo = services.taginfo,
|
||||
placeholder = d3.select(null),
|
||||
wrap = d3.select(null),
|
||||
labels = d3.select(null),
|
||||
radios = d3.select(null),
|
||||
typeInput = d3.select(null),
|
||||
layerInput = d3.select(null),
|
||||
typeField,
|
||||
layerField,
|
||||
oldType = {},
|
||||
entity;
|
||||
|
||||
@@ -32,32 +25,6 @@ export function uiFieldRadio(field, context) {
|
||||
return !node.empty() && node.datum();
|
||||
}
|
||||
|
||||
// returns the tag value for a display value
|
||||
function tagValue(dispVal) {
|
||||
dispVal = snake(clean(dispVal || ''));
|
||||
return dispVal.toLowerCase() || 'yes';
|
||||
}
|
||||
|
||||
// returns the display value for a tag value
|
||||
function displayValue(tagVal) {
|
||||
tagVal = tagVal || '';
|
||||
return tagVal.toLowerCase() === 'yes' ? '' : unsnake(tagVal);
|
||||
}
|
||||
|
||||
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 radio(selection) {
|
||||
selection.classed('preset-radio', true);
|
||||
@@ -101,11 +68,16 @@ export function uiFieldRadio(field, context) {
|
||||
|
||||
radios = labels.selectAll('input')
|
||||
.on('change', changeRadio);
|
||||
|
||||
}
|
||||
|
||||
|
||||
function structureExtras(selection) {
|
||||
var selected = selectedKey();
|
||||
function structureExtras(selection, tags) {
|
||||
var selected = selectedKey(),
|
||||
type = context.presets().field(selected),
|
||||
layer = context.presets().field('layer'),
|
||||
showLayer = (selected === 'bridge' || selected === 'tunnel');
|
||||
|
||||
|
||||
var extrasWrap = selection.selectAll('.structure-extras-wrap')
|
||||
.data(selected ? [0] : []);
|
||||
@@ -127,55 +99,67 @@ export function uiFieldRadio(field, context) {
|
||||
|
||||
|
||||
// Type
|
||||
var typeItem = list.selectAll('.structure-type-item')
|
||||
.data([0]);
|
||||
if (type) {
|
||||
if (!typeField || typeField.id !== selected) {
|
||||
typeField = uiField(context, type, entity, { wrap: false })
|
||||
.on('change', changeType);
|
||||
}
|
||||
typeField.tags(tags);
|
||||
} else {
|
||||
typeField = null;
|
||||
}
|
||||
|
||||
var typeItem = list.selectAll('.structure-type-item')
|
||||
.data(typeField ? [typeField] : [], function(d) { return d.id; });
|
||||
|
||||
// Exit
|
||||
typeItem.exit()
|
||||
.remove();
|
||||
|
||||
// Enter
|
||||
var typeEnter = typeItem.enter()
|
||||
.append('li')
|
||||
.insert('li', ':first-child')
|
||||
.attr('class', 'cf structure-type-item');
|
||||
|
||||
typeEnter
|
||||
.append('span')
|
||||
.attr('class', 'col6 label structure-label-type')
|
||||
.attr('for', 'structure-input-type')
|
||||
.attr('for', 'preset-input-' + selected)
|
||||
.text(t('inspector.radio.structure.type'));
|
||||
|
||||
typeEnter
|
||||
.append('div')
|
||||
.attr('class', 'col6 structure-input-type-wrap')
|
||||
.append('input')
|
||||
.attr('type', 'text')
|
||||
.attr('class', 'structure-input-type')
|
||||
.attr('placeholder', t('inspector.radio.structure.default'))
|
||||
.call(utilNoAuto);
|
||||
.attr('class', 'col6 structure-input-type-wrap');
|
||||
|
||||
// Update
|
||||
typeItem = typeItem
|
||||
.merge(typeEnter);
|
||||
|
||||
typeInput = typeItem.selectAll('.structure-input-type');
|
||||
|
||||
if (taginfo) {
|
||||
typeInput
|
||||
.call(d3combobox()
|
||||
.container(context.container())
|
||||
.fetcher(typeFetcher)
|
||||
);
|
||||
if (typeField) {
|
||||
typeItem.selectAll('.structure-input-type-wrap')
|
||||
.call(typeField.render);
|
||||
}
|
||||
|
||||
typeInput
|
||||
.on('change', changeType)
|
||||
.on('blur', changeType);
|
||||
|
||||
|
||||
// Layer
|
||||
var showLayer = (selected === 'bridge' || selected === 'tunnel');
|
||||
if (layer && showLayer) {
|
||||
if (!layerField) {
|
||||
layerField = uiField(context, layer, entity, { wrap: false })
|
||||
.on('change', changeLayer);
|
||||
}
|
||||
layerField.tags(tags);
|
||||
} else {
|
||||
layerField = null;
|
||||
}
|
||||
|
||||
var layerItem = list.selectAll('.structure-layer-item')
|
||||
.data(showLayer ? [0] : []);
|
||||
.data(layerField ? [layerField] : []);
|
||||
|
||||
// Exit
|
||||
layerItem.exit()
|
||||
.remove();
|
||||
|
||||
// Enter
|
||||
var layerEnter = layerItem.enter()
|
||||
.append('li')
|
||||
.attr('class', 'cf structure-layer-item');
|
||||
@@ -183,87 +167,39 @@ export function uiFieldRadio(field, context) {
|
||||
layerEnter
|
||||
.append('span')
|
||||
.attr('class', 'col6 label structure-label-layer')
|
||||
.attr('for', 'structure-input-layer')
|
||||
.attr('for', 'preset-input-layer')
|
||||
.text(t('inspector.radio.structure.layer'));
|
||||
|
||||
layerEnter
|
||||
.append('div')
|
||||
.attr('class', 'col6 structure-input-layer-wrap')
|
||||
.append('input')
|
||||
.attr('type', 'text')
|
||||
.attr('class', 'structure-input-layer')
|
||||
.attr('placeholder', '0')
|
||||
.call(utilNoAuto);
|
||||
|
||||
var spin = layerEnter
|
||||
.append('div')
|
||||
.attr('class', 'spin-control');
|
||||
|
||||
spin
|
||||
.append('button')
|
||||
.datum(-1)
|
||||
.attr('class', 'decrement')
|
||||
.attr('tabindex', -1);
|
||||
|
||||
spin
|
||||
.append('button')
|
||||
.datum(1)
|
||||
.attr('class', 'increment')
|
||||
.attr('tabindex', -1);
|
||||
.attr('class', 'col6 structure-input-layer-wrap');
|
||||
|
||||
// Update
|
||||
layerItem = layerItem
|
||||
.merge(layerEnter);
|
||||
|
||||
layerInput = layerItem.selectAll('.structure-input-layer')
|
||||
.on('change', changeLayer)
|
||||
.on('blur', changeLayer);
|
||||
|
||||
layerItem.selectAll('button')
|
||||
.on('click', function(d) {
|
||||
d3.event.preventDefault();
|
||||
var num = parseInt(layerInput.node().value || 0, 10);
|
||||
if (!isNaN(num)) layerInput.node().value = num + d;
|
||||
changeLayer();
|
||||
});
|
||||
|
||||
if (layerField) {
|
||||
layerItem.selectAll('.structure-input-layer-wrap')
|
||||
.call(layerField.render);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function typeFetcher(q, callback) {
|
||||
taginfo.values({
|
||||
debounce: true,
|
||||
key: selectedKey(),
|
||||
query: q
|
||||
}, function(err, data) {
|
||||
if (err) return;
|
||||
var comboData = data.map(function(d) {
|
||||
return {
|
||||
key: d.value,
|
||||
value: unsnake(d.value),
|
||||
title: d.title
|
||||
};
|
||||
});
|
||||
if (callback) callback(comboData);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function changeType() {
|
||||
var key = selectedKey(),
|
||||
t = {};
|
||||
|
||||
function changeType(t, onInput) {
|
||||
var key = selectedKey();
|
||||
if (!key) return;
|
||||
var val = tagValue(utilGetSetValue(typeInput));
|
||||
t[key] = val;
|
||||
|
||||
var val = t[key];
|
||||
if (val !== 'no') oldType[key] = val;
|
||||
dispatch.call('change', this, t);
|
||||
dispatch.call('change', this, t, onInput);
|
||||
}
|
||||
|
||||
|
||||
function changeLayer() {
|
||||
// note: don't use utilGetSetValue here because we want 0 to be falsy.
|
||||
var t = { layer: layerInput.node().value || undefined };
|
||||
dispatch.call('change', this, t);
|
||||
function changeLayer(t, onInput) {
|
||||
if (t.layer === '0') {
|
||||
t.layer = undefined;
|
||||
}
|
||||
dispatch.call('change', this, t, onInput);
|
||||
}
|
||||
|
||||
|
||||
@@ -314,19 +250,16 @@ export function uiFieldRadio(field, context) {
|
||||
radios.property('checked', checked);
|
||||
|
||||
var selection = radios.filter(function() { return this.checked; });
|
||||
var typeVal = '';
|
||||
|
||||
if (selection.empty()) {
|
||||
placeholder.text(t('inspector.none'));
|
||||
} else {
|
||||
placeholder.text(selection.attr('value'));
|
||||
typeVal = oldType[selection.datum()] = tags[selection.datum()];
|
||||
oldType[selection.datum()] = tags[selection.datum()];
|
||||
}
|
||||
|
||||
if (field.type === 'structureRadio') {
|
||||
wrap.call(structureExtras);
|
||||
utilGetSetValue(typeInput, displayValue(typeVal) || '');
|
||||
utilGetSetValue(layerInput, tags.layer || '');
|
||||
wrap.call(structureExtras, tags);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+2
-1
@@ -13,6 +13,7 @@ export { uiEditMenu } from './edit_menu';
|
||||
export { uiEntityEditor } from './entity_editor';
|
||||
export { uiFeatureInfo } from './feature_info';
|
||||
export { uiFeatureList } from './feature_list';
|
||||
export { uiField } from './field';
|
||||
export { uiFlash } from './flash';
|
||||
export { uiFullScreen } from './full_screen';
|
||||
export { uiGeolocate } from './geolocate';
|
||||
@@ -26,7 +27,7 @@ export { uiMapInMap } from './map_in_map';
|
||||
export { uiModal } from './modal';
|
||||
export { uiModes } from './modes';
|
||||
export { uiNotice } from './notice';
|
||||
export { uiPreset } from './preset';
|
||||
export { uiPresetEditor } from './preset_editor';
|
||||
export { uiPresetIcon } from './preset_icon';
|
||||
export { uiPresetList } from './preset_list';
|
||||
export { uiRadialMenu } from './radial_menu';
|
||||
|
||||
@@ -326,7 +326,7 @@ export function uiIntroNavigation(context, reveal) {
|
||||
|
||||
var onClick = function() { continueTo(closeTownHall); };
|
||||
|
||||
reveal('.inspector-body .inspector-preset',
|
||||
reveal('.inspector-body .preset-editor',
|
||||
t('intro.navigation.fields_townhall'),
|
||||
{ buttonText: t('intro.ok'), buttonCallback: onClick }
|
||||
);
|
||||
|
||||
@@ -1,327 +0,0 @@
|
||||
import * as d3 from 'd3';
|
||||
import _ from 'lodash';
|
||||
import { d3combobox } from '../lib/d3.combobox.js';
|
||||
import { t, textDirection } from '../util/locale';
|
||||
import { modeBrowse } from '../modes/index';
|
||||
import { svgIcon } from '../svg/index';
|
||||
import { uiDisclosure } from './disclosure';
|
||||
import { uiFields } from './fields/index';
|
||||
import { uiTagReference } from './tag_reference';
|
||||
import {
|
||||
utilGetSetValue,
|
||||
utilNoAuto,
|
||||
utilRebind
|
||||
} from '../util';
|
||||
|
||||
|
||||
export function uiPreset(context) {
|
||||
var dispatch = d3.dispatch('change'),
|
||||
expandedPreference = (context.storage('preset_fields.expanded') !== 'false'),
|
||||
state,
|
||||
fieldsArr,
|
||||
preset,
|
||||
tags,
|
||||
id;
|
||||
|
||||
|
||||
// Field Constructor
|
||||
function UIField(field, entity, show) {
|
||||
field = _.clone(field);
|
||||
|
||||
field.input = uiFields[field.type](field, context)
|
||||
.on('change', function(t, onInput) {
|
||||
dispatch.call('change', field, t, onInput);
|
||||
});
|
||||
|
||||
if (field.input.entity) field.input.entity(entity);
|
||||
|
||||
field.keys = field.keys || [field.key];
|
||||
|
||||
field.show = show;
|
||||
|
||||
field.shown = function() {
|
||||
return field.show || _.some(field.keys, function(key) { return !!tags[key]; });
|
||||
};
|
||||
|
||||
field.modified = function() {
|
||||
var original = context.graph().base().entities[entity.id];
|
||||
return _.some(field.keys, function(key) {
|
||||
return original ? tags[key] !== original.tags[key] : tags[key];
|
||||
});
|
||||
};
|
||||
|
||||
field.revert = function() {
|
||||
var original = context.graph().base().entities[entity.id],
|
||||
t = {};
|
||||
field.keys.forEach(function(key) {
|
||||
t[key] = original ? original.tags[key] : undefined;
|
||||
});
|
||||
return t;
|
||||
};
|
||||
|
||||
field.present = function() {
|
||||
return _.some(field.keys, function(key) {
|
||||
return tags[key];
|
||||
});
|
||||
};
|
||||
|
||||
field.remove = function() {
|
||||
var t = {};
|
||||
field.keys.forEach(function(key) {
|
||||
t[key] = undefined;
|
||||
});
|
||||
return t;
|
||||
};
|
||||
|
||||
return field;
|
||||
}
|
||||
|
||||
|
||||
function fieldKey(field) {
|
||||
return field.id;
|
||||
}
|
||||
|
||||
|
||||
function presets(selection) {
|
||||
selection.call(uiDisclosure()
|
||||
.title(t('inspector.all_fields'))
|
||||
.expanded(expandedPreference)
|
||||
.on('toggled', toggled)
|
||||
.content(content)
|
||||
);
|
||||
|
||||
function toggled(expanded) {
|
||||
expandedPreference = expanded;
|
||||
context.storage('preset_fields.expanded', expanded);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function content(selection) {
|
||||
if (!fieldsArr) {
|
||||
var entity = context.entity(id),
|
||||
geometry = context.geometry(id),
|
||||
presets = context.presets();
|
||||
|
||||
fieldsArr = [];
|
||||
|
||||
preset.fields.forEach(function(field) {
|
||||
if (field.matchGeometry(geometry)) {
|
||||
fieldsArr.push(UIField(field, entity, true));
|
||||
}
|
||||
});
|
||||
|
||||
if (entity.isHighwayIntersection(context.graph()) && presets.field('restrictions')) {
|
||||
fieldsArr.push(UIField(presets.field('restrictions'), entity, true));
|
||||
}
|
||||
|
||||
presets.universal().forEach(function(field) {
|
||||
if (preset.fields.indexOf(field) < 0) {
|
||||
fieldsArr.push(UIField(field, entity));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var shown = fieldsArr.filter(function(field) { return field.shown(); }),
|
||||
notShown = fieldsArr.filter(function(field) { return !field.shown(); });
|
||||
|
||||
|
||||
var form = selection.selectAll('.preset-form')
|
||||
.data([0]);
|
||||
|
||||
form = form.enter()
|
||||
.append('div')
|
||||
.attr('class', 'preset-form inspector-inner fillL3')
|
||||
.merge(form);
|
||||
|
||||
|
||||
var fields = form.selectAll('.form-field')
|
||||
.data(shown, fieldKey);
|
||||
|
||||
fields.exit()
|
||||
.remove();
|
||||
|
||||
// Enter
|
||||
var enter = fields.enter()
|
||||
.append('div')
|
||||
.attr('class', function(field) {
|
||||
return 'form-field form-field-' + field.id;
|
||||
});
|
||||
|
||||
var label = enter
|
||||
.append('label')
|
||||
.attr('class', 'form-label')
|
||||
.attr('for', function(field) { return 'preset-input-' + field.id; })
|
||||
.text(function(field) { return field.label(); });
|
||||
|
||||
var wrap = label
|
||||
.append('div')
|
||||
.attr('class', 'form-label-button-wrap');
|
||||
|
||||
wrap.append('button')
|
||||
.attr('class', 'remove-icon')
|
||||
.attr('tabindex', -1)
|
||||
.call(svgIcon('#operation-delete'));
|
||||
|
||||
wrap.append('button')
|
||||
.attr('class', 'modified-icon')
|
||||
.attr('tabindex', -1)
|
||||
.call(
|
||||
(textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo')
|
||||
);
|
||||
|
||||
|
||||
// Update
|
||||
fields = fields
|
||||
.merge(enter);
|
||||
|
||||
fields.selectAll('.form-label-button-wrap .remove-icon')
|
||||
.on('click', remove);
|
||||
|
||||
fields.selectAll('.modified-icon')
|
||||
.on('click', revert);
|
||||
|
||||
fields
|
||||
.order()
|
||||
.classed('modified', function(field) { return field.modified(); })
|
||||
.classed('present', function(field) { return field.present(); })
|
||||
.each(function(field) {
|
||||
var referenceKey = field.key;
|
||||
if (field.type === 'multiCombo') { // lookup key without the trailing ':'
|
||||
referenceKey = referenceKey.replace(/:$/, '');
|
||||
}
|
||||
var reference = uiTagReference(field.reference || { key: referenceKey }, context);
|
||||
|
||||
if (state === 'hover') {
|
||||
reference.showing(false);
|
||||
}
|
||||
|
||||
d3.select(this)
|
||||
.call(field.input)
|
||||
.selectAll('input')
|
||||
.on('keydown', function() {
|
||||
// if user presses enter, and combobox is not active, accept edits..
|
||||
if (d3.event.keyCode === 13 && d3.select('.combobox').empty()) {
|
||||
context.enter(modeBrowse(context));
|
||||
}
|
||||
});
|
||||
|
||||
d3.select(this)
|
||||
.call(reference.body)
|
||||
.select('.form-label-button-wrap')
|
||||
.call(reference.button);
|
||||
|
||||
field.input.tags(tags);
|
||||
});
|
||||
|
||||
notShown = notShown.map(function(field) {
|
||||
return {
|
||||
title: field.label(),
|
||||
value: field.label(),
|
||||
field: field
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
var more = selection.selectAll('.more-fields')
|
||||
.data((notShown.length > 0) ? [0] : []);
|
||||
|
||||
more.exit()
|
||||
.remove();
|
||||
|
||||
more = more.enter()
|
||||
.append('div')
|
||||
.attr('class', 'more-fields')
|
||||
.append('label')
|
||||
.text(t('inspector.add_fields'))
|
||||
.merge(more);
|
||||
|
||||
|
||||
var input = more.selectAll('.value')
|
||||
.data([0]);
|
||||
|
||||
input.exit()
|
||||
.remove();
|
||||
|
||||
input = input.enter()
|
||||
.append('input')
|
||||
.attr('class', 'value')
|
||||
.attr('type', 'text')
|
||||
.call(utilNoAuto)
|
||||
.merge(input);
|
||||
|
||||
input
|
||||
.call(utilGetSetValue, '')
|
||||
.attr('placeholder', function() {
|
||||
var placeholder = [];
|
||||
for (var field in notShown) {
|
||||
placeholder.push(notShown[field].title);
|
||||
}
|
||||
return placeholder.slice(0,3).join(', ') + ((placeholder.length > 3) ? '…' : '');
|
||||
})
|
||||
.call(d3combobox()
|
||||
.container(context.container())
|
||||
.data(notShown)
|
||||
.minItems(1)
|
||||
.on('accept', show)
|
||||
);
|
||||
|
||||
|
||||
function show(field) {
|
||||
field = field.field;
|
||||
field.show = true;
|
||||
content(selection);
|
||||
field.input.focus();
|
||||
}
|
||||
|
||||
|
||||
function revert(field) {
|
||||
d3.event.stopPropagation();
|
||||
d3.event.preventDefault();
|
||||
dispatch.call('change', field, field.revert());
|
||||
}
|
||||
|
||||
|
||||
function remove(field) {
|
||||
d3.event.stopPropagation();
|
||||
d3.event.preventDefault();
|
||||
dispatch.call('change', field, field.remove());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
presets.preset = function(_) {
|
||||
if (!arguments.length) return preset;
|
||||
if (preset && preset.id === _.id) return presets;
|
||||
preset = _;
|
||||
fieldsArr = null;
|
||||
return presets;
|
||||
};
|
||||
|
||||
|
||||
presets.state = function(_) {
|
||||
if (!arguments.length) return state;
|
||||
state = _;
|
||||
return presets;
|
||||
};
|
||||
|
||||
|
||||
presets.tags = function(_) {
|
||||
if (!arguments.length) return tags;
|
||||
tags = _;
|
||||
// Don't reset fieldsArr here.
|
||||
return presets;
|
||||
};
|
||||
|
||||
|
||||
presets.entityID = function(_) {
|
||||
if (!arguments.length) return id;
|
||||
if (id === _) return presets;
|
||||
id = _;
|
||||
fieldsArr = null;
|
||||
return presets;
|
||||
};
|
||||
|
||||
|
||||
return utilRebind(presets, dispatch, 'on');
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
import * as d3 from 'd3';
|
||||
import { d3combobox } from '../lib/d3.combobox.js';
|
||||
import { t } from '../util/locale';
|
||||
import { modeBrowse } from '../modes';
|
||||
import { uiDisclosure } from './disclosure';
|
||||
import { uiField } from './field';
|
||||
import {
|
||||
utilGetSetValue,
|
||||
utilNoAuto,
|
||||
utilRebind
|
||||
} from '../util';
|
||||
|
||||
|
||||
export function uiPresetEditor(context) {
|
||||
var dispatch = d3.dispatch('change'),
|
||||
expandedPreference = (context.storage('preset_fields.expanded') !== 'false'),
|
||||
state,
|
||||
fieldsArr,
|
||||
preset,
|
||||
tags,
|
||||
entityId;
|
||||
|
||||
|
||||
function presetEditor(selection) {
|
||||
selection.call(uiDisclosure()
|
||||
.title(t('inspector.all_fields'))
|
||||
.expanded(expandedPreference)
|
||||
.on('toggled', toggled)
|
||||
.content(render)
|
||||
);
|
||||
|
||||
function toggled(expanded) {
|
||||
expandedPreference = expanded;
|
||||
context.storage('preset_fields.expanded', expanded);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function render(selection) {
|
||||
if (!fieldsArr) {
|
||||
var entity = context.entity(entityId),
|
||||
geometry = context.geometry(entityId),
|
||||
presets = context.presets();
|
||||
|
||||
fieldsArr = [];
|
||||
|
||||
preset.fields.forEach(function(field) {
|
||||
if (field.matchGeometry(geometry)) {
|
||||
fieldsArr.push(
|
||||
uiField(context, field, entity)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
if (entity.isHighwayIntersection(context.graph()) && presets.field('restrictions')) {
|
||||
fieldsArr.push(
|
||||
uiField(context, presets.field('restrictions'), entity)
|
||||
);
|
||||
}
|
||||
|
||||
presets.universal().forEach(function(field) {
|
||||
if (preset.fields.indexOf(field) === -1) {
|
||||
fieldsArr.push(
|
||||
uiField(context, field, entity, { show: false })
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
fieldsArr.forEach(function(field) {
|
||||
field
|
||||
.on('change', function(t, onInput) {
|
||||
dispatch.call('change', field, t, onInput);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fieldsArr.forEach(function(field) {
|
||||
field
|
||||
.state(state)
|
||||
.tags(tags);
|
||||
});
|
||||
|
||||
var shown = fieldsArr.filter(function(field) { return field.isShown(); }),
|
||||
notShown = fieldsArr.filter(function(field) { return !field.isShown(); });
|
||||
|
||||
|
||||
var form = selection.selectAll('.preset-form')
|
||||
.data([0]);
|
||||
|
||||
form = form.enter()
|
||||
.append('div')
|
||||
.attr('class', 'preset-form inspector-inner fillL3')
|
||||
.merge(form);
|
||||
|
||||
|
||||
var fields = form.selectAll('.wrap-form-field')
|
||||
.data(shown, function(d) { return d.id; });
|
||||
|
||||
fields.exit()
|
||||
.remove();
|
||||
|
||||
// Enter
|
||||
var enter = fields.enter()
|
||||
.append('div')
|
||||
.attr('class', function(d) { return 'wrap-form-field wrap-form-field-' + d.id; });
|
||||
|
||||
// Update
|
||||
fields = fields
|
||||
.merge(enter);
|
||||
|
||||
fields
|
||||
.order()
|
||||
.each(function(d) {
|
||||
d3.select(this)
|
||||
.call(d.render)
|
||||
.selectAll('input')
|
||||
.on('keydown', function() {
|
||||
// if user presses enter, and combobox is not active, accept edits..
|
||||
if (d3.event.keyCode === 13 && d3.select('.combobox').empty()) {
|
||||
context.enter(modeBrowse(context));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
notShown = notShown.map(function(field) {
|
||||
return {
|
||||
title: field.label(),
|
||||
value: field.label(),
|
||||
field: field
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
var more = selection.selectAll('.more-fields')
|
||||
.data((notShown.length > 0) ? [0] : []);
|
||||
|
||||
more.exit()
|
||||
.remove();
|
||||
|
||||
more = more.enter()
|
||||
.append('div')
|
||||
.attr('class', 'more-fields')
|
||||
.append('label')
|
||||
.text(t('inspector.add_fields'))
|
||||
.merge(more);
|
||||
|
||||
|
||||
var input = more.selectAll('.value')
|
||||
.data([0]);
|
||||
|
||||
input.exit()
|
||||
.remove();
|
||||
|
||||
input = input.enter()
|
||||
.append('input')
|
||||
.attr('class', 'value')
|
||||
.attr('type', 'text')
|
||||
.call(utilNoAuto)
|
||||
.merge(input);
|
||||
|
||||
input
|
||||
.call(utilGetSetValue, '')
|
||||
.attr('placeholder', function() {
|
||||
var placeholder = [];
|
||||
for (var field in notShown) {
|
||||
placeholder.push(notShown[field].title);
|
||||
}
|
||||
return placeholder.slice(0,3).join(', ') + ((placeholder.length > 3) ? '…' : '');
|
||||
})
|
||||
.call(d3combobox()
|
||||
.container(context.container())
|
||||
.data(notShown)
|
||||
.minItems(1)
|
||||
.on('accept', function (d) {
|
||||
var field = d.field;
|
||||
field.show = true;
|
||||
render(selection);
|
||||
field.focus();
|
||||
})
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
presetEditor.preset = function(_) {
|
||||
if (!arguments.length) return preset;
|
||||
if (preset && preset.id === _.id) return presetEditor;
|
||||
preset = _;
|
||||
fieldsArr = null;
|
||||
return presetEditor;
|
||||
};
|
||||
|
||||
|
||||
presetEditor.state = function(_) {
|
||||
if (!arguments.length) return state;
|
||||
state = _;
|
||||
return presetEditor;
|
||||
};
|
||||
|
||||
|
||||
presetEditor.tags = function(_) {
|
||||
if (!arguments.length) return tags;
|
||||
tags = _;
|
||||
// Don't reset fieldsArr here.
|
||||
return presetEditor;
|
||||
};
|
||||
|
||||
|
||||
presetEditor.entityID = function(_) {
|
||||
if (!arguments.length) return entityId;
|
||||
if (entityId === _) return presetEditor;
|
||||
entityId = _;
|
||||
fieldsArr = null;
|
||||
return presetEditor;
|
||||
};
|
||||
|
||||
|
||||
return utilRebind(presetEditor, dispatch, 'on');
|
||||
}
|
||||
Reference in New Issue
Block a user