mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-19 06:58:32 +02:00
Use live bound object for presets object, change context.presets() getter
This commit is contained in:
@@ -145,7 +145,7 @@ certain parts of the iD code to be replaced at runtime by custom code or data.
|
||||
|
||||
iD is written in a modular style and bundled with [rollup.js](http://rollupjs.org/),
|
||||
which makes hot code replacement tricky. (ES6 module exports are
|
||||
[immutable bindings](http://www.2ality.com/2015/07/es6-module-exports.html)).
|
||||
[immutable live bindings](http://www.2ality.com/2015/07/es6-module-exports.html)).
|
||||
Because of this, the parts of iD which are designed for customization are exported
|
||||
as live bound objects that can be overriden at runtime _before initializing the iD context_.
|
||||
|
||||
@@ -169,7 +169,9 @@ delete iD.services.mapillary;
|
||||
### Background Imagery
|
||||
|
||||
iD's background imagery database is stored in the `iD.data.imagery` array and can be
|
||||
overridden. (Note that the "None" and "Custom" options will always be shown in the list)
|
||||
overridden or modified prior to creating the iD context.
|
||||
|
||||
Note that the "None" and "Custom" options will always be shown in the list.
|
||||
|
||||
To remove all imagery from iD:
|
||||
```js
|
||||
@@ -213,16 +215,59 @@ For more details about the `iD.data.imagery` structure, see
|
||||
|
||||
### Presets
|
||||
|
||||
iD can use external presets exclusively or along with the default OpenStreetMap presets. This is configured using the `context.presets` accessor. To use external presets alone, initialize the iD context with a custom `Presets` object:
|
||||
iD's preset database is stored in the `iD.data.presets` object and can be overridden
|
||||
or modified prior to creating the iD context.
|
||||
|
||||
The format of the `presets` object is
|
||||
[documented here](https://github.com/openstreetmap/iD/tree/master/data/presets#custom-presets).
|
||||
|
||||
To add a new preset to iD's existing preset database.
|
||||
```js
|
||||
|
||||
var id = iD.Context()
|
||||
.presets(customPresets);
|
||||
|
||||
iD.data.presets.presets["aerialway/zipline"] = {
|
||||
geometry: ["line"],
|
||||
fields: ["incline"],
|
||||
tags: { "aerialway": "zip_line" },
|
||||
name: "Zipline"
|
||||
};
|
||||
```
|
||||
|
||||
The format of the Preset object is [documented here](https://github.com/openstreetmap/iD/tree/master/data/presets#custom-presets).
|
||||
To completely replace iD's default presets with your own:
|
||||
```js
|
||||
iD.data.presets = myPresets;
|
||||
```
|
||||
|
||||
To run iD with the minimal set of presets that only match basic geometry types:
|
||||
```js
|
||||
iD.data.presets = {
|
||||
presets: {
|
||||
"area": {
|
||||
"name": "Area",
|
||||
"tags": {},
|
||||
"geometry": ["area"]
|
||||
},
|
||||
"line": {
|
||||
"name": "Line",
|
||||
"tags": {},
|
||||
"geometry": ["line"]
|
||||
},
|
||||
"point": {
|
||||
"name": "Point",
|
||||
"tags": {},
|
||||
"geometry": ["point"]
|
||||
},
|
||||
"vertex": {
|
||||
"name": "Vertex",
|
||||
"tags": {},
|
||||
"geometry": ["vertex"]
|
||||
},
|
||||
"relation": {
|
||||
"name": "Relation",
|
||||
"tags": {},
|
||||
"geometry": ["relation"]
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
### Minimum Editable Zoom
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
* :warning: Flattened namespace means that all functions have changed names (#3479)
|
||||
* e.g. `iD.actions.Move` -> `iD.actionMove`, `iD.geo.Extent` -> `iD.geoExtent`
|
||||
* Many deprecated names are still exported as symbols, e.g. `iD.Context` - we will remove these eventually
|
||||
* :warning: Customized iD deployments can manipulate live objects, rather than iD.Context accessors
|
||||
* No longer need to call things like `presets()`, `imagery()`, `taginfo()` when creating `iD.Context`
|
||||
* See [API.md](https://github.com/openstreetmap/iD/blob/master/API.md#customized-deployments) for details on customized deployments
|
||||
* :warning: iD has upgraded to the latest released versions of d3, lodash, rbush, etc.
|
||||
* d3 no longer adds itself to the global namespace, but can now be accessed via `iD.d3`
|
||||
* :warning: iD now uses `npm` scripts for all build processes
|
||||
|
||||
+8
-9
@@ -12,19 +12,18 @@ export { default as dataImperial } from './imperial.json';
|
||||
export { default as dataDriveLeft } from './drive-left.json';
|
||||
export { en as dataEn } from '../dist/locales/en.json';
|
||||
|
||||
import { dataImagery } from './imagery.json';
|
||||
import { presets } from './presets/presets.json';
|
||||
import { defaults } from './presets/defaults.json';
|
||||
import { categories } from './presets/categories.json';
|
||||
import { fields } from './presets/fields.json';
|
||||
|
||||
export var dataPresets = {
|
||||
presets: presets,
|
||||
defaults: defaults,
|
||||
categories: categories,
|
||||
fields: fields
|
||||
};
|
||||
|
||||
import { dataImagery } from './imagery.json';
|
||||
export var data = {
|
||||
imagery: dataImagery
|
||||
imagery: dataImagery,
|
||||
presets: {
|
||||
presets: presets,
|
||||
defaults: defaults,
|
||||
categories: categories,
|
||||
fields: fields
|
||||
}
|
||||
};
|
||||
|
||||
@@ -274,6 +274,12 @@ For example:
|
||||
"tags": {},
|
||||
"geometry": ["vertex"],
|
||||
"matchScore": 0.1
|
||||
},
|
||||
"relation": {
|
||||
"name": "Relation",
|
||||
"tags": {},
|
||||
"geometry": ["relation"],
|
||||
"matchScore": 0.1
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Vendored
+1
-3
@@ -37,9 +37,7 @@
|
||||
document.getElementById('id-container').innerHTML = 'Sorry, your browser is not currently supported. Please use Potlatch 2 to edit the map.';
|
||||
document.getElementById('id-container').className = 'unsupported';
|
||||
} else {
|
||||
var id = iD.Context()
|
||||
.presets(iD.dataPresets);
|
||||
|
||||
var id = iD.Context();
|
||||
id.ui()(document.getElementById('id-container'));
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
<script>
|
||||
|
||||
id = iD.Context()
|
||||
.presets(iD.dataPresets)
|
||||
.assetPath('dist/');
|
||||
|
||||
id.ui()(document.getElementById('id-container'), function() {
|
||||
|
||||
+9
-12
@@ -5,7 +5,7 @@ import { coreHistory } from './history';
|
||||
import { dataLocales, dataEn } from '../../data/index';
|
||||
import { geoRawMercator } from '../geo/raw_mercator';
|
||||
import { modeSelect } from '../modes/select';
|
||||
import { presetInit } from '../presets/init';
|
||||
import { presetIndex } from '../presets/index';
|
||||
import { rendererBackground } from '../renderer/background';
|
||||
import { rendererFeatures } from '../renderer/features';
|
||||
import { rendererMap } from '../renderer/map';
|
||||
@@ -212,6 +212,11 @@ export function coreContext() {
|
||||
};
|
||||
|
||||
|
||||
/* Presets */
|
||||
var presets;
|
||||
context.presets = function() { return presets; };
|
||||
|
||||
|
||||
/* Map */
|
||||
var map;
|
||||
context.map = function() { return map; };
|
||||
@@ -249,16 +254,6 @@ export function coreContext() {
|
||||
};
|
||||
|
||||
|
||||
/* Presets */
|
||||
var presets;
|
||||
context.presets = function(_) {
|
||||
if (!arguments.length) return presets;
|
||||
presets.load(_);
|
||||
areaKeys = presets.areaKeys();
|
||||
return context;
|
||||
};
|
||||
|
||||
|
||||
/* Container */
|
||||
var container, embed;
|
||||
context.container = function(_) {
|
||||
@@ -389,6 +384,7 @@ export function coreContext() {
|
||||
|
||||
background = rendererBackground(context);
|
||||
features = rendererFeatures(context);
|
||||
presets = presetIndex();
|
||||
|
||||
map = rendererMap(context);
|
||||
context.mouse = map.mouse;
|
||||
@@ -401,7 +397,8 @@ export function coreContext() {
|
||||
context.redrawEnable = map.redrawEnable;
|
||||
|
||||
background.init();
|
||||
presets = presetInit();
|
||||
presets.init();
|
||||
areaKeys = presets.areaKeys();
|
||||
|
||||
_.each(services, function(service) {
|
||||
if (service && typeof service.init === 'function') {
|
||||
|
||||
+10
-6
@@ -244,10 +244,11 @@ export function modeSelect(context, selectedIDs) {
|
||||
return;
|
||||
}
|
||||
|
||||
var parent = singularParent();
|
||||
if (parent) {
|
||||
surface.selectAll('.related')
|
||||
.classed('related', false);
|
||||
surface.selectAll('.related')
|
||||
.classed('related', false);
|
||||
|
||||
singularParent();
|
||||
if (relatedParent) {
|
||||
surface.selectAll(utilEntitySelector([relatedParent]))
|
||||
.classed('related', true);
|
||||
}
|
||||
@@ -363,8 +364,11 @@ export function modeSelect(context, selectedIDs) {
|
||||
var surface = context.surface();
|
||||
surface.selectAll('.related')
|
||||
.classed('related', false);
|
||||
surface.selectAll(utilEntitySelector([relatedParent]))
|
||||
.classed('related', true);
|
||||
|
||||
if (relatedParent) {
|
||||
surface.selectAll(utilEntitySelector([relatedParent]))
|
||||
.classed('related', true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+177
-5
@@ -1,5 +1,177 @@
|
||||
export { presetCategory } from './category.js';
|
||||
export { presetCollection } from './collection.js';
|
||||
export { presetField } from './field.js';
|
||||
export { presetInit } from './init.js';
|
||||
export { presetPreset } from './preset.js';
|
||||
import _ from 'lodash';
|
||||
import { data } from '../../data/index';
|
||||
import { presetCategory } from './category';
|
||||
import { presetCollection } from './collection';
|
||||
import { presetField } from './field';
|
||||
import { presetPreset } from './preset';
|
||||
|
||||
export { presetCategory };
|
||||
export { presetCollection };
|
||||
export { presetField };
|
||||
export { presetPreset };
|
||||
|
||||
|
||||
export function presetIndex() {
|
||||
// a presetCollection with methods for
|
||||
// loading new data and returning defaults
|
||||
|
||||
var all = presetCollection([]),
|
||||
defaults = { area: all, line: all, point: all, vertex: all, relation: all },
|
||||
fields = {},
|
||||
universal = [],
|
||||
recent = presetCollection([]);
|
||||
|
||||
// Index of presets by (geometry, tag key).
|
||||
var index = {
|
||||
point: {},
|
||||
vertex: {},
|
||||
line: {},
|
||||
area: {},
|
||||
relation: {}
|
||||
};
|
||||
|
||||
all.match = function(entity, resolver) {
|
||||
var geometry = entity.geometry(resolver);
|
||||
|
||||
// Treat entities on addr:interpolation lines as points, not vertices (#3241)
|
||||
if (geometry === 'vertex' && entity.isOnAddressLine(resolver)) {
|
||||
geometry = 'point';
|
||||
}
|
||||
|
||||
var geometryMatches = index[geometry],
|
||||
best = -1,
|
||||
match;
|
||||
|
||||
for (var k in entity.tags) {
|
||||
var keyMatches = geometryMatches[k];
|
||||
if (!keyMatches) continue;
|
||||
|
||||
for (var i = 0; i < keyMatches.length; i++) {
|
||||
var score = keyMatches[i].matchScore(entity);
|
||||
if (score > best) {
|
||||
best = score;
|
||||
match = keyMatches[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return match || all.item(geometry);
|
||||
};
|
||||
|
||||
|
||||
// Because of the open nature of tagging, iD will never have a complete
|
||||
// list of tags used in OSM, so we want it to have logic like "assume
|
||||
// that a closed way with an amenity tag is an area, unless the amenity
|
||||
// is one of these specific types". This function computes a structure
|
||||
// that allows testing of such conditions, based on the presets designated
|
||||
// as as supporting (or not supporting) the area geometry.
|
||||
//
|
||||
// The returned object L is a whitelist/blacklist of tags. A closed way
|
||||
// with a tag (k, v) is considered to be an area if `k in L && !(v in L[k])`
|
||||
// (see `Way#isArea()`). In other words, the keys of L form the whitelist,
|
||||
// and the subkeys form the blacklist.
|
||||
all.areaKeys = function() {
|
||||
var areaKeys = {},
|
||||
ignore = ['barrier', 'highway', 'footway', 'railway', 'type'],
|
||||
presets = _.reject(all.collection, 'suggestion');
|
||||
|
||||
// whitelist
|
||||
presets.forEach(function(d) {
|
||||
for (var key in d.tags) break;
|
||||
if (!key) return;
|
||||
if (ignore.indexOf(key) !== -1) return;
|
||||
|
||||
if (d.geometry.indexOf('area') !== -1) {
|
||||
areaKeys[key] = areaKeys[key] || {};
|
||||
}
|
||||
});
|
||||
|
||||
// blacklist
|
||||
presets.forEach(function(d) {
|
||||
for (var key in d.tags) break;
|
||||
if (!key) return;
|
||||
if (ignore.indexOf(key) !== -1) return;
|
||||
|
||||
var value = d.tags[key];
|
||||
if (d.geometry.indexOf('area') === -1 &&
|
||||
d.geometry.indexOf('line') !== -1 &&
|
||||
key in areaKeys && value !== '*') {
|
||||
areaKeys[key][value] = true;
|
||||
}
|
||||
});
|
||||
|
||||
return areaKeys;
|
||||
};
|
||||
|
||||
|
||||
all.init = function() {
|
||||
var d = data.presets;
|
||||
|
||||
if (d.fields) {
|
||||
_.forEach(d.fields, function(d, id) {
|
||||
fields[id] = presetField(id, d);
|
||||
if (d.universal) universal.push(fields[id]);
|
||||
});
|
||||
}
|
||||
|
||||
if (d.presets) {
|
||||
_.forEach(d.presets, function(d, id) {
|
||||
all.collection.push(presetPreset(id, d, fields));
|
||||
});
|
||||
}
|
||||
|
||||
if (d.categories) {
|
||||
_.forEach(d.categories, function(d, id) {
|
||||
all.collection.push(presetCategory(id, d, all));
|
||||
});
|
||||
}
|
||||
|
||||
if (d.defaults) {
|
||||
var getItem = _.bind(all.item, all);
|
||||
defaults = {
|
||||
area: presetCollection(d.defaults.area.map(getItem)),
|
||||
line: presetCollection(d.defaults.line.map(getItem)),
|
||||
point: presetCollection(d.defaults.point.map(getItem)),
|
||||
vertex: presetCollection(d.defaults.vertex.map(getItem)),
|
||||
relation: presetCollection(d.defaults.relation.map(getItem))
|
||||
};
|
||||
}
|
||||
|
||||
for (var i = 0; i < all.collection.length; i++) {
|
||||
var preset = all.collection[i],
|
||||
geometry = preset.geometry;
|
||||
|
||||
for (var j = 0; j < geometry.length; j++) {
|
||||
var g = index[geometry[j]];
|
||||
for (var k in preset.tags) {
|
||||
(g[k] = g[k] || []).push(preset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return all;
|
||||
};
|
||||
|
||||
all.field = function(id) {
|
||||
return fields[id];
|
||||
};
|
||||
|
||||
all.universal = function() {
|
||||
return universal;
|
||||
};
|
||||
|
||||
all.defaults = function(geometry, n) {
|
||||
var rec = recent.matchGeometry(geometry).collection.slice(0, 4),
|
||||
def = _.uniq(rec.concat(defaults[geometry].collection)).slice(0, n - 1);
|
||||
return presetCollection(_.uniq(rec.concat(def).concat(all.item(geometry))));
|
||||
};
|
||||
|
||||
all.choose = function(preset) {
|
||||
if (!preset.isFallback()) {
|
||||
recent = presetCollection(_.uniq([preset].concat(recent.collection)));
|
||||
}
|
||||
return all;
|
||||
};
|
||||
|
||||
return all;
|
||||
}
|
||||
|
||||
@@ -1,168 +0,0 @@
|
||||
import _ from 'lodash';
|
||||
import { presetCategory } from './category';
|
||||
import { presetCollection } from './collection';
|
||||
import { presetField } from './field';
|
||||
import { presetPreset } from './preset';
|
||||
|
||||
|
||||
export function presetInit() {
|
||||
// a presetCollection with methods for
|
||||
// loading new data and returning defaults
|
||||
|
||||
var all = presetCollection([]),
|
||||
defaults = { area: all, line: all, point: all, vertex: all, relation: all },
|
||||
fields = {},
|
||||
universal = [],
|
||||
recent = presetCollection([]);
|
||||
|
||||
// Index of presets by (geometry, tag key).
|
||||
var index = {
|
||||
point: {},
|
||||
vertex: {},
|
||||
line: {},
|
||||
area: {},
|
||||
relation: {}
|
||||
};
|
||||
|
||||
all.match = function(entity, resolver) {
|
||||
var geometry = entity.geometry(resolver);
|
||||
|
||||
// Treat entities on addr:interpolation lines as points, not vertices (#3241)
|
||||
if (geometry === 'vertex' && entity.isOnAddressLine(resolver)) {
|
||||
geometry = 'point';
|
||||
}
|
||||
|
||||
var geometryMatches = index[geometry],
|
||||
best = -1,
|
||||
match;
|
||||
|
||||
for (var k in entity.tags) {
|
||||
var keyMatches = geometryMatches[k];
|
||||
if (!keyMatches) continue;
|
||||
|
||||
for (var i = 0; i < keyMatches.length; i++) {
|
||||
var score = keyMatches[i].matchScore(entity);
|
||||
if (score > best) {
|
||||
best = score;
|
||||
match = keyMatches[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return match || all.item(geometry);
|
||||
};
|
||||
|
||||
// Because of the open nature of tagging, iD will never have a complete
|
||||
// list of tags used in OSM, so we want it to have logic like "assume
|
||||
// that a closed way with an amenity tag is an area, unless the amenity
|
||||
// is one of these specific types". This function computes a structure
|
||||
// that allows testing of such conditions, based on the presets designated
|
||||
// as as supporting (or not supporting) the area geometry.
|
||||
//
|
||||
// The returned object L is a whitelist/blacklist of tags. A closed way
|
||||
// with a tag (k, v) is considered to be an area if `k in L && !(v in L[k])`
|
||||
// (see `Way#isArea()`). In other words, the keys of L form the whitelist,
|
||||
// and the subkeys form the blacklist.
|
||||
all.areaKeys = function() {
|
||||
var areaKeys = {},
|
||||
ignore = ['barrier', 'highway', 'footway', 'railway', 'type'],
|
||||
presets = _.reject(all.collection, 'suggestion');
|
||||
|
||||
// whitelist
|
||||
presets.forEach(function(d) {
|
||||
for (var key in d.tags) break;
|
||||
if (!key) return;
|
||||
if (ignore.indexOf(key) !== -1) return;
|
||||
|
||||
if (d.geometry.indexOf('area') !== -1) {
|
||||
areaKeys[key] = areaKeys[key] || {};
|
||||
}
|
||||
});
|
||||
|
||||
// blacklist
|
||||
presets.forEach(function(d) {
|
||||
for (var key in d.tags) break;
|
||||
if (!key) return;
|
||||
if (ignore.indexOf(key) !== -1) return;
|
||||
|
||||
var value = d.tags[key];
|
||||
if (d.geometry.indexOf('area') === -1 &&
|
||||
d.geometry.indexOf('line') !== -1 &&
|
||||
key in areaKeys && value !== '*') {
|
||||
areaKeys[key][value] = true;
|
||||
}
|
||||
});
|
||||
|
||||
return areaKeys;
|
||||
};
|
||||
|
||||
all.load = function(d) {
|
||||
|
||||
if (d.fields) {
|
||||
_.forEach(d.fields, function(d, id) {
|
||||
fields[id] = presetField(id, d);
|
||||
if (d.universal) universal.push(fields[id]);
|
||||
});
|
||||
}
|
||||
|
||||
if (d.presets) {
|
||||
_.forEach(d.presets, function(d, id) {
|
||||
all.collection.push(presetPreset(id, d, fields));
|
||||
});
|
||||
}
|
||||
|
||||
if (d.categories) {
|
||||
_.forEach(d.categories, function(d, id) {
|
||||
all.collection.push(presetCategory(id, d, all));
|
||||
});
|
||||
}
|
||||
|
||||
if (d.defaults) {
|
||||
var getItem = _.bind(all.item, all);
|
||||
defaults = {
|
||||
area: presetCollection(d.defaults.area.map(getItem)),
|
||||
line: presetCollection(d.defaults.line.map(getItem)),
|
||||
point: presetCollection(d.defaults.point.map(getItem)),
|
||||
vertex: presetCollection(d.defaults.vertex.map(getItem)),
|
||||
relation: presetCollection(d.defaults.relation.map(getItem))
|
||||
};
|
||||
}
|
||||
|
||||
for (var i = 0; i < all.collection.length; i++) {
|
||||
var preset = all.collection[i],
|
||||
geometry = preset.geometry;
|
||||
|
||||
for (var j = 0; j < geometry.length; j++) {
|
||||
var g = index[geometry[j]];
|
||||
for (var k in preset.tags) {
|
||||
(g[k] = g[k] || []).push(preset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return all;
|
||||
};
|
||||
|
||||
all.field = function(id) {
|
||||
return fields[id];
|
||||
};
|
||||
|
||||
all.universal = function() {
|
||||
return universal;
|
||||
};
|
||||
|
||||
all.defaults = function(geometry, n) {
|
||||
var rec = recent.matchGeometry(geometry).collection.slice(0, 4),
|
||||
def = _.uniq(rec.concat(defaults[geometry].collection)).slice(0, n - 1);
|
||||
return presetCollection(_.uniq(rec.concat(def).concat(all.item(geometry))));
|
||||
};
|
||||
|
||||
all.choose = function(preset) {
|
||||
if (!preset.isFallback()) {
|
||||
recent = presetCollection(_.uniq([preset].concat(recent.collection)));
|
||||
}
|
||||
return all;
|
||||
};
|
||||
|
||||
return all;
|
||||
}
|
||||
+10
-3
@@ -1,11 +1,15 @@
|
||||
import * as d3 from 'd3';
|
||||
import _ from 'lodash';
|
||||
import { d3combobox } from '../lib/d3.combobox.js';
|
||||
import { t } from '../util/locale';
|
||||
import { d3combobox } from '../lib/d3.combobox.js';
|
||||
import { modeSelect } from '../modes/index';
|
||||
import { svgIcon } from '../svg/index';
|
||||
import { tooltip } from '../util/tooltip';
|
||||
import { utilDisplayName, utilEntityOrMemberSelector } from '../util/index';
|
||||
import {
|
||||
utilDisplayName,
|
||||
utilDisplayType,
|
||||
utilEntityOrMemberSelector
|
||||
} from '../util/index';
|
||||
import { utilRebind } from '../util/rebind';
|
||||
import { utilTriggerEvent } from '../util/trigger_event';
|
||||
|
||||
@@ -229,7 +233,10 @@ export function uiCommit(context) {
|
||||
|
||||
li.append('strong')
|
||||
.attr('class', 'entity-type')
|
||||
.text(function(d) { return context.presets().match(d.entity, d.graph).name(); });
|
||||
.text(function(d) {
|
||||
var matched = context.presets().match(d.entity, d.graph);
|
||||
return (matched && matched.name()) || utilDisplayType(d.entity.id);
|
||||
});
|
||||
|
||||
li.append('span')
|
||||
.attr('class', 'entity-name')
|
||||
|
||||
@@ -5,7 +5,11 @@ import { geoExtent, geoChooseEdge } from '../geo/index';
|
||||
import { modeSelect } from '../modes/index';
|
||||
import { osmEntity } from '../osm/index';
|
||||
import { svgIcon } from '../svg/index';
|
||||
import { utilDisplayName, utilEntityOrMemberSelector } from '../util/index';
|
||||
import {
|
||||
utilDisplayName,
|
||||
utilDisplayType,
|
||||
utilEntityOrMemberSelector
|
||||
} from '../util/index';
|
||||
|
||||
|
||||
export function uiFeatureList(context) {
|
||||
@@ -111,11 +115,13 @@ export function uiFeatureList(context) {
|
||||
|
||||
var name = utilDisplayName(entity) || '';
|
||||
if (name.toLowerCase().indexOf(q) >= 0) {
|
||||
var matched = context.presets().match(entity, graph),
|
||||
type = (matched && matched.name()) || utilDisplayType(entity.id);
|
||||
result.push({
|
||||
id: entity.id,
|
||||
entity: entity,
|
||||
geometry: context.geometry(entity.id),
|
||||
type: context.presets().match(entity, graph).name(),
|
||||
type: type,
|
||||
name: name
|
||||
});
|
||||
}
|
||||
|
||||
+10
-5
@@ -95,9 +95,14 @@ export function uiPreset(context) {
|
||||
function content(selection) {
|
||||
if (!fieldsArr) {
|
||||
var entity = context.entity(id),
|
||||
geometry = context.geometry(id);
|
||||
geometry = context.geometry(id),
|
||||
presets = context.presets();
|
||||
|
||||
fieldsArr = [UIField(context.presets().field('name'), entity)];
|
||||
fieldsArr = [];
|
||||
|
||||
if (presets.field('name')) {
|
||||
fieldsArr.push(UIField(presets.field('name'), entity));
|
||||
}
|
||||
|
||||
preset.fields.forEach(function(field) {
|
||||
if (field.matchGeometry(geometry)) {
|
||||
@@ -105,11 +110,11 @@ export function uiPreset(context) {
|
||||
}
|
||||
});
|
||||
|
||||
if (entity.isHighwayIntersection(context.graph())) {
|
||||
fieldsArr.push(UIField(context.presets().field('restrictions'), entity, true));
|
||||
if (entity.isHighwayIntersection(context.graph()) && presets.field('restrictions')) {
|
||||
fieldsArr.push(UIField(presets.field('restrictions'), entity, true));
|
||||
}
|
||||
|
||||
context.presets().universal().forEach(function(field) {
|
||||
presets.universal().forEach(function(field) {
|
||||
if (preset.fields.indexOf(field) < 0) {
|
||||
fieldsArr.push(UIField(field, entity));
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import { osmEntity } from '../osm/index';
|
||||
import { svgIcon } from '../svg/index';
|
||||
import { services } from '../services/index';
|
||||
import { uiDisclosure } from './disclosure';
|
||||
import { utilDisplayName } from '../util/index';
|
||||
import { utilDisplayName, utilDisplayType } from '../util/index';
|
||||
|
||||
|
||||
export function uiRawMemberEditor(context) {
|
||||
@@ -109,7 +109,10 @@ export function uiRawMemberEditor(context) {
|
||||
|
||||
label.append('span')
|
||||
.attr('class', 'member-entity-type')
|
||||
.text(function(d) { return context.presets().match(d.member, context.graph()).name(); });
|
||||
.text(function(d) {
|
||||
var matched = context.presets().match(d.member, context.graph());
|
||||
return (matched && matched.name()) || utilDisplayType(d.member.id);
|
||||
});
|
||||
|
||||
label.append('span')
|
||||
.attr('class', 'member-entity-name')
|
||||
|
||||
@@ -80,7 +80,8 @@ export function uiRawMembershipEditor(context) {
|
||||
if (entity.type !== 'relation' || entity.id === id)
|
||||
return;
|
||||
|
||||
var presetName = context.presets().match(entity, graph).name(),
|
||||
var matched = context.presets().match(entity, graph),
|
||||
presetName = (matched && matched.name()) || t('inspector.relation'),
|
||||
entityName = utilDisplayName(entity) || '';
|
||||
|
||||
var value = presetName + ' ' + entityName;
|
||||
@@ -175,7 +176,8 @@ export function uiRawMembershipEditor(context) {
|
||||
.append('span')
|
||||
.attr('class', 'member-entity-type')
|
||||
.text(function(d) {
|
||||
return context.presets().match(d.relation, context.graph()).name();
|
||||
var matched = context.presets().match(d.relation, context.graph());
|
||||
return (matched && matched.name()) || t('inspector.relation');
|
||||
});
|
||||
|
||||
label
|
||||
|
||||
+1
-1
@@ -90,7 +90,7 @@
|
||||
|
||||
<script src='spec/presets/category.js'></script>
|
||||
<script src='spec/presets/collection.js'></script>
|
||||
<script src='spec/presets/init.js'></script>
|
||||
<script src='spec/presets/index.js'></script>
|
||||
<script src='spec/presets/preset.js'></script>
|
||||
|
||||
<script src='spec/renderer/background_source.js'></script>
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@
|
||||
};
|
||||
|
||||
context.presets = function() {
|
||||
return iD.presetInit().load({
|
||||
return iD.presetIndex().load({
|
||||
presets: {
|
||||
'amenity/restaurant': {
|
||||
geometry: ['point'],
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
describe('iD.actionSplit', function () {
|
||||
|
||||
beforeEach(function () {
|
||||
iD.areaKeys = iD.Context()
|
||||
.presets(iD.dataPresets).presets().areaKeys();
|
||||
iD.areaKeys = iD.Context().presets().areaKeys();
|
||||
});
|
||||
|
||||
describe('#disabled', function () {
|
||||
|
||||
@@ -51,54 +51,6 @@ describe('iD.Context', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('#presets', function() {
|
||||
it('supports custom presets', function() {
|
||||
var presetsCollection = {
|
||||
presets: {
|
||||
'mines': {
|
||||
geometry: ['point', 'area'],
|
||||
name: 'Mining Concession',
|
||||
tags: { 'concession': 'mining' }
|
||||
},
|
||||
'area': {
|
||||
'name': 'Area',
|
||||
'tags': {},
|
||||
'geometry': ['area']
|
||||
},
|
||||
'point': {
|
||||
'name': 'Point',
|
||||
'tags': {},
|
||||
'geometry': ['point']
|
||||
},
|
||||
'line': {
|
||||
'name': 'Line',
|
||||
'tags': {},
|
||||
'geometry': ['line']
|
||||
},
|
||||
'vertex': {
|
||||
'name': 'Other',
|
||||
'tags': {},
|
||||
'geometry': ['vertex']
|
||||
}
|
||||
},
|
||||
fields: {
|
||||
'name': {
|
||||
'key': 'name',
|
||||
'type': 'localized',
|
||||
'label': 'Name',
|
||||
'placeholder': 'Common name (if any)'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var context = iD.Context().presets(presetsCollection),
|
||||
way = iD.Way({tags: {concession: 'mining', area: 'yes'}}),
|
||||
graph = iD.Graph([way]);
|
||||
|
||||
expect(context.presets().match(way, graph).id).to.eql('mines');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#debug', function() {
|
||||
it('sets and gets debug flags', function() {
|
||||
var context = iD.Context(),
|
||||
|
||||
@@ -5,7 +5,6 @@ describe.skip('iD.modeAddPoint', function() {
|
||||
var container = d3.select(document.createElement('div'));
|
||||
|
||||
context = iD.Context()
|
||||
.presets(iD.dataPresets)
|
||||
.container(container);
|
||||
|
||||
context.loadTiles = function () {};
|
||||
|
||||
@@ -318,7 +318,7 @@ describe('iD.osmWay', function() {
|
||||
|
||||
describe('#isArea', function() {
|
||||
before(function() {
|
||||
iD.Context().presets(iD.dataPresets);
|
||||
iD.Context();
|
||||
});
|
||||
|
||||
it('returns false when the way has no tags', function() {
|
||||
|
||||
@@ -1,65 +1,84 @@
|
||||
describe('iD.presetInit', function() {
|
||||
var p = {
|
||||
point: {
|
||||
tags: {},
|
||||
geometry: ['point']
|
||||
},
|
||||
line: {
|
||||
tags: {},
|
||||
geometry: ['line']
|
||||
},
|
||||
vertex: {
|
||||
tags: {},
|
||||
geometry: ['vertex']
|
||||
},
|
||||
residential: {
|
||||
tags: { highway: 'residential' },
|
||||
geometry: ['line']
|
||||
},
|
||||
park: {
|
||||
tags: { leisure: 'park' },
|
||||
geometry: ['point', 'area']
|
||||
}
|
||||
};
|
||||
describe('iD.presetIndex', function() {
|
||||
var savedPresets;
|
||||
|
||||
var c = iD.presetInit().load({presets: p});
|
||||
before(function () {
|
||||
savedPresets = iD.data.presets;
|
||||
});
|
||||
|
||||
after(function () {
|
||||
iD.data.presets = savedPresets;
|
||||
});
|
||||
|
||||
describe('#match', function() {
|
||||
var testPresets = {
|
||||
presets: {
|
||||
point: {
|
||||
tags: {},
|
||||
geometry: ['point']
|
||||
},
|
||||
line: {
|
||||
tags: {},
|
||||
geometry: ['line']
|
||||
},
|
||||
vertex: {
|
||||
tags: {},
|
||||
geometry: ['vertex']
|
||||
},
|
||||
residential: {
|
||||
tags: { highway: 'residential' },
|
||||
geometry: ['line']
|
||||
},
|
||||
park: {
|
||||
tags: { leisure: 'park' },
|
||||
geometry: ['point', 'area']
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
it('returns a collection containing presets matching a geometry and tags', function() {
|
||||
var way = iD.Way({ tags: { highway: 'residential' } }),
|
||||
iD.data.presets = testPresets;
|
||||
var presets = iD.Context().presets(),
|
||||
way = iD.Way({ tags: { highway: 'residential' } }),
|
||||
graph = iD.Graph([way]);
|
||||
expect(c.match(way, graph).id).to.eql('residential');
|
||||
|
||||
expect(presets.match(way, graph).id).to.eql('residential');
|
||||
});
|
||||
|
||||
it('returns the appropriate fallback preset when no tags match', function() {
|
||||
var point = iD.Node(),
|
||||
iD.data.presets = testPresets;
|
||||
var presets = iD.Context().presets(),
|
||||
point = iD.Node(),
|
||||
line = iD.Way({ tags: { foo: 'bar' } }),
|
||||
graph = iD.Graph([point, line]);
|
||||
|
||||
expect(c.match(point, graph).id).to.eql('point');
|
||||
expect(c.match(line, graph).id).to.eql('line');
|
||||
expect(presets.match(point, graph).id).to.eql('point');
|
||||
expect(presets.match(line, graph).id).to.eql('line');
|
||||
});
|
||||
|
||||
it('matches vertices on a line as vertices', function() {
|
||||
var point = iD.Node({ tags: { leisure: 'park' } }),
|
||||
iD.data.presets = testPresets;
|
||||
var presets = iD.Context().presets(),
|
||||
point = iD.Node({ tags: { leisure: 'park' } }),
|
||||
line = iD.Way({ nodes: [point.id], tags: { 'highway': 'residential' } }),
|
||||
graph = iD.Graph([point, line]);
|
||||
|
||||
expect(c.match(point, graph).id).to.eql('vertex');
|
||||
expect(presets.match(point, graph).id).to.eql('vertex');
|
||||
});
|
||||
|
||||
it('matches vertices on an addr:interpolation line as points', function() {
|
||||
var point = iD.Node({ tags: { leisure: 'park' } }),
|
||||
iD.data.presets = testPresets;
|
||||
var presets = iD.Context().presets(),
|
||||
point = iD.Node({ tags: { leisure: 'park' } }),
|
||||
line = iD.Way({ nodes: [point.id], tags: { 'addr:interpolation': 'even' } }),
|
||||
graph = iD.Graph([point, line]);
|
||||
|
||||
expect(c.match(point, graph).id).to.eql('park');
|
||||
expect(presets.match(point, graph).id).to.eql('park');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('#areaKeys', function() {
|
||||
var presets = iD.presetInit().load({
|
||||
var testPresets = {
|
||||
presets: {
|
||||
'amenity/fuel/shell': {
|
||||
tags: { 'amenity': 'fuel' },
|
||||
@@ -91,62 +110,78 @@ describe('iD.presetInit', function() {
|
||||
geometry: ['point', 'area']
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
it('whitelists keys for presets with area geometry', function() {
|
||||
iD.data.presets = testPresets;
|
||||
var presets = iD.Context().presets();
|
||||
expect(presets.areaKeys()).to.include.keys('natural');
|
||||
});
|
||||
|
||||
it('blacklists key-values for presets with a line geometry', function() {
|
||||
iD.data.presets = testPresets;
|
||||
var presets = iD.Context().presets();
|
||||
expect(presets.areaKeys().natural).to.include.keys('tree_row');
|
||||
expect(presets.areaKeys().natural.tree_row).to.be.true;
|
||||
});
|
||||
|
||||
it('does not blacklist key-values for presets with both area and line geometry', function() {
|
||||
iD.data.presets = testPresets;
|
||||
var presets = iD.Context().presets();
|
||||
expect(presets.areaKeys().golf).not.to.include.keys('water_hazard');
|
||||
});
|
||||
|
||||
it('does not blacklist key-values for presets with neither area nor line geometry', function() {
|
||||
iD.data.presets = testPresets;
|
||||
var presets = iD.Context().presets();
|
||||
expect(presets.areaKeys().natural).not.to.include.keys('peak');
|
||||
});
|
||||
|
||||
it('does not blacklist generic \'*\' key-values', function() {
|
||||
iD.data.presets = testPresets;
|
||||
var presets = iD.Context().presets();
|
||||
expect(presets.areaKeys().natural).not.to.include.keys('natural');
|
||||
});
|
||||
|
||||
it('ignores keys like \'highway\' that are assumed to be lines', function() {
|
||||
iD.data.presets = testPresets;
|
||||
var presets = iD.Context().presets();
|
||||
expect(presets.areaKeys()).not.to.include.keys('highway');
|
||||
});
|
||||
|
||||
it('ignores suggestion presets', function() {
|
||||
iD.data.presets = testPresets;
|
||||
var presets = iD.Context().presets();
|
||||
expect(presets.areaKeys()).not.to.include.keys('amenity');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('expected matches', function() {
|
||||
var presets;
|
||||
|
||||
before(function() {
|
||||
presets = iD.presetInit().load(iD.dataPresets);
|
||||
});
|
||||
describe('expected matches', function() {
|
||||
|
||||
it('prefers building to multipolygon', function() {
|
||||
var relation = iD.Relation({tags: {type: 'multipolygon', building: 'yes'}}),
|
||||
graph = iD.Graph([relation]);
|
||||
iD.data.presets = savedPresets;
|
||||
var presets = iD.Context().presets(),
|
||||
relation = iD.Relation({ tags: { type: 'multipolygon', building: 'yes' }}),
|
||||
graph = iD.Graph([relation]);
|
||||
expect(presets.match(relation, graph).id).to.eql('building');
|
||||
});
|
||||
|
||||
it('prefers building to address', function() {
|
||||
var way = iD.Way({tags: {area: 'yes', building: 'yes', 'addr:housenumber': '1234'}}),
|
||||
iD.data.presets = savedPresets;
|
||||
var presets = iD.Context().presets(),
|
||||
way = iD.Way({ tags: { area: 'yes', building: 'yes', 'addr:housenumber': '1234' }}),
|
||||
graph = iD.Graph([way]);
|
||||
expect(presets.match(way, graph).id).to.eql('building');
|
||||
});
|
||||
|
||||
it('prefers pedestrian to area', function() {
|
||||
var way = iD.Way({tags: {area: 'yes', highway: 'pedestrian'}}),
|
||||
iD.data.presets = savedPresets;
|
||||
var presets = iD.Context().presets(),
|
||||
way = iD.Way({ tags: { area: 'yes', highway: 'pedestrian' }}),
|
||||
graph = iD.Graph([way]);
|
||||
expect(presets.match(way, graph).id).to.eql('highway/pedestrian');
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
@@ -2,8 +2,7 @@ describe('iD.uiFieldAccess', function() {
|
||||
var selection, field;
|
||||
beforeEach(function() {
|
||||
selection = d3.select(document.createElement('div'));
|
||||
field = iD.Context()
|
||||
.presets(iD.dataPresets).presets().field('access');
|
||||
field = iD.Context().presets().field('access');
|
||||
});
|
||||
|
||||
it('creates inputs for a variety of modes of access', function() {
|
||||
|
||||
@@ -14,7 +14,7 @@ describe('iD.uiFieldWikipedia', function() {
|
||||
context = iD.Context();
|
||||
context.history().merge([entity]);
|
||||
selection = d3.select(document.createElement('div'));
|
||||
field = context.presets(iD.dataPresets).presets().field('wikipedia');
|
||||
field = context.presets().field('wikipedia');
|
||||
window.JSONP_DELAY = 0;
|
||||
window.JSONP_FIX = {
|
||||
entities: {
|
||||
@@ -114,7 +114,7 @@ describe('iD.uiFieldWikipedia', function() {
|
||||
// skip delayed wikidata for 'Skip' // 'Skip' wikidata +20ms
|
||||
expect(spy.getCall(4)).to.have.been.calledWith({ wikipedia: 'de:Title', wikidata: 'Q216353' }); // 'Title' wikidata +40ms
|
||||
done();
|
||||
}, 50);
|
||||
}, 100);
|
||||
});
|
||||
|
||||
it('does not set delayed wikidata tag if selected entity has changed', function(done) {
|
||||
@@ -140,7 +140,7 @@ describe('iD.uiFieldWikipedia', function() {
|
||||
expect(spy.getCall(1)).to.have.been.calledWith({ wikipedia: 'de:Title' }); // 'Title' on blur
|
||||
// wikidata tag not changed because another entity is now selected
|
||||
done();
|
||||
}, 50);
|
||||
}, 100);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user