mirror of
https://github.com/FoggedLens/iD.git
synced 2026-04-29 23:17:53 +02:00
@@ -43,9 +43,8 @@ of iD (e.g. `http://preview.ideditor.com/release/`), the following parameters ar
|
||||
* __`photo_overlay`__ - The street-level photo overlay layers to enable.<br/>
|
||||
_Example:_ `photo_overlay=streetside,mapillary,openstreetcam`<br/>
|
||||
_Available values:_ `streetside` (Microsoft Bing), `mapillary`, `mapillary-signs`, `mapillary-map-features`, `openstreetcam`
|
||||
* __`presets`__ - A path to an external presets file or a comma-separated list of preset IDs. These will be the only presets the user may select.<br/>
|
||||
_Example:_ `presets=https://path/to/presets.json`
|
||||
_Example 2:_ `presets=building,highway/residential,highway/unclassified`
|
||||
* __`presets`__ - A comma-separated list of preset IDs. These will be the only presets the user may select.<br/>
|
||||
_Example:_ `presets=building,highway/residential,highway/unclassified`
|
||||
* __`rtl=true`__ - Force iD into right-to-left mode (useful for testing).
|
||||
* __`source`__ - Prefills the changeset source. Pass a url encoded string.<br/>
|
||||
_Example:_ `source=Bing%3BMapillary`
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ $ git push origin 2.x
|
||||
$ git checkout release
|
||||
$ git reset --hard 2.x
|
||||
$ npm run all
|
||||
$ git add -f dist/*.css dist/*.js dist/img/*.svg dist/mapillary-js/ dist/pannellum-streetside/
|
||||
$ git add -f dist/*.css dist/*.js dist/data/* dist/img/*.svg dist/mapillary-js/ dist/pannellum-streetside/
|
||||
$ git commit -m 'Check in build'
|
||||
$ git tag vA.B.C
|
||||
$ git push origin -f release vA.B.C
|
||||
|
||||
+1
-13
@@ -1,16 +1,4 @@
|
||||
export { dataLocales } from './locales.json';
|
||||
export { en as dataEn } from '../dist/locales/en.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 let data = {
|
||||
presets: {
|
||||
presets: presets,
|
||||
defaults: defaults,
|
||||
categories: categories,
|
||||
fields: fields
|
||||
}
|
||||
};
|
||||
export let data = {};
|
||||
|
||||
@@ -1,226 +1 @@
|
||||
{
|
||||
"categories": {
|
||||
"category-barrier": {
|
||||
"icon": "maki-roadblock",
|
||||
"name": "Barrier Features",
|
||||
"members": [
|
||||
"barrier/fence",
|
||||
"barrier/wall",
|
||||
"barrier/ditch",
|
||||
"barrier/gate",
|
||||
"barrier/hedge",
|
||||
"barrier/kerb",
|
||||
"barrier"
|
||||
]
|
||||
},
|
||||
"category-building": {
|
||||
"icon": "maki-building",
|
||||
"name": "Building Features",
|
||||
"members": [
|
||||
"building",
|
||||
"building/house",
|
||||
"building/apartments",
|
||||
"building/garage",
|
||||
"building/retail",
|
||||
"building/commercial",
|
||||
"building/industrial",
|
||||
"building/residential"
|
||||
]
|
||||
},
|
||||
"category-golf": {
|
||||
"icon": "maki-golf",
|
||||
"name": "Golf Features",
|
||||
"members": [
|
||||
"golf/fairway",
|
||||
"golf/green",
|
||||
"golf/lateral_water_hazard",
|
||||
"golf/rough",
|
||||
"golf/bunker",
|
||||
"golf/tee",
|
||||
"golf/water_hazard",
|
||||
"golf/driving_range",
|
||||
"golf/hole",
|
||||
"golf/cartpath",
|
||||
"golf/path"
|
||||
]
|
||||
},
|
||||
"category-landuse": {
|
||||
"icon": "maki-landuse",
|
||||
"name": "Land Use Features",
|
||||
"members": [
|
||||
"landuse/residential",
|
||||
"landuse/industrial",
|
||||
"landuse/commercial",
|
||||
"landuse/retail",
|
||||
"landuse/farmland",
|
||||
"landuse/farmyard",
|
||||
"landuse/forest",
|
||||
"landuse/meadow",
|
||||
"landuse/aquaculture",
|
||||
"landuse/cemetery",
|
||||
"landuse/military",
|
||||
"landuse/religious"
|
||||
]
|
||||
},
|
||||
"category-natural": {
|
||||
"icon": "maki-natural",
|
||||
"name": "Natural Features",
|
||||
"members": [
|
||||
"natural/water",
|
||||
"natural/wood",
|
||||
"natural/scrub",
|
||||
"natural/wetland",
|
||||
"natural/grassland",
|
||||
"natural/heath",
|
||||
"natural/bare_rock",
|
||||
"natural/beach",
|
||||
"natural/cave_entrance",
|
||||
"natural/glacier",
|
||||
"natural/coastline",
|
||||
"natural/tree_row",
|
||||
"natural/peak",
|
||||
"natural/cliff"
|
||||
]
|
||||
},
|
||||
"category-path": {
|
||||
"icon": "temaki-pedestrian",
|
||||
"name": "Paths",
|
||||
"members": [
|
||||
"highway/path",
|
||||
"highway/footway",
|
||||
"highway/footway/marked",
|
||||
"highway/footway/sidewalk",
|
||||
"highway/steps",
|
||||
"highway/cycleway",
|
||||
"highway/bridleway",
|
||||
"highway/pedestrian_line"
|
||||
]
|
||||
},
|
||||
"category-rail": {
|
||||
"icon": "temaki-railway_track",
|
||||
"name": "Rails",
|
||||
"members": [
|
||||
"railway/rail",
|
||||
"railway/disused",
|
||||
"railway/tram",
|
||||
"railway/subway",
|
||||
"railway/narrow_gauge",
|
||||
"railway/light_rail",
|
||||
"railway/monorail",
|
||||
"railway/funicular"
|
||||
]
|
||||
},
|
||||
"category-restriction": {
|
||||
"icon": "iD-restriction",
|
||||
"name": "Restriction Features",
|
||||
"members": [
|
||||
"type/restriction/no_left_turn",
|
||||
"type/restriction/no_right_turn",
|
||||
"type/restriction/no_straight_on",
|
||||
"type/restriction/no_u_turn",
|
||||
"type/restriction/only_left_turn",
|
||||
"type/restriction/only_right_turn",
|
||||
"type/restriction/only_straight_on",
|
||||
"type/restriction/only_u_turn",
|
||||
"type/restriction"
|
||||
]
|
||||
},
|
||||
"category-road_major": {
|
||||
"icon": "iD-highway-unclassified",
|
||||
"name": "Major Roads",
|
||||
"members": [
|
||||
"highway/motorway",
|
||||
"highway/trunk",
|
||||
"highway/primary",
|
||||
"highway/secondary",
|
||||
"highway/tertiary",
|
||||
"highway/motorway_link",
|
||||
"highway/trunk_link",
|
||||
"highway/primary_link",
|
||||
"highway/secondary_link",
|
||||
"highway/tertiary_link"
|
||||
]
|
||||
},
|
||||
"category-road_minor": {
|
||||
"icon": "iD-highway-unclassified",
|
||||
"name": "Minor Roads",
|
||||
"members": [
|
||||
"highway/unclassified",
|
||||
"highway/residential",
|
||||
"highway/living_street",
|
||||
"highway/service",
|
||||
"highway/track"
|
||||
]
|
||||
},
|
||||
"category-road_service": {
|
||||
"icon": "iD-highway-service",
|
||||
"name": "Service Roads",
|
||||
"members": [
|
||||
"highway/service",
|
||||
"highway/service/parking_aisle",
|
||||
"highway/service/driveway",
|
||||
"highway/service/alley",
|
||||
"highway/service/emergency_access",
|
||||
"highway/service/drive-through"
|
||||
]
|
||||
},
|
||||
"category-route": {
|
||||
"icon": "iD-route",
|
||||
"name": "Route Features",
|
||||
"members": [
|
||||
"type/route/road",
|
||||
"type/route/bicycle",
|
||||
"type/route/foot",
|
||||
"type/route/hiking",
|
||||
"type/route/horse",
|
||||
"type/route/piste",
|
||||
"type/route/bus",
|
||||
"type/route/train",
|
||||
"type/route/light_rail",
|
||||
"type/route/tram",
|
||||
"type/route/subway",
|
||||
"type/route/ferry",
|
||||
"type/route/power",
|
||||
"type/route/pipeline",
|
||||
"type/route/detour",
|
||||
"type/route_master",
|
||||
"type/route"
|
||||
]
|
||||
},
|
||||
"category-utility": {
|
||||
"icon": "iD-power-line",
|
||||
"name": "Utility Features",
|
||||
"members": [
|
||||
"power/line",
|
||||
"power/minor_line",
|
||||
"man_made/pipeline",
|
||||
"power/cable/underground"
|
||||
]
|
||||
},
|
||||
"category-water": {
|
||||
"icon": "maki-water",
|
||||
"name": "Water Bodies",
|
||||
"members": [
|
||||
"natural/water",
|
||||
"natural/water/pond",
|
||||
"natural/water/basin",
|
||||
"natural/water/lake",
|
||||
"natural/water/reservoir"
|
||||
]
|
||||
},
|
||||
"category-waterway": {
|
||||
"icon": "iD-waterway-stream",
|
||||
"name": "Waterways",
|
||||
"members": [
|
||||
"waterway/stream",
|
||||
"waterway/drain",
|
||||
"waterway/river",
|
||||
"waterway/canal",
|
||||
"waterway/ditch",
|
||||
"natural/water/stream",
|
||||
"natural/water/river",
|
||||
"natural/water/canal"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
{"category-barrier": {"icon": "maki-roadblock", "name": "Barrier Features", "members": ["barrier/fence", "barrier/wall", "barrier/ditch", "barrier/gate", "barrier/hedge", "barrier/kerb", "barrier"]}, "category-building": {"icon": "maki-building", "name": "Building Features", "members": ["building", "building/house", "building/apartments", "building/garage", "building/retail", "building/commercial", "building/industrial", "building/residential"]}, "category-golf": {"icon": "maki-golf", "name": "Golf Features", "members": ["golf/fairway", "golf/green", "golf/lateral_water_hazard", "golf/rough", "golf/bunker", "golf/tee", "golf/water_hazard", "golf/driving_range", "golf/hole", "golf/cartpath", "golf/path"]}, "category-landuse": {"icon": "maki-landuse", "name": "Land Use Features", "members": ["landuse/residential", "landuse/industrial", "landuse/commercial", "landuse/retail", "landuse/farmland", "landuse/farmyard", "landuse/forest", "landuse/meadow", "landuse/aquaculture", "landuse/cemetery", "landuse/military", "landuse/religious"]}, "category-natural": {"icon": "maki-natural", "name": "Natural Features", "members": ["natural/water", "natural/wood", "natural/scrub", "natural/wetland", "natural/grassland", "natural/heath", "natural/bare_rock", "natural/beach", "natural/cave_entrance", "natural/glacier", "natural/coastline", "natural/tree_row", "natural/peak", "natural/cliff"]}, "category-path": {"icon": "temaki-pedestrian", "name": "Paths", "members": ["highway/path", "highway/footway", "highway/footway/marked", "highway/footway/sidewalk", "highway/steps", "highway/cycleway", "highway/bridleway", "highway/pedestrian_line"]}, "category-rail": {"icon": "temaki-railway_track", "name": "Rails", "members": ["railway/rail", "railway/disused", "railway/tram", "railway/subway", "railway/narrow_gauge", "railway/light_rail", "railway/monorail", "railway/funicular"]}, "category-restriction": {"icon": "iD-restriction", "name": "Restriction Features", "members": ["type/restriction/no_left_turn", "type/restriction/no_right_turn", "type/restriction/no_straight_on", "type/restriction/no_u_turn", "type/restriction/only_left_turn", "type/restriction/only_right_turn", "type/restriction/only_straight_on", "type/restriction/only_u_turn", "type/restriction"]}, "category-road_major": {"icon": "iD-highway-unclassified", "name": "Major Roads", "members": ["highway/motorway", "highway/trunk", "highway/primary", "highway/secondary", "highway/tertiary", "highway/motorway_link", "highway/trunk_link", "highway/primary_link", "highway/secondary_link", "highway/tertiary_link"]}, "category-road_minor": {"icon": "iD-highway-unclassified", "name": "Minor Roads", "members": ["highway/unclassified", "highway/residential", "highway/living_street", "highway/service", "highway/track"]}, "category-road_service": {"icon": "iD-highway-service", "name": "Service Roads", "members": ["highway/service", "highway/service/parking_aisle", "highway/service/driveway", "highway/service/alley", "highway/service/emergency_access", "highway/service/drive-through"]}, "category-route": {"icon": "iD-route", "name": "Route Features", "members": ["type/route/road", "type/route/bicycle", "type/route/foot", "type/route/hiking", "type/route/horse", "type/route/piste", "type/route/bus", "type/route/train", "type/route/light_rail", "type/route/tram", "type/route/subway", "type/route/ferry", "type/route/power", "type/route/pipeline", "type/route/detour", "type/route_master", "type/route"]}, "category-utility": {"icon": "iD-power-line", "name": "Utility Features", "members": ["power/line", "power/minor_line", "man_made/pipeline", "power/cable/underground"]}, "category-water": {"icon": "maki-water", "name": "Water Bodies", "members": ["natural/water", "natural/water/pond", "natural/water/basin", "natural/water/lake", "natural/water/reservoir"]}, "category-waterway": {"icon": "iD-waterway-stream", "name": "Waterways", "members": ["waterway/stream", "waterway/drain", "waterway/river", "waterway/canal", "waterway/ditch", "natural/water/stream", "natural/water/river", "natural/water/canal"]}}
|
||||
+59
-61
@@ -1,63 +1,61 @@
|
||||
{
|
||||
"defaults": {
|
||||
"area": [
|
||||
"category-landuse",
|
||||
"category-building",
|
||||
"category-water",
|
||||
"category-natural",
|
||||
"leisure/park",
|
||||
"amenity/hospital",
|
||||
"amenity/place_of_worship",
|
||||
"amenity/cafe",
|
||||
"amenity/restaurant",
|
||||
"area"
|
||||
],
|
||||
"line": [
|
||||
"category-road_major",
|
||||
"category-road_minor",
|
||||
"category-rail",
|
||||
"category-path",
|
||||
"category-waterway",
|
||||
"category-barrier",
|
||||
"category-natural",
|
||||
"category-utility",
|
||||
"line"
|
||||
],
|
||||
"point": [
|
||||
"category-natural",
|
||||
"leisure/park",
|
||||
"amenity/hospital",
|
||||
"amenity/place_of_worship",
|
||||
"amenity/cafe",
|
||||
"amenity/restaurant",
|
||||
"amenity/fast_food",
|
||||
"amenity/bar",
|
||||
"amenity/bank",
|
||||
"shop/supermarket",
|
||||
"point"
|
||||
],
|
||||
"vertex": [
|
||||
"highway/crossing/marked",
|
||||
"highway/crossing/unmarked",
|
||||
"railway/level_crossing",
|
||||
"highway/traffic_signals",
|
||||
"highway/turning_circle",
|
||||
"highway/turning_loop",
|
||||
"traffic_calming",
|
||||
"highway/mini_roundabout",
|
||||
"highway/motorway_junction",
|
||||
"point"
|
||||
],
|
||||
"relation": [
|
||||
"category-route",
|
||||
"category-restriction",
|
||||
"public_transport/stop_area",
|
||||
"type/boundary",
|
||||
"type/waterway",
|
||||
"type/multipolygon",
|
||||
"type/enforcement",
|
||||
"type/site",
|
||||
"relation"
|
||||
]
|
||||
}
|
||||
"area": [
|
||||
"category-landuse",
|
||||
"category-building",
|
||||
"category-water",
|
||||
"category-natural",
|
||||
"leisure/park",
|
||||
"amenity/hospital",
|
||||
"amenity/place_of_worship",
|
||||
"amenity/cafe",
|
||||
"amenity/restaurant",
|
||||
"area"
|
||||
],
|
||||
"line": [
|
||||
"category-road_major",
|
||||
"category-road_minor",
|
||||
"category-rail",
|
||||
"category-path",
|
||||
"category-waterway",
|
||||
"category-barrier",
|
||||
"category-natural",
|
||||
"category-utility",
|
||||
"line"
|
||||
],
|
||||
"point": [
|
||||
"category-natural",
|
||||
"leisure/park",
|
||||
"amenity/hospital",
|
||||
"amenity/place_of_worship",
|
||||
"amenity/cafe",
|
||||
"amenity/restaurant",
|
||||
"amenity/fast_food",
|
||||
"amenity/bar",
|
||||
"amenity/bank",
|
||||
"shop/supermarket",
|
||||
"point"
|
||||
],
|
||||
"vertex": [
|
||||
"highway/crossing/marked",
|
||||
"highway/crossing/unmarked",
|
||||
"railway/level_crossing",
|
||||
"highway/traffic_signals",
|
||||
"highway/turning_circle",
|
||||
"highway/turning_loop",
|
||||
"traffic_calming",
|
||||
"highway/mini_roundabout",
|
||||
"highway/motorway_junction",
|
||||
"point"
|
||||
],
|
||||
"relation": [
|
||||
"category-route",
|
||||
"category-restriction",
|
||||
"public_transport/stop_area",
|
||||
"type/boundary",
|
||||
"type/waterway",
|
||||
"type/multipolygon",
|
||||
"type/enforcement",
|
||||
"type/site",
|
||||
"relation"
|
||||
]
|
||||
}
|
||||
|
||||
+475
-477
@@ -1,479 +1,477 @@
|
||||
{
|
||||
"fields": {
|
||||
"access_aisle": {"key": "access_aisle", "type": "combo", "label": "Type"},
|
||||
"access_simple": {"key": "access", "type": "combo", "label": "Allowed Access", "options": ["yes", "permissive", "private", "customers", "permit", "no"], "terms": ["permitted", "private", "public"]},
|
||||
"access": {"keys": ["access", "foot", "motor_vehicle", "bicycle", "horse"], "reference": {"key": "access"}, "type": "access", "label": "Allowed Access", "placeholder": "Not Specified", "strings": {"types": {"access": "All", "foot": "Foot", "motor_vehicle": "Motor Vehicles", "bicycle": "Bicycles", "horse": "Horses"}, "options": {"yes": {"title": "Allowed", "description": "Access allowed by law; a right of way"}, "no": {"title": "Prohibited", "description": "Access not allowed to the general public"}, "permissive": {"title": "Permissive", "description": "Access allowed until such time as the owner revokes the permission"}, "private": {"title": "Private", "description": "Access allowed only with permission of the owner on an individual basis"}, "designated": {"title": "Designated", "description": "Access allowed according to signs or specific local laws"}, "destination": {"title": "Destination", "description": "Access allowed only to reach a destination"}, "dismount": {"title": "Dismount", "description": "Access allowed but rider must dismount"}, "permit": {"title": "Permit", "description": "Access allowed only with a valid permit or license"}}}},
|
||||
"addr/interpolation": {"key": "addr:interpolation", "type": "combo", "label": "Type", "strings": {"options": {"all": "All", "even": "Even", "odd": "Odd", "alphabetic": "Alphabetic"}}},
|
||||
"address": {"type": "address", "key": "addr", "keys": ["addr:block_number", "addr:city", "addr:block_number", "addr:conscriptionnumber", "addr:county", "addr:country", "addr:county", "addr:district", "addr:floor", "addr:hamlet", "addr:housename", "addr:housenumber", "addr:neighbourhood", "addr:place", "addr:postcode", "addr:province", "addr:quarter", "addr:state", "addr:street", "addr:subdistrict", "addr:suburb", "addr:unit"], "icon": "address", "label": "Address", "strings": {"placeholders": {"block_number": "Block Number", "block_number!jp": "Block No.", "city": "City", "city!cn": "City/Prefecture/League", "city!jp": "City/Town/Village/Tokyo Special Ward", "city!vn": "City/Town", "conscriptionnumber": "123", "country": "Country", "county": "County", "county!jp": "District", "district": "District", "district!cn": "District/County/Banner", "district!vn": "Arrondissement/Town/District", "floor": "Floor", "hamlet": "Hamlet", "housename": "Housename", "housenumber": "123", "housenumber!jp": "Building No./Lot No.", "neighbourhood": "Neighbourhood", "neighbourhood!jp": "Chōme/Aza/Koaza", "place": "Place", "postcode": "Postcode", "province": "Province", "province!cn": "Province/Municipality/AR/SAR", "province!jp": "Prefecture", "quarter": "Quarter", "quarter!jp": "Ōaza/Machi", "state": "State", "street": "Street", "subdistrict": "Subdistrict", "subdistrict!vn": "Ward/Commune/Townlet", "suburb": "Suburb", "suburb!jp": "Ward", "unit": "Unit"}}, "terms": ["location"]},
|
||||
"admin_level": {"key": "admin_level", "type": "number", "minValue": 1, "label": "Admin Level"},
|
||||
"aerialway": {"key": "aerialway", "type": "typeCombo", "label": "Type"},
|
||||
"aerialway/access": {"key": "aerialway:access", "type": "combo", "label": "Access", "strings": {"options": {"entry": "Entry", "exit": "Exit", "both": "Both"}}},
|
||||
"aerialway/bubble": {"key": "aerialway:bubble", "type": "check", "label": "Bubble"},
|
||||
"aerialway/capacity": {"key": "aerialway:capacity", "type": "number", "minValue": 0, "label": "Capacity (per hour)", "placeholder": "500, 2500, 5000..."},
|
||||
"aerialway/duration": {"key": "aerialway:duration", "type": "number", "minValue": 0, "label": "Duration (minutes)", "placeholder": "1, 2, 3..."},
|
||||
"aerialway/heating": {"key": "aerialway:heating", "type": "check", "label": "Heated"},
|
||||
"aerialway/occupancy": {"key": "aerialway:occupancy", "type": "number", "minValue": 0, "label": "Occupancy", "placeholder": "2, 4, 8..."},
|
||||
"aerialway/summer/access": {"key": "aerialway:summer:access", "type": "combo", "label": "Access (summer)", "strings": {"options": {"entry": "Entry", "exit": "Exit", "both": "Both"}}},
|
||||
"aeroway": {"key": "aeroway", "type": "typeCombo", "label": "Type"},
|
||||
"agrarian": {"key": "agrarian", "type": "semiCombo", "label": "Products"},
|
||||
"air_conditioning": {"key": "air_conditioning", "type": "check", "label": "Air Conditioning", "terms": ["cooling system", "refrigeration"]},
|
||||
"amenity": {"key": "amenity", "type": "typeCombo", "label": "Type"},
|
||||
"animal_boarding": {"key": "animal_boarding", "type": "semiCombo", "label": "For Animals"},
|
||||
"animal_breeding": {"key": "animal_breeding", "type": "semiCombo", "label": "For Animals"},
|
||||
"animal_shelter": {"key": "animal_shelter", "type": "semiCombo", "label": "For Animals"},
|
||||
"architect": {"key": "architect", "type": "text", "label": "Architect", "terms": ["building designer"]},
|
||||
"area/highway": {"key": "area:highway", "type": "typeCombo", "label": "Type"},
|
||||
"artist": {"key": "artist_name", "type": "text", "label": "Artist"},
|
||||
"artwork_type": {"key": "artwork_type", "type": "combo", "label": "Type"},
|
||||
"atm": {"key": "atm", "type": "check", "label": "ATM"},
|
||||
"attraction": {"key": "attraction", "type": "typeCombo", "label": "Type"},
|
||||
"baby_feeding": {"key": "baby_feeding", "type": "combo", "label": "Baby Nursing Area", "strings": {"options": {"room": "Dedicated Room", "yes": "Marked Space", "no": "None"}}, "terms": ["baby feeding", "breastfeeding", "lactation", "mothers", "nursing"]},
|
||||
"baby_seat": {"key": "baby", "type": "check", "label": "Baby Seat"},
|
||||
"backcountry": {"key": "backcountry", "type": "check", "label": "Backcountry"},
|
||||
"backrest": {"key": "backrest", "type": "check", "label": "Backrest"},
|
||||
"bar": {"key": "bar", "type": "check", "label": "Bar"},
|
||||
"barrier": {"key": "barrier", "type": "typeCombo", "label": "Type"},
|
||||
"basin": {"key": "basin", "type": "combo", "label": "Type"},
|
||||
"bath/open_air": {"key": "bath:open_air", "label": "Open Air", "type": "check"},
|
||||
"bath/sand_bath": {"key": "bath:sand_bath", "label": "Sand Bath", "type": "check"},
|
||||
"bath/type": {"key": "bath:type", "type": "combo", "label": "Specialty", "strings": {"options": {"onsen": "Japanese Onsen", "foot_bath": "Foot Bath", "hot_spring": "Hot Spring"}}},
|
||||
"beauty": {"key": "beauty", "type": "semiCombo", "label": "Services"},
|
||||
"bench": {"key": "bench", "type": "check", "label": "Bench", "terms": ["seating"]},
|
||||
"bicycle_parking": {"key": "bicycle_parking", "type": "combo", "label": "Type"},
|
||||
"bin": {"key": "bin", "type": "check", "label": "Waste Bin", "terms": ["garbage can", "trash can"]},
|
||||
"blind": {"key": "blind", "type": "radio", "strings": {"options": {"yes": "Yes", "limited": "Limited", "no": "No"}}, "label": "Blind Person Access", "terms": ["sight impairment", "vision impairment"]},
|
||||
"blood_components": {"key": "blood:", "type": "multiCombo", "label": "Blood Components", "strings": {"options": {"whole": "whole blood", "plasma": "plasma", "platelets": "platelets", "stemcells": "stem cell samples"}}},
|
||||
"board_type": {"key": "board_type", "type": "combo", "label": "Type"},
|
||||
"bollard": {"key": "bollard", "type": "combo", "label": "Type"},
|
||||
"booth": {"key": "booth", "type": "combo", "label": "Booth", "caseSensitive": true},
|
||||
"bottle": {"key": "bottle", "type": "check", "label": "Bottle Filling"},
|
||||
"boules": {"key": "boules", "type": "typeCombo", "label": "Type"},
|
||||
"boundary": {"key": "boundary", "type": "combo", "label": "Type"},
|
||||
"brand": {"key": "brand", "type": "text", "label": "Brand"},
|
||||
"brewery": {"key": "brewery", "type": "semiCombo", "label": "Draft Beers", "terms": ["on tap"]},
|
||||
"bridge": {"key": "bridge", "type": "typeCombo", "label": "Type", "placeholder": "Default"},
|
||||
"bridge/support": {"key": "bridge:support", "type": "combo", "label": "Type"},
|
||||
"building_area": {"key": "building", "type": "combo", "default": "yes", "geometry": "area", "label": "Building"},
|
||||
"building": {"key": "building", "type": "combo", "label": "Building", "terms": ["structure"]},
|
||||
"building/levels_building": {"key": "building:levels", "type": "number", "minValue": 0, "label": "Building Levels", "placeholder": "2, 4, 6...", "prerequisiteTag": {"key": "building", "valueNot": "no"}},
|
||||
"building/levels": {"key": "building:levels", "type": "number", "minValue": 0, "label": "Levels", "placeholder": "2, 4, 6..."},
|
||||
"building/levels/underground": {"key": "building:levels:underground", "type": "number", "minValue": 0, "label": "Underground Levels", "placeholder": "2, 4, 6...", "terms": ["basement levels"]},
|
||||
"building/material": {"key": "building:material", "type": "combo", "label": "Material"},
|
||||
"bunker_type": {"key": "bunker_type", "type": "combo", "label": "Type"},
|
||||
"cables": {"key": "cables", "type": "number", "minValue": 1, "label": "Cables", "placeholder": "1, 2, 3..."},
|
||||
"camera/direction": {"key": "camera:direction", "type": "number", "label": "Direction (Degrees Clockwise)", "placeholder": "45, 90, 180, 270"},
|
||||
"camera/mount": {"key": "camera:mount", "type": "combo", "label": "Camera Mount"},
|
||||
"camera/type": {"key": "camera:type", "type": "combo", "label": "Camera Type", "strings": {"options": {"fixed": "Fixed", "panning": "Panning", "dome": "Dome"}}},
|
||||
"capacity": {"key": "capacity", "type": "number", "minValue": 0, "label": "Capacity", "placeholder": "50, 100, 200..."},
|
||||
"cash_in": {"key": "cash_in", "type": "check", "label": "Cash In"},
|
||||
"castle_type": {"key": "castle_type", "type": "combo", "label": "Type"},
|
||||
"changing_table": {"key": "changing_table", "type": "check", "label": "Diaper Changing Table"},
|
||||
"charge_fee": {"key": "charge", "type": "text", "label": "Fee Amount", "placeholder": "1 EUR, 5 USD, 10 JPY…", "prerequisiteTag": {"key": "fee", "valueNot": "no"}},
|
||||
"charge_toll": {"key": "charge", "type": "text", "label": "Toll Amount", "placeholder": "1 EUR, 5 USD, 10 JPY…", "prerequisiteTag": {"key": "toll", "valueNot": "no"}},
|
||||
"check_date": {"key": "check_date", "type": "text", "label": "Last Checked Date"},
|
||||
"clothes": {"key": "clothes", "type": "semiCombo", "label": "Clothes"},
|
||||
"club": {"key": "club", "type": "typeCombo", "label": "Type"},
|
||||
"collection_times": {"key": "collection_times", "type": "text", "label": "Collection Times"},
|
||||
"colour": {"key": "colour", "type": "text", "label": "Color"},
|
||||
"comment": {"key": "comment", "type": "textarea", "label": "Changeset Comment", "placeholder": "Brief description of your contributions (required)"},
|
||||
"communication_multi": {"key": "communication:", "type": "multiCombo", "label": "Communication Types"},
|
||||
"connectivity": {"key": "connectivity", "type": "text", "label": "Connectivity"},
|
||||
"construction": {"key": "construction", "type": "combo", "label": "Type"},
|
||||
"consulate": {"key": "consulate", "type": "combo", "label": "Type"},
|
||||
"consulting": {"key": "consulting", "type": "semiCombo", "label": "Expertise"},
|
||||
"contact/webcam": {"key": "contact:webcam", "type": "url", "icon": "website", "label": "Webcam URL", "placeholder": "http://example.com/"},
|
||||
"content": {"key": "content", "type": "combo", "label": "Content", "options": ["silage", "water", "oil", "fuel", "slurry", "gas", "manure", "sewage"]},
|
||||
"conveying_escalator": {"key": "conveying", "type": "check", "label": "Escalator"},
|
||||
"conveying": {"key": "conveying", "type": "typeCombo", "label": "Movement Direction", "strings": {"options": {"forward": "Forward", "backward": "Backward", "reversible": "Reversible"}}},
|
||||
"country_flag": {"key": "country", "type": "combo", "label": "Flag Country", "prerequisiteTag": {"key": "flag:type", "value": "national"}},
|
||||
"country": {"key": "country", "type": "combo", "label": "Country"},
|
||||
"couplings": {"key": "couplings", "type": "number", "minValue": 1, "label": "Couplings", "placeholder": "1, 2, 3..."},
|
||||
"covered": {"key": "covered", "type": "check", "label": "Covered"},
|
||||
"craft": {"key": "craft", "type": "typeCombo", "label": "Type"},
|
||||
"crane/type": {"key": "crane:type", "type": "combo", "label": "Crane Type", "strings": {"options": {"portal_crane": "Portal Crane", "floor-mounted_crane": "Floor-mounted Crane", "travel_lift": "Travel Lift"}}},
|
||||
"crop": {"key": "crop", "type": "semiCombo", "label": "Crops"},
|
||||
"crossing": {"key": "crossing", "type": "combo", "label": "Type"},
|
||||
"crossing/island": {"key": "crossing:island", "type": "check", "label": "Refuge Island"},
|
||||
"cuisine": {"key": "cuisine", "type": "semiCombo", "label": "Cuisines", "terms": ["fare", "food types"]},
|
||||
"currency_multi": {"key": "currency:", "type": "multiCombo", "label": "Currency Types", "terms": ["bills", "cash", "coins", "money"]},
|
||||
"cutting": {"key": "cutting", "type": "typeCombo", "label": "Type", "placeholder": "Default"},
|
||||
"cycle_network": {"key": "cycle_network", "type": "networkCombo", "label": "Network"},
|
||||
"cycleway": {"keys": ["cycleway", "cycleway:left", "cycleway:right"], "reference": {"key": "cycleway"}, "type": "cycleway", "label": "Bike Lanes", "placeholder": "none", "strings": {"types": {"cycleway:left": "Left side", "cycleway:right": "Right side"}, "options": {"none": {"title": "None", "description": "No bike lane"}, "lane": {"title": "Standard bike lane", "description": "A bike lane separated from auto traffic by a painted line"}, "shared_lane": {"title": "Shared bike lane", "description": "A bike lane with no separation from auto traffic"}, "track": {"title": "Bike track", "description": "A bike lane separated from traffic by a physical barrier"}, "share_busway": {"title": "Bike lane shared with bus", "description": "A bike lane shared with a bus lane"}, "opposite_lane": {"title": "Opposite bike lane", "description": "A bike lane that travels in the opposite direction of traffic"}, "opposite": {"title": "Contraflow bike lane", "description": "A bike lane that travels in both directions on a one-way street"}}}},
|
||||
"dance/style": {"key": "dance:style", "type": "semiCombo", "label": "Dance Styles"},
|
||||
"date": {"key": "date", "type": "check", "label": "Date"},
|
||||
"delivery": {"key": "delivery", "type": "check", "label": "Delivery"},
|
||||
"denomination": {"key": "denomination", "type": "combo", "label": "Denomination", "prerequisiteTag": {"key": "religion", "valueNot": "none"}},
|
||||
"denotation": {"key": "denotation", "type": "combo", "label": "Denotation"},
|
||||
"departures_board": {"key": "departures_board", "type": "combo", "label": "Departures Board", "strings": {"options": {"yes": "Yes", "timetable": "Timetable", "realtime": "Realtime", "no": "None"}}},
|
||||
"description": {"key": "description", "type": "textarea", "label": "Description", "universal": true, "terms": ["summary"]},
|
||||
"design": {"key": "design", "type": "combo", "label": "Design"},
|
||||
"destination_oneway": {"key": "destination", "type": "semiCombo", "label": "Destinations", "prerequisiteTag": {"key": "oneway", "value": "yes"}, "snake_case": false},
|
||||
"destination/ref_oneway": {"key": "destination:ref", "type": "semiCombo", "label": "Destination Road Numbers", "prerequisiteTag": {"key": "oneway", "value": "yes"}, "snake_case": false},
|
||||
"destination/symbol_oneway": {"key": "destination:symbol", "type": "semiCombo", "label": "Destination Symbols", "prerequisiteTag": {"key": "oneway", "value": "yes"}},
|
||||
"devices": {"key": "devices", "type": "number", "minValue": 0, "label": "Devices", "placeholder": "1, 2, 3..."},
|
||||
"diameter": {"key": "diameter", "type": "combo", "label": "Diameter", "snake_case": false, "placeholder": "5 mm, 10 cm, 15 in…"},
|
||||
"diet_multi": {"key": "diet:", "type": "multiCombo", "label": "Diet Types", "terms": ["gluten free", "fruitarian", "halal", "kosher", "lactose free", "meat", "pescatarian", "raw", "vegan", "vegetarian"]},
|
||||
"diplomatic": {"key": "diplomatic", "type": "combo", "label": "Type"},
|
||||
"diplomatic/services": {"key": "diplomatic:services:", "type": "multiCombo", "label": "Services"},
|
||||
"direction_cardinal": {"key": "direction", "type": "combo", "label": "Direction", "strings": {"options": {"N": "North", "E": "East", "S": "South", "W": "West", "NE": "Northeast", "SE": "Southeast", "SW": "Southwest", "NW": "Northwest", "NNE": "North-northeast", "ENE": "East-northeast", "ESE": "East-southeast", "SSE": "South-southeast", "SSW": "South-southwest", "WSW": "West-southwest", "WNW": "West-northwest", "NNW": "North-northwest"}}},
|
||||
"direction_clock": {"key": "direction", "type": "combo", "label": "Direction", "strings": {"options": {"clockwise": "Clockwise", "anticlockwise": "Counterclockwise"}}},
|
||||
"direction_vertex": {"key": "direction", "type": "combo", "label": "Direction Affected", "strings": {"options": {"forward": "Forward", "backward": "Backward", "both": "Both / All"}}},
|
||||
"direction": {"key": "direction", "type": "number", "label": "Direction (Degrees Clockwise)", "placeholder": "45, 90, 180, 270"},
|
||||
"dispensing": {"key": "dispensing", "type": "check", "label": "Dispenses Prescriptions", "default": "yes"},
|
||||
"display": {"key": "display", "type": "combo", "label": "Display", "options": ["analog", "digital", "sundial", "unorthodox"]},
|
||||
"distance": {"key": "distance", "type": "text", "label": "Distance"},
|
||||
"disused/railway": {"key": "disused:railway", "type": "typeCombo", "label": "Type"},
|
||||
"dock": {"key": "dock", "type": "combo", "label": "Type"},
|
||||
"dog": {"key": "dog", "type": "combo", "label": "Dogs", "strings": {"options": {"yes": "Allowed", "leashed": "Leashed Only", "no": "Not Allowed"}}, "terms": ["animals", "pets"]},
|
||||
"door_type": {"key": "door", "type": "typeCombo", "label": "Type"},
|
||||
"door": {"key": "door", "type": "combo", "label": "Door"},
|
||||
"drink_multi": {"key": "drink:", "type": "multiCombo", "label": "Drinks"},
|
||||
"drinking_water": {"key": "drinking_water", "type": "check", "label": "Drinkable", "terms": ["drinkworthy", "potable"]},
|
||||
"drive_through": {"key": "drive_through", "type": "check", "label": "Drive-Through"},
|
||||
"duration": {"key": "duration", "type": "text", "label": "Duration", "placeholder": "00:00"},
|
||||
"electrified": {"key": "electrified", "type": "combo", "label": "Electrification", "placeholder": "Contact Line, Electrified Rail...", "strings": {"options": {"contact_line": "Contact Line", "rail": "Electrified Rail", "yes": "Yes (unspecified)", "no": "No"}}, "terms": ["contact line", "powered", "third rail"]},
|
||||
"elevation": {"key": "ele", "type": "number", "icon": "elevation", "universal": true, "label": "Elevation", "terms": ["altitude"]},
|
||||
"email": {"key": "email", "type": "email", "placeholder": "example@example.com", "label": "Email"},
|
||||
"embankment": {"key": "embankment", "type": "typeCombo", "label": "Type", "placeholder": "Default"},
|
||||
"embassy": {"key": "embassy", "type": "combo", "label": "Type"},
|
||||
"emergency_combo": {"key": "emergency", "type": "combo", "label": "Type"},
|
||||
"emergency": {"key": "emergency", "type": "check", "label": "Emergency"},
|
||||
"enforcement": {"key": "enforcement", "type": "combo", "label": "Type"},
|
||||
"entrance": {"key": "entrance", "type": "typeCombo", "label": "Type"},
|
||||
"except": {"key": "except", "type": "combo", "label": "Exceptions"},
|
||||
"expected_rcn_route_relations": {"key": "expected_rcn_route_relations", "type": "number", "label": "Adjacent Cycling Nodes"},
|
||||
"expected_rwn_route_relations": {"key": "expected_rwn_route_relations", "type": "number", "label": "Adjacent Walking Nodes"},
|
||||
"faces": {"key": "faces", "type": "number", "minValue": 0, "label": "Faces"},
|
||||
"fax": {"key": "fax", "type": "tel", "label": "Fax", "placeholder": "+31 42 123 4567"},
|
||||
"fee": {"key": "fee", "type": "check", "label": "Fee"},
|
||||
"fence_type": {"key": "fence_type", "type": "combo", "label": "Type"},
|
||||
"fire_hydrant/diameter": {"key": "fire_hydrant:diameter", "type": "combo", "label": "Diameter (mm, in, or letters)", "snake_case": false},
|
||||
"fire_hydrant/pressure": {"key": "fire_hydrant:pressure", "type": "combo", "label": "Pressure (bar)", "snake_case": false},
|
||||
"fire_hydrant/type": {"key": "fire_hydrant:type", "type": "combo", "label": "Shape", "strings": {"options": {"pillar": "Pillar/Aboveground", "underground": "Underground", "wall": "Wall", "pipe": "Capped Pipe"}}},
|
||||
"fireplace": {"key": "fireplace", "type": "check", "label": "Fireplace"},
|
||||
"fishing": {"key": "fishing", "type": "combo", "label": "Fishing"},
|
||||
"fitness_station": {"key": "fitness_station", "type": "typeCombo", "label": "Equipment Type"},
|
||||
"fixme": {"key": "fixme", "type": "textarea", "label": "Fix Me", "universal": true, "terms": ["help request"]},
|
||||
"flag/type": {"key": "flag:type", "type": "combo", "label": "Flag Type"},
|
||||
"floating": {"key": "floating", "type": "check", "label": "Floating"},
|
||||
"flood_prone": {"key": "flood_prone", "type": "check", "label": "Flood Prone"},
|
||||
"ford": {"key": "ford", "type": "typeCombo", "label": "Type", "placeholder": "Default"},
|
||||
"fountain": {"key": "fountain", "type": "combo", "label": "Type"},
|
||||
"frequency_electrified": {"key": "frequency", "type": "combo", "label": "Operating Frequency", "prerequisiteTag": {"key": "electrified", "valueNot": "no"}},
|
||||
"frequency": {"key": "frequency", "type": "combo", "label": "Operating Frequency"},
|
||||
"from": {"key": "from", "type": "text", "label": "From"},
|
||||
"fuel_multi": {"key": "fuel:", "type": "multiCombo", "label": "Fuel Types"},
|
||||
"fuel": {"key": "fuel", "type": "combo", "label": "Fuel"},
|
||||
"gambling": {"key": "gambling", "type": "semiCombo", "label": "Games"},
|
||||
"gauge": {"key": "gauge", "type": "combo", "label": "Gauge"},
|
||||
"gender": {"type": "radio", "keys": ["male", "female", "unisex"], "label": "Gender", "placeholder": "Unknown", "strings": {"options": {"male": "Male", "female": "Female", "unisex": "Unisex"}}, "terms": ["access", "female", "male", "unisex"]},
|
||||
"generator/method": {"key": "generator:method", "type": "combo", "label": "Method"},
|
||||
"generator/output/electricity": {"key": "generator:output:electricity", "type": "typeCombo", "label": "Power Output", "placeholder": "50 MW, 100 MW, 200 MW...", "snake_case": false},
|
||||
"generator/source": {"key": "generator:source", "type": "combo", "label": "Source"},
|
||||
"generator/type": {"key": "generator:type", "type": "combo", "label": "Type"},
|
||||
"geyser/height": {"key": "geyser:height", "type": "text", "label": "Eruption Height"},
|
||||
"gnis/feature_id": {"key": "gnis:feature_id", "type": "identifier", "label": "GNIS Feature ID", "urlFormat": "https://geonames.usgs.gov/apex/f?p=gnispq:3:::NO::P3_FID:{value}", "pattern": "^[0-9]{1,}$", "countryCodes": ["us"], "terms": ["Federal Geographic Names Information Service", "United States Board on Geographic Names", "USA"]},
|
||||
"government": {"key": "government", "type": "typeCombo", "label": "Type"},
|
||||
"grape_variety": {"key": "grape_variety", "type": "semiCombo", "label": "Grape Varieties"},
|
||||
"group_only": {"key": "group_only", "type": "check", "label": "Groups Only"},
|
||||
"guest_house": {"key": "guest_house", "type": "combo", "label": "Type"},
|
||||
"handicap": {"key": "handicap", "type": "number", "label": "Handicap", "placeholder": "1-18"},
|
||||
"handrail": {"key": "handrail", "type": "check", "label": "Handrail"},
|
||||
"hashtags": {"key": "hashtags", "type": "semiCombo", "label": "Hashtags", "placeholder": "#example"},
|
||||
"healthcare": {"key": "healthcare", "type": "typeCombo", "label": "Type"},
|
||||
"healthcare/speciality": {"key": "healthcare:speciality", "type": "semiCombo", "reference": {"key": "healthcare"}, "label": "Specialties"},
|
||||
"height_building": {"key": "height", "minValue": 0, "type": "number", "label": "Building Height (Meters)", "prerequisiteTag": {"key": "building", "valueNot": "no"}},
|
||||
"height": {"key": "height", "minValue": 0, "type": "number", "label": "Height (Meters)"},
|
||||
"highspeed": {"key": "highspeed", "type": "check", "label": "High-Speed"},
|
||||
"highway": {"key": "highway", "type": "typeCombo", "label": "Type"},
|
||||
"historic": {"key": "historic", "type": "typeCombo", "label": "Type"},
|
||||
"historic/civilization": {"key": "historic:civilization", "type": "combo", "label": "Historic Civilization"},
|
||||
"historic/wreck/date_sunk": {"key": "wreck:date_sunk", "type": "text", "label": "Date Sunk"},
|
||||
"historic/wreck/visible_at_high_tide": {"key": "wreck:visible_at_high_tide", "type": "check", "label": "Visible At High Tide"},
|
||||
"historic/wreck/visible_at_low_tide": {"key": "wreck:visible_at_low_tide", "type": "check", "label": "Visible At Low Tide"},
|
||||
"hoops": {"key": "hoops", "type": "number", "minValue": 0, "label": "Hoops", "placeholder": "1, 2, 4..."},
|
||||
"horse_dressage": {"key": "sport", "type": "check", "label": "Dressage Riding", "strings": {"options": {"undefined": "No", "equestrian": "Yes"}}, "reference": {"key": "sport", "value": "equestrian"}},
|
||||
"horse_riding": {"key": "leisure", "type": "check", "label": "Horseback Riding", "strings": {"options": {"undefined": "No", "horse_riding": "Yes"}}, "reference": {"key": "leisure", "value": "horse_riding"}},
|
||||
"horse_scale": {"key": "horse_scale", "type": "combo", "label": "Horseback Riding Difficulty", "placeholder": "Difficult, Dangerous...", "strings": {"options": {"common": "Easy: No problems or difficulties. (default)", "demanding": "Use with caution: Uneven way, occasional difficult passages.", "difficult": "Difficult: Way narrow and exposed. May contain obstacles to step over and narrow passages.", "critical": "Borderline: Passable only for experienced riders and horses. Major obstacles. Bridges should be examined carefully.", "dangerous": "Dangerous: Passable only for very experienced riders and horses and only in good weather. Dismount.", "impossible": "Impassable: Way or bridge not passable for horses. Too narrow, insuffient support, obstacles like ladders. Danger of life."}}},
|
||||
"horse_stables": {"key": "amenity", "type": "check", "label": "Riding Stable", "strings": {"options": {"undefined": "No", "stables": "Yes"}}, "reference": {"key": "amenity", "value": "stables"}},
|
||||
"hot_water": {"key": "hot_water", "type": "check", "label": "Hot Water"},
|
||||
"iata": {"key": "iata", "type": "text", "label": "IATA Airport Code"},
|
||||
"icao": {"key": "icao", "type": "text", "label": "ICAO Airport Code"},
|
||||
"incline_steps": {"key": "incline", "type": "combo", "label": "Incline", "strings": {"options": {"up": "Up", "down": "Down"}}},
|
||||
"incline": {"key": "incline", "type": "combo", "label": "Incline"},
|
||||
"indoor_type": {"key": "indoor", "type": "typeCombo", "label": "Type"},
|
||||
"indoor": {"key": "indoor", "type": "check", "label": "Indoor"},
|
||||
"industrial": {"key": "industrial", "type": "combo", "label": "Type"},
|
||||
"informal": {"key": "informal", "type": "check", "label": "Informal"},
|
||||
"information": {"key": "information", "type": "typeCombo", "label": "Type"},
|
||||
"inscription": {"key": "inscription", "type": "textarea", "label": "Inscription"},
|
||||
"intermittent_yes": {"key": "intermittent", "type": "check", "label": "Intermittent", "default": "yes"},
|
||||
"intermittent": {"key": "intermittent", "type": "check", "label": "Intermittent"},
|
||||
"internet_access": {"key": "internet_access", "type": "combo", "label": "Internet Access", "strings": {"options": {"yes": "Yes", "no": "No", "wlan": "Wifi", "wired": "Wired", "terminal": "Terminal"}}, "terms": ["wifi", "wlan"]},
|
||||
"internet_access/fee": {"key": "internet_access:fee", "type": "check", "label": "Internet Access Fee", "prerequisiteTag": {"key": "internet_access", "valueNot": "no"}, "terms": ["wifi fee"]},
|
||||
"internet_access/ssid": {"key": "internet_access:ssid", "type": "text", "label": "Wifi Network Name", "prerequisiteTag": {"key": "internet_access", "valueNot": "no"}, "terms": ["ssid"]},
|
||||
"interval": {"key": "interval", "type": "text", "label": "Interval"},
|
||||
"junction_line": {"key": "junction", "type": "combo", "label": "Junction", "strings": {"options": {"roundabout": "Roundabout", "circular": "Traffic Circle", "jughandle": "Jughandle"}}},
|
||||
"junction/ref_oneway": {"key": "junction:ref", "type": "text", "label": "Junction Number", "prerequisiteTag": {"key": "oneway", "value": "yes"}},
|
||||
"kerb": {"key": "kerb", "type": "combo", "label": "Curb"},
|
||||
"kerb/height": {"key": "kerb:height", "type": "combo", "snake_case": false, "label": "Height"},
|
||||
"label": {"key": "label", "type": "textarea", "label": "Label"},
|
||||
"lamp_type": {"key": "lamp_type", "type": "combo", "label": "Type"},
|
||||
"landuse": {"key": "landuse", "type": "typeCombo", "label": "Type"},
|
||||
"lanes": {"key": "lanes", "type": "number", "minValue": 0, "label": "Lanes", "placeholder": "1, 2, 3..."},
|
||||
"language_multi": {"key": "language:", "type": "multiCombo", "label": "Languages"},
|
||||
"layer": {"key": "layer", "type": "number", "label": "Layer", "placeholder": "0"},
|
||||
"leaf_cycle_singular": {"key": "leaf_cycle", "type": "combo", "label": "Leaf Cycle", "strings": {"options": {"evergreen": "Evergreen", "deciduous": "Deciduous", "semi_evergreen": "Semi-Evergreen", "semi_deciduous": "Semi-Deciduous"}}},
|
||||
"leaf_cycle": {"key": "leaf_cycle", "type": "combo", "label": "Leaf Cycle", "strings": {"options": {"evergreen": "Evergreen", "deciduous": "Deciduous", "semi_evergreen": "Semi-Evergreen", "semi_deciduous": "Semi-Deciduous", "mixed": "Mixed"}}},
|
||||
"leaf_type_singular": {"key": "leaf_type", "type": "combo", "label": "Leaf Type", "strings": {"options": {"broadleaved": "Broadleaved", "needleleaved": "Needleleaved", "leafless": "Leafless"}}},
|
||||
"leaf_type": {"key": "leaf_type", "type": "combo", "label": "Leaf Type", "strings": {"options": {"broadleaved": "Broadleaved", "needleleaved": "Needleleaved", "mixed": "Mixed", "leafless": "Leafless"}}},
|
||||
"leisure": {"key": "leisure", "type": "typeCombo", "label": "Type"},
|
||||
"length": {"key": "length", "type": "number", "minValue": 0, "label": "Length (Meters)"},
|
||||
"level_semi": {"key": "level", "type": "semiCombo", "label": "Levels", "terms": ["building floors", "decks", "stories", "storeys", "storys"]},
|
||||
"level": {"key": "level", "type": "combo", "label": "Level", "terms": ["building floor", "deck", "storey", "story"], "prerequisiteTag": {"keyNot": "building"}},
|
||||
"liaison": {"key": "liaison", "type": "combo", "label": "Type"},
|
||||
"line_attachment": {"key": "line_attachment", "type": "combo", "label": "Line Attachment"},
|
||||
"lit": {"key": "lit", "type": "check", "label": "Lit", "terms": ["lamp", "lighting"]},
|
||||
"location_pool": {"key": "location", "type": "typeCombo", "label": "Location", "strings": {"options": {"outdoor": "Outdoor", "indoor": "Indoor", "roof": "Rooftop"}}},
|
||||
"location": {"key": "location", "type": "combo", "label": "Location"},
|
||||
"lock": {"key": "lock", "type": "check", "label": "Lock"},
|
||||
"lockable": {"key": "lockable", "type": "check", "label": "Lockable"},
|
||||
"man_made": {"key": "man_made", "type": "typeCombo", "label": "Type"},
|
||||
"manhole": {"key": "manhole", "type": "typeCombo", "label": "Type"},
|
||||
"manufacturer": {"key": "manufacturer", "type": "combo", "snake_case": false, "caseSensitive": true, "label": "Manufacturer"},
|
||||
"map_size": {"key": "map_size", "type": "typeCombo", "label": "Coverage"},
|
||||
"map_type": {"key": "map_type", "type": "typeCombo", "label": "Type"},
|
||||
"mapillary": {"key": "mapillary", "type": "identifier", "label": "Mapillary Image ID", "urlFormat": "https://mapillary.com/app/?focus=photo&pKey={value}", "pattern": "^[a-zA-Z0-9-_]{1,}$", "universal": true},
|
||||
"marker": {"key": "marker", "type": "typeCombo", "label": "Type"},
|
||||
"material": {"key": "material", "type": "combo", "label": "Material"},
|
||||
"max_age": {"key": "max_age", "type": "number", "minValue": 0, "label": "Maximum Age", "terms": ["upper age limit"]},
|
||||
"maxheight": {"key": "maxheight", "type": "combo", "label": "Max Height", "placeholder": "4, 4.5, 5, 14'0\", 14'6\", 15'0\"", "snake_case": false},
|
||||
"maxspeed": {"key": "maxspeed", "type": "maxspeed", "label": "Speed Limit", "placeholder": "40, 50, 60..."},
|
||||
"maxspeed/advisory": {"key": "maxspeed:advisory", "type": "maxspeed", "label": "Advisory Speed Limit", "placeholder": "40, 50, 60..."},
|
||||
"maxstay": {"key": "maxstay", "type": "combo", "label": "Max Stay", "options": ["15 min", "30 min", "45 min", "1 hr", "1.5 hr", "2 hr", "2.5 hr", "3 hr", "4 hr", "1 day", "2 day"], "snake_case": false},
|
||||
"maxweight_bridge": {"key": "maxweight", "type": "combo", "label": "Max Weight", "snake_case": false, "prerequisiteTag": {"key": "bridge", "valueNot": "no"}},
|
||||
"maxweight": {"key": "maxweight", "type": "combo", "label": "Max Weight", "snake_case": false},
|
||||
"memorial": {"key": "memorial", "type": "typeCombo", "label": "Type"},
|
||||
"microbrewery": {"key": "microbrewery", "type": "check", "label": "Microbrewery", "terms": ["brewpub", "craft beer"]},
|
||||
"min_age": {"key": "min_age", "type": "number", "minValue": 0, "label": "Minimum Age", "terms": ["lower age limit"]},
|
||||
"minspeed": {"key": "minspeed", "type": "maxspeed", "label": "Minimum Speed Limit", "placeholder": "20, 30, 40..."},
|
||||
"monitoring_multi": {"key": "monitoring:", "type": "multiCombo", "label": "Monitoring"},
|
||||
"mtb/scale": {"key": "mtb:scale", "type": "combo", "label": "Mountain Biking Difficulty", "placeholder": "0, 1, 2, 3...", "strings": {"options": {"0": "0: Solid gravel/packed earth, no obstacles, wide curves", "1": "1: Some loose surface, small obstacles, wide curves", "2": "2: Much loose surface, large obstacles, easy hairpins", "3": "3: Slippery surface, large obstacles, tight hairpins", "4": "4: Loose surface or boulders, dangerous hairpins", "5": "5: Maximum difficulty, boulder fields, landslides", "6": "6: Not rideable except by the very best mountain bikers"}}},
|
||||
"mtb/scale/imba": {"key": "mtb:scale:imba", "type": "combo", "label": "IMBA Trail Difficulty", "placeholder": "Easy, Medium, Difficult...", "strings": {"options": {"0": "Easiest (white circle)", "1": "Easy (green circle)", "2": "Medium (blue square)", "3": "Difficult (black diamond)", "4": "Extremely Difficult (double black diamond)"}}},
|
||||
"mtb/scale/uphill": {"key": "mtb:scale:uphill", "type": "combo", "label": "Mountain Biking Uphill Difficulty", "placeholder": "0, 1, 2, 3...", "strings": {"options": {"0": "0: Avg. incline <10%, gravel/packed earth, no obstacles", "1": "1: Avg. incline <15%, gravel/packed earth, few small objects", "2": "2: Avg. incline <20%, stable surface, fistsize rocks/roots", "3": "3: Avg. incline <25%, variable surface, fistsize rocks/branches", "4": "4: Avg. incline <30%, poor condition, big rocks/branches", "5": "5: Very steep, bike generally needs to be pushed or carried"}}},
|
||||
"museum": {"key": "museum", "type": "combo", "label": "Type"},
|
||||
"name": {"key": "name", "type": "localized", "label": "Name", "universal": true, "placeholder": "Common name (if any)", "terms": ["label", "title"]},
|
||||
"natural": {"key": "natural", "type": "typeCombo", "label": "Natural"},
|
||||
"network_bicycle": {"key": "network", "type": "combo", "label": "Network Class", "placeholder": "Local, Regional, National, International", "strings": {"options": {"lcn": "Local", "rcn": "Regional", "ncn": "National", "icn": "International"}}},
|
||||
"network_foot": {"key": "network", "type": "combo", "label": "Network Class", "placeholder": "Local, Regional, National, International", "strings": {"options": {"lwn": "Local", "rwn": "Regional", "nwn": "National", "iwn": "International"}}},
|
||||
"network_horse": {"key": "network", "type": "combo", "label": "Network Class", "placeholder": "Local, Regional, National, International", "strings": {"options": {"lhn": "Local", "rhn": "Regional", "nhn": "National", "ihn": "International"}}},
|
||||
"network_road": {"key": "network", "type": "networkCombo", "label": "Network"},
|
||||
"network": {"key": "network", "type": "text", "label": "Network"},
|
||||
"network/type": {"key": "network:type", "type": "combo", "label": "Network Type", "prerequisiteTag": {"key": "network"}},
|
||||
"not/name": {"key": "not:name", "type": "semiCombo", "label": "Incorrect Names", "terms": ["common mistake names", "wrong names"]},
|
||||
"note": {"key": "note", "type": "textarea", "universal": true, "icon": "note", "label": "Note", "terms": ["comment"]},
|
||||
"office": {"key": "office", "type": "typeCombo", "label": "Type"},
|
||||
"oneway_yes": {"key": "oneway", "type": "onewayCheck", "label": "One Way", "strings": {"options": {"undefined": "Assumed to be Yes", "yes": "Yes", "no": "No", "reversible": "Reversible", "alternating": "Alternating"}}},
|
||||
"oneway": {"key": "oneway", "type": "onewayCheck", "label": "One Way", "strings": {"options": {"undefined": "Assumed to be No", "yes": "Yes", "no": "No", "reversible": "Reversible", "alternating": "Alternating"}}},
|
||||
"oneway/bicycle": {"key": "oneway:bicycle", "type": "check", "label": "One Way (Bicycles)", "prerequisiteTag": {"key": "oneway"}},
|
||||
"openfire": {"key": "openfire", "type": "check", "label": "Open Fires Allowed"},
|
||||
"opening_date": {"key": "opening_date", "type": "text", "label": "Expected Opening Date"},
|
||||
"opening_hours": {"key": "opening_hours", "type": "combo", "label": "Hours", "placeholder": "Unknown", "snake_case": false},
|
||||
"operator": {"key": "operator", "type": "text", "label": "Operator"},
|
||||
"operator/type": {"key": "operator:type", "type": "combo", "label": "Operator Type", "prerequisiteTag": {"key": "operator"}},
|
||||
"outdoor_seating": {"key": "outdoor_seating", "type": "check", "label": "Outdoor Seating"},
|
||||
"par": {"key": "par", "type": "number", "minValue": 1, "label": "Par", "placeholder": "3, 4, 5..."},
|
||||
"park_ride": {"key": "park_ride", "type": "check", "label": "Park and Ride"},
|
||||
"parking": {"key": "parking", "type": "combo", "label": "Type", "strings": {"options": {"surface": "Surface", "multi-storey": "Multilevel", "underground": "Underground", "sheds": "Sheds", "carports": "Carports", "garage_boxes": "Garage Boxes", "lane": "Roadside Lane"}}},
|
||||
"payment_multi_fee": {"key": "payment:", "type": "multiCombo", "label": "Payment Types", "prerequisiteTag": {"key": "fee", "valueNot": "no"}},
|
||||
"payment_multi": {"key": "payment:", "type": "multiCombo", "label": "Payment Types"},
|
||||
"phases": {"key": "phases", "type": "number", "minValue": 1, "label": "Phases", "placeholder": "1, 2, 3..."},
|
||||
"phone": {"key": "phone", "type": "tel", "icon": "maki-telephone", "label": "Telephone", "placeholder": "+31 42 123 4567", "terms": ["phone number"]},
|
||||
"piste/difficulty_downhill": {"key": "piste:difficulty", "type": "combo", "label": "Difficulty", "placeholder": "Easy, Intermediate, Advanced...", "strings": {"options": {"novice": "Novice (instructional)", "easy": "Easy (green circle)", "intermediate": "Intermediate (blue square)", "advanced": "Advanced (black diamond)", "expert": "Expert (double black diamond)", "freeride": "Freeride (off-piste)", "extreme": "Extreme (climbing equipment required)"}}},
|
||||
"piste/difficulty_nordic": {"key": "piste:difficulty", "type": "combo", "label": "Difficulty", "placeholder": "Easy, Intermediate, Advanced...", "strings": {"options": {"novice": "Novice - Flat, no effort needed", "easy": "Easy - Soft hills, short steep section", "intermediate": "Intermediate - Steep section", "advanced": "Advanced - Narrow, steep or icy section, sharp turn", "expert": "Expert - Dangerous terrain around"}}},
|
||||
"piste/difficulty_skitour": {"key": "piste:difficulty", "type": "combo", "label": "Difficulty", "placeholder": "Easy, Intermediate, Advanced...", "strings": {"options": {"novice": "Novice - L: <30° incline", "easy": "Easy - WS: 30-35° incline", "intermediate": "Intermediate - ZS: 35-40° incline", "advanced": "Advanced - S: 40-45° incline", "expert": "Expert - SS: 45–50° incline", "freeride": "Freeride - AS: 50–55° incline", "extreme": "Extreme - EX: >55° incline"}}},
|
||||
"piste/difficulty": {"key": "piste:difficulty", "type": "combo", "label": "Difficulty", "placeholder": "Easy, Intermediate, Advanced...", "strings": {"options": {"novice": "Novice", "easy": "Easy", "intermediate": "Intermediate", "advanced": "Advanced", "expert": "Expert", "freeride": "Freeride", "extreme": "Extreme"}}},
|
||||
"piste/grooming_downhill": {"key": "piste:grooming", "type": "combo", "label": "Grooming", "strings": {"options": {"classic": "Classic", "mogul": "Mogul", "backcountry": "Backcountry - no grooming"}}},
|
||||
"piste/grooming_hike": {"key": "piste:grooming", "type": "combo", "label": "Grooming", "strings": {"options": {"classic": "Classic - Winter Hiking", "backcountry": "Backcountry - Snowshoeing"}}},
|
||||
"piste/grooming_nordic": {"key": "piste:grooming", "type": "combo", "label": "Grooming", "strings": {"options": {"classic": "Classic", "backcountry": "Backcountry, no grooming", "classic+skating": "Classic and Skating", "scooter": "Scooter/Snowmobile", "skating": "Skating"}}},
|
||||
"piste/grooming": {"key": "piste:grooming", "type": "combo", "label": "Grooming", "strings": {"options": {"classic": "Classic", "mogul": "Mogul", "backcountry": "Backcountry", "classic+skating": "Classic and Skating", "scooter": "Scooter/Snowmobile", "skating": "Skating"}}},
|
||||
"piste/type": {"key": "piste:type", "type": "typeCombo", "label": "Type", "strings": {"options": {"downhill": "Downhill", "nordic": "Nordic", "skitour": "Skitour", "sled": "Sled", "hike": "Hike", "sleigh": "Sleigh", "ice_skate": "Ice Skate", "snow_park": "Snow Park", "playground": "Playground", "connection": "Connection"}}},
|
||||
"place": {"key": "place", "type": "typeCombo", "label": "Type"},
|
||||
"plant": {"key": "plant", "type": "combo", "label": "Plant"},
|
||||
"plant/method": {"key": "plant:method", "type": "combo", "label": "Generation Method"},
|
||||
"plant/output/electricity": {"key": "plant:output:electricity", "type": "typeCombo", "label": "Power Output", "placeholder": "500 MW, 1000 MW, 2000 MW...", "snake_case": false},
|
||||
"plant/source": {"key": "plant:source", "type": "combo", "label": "Energy Source"},
|
||||
"playground": {"key": "playground", "type": "combo", "label": "Type"},
|
||||
"playground/theme": {"key": "playground:theme", "type": "combo", "label": "Theme"},
|
||||
"polling_station": {"key": "polling_station", "type": "check", "label": "Polling Place", "terms": ["voting place"]},
|
||||
"population": {"key": "population", "type": "text", "label": "Population"},
|
||||
"post": {"type": "address", "key": "post", "keys": ["post:block_number", "post:city", "post:block_number", "post:conscriptionnumber", "post:county", "post:country", "post:county", "post:district", "post:floor", "post:hamlet", "post:housename", "post:housenumber", "post:neighbourhood", "post:place", "post:postcode", "post:province", "post:quarter", "post:state", "post:street", "post:subdistrict", "post:suburb", "post:unit"], "label": "Delivery Address"},
|
||||
"power_supply": {"key": "power_supply", "type": "check", "label": "Power Supply"},
|
||||
"power": {"key": "power", "type": "typeCombo", "label": "Type"},
|
||||
"preschool": {"key": "preschool", "type": "check", "label": "Preschool"},
|
||||
"produce": {"key": "produce", "type": "semiCombo", "label": "Produce"},
|
||||
"product": {"key": "product", "type": "semiCombo", "label": "Products"},
|
||||
"public_bookcase/type": {"key": "public_bookcase:type", "type": "combo", "label": "Type"},
|
||||
"pump": {"key": "pump", "type": "combo", "label": "Pump", "strings": {"options": {"yes": "Yes", "manual": "Manual Hand Pump", "powered": "Machine-Powered Pump", "no": "None"}}},
|
||||
"railway": {"key": "railway", "type": "typeCombo", "label": "Type"},
|
||||
"railway/position": {"key": "railway:position", "type": "text", "placeholder": "Distance to one decimal (123.4)", "label": "Milestone Position"},
|
||||
"railway/signal/direction": {"key": "railway:signal:direction", "type": "combo", "label": "Direction Affected", "strings": {"options": {"forward": "Forward", "backward": "Backward", "both": "Both / All"}}},
|
||||
"rating": {"key": "rating", "type": "combo", "label": "Power Rating", "snake_case": false},
|
||||
"rcn_ref": {"key": "rcn_ref", "type": "text", "label": "Cycling Code"},
|
||||
"recycling_accepts": {"key": "recycling:", "type": "multiCombo", "label": "Accepts"},
|
||||
"recycling_type": {"key": "recycling_type", "type": "combo", "label": "Type", "placeholder": "Container, Center", "strings": {"options": {"container": "Container", "centre": "Center"}}},
|
||||
"ref_aeroway_gate": {"key": "ref", "type": "text", "label": "Gate Number"},
|
||||
"ref_golf_hole": {"key": "ref", "type": "text", "label": "Hole Number", "placeholder": "1-18"},
|
||||
"ref_highway_junction": {"key": "ref", "type": "text", "label": "Junction Number"},
|
||||
"ref_platform": {"key": "ref", "type": "text", "label": "Platform Number"},
|
||||
"ref_road_number": {"key": "ref", "type": "text", "label": "Road Number"},
|
||||
"ref_room_number": {"key": "ref", "type": "text", "label": "Room Number"},
|
||||
"ref_route": {"key": "ref", "type": "text", "label": "Route Number"},
|
||||
"ref_runway": {"key": "ref", "type": "text", "label": "Runway Number", "placeholder": "e.g. 01L/19R"},
|
||||
"ref_stop_position": {"key": "ref", "type": "text", "label": "Stop Number"},
|
||||
"ref_taxiway": {"key": "ref", "type": "text", "label": "Taxiway Name", "placeholder": "e.g. A5"},
|
||||
"ref": {"key": "ref", "type": "text", "label": "Reference Code"},
|
||||
"ref/isil": {"key": "ref:isil", "type": "text", "label": "ISIL Code"},
|
||||
"ref/vatin": {"key": "ref:vatin", "type": "identifier", "label": "VAT ID Number", "notCountryCodes": ["ao", "ai", "bm", "bt", "io", "vg", "bn", "ky", "km", "cu", "dj", "er", "fk", "gi", "gg", "hk", "iq", "ki", "xk", "kw", "lr", "ly", "mo", "mv", "mh", "fm", "ms", "mm", "nr", "kp", "om", "pw", "pn", "qa", "sh", "sm", "st", "sb", "so", "gs", "ss", "sr", "sz", "sy", "tl", "tc", "tv", "us", "va", "ye"], "terms": ["value added tax identification number", "vatin"]},
|
||||
"relation": {"key": "type", "type": "combo", "label": "Type"},
|
||||
"religion": {"key": "religion", "type": "combo", "label": "Religion"},
|
||||
"reservation": {"key": "reservation", "type": "combo", "label": "Reservations", "strings": {"options": {"yes": "Accepted", "no": "Not Accepted", "required": "Required", "recommended": "Recommended"}}},
|
||||
"residential": {"key": "residential", "type": "combo", "label": "Type"},
|
||||
"resort": {"key": "resort", "type": "combo", "label": "Type"},
|
||||
"resource": {"key": "resource", "type": "semiCombo", "label": "Resources"},
|
||||
"restriction": {"key": "restriction", "type": "combo", "label": "Type"},
|
||||
"restrictions": {"type": "restrictions", "geometry": "vertex", "icon": "iD-restrictions", "reference": {"rtype": "restriction"}, "label": "Turn Restrictions"},
|
||||
"roof/colour": {"key": "roof:colour", "type": "combo", "label": "Roof Color"},
|
||||
"room": {"key": "room", "type": "combo", "label": "Type"},
|
||||
"rooms": {"key": "rooms", "type": "number", "minValue": 0, "label": "Rooms"},
|
||||
"route_master": {"key": "route_master", "type": "combo", "label": "Type"},
|
||||
"route": {"key": "route", "type": "combo", "label": "Type"},
|
||||
"rwn_ref": {"key": "rwn_ref", "type": "text", "label": "Walking Code"},
|
||||
"sac_scale": {"key": "sac_scale", "type": "combo", "label": "Hiking Difficulty", "placeholder": "Mountain Hiking, Alpine Hiking...", "strings": {"options": {"hiking": "T1: Hiking", "mountain_hiking": "T2: Mountain Hiking", "demanding_mountain_hiking": "T3: Demanding Mountain Hiking", "alpine_hiking": "T4: Alpine Hiking", "demanding_alpine_hiking": "T5: Demanding Alpine Hiking", "difficult_alpine_hiking": "T6: Difficult Alpine Hiking"}}},
|
||||
"salt": {"key": "salt", "type": "check", "label": "Salt", "terms": ["saline", "salinated"]},
|
||||
"sanitary_dump_station": {"key": "sanitary_dump_station", "type": "check", "label": "Toilet Disposal"},
|
||||
"screen": {"key": "screen", "type": "number", "label": "Screens", "placeholder": "1, 4, 8…", "minValue": 0},
|
||||
"scuba_diving": {"key": "scuba_diving:", "type": "multiCombo", "label": "Services", "options": ["repair", "courses", "rental", "filling", "air_filling", "nitrox_filling", "trimix_filling", "oxygen_filling"]},
|
||||
"seamark/beacon_isolated_danger/shape": {"key": "seamark:beacon_isolated_danger:shape", "type": "combo", "label": "Shape"},
|
||||
"seamark/beacon_lateral/category": {"key": "seamark:beacon_lateral:category", "type": "combo", "label": "Category", "strings": {"options": {"port": "Port", "starboard": "Starboard", "waterway_left": "Waterway Left", "waterway_right": "Waterway Right", "danger_left": "Danger Left", "danger_right": "Danger Right"}}},
|
||||
"seamark/beacon_lateral/colour": {"key": "seamark:beacon_lateral:colour", "type": "combo", "label": "Color", "strings": {"options": {"red": "Red", "green": "Green", "grey": "Grey"}}},
|
||||
"seamark/beacon_lateral/shape": {"key": "seamark:beacon_lateral:shape", "type": "combo", "label": "Shape"},
|
||||
"seamark/beacon_lateral/system": {"key": "seamark:beacon_lateral:system", "type": "combo", "label": "System", "strings": {"options": {"iala-a": "IALA A", "iala-b": "IALA B", "cevni": "CEVNI", "other": "Other"}}},
|
||||
"seamark/buoy_lateral/category": {"key": "seamark:buoy_lateral:category", "type": "combo", "label": "Category", "strings": {"options": {"port": "Port", "starboard": "Starboard", "channel_left": "Channel Left", "channel_right": "Channel Right", "waterway_left": "Waterway Left", "waterway_right": "Waterway Right", "danger_left": "Danger Left", "danger_right": "Danger Right", "preferred_channel_port": "Preferred Channel Port", "preferred_channel_starboard": "Preferred Channel Starboard"}}},
|
||||
"seamark/buoy_lateral/colour": {"key": "seamark:buoy_lateral:colour", "type": "combo", "label": "Color", "strings": {"options": {"red": "Red", "green": "Green", "red;white;red;white": "Red-White-Red-White", "green;white;green;white": "Green-White-Green-White", "red;green;red": "Red-Green-Red", "green;red;green": "Green-Red-Green", "white": "White", "yellow": "Yellow"}}},
|
||||
"seamark/buoy_lateral/shape": {"key": "seamark:buoy_lateral:shape", "type": "combo", "label": "Shape"},
|
||||
"seamark/buoy_lateral/system": {"key": "seamark:buoy_lateral:system", "type": "combo", "label": "System", "strings": {"options": {"iala-a": "IALA A", "iala-b": "IALA B", "cevni": "CEVNI", "other": "Other"}}},
|
||||
"seamark/mooring/category": {"key": "seamark:mooring:category", "type": "combo", "label": "Category"},
|
||||
"seamark/type": {"key": "seamark:type", "type": "combo", "label": "Seamark", "terms": ["marine"]},
|
||||
"seamark/wreck/category": {"key": "seamark:wreck:category", "type": "combo", "label": "Category"},
|
||||
"seasonal": {"key": "seasonal", "type": "check", "label": "Seasonal"},
|
||||
"seats": {"key": "seats", "type": "number", "minValue": 0, "label": "Seats", "placeholder": "2, 4, 6..."},
|
||||
"second_hand": {"key": "second_hand", "type": "combo", "label": "Sells Used", "placeholder": "Yes, No, Only", "strings": {"options": {"yes": "Yes", "no": "No", "only": "Only"}}},
|
||||
"segregated": {"key": "segregated", "type": "check", "label": "Bicycle-Pedestrian Separation"},
|
||||
"self_service": {"key": "self_service", "type": "check", "label": "Self-Service"},
|
||||
"service_rail": {"key": "service", "type": "combo", "label": "Service Type", "strings": {"options": {"spur": "Spur", "yard": "Yard", "siding": "Siding", "crossover": "Crossover"}}},
|
||||
"service_times": {"key": "service_times", "type": "text", "label": "Service Times"},
|
||||
"service": {"key": "service", "type": "combo", "label": "Type", "options": ["parking_aisle", "driveway", "alley", "emergency_access", "drive-through"]},
|
||||
"service/bicycle": {"key": "service:bicycle:", "type": "multiCombo", "label": "Services"},
|
||||
"service/vehicle": {"key": "service:vehicle:", "type": "multiCombo", "label": "Services"},
|
||||
"shelter_type": {"key": "shelter_type", "type": "combo", "label": "Type"},
|
||||
"shelter": {"key": "shelter", "type": "check", "label": "Shelter"},
|
||||
"shop": {"key": "shop", "type": "typeCombo", "label": "Type"},
|
||||
"shower": {"key": "shower", "type": "check", "label": "Showers"},
|
||||
"siren/purpose": {"key": "siren:purpose", "type": "combo", "label": "Purpose"},
|
||||
"siren/type": {"key": "siren:type", "type": "combo", "label": "Type", "strings": {"options": {"pneumatic": "Pneumatic", "electronic": "Electronic", "other": "Other"}}},
|
||||
"site_type": {"key": "site_type", "type": "combo", "label": "Site Type"},
|
||||
"site": {"key": "site", "type": "combo", "label": "Type"},
|
||||
"smoking": {"key": "smoking", "type": "combo", "label": "Smoking", "placeholder": "No, Separated, Yes...", "strings": {"options": {"no": "No smoking anywhere", "separated": "In smoking areas, not physically isolated", "isolated": "In smoking areas, physically isolated", "outside": "Allowed outside", "yes": "Allowed everywhere", "dedicated": "Dedicated to smokers (e.g. smokers' club)"}}},
|
||||
"smoothness": {"key": "smoothness", "type": "combo", "label": "Smoothness", "placeholder": "Thin Rollers, Wheels, Off-Road...", "strings": {"options": {"excellent": "Thin Rollers: rollerblade, skateboard", "good": "Thin Wheels: racing bike", "intermediate": "Wheels: city bike, wheelchair, scooter", "bad": "Robust Wheels: trekking bike, car, rickshaw", "very_bad": "High Clearance: light duty off-road vehicle", "horrible": "Off-Road: heavy duty off-road vehicle", "very_horrible": "Specialized off-road: tractor, ATV", "impassable": "Impassable / No wheeled vehicle"}}},
|
||||
"sms": {"key": "sms", "type": "check", "label": "SMS"},
|
||||
"social_facility_for": {"key": "social_facility:for", "type": "combo", "label": "People Served"},
|
||||
"social_facility": {"key": "social_facility", "type": "combo", "label": "Type"},
|
||||
"source": {"key": "source", "type": "semiCombo", "icon": "source", "universal": true, "label": "Sources", "snake_case": false, "caseSensitive": true, "options": ["survey", "local knowledge", "gps", "aerial imagery", "streetlevel imagery"], "terms": ["reference"]},
|
||||
"species/wikidata": {"key": "species:wikidata", "keys": ["species:wikidata", "species:wikipedia"], "type": "wikidata", "label": "Species Wikidata"},
|
||||
"sport_ice": {"key": "sport", "type": "semiCombo", "label": "Sports", "options": ["ice_skating", "ice_hockey", "multi", "curling", "ice_stock"]},
|
||||
"sport_racing_motor": {"key": "sport", "type": "semiCombo", "label": "Sports", "options": ["motor", "karting", "motocross"]},
|
||||
"sport_racing_nonmotor": {"key": "sport", "type": "semiCombo", "label": "Sports", "options": ["bmx", "cycling", "dog_racing", "horse_racing", "running"]},
|
||||
"sport": {"key": "sport", "type": "semiCombo", "label": "Sports"},
|
||||
"stars": {"key": "stars", "type": "combo", "label": "Stars", "terms": ["rating"]},
|
||||
"start_date": {"key": "start_date", "type": "text", "universal": true, "label": "Start Date", "terms": ["inception"]},
|
||||
"step_count": {"key": "step_count", "type": "number", "minValue": 0, "label": "Number of Steps"},
|
||||
"stile": {"key": "stile", "type": "combo", "label": "Type"},
|
||||
"stop": {"key": "stop", "type": "combo", "label": "Stop Type", "strings": {"options": {"all": "All Ways", "minor": "Minor Road"}}},
|
||||
"street_cabinet": {"key": "street_cabinet", "type": "combo", "label": "Type"},
|
||||
"stroller": {"key": "stroller", "type": "radio", "strings": {"options": {"yes": "Yes", "limited": "Limited", "no": "No"}}, "label": "Stroller Access", "terms": ["baby carriage", "perambulator", "pram", "pushchair"]},
|
||||
"structure_waterway": {"type": "structureRadio", "keys": ["tunnel"], "label": "Structure", "placeholder": "Unknown", "strings": {"options": {"tunnel": "Tunnel"}}},
|
||||
"structure": {"type": "structureRadio", "keys": ["bridge", "tunnel", "embankment", "cutting", "ford"], "label": "Structure", "placeholder": "Unknown", "strings": {"options": {"bridge": "Bridge", "tunnel": "Tunnel", "embankment": "Embankment", "cutting": "Cutting", "ford": "Ford"}}},
|
||||
"studio": {"key": "studio", "type": "combo", "label": "Type"},
|
||||
"substance": {"key": "substance", "type": "combo", "label": "Substance"},
|
||||
"substation": {"key": "substation", "type": "typeCombo", "label": "Type"},
|
||||
"supervised": {"key": "supervised", "type": "check", "label": "Supervised", "terms": ["guarded", "manned"]},
|
||||
"support": {"key": "support", "type": "combo", "label": "Support"},
|
||||
"surface": {"key": "surface", "type": "combo", "label": "Surface"},
|
||||
"surveillance": {"key": "surveillance", "type": "combo", "label": "Surveillance Kind"},
|
||||
"surveillance/type": {"key": "surveillance:type", "type": "combo", "label": "Surveillance Type", "strings": {"options": {"camera": "Camera", "guard": "Guard", "ALPR": "Automatic License Plate Reader"}}},
|
||||
"surveillance/zone": {"key": "surveillance:zone", "type": "combo", "label": "Surveillance Zone"},
|
||||
"survey/date": {"key": "survey:date", "type": "text", "label": "Last Survey Date"},
|
||||
"swimming_pool": {"key": "swimming_pool", "type": "combo", "label": "Type"},
|
||||
"switch": {"key": "switch", "type": "combo", "label": "Type", "strings": {"options": {"mechanical": "Mechanical", "circuit_breaker": "Circuit Breaker", "disconnector": "Disconnector", "earthing": "Earthing"}}},
|
||||
"tactile_paving": {"key": "tactile_paving", "type": "check", "label": "Tactile Paving"},
|
||||
"takeaway": {"key": "takeaway", "type": "combo", "label": "Takeaway", "placeholder": "Yes, No, Takeaway Only...", "strings": {"options": {"yes": "Yes", "no": "No", "only": "Takeaway Only"}}, "terms": ["take out", "takeout"]},
|
||||
"target": {"key": "target", "type": "combo", "label": "Target"},
|
||||
"tidal": {"key": "tidal", "type": "check", "label": "Tidal"},
|
||||
"to": {"key": "to", "type": "text", "label": "To"},
|
||||
"toilets": {"key": "toilets", "type": "check", "label": "Toilets"},
|
||||
"toilets/disposal": {"key": "toilets:disposal", "type": "combo", "label": "Disposal", "strings": {"options": {"flush": "Flush", "pitlatrine": "Pit Latrine", "chemical": "Chemical", "bucket": "Bucket"}}},
|
||||
"toilets/handwashing": {"key": "toilets:handwashing", "type": "check", "label": "Handwashing"},
|
||||
"toilets/position": {"key": "toilets:position", "type": "semiCombo", "label": "Positions"},
|
||||
"toll": {"key": "toll", "type": "check", "label": "Toll"},
|
||||
"tomb": {"key": "tomb", "type": "typeCombo", "label": "Type"},
|
||||
"tourism": {"key": "tourism", "type": "typeCombo", "label": "Type"},
|
||||
"tower/construction": {"key": "tower:construction", "type": "combo", "label": "Construction", "placeholder": "Guyed, Lattice, Concealed, ..."},
|
||||
"tower/type": {"key": "tower:type", "type": "combo", "label": "Type"},
|
||||
"townhall/type": {"key": "townhall:type", "type": "combo", "label": "Type"},
|
||||
"tracktype": {"key": "tracktype", "type": "combo", "label": "Track Type", "placeholder": "Solid, Mostly Solid, Soft...", "strings": {"options": {"grade1": "Solid: paved or heavily compacted hardcore surface", "grade2": "Mostly Solid: gravel/rock with some soft material mixed in", "grade3": "Even mixture of hard and soft materials", "grade4": "Mostly Soft: soil/sand/grass with some hard material mixed in", "grade5": "Soft: soil/sand/grass"}}},
|
||||
"trade": {"key": "trade", "type": "typeCombo", "label": "Type"},
|
||||
"traffic_calming": {"key": "traffic_calming", "type": "typeCombo", "label": "Type"},
|
||||
"traffic_sign": {"key": "traffic_sign", "type": "typeCombo", "label": "Traffic Sign"},
|
||||
"traffic_sign/direction": {"key": "traffic_sign:direction", "type": "combo", "label": "Direction Affected", "strings": {"options": {"forward": "Forward", "backward": "Backward", "both": "Both / All"}}},
|
||||
"traffic_signals": {"key": "traffic_signals", "type": "combo", "label": "Type", "default": "signal"},
|
||||
"traffic_signals/direction": {"key": "traffic_signals:direction", "type": "combo", "label": "Direction Affected", "strings": {"options": {"forward": "Forward", "backward": "Backward", "both": "Both / All"}}},
|
||||
"trail_visibility": {"key": "trail_visibility", "type": "combo", "label": "Trail Visibility", "placeholder": "Excellent, Good, Bad...", "strings": {"options": {"excellent": "Excellent: unambiguous path or markers everywhere", "good": "Good: markers visible, sometimes require searching", "intermediate": "Intermediate: few markers, path mostly visible", "bad": "Bad: no markers, path sometimes invisible/pathless", "horrible": "Horrible: often pathless, some orientation skills required", "no": "No: pathless, excellent orientation skills required"}}},
|
||||
"transformer": {"key": "transformer", "type": "combo", "label": "Type", "strings": {"options": {"distribution": "Distribution", "generator": "Generator", "converter": "Converter", "traction": "Traction", "auto": "Autotransformer", "phase_angle_regulator": "Phase Angle Regulator", "auxiliary": "Auxiliary", "yes": "Unknown"}}},
|
||||
"trees": {"key": "trees", "type": "semiCombo", "label": "Trees"},
|
||||
"trench": {"key": "trench", "type": "combo", "label": "Type"},
|
||||
"trolley_wire": {"key": "trolley_wire", "type": "check", "label": "Overhead Trolley Wires"},
|
||||
"tunnel": {"key": "tunnel", "type": "typeCombo", "label": "Type", "placeholder": "Default"},
|
||||
"usage_rail": {"key": "usage", "type": "combo", "label": "Usage Type", "strings": {"options": {"main": "Main", "branch": "Branch", "industrial": "Industrial", "military": "Military", "test": "Test", "tourism": "Tourism"}}},
|
||||
"utility_semi": {"key": "utility", "type": "semiCombo", "label": "Utilities"},
|
||||
"utility": {"key": "utility", "type": "typeCombo", "label": "Utility"},
|
||||
"valve": {"key": "valve", "type": "combo", "label": "Type"},
|
||||
"vending": {"key": "vending", "type": "semiCombo", "label": "Types of Goods"},
|
||||
"video_calls": {"key": "video", "type": "check", "label": "Video Calls"},
|
||||
"visibility": {"key": "visibility", "type": "combo", "label": "Visibility", "strings": {"options": {"house": "Up to 5m (16ft)", "street": "5 to 20m (16 to 65ft)", "area": "Over 20m (65ft)"}}},
|
||||
"volcano/status": {"key": "volcano:status", "type": "combo", "label": "Volcano Status", "strings": {"options": {"active": "Active", "dormant": "Dormant", "extinct": "Extinct"}}},
|
||||
"volcano/type": {"key": "volcano:type", "type": "combo", "label": "Volcano Type", "strings": {"options": {"stratovolcano": "Stratovolcano", "shield": "Shield", "scoria": "Scoria"}}},
|
||||
"voltage_electrified": {"key": "voltage", "type": "combo", "label": "Voltage", "prerequisiteTag": {"key": "electrified", "valueNot": "no"}},
|
||||
"voltage": {"key": "voltage", "type": "combo", "label": "Voltage"},
|
||||
"voltage/primary": {"key": "voltage:primary", "type": "combo", "label": "Primary Voltage"},
|
||||
"voltage/secondary": {"key": "voltage:secondary", "type": "combo", "label": "Secondary Voltage"},
|
||||
"voltage/tertiary": {"key": "voltage:tertiary", "type": "combo", "label": "Tertiary Voltage"},
|
||||
"wall": {"key": "wall", "type": "combo", "label": "Type"},
|
||||
"waste": {"key": "waste", "type": "semiCombo", "label": "Waste"},
|
||||
"water_point": {"key": "water_point", "type": "check", "label": "Water Point"},
|
||||
"water_source": {"key": "water_source", "default": "main", "type": "combo", "label": "Water Source"},
|
||||
"water_volume": {"key": "water_volume", "type": "number", "label": "Water Reserve Volume (m³)", "snake_case": false},
|
||||
"water": {"key": "water", "type": "combo", "label": "Type"},
|
||||
"waterway": {"key": "waterway", "type": "typeCombo", "label": "Type"},
|
||||
"website": {"key": "website", "type": "url", "icon": "website", "placeholder": "https://example.com", "label": "Website", "terms": ["internet presence", "uri", "url", "webpage"]},
|
||||
"wetland": {"key": "wetland", "type": "combo", "label": "Type"},
|
||||
"wheelchair": {"key": "wheelchair", "type": "radio", "strings": {"options": {"yes": "Yes", "limited": "Limited", "no": "No"}}, "icon": "maki-wheelchair", "label": "Wheelchair Access", "terms": ["handicap access"]},
|
||||
"wholesale": {"key": "wholesale", "type": "typeCombo", "label": "Wholesale"},
|
||||
"width": {"key": "width", "type": "number", "minValue": 0, "label": "Width (Meters)"},
|
||||
"wikidata": {"key": "wikidata", "keys": ["wikidata", "wikipedia"], "type": "wikidata", "icon": "wikipedia", "universal": true, "label": "Wikidata"},
|
||||
"wikimedia_commons": {"key": "wikimedia_commons", "type": "identifier", "label": "Wikimedia Commons Page", "placeholder": "File:Example.jpg", "urlFormat": "https://commons.wikimedia.org/wiki/{value}", "pattern": "^(?:File|Category):.{1,}", "universal": true},
|
||||
"wikipedia": {"key": "wikipedia", "keys": ["wikipedia", "wikidata"], "type": "wikipedia", "icon": "wikipedia", "universal": true, "label": "Wikipedia"},
|
||||
"windings": {"key": "windings", "type": "number", "minValue": 1, "label": "Windings", "placeholder": "1, 2, 3..."},
|
||||
"windings/configuration": {"key": "windings:configuration", "type": "combo", "label": "Windings Configuration", "strings": {"options": {"star": "Star / Wye", "delta": "Delta", "open-delta": "Open Delta", "zigzag": "Zig Zag", "open": "Open", "scott": "Scott", "leblanc": "Leblanc"}}}
|
||||
}
|
||||
"access_aisle": {"key": "access_aisle", "type": "combo", "label": "Type"},
|
||||
"access_simple": {"key": "access", "type": "combo", "label": "Allowed Access", "options": ["yes", "permissive", "private", "customers", "permit", "no"], "terms": ["permitted", "private", "public"]},
|
||||
"access": {"keys": ["access", "foot", "motor_vehicle", "bicycle", "horse"], "reference": {"key": "access"}, "type": "access", "label": "Allowed Access", "placeholder": "Not Specified", "strings": {"types": {"access": "All", "foot": "Foot", "motor_vehicle": "Motor Vehicles", "bicycle": "Bicycles", "horse": "Horses"}, "options": {"yes": {"title": "Allowed", "description": "Access allowed by law; a right of way"}, "no": {"title": "Prohibited", "description": "Access not allowed to the general public"}, "permissive": {"title": "Permissive", "description": "Access allowed until such time as the owner revokes the permission"}, "private": {"title": "Private", "description": "Access allowed only with permission of the owner on an individual basis"}, "designated": {"title": "Designated", "description": "Access allowed according to signs or specific local laws"}, "destination": {"title": "Destination", "description": "Access allowed only to reach a destination"}, "dismount": {"title": "Dismount", "description": "Access allowed but rider must dismount"}, "permit": {"title": "Permit", "description": "Access allowed only with a valid permit or license"}}}},
|
||||
"addr/interpolation": {"key": "addr:interpolation", "type": "combo", "label": "Type", "strings": {"options": {"all": "All", "even": "Even", "odd": "Odd", "alphabetic": "Alphabetic"}}},
|
||||
"address": {"type": "address", "key": "addr", "keys": ["addr:block_number", "addr:city", "addr:block_number", "addr:conscriptionnumber", "addr:county", "addr:country", "addr:county", "addr:district", "addr:floor", "addr:hamlet", "addr:housename", "addr:housenumber", "addr:neighbourhood", "addr:place", "addr:postcode", "addr:province", "addr:quarter", "addr:state", "addr:street", "addr:subdistrict", "addr:suburb", "addr:unit"], "icon": "address", "label": "Address", "strings": {"placeholders": {"block_number": "Block Number", "block_number!jp": "Block No.", "city": "City", "city!cn": "City/Prefecture/League", "city!jp": "City/Town/Village/Tokyo Special Ward", "city!vn": "City/Town", "conscriptionnumber": "123", "country": "Country", "county": "County", "county!jp": "District", "district": "District", "district!cn": "District/County/Banner", "district!vn": "Arrondissement/Town/District", "floor": "Floor", "hamlet": "Hamlet", "housename": "Housename", "housenumber": "123", "housenumber!jp": "Building No./Lot No.", "neighbourhood": "Neighbourhood", "neighbourhood!jp": "Chōme/Aza/Koaza", "place": "Place", "postcode": "Postcode", "province": "Province", "province!cn": "Province/Municipality/AR/SAR", "province!jp": "Prefecture", "quarter": "Quarter", "quarter!jp": "Ōaza/Machi", "state": "State", "street": "Street", "subdistrict": "Subdistrict", "subdistrict!vn": "Ward/Commune/Townlet", "suburb": "Suburb", "suburb!jp": "Ward", "unit": "Unit"}}, "terms": ["location"]},
|
||||
"admin_level": {"key": "admin_level", "type": "number", "minValue": 1, "label": "Admin Level"},
|
||||
"aerialway": {"key": "aerialway", "type": "typeCombo", "label": "Type"},
|
||||
"aerialway/access": {"key": "aerialway:access", "type": "combo", "label": "Access", "strings": {"options": {"entry": "Entry", "exit": "Exit", "both": "Both"}}},
|
||||
"aerialway/bubble": {"key": "aerialway:bubble", "type": "check", "label": "Bubble"},
|
||||
"aerialway/capacity": {"key": "aerialway:capacity", "type": "number", "minValue": 0, "label": "Capacity (per hour)", "placeholder": "500, 2500, 5000..."},
|
||||
"aerialway/duration": {"key": "aerialway:duration", "type": "number", "minValue": 0, "label": "Duration (minutes)", "placeholder": "1, 2, 3..."},
|
||||
"aerialway/heating": {"key": "aerialway:heating", "type": "check", "label": "Heated"},
|
||||
"aerialway/occupancy": {"key": "aerialway:occupancy", "type": "number", "minValue": 0, "label": "Occupancy", "placeholder": "2, 4, 8..."},
|
||||
"aerialway/summer/access": {"key": "aerialway:summer:access", "type": "combo", "label": "Access (summer)", "strings": {"options": {"entry": "Entry", "exit": "Exit", "both": "Both"}}},
|
||||
"aeroway": {"key": "aeroway", "type": "typeCombo", "label": "Type"},
|
||||
"agrarian": {"key": "agrarian", "type": "semiCombo", "label": "Products"},
|
||||
"air_conditioning": {"key": "air_conditioning", "type": "check", "label": "Air Conditioning", "terms": ["cooling system", "refrigeration"]},
|
||||
"amenity": {"key": "amenity", "type": "typeCombo", "label": "Type"},
|
||||
"animal_boarding": {"key": "animal_boarding", "type": "semiCombo", "label": "For Animals"},
|
||||
"animal_breeding": {"key": "animal_breeding", "type": "semiCombo", "label": "For Animals"},
|
||||
"animal_shelter": {"key": "animal_shelter", "type": "semiCombo", "label": "For Animals"},
|
||||
"architect": {"key": "architect", "type": "text", "label": "Architect", "terms": ["building designer"]},
|
||||
"area/highway": {"key": "area:highway", "type": "typeCombo", "label": "Type"},
|
||||
"artist": {"key": "artist_name", "type": "text", "label": "Artist"},
|
||||
"artwork_type": {"key": "artwork_type", "type": "combo", "label": "Type"},
|
||||
"atm": {"key": "atm", "type": "check", "label": "ATM"},
|
||||
"attraction": {"key": "attraction", "type": "typeCombo", "label": "Type"},
|
||||
"baby_feeding": {"key": "baby_feeding", "type": "combo", "label": "Baby Nursing Area", "strings": {"options": {"room": "Dedicated Room", "yes": "Marked Space", "no": "None"}}, "terms": ["baby feeding", "breastfeeding", "lactation", "mothers", "nursing"]},
|
||||
"baby_seat": {"key": "baby", "type": "check", "label": "Baby Seat"},
|
||||
"backcountry": {"key": "backcountry", "type": "check", "label": "Backcountry"},
|
||||
"backrest": {"key": "backrest", "type": "check", "label": "Backrest"},
|
||||
"bar": {"key": "bar", "type": "check", "label": "Bar"},
|
||||
"barrier": {"key": "barrier", "type": "typeCombo", "label": "Type"},
|
||||
"basin": {"key": "basin", "type": "combo", "label": "Type"},
|
||||
"bath/open_air": {"key": "bath:open_air", "label": "Open Air", "type": "check"},
|
||||
"bath/sand_bath": {"key": "bath:sand_bath", "label": "Sand Bath", "type": "check"},
|
||||
"bath/type": {"key": "bath:type", "type": "combo", "label": "Specialty", "strings": {"options": {"onsen": "Japanese Onsen", "foot_bath": "Foot Bath", "hot_spring": "Hot Spring"}}},
|
||||
"beauty": {"key": "beauty", "type": "semiCombo", "label": "Services"},
|
||||
"bench": {"key": "bench", "type": "check", "label": "Bench", "terms": ["seating"]},
|
||||
"bicycle_parking": {"key": "bicycle_parking", "type": "combo", "label": "Type"},
|
||||
"bin": {"key": "bin", "type": "check", "label": "Waste Bin", "terms": ["garbage can", "trash can"]},
|
||||
"blind": {"key": "blind", "type": "radio", "strings": {"options": {"yes": "Yes", "limited": "Limited", "no": "No"}}, "label": "Blind Person Access", "terms": ["sight impairment", "vision impairment"]},
|
||||
"blood_components": {"key": "blood:", "type": "multiCombo", "label": "Blood Components", "strings": {"options": {"whole": "whole blood", "plasma": "plasma", "platelets": "platelets", "stemcells": "stem cell samples"}}},
|
||||
"board_type": {"key": "board_type", "type": "combo", "label": "Type"},
|
||||
"bollard": {"key": "bollard", "type": "combo", "label": "Type"},
|
||||
"booth": {"key": "booth", "type": "combo", "label": "Booth", "caseSensitive": true},
|
||||
"bottle": {"key": "bottle", "type": "check", "label": "Bottle Filling"},
|
||||
"boules": {"key": "boules", "type": "typeCombo", "label": "Type"},
|
||||
"boundary": {"key": "boundary", "type": "combo", "label": "Type"},
|
||||
"brand": {"key": "brand", "type": "text", "label": "Brand"},
|
||||
"brewery": {"key": "brewery", "type": "semiCombo", "label": "Draft Beers", "terms": ["on tap"]},
|
||||
"bridge": {"key": "bridge", "type": "typeCombo", "label": "Type", "placeholder": "Default"},
|
||||
"bridge/support": {"key": "bridge:support", "type": "combo", "label": "Type"},
|
||||
"building_area": {"key": "building", "type": "combo", "default": "yes", "geometry": "area", "label": "Building"},
|
||||
"building": {"key": "building", "type": "combo", "label": "Building", "terms": ["structure"]},
|
||||
"building/levels_building": {"key": "building:levels", "type": "number", "minValue": 0, "label": "Building Levels", "placeholder": "2, 4, 6...", "prerequisiteTag": {"key": "building", "valueNot": "no"}},
|
||||
"building/levels": {"key": "building:levels", "type": "number", "minValue": 0, "label": "Levels", "placeholder": "2, 4, 6..."},
|
||||
"building/levels/underground": {"key": "building:levels:underground", "type": "number", "minValue": 0, "label": "Underground Levels", "placeholder": "2, 4, 6...", "terms": ["basement levels"]},
|
||||
"building/material": {"key": "building:material", "type": "combo", "label": "Material"},
|
||||
"bunker_type": {"key": "bunker_type", "type": "combo", "label": "Type"},
|
||||
"cables": {"key": "cables", "type": "number", "minValue": 1, "label": "Cables", "placeholder": "1, 2, 3..."},
|
||||
"camera/direction": {"key": "camera:direction", "type": "number", "label": "Direction (Degrees Clockwise)", "placeholder": "45, 90, 180, 270"},
|
||||
"camera/mount": {"key": "camera:mount", "type": "combo", "label": "Camera Mount"},
|
||||
"camera/type": {"key": "camera:type", "type": "combo", "label": "Camera Type", "strings": {"options": {"fixed": "Fixed", "panning": "Panning", "dome": "Dome"}}},
|
||||
"capacity": {"key": "capacity", "type": "number", "minValue": 0, "label": "Capacity", "placeholder": "50, 100, 200..."},
|
||||
"cash_in": {"key": "cash_in", "type": "check", "label": "Cash In"},
|
||||
"castle_type": {"key": "castle_type", "type": "combo", "label": "Type"},
|
||||
"changing_table": {"key": "changing_table", "type": "check", "label": "Diaper Changing Table"},
|
||||
"charge_fee": {"key": "charge", "type": "text", "label": "Fee Amount", "placeholder": "1 EUR, 5 USD, 10 JPY…", "prerequisiteTag": {"key": "fee", "valueNot": "no"}},
|
||||
"charge_toll": {"key": "charge", "type": "text", "label": "Toll Amount", "placeholder": "1 EUR, 5 USD, 10 JPY…", "prerequisiteTag": {"key": "toll", "valueNot": "no"}},
|
||||
"check_date": {"key": "check_date", "type": "text", "label": "Last Checked Date"},
|
||||
"clothes": {"key": "clothes", "type": "semiCombo", "label": "Clothes"},
|
||||
"club": {"key": "club", "type": "typeCombo", "label": "Type"},
|
||||
"collection_times": {"key": "collection_times", "type": "text", "label": "Collection Times"},
|
||||
"colour": {"key": "colour", "type": "text", "label": "Color"},
|
||||
"comment": {"key": "comment", "type": "textarea", "label": "Changeset Comment", "placeholder": "Brief description of your contributions (required)"},
|
||||
"communication_multi": {"key": "communication:", "type": "multiCombo", "label": "Communication Types"},
|
||||
"connectivity": {"key": "connectivity", "type": "text", "label": "Connectivity"},
|
||||
"construction": {"key": "construction", "type": "combo", "label": "Type"},
|
||||
"consulate": {"key": "consulate", "type": "combo", "label": "Type"},
|
||||
"consulting": {"key": "consulting", "type": "semiCombo", "label": "Expertise"},
|
||||
"contact/webcam": {"key": "contact:webcam", "type": "url", "icon": "website", "label": "Webcam URL", "placeholder": "http://example.com/"},
|
||||
"content": {"key": "content", "type": "combo", "label": "Content", "options": ["silage", "water", "oil", "fuel", "slurry", "gas", "manure", "sewage"]},
|
||||
"conveying_escalator": {"key": "conveying", "type": "check", "label": "Escalator"},
|
||||
"conveying": {"key": "conveying", "type": "typeCombo", "label": "Movement Direction", "strings": {"options": {"forward": "Forward", "backward": "Backward", "reversible": "Reversible"}}},
|
||||
"country_flag": {"key": "country", "type": "combo", "label": "Flag Country", "prerequisiteTag": {"key": "flag:type", "value": "national"}},
|
||||
"country": {"key": "country", "type": "combo", "label": "Country"},
|
||||
"couplings": {"key": "couplings", "type": "number", "minValue": 1, "label": "Couplings", "placeholder": "1, 2, 3..."},
|
||||
"covered": {"key": "covered", "type": "check", "label": "Covered"},
|
||||
"craft": {"key": "craft", "type": "typeCombo", "label": "Type"},
|
||||
"crane/type": {"key": "crane:type", "type": "combo", "label": "Crane Type", "strings": {"options": {"portal_crane": "Portal Crane", "floor-mounted_crane": "Floor-mounted Crane", "travel_lift": "Travel Lift"}}},
|
||||
"crop": {"key": "crop", "type": "semiCombo", "label": "Crops"},
|
||||
"crossing": {"key": "crossing", "type": "combo", "label": "Type"},
|
||||
"crossing/island": {"key": "crossing:island", "type": "check", "label": "Refuge Island"},
|
||||
"cuisine": {"key": "cuisine", "type": "semiCombo", "label": "Cuisines", "terms": ["fare", "food types"]},
|
||||
"currency_multi": {"key": "currency:", "type": "multiCombo", "label": "Currency Types", "terms": ["bills", "cash", "coins", "money"]},
|
||||
"cutting": {"key": "cutting", "type": "typeCombo", "label": "Type", "placeholder": "Default"},
|
||||
"cycle_network": {"key": "cycle_network", "type": "networkCombo", "label": "Network"},
|
||||
"cycleway": {"keys": ["cycleway", "cycleway:left", "cycleway:right"], "reference": {"key": "cycleway"}, "type": "cycleway", "label": "Bike Lanes", "placeholder": "none", "strings": {"types": {"cycleway:left": "Left side", "cycleway:right": "Right side"}, "options": {"none": {"title": "None", "description": "No bike lane"}, "lane": {"title": "Standard bike lane", "description": "A bike lane separated from auto traffic by a painted line"}, "shared_lane": {"title": "Shared bike lane", "description": "A bike lane with no separation from auto traffic"}, "track": {"title": "Bike track", "description": "A bike lane separated from traffic by a physical barrier"}, "share_busway": {"title": "Bike lane shared with bus", "description": "A bike lane shared with a bus lane"}, "opposite_lane": {"title": "Opposite bike lane", "description": "A bike lane that travels in the opposite direction of traffic"}, "opposite": {"title": "Contraflow bike lane", "description": "A bike lane that travels in both directions on a one-way street"}}}},
|
||||
"dance/style": {"key": "dance:style", "type": "semiCombo", "label": "Dance Styles"},
|
||||
"date": {"key": "date", "type": "check", "label": "Date"},
|
||||
"delivery": {"key": "delivery", "type": "check", "label": "Delivery"},
|
||||
"denomination": {"key": "denomination", "type": "combo", "label": "Denomination", "prerequisiteTag": {"key": "religion", "valueNot": "none"}},
|
||||
"denotation": {"key": "denotation", "type": "combo", "label": "Denotation"},
|
||||
"departures_board": {"key": "departures_board", "type": "combo", "label": "Departures Board", "strings": {"options": {"yes": "Yes", "timetable": "Timetable", "realtime": "Realtime", "no": "None"}}},
|
||||
"description": {"key": "description", "type": "textarea", "label": "Description", "universal": true, "terms": ["summary"]},
|
||||
"design": {"key": "design", "type": "combo", "label": "Design"},
|
||||
"destination_oneway": {"key": "destination", "type": "semiCombo", "label": "Destinations", "prerequisiteTag": {"key": "oneway", "value": "yes"}, "snake_case": false},
|
||||
"destination/ref_oneway": {"key": "destination:ref", "type": "semiCombo", "label": "Destination Road Numbers", "prerequisiteTag": {"key": "oneway", "value": "yes"}, "snake_case": false},
|
||||
"destination/symbol_oneway": {"key": "destination:symbol", "type": "semiCombo", "label": "Destination Symbols", "prerequisiteTag": {"key": "oneway", "value": "yes"}},
|
||||
"devices": {"key": "devices", "type": "number", "minValue": 0, "label": "Devices", "placeholder": "1, 2, 3..."},
|
||||
"diameter": {"key": "diameter", "type": "combo", "label": "Diameter", "snake_case": false, "placeholder": "5 mm, 10 cm, 15 in…"},
|
||||
"diet_multi": {"key": "diet:", "type": "multiCombo", "label": "Diet Types", "terms": ["gluten free", "fruitarian", "halal", "kosher", "lactose free", "meat", "pescatarian", "raw", "vegan", "vegetarian"]},
|
||||
"diplomatic": {"key": "diplomatic", "type": "combo", "label": "Type"},
|
||||
"diplomatic/services": {"key": "diplomatic:services:", "type": "multiCombo", "label": "Services"},
|
||||
"direction_cardinal": {"key": "direction", "type": "combo", "label": "Direction", "strings": {"options": {"N": "North", "E": "East", "S": "South", "W": "West", "NE": "Northeast", "SE": "Southeast", "SW": "Southwest", "NW": "Northwest", "NNE": "North-northeast", "ENE": "East-northeast", "ESE": "East-southeast", "SSE": "South-southeast", "SSW": "South-southwest", "WSW": "West-southwest", "WNW": "West-northwest", "NNW": "North-northwest"}}},
|
||||
"direction_clock": {"key": "direction", "type": "combo", "label": "Direction", "strings": {"options": {"clockwise": "Clockwise", "anticlockwise": "Counterclockwise"}}},
|
||||
"direction_vertex": {"key": "direction", "type": "combo", "label": "Direction Affected", "strings": {"options": {"forward": "Forward", "backward": "Backward", "both": "Both / All"}}},
|
||||
"direction": {"key": "direction", "type": "number", "label": "Direction (Degrees Clockwise)", "placeholder": "45, 90, 180, 270"},
|
||||
"dispensing": {"key": "dispensing", "type": "check", "label": "Dispenses Prescriptions", "default": "yes"},
|
||||
"display": {"key": "display", "type": "combo", "label": "Display", "options": ["analog", "digital", "sundial", "unorthodox"]},
|
||||
"distance": {"key": "distance", "type": "text", "label": "Distance"},
|
||||
"disused/railway": {"key": "disused:railway", "type": "typeCombo", "label": "Type"},
|
||||
"dock": {"key": "dock", "type": "combo", "label": "Type"},
|
||||
"dog": {"key": "dog", "type": "combo", "label": "Dogs", "strings": {"options": {"yes": "Allowed", "leashed": "Leashed Only", "no": "Not Allowed"}}, "terms": ["animals", "pets"]},
|
||||
"door_type": {"key": "door", "type": "typeCombo", "label": "Type"},
|
||||
"door": {"key": "door", "type": "combo", "label": "Door"},
|
||||
"drink_multi": {"key": "drink:", "type": "multiCombo", "label": "Drinks"},
|
||||
"drinking_water": {"key": "drinking_water", "type": "check", "label": "Drinkable", "terms": ["drinkworthy", "potable"]},
|
||||
"drive_through": {"key": "drive_through", "type": "check", "label": "Drive-Through"},
|
||||
"duration": {"key": "duration", "type": "text", "label": "Duration", "placeholder": "00:00"},
|
||||
"electrified": {"key": "electrified", "type": "combo", "label": "Electrification", "placeholder": "Contact Line, Electrified Rail...", "strings": {"options": {"contact_line": "Contact Line", "rail": "Electrified Rail", "yes": "Yes (unspecified)", "no": "No"}}, "terms": ["contact line", "powered", "third rail"]},
|
||||
"elevation": {"key": "ele", "type": "number", "icon": "elevation", "universal": true, "label": "Elevation", "terms": ["altitude"]},
|
||||
"email": {"key": "email", "type": "email", "placeholder": "example@example.com", "label": "Email"},
|
||||
"embankment": {"key": "embankment", "type": "typeCombo", "label": "Type", "placeholder": "Default"},
|
||||
"embassy": {"key": "embassy", "type": "combo", "label": "Type"},
|
||||
"emergency_combo": {"key": "emergency", "type": "combo", "label": "Type"},
|
||||
"emergency": {"key": "emergency", "type": "check", "label": "Emergency"},
|
||||
"enforcement": {"key": "enforcement", "type": "combo", "label": "Type"},
|
||||
"entrance": {"key": "entrance", "type": "typeCombo", "label": "Type"},
|
||||
"except": {"key": "except", "type": "combo", "label": "Exceptions"},
|
||||
"expected_rcn_route_relations": {"key": "expected_rcn_route_relations", "type": "number", "label": "Adjacent Cycling Nodes"},
|
||||
"expected_rwn_route_relations": {"key": "expected_rwn_route_relations", "type": "number", "label": "Adjacent Walking Nodes"},
|
||||
"faces": {"key": "faces", "type": "number", "minValue": 0, "label": "Faces"},
|
||||
"fax": {"key": "fax", "type": "tel", "label": "Fax", "placeholder": "+31 42 123 4567"},
|
||||
"fee": {"key": "fee", "type": "check", "label": "Fee"},
|
||||
"fence_type": {"key": "fence_type", "type": "combo", "label": "Type"},
|
||||
"fire_hydrant/diameter": {"key": "fire_hydrant:diameter", "type": "combo", "label": "Diameter (mm, in, or letters)", "snake_case": false},
|
||||
"fire_hydrant/pressure": {"key": "fire_hydrant:pressure", "type": "combo", "label": "Pressure (bar)", "snake_case": false},
|
||||
"fire_hydrant/type": {"key": "fire_hydrant:type", "type": "combo", "label": "Shape", "strings": {"options": {"pillar": "Pillar/Aboveground", "underground": "Underground", "wall": "Wall", "pipe": "Capped Pipe"}}},
|
||||
"fireplace": {"key": "fireplace", "type": "check", "label": "Fireplace"},
|
||||
"fishing": {"key": "fishing", "type": "combo", "label": "Fishing"},
|
||||
"fitness_station": {"key": "fitness_station", "type": "typeCombo", "label": "Equipment Type"},
|
||||
"fixme": {"key": "fixme", "type": "textarea", "label": "Fix Me", "universal": true, "terms": ["help request"]},
|
||||
"flag/type": {"key": "flag:type", "type": "combo", "label": "Flag Type"},
|
||||
"floating": {"key": "floating", "type": "check", "label": "Floating"},
|
||||
"flood_prone": {"key": "flood_prone", "type": "check", "label": "Flood Prone"},
|
||||
"ford": {"key": "ford", "type": "typeCombo", "label": "Type", "placeholder": "Default"},
|
||||
"fountain": {"key": "fountain", "type": "combo", "label": "Type"},
|
||||
"frequency_electrified": {"key": "frequency", "type": "combo", "label": "Operating Frequency", "prerequisiteTag": {"key": "electrified", "valueNot": "no"}},
|
||||
"frequency": {"key": "frequency", "type": "combo", "label": "Operating Frequency"},
|
||||
"from": {"key": "from", "type": "text", "label": "From"},
|
||||
"fuel_multi": {"key": "fuel:", "type": "multiCombo", "label": "Fuel Types"},
|
||||
"fuel": {"key": "fuel", "type": "combo", "label": "Fuel"},
|
||||
"gambling": {"key": "gambling", "type": "semiCombo", "label": "Games"},
|
||||
"gauge": {"key": "gauge", "type": "combo", "label": "Gauge"},
|
||||
"gender": {"type": "radio", "keys": ["male", "female", "unisex"], "label": "Gender", "placeholder": "Unknown", "strings": {"options": {"male": "Male", "female": "Female", "unisex": "Unisex"}}, "terms": ["access", "female", "male", "unisex"]},
|
||||
"generator/method": {"key": "generator:method", "type": "combo", "label": "Method"},
|
||||
"generator/output/electricity": {"key": "generator:output:electricity", "type": "typeCombo", "label": "Power Output", "placeholder": "50 MW, 100 MW, 200 MW...", "snake_case": false},
|
||||
"generator/source": {"key": "generator:source", "type": "combo", "label": "Source"},
|
||||
"generator/type": {"key": "generator:type", "type": "combo", "label": "Type"},
|
||||
"geyser/height": {"key": "geyser:height", "type": "text", "label": "Eruption Height"},
|
||||
"gnis/feature_id": {"key": "gnis:feature_id", "type": "identifier", "label": "GNIS Feature ID", "urlFormat": "https://geonames.usgs.gov/apex/f?p=gnispq:3:::NO::P3_FID:{value}", "pattern": "^[0-9]{1,}$", "countryCodes": ["us"], "terms": ["Federal Geographic Names Information Service", "United States Board on Geographic Names", "USA"]},
|
||||
"government": {"key": "government", "type": "typeCombo", "label": "Type"},
|
||||
"grape_variety": {"key": "grape_variety", "type": "semiCombo", "label": "Grape Varieties"},
|
||||
"group_only": {"key": "group_only", "type": "check", "label": "Groups Only"},
|
||||
"guest_house": {"key": "guest_house", "type": "combo", "label": "Type"},
|
||||
"handicap": {"key": "handicap", "type": "number", "label": "Handicap", "placeholder": "1-18"},
|
||||
"handrail": {"key": "handrail", "type": "check", "label": "Handrail"},
|
||||
"hashtags": {"key": "hashtags", "type": "semiCombo", "label": "Hashtags", "placeholder": "#example"},
|
||||
"healthcare": {"key": "healthcare", "type": "typeCombo", "label": "Type"},
|
||||
"healthcare/speciality": {"key": "healthcare:speciality", "type": "semiCombo", "reference": {"key": "healthcare"}, "label": "Specialties"},
|
||||
"height_building": {"key": "height", "minValue": 0, "type": "number", "label": "Building Height (Meters)", "prerequisiteTag": {"key": "building", "valueNot": "no"}},
|
||||
"height": {"key": "height", "minValue": 0, "type": "number", "label": "Height (Meters)"},
|
||||
"highspeed": {"key": "highspeed", "type": "check", "label": "High-Speed"},
|
||||
"highway": {"key": "highway", "type": "typeCombo", "label": "Type"},
|
||||
"historic": {"key": "historic", "type": "typeCombo", "label": "Type"},
|
||||
"historic/civilization": {"key": "historic:civilization", "type": "combo", "label": "Historic Civilization"},
|
||||
"historic/wreck/date_sunk": {"key": "wreck:date_sunk", "type": "text", "label": "Date Sunk"},
|
||||
"historic/wreck/visible_at_high_tide": {"key": "wreck:visible_at_high_tide", "type": "check", "label": "Visible At High Tide"},
|
||||
"historic/wreck/visible_at_low_tide": {"key": "wreck:visible_at_low_tide", "type": "check", "label": "Visible At Low Tide"},
|
||||
"hoops": {"key": "hoops", "type": "number", "minValue": 0, "label": "Hoops", "placeholder": "1, 2, 4..."},
|
||||
"horse_dressage": {"key": "sport", "type": "check", "label": "Dressage Riding", "strings": {"options": {"undefined": "No", "equestrian": "Yes"}}, "reference": {"key": "sport", "value": "equestrian"}},
|
||||
"horse_riding": {"key": "leisure", "type": "check", "label": "Horseback Riding", "strings": {"options": {"undefined": "No", "horse_riding": "Yes"}}, "reference": {"key": "leisure", "value": "horse_riding"}},
|
||||
"horse_scale": {"key": "horse_scale", "type": "combo", "label": "Horseback Riding Difficulty", "placeholder": "Difficult, Dangerous...", "strings": {"options": {"common": "Easy: No problems or difficulties. (default)", "demanding": "Use with caution: Uneven way, occasional difficult passages.", "difficult": "Difficult: Way narrow and exposed. May contain obstacles to step over and narrow passages.", "critical": "Borderline: Passable only for experienced riders and horses. Major obstacles. Bridges should be examined carefully.", "dangerous": "Dangerous: Passable only for very experienced riders and horses and only in good weather. Dismount.", "impossible": "Impassable: Way or bridge not passable for horses. Too narrow, insuffient support, obstacles like ladders. Danger of life."}}},
|
||||
"horse_stables": {"key": "amenity", "type": "check", "label": "Riding Stable", "strings": {"options": {"undefined": "No", "stables": "Yes"}}, "reference": {"key": "amenity", "value": "stables"}},
|
||||
"hot_water": {"key": "hot_water", "type": "check", "label": "Hot Water"},
|
||||
"iata": {"key": "iata", "type": "text", "label": "IATA Airport Code"},
|
||||
"icao": {"key": "icao", "type": "text", "label": "ICAO Airport Code"},
|
||||
"incline_steps": {"key": "incline", "type": "combo", "label": "Incline", "strings": {"options": {"up": "Up", "down": "Down"}}},
|
||||
"incline": {"key": "incline", "type": "combo", "label": "Incline"},
|
||||
"indoor_type": {"key": "indoor", "type": "typeCombo", "label": "Type"},
|
||||
"indoor": {"key": "indoor", "type": "check", "label": "Indoor"},
|
||||
"industrial": {"key": "industrial", "type": "combo", "label": "Type"},
|
||||
"informal": {"key": "informal", "type": "check", "label": "Informal"},
|
||||
"information": {"key": "information", "type": "typeCombo", "label": "Type"},
|
||||
"inscription": {"key": "inscription", "type": "textarea", "label": "Inscription"},
|
||||
"intermittent_yes": {"key": "intermittent", "type": "check", "label": "Intermittent", "default": "yes"},
|
||||
"intermittent": {"key": "intermittent", "type": "check", "label": "Intermittent"},
|
||||
"internet_access": {"key": "internet_access", "type": "combo", "label": "Internet Access", "strings": {"options": {"yes": "Yes", "no": "No", "wlan": "Wifi", "wired": "Wired", "terminal": "Terminal"}}, "terms": ["wifi", "wlan"]},
|
||||
"internet_access/fee": {"key": "internet_access:fee", "type": "check", "label": "Internet Access Fee", "prerequisiteTag": {"key": "internet_access", "valueNot": "no"}, "terms": ["wifi fee"]},
|
||||
"internet_access/ssid": {"key": "internet_access:ssid", "type": "text", "label": "Wifi Network Name", "prerequisiteTag": {"key": "internet_access", "valueNot": "no"}, "terms": ["ssid"]},
|
||||
"interval": {"key": "interval", "type": "text", "label": "Interval"},
|
||||
"junction_line": {"key": "junction", "type": "combo", "label": "Junction", "strings": {"options": {"roundabout": "Roundabout", "circular": "Traffic Circle", "jughandle": "Jughandle"}}},
|
||||
"junction/ref_oneway": {"key": "junction:ref", "type": "text", "label": "Junction Number", "prerequisiteTag": {"key": "oneway", "value": "yes"}},
|
||||
"kerb": {"key": "kerb", "type": "combo", "label": "Curb"},
|
||||
"kerb/height": {"key": "kerb:height", "type": "combo", "snake_case": false, "label": "Height"},
|
||||
"label": {"key": "label", "type": "textarea", "label": "Label"},
|
||||
"lamp_type": {"key": "lamp_type", "type": "combo", "label": "Type"},
|
||||
"landuse": {"key": "landuse", "type": "typeCombo", "label": "Type"},
|
||||
"lanes": {"key": "lanes", "type": "number", "minValue": 0, "label": "Lanes", "placeholder": "1, 2, 3..."},
|
||||
"language_multi": {"key": "language:", "type": "multiCombo", "label": "Languages"},
|
||||
"layer": {"key": "layer", "type": "number", "label": "Layer", "placeholder": "0"},
|
||||
"leaf_cycle_singular": {"key": "leaf_cycle", "type": "combo", "label": "Leaf Cycle", "strings": {"options": {"evergreen": "Evergreen", "deciduous": "Deciduous", "semi_evergreen": "Semi-Evergreen", "semi_deciduous": "Semi-Deciduous"}}},
|
||||
"leaf_cycle": {"key": "leaf_cycle", "type": "combo", "label": "Leaf Cycle", "strings": {"options": {"evergreen": "Evergreen", "deciduous": "Deciduous", "semi_evergreen": "Semi-Evergreen", "semi_deciduous": "Semi-Deciduous", "mixed": "Mixed"}}},
|
||||
"leaf_type_singular": {"key": "leaf_type", "type": "combo", "label": "Leaf Type", "strings": {"options": {"broadleaved": "Broadleaved", "needleleaved": "Needleleaved", "leafless": "Leafless"}}},
|
||||
"leaf_type": {"key": "leaf_type", "type": "combo", "label": "Leaf Type", "strings": {"options": {"broadleaved": "Broadleaved", "needleleaved": "Needleleaved", "mixed": "Mixed", "leafless": "Leafless"}}},
|
||||
"leisure": {"key": "leisure", "type": "typeCombo", "label": "Type"},
|
||||
"length": {"key": "length", "type": "number", "minValue": 0, "label": "Length (Meters)"},
|
||||
"level_semi": {"key": "level", "type": "semiCombo", "label": "Levels", "terms": ["building floors", "decks", "stories", "storeys", "storys"]},
|
||||
"level": {"key": "level", "type": "combo", "label": "Level", "terms": ["building floor", "deck", "storey", "story"], "prerequisiteTag": {"keyNot": "building"}},
|
||||
"liaison": {"key": "liaison", "type": "combo", "label": "Type"},
|
||||
"line_attachment": {"key": "line_attachment", "type": "combo", "label": "Line Attachment"},
|
||||
"lit": {"key": "lit", "type": "check", "label": "Lit", "terms": ["lamp", "lighting"]},
|
||||
"location_pool": {"key": "location", "type": "typeCombo", "label": "Location", "strings": {"options": {"outdoor": "Outdoor", "indoor": "Indoor", "roof": "Rooftop"}}},
|
||||
"location": {"key": "location", "type": "combo", "label": "Location"},
|
||||
"lock": {"key": "lock", "type": "check", "label": "Lock"},
|
||||
"lockable": {"key": "lockable", "type": "check", "label": "Lockable"},
|
||||
"man_made": {"key": "man_made", "type": "typeCombo", "label": "Type"},
|
||||
"manhole": {"key": "manhole", "type": "typeCombo", "label": "Type"},
|
||||
"manufacturer": {"key": "manufacturer", "type": "combo", "snake_case": false, "caseSensitive": true, "label": "Manufacturer"},
|
||||
"map_size": {"key": "map_size", "type": "typeCombo", "label": "Coverage"},
|
||||
"map_type": {"key": "map_type", "type": "typeCombo", "label": "Type"},
|
||||
"mapillary": {"key": "mapillary", "type": "identifier", "label": "Mapillary Image ID", "urlFormat": "https://mapillary.com/app/?focus=photo&pKey={value}", "pattern": "^[a-zA-Z0-9-_]{1,}$", "universal": true},
|
||||
"marker": {"key": "marker", "type": "typeCombo", "label": "Type"},
|
||||
"material": {"key": "material", "type": "combo", "label": "Material"},
|
||||
"max_age": {"key": "max_age", "type": "number", "minValue": 0, "label": "Maximum Age", "terms": ["upper age limit"]},
|
||||
"maxheight": {"key": "maxheight", "type": "combo", "label": "Max Height", "placeholder": "4, 4.5, 5, 14'0\", 14'6\", 15'0\"", "snake_case": false},
|
||||
"maxspeed": {"key": "maxspeed", "type": "maxspeed", "label": "Speed Limit", "placeholder": "40, 50, 60..."},
|
||||
"maxspeed/advisory": {"key": "maxspeed:advisory", "type": "maxspeed", "label": "Advisory Speed Limit", "placeholder": "40, 50, 60..."},
|
||||
"maxstay": {"key": "maxstay", "type": "combo", "label": "Max Stay", "options": ["15 min", "30 min", "45 min", "1 hr", "1.5 hr", "2 hr", "2.5 hr", "3 hr", "4 hr", "1 day", "2 day"], "snake_case": false},
|
||||
"maxweight_bridge": {"key": "maxweight", "type": "combo", "label": "Max Weight", "snake_case": false, "prerequisiteTag": {"key": "bridge", "valueNot": "no"}},
|
||||
"maxweight": {"key": "maxweight", "type": "combo", "label": "Max Weight", "snake_case": false},
|
||||
"memorial": {"key": "memorial", "type": "typeCombo", "label": "Type"},
|
||||
"microbrewery": {"key": "microbrewery", "type": "check", "label": "Microbrewery", "terms": ["brewpub", "craft beer"]},
|
||||
"min_age": {"key": "min_age", "type": "number", "minValue": 0, "label": "Minimum Age", "terms": ["lower age limit"]},
|
||||
"minspeed": {"key": "minspeed", "type": "maxspeed", "label": "Minimum Speed Limit", "placeholder": "20, 30, 40..."},
|
||||
"monitoring_multi": {"key": "monitoring:", "type": "multiCombo", "label": "Monitoring"},
|
||||
"mtb/scale": {"key": "mtb:scale", "type": "combo", "label": "Mountain Biking Difficulty", "placeholder": "0, 1, 2, 3...", "strings": {"options": {"0": "0: Solid gravel/packed earth, no obstacles, wide curves", "1": "1: Some loose surface, small obstacles, wide curves", "2": "2: Much loose surface, large obstacles, easy hairpins", "3": "3: Slippery surface, large obstacles, tight hairpins", "4": "4: Loose surface or boulders, dangerous hairpins", "5": "5: Maximum difficulty, boulder fields, landslides", "6": "6: Not rideable except by the very best mountain bikers"}}},
|
||||
"mtb/scale/imba": {"key": "mtb:scale:imba", "type": "combo", "label": "IMBA Trail Difficulty", "placeholder": "Easy, Medium, Difficult...", "strings": {"options": {"0": "Easiest (white circle)", "1": "Easy (green circle)", "2": "Medium (blue square)", "3": "Difficult (black diamond)", "4": "Extremely Difficult (double black diamond)"}}},
|
||||
"mtb/scale/uphill": {"key": "mtb:scale:uphill", "type": "combo", "label": "Mountain Biking Uphill Difficulty", "placeholder": "0, 1, 2, 3...", "strings": {"options": {"0": "0: Avg. incline <10%, gravel/packed earth, no obstacles", "1": "1: Avg. incline <15%, gravel/packed earth, few small objects", "2": "2: Avg. incline <20%, stable surface, fistsize rocks/roots", "3": "3: Avg. incline <25%, variable surface, fistsize rocks/branches", "4": "4: Avg. incline <30%, poor condition, big rocks/branches", "5": "5: Very steep, bike generally needs to be pushed or carried"}}},
|
||||
"museum": {"key": "museum", "type": "combo", "label": "Type"},
|
||||
"name": {"key": "name", "type": "localized", "label": "Name", "universal": true, "placeholder": "Common name (if any)", "terms": ["label", "title"]},
|
||||
"natural": {"key": "natural", "type": "typeCombo", "label": "Natural"},
|
||||
"network_bicycle": {"key": "network", "type": "combo", "label": "Network Class", "placeholder": "Local, Regional, National, International", "strings": {"options": {"lcn": "Local", "rcn": "Regional", "ncn": "National", "icn": "International"}}},
|
||||
"network_foot": {"key": "network", "type": "combo", "label": "Network Class", "placeholder": "Local, Regional, National, International", "strings": {"options": {"lwn": "Local", "rwn": "Regional", "nwn": "National", "iwn": "International"}}},
|
||||
"network_horse": {"key": "network", "type": "combo", "label": "Network Class", "placeholder": "Local, Regional, National, International", "strings": {"options": {"lhn": "Local", "rhn": "Regional", "nhn": "National", "ihn": "International"}}},
|
||||
"network_road": {"key": "network", "type": "networkCombo", "label": "Network"},
|
||||
"network": {"key": "network", "type": "text", "label": "Network"},
|
||||
"network/type": {"key": "network:type", "type": "combo", "label": "Network Type", "prerequisiteTag": {"key": "network"}},
|
||||
"not/name": {"key": "not:name", "type": "semiCombo", "label": "Incorrect Names", "terms": ["common mistake names", "wrong names"]},
|
||||
"note": {"key": "note", "type": "textarea", "universal": true, "icon": "note", "label": "Note", "terms": ["comment"]},
|
||||
"office": {"key": "office", "type": "typeCombo", "label": "Type"},
|
||||
"oneway_yes": {"key": "oneway", "type": "onewayCheck", "label": "One Way", "strings": {"options": {"undefined": "Assumed to be Yes", "yes": "Yes", "no": "No", "reversible": "Reversible", "alternating": "Alternating"}}},
|
||||
"oneway": {"key": "oneway", "type": "onewayCheck", "label": "One Way", "strings": {"options": {"undefined": "Assumed to be No", "yes": "Yes", "no": "No", "reversible": "Reversible", "alternating": "Alternating"}}},
|
||||
"oneway/bicycle": {"key": "oneway:bicycle", "type": "check", "label": "One Way (Bicycles)", "prerequisiteTag": {"key": "oneway"}},
|
||||
"openfire": {"key": "openfire", "type": "check", "label": "Open Fires Allowed"},
|
||||
"opening_date": {"key": "opening_date", "type": "text", "label": "Expected Opening Date"},
|
||||
"opening_hours": {"key": "opening_hours", "type": "combo", "label": "Hours", "placeholder": "Unknown", "snake_case": false},
|
||||
"operator": {"key": "operator", "type": "text", "label": "Operator"},
|
||||
"operator/type": {"key": "operator:type", "type": "combo", "label": "Operator Type", "prerequisiteTag": {"key": "operator"}},
|
||||
"outdoor_seating": {"key": "outdoor_seating", "type": "check", "label": "Outdoor Seating"},
|
||||
"par": {"key": "par", "type": "number", "minValue": 1, "label": "Par", "placeholder": "3, 4, 5..."},
|
||||
"park_ride": {"key": "park_ride", "type": "check", "label": "Park and Ride"},
|
||||
"parking": {"key": "parking", "type": "combo", "label": "Type", "strings": {"options": {"surface": "Surface", "multi-storey": "Multilevel", "underground": "Underground", "sheds": "Sheds", "carports": "Carports", "garage_boxes": "Garage Boxes", "lane": "Roadside Lane"}}},
|
||||
"payment_multi_fee": {"key": "payment:", "type": "multiCombo", "label": "Payment Types", "prerequisiteTag": {"key": "fee", "valueNot": "no"}},
|
||||
"payment_multi": {"key": "payment:", "type": "multiCombo", "label": "Payment Types"},
|
||||
"phases": {"key": "phases", "type": "number", "minValue": 1, "label": "Phases", "placeholder": "1, 2, 3..."},
|
||||
"phone": {"key": "phone", "type": "tel", "icon": "maki-telephone", "label": "Telephone", "placeholder": "+31 42 123 4567", "terms": ["phone number"]},
|
||||
"piste/difficulty_downhill": {"key": "piste:difficulty", "type": "combo", "label": "Difficulty", "placeholder": "Easy, Intermediate, Advanced...", "strings": {"options": {"novice": "Novice (instructional)", "easy": "Easy (green circle)", "intermediate": "Intermediate (blue square)", "advanced": "Advanced (black diamond)", "expert": "Expert (double black diamond)", "freeride": "Freeride (off-piste)", "extreme": "Extreme (climbing equipment required)"}}},
|
||||
"piste/difficulty_nordic": {"key": "piste:difficulty", "type": "combo", "label": "Difficulty", "placeholder": "Easy, Intermediate, Advanced...", "strings": {"options": {"novice": "Novice - Flat, no effort needed", "easy": "Easy - Soft hills, short steep section", "intermediate": "Intermediate - Steep section", "advanced": "Advanced - Narrow, steep or icy section, sharp turn", "expert": "Expert - Dangerous terrain around"}}},
|
||||
"piste/difficulty_skitour": {"key": "piste:difficulty", "type": "combo", "label": "Difficulty", "placeholder": "Easy, Intermediate, Advanced...", "strings": {"options": {"novice": "Novice - L: <30° incline", "easy": "Easy - WS: 30-35° incline", "intermediate": "Intermediate - ZS: 35-40° incline", "advanced": "Advanced - S: 40-45° incline", "expert": "Expert - SS: 45–50° incline", "freeride": "Freeride - AS: 50–55° incline", "extreme": "Extreme - EX: >55° incline"}}},
|
||||
"piste/difficulty": {"key": "piste:difficulty", "type": "combo", "label": "Difficulty", "placeholder": "Easy, Intermediate, Advanced...", "strings": {"options": {"novice": "Novice", "easy": "Easy", "intermediate": "Intermediate", "advanced": "Advanced", "expert": "Expert", "freeride": "Freeride", "extreme": "Extreme"}}},
|
||||
"piste/grooming_downhill": {"key": "piste:grooming", "type": "combo", "label": "Grooming", "strings": {"options": {"classic": "Classic", "mogul": "Mogul", "backcountry": "Backcountry - no grooming"}}},
|
||||
"piste/grooming_hike": {"key": "piste:grooming", "type": "combo", "label": "Grooming", "strings": {"options": {"classic": "Classic - Winter Hiking", "backcountry": "Backcountry - Snowshoeing"}}},
|
||||
"piste/grooming_nordic": {"key": "piste:grooming", "type": "combo", "label": "Grooming", "strings": {"options": {"classic": "Classic", "backcountry": "Backcountry, no grooming", "classic+skating": "Classic and Skating", "scooter": "Scooter/Snowmobile", "skating": "Skating"}}},
|
||||
"piste/grooming": {"key": "piste:grooming", "type": "combo", "label": "Grooming", "strings": {"options": {"classic": "Classic", "mogul": "Mogul", "backcountry": "Backcountry", "classic+skating": "Classic and Skating", "scooter": "Scooter/Snowmobile", "skating": "Skating"}}},
|
||||
"piste/type": {"key": "piste:type", "type": "typeCombo", "label": "Type", "strings": {"options": {"downhill": "Downhill", "nordic": "Nordic", "skitour": "Skitour", "sled": "Sled", "hike": "Hike", "sleigh": "Sleigh", "ice_skate": "Ice Skate", "snow_park": "Snow Park", "playground": "Playground", "connection": "Connection"}}},
|
||||
"place": {"key": "place", "type": "typeCombo", "label": "Type"},
|
||||
"plant": {"key": "plant", "type": "combo", "label": "Plant"},
|
||||
"plant/method": {"key": "plant:method", "type": "combo", "label": "Generation Method"},
|
||||
"plant/output/electricity": {"key": "plant:output:electricity", "type": "typeCombo", "label": "Power Output", "placeholder": "500 MW, 1000 MW, 2000 MW...", "snake_case": false},
|
||||
"plant/source": {"key": "plant:source", "type": "combo", "label": "Energy Source"},
|
||||
"playground": {"key": "playground", "type": "combo", "label": "Type"},
|
||||
"playground/theme": {"key": "playground:theme", "type": "combo", "label": "Theme"},
|
||||
"polling_station": {"key": "polling_station", "type": "check", "label": "Polling Place", "terms": ["voting place"]},
|
||||
"population": {"key": "population", "type": "text", "label": "Population"},
|
||||
"post": {"type": "address", "key": "post", "keys": ["post:block_number", "post:city", "post:block_number", "post:conscriptionnumber", "post:county", "post:country", "post:county", "post:district", "post:floor", "post:hamlet", "post:housename", "post:housenumber", "post:neighbourhood", "post:place", "post:postcode", "post:province", "post:quarter", "post:state", "post:street", "post:subdistrict", "post:suburb", "post:unit"], "label": "Delivery Address"},
|
||||
"power_supply": {"key": "power_supply", "type": "check", "label": "Power Supply"},
|
||||
"power": {"key": "power", "type": "typeCombo", "label": "Type"},
|
||||
"preschool": {"key": "preschool", "type": "check", "label": "Preschool"},
|
||||
"produce": {"key": "produce", "type": "semiCombo", "label": "Produce"},
|
||||
"product": {"key": "product", "type": "semiCombo", "label": "Products"},
|
||||
"public_bookcase/type": {"key": "public_bookcase:type", "type": "combo", "label": "Type"},
|
||||
"pump": {"key": "pump", "type": "combo", "label": "Pump", "strings": {"options": {"yes": "Yes", "manual": "Manual Hand Pump", "powered": "Machine-Powered Pump", "no": "None"}}},
|
||||
"railway": {"key": "railway", "type": "typeCombo", "label": "Type"},
|
||||
"railway/position": {"key": "railway:position", "type": "text", "placeholder": "Distance to one decimal (123.4)", "label": "Milestone Position"},
|
||||
"railway/signal/direction": {"key": "railway:signal:direction", "type": "combo", "label": "Direction Affected", "strings": {"options": {"forward": "Forward", "backward": "Backward", "both": "Both / All"}}},
|
||||
"rating": {"key": "rating", "type": "combo", "label": "Power Rating", "snake_case": false},
|
||||
"rcn_ref": {"key": "rcn_ref", "type": "text", "label": "Cycling Code"},
|
||||
"recycling_accepts": {"key": "recycling:", "type": "multiCombo", "label": "Accepts"},
|
||||
"recycling_type": {"key": "recycling_type", "type": "combo", "label": "Type", "placeholder": "Container, Center", "strings": {"options": {"container": "Container", "centre": "Center"}}},
|
||||
"ref_aeroway_gate": {"key": "ref", "type": "text", "label": "Gate Number"},
|
||||
"ref_golf_hole": {"key": "ref", "type": "text", "label": "Hole Number", "placeholder": "1-18"},
|
||||
"ref_highway_junction": {"key": "ref", "type": "text", "label": "Junction Number"},
|
||||
"ref_platform": {"key": "ref", "type": "text", "label": "Platform Number"},
|
||||
"ref_road_number": {"key": "ref", "type": "text", "label": "Road Number"},
|
||||
"ref_room_number": {"key": "ref", "type": "text", "label": "Room Number"},
|
||||
"ref_route": {"key": "ref", "type": "text", "label": "Route Number"},
|
||||
"ref_runway": {"key": "ref", "type": "text", "label": "Runway Number", "placeholder": "e.g. 01L/19R"},
|
||||
"ref_stop_position": {"key": "ref", "type": "text", "label": "Stop Number"},
|
||||
"ref_taxiway": {"key": "ref", "type": "text", "label": "Taxiway Name", "placeholder": "e.g. A5"},
|
||||
"ref": {"key": "ref", "type": "text", "label": "Reference Code"},
|
||||
"ref/isil": {"key": "ref:isil", "type": "text", "label": "ISIL Code"},
|
||||
"ref/vatin": {"key": "ref:vatin", "type": "identifier", "label": "VAT ID Number", "notCountryCodes": ["ao", "ai", "bm", "bt", "io", "vg", "bn", "ky", "km", "cu", "dj", "er", "fk", "gi", "gg", "hk", "iq", "ki", "xk", "kw", "lr", "ly", "mo", "mv", "mh", "fm", "ms", "mm", "nr", "kp", "om", "pw", "pn", "qa", "sh", "sm", "st", "sb", "so", "gs", "ss", "sr", "sz", "sy", "tl", "tc", "tv", "us", "va", "ye"], "terms": ["value added tax identification number", "vatin"]},
|
||||
"relation": {"key": "type", "type": "combo", "label": "Type"},
|
||||
"religion": {"key": "religion", "type": "combo", "label": "Religion"},
|
||||
"reservation": {"key": "reservation", "type": "combo", "label": "Reservations", "strings": {"options": {"yes": "Accepted", "no": "Not Accepted", "required": "Required", "recommended": "Recommended"}}},
|
||||
"residential": {"key": "residential", "type": "combo", "label": "Type"},
|
||||
"resort": {"key": "resort", "type": "combo", "label": "Type"},
|
||||
"resource": {"key": "resource", "type": "semiCombo", "label": "Resources"},
|
||||
"restriction": {"key": "restriction", "type": "combo", "label": "Type"},
|
||||
"restrictions": {"type": "restrictions", "geometry": "vertex", "icon": "iD-restrictions", "reference": {"rtype": "restriction"}, "label": "Turn Restrictions"},
|
||||
"roof/colour": {"key": "roof:colour", "type": "combo", "label": "Roof Color"},
|
||||
"room": {"key": "room", "type": "combo", "label": "Type"},
|
||||
"rooms": {"key": "rooms", "type": "number", "minValue": 0, "label": "Rooms"},
|
||||
"route_master": {"key": "route_master", "type": "combo", "label": "Type"},
|
||||
"route": {"key": "route", "type": "combo", "label": "Type"},
|
||||
"rwn_ref": {"key": "rwn_ref", "type": "text", "label": "Walking Code"},
|
||||
"sac_scale": {"key": "sac_scale", "type": "combo", "label": "Hiking Difficulty", "placeholder": "Mountain Hiking, Alpine Hiking...", "strings": {"options": {"hiking": "T1: Hiking", "mountain_hiking": "T2: Mountain Hiking", "demanding_mountain_hiking": "T3: Demanding Mountain Hiking", "alpine_hiking": "T4: Alpine Hiking", "demanding_alpine_hiking": "T5: Demanding Alpine Hiking", "difficult_alpine_hiking": "T6: Difficult Alpine Hiking"}}},
|
||||
"salt": {"key": "salt", "type": "check", "label": "Salt", "terms": ["saline", "salinated"]},
|
||||
"sanitary_dump_station": {"key": "sanitary_dump_station", "type": "check", "label": "Toilet Disposal"},
|
||||
"screen": {"key": "screen", "type": "number", "label": "Screens", "placeholder": "1, 4, 8…", "minValue": 0},
|
||||
"scuba_diving": {"key": "scuba_diving:", "type": "multiCombo", "label": "Services", "options": ["repair", "courses", "rental", "filling", "air_filling", "nitrox_filling", "trimix_filling", "oxygen_filling"]},
|
||||
"seamark/beacon_isolated_danger/shape": {"key": "seamark:beacon_isolated_danger:shape", "type": "combo", "label": "Shape"},
|
||||
"seamark/beacon_lateral/category": {"key": "seamark:beacon_lateral:category", "type": "combo", "label": "Category", "strings": {"options": {"port": "Port", "starboard": "Starboard", "waterway_left": "Waterway Left", "waterway_right": "Waterway Right", "danger_left": "Danger Left", "danger_right": "Danger Right"}}},
|
||||
"seamark/beacon_lateral/colour": {"key": "seamark:beacon_lateral:colour", "type": "combo", "label": "Color", "strings": {"options": {"red": "Red", "green": "Green", "grey": "Grey"}}},
|
||||
"seamark/beacon_lateral/shape": {"key": "seamark:beacon_lateral:shape", "type": "combo", "label": "Shape"},
|
||||
"seamark/beacon_lateral/system": {"key": "seamark:beacon_lateral:system", "type": "combo", "label": "System", "strings": {"options": {"iala-a": "IALA A", "iala-b": "IALA B", "cevni": "CEVNI", "other": "Other"}}},
|
||||
"seamark/buoy_lateral/category": {"key": "seamark:buoy_lateral:category", "type": "combo", "label": "Category", "strings": {"options": {"port": "Port", "starboard": "Starboard", "channel_left": "Channel Left", "channel_right": "Channel Right", "waterway_left": "Waterway Left", "waterway_right": "Waterway Right", "danger_left": "Danger Left", "danger_right": "Danger Right", "preferred_channel_port": "Preferred Channel Port", "preferred_channel_starboard": "Preferred Channel Starboard"}}},
|
||||
"seamark/buoy_lateral/colour": {"key": "seamark:buoy_lateral:colour", "type": "combo", "label": "Color", "strings": {"options": {"red": "Red", "green": "Green", "red;white;red;white": "Red-White-Red-White", "green;white;green;white": "Green-White-Green-White", "red;green;red": "Red-Green-Red", "green;red;green": "Green-Red-Green", "white": "White", "yellow": "Yellow"}}},
|
||||
"seamark/buoy_lateral/shape": {"key": "seamark:buoy_lateral:shape", "type": "combo", "label": "Shape"},
|
||||
"seamark/buoy_lateral/system": {"key": "seamark:buoy_lateral:system", "type": "combo", "label": "System", "strings": {"options": {"iala-a": "IALA A", "iala-b": "IALA B", "cevni": "CEVNI", "other": "Other"}}},
|
||||
"seamark/mooring/category": {"key": "seamark:mooring:category", "type": "combo", "label": "Category"},
|
||||
"seamark/type": {"key": "seamark:type", "type": "combo", "label": "Seamark", "terms": ["marine"]},
|
||||
"seamark/wreck/category": {"key": "seamark:wreck:category", "type": "combo", "label": "Category"},
|
||||
"seasonal": {"key": "seasonal", "type": "check", "label": "Seasonal"},
|
||||
"seats": {"key": "seats", "type": "number", "minValue": 0, "label": "Seats", "placeholder": "2, 4, 6..."},
|
||||
"second_hand": {"key": "second_hand", "type": "combo", "label": "Sells Used", "placeholder": "Yes, No, Only", "strings": {"options": {"yes": "Yes", "no": "No", "only": "Only"}}},
|
||||
"segregated": {"key": "segregated", "type": "check", "label": "Bicycle-Pedestrian Separation"},
|
||||
"self_service": {"key": "self_service", "type": "check", "label": "Self-Service"},
|
||||
"service_rail": {"key": "service", "type": "combo", "label": "Service Type", "strings": {"options": {"spur": "Spur", "yard": "Yard", "siding": "Siding", "crossover": "Crossover"}}},
|
||||
"service_times": {"key": "service_times", "type": "text", "label": "Service Times"},
|
||||
"service": {"key": "service", "type": "combo", "label": "Type", "options": ["parking_aisle", "driveway", "alley", "emergency_access", "drive-through"]},
|
||||
"service/bicycle": {"key": "service:bicycle:", "type": "multiCombo", "label": "Services"},
|
||||
"service/vehicle": {"key": "service:vehicle:", "type": "multiCombo", "label": "Services"},
|
||||
"shelter_type": {"key": "shelter_type", "type": "combo", "label": "Type"},
|
||||
"shelter": {"key": "shelter", "type": "check", "label": "Shelter"},
|
||||
"shop": {"key": "shop", "type": "typeCombo", "label": "Type"},
|
||||
"shower": {"key": "shower", "type": "check", "label": "Showers"},
|
||||
"siren/purpose": {"key": "siren:purpose", "type": "combo", "label": "Purpose"},
|
||||
"siren/type": {"key": "siren:type", "type": "combo", "label": "Type", "strings": {"options": {"pneumatic": "Pneumatic", "electronic": "Electronic", "other": "Other"}}},
|
||||
"site_type": {"key": "site_type", "type": "combo", "label": "Site Type"},
|
||||
"site": {"key": "site", "type": "combo", "label": "Type"},
|
||||
"smoking": {"key": "smoking", "type": "combo", "label": "Smoking", "placeholder": "No, Separated, Yes...", "strings": {"options": {"no": "No smoking anywhere", "separated": "In smoking areas, not physically isolated", "isolated": "In smoking areas, physically isolated", "outside": "Allowed outside", "yes": "Allowed everywhere", "dedicated": "Dedicated to smokers (e.g. smokers' club)"}}},
|
||||
"smoothness": {"key": "smoothness", "type": "combo", "label": "Smoothness", "placeholder": "Thin Rollers, Wheels, Off-Road...", "strings": {"options": {"excellent": "Thin Rollers: rollerblade, skateboard", "good": "Thin Wheels: racing bike", "intermediate": "Wheels: city bike, wheelchair, scooter", "bad": "Robust Wheels: trekking bike, car, rickshaw", "very_bad": "High Clearance: light duty off-road vehicle", "horrible": "Off-Road: heavy duty off-road vehicle", "very_horrible": "Specialized off-road: tractor, ATV", "impassable": "Impassable / No wheeled vehicle"}}},
|
||||
"sms": {"key": "sms", "type": "check", "label": "SMS"},
|
||||
"social_facility_for": {"key": "social_facility:for", "type": "combo", "label": "People Served"},
|
||||
"social_facility": {"key": "social_facility", "type": "combo", "label": "Type"},
|
||||
"source": {"key": "source", "type": "semiCombo", "icon": "source", "universal": true, "label": "Sources", "snake_case": false, "caseSensitive": true, "options": ["survey", "local knowledge", "gps", "aerial imagery", "streetlevel imagery"], "terms": ["reference"]},
|
||||
"species/wikidata": {"key": "species:wikidata", "keys": ["species:wikidata", "species:wikipedia"], "type": "wikidata", "label": "Species Wikidata"},
|
||||
"sport_ice": {"key": "sport", "type": "semiCombo", "label": "Sports", "options": ["ice_skating", "ice_hockey", "multi", "curling", "ice_stock"]},
|
||||
"sport_racing_motor": {"key": "sport", "type": "semiCombo", "label": "Sports", "options": ["motor", "karting", "motocross"]},
|
||||
"sport_racing_nonmotor": {"key": "sport", "type": "semiCombo", "label": "Sports", "options": ["bmx", "cycling", "dog_racing", "horse_racing", "running"]},
|
||||
"sport": {"key": "sport", "type": "semiCombo", "label": "Sports"},
|
||||
"stars": {"key": "stars", "type": "combo", "label": "Stars", "terms": ["rating"]},
|
||||
"start_date": {"key": "start_date", "type": "text", "universal": true, "label": "Start Date", "terms": ["inception"]},
|
||||
"step_count": {"key": "step_count", "type": "number", "minValue": 0, "label": "Number of Steps"},
|
||||
"stile": {"key": "stile", "type": "combo", "label": "Type"},
|
||||
"stop": {"key": "stop", "type": "combo", "label": "Stop Type", "strings": {"options": {"all": "All Ways", "minor": "Minor Road"}}},
|
||||
"street_cabinet": {"key": "street_cabinet", "type": "combo", "label": "Type"},
|
||||
"stroller": {"key": "stroller", "type": "radio", "strings": {"options": {"yes": "Yes", "limited": "Limited", "no": "No"}}, "label": "Stroller Access", "terms": ["baby carriage", "perambulator", "pram", "pushchair"]},
|
||||
"structure_waterway": {"type": "structureRadio", "keys": ["tunnel"], "label": "Structure", "placeholder": "Unknown", "strings": {"options": {"tunnel": "Tunnel"}}},
|
||||
"structure": {"type": "structureRadio", "keys": ["bridge", "tunnel", "embankment", "cutting", "ford"], "label": "Structure", "placeholder": "Unknown", "strings": {"options": {"bridge": "Bridge", "tunnel": "Tunnel", "embankment": "Embankment", "cutting": "Cutting", "ford": "Ford"}}},
|
||||
"studio": {"key": "studio", "type": "combo", "label": "Type"},
|
||||
"substance": {"key": "substance", "type": "combo", "label": "Substance"},
|
||||
"substation": {"key": "substation", "type": "typeCombo", "label": "Type"},
|
||||
"supervised": {"key": "supervised", "type": "check", "label": "Supervised", "terms": ["guarded", "manned"]},
|
||||
"support": {"key": "support", "type": "combo", "label": "Support"},
|
||||
"surface": {"key": "surface", "type": "combo", "label": "Surface"},
|
||||
"surveillance": {"key": "surveillance", "type": "combo", "label": "Surveillance Kind"},
|
||||
"surveillance/type": {"key": "surveillance:type", "type": "combo", "label": "Surveillance Type", "strings": {"options": {"camera": "Camera", "guard": "Guard", "ALPR": "Automatic License Plate Reader"}}},
|
||||
"surveillance/zone": {"key": "surveillance:zone", "type": "combo", "label": "Surveillance Zone"},
|
||||
"survey/date": {"key": "survey:date", "type": "text", "label": "Last Survey Date"},
|
||||
"swimming_pool": {"key": "swimming_pool", "type": "combo", "label": "Type"},
|
||||
"switch": {"key": "switch", "type": "combo", "label": "Type", "strings": {"options": {"mechanical": "Mechanical", "circuit_breaker": "Circuit Breaker", "disconnector": "Disconnector", "earthing": "Earthing"}}},
|
||||
"tactile_paving": {"key": "tactile_paving", "type": "check", "label": "Tactile Paving"},
|
||||
"takeaway": {"key": "takeaway", "type": "combo", "label": "Takeaway", "placeholder": "Yes, No, Takeaway Only...", "strings": {"options": {"yes": "Yes", "no": "No", "only": "Takeaway Only"}}, "terms": ["take out", "takeout"]},
|
||||
"target": {"key": "target", "type": "combo", "label": "Target"},
|
||||
"tidal": {"key": "tidal", "type": "check", "label": "Tidal"},
|
||||
"to": {"key": "to", "type": "text", "label": "To"},
|
||||
"toilets": {"key": "toilets", "type": "check", "label": "Toilets"},
|
||||
"toilets/disposal": {"key": "toilets:disposal", "type": "combo", "label": "Disposal", "strings": {"options": {"flush": "Flush", "pitlatrine": "Pit Latrine", "chemical": "Chemical", "bucket": "Bucket"}}},
|
||||
"toilets/handwashing": {"key": "toilets:handwashing", "type": "check", "label": "Handwashing"},
|
||||
"toilets/position": {"key": "toilets:position", "type": "semiCombo", "label": "Positions"},
|
||||
"toll": {"key": "toll", "type": "check", "label": "Toll"},
|
||||
"tomb": {"key": "tomb", "type": "typeCombo", "label": "Type"},
|
||||
"tourism": {"key": "tourism", "type": "typeCombo", "label": "Type"},
|
||||
"tower/construction": {"key": "tower:construction", "type": "combo", "label": "Construction", "placeholder": "Guyed, Lattice, Concealed, ..."},
|
||||
"tower/type": {"key": "tower:type", "type": "combo", "label": "Type"},
|
||||
"townhall/type": {"key": "townhall:type", "type": "combo", "label": "Type"},
|
||||
"tracktype": {"key": "tracktype", "type": "combo", "label": "Track Type", "placeholder": "Solid, Mostly Solid, Soft...", "strings": {"options": {"grade1": "Solid: paved or heavily compacted hardcore surface", "grade2": "Mostly Solid: gravel/rock with some soft material mixed in", "grade3": "Even mixture of hard and soft materials", "grade4": "Mostly Soft: soil/sand/grass with some hard material mixed in", "grade5": "Soft: soil/sand/grass"}}},
|
||||
"trade": {"key": "trade", "type": "typeCombo", "label": "Type"},
|
||||
"traffic_calming": {"key": "traffic_calming", "type": "typeCombo", "label": "Type"},
|
||||
"traffic_sign": {"key": "traffic_sign", "type": "typeCombo", "label": "Traffic Sign"},
|
||||
"traffic_sign/direction": {"key": "traffic_sign:direction", "type": "combo", "label": "Direction Affected", "strings": {"options": {"forward": "Forward", "backward": "Backward", "both": "Both / All"}}},
|
||||
"traffic_signals": {"key": "traffic_signals", "type": "combo", "label": "Type", "default": "signal"},
|
||||
"traffic_signals/direction": {"key": "traffic_signals:direction", "type": "combo", "label": "Direction Affected", "strings": {"options": {"forward": "Forward", "backward": "Backward", "both": "Both / All"}}},
|
||||
"trail_visibility": {"key": "trail_visibility", "type": "combo", "label": "Trail Visibility", "placeholder": "Excellent, Good, Bad...", "strings": {"options": {"excellent": "Excellent: unambiguous path or markers everywhere", "good": "Good: markers visible, sometimes require searching", "intermediate": "Intermediate: few markers, path mostly visible", "bad": "Bad: no markers, path sometimes invisible/pathless", "horrible": "Horrible: often pathless, some orientation skills required", "no": "No: pathless, excellent orientation skills required"}}},
|
||||
"transformer": {"key": "transformer", "type": "combo", "label": "Type", "strings": {"options": {"distribution": "Distribution", "generator": "Generator", "converter": "Converter", "traction": "Traction", "auto": "Autotransformer", "phase_angle_regulator": "Phase Angle Regulator", "auxiliary": "Auxiliary", "yes": "Unknown"}}},
|
||||
"trees": {"key": "trees", "type": "semiCombo", "label": "Trees"},
|
||||
"trench": {"key": "trench", "type": "combo", "label": "Type"},
|
||||
"trolley_wire": {"key": "trolley_wire", "type": "check", "label": "Overhead Trolley Wires"},
|
||||
"tunnel": {"key": "tunnel", "type": "typeCombo", "label": "Type", "placeholder": "Default"},
|
||||
"usage_rail": {"key": "usage", "type": "combo", "label": "Usage Type", "strings": {"options": {"main": "Main", "branch": "Branch", "industrial": "Industrial", "military": "Military", "test": "Test", "tourism": "Tourism"}}},
|
||||
"utility_semi": {"key": "utility", "type": "semiCombo", "label": "Utilities"},
|
||||
"utility": {"key": "utility", "type": "typeCombo", "label": "Utility"},
|
||||
"valve": {"key": "valve", "type": "combo", "label": "Type"},
|
||||
"vending": {"key": "vending", "type": "semiCombo", "label": "Types of Goods"},
|
||||
"video_calls": {"key": "video", "type": "check", "label": "Video Calls"},
|
||||
"visibility": {"key": "visibility", "type": "combo", "label": "Visibility", "strings": {"options": {"house": "Up to 5m (16ft)", "street": "5 to 20m (16 to 65ft)", "area": "Over 20m (65ft)"}}},
|
||||
"volcano/status": {"key": "volcano:status", "type": "combo", "label": "Volcano Status", "strings": {"options": {"active": "Active", "dormant": "Dormant", "extinct": "Extinct"}}},
|
||||
"volcano/type": {"key": "volcano:type", "type": "combo", "label": "Volcano Type", "strings": {"options": {"stratovolcano": "Stratovolcano", "shield": "Shield", "scoria": "Scoria"}}},
|
||||
"voltage_electrified": {"key": "voltage", "type": "combo", "label": "Voltage", "prerequisiteTag": {"key": "electrified", "valueNot": "no"}},
|
||||
"voltage": {"key": "voltage", "type": "combo", "label": "Voltage"},
|
||||
"voltage/primary": {"key": "voltage:primary", "type": "combo", "label": "Primary Voltage"},
|
||||
"voltage/secondary": {"key": "voltage:secondary", "type": "combo", "label": "Secondary Voltage"},
|
||||
"voltage/tertiary": {"key": "voltage:tertiary", "type": "combo", "label": "Tertiary Voltage"},
|
||||
"wall": {"key": "wall", "type": "combo", "label": "Type"},
|
||||
"waste": {"key": "waste", "type": "semiCombo", "label": "Waste"},
|
||||
"water_point": {"key": "water_point", "type": "check", "label": "Water Point"},
|
||||
"water_source": {"key": "water_source", "default": "main", "type": "combo", "label": "Water Source"},
|
||||
"water_volume": {"key": "water_volume", "type": "number", "label": "Water Reserve Volume (m³)", "snake_case": false},
|
||||
"water": {"key": "water", "type": "combo", "label": "Type"},
|
||||
"waterway": {"key": "waterway", "type": "typeCombo", "label": "Type"},
|
||||
"website": {"key": "website", "type": "url", "icon": "website", "placeholder": "https://example.com", "label": "Website", "terms": ["internet presence", "uri", "url", "webpage"]},
|
||||
"wetland": {"key": "wetland", "type": "combo", "label": "Type"},
|
||||
"wheelchair": {"key": "wheelchair", "type": "radio", "strings": {"options": {"yes": "Yes", "limited": "Limited", "no": "No"}}, "icon": "maki-wheelchair", "label": "Wheelchair Access", "terms": ["handicap access"]},
|
||||
"wholesale": {"key": "wholesale", "type": "typeCombo", "label": "Wholesale"},
|
||||
"width": {"key": "width", "type": "number", "minValue": 0, "label": "Width (Meters)"},
|
||||
"wikidata": {"key": "wikidata", "keys": ["wikidata", "wikipedia"], "type": "wikidata", "icon": "wikipedia", "universal": true, "label": "Wikidata"},
|
||||
"wikimedia_commons": {"key": "wikimedia_commons", "type": "identifier", "label": "Wikimedia Commons Page", "placeholder": "File:Example.jpg", "urlFormat": "https://commons.wikimedia.org/wiki/{value}", "pattern": "^(?:File|Category):.{1,}", "universal": true},
|
||||
"wikipedia": {"key": "wikipedia", "keys": ["wikipedia", "wikidata"], "type": "wikipedia", "icon": "wikipedia", "universal": true, "label": "Wikipedia"},
|
||||
"windings": {"key": "windings", "type": "number", "minValue": 1, "label": "Windings", "placeholder": "1, 2, 3..."},
|
||||
"windings/configuration": {"key": "windings:configuration", "type": "combo", "label": "Windings Configuration", "strings": {"options": {"star": "Star / Wye", "delta": "Delta", "open-delta": "Open Delta", "zigzag": "Zig Zag", "open": "Open", "scott": "Scott", "leblanc": "Leblanc"}}}
|
||||
}
|
||||
+6058
-6060
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
+24
-20
@@ -557,26 +557,30 @@ export function coreContext() {
|
||||
_features.init();
|
||||
_photos.init();
|
||||
|
||||
let presetsParameter = hash.presets;
|
||||
if (presetsParameter && presetsParameter.indexOf('://') !== -1) {
|
||||
// a URL of external presets file
|
||||
_presets.fromExternal(external, (externalPresets) => {
|
||||
context.presets = () => externalPresets; // default + external presets...
|
||||
osmSetAreaKeys(_presets.areaKeys());
|
||||
osmSetPointTags(_presets.pointTags());
|
||||
osmSetVertexTags(_presets.vertexTags());
|
||||
});
|
||||
} else {
|
||||
let addablePresetIDs;
|
||||
if (presetsParameter) {
|
||||
// a list of allowed preset IDs
|
||||
addablePresetIDs = presetsParameter.split(',');
|
||||
}
|
||||
_presets.init(addablePresetIDs);
|
||||
osmSetAreaKeys(_presets.areaKeys());
|
||||
osmSetPointTags(_presets.pointTags());
|
||||
osmSetVertexTags(_presets.vertexTags());
|
||||
}
|
||||
// let presetsParameter = hash.presets;
|
||||
// if (presetsParameter && presetsParameter.indexOf('://') !== -1) {
|
||||
// // a URL of external presets file
|
||||
// _presets.fromExternal(external, (externalPresets) => {
|
||||
// context.presets = () => externalPresets; // default + external presets...
|
||||
// osmSetAreaKeys(_presets.areaKeys());
|
||||
// osmSetPointTags(_presets.pointTags());
|
||||
// osmSetVertexTags(_presets.vertexTags());
|
||||
// });
|
||||
// } else {
|
||||
// let addablePresetIDs;
|
||||
// if (presetsParameter) {
|
||||
// // a list of allowed preset IDs
|
||||
// addablePresetIDs = presetsParameter.split(',');
|
||||
// }
|
||||
// _presets.init(addablePresetIDs);
|
||||
_presets.init()
|
||||
.then(() => {
|
||||
osmSetAreaKeys(_presets.areaKeys());
|
||||
osmSetPointTags(_presets.pointTags());
|
||||
osmSetVertexTags(_presets.vertexTags());
|
||||
});
|
||||
// }
|
||||
|
||||
return context;
|
||||
};
|
||||
|
||||
|
||||
+11
-7
@@ -6,7 +6,7 @@ import { data as _data } from '../../data'; // prebundled data
|
||||
// The coreData module fetches data from JSON files
|
||||
//
|
||||
export function coreData(context) {
|
||||
let _module = {};
|
||||
let _this = {};
|
||||
let _inflight = {};
|
||||
let _fileMap = {
|
||||
'address_formats': 'data/address_formats.min.json',
|
||||
@@ -16,10 +16,14 @@ export function coreData(context) {
|
||||
'intro_graph': 'data/intro_graph.min.json',
|
||||
'languages': 'data/languages.min.json',
|
||||
'locales': 'data/locales.min.json',
|
||||
'nsi_brands': 'https://cdn.jsdelivr.net/npm/name-suggestion-index@3/dist/brands.min.json',
|
||||
'nsi_filters': 'https://cdn.jsdelivr.net/npm/name-suggestion-index@3/dist/filters.min.json',
|
||||
'nsi_brands': 'https://cdn.jsdelivr.net/npm/name-suggestion-index@3/dist/brands.json',
|
||||
'nsi_filters': 'https://cdn.jsdelivr.net/npm/name-suggestion-index@3/dist/filters.json',
|
||||
'oci_features': 'https://cdn.jsdelivr.net/npm/osm-community-index@2/dist/features.min.json',
|
||||
'oci_resources': 'https://cdn.jsdelivr.net/npm/osm-community-index@2/dist/resources.min.json',
|
||||
'preset_categories': 'data/preset_categories.min.json',
|
||||
'preset_defaults': 'data/preset_defaults.min.json',
|
||||
'preset_fields': 'data/preset_fields.min.json',
|
||||
'preset_presets': 'data/preset_presets.min.json',
|
||||
'phone_formats': 'data/phone_formats.min.json',
|
||||
'shortcuts': 'data/shortcuts.min.json',
|
||||
'territory_languages': 'data/territory_languages.min.json',
|
||||
@@ -29,7 +33,7 @@ export function coreData(context) {
|
||||
|
||||
// Returns a Promise to fetch data
|
||||
// (resolved with the data if we have it already)
|
||||
_module.get = (which) => {
|
||||
_this.get = (which) => {
|
||||
if (_data[which]) {
|
||||
return Promise.resolve(_data[which]);
|
||||
}
|
||||
@@ -62,12 +66,12 @@ export function coreData(context) {
|
||||
|
||||
|
||||
// Accessor for the file map
|
||||
_module.fileMap = function(val) {
|
||||
_this.fileMap = function(val) {
|
||||
if (!arguments.length) return _fileMap;
|
||||
_fileMap = val;
|
||||
return _module;
|
||||
return _this;
|
||||
};
|
||||
|
||||
|
||||
return _module;
|
||||
return _this;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ export function operationDowngrade(selectedIDs, context) {
|
||||
var entity = graph.entity(entityID);
|
||||
var preset = context.presets().match(entity, graph);
|
||||
|
||||
if (preset.isFallback()) return null;
|
||||
if (!preset || preset.isFallback()) return null;
|
||||
|
||||
if (entity.type === 'node' &&
|
||||
preset.id !== 'address' &&
|
||||
|
||||
+27
-39
@@ -2,53 +2,41 @@ import { t } from '../util/locale';
|
||||
import { presetCollection } from './collection';
|
||||
|
||||
|
||||
export function presetCategory(id, category, all) {
|
||||
category = Object.assign({}, category); // shallow copy
|
||||
//
|
||||
// `presetCategory` builds a `presetCollection` of member presets,
|
||||
// decorated with some extra methods for searching and matching geometry
|
||||
//
|
||||
export function presetCategory(categoryID, category, all) {
|
||||
let _this = Object.assign({}, category); // shallow copy
|
||||
|
||||
category.id = id;
|
||||
_this.id = categoryID;
|
||||
|
||||
_this.members = presetCollection(
|
||||
category.members.map(presetID => all.item(presetID)).filter(Boolean)
|
||||
);
|
||||
|
||||
category.members = presetCollection(category.members.map(function(id) {
|
||||
return all.item(id);
|
||||
}));
|
||||
|
||||
|
||||
category.geometry = category.members.collection.reduce(function(geometries, preset) {
|
||||
for (var index in preset.geometry) {
|
||||
var geometry = preset.geometry[index];
|
||||
if (geometries.indexOf(geometry) === -1) {
|
||||
geometries.push(geometry);
|
||||
}
|
||||
_this.geometry = _this.members.collection
|
||||
.reduce((acc, preset) => {
|
||||
for (let i in preset.geometry) {
|
||||
const geometry = preset.geometry[i];
|
||||
if (acc.indexOf(geometry) === -1) {
|
||||
acc.push(geometry);
|
||||
}
|
||||
return geometries;
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
_this.matchGeometry = (geom) => _this.geometry.indexOf(geom) >= 0;
|
||||
|
||||
category.matchGeometry = function(geometry) {
|
||||
return category.geometry.indexOf(geometry) >= 0;
|
||||
};
|
||||
_this.matchAllGeometry = (geometries) => _this.members.collection
|
||||
.some(preset => preset.matchAllGeometry(geometries));
|
||||
|
||||
category.matchAllGeometry = function(geometries) {
|
||||
return category.members.collection.some(function(preset) {
|
||||
return preset.matchAllGeometry(geometries);
|
||||
});
|
||||
};
|
||||
_this.matchScore = () => -1;
|
||||
|
||||
_this.name = () => t(`presets.categories.${categoryID}.name`, { 'default': categoryID });
|
||||
|
||||
_this.terms = () => [];
|
||||
|
||||
|
||||
category.matchScore = function() {
|
||||
return -1;
|
||||
};
|
||||
|
||||
|
||||
category.name = function() {
|
||||
return t('presets.categories.' + id + '.name', {'default': id});
|
||||
};
|
||||
|
||||
|
||||
category.terms = function() {
|
||||
return [];
|
||||
};
|
||||
|
||||
|
||||
return category;
|
||||
return _this;
|
||||
}
|
||||
|
||||
+149
-179
@@ -1,188 +1,158 @@
|
||||
import { utilArrayUniq, utilEditDistance } from '../util';
|
||||
|
||||
|
||||
//
|
||||
// `presetCollection` is a wrapper around an `Array` of presets `collection`,
|
||||
// and decorated with some extra methods for searching and matching geometry
|
||||
//
|
||||
export function presetCollection(collection) {
|
||||
var maxSearchResults = 50;
|
||||
const MAXRESULTS = 50;
|
||||
let _this = {};
|
||||
let _memo = {};
|
||||
|
||||
var presets = {
|
||||
_this.collection = collection;
|
||||
|
||||
collection: collection,
|
||||
_this.item = (id) => {
|
||||
if (_memo[id]) return _memo[id];
|
||||
const found = _this.collection.find(d => d.id === id);
|
||||
if (found) _memo[id] = found;
|
||||
return found;
|
||||
};
|
||||
|
||||
_this.index = (id) => _this.collection.findIndex(d => d.id === id);
|
||||
|
||||
_this.matchGeometry = (geometry) => {
|
||||
return presetCollection(
|
||||
_this.collection.filter(d => d.matchGeometry(geometry))
|
||||
);
|
||||
};
|
||||
|
||||
_this.matchAllGeometry = (geometries) => {
|
||||
return presetCollection(
|
||||
_this.collection.filter(d => d && d.matchAllGeometry(geometries))
|
||||
);
|
||||
};
|
||||
|
||||
_this.matchAnyGeometry = (geometries) => {
|
||||
return presetCollection(
|
||||
_this.collection.filter(d => geometries.some(geom => d.matchGeometry(geom)))
|
||||
);
|
||||
};
|
||||
|
||||
_this.fallback = (geometry) => {
|
||||
let id = geometry;
|
||||
if (id === 'vertex') id = 'point';
|
||||
return _this.item(id);
|
||||
};
|
||||
|
||||
_this.search = (value, geometry, countryCode) => {
|
||||
if (!value) return _this;
|
||||
|
||||
value = value.toLowerCase().trim();
|
||||
|
||||
// match at name beginning or just after a space (e.g. "office" -> match "Law Office")
|
||||
function leading(a) {
|
||||
const index = a.indexOf(value);
|
||||
return index === 0 || a[index - 1] === ' ';
|
||||
}
|
||||
|
||||
// match at name beginning only
|
||||
function leadingStrict(a) {
|
||||
const index = a.indexOf(value);
|
||||
return index === 0;
|
||||
}
|
||||
|
||||
function sortNames(a, b) {
|
||||
let aCompare = (a.suggestion ? a.originalName : a.name()).toLowerCase();
|
||||
let bCompare = (b.suggestion ? b.originalName : b.name()).toLowerCase();
|
||||
|
||||
// priority if search string matches preset name exactly - #4325
|
||||
if (value === aCompare) return -1;
|
||||
if (value === bCompare) return 1;
|
||||
|
||||
// priority for higher matchScore
|
||||
let i = b.originalScore - a.originalScore;
|
||||
if (i !== 0) return i;
|
||||
|
||||
// priority if search string appears earlier in preset name
|
||||
i = aCompare.indexOf(value) - bCompare.indexOf(value);
|
||||
if (i !== 0) return i;
|
||||
|
||||
// priority for shorter preset names
|
||||
return aCompare.length - bCompare.length;
|
||||
}
|
||||
|
||||
let pool = _this.collection;
|
||||
if (countryCode) {
|
||||
pool = pool.filter(a => {
|
||||
if (a.countryCodes && a.countryCodes.indexOf(countryCode) === -1) return false;
|
||||
if (a.notCountryCodes && a.notCountryCodes.indexOf(countryCode) !== -1) return false;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
const searchable = pool.filter(a => a.searchable !== false && a.suggestion !== true);
|
||||
const suggestions = pool.filter(a => a.suggestion === true);
|
||||
|
||||
// matches value to preset.name
|
||||
const leading_name = searchable
|
||||
.filter(a => leading(a.name().toLowerCase()))
|
||||
.sort(sortNames);
|
||||
|
||||
// matches value to preset suggestion name (original name is unhyphenated)
|
||||
const leading_suggestions = suggestions
|
||||
.filter(a => leadingStrict(a.originalName.toLowerCase()))
|
||||
.sort(sortNames);
|
||||
|
||||
// matches value to preset.terms values
|
||||
const leading_terms = searchable
|
||||
.filter(a => (a.terms() || []).some(leading));
|
||||
|
||||
// matches value to preset.tags values
|
||||
const leading_tag_values = searchable
|
||||
.filter(a => Object.values(a.tags || {}).filter(val => val !== '*').some(leading));
|
||||
|
||||
// finds close matches to value in preset.name
|
||||
const similar_name = searchable
|
||||
.map(a => ({ preset: a, dist: utilEditDistance(value, a.name()) }))
|
||||
.filter(a => a.dist + Math.min(value.length - a.preset.name().length, 0) < 3)
|
||||
.sort((a, b) => a.dist - b.dist)
|
||||
.map(a => a.preset);
|
||||
|
||||
// finds close matches to value to preset suggestion name (original name is unhyphenated)
|
||||
const similar_suggestions = suggestions
|
||||
.map(a => ({ preset: a, dist: utilEditDistance(value, a.originalName.toLowerCase()) }))
|
||||
.filter(a => a.dist + Math.min(value.length - a.preset.originalName.length, 0) < 1)
|
||||
.sort((a, b) => a.dist - b.dist)
|
||||
.map(a => a.preset);
|
||||
|
||||
// finds close matches to value in preset.terms
|
||||
const similar_terms = searchable
|
||||
.filter(a => {
|
||||
return (a.terms() || []).some(b => {
|
||||
return utilEditDistance(value, b) + Math.min(value.length - b.length, 0) < 3;
|
||||
});
|
||||
});
|
||||
|
||||
let results = leading_name.concat(
|
||||
leading_suggestions,
|
||||
leading_terms,
|
||||
leading_tag_values,
|
||||
similar_name,
|
||||
similar_suggestions,
|
||||
similar_terms
|
||||
).slice(0, MAXRESULTS - 1);
|
||||
|
||||
if (geometry) {
|
||||
if (typeof geometry === 'string') {
|
||||
results.push(_this.fallback(geometry));
|
||||
} else {
|
||||
geometry.forEach(geom => results.push(_this.fallback(geom)));
|
||||
}
|
||||
}
|
||||
|
||||
return presetCollection(utilArrayUniq(results));
|
||||
};
|
||||
|
||||
|
||||
item: function(id) {
|
||||
return this.collection.find(function(d) {
|
||||
return d.id === id;
|
||||
});
|
||||
},
|
||||
|
||||
index: function(id) {
|
||||
return this.collection.findIndex(function(d) {
|
||||
return d.id === id;
|
||||
});
|
||||
},
|
||||
|
||||
matchGeometry: function(geometry) {
|
||||
return presetCollection(this.collection.filter(function(d) {
|
||||
return d.matchGeometry(geometry);
|
||||
}));
|
||||
},
|
||||
|
||||
matchAllGeometry: function(geometries) {
|
||||
return presetCollection(this.collection.filter(function(d) {
|
||||
if (!d) return false;
|
||||
return d.matchAllGeometry(geometries);
|
||||
}));
|
||||
},
|
||||
|
||||
matchAnyGeometry: function(geometries) {
|
||||
return presetCollection(this.collection.filter(function(d) {
|
||||
return geometries.some(function(geometry) {
|
||||
return d.matchGeometry(geometry);
|
||||
});
|
||||
}));
|
||||
},
|
||||
|
||||
fallback: function(geometry) {
|
||||
var id = geometry;
|
||||
if (id === 'vertex') id = 'point';
|
||||
return this.item(id);
|
||||
},
|
||||
|
||||
search: function(value, geometry, countryCode) {
|
||||
if (!value) return this;
|
||||
|
||||
value = value.toLowerCase().trim();
|
||||
|
||||
// match at name beginning or just after a space (e.g. "office" -> match "Law Office")
|
||||
function leading(a) {
|
||||
var index = a.indexOf(value);
|
||||
return index === 0 || a[index - 1] === ' ';
|
||||
}
|
||||
|
||||
// match at name beginning only
|
||||
function leadingStrict(a) {
|
||||
var index = a.indexOf(value);
|
||||
return index === 0;
|
||||
}
|
||||
|
||||
function sortNames(a, b) {
|
||||
var aCompare = (a.suggestion ? a.originalName : a.name()).toLowerCase();
|
||||
var bCompare = (b.suggestion ? b.originalName : b.name()).toLowerCase();
|
||||
|
||||
// priority if search string matches preset name exactly - #4325
|
||||
if (value === aCompare) return -1;
|
||||
if (value === bCompare) return 1;
|
||||
|
||||
// priority for higher matchScore
|
||||
var i = b.originalScore - a.originalScore;
|
||||
if (i !== 0) return i;
|
||||
|
||||
// priority if search string appears earlier in preset name
|
||||
i = aCompare.indexOf(value) - bCompare.indexOf(value);
|
||||
if (i !== 0) return i;
|
||||
|
||||
// priority for shorter preset names
|
||||
return aCompare.length - bCompare.length;
|
||||
}
|
||||
|
||||
var pool = this.collection;
|
||||
if (countryCode) {
|
||||
pool = pool.filter(function(a) {
|
||||
if (a.countryCodes && a.countryCodes.indexOf(countryCode) === -1) {
|
||||
return false;
|
||||
}
|
||||
if (a.notCountryCodes && a.notCountryCodes.indexOf(countryCode) !== -1) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
var searchable = pool.filter(function(a) {
|
||||
return a.searchable !== false && a.suggestion !== true;
|
||||
});
|
||||
var suggestions = pool.filter(function(a) {
|
||||
return a.suggestion === true;
|
||||
});
|
||||
|
||||
// matches value to preset.name
|
||||
var leading_name = searchable
|
||||
.filter(function(a) {
|
||||
return leading(a.name().toLowerCase());
|
||||
}).sort(sortNames);
|
||||
|
||||
// matches value to preset.terms values
|
||||
var leading_terms = searchable
|
||||
.filter(function(a) {
|
||||
return (a.terms() || []).some(leading);
|
||||
});
|
||||
|
||||
// matches value to preset.tags values
|
||||
var leading_tag_values = searchable
|
||||
.filter(function(a) {
|
||||
return Object.values(a.tags || {})
|
||||
.filter(function(val) { return val !== '*'; })
|
||||
.some(leading);
|
||||
});
|
||||
|
||||
var leading_suggestions = suggestions
|
||||
.filter(function(a) {
|
||||
return leadingStrict(a.originalName.toLowerCase());
|
||||
}).sort(sortNames);
|
||||
|
||||
// finds close matches to value in preset.name
|
||||
var similar_name = searchable
|
||||
.map(function(a) {
|
||||
return { preset: a, dist: utilEditDistance(value, a.name()) };
|
||||
}).filter(function(a) {
|
||||
return a.dist + Math.min(value.length - a.preset.name().length, 0) < 3;
|
||||
}).sort(function(a, b) {
|
||||
return a.dist - b.dist;
|
||||
}).map(function(a) {
|
||||
return a.preset;
|
||||
});
|
||||
|
||||
// finds close matches to value in preset.terms
|
||||
var similar_terms = searchable
|
||||
.filter(function(a) {
|
||||
return (a.terms() || []).some(function(b) {
|
||||
return utilEditDistance(value, b) + Math.min(value.length - b.length, 0) < 3;
|
||||
});
|
||||
});
|
||||
|
||||
var similar_suggestions = suggestions
|
||||
.map(function(a) {
|
||||
return { preset: a, dist: utilEditDistance(value, a.originalName.toLowerCase()) };
|
||||
}).filter(function(a) {
|
||||
return a.dist + Math.min(value.length - a.preset.originalName.length, 0) < 1;
|
||||
}).sort(function(a, b) {
|
||||
return a.dist - b.dist;
|
||||
}).map(function(a) {
|
||||
return a.preset;
|
||||
});
|
||||
|
||||
var results = leading_name.concat(
|
||||
leading_suggestions,
|
||||
leading_terms,
|
||||
leading_tag_values,
|
||||
similar_name,
|
||||
similar_suggestions,
|
||||
similar_terms
|
||||
).slice(0, maxSearchResults - 1);
|
||||
|
||||
if (geometry) {
|
||||
if (typeof geometry === 'string') {
|
||||
results.push(presets.fallback(geometry));
|
||||
} else {
|
||||
geometry.forEach(function(geom) {
|
||||
results.push(presets.fallback(geom));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return presetCollection(utilArrayUniq(results));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return presets;
|
||||
return _this;
|
||||
}
|
||||
|
||||
+27
-37
@@ -1,47 +1,37 @@
|
||||
import { t } from '../util/locale';
|
||||
import { utilSafeClassName } from '../util/util';
|
||||
|
||||
export function presetField(id, field) {
|
||||
field = Object.assign({}, field); // shallow copy
|
||||
|
||||
field.id = id;
|
||||
//
|
||||
// `presetField` decorates a given `field` Object
|
||||
// with some extra methods for searching and matching geometry
|
||||
//
|
||||
export function presetField(fieldID, field) {
|
||||
let _this = Object.assign({}, field); // shallow copy
|
||||
|
||||
// for use in classes, element ids, css selectors
|
||||
field.safeid = utilSafeClassName(id);
|
||||
_this.id = fieldID;
|
||||
|
||||
field.matchGeometry = function(geometry) {
|
||||
return !field.geometry || field.geometry === geometry;
|
||||
};
|
||||
// for use in classes, element ids, css selectors
|
||||
_this.safeid = utilSafeClassName(fieldID);
|
||||
|
||||
field.matchAllGeometry = function(geometries) {
|
||||
return !field.geometry || geometries.every(function(geometry) {
|
||||
return field.geometry.indexOf(geometry) !== -1;
|
||||
});
|
||||
};
|
||||
_this.matchGeometry = (geom) => !_this.geometry || _this.geometry === geom;
|
||||
|
||||
_this.matchAllGeometry = (geometries) => {
|
||||
return !_this.geometry || geometries.every(geom => _this.geometry.indexOf(geom) !== -1);
|
||||
};
|
||||
|
||||
_this.t = (scope, options) => t(`presets.fields.${fieldID}.${scope}`, options);
|
||||
|
||||
_this.label = () => _this.overrideLabel || _this.t('label', { 'default': fieldID });
|
||||
|
||||
const _placeholder = _this.placeholder;
|
||||
_this.placeholder = () => _this.t('placeholder', { 'default': _placeholder });
|
||||
|
||||
_this.originalTerms = (_this.terms || []).join();
|
||||
|
||||
_this.terms = () => _this.t('terms', { 'default': _this.originalTerms })
|
||||
.toLowerCase().trim().split(/\s*,+\s*/);
|
||||
|
||||
|
||||
field.t = function(scope, options) {
|
||||
return t('presets.fields.' + id + '.' + scope, options);
|
||||
};
|
||||
|
||||
|
||||
field.label = function() {
|
||||
return field.overrideLabel || field.t('label', {'default': id});
|
||||
};
|
||||
|
||||
|
||||
var placeholder = field.placeholder;
|
||||
field.placeholder = function() {
|
||||
return field.t('placeholder', {'default': placeholder});
|
||||
};
|
||||
|
||||
|
||||
field.originalTerms = (field.terms || []).join();
|
||||
|
||||
field.terms = function() {
|
||||
return field.t('terms', { 'default': field.originalTerms }).toLowerCase().trim().split(/\s*,+\s*/);
|
||||
};
|
||||
|
||||
|
||||
return field;
|
||||
return _this;
|
||||
}
|
||||
|
||||
+405
-404
@@ -1,7 +1,5 @@
|
||||
import { dispatch as d3_dispatch } from 'd3-dispatch';
|
||||
import { json as d3_json } from 'd3-fetch';
|
||||
|
||||
import { data } from '../../data/index';
|
||||
import { osmNodeGeometriesForTags } from '../osm/tags';
|
||||
import { presetCategory } from './category';
|
||||
import { presetCollection } from './collection';
|
||||
@@ -15,440 +13,443 @@ export { presetField };
|
||||
export { presetPreset };
|
||||
|
||||
|
||||
//
|
||||
// `presetIndex` wraps a `presetCollection`
|
||||
// with methods for loading new data and returning defaults
|
||||
//
|
||||
export function presetIndex(context) {
|
||||
// a presetCollection with methods for
|
||||
// loading new data and returning defaults
|
||||
const dispatch = d3_dispatch('recentsChange');
|
||||
const MAXRECENTS = 30;
|
||||
let _presetData;
|
||||
|
||||
var dispatch = d3_dispatch('recentsChange');
|
||||
// seed the preset lists with geometry fallbacks
|
||||
const POINT = presetPreset('point', { name: 'Point', tags: {}, geometry: ['point'], matchScore: 0.1 } );
|
||||
const VERTEX = presetPreset('vertex', { name: 'Point', tags: {}, geometry: ['vertex'], matchScore: 0.1 } );
|
||||
const LINE = presetPreset('line', { name: 'Line', tags: {}, geometry: ['line'], matchScore: 0.1 } );
|
||||
const AREA = presetPreset('area', { name: 'Area', tags: { area: 'yes' }, geometry: ['area'], matchScore: 0.1 } );
|
||||
const RELATION = presetPreset('relation', { name: 'Relation', tags: {}, geometry: ['relation'], matchScore: 0.1 } );
|
||||
|
||||
var all = presetCollection([]);
|
||||
var _defaults = { area: all, line: all, point: all, vertex: all, relation: all };
|
||||
var _fields = {};
|
||||
var _universal = [];
|
||||
var _recents;
|
||||
// presets that the user can add
|
||||
var _addablePresetIDs;
|
||||
let _this = presetCollection([POINT, VERTEX, LINE, AREA, RELATION]);
|
||||
let _presets = { point: POINT, vertex: VERTEX, line: LINE, area: AREA, relation: RELATION };
|
||||
|
||||
// Index of presets by (geometry, tag key).
|
||||
var _index = {
|
||||
point: {},
|
||||
vertex: {},
|
||||
line: {},
|
||||
area: {},
|
||||
relation: {}
|
||||
};
|
||||
let _defaults = {
|
||||
point: presetCollection([POINT]),
|
||||
vertex: presetCollection([VERTEX]),
|
||||
line: presetCollection([LINE]),
|
||||
area: presetCollection([AREA]),
|
||||
relation: presetCollection([RELATION])
|
||||
};
|
||||
|
||||
all.match = function(entity, resolver) {
|
||||
return resolver.transient(entity, 'presetMatch', function() {
|
||||
var geometry = entity.geometry(resolver);
|
||||
let _fields = {};
|
||||
let _categories = {};
|
||||
let _universal = [];
|
||||
let _recents;
|
||||
let _addablePresetIDs; // presets that the user can add
|
||||
|
||||
// Treat entities on addr:interpolation lines as points, not vertices - #3241
|
||||
if (geometry === 'vertex' && entity.isOnAddressLine(resolver)) {
|
||||
geometry = 'point';
|
||||
}
|
||||
|
||||
return all.matchTags(entity.tags, geometry);
|
||||
});
|
||||
};
|
||||
|
||||
all.matchTags = function(tags, geometry) {
|
||||
|
||||
var address;
|
||||
var geometryMatches = _index[geometry];
|
||||
var best = -1;
|
||||
var match;
|
||||
|
||||
for (var k in tags) {
|
||||
// If any part of an address is present,
|
||||
// allow fallback to "Address" preset - #4353
|
||||
if (/^addr:/.test(k) && geometryMatches['addr:*']) {
|
||||
address = geometryMatches['addr:*'][0];
|
||||
}
|
||||
|
||||
var keyMatches = geometryMatches[k];
|
||||
if (!keyMatches) continue;
|
||||
|
||||
for (var i = 0; i < keyMatches.length; i++) {
|
||||
var score = keyMatches[i].matchScore(tags);
|
||||
if (score > best) {
|
||||
best = score;
|
||||
match = keyMatches[i];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (address && (!match || match.isFallback())) {
|
||||
match = address;
|
||||
}
|
||||
return match || all.fallback(geometry);
|
||||
};
|
||||
|
||||
all.allowsVertex = function(entity, resolver) {
|
||||
if (entity.type !== 'node') return false;
|
||||
if (Object.keys(entity.tags).length === 0) return true;
|
||||
|
||||
return resolver.transient(entity, 'vertexMatch', function() {
|
||||
// address lines allow vertices to act as standalone points
|
||||
if (entity.isOnAddressLine(resolver)) return true;
|
||||
|
||||
var geometries = osmNodeGeometriesForTags(entity.tags);
|
||||
if (geometries.vertex) return true;
|
||||
if (geometries.point) return false;
|
||||
// allow vertices for unspecified points
|
||||
return true;
|
||||
});
|
||||
};
|
||||
// Index of presets by (geometry, tag key).
|
||||
let _geometryIndex = { point: {}, vertex: {}, line: {}, area: {}, relation: {} };
|
||||
|
||||
|
||||
// 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 = {};
|
||||
var ignore = ['barrier', 'highway', 'footway', 'railway', 'junction', 'type']; // probably a line..
|
||||
function ensurePresetData() {
|
||||
const data = context.data();
|
||||
return Promise.all([
|
||||
data.get('preset_categories'),
|
||||
data.get('preset_defaults'),
|
||||
data.get('preset_presets'),
|
||||
data.get('preset_fields')
|
||||
])
|
||||
.then(vals => {
|
||||
if (_presetData) return _presetData;
|
||||
|
||||
// ignore name-suggestion-index and deprecated presets
|
||||
var presets = all.collection.filter(function(p) {
|
||||
return !p.suggestion && !p.replacement;
|
||||
});
|
||||
|
||||
// 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) { // probably an area..
|
||||
areaKeys[key] = areaKeys[key] || {};
|
||||
}
|
||||
});
|
||||
|
||||
// blacklist
|
||||
presets.forEach(function(d) {
|
||||
for (var key in d.addTags) {
|
||||
// examine all addTags to get a better sense of what can be tagged on lines - #6800
|
||||
var value = d.addTags[key];
|
||||
if (key in areaKeys && // probably an area...
|
||||
d.geometry.indexOf('line') !== -1 && // but sometimes a line
|
||||
value !== '*') {
|
||||
areaKeys[key][value] = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return areaKeys;
|
||||
};
|
||||
|
||||
all.pointTags = function() {
|
||||
return all.collection.reduce(function(pointTags, d) {
|
||||
// ignore name-suggestion-index, deprecated, and generic presets
|
||||
if (d.suggestion || d.replacement || d.searchable === false) return pointTags;
|
||||
|
||||
// only care about the primary tag
|
||||
for (var key in d.tags) break;
|
||||
if (!key) return pointTags;
|
||||
|
||||
// if this can be a point
|
||||
if (d.geometry.indexOf('point') !== -1) {
|
||||
pointTags[key] = pointTags[key] || {};
|
||||
pointTags[key][d.tags[key]] = true;
|
||||
}
|
||||
return pointTags;
|
||||
}, {});
|
||||
};
|
||||
|
||||
all.vertexTags = function() {
|
||||
return all.collection.reduce(function(vertexTags, d) {
|
||||
// ignore name-suggestion-index, deprecated, and generic presets
|
||||
if (d.suggestion || d.replacement || d.searchable === false) return vertexTags;
|
||||
|
||||
// only care about the primary tag
|
||||
for (var key in d.tags) break;
|
||||
if (!key) return vertexTags;
|
||||
|
||||
// if this can be a vertex
|
||||
if (d.geometry.indexOf('vertex') !== -1) {
|
||||
vertexTags[key] = vertexTags[key] || {};
|
||||
vertexTags[key][d.tags[key]] = true;
|
||||
}
|
||||
return vertexTags;
|
||||
}, {});
|
||||
};
|
||||
|
||||
all.build = function(d, addable) {
|
||||
if (d.fields) {
|
||||
Object.keys(d.fields).forEach(function(id) {
|
||||
var f = d.fields[id];
|
||||
_fields[id] = presetField(id, f);
|
||||
if (f.universal) {
|
||||
_universal.push(_fields[id]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (d.presets) {
|
||||
var rawPresets = d.presets;
|
||||
Object.keys(d.presets).forEach(function(id) {
|
||||
var p = d.presets[id];
|
||||
var existing = all.index(id);
|
||||
var isAddable = typeof addable === 'function' ? addable(id, p) : addable;
|
||||
if (existing !== -1) {
|
||||
all.collection[existing] = presetPreset(id, p, _fields, isAddable, rawPresets);
|
||||
} else {
|
||||
all.collection.push(presetPreset(id, p, _fields, isAddable, rawPresets));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (d.categories) {
|
||||
Object.keys(d.categories).forEach(function(id) {
|
||||
var c = d.categories[id];
|
||||
var existing = all.index(id);
|
||||
if (existing !== -1) {
|
||||
all.collection[existing] = presetCategory(id, c, all);
|
||||
} else {
|
||||
all.collection.push(presetCategory(id, c, all));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var getItem = (all.item).bind(all);
|
||||
if (_addablePresetIDs) {
|
||||
['area', 'line', 'point', 'vertex', 'relation'].forEach(function(geometry) {
|
||||
_defaults[geometry] = presetCollection(_addablePresetIDs.map(getItem).filter(function(preset) {
|
||||
return preset.geometry.indexOf(geometry) !== -1;
|
||||
}));
|
||||
});
|
||||
} else if (d.defaults) {
|
||||
_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];
|
||||
var 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.init = function(addablePresetIDs) {
|
||||
all.collection = [];
|
||||
_recents = null;
|
||||
_addablePresetIDs = addablePresetIDs;
|
||||
_fields = {};
|
||||
_universal = [];
|
||||
_index = { point: {}, vertex: {}, line: {}, area: {}, relation: {} };
|
||||
|
||||
var addable = true;
|
||||
if (addablePresetIDs) {
|
||||
addable = function(presetID) {
|
||||
return addablePresetIDs.indexOf(presetID) !== -1;
|
||||
};
|
||||
}
|
||||
|
||||
return all.build(data.presets, addable);
|
||||
};
|
||||
|
||||
|
||||
all.reset = function() {
|
||||
all.collection = [];
|
||||
_defaults = { area: all, line: all, point: all, vertex: all, relation: all };
|
||||
_fields = {};
|
||||
_universal = [];
|
||||
_recents = null;
|
||||
|
||||
// Index of presets by (geometry, tag key).
|
||||
_index = {
|
||||
point: {},
|
||||
vertex: {},
|
||||
line: {},
|
||||
area: {},
|
||||
relation: {}
|
||||
return _presetData = {
|
||||
categories: vals[0],
|
||||
defaults: vals[1],
|
||||
presets: vals[2],
|
||||
fields: vals[3]
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
return all;
|
||||
};
|
||||
|
||||
all.fromExternal = function(external, done) {
|
||||
all.reset();
|
||||
d3_json(external)
|
||||
.then(function(externalPresets) {
|
||||
all.build(data.presets, false); // load the default presets as non-addable to start
|
||||
_this.init = () => {
|
||||
return ensurePresetData()
|
||||
.then(_this.merge);
|
||||
};
|
||||
|
||||
_addablePresetIDs = externalPresets.presets && Object.keys(externalPresets.presets);
|
||||
|
||||
all.build(externalPresets, true); // then load the external presets as addable
|
||||
})
|
||||
.catch(function() {
|
||||
all.init();
|
||||
})
|
||||
.finally(function() {
|
||||
done(all);
|
||||
});
|
||||
};
|
||||
|
||||
all.field = function(id) {
|
||||
return _fields[id];
|
||||
};
|
||||
|
||||
all.universal = function() {
|
||||
return _universal;
|
||||
};
|
||||
|
||||
all.defaults = function(geometry, n) {
|
||||
var rec = [];
|
||||
if (!context.inIntro()) {
|
||||
rec = all.recent().matchGeometry(geometry).collection.slice(0, 4);
|
||||
_this.merge = (d) => {
|
||||
// Merge Fields
|
||||
if (d.fields) {
|
||||
Object.keys(d.fields).forEach(fieldID => {
|
||||
const f = d.fields[fieldID];
|
||||
if (f) { // add or replace
|
||||
_fields[fieldID] = presetField(fieldID, f);
|
||||
} else { // remove
|
||||
delete _fields[fieldID];
|
||||
}
|
||||
var def = utilArrayUniq(rec.concat(_defaults[geometry].collection)).slice(0, n - 1);
|
||||
return presetCollection(utilArrayUniq(rec.concat(def).concat(all.fallback(geometry))));
|
||||
};
|
||||
|
||||
all.recent = function() {
|
||||
return presetCollection(utilArrayUniq(all.getRecents().map(function(d) {
|
||||
return d.preset;
|
||||
})));
|
||||
};
|
||||
|
||||
function RibbonItem(preset, geometry, source) {
|
||||
var item = {};
|
||||
item.preset = preset;
|
||||
item.geometry = geometry;
|
||||
item.source = source;
|
||||
|
||||
item.isRecent = function() {
|
||||
return item.source === 'recent';
|
||||
};
|
||||
item.matches = function(preset, geometry) {
|
||||
return item.preset.id === preset.id && item.geometry === geometry;
|
||||
};
|
||||
item.minified = function() {
|
||||
return {
|
||||
pID: item.preset.id,
|
||||
geom: item.geometry
|
||||
};
|
||||
};
|
||||
return item;
|
||||
});
|
||||
}
|
||||
|
||||
function ribbonItemForMinified(d, source) {
|
||||
if (d && d.pID && d.geom) {
|
||||
var preset = all.item(d.pID);
|
||||
if (!preset) return null;
|
||||
|
||||
var geom = d.geom;
|
||||
// treat point and vertex features as one geometry
|
||||
if (geom === 'vertex') geom = 'point';
|
||||
|
||||
// iD's presets could have changed since this was saved,
|
||||
// so make sure it's still valid.
|
||||
if (preset.matchGeometry(geom) || (geom === 'point' && preset.matchGeometry('vertex'))) {
|
||||
return RibbonItem(preset, geom, source);
|
||||
}
|
||||
// Merge Presets
|
||||
if (d.presets) {
|
||||
Object.keys(d.presets).forEach(presetID => {
|
||||
const p = d.presets[presetID];
|
||||
if (p) { // add or replace
|
||||
// _presets[presetID] = presetPreset(presetID, p, _fields, isAddable, _presets);
|
||||
_presets[presetID] = presetPreset(presetID, p, _fields, true);
|
||||
} else { // remove (but not if it's a fallback)
|
||||
const existing = _presets[presetID];
|
||||
if (existing && !existing.isFallback()) {
|
||||
delete _presets[presetID];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
function setRecents(items) {
|
||||
_recents = items;
|
||||
var minifiedItems = items.map(function(d) { return d.minified(); });
|
||||
context.storage('preset_recents', JSON.stringify(minifiedItems));
|
||||
|
||||
dispatch.call('recentsChange');
|
||||
// Merge Categories
|
||||
if (d.categories) {
|
||||
Object.keys(d.categories).forEach(categoryID => {
|
||||
const c = d.categories[categoryID];
|
||||
if (c) { // add or replace
|
||||
_categories[categoryID] = presetCategory(categoryID, c, _this);
|
||||
} else { // remove
|
||||
delete _categories[categoryID];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
all.getRecents = function() {
|
||||
if (!_recents) {
|
||||
// fetch from local storage
|
||||
_recents = (JSON.parse(context.storage('preset_recents')) || [])
|
||||
.reduce(function(output, d) {
|
||||
var item = ribbonItemForMinified(d, 'recent');
|
||||
if (item && item.preset.addable()) output.push(item);
|
||||
return output;
|
||||
}, []);
|
||||
// Merge Defaults
|
||||
if (d.defaults) {
|
||||
Object.keys(d.defaults).forEach(geometry => {
|
||||
const def = d.defaults[geometry];
|
||||
if (Array.isArray(def)) { // add or replace
|
||||
_defaults[geometry] = presetCollection(
|
||||
def.map(presetID => _presets[presetID]).filter(Boolean)
|
||||
);
|
||||
} else { // remove
|
||||
delete _defaults[geometry];
|
||||
}
|
||||
return _recents;
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
all.removeRecent = function(preset, geometry) {
|
||||
var item = all.recentMatching(preset, geometry);
|
||||
if (item) {
|
||||
var items = all.getRecents();
|
||||
items.splice(items.indexOf(item), 1);
|
||||
setRecents(items);
|
||||
// Rebuild universal fields
|
||||
_universal = Object.values(_fields).reduce((acc, field) => {
|
||||
if (field.universal) acc.push(field);
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
// Rebuild _this.collection
|
||||
_this.collection = Object.values(_presets).concat(Object.values(_categories));
|
||||
|
||||
// Rebuild geometry index
|
||||
_geometryIndex = { point: {}, vertex: {}, line: {}, area: {}, relation: {} };
|
||||
_this.collection.forEach(preset => {
|
||||
(preset.geometry || []).forEach(geometry => {
|
||||
let g = _geometryIndex[geometry];
|
||||
for (let key in preset.tags) {
|
||||
(g[key] = g[key] || []).push(preset);
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
all.recentMatching = function(preset, geometry) {
|
||||
geometry = all.fallback(geometry).id;
|
||||
var items = all.getRecents();
|
||||
for (var index in items) {
|
||||
if (items[index].matches(preset, geometry)) {
|
||||
return items[index];
|
||||
}
|
||||
return _this;
|
||||
};
|
||||
|
||||
|
||||
_this.match = (entity, resolver) => {
|
||||
return resolver.transient(entity, 'presetMatch', () => {
|
||||
let geometry = entity.geometry(resolver);
|
||||
// Treat entities on addr:interpolation lines as points, not vertices - #3241
|
||||
if (geometry === 'vertex' && entity.isOnAddressLine(resolver)) {
|
||||
geometry = 'point';
|
||||
}
|
||||
return _this.matchTags(entity.tags, geometry);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
_this.matchTags = (tags, geometry) => {
|
||||
const geometryMatches = _geometryIndex[geometry];
|
||||
let address;
|
||||
let best = -1;
|
||||
let match;
|
||||
|
||||
for (let k in tags) {
|
||||
// If any part of an address is present, allow fallback to "Address" preset - #4353
|
||||
if (/^addr:/.test(k) && geometryMatches['addr:*']) {
|
||||
address = geometryMatches['addr:*'][0];
|
||||
}
|
||||
|
||||
const keyMatches = geometryMatches[k];
|
||||
if (!keyMatches) continue;
|
||||
|
||||
for (let i = 0; i < keyMatches.length; i++) {
|
||||
const score = keyMatches[i].matchScore(tags);
|
||||
if (score > best) {
|
||||
best = score;
|
||||
match = keyMatches[i];
|
||||
}
|
||||
return null;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
all.moveItem = function(items, fromIndex, toIndex) {
|
||||
if (fromIndex === toIndex ||
|
||||
fromIndex < 0 || toIndex < 0 ||
|
||||
fromIndex >= items.length || toIndex >= items.length) return null;
|
||||
items.splice(toIndex, 0, items.splice(fromIndex, 1)[0]);
|
||||
return items;
|
||||
};
|
||||
if (address && (!match || match.isFallback())) {
|
||||
match = address;
|
||||
}
|
||||
return match || _this.fallback(geometry);
|
||||
};
|
||||
|
||||
all.moveRecent = function(item, beforeItem) {
|
||||
var recents = all.getRecents();
|
||||
var fromIndex = recents.indexOf(item);
|
||||
var toIndex = recents.indexOf(beforeItem);
|
||||
var items = all.moveItem(recents, fromIndex, toIndex);
|
||||
if (items) setRecents(items);
|
||||
};
|
||||
|
||||
all.setMostRecent = function(preset, geometry) {
|
||||
if (context.inIntro()) return;
|
||||
if (preset.searchable === false) return;
|
||||
_this.allowsVertex = (entity, resolver) => {
|
||||
if (entity.type !== 'node') return false;
|
||||
if (Object.keys(entity.tags).length === 0) return true;
|
||||
|
||||
geometry = all.fallback(geometry).id;
|
||||
return resolver.transient(entity, 'vertexMatch', () => {
|
||||
// address lines allow vertices to act as standalone points
|
||||
if (entity.isOnAddressLine(resolver)) return true;
|
||||
|
||||
var items = all.getRecents();
|
||||
var item = all.recentMatching(preset, geometry);
|
||||
if (item) {
|
||||
items.splice(items.indexOf(item), 1);
|
||||
} else {
|
||||
item = RibbonItem(preset, geometry, 'recent');
|
||||
const geometries = osmNodeGeometriesForTags(entity.tags);
|
||||
if (geometries.vertex) return true;
|
||||
if (geometries.point) return false;
|
||||
// allow vertices for unspecified points
|
||||
return true;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// 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 keeplist/discardlist 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 keeplist,
|
||||
// and the subkeys form the discardlist.
|
||||
_this.areaKeys = () => {
|
||||
// The ignore list is for keys that imply lines. (We always add `area=yes` for exceptions)
|
||||
const ignore = ['barrier', 'highway', 'footway', 'railway', 'junction', 'type'];
|
||||
let areaKeys = {};
|
||||
|
||||
// ignore name-suggestion-index and deprecated presets
|
||||
const presets = _this.collection.filter(p => !p.suggestion && !p.replacement);
|
||||
|
||||
// keeplist
|
||||
presets.forEach(p => {
|
||||
let key;
|
||||
for (key in p.tags) break; // pick the first tag
|
||||
if (!key) return;
|
||||
if (ignore.indexOf(key) !== -1) return;
|
||||
|
||||
if (p.geometry.indexOf('area') !== -1) { // probably an area..
|
||||
areaKeys[key] = areaKeys[key] || {};
|
||||
}
|
||||
});
|
||||
|
||||
// discardlist
|
||||
presets.forEach(p => {
|
||||
let key;
|
||||
for (key in p.addTags) {
|
||||
// examine all addTags to get a better sense of what can be tagged on lines - #6800
|
||||
const value = p.addTags[key];
|
||||
if (key in areaKeys && // probably an area...
|
||||
p.geometry.indexOf('line') !== -1 && // but sometimes a line
|
||||
value !== '*') {
|
||||
areaKeys[key][value] = true;
|
||||
}
|
||||
// allow 30 recents
|
||||
if (items.length === 30) {
|
||||
// remove the last recent (first in, first out)
|
||||
items.pop();
|
||||
}
|
||||
// prepend array
|
||||
items.unshift(item);
|
||||
setRecents(items);
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
return utilRebind(all, dispatch, 'on');
|
||||
return areaKeys;
|
||||
};
|
||||
|
||||
|
||||
_this.pointTags = () => {
|
||||
return _this.collection.reduce((pointTags, d) => {
|
||||
// ignore name-suggestion-index, deprecated, and generic presets
|
||||
if (d.suggestion || d.replacement || d.searchable === false) return pointTags;
|
||||
|
||||
// only care about the primary tag
|
||||
let key;
|
||||
for (key in d.tags) break; // pick the first tag
|
||||
if (!key) return pointTags;
|
||||
|
||||
// if this can be a point
|
||||
if (d.geometry.indexOf('point') !== -1) {
|
||||
pointTags[key] = pointTags[key] || {};
|
||||
pointTags[key][d.tags[key]] = true;
|
||||
}
|
||||
return pointTags;
|
||||
}, {});
|
||||
};
|
||||
|
||||
|
||||
_this.vertexTags = () => {
|
||||
return _this.collection.reduce((vertexTags, d) => {
|
||||
// ignore name-suggestion-index, deprecated, and generic presets
|
||||
if (d.suggestion || d.replacement || d.searchable === false) return vertexTags;
|
||||
|
||||
// only care about the primary tag
|
||||
let key;
|
||||
for (key in d.tags) break; // pick the first tag
|
||||
if (!key) return vertexTags;
|
||||
|
||||
// if this can be a vertex
|
||||
if (d.geometry.indexOf('vertex') !== -1) {
|
||||
vertexTags[key] = vertexTags[key] || {};
|
||||
vertexTags[key][d.tags[key]] = true;
|
||||
}
|
||||
return vertexTags;
|
||||
}, {});
|
||||
};
|
||||
|
||||
|
||||
_this.field = (id) => _fields[id];
|
||||
|
||||
_this.universal = () => _universal;
|
||||
|
||||
|
||||
_this.defaults = (geometry, n) => {
|
||||
let rec = [];
|
||||
if (!context.inIntro()) {
|
||||
rec = _this.recent().matchGeometry(geometry).collection.slice(0, 4);
|
||||
}
|
||||
const def = utilArrayUniq(rec.concat(_defaults[geometry].collection)).slice(0, n - 1);
|
||||
return presetCollection(
|
||||
utilArrayUniq(rec.concat(def).concat(_this.fallback(geometry)))
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
_this.recent = () => {
|
||||
return presetCollection(
|
||||
utilArrayUniq(_this.getRecents().map(d => d.preset))
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
function RibbonItem(preset, geometry, source) {
|
||||
let item = {};
|
||||
item.preset = preset;
|
||||
item.geometry = geometry;
|
||||
item.source = source;
|
||||
|
||||
item.isRecent = () => item.source === 'recent';
|
||||
item.matches = (preset, geometry) => item.preset.id === preset.id && item.geometry === geometry;
|
||||
item.minified = () => ({ pID: item.preset.id, geom: item.geometry });
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
|
||||
function ribbonItemForMinified(d, source) {
|
||||
if (d && d.pID && d.geom) {
|
||||
const preset = _this.item(d.pID);
|
||||
if (!preset) return null;
|
||||
|
||||
let geom = d.geom;
|
||||
// treat point and vertex features as one geometry
|
||||
if (geom === 'vertex') geom = 'point';
|
||||
|
||||
// iD's presets could have changed since this was saved,
|
||||
// so make sure it's still valid.
|
||||
if (preset.matchGeometry(geom) || (geom === 'point' && preset.matchGeometry('vertex'))) {
|
||||
return RibbonItem(preset, geom, source);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
function setRecents(items) {
|
||||
_recents = items;
|
||||
const minifiedItems = items.map(d => d.minified());
|
||||
context.storage('preset_recents', JSON.stringify(minifiedItems));
|
||||
dispatch.call('recentsChange');
|
||||
}
|
||||
|
||||
|
||||
_this.getRecents = () => {
|
||||
if (!_recents) {
|
||||
// fetch from local storage
|
||||
_recents = (JSON.parse(context.storage('preset_recents')) || [])
|
||||
.reduce((acc, d) => {
|
||||
let item = ribbonItemForMinified(d, 'recent');
|
||||
if (item && item.preset.addable()) acc.push(item);
|
||||
return acc;
|
||||
}, []);
|
||||
}
|
||||
return _recents;
|
||||
};
|
||||
|
||||
|
||||
_this.removeRecent = (preset, geometry) => {
|
||||
const item = _this.recentMatching(preset, geometry);
|
||||
if (item) {
|
||||
let items = _this.getRecents();
|
||||
items.splice(items.indexOf(item), 1);
|
||||
setRecents(items);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
_this.recentMatching = (preset, geometry) => {
|
||||
geometry = _this.fallback(geometry).id;
|
||||
const items = _this.getRecents();
|
||||
for (let i in items) {
|
||||
if (items[i].matches(preset, geometry)) {
|
||||
return items[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
_this.moveItem = (items, fromIndex, toIndex) => {
|
||||
if (fromIndex === toIndex ||
|
||||
fromIndex < 0 || toIndex < 0 ||
|
||||
fromIndex >= items.length || toIndex >= items.length
|
||||
) return null;
|
||||
|
||||
items.splice(toIndex, 0, items.splice(fromIndex, 1)[0]);
|
||||
return items;
|
||||
};
|
||||
|
||||
|
||||
_this.moveRecent = (item, beforeItem) => {
|
||||
const recents = _this.getRecents();
|
||||
const fromIndex = recents.indexOf(item);
|
||||
const toIndex = recents.indexOf(beforeItem);
|
||||
const items = _this.moveItem(recents, fromIndex, toIndex);
|
||||
if (items) setRecents(items);
|
||||
};
|
||||
|
||||
|
||||
_this.setMostRecent = (preset, geometry) => {
|
||||
if (context.inIntro()) return;
|
||||
if (preset.searchable === false) return;
|
||||
|
||||
geometry = _this.fallback(geometry).id;
|
||||
|
||||
let items = _this.getRecents();
|
||||
let item = _this.recentMatching(preset, geometry);
|
||||
if (item) {
|
||||
items.splice(items.indexOf(item), 1);
|
||||
} else {
|
||||
item = RibbonItem(preset, geometry, 'recent');
|
||||
}
|
||||
|
||||
// remove the last recent (first in, first out)
|
||||
while (items.length >= MAXRECENTS) {
|
||||
items.pop();
|
||||
}
|
||||
|
||||
// prepend array
|
||||
items.unshift(item);
|
||||
setRecents(items);
|
||||
};
|
||||
|
||||
|
||||
return utilRebind(_this, dispatch, 'on');
|
||||
}
|
||||
|
||||
+235
-257
@@ -4,291 +4,269 @@ import { utilArrayUniq, utilObjectOmit } from '../util';
|
||||
import { utilSafeClassName } from '../util/util';
|
||||
|
||||
|
||||
export function presetPreset(id, preset, fields, addable, rawPresets) {
|
||||
preset = Object.assign({}, preset); // shallow copy
|
||||
//
|
||||
// `presetPreset` decorates a given `preset` Object
|
||||
// with some extra methods for searching and matching geometry
|
||||
//
|
||||
export function presetPreset(presetID, preset, fields, addable, rawPresets) {
|
||||
let _this = Object.assign({}, preset); // shallow copy
|
||||
|
||||
preset.id = id;
|
||||
_this.id = presetID;
|
||||
|
||||
// for use in classes, element ids, css selectors
|
||||
preset.safeid = utilSafeClassName(id);
|
||||
// for use in classes, element ids, css selectors
|
||||
_this.safeid = utilSafeClassName(presetID);
|
||||
|
||||
preset.parentPresetID = function() {
|
||||
var endIndex = preset.id.lastIndexOf('/');
|
||||
if (endIndex < 0) return null;
|
||||
|
||||
return preset.id.substring(0, endIndex);
|
||||
};
|
||||
_this.parentPresetID = () => {
|
||||
const endIndex = _this.id.lastIndexOf('/');
|
||||
if (endIndex < 0) return null;
|
||||
return _this.id.substring(0, endIndex);
|
||||
};
|
||||
|
||||
|
||||
// For a preset without fields, use the fields of the parent preset.
|
||||
// Replace {preset} placeholders with the fields of the specified presets.
|
||||
function resolveFieldInheritance() {
|
||||
// For a preset without fields, use the fields of the parent _this.
|
||||
// Replace {preset} placeholders with the fields of the specified presets.
|
||||
function resolveFieldInheritance() {
|
||||
|
||||
// Skip `fields` for the keys which define the preset.
|
||||
// These are usually `typeCombo` fields like `shop=*`
|
||||
function shouldInheritFieldWithID(fieldID) {
|
||||
var f = fields[fieldID];
|
||||
if (f.key) {
|
||||
if (preset.tags[f.key] !== undefined &&
|
||||
// inherit anyway if multiple values are allowed or just a checkbox
|
||||
f.type !== 'multiCombo' && f.type !== 'semiCombo' && f.type !== 'check') {
|
||||
return false;
|
||||
}
|
||||
// Skip `fields` for the keys which define the _this.
|
||||
// These are usually `typeCombo` fields like `shop=*`
|
||||
function shouldInheritFieldWithID(fieldID) {
|
||||
const f = fields[fieldID];
|
||||
if (f.key) {
|
||||
if (_this.tags[f.key] !== undefined &&
|
||||
// inherit anyway if multiple values are allowed or just a checkbox
|
||||
f.type !== 'multiCombo' && f.type !== 'semiCombo' && f.type !== 'check'
|
||||
) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// returns an array of field IDs to inherit from the given presetID, if found
|
||||
function inheritedFieldIDs(presetID, prop) {
|
||||
if (!presetID) return null;
|
||||
|
||||
const inheritPreset = rawPresets[presetID];
|
||||
if (!inheritPreset) return null;
|
||||
|
||||
let inheritFieldIDs = inheritPreset[prop] || [];
|
||||
if (prop === 'fields') {
|
||||
inheritFieldIDs = inheritFieldIDs.filter(shouldInheritFieldWithID);
|
||||
}
|
||||
|
||||
return inheritFieldIDs;
|
||||
}
|
||||
|
||||
|
||||
['fields', 'moreFields'].forEach(prop => {
|
||||
let fieldIDs = [];
|
||||
if (preset[prop] && preset[prop].length) { // fields were defined
|
||||
preset[prop].forEach(fieldID => {
|
||||
const match = fieldID.match(/\{(.*)\}/);
|
||||
if (match !== null) { // presetID wrapped in braces {}
|
||||
const inheritIDs = inheritedFieldIDs(match[1], prop);
|
||||
if (inheritIDs !== null) {
|
||||
fieldIDs = fieldIDs.concat(inheritIDs);
|
||||
} else {
|
||||
/* eslint-disable no-console */
|
||||
console.log(`Cannot resolve presetID ${match[0]} found in ${_this.id} ${prop}`);
|
||||
/* eslint-enable no-console */
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// returns an array of field IDs to inherit from the given presetID, if found
|
||||
function inheritedFieldIDs(presetID, prop) {
|
||||
if (!presetID) return null;
|
||||
|
||||
var inheritPreset = rawPresets[presetID];
|
||||
if (!inheritPreset) return null;
|
||||
|
||||
var inheritFieldIDs = inheritPreset[prop] || [];
|
||||
|
||||
if (prop === 'fields') {
|
||||
inheritFieldIDs = inheritFieldIDs.filter(shouldInheritFieldWithID);
|
||||
}
|
||||
|
||||
return inheritFieldIDs;
|
||||
}
|
||||
|
||||
|
||||
['fields', 'moreFields'].forEach(function(prop) {
|
||||
var fieldIDs = [];
|
||||
if (preset[prop] && preset[prop].length) { // fields were defined
|
||||
preset[prop].forEach(function(fieldID) {
|
||||
var match = fieldID.match(/\{(.*)\}/);
|
||||
if (match !== null) { // presetID wrapped in braces {}
|
||||
var inheritIDs = inheritedFieldIDs(match[1], prop);
|
||||
if (inheritIDs !== null) {
|
||||
fieldIDs = fieldIDs.concat(inheritIDs);
|
||||
} else {
|
||||
/* eslint-disable no-console */
|
||||
console.log('Cannot resolve presetID ' + match[0] +
|
||||
' found in ' + preset.id + ' ' + prop);
|
||||
/* eslint-enable no-console */
|
||||
}
|
||||
} else {
|
||||
fieldIDs.push(fieldID); // no braces - just a normal field
|
||||
}
|
||||
});
|
||||
|
||||
} else { // no fields defined, so use the parent's if possible
|
||||
fieldIDs = inheritedFieldIDs(preset.parentPresetID(), prop);
|
||||
}
|
||||
// resolve duplicate fields
|
||||
fieldIDs = utilArrayUniq(fieldIDs);
|
||||
|
||||
// update this preset with the results
|
||||
preset[prop] = fieldIDs;
|
||||
|
||||
// update the raw object to allow for multiple levels of inheritance
|
||||
rawPresets[preset.id][prop] = fieldIDs;
|
||||
} else {
|
||||
fieldIDs.push(fieldID); // no braces - just a normal field
|
||||
}
|
||||
});
|
||||
|
||||
} else { // no fields defined, so use the parent's if possible
|
||||
fieldIDs = inheritedFieldIDs(_this.parentPresetID(), prop);
|
||||
}
|
||||
fieldIDs = utilArrayUniq(fieldIDs);
|
||||
preset[prop] = fieldIDs;
|
||||
rawPresets[_this.id][prop] = fieldIDs;
|
||||
});
|
||||
}
|
||||
|
||||
if (rawPresets) {
|
||||
resolveFieldInheritance();
|
||||
}
|
||||
|
||||
_this.fields = (_this.fields || []).map(getFields);
|
||||
_this.moreFields = (_this.moreFields || []).map(getFields);
|
||||
_this.geometry = (_this.geometry || []);
|
||||
|
||||
function getFields(f) {
|
||||
return fields[f];
|
||||
}
|
||||
|
||||
|
||||
_this.matchGeometry = (geom) => _this.geometry.indexOf(geom) >= 0;
|
||||
|
||||
_this.matchAllGeometry = (geoms) => geoms.every(_this.matchGeometry);
|
||||
|
||||
_this.originalScore = _this.matchScore || 1;
|
||||
|
||||
_this.matchScore = (entityTags) => {
|
||||
const tags = _this.tags;
|
||||
let seen = {};
|
||||
let score = 0;
|
||||
|
||||
// match on tags
|
||||
for (let k in tags) {
|
||||
seen[k] = true;
|
||||
if (entityTags[k] === tags[k]) {
|
||||
score += _this.originalScore;
|
||||
} else if (tags[k] === '*' && k in entityTags) {
|
||||
score += _this.originalScore / 2;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (rawPresets) {
|
||||
resolveFieldInheritance();
|
||||
// boost score for additional matches in addTags - #6802
|
||||
const addTags = _this.addTags;
|
||||
for (let k in addTags) {
|
||||
if (!seen[k] && entityTags[k] === addTags[k]) {
|
||||
score += _this.originalScore;
|
||||
}
|
||||
}
|
||||
|
||||
preset.fields = (preset.fields || []).map(getFields);
|
||||
preset.moreFields = (preset.moreFields || []).map(getFields);
|
||||
preset.geometry = (preset.geometry || []);
|
||||
return score;
|
||||
};
|
||||
|
||||
addable = addable || false;
|
||||
|
||||
function getFields(f) {
|
||||
return fields[f];
|
||||
let _textCache = {};
|
||||
_this.t = (scope, options) => {
|
||||
const textID = `presets.presets.${presetID}.${scope}`;
|
||||
if (_textCache[textID]) return _textCache[textID];
|
||||
return _textCache[textID] = t(textID, options);
|
||||
};
|
||||
|
||||
|
||||
_this.originalName = _this.name || '';
|
||||
|
||||
|
||||
_this.name = () => {
|
||||
if (_this.suggestion) {
|
||||
let path = presetID.split('/');
|
||||
path.pop(); // remove brand name
|
||||
// NOTE: insert an en-dash, not a hypen (to avoid conflict with fr - nl names in Brussels etc)
|
||||
return _this.originalName + ' – ' + t('presets.presets.' + path.join('/') + '.name');
|
||||
}
|
||||
return _this.t('name', { 'default': _this.originalName });
|
||||
};
|
||||
|
||||
|
||||
_this.originalTerms = (_this.terms || []).join();
|
||||
|
||||
_this.terms = () => _this.t('terms', { 'default': _this.originalTerms })
|
||||
.toLowerCase().trim().split(/\s*,+\s*/);
|
||||
|
||||
_this.isFallback = () => {
|
||||
const tagCount = Object.keys(_this.tags).length;
|
||||
return tagCount === 0 || (tagCount === 1 && _this.tags.hasOwnProperty('area'));
|
||||
};
|
||||
|
||||
|
||||
addable = addable || false;
|
||||
|
||||
_this.addable = function(val) {
|
||||
if (!arguments.length) return addable;
|
||||
addable = val;
|
||||
return addable;
|
||||
};
|
||||
|
||||
|
||||
const _reference = _this.reference || {};
|
||||
_this.reference = (geom) => {
|
||||
// Lookup documentation on Wikidata...
|
||||
const qid = _this.tags.wikidata || _this.tags['brand:wikidata'] || _this.tags['operator:wikidata'];
|
||||
if (qid) {
|
||||
return { qid: qid };
|
||||
}
|
||||
|
||||
// Lookup documentation on OSM Wikibase...
|
||||
let key = _reference.key || Object.keys(utilObjectOmit(_this.tags, 'name'))[0];
|
||||
let value = _reference.value || _this.tags[key];
|
||||
|
||||
preset.matchGeometry = function(geometry) {
|
||||
return preset.geometry.indexOf(geometry) >= 0;
|
||||
};
|
||||
if (geom === 'relation' && key === 'type') {
|
||||
if (value in _this.tags) {
|
||||
key = value;
|
||||
value = _this.tags[key];
|
||||
} else {
|
||||
return { rtype: value };
|
||||
}
|
||||
}
|
||||
|
||||
if (value === '*') {
|
||||
return { key: key };
|
||||
} else {
|
||||
return { key: key, value: value };
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
preset.matchAllGeometry = function(geometries) {
|
||||
return geometries.every(function(geometry) {
|
||||
return preset.geometry.indexOf(geometry) >= 0;
|
||||
});
|
||||
};
|
||||
_this.removeTags = _this.removeTags || _this.addTags || _this.tags || {};
|
||||
|
||||
_this.unsetTags = (tags, geometry) => {
|
||||
tags = utilObjectOmit(tags, Object.keys(_this.removeTags));
|
||||
|
||||
for (let f in _this.fields) {
|
||||
const field = _this.fields[f];
|
||||
if (field.matchGeometry(geometry) && field.default === tags[field.key]) {
|
||||
delete tags[field.key];
|
||||
}
|
||||
}
|
||||
|
||||
delete tags.area;
|
||||
return tags;
|
||||
};
|
||||
|
||||
|
||||
preset.originalScore = preset.matchScore || 1;
|
||||
_this.addTags = _this.addTags || _this.tags || {};
|
||||
|
||||
_this.setTags = (tags, geometry, skipFieldDefaults) => {
|
||||
const addTags = _this.addTags;
|
||||
tags = Object.assign({}, tags); // shallow copy
|
||||
|
||||
preset.matchScore = function(entityTags) {
|
||||
var tags = preset.tags;
|
||||
var seen = {};
|
||||
var score = 0;
|
||||
var k;
|
||||
for (let k in addTags) {
|
||||
if (addTags[k] === '*') {
|
||||
tags[k] = 'yes';
|
||||
} else {
|
||||
tags[k] = addTags[k];
|
||||
}
|
||||
}
|
||||
|
||||
// match on tags
|
||||
for (k in tags) {
|
||||
seen[k] = true;
|
||||
if (entityTags[k] === tags[k]) {
|
||||
score += preset.originalScore;
|
||||
} else if (tags[k] === '*' && k in entityTags) {
|
||||
score += preset.originalScore / 2;
|
||||
} else {
|
||||
return -1;
|
||||
// Add area=yes if necessary.
|
||||
// This is necessary if the geometry is already an area (e.g. user drew an area) AND any of:
|
||||
// 1. chosen preset could be either an area or a line (`barrier=city_wall`)
|
||||
// 2. chosen preset doesn't have a key in osmAreaKeys (`railway=station`)
|
||||
if (!addTags.hasOwnProperty('area')) {
|
||||
delete tags.area;
|
||||
if (geometry === 'area') {
|
||||
let needsAreaTag = true;
|
||||
if (_this.geometry.indexOf('line') === -1) {
|
||||
for (let k in addTags) {
|
||||
if (k in osmAreaKeys) {
|
||||
needsAreaTag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// boost score for additional matches in addTags - #6802
|
||||
var addTags = preset.addTags;
|
||||
for (k in addTags) {
|
||||
if (!seen[k] && entityTags[k] === addTags[k]) {
|
||||
score += preset.originalScore;
|
||||
}
|
||||
if (needsAreaTag) {
|
||||
tags.area = 'yes';
|
||||
}
|
||||
|
||||
return score;
|
||||
};
|
||||
|
||||
|
||||
var _textCache = {};
|
||||
|
||||
preset.t = function(scope, options) {
|
||||
var textID = 'presets.presets.' + id + '.' + scope;
|
||||
|
||||
if (_textCache[textID]) return _textCache[textID];
|
||||
|
||||
var text = t(textID, options);
|
||||
_textCache[textID] = text;
|
||||
return text;
|
||||
};
|
||||
|
||||
|
||||
preset.originalName = preset.name || '';
|
||||
|
||||
|
||||
preset.name = function() {
|
||||
if (preset.suggestion) {
|
||||
var path = id.split('/');
|
||||
path.pop(); // remove brand name
|
||||
// NOTE: insert an en-dash, not a hypen (to avoid conflict with fr - nl names in Brussels etc)
|
||||
return preset.originalName + ' – ' + t('presets.presets.' + path.join('/') + '.name');
|
||||
}
|
||||
}
|
||||
if (geometry && !skipFieldDefaults) {
|
||||
for (let f in _this.fields) {
|
||||
const field = _this.fields[f];
|
||||
if (field.matchGeometry(geometry) && field.key && !tags[field.key] && field.default) {
|
||||
tags[field.key] = field.default;
|
||||
}
|
||||
return preset.t('name', { 'default': preset.originalName });
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return tags;
|
||||
};
|
||||
|
||||
|
||||
preset.originalTerms = (preset.terms || []).join();
|
||||
|
||||
|
||||
preset.terms = function() {
|
||||
return preset.t('terms', { 'default': preset.originalTerms }).toLowerCase().trim().split(/\s*,+\s*/);
|
||||
};
|
||||
|
||||
|
||||
preset.isFallback = function() {
|
||||
var tagCount = Object.keys(preset.tags).length;
|
||||
return tagCount === 0 || (tagCount === 1 && preset.tags.hasOwnProperty('area'));
|
||||
};
|
||||
|
||||
preset.addable = function(val) {
|
||||
if (!arguments.length) return addable;
|
||||
addable = val;
|
||||
return addable;
|
||||
};
|
||||
|
||||
|
||||
var reference = preset.reference || {};
|
||||
preset.reference = function(geometry) {
|
||||
// Lookup documentation on Wikidata...
|
||||
var qid = preset.tags.wikidata || preset.tags['brand:wikidata'] || preset.tags['operator:wikidata'];
|
||||
if (qid) {
|
||||
return { qid: qid };
|
||||
}
|
||||
|
||||
// Lookup documentation on OSM Wikibase...
|
||||
var key = reference.key || Object.keys(utilObjectOmit(preset.tags, 'name'))[0];
|
||||
var value = reference.value || preset.tags[key];
|
||||
|
||||
if (geometry === 'relation' && key === 'type') {
|
||||
if (value in preset.tags) {
|
||||
key = value;
|
||||
value = preset.tags[key];
|
||||
} else {
|
||||
return { rtype: value };
|
||||
}
|
||||
}
|
||||
|
||||
if (value === '*') {
|
||||
return { key: key };
|
||||
} else {
|
||||
return { key: key, value: value };
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
preset.removeTags = preset.removeTags || preset.addTags || preset.tags || {};
|
||||
preset.unsetTags = function(tags, geometry) {
|
||||
tags = utilObjectOmit(tags, Object.keys(preset.removeTags));
|
||||
|
||||
for (var f in preset.fields) {
|
||||
var field = preset.fields[f];
|
||||
if (field.matchGeometry(geometry) && field.default === tags[field.key]) {
|
||||
delete tags[field.key];
|
||||
}
|
||||
}
|
||||
|
||||
delete tags.area;
|
||||
return tags;
|
||||
};
|
||||
|
||||
|
||||
preset.addTags = preset.addTags || preset.tags || {};
|
||||
preset.setTags = function(tags, geometry, skipFieldDefaults) {
|
||||
var addTags = preset.addTags;
|
||||
var k;
|
||||
|
||||
tags = Object.assign({}, tags); // shallow copy
|
||||
|
||||
for (k in addTags) {
|
||||
if (addTags[k] === '*') {
|
||||
tags[k] = 'yes';
|
||||
} else {
|
||||
tags[k] = addTags[k];
|
||||
}
|
||||
}
|
||||
|
||||
// Add area=yes if necessary.
|
||||
// This is necessary if the geometry is already an area (e.g. user drew an area) AND any of:
|
||||
// 1. chosen preset could be either an area or a line (`barrier=city_wall`)
|
||||
// 2. chosen preset doesn't have a key in osmAreaKeys (`railway=station`)
|
||||
if (!addTags.hasOwnProperty('area')) {
|
||||
delete tags.area;
|
||||
if (geometry === 'area') {
|
||||
var needsAreaTag = true;
|
||||
if (preset.geometry.indexOf('line') === -1) {
|
||||
for (k in addTags) {
|
||||
if (k in osmAreaKeys) {
|
||||
needsAreaTag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (needsAreaTag) {
|
||||
tags.area = 'yes';
|
||||
}
|
||||
}
|
||||
}
|
||||
if (geometry && !skipFieldDefaults) {
|
||||
for (var f in preset.fields) {
|
||||
var field = preset.fields[f];
|
||||
if (field.matchGeometry(geometry) && field.key && !tags[field.key] && field.default) {
|
||||
tags[field.key] = field.default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tags;
|
||||
};
|
||||
|
||||
|
||||
return preset;
|
||||
return _this;
|
||||
}
|
||||
|
||||
@@ -22,8 +22,9 @@ export function validationMismatchedGeometry(context) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (context.presets().matchTags(tagSuggestingArea, 'line') ===
|
||||
context.presets().matchTags(tagSuggestingArea, 'area')) {
|
||||
var asLine = context.presets().matchTags(tagSuggestingArea, 'line');
|
||||
var asArea = context.presets().matchTags(tagSuggestingArea, 'area');
|
||||
if (asLine && asArea && (asLine === asArea)) {
|
||||
// these tags also allow lines and making this an area wouldn't matter
|
||||
return null;
|
||||
}
|
||||
@@ -31,6 +32,7 @@ export function validationMismatchedGeometry(context) {
|
||||
return tagSuggestingArea;
|
||||
}
|
||||
|
||||
|
||||
function makeConnectEndpointsFixOnClick(way, graph) {
|
||||
// must have at least three nodes to close this automatically
|
||||
if (way.nodes.length < 3) return null;
|
||||
|
||||
@@ -56,6 +56,7 @@ export function validationOutdatedTags(context) {
|
||||
const oldTags = Object.assign({}, entity.tags); // shallow copy
|
||||
let preset = context.presets().match(entity, graph);
|
||||
let subtype = 'deprecated_tags';
|
||||
if (!preset) return [];
|
||||
|
||||
// upgrade preset..
|
||||
if (preset.replacement) {
|
||||
|
||||
@@ -105,18 +105,19 @@ function buildData() {
|
||||
|
||||
// Save individual data files
|
||||
let tasks = [
|
||||
writeFileProm('data/presets/categories.json', prettyStringify({ categories: categories }) ),
|
||||
writeFileProm('data/presets/fields.json', prettyStringify({ fields: fields }, { maxLength: 9999 }) ),
|
||||
writeFileProm('data/presets/presets.json', prettyStringify({ presets: presets }, { maxLength: 9999 }) ),
|
||||
writeFileProm('data/presets/categories.json', prettyStringify(categories, { maxLength: 9999 }) ),
|
||||
writeFileProm('data/presets/fields.json', prettyStringify(fields, { maxLength: 9999 }) ),
|
||||
writeFileProm('data/presets/presets.json', prettyStringify(presets, { maxLength: 9999 }) ),
|
||||
writeFileProm('data/presets.yaml', translationsToYAML(translations) ),
|
||||
writeFileProm('data/taginfo.json', prettyStringify(taginfo, { maxLength: 9999 }) ),
|
||||
writeFileProm('data/territory_languages.json', prettyStringify(territoryLanguages, { maxLength: 9999 }) ),
|
||||
writeEnJson(tstrings),
|
||||
writeFaIcons(faIcons),
|
||||
writeTnpIcons(tnpIcons),
|
||||
minifyJSON('data/presets/categories.json', 'dist/data/categories.min.json'),
|
||||
minifyJSON('data/presets/fields.json', 'dist/data/fields.min.json'),
|
||||
minifyJSON('data/presets/presets.json', 'dist/data/presets.min.json'),
|
||||
minifyJSON('data/presets/categories.json', 'dist/data/preset_categories.min.json'),
|
||||
minifyJSON('data/presets/defaults.json', 'dist/data/preset_defaults.min.json'),
|
||||
minifyJSON('data/presets/fields.json', 'dist/data/preset_fields.min.json'),
|
||||
minifyJSON('data/presets/presets.json', 'dist/data/preset_presets.min.json'),
|
||||
minifyJSON('data/address_formats.json', 'dist/data/address_formats.min.json'),
|
||||
minifyJSON('data/deprecated.json', 'dist/data/deprecated.min.json'),
|
||||
minifyJSON('data/discarded.json', 'dist/data/discarded.min.json'),
|
||||
@@ -747,8 +748,8 @@ function validatePresetFields(presets, fields) {
|
||||
}
|
||||
|
||||
function validateDefaults(defaults, categories, presets) {
|
||||
Object.keys(defaults.defaults).forEach(name => {
|
||||
let members = defaults.defaults[name];
|
||||
Object.keys(defaults).forEach(name => {
|
||||
const members = defaults[name];
|
||||
members.forEach(id => {
|
||||
if (!presets[id] && !categories[id]) {
|
||||
console.error(`Unknown category or preset: ${id} in default ${name}`);
|
||||
|
||||
@@ -1 +1 @@
|
||||
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="shapes" class="svg-inline--fa fa-shapes fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M512 320v160c0 17.67-14.33 32-32 32H320c-17.67 0-32-14.33-32-32V320c0-17.67 14.33-32 32-32h160c17.67 0 32 14.33 32 32zm-384-64C57.31 256 0 313.31 0 384s57.31 128 128 128 128-57.31 128-128-57.31-128-128-128zm351.03-32c25.34 0 41.18-26.67 28.51-48L412.51 16c-12.67-21.33-44.35-21.33-57.02 0l-95.03 160c-12.67 21.33 3.17 48 28.51 48h190.06z"></path></svg>
|
||||
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="shapes" class="svg-inline--fa fa-shapes fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M128,256A128,128,0,1,0,256,384,128,128,0,0,0,128,256Zm379-54.86L400.07,18.29a37.26,37.26,0,0,0-64.14,0L229,201.14C214.76,225.52,232.58,256,261.09,256H474.91C503.42,256,521.24,225.52,507,201.14ZM480,288H320a32,32,0,0,0-32,32V480a32,32,0,0,0,32,32H480a32,32,0,0,0,32-32V320A32,32,0,0,0,480,288Z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 569 B After Width: | Height: | Size: 524 B |
+14
-6
@@ -1,4 +1,16 @@
|
||||
describe('iD.osmWay', function() {
|
||||
var _savedAreaKeys;
|
||||
|
||||
before(function() {
|
||||
_savedAreaKeys = iD.osmAreaKeys;
|
||||
iD.osmSetAreaKeys({ building: {} });
|
||||
});
|
||||
|
||||
after(function() {
|
||||
iD.osmSetAreaKeys(_savedAreaKeys);
|
||||
});
|
||||
|
||||
|
||||
if (iD.debug) {
|
||||
it('freezes nodes', function () {
|
||||
expect(Object.isFrozen(iD.osmWay().nodes)).to.be.true;
|
||||
@@ -405,10 +417,6 @@ describe('iD.osmWay', function() {
|
||||
});
|
||||
|
||||
describe('#isArea', function() {
|
||||
before(function() {
|
||||
iD.coreContext().init();
|
||||
});
|
||||
|
||||
it('returns false when the way has no tags', function() {
|
||||
expect(iD.osmWay().isArea()).to.equal(false);
|
||||
});
|
||||
@@ -421,7 +429,7 @@ describe('iD.osmWay', function() {
|
||||
expect(iD.osmWay({nodes: ['n1', 'n1']}).isArea()).to.equal(false);
|
||||
});
|
||||
|
||||
it('returns true if the way is closed and has a key in iD.areaKeys', function() {
|
||||
it('returns true if the way is closed and has a key in iD.osmAreaKeys', function() {
|
||||
expect(iD.osmWay({nodes: ['n1', 'n1'], tags: {building: 'yes'}}).isArea()).to.equal(true);
|
||||
});
|
||||
|
||||
@@ -435,7 +443,7 @@ describe('iD.osmWay', function() {
|
||||
expect(iD.osmWay({nodes: ['n1', 'n1'], tags: { railway: 'wash' }}).isArea(), 'railway=wash').to.equal(true);
|
||||
});
|
||||
|
||||
it('returns false if the way is closed and has no keys in iD.areaKeys', function() {
|
||||
it('returns false if the way is closed and has no keys in iD.osmAreaKeys', function() {
|
||||
expect(iD.osmWay({nodes: ['n1', 'n1'], tags: {a: 'b'}}).isArea()).to.equal(false);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,31 +1,25 @@
|
||||
describe('iD.presetCategory', function() {
|
||||
var category, residential;
|
||||
var category = {
|
||||
'geometry': 'line',
|
||||
'icon': 'highway',
|
||||
'name': 'roads',
|
||||
'members': [ 'highway/residential' ]
|
||||
};
|
||||
|
||||
var residential = iD.presetPreset('highway/residential',
|
||||
{ tags: { highway: 'residential' }, geometry: ['line'] }
|
||||
);
|
||||
var all = iD.presetCollection([residential]);
|
||||
|
||||
beforeEach(function() {
|
||||
category = {
|
||||
'geometry': 'line',
|
||||
'icon': 'highway',
|
||||
'name': 'roads',
|
||||
'members': [
|
||||
'highway/residential'
|
||||
]
|
||||
};
|
||||
residential = iD.presetPreset('highway/residential', {
|
||||
tags: {
|
||||
highway: 'residential'
|
||||
},
|
||||
geometry: ['line']
|
||||
});
|
||||
});
|
||||
|
||||
it('maps members names to preset instances', function() {
|
||||
var c = iD.presetCategory('road', category, iD.presetCollection([residential]));
|
||||
var c = iD.presetCategory('road', category, all);
|
||||
expect(c.members.collection[0]).to.eql(residential);
|
||||
});
|
||||
|
||||
describe('#matchGeometry', function() {
|
||||
it('matches the type of an entity', function() {
|
||||
var c = iD.presetCategory('road', category, iD.presetCollection([residential]));
|
||||
var c = iD.presetCategory('road', category, all);
|
||||
expect(c.matchGeometry('line')).to.eql(true);
|
||||
expect(c.matchGeometry('point')).to.eql(false);
|
||||
});
|
||||
|
||||
@@ -15,56 +15,56 @@ describe('iD.presetCollection', function() {
|
||||
tags: {},
|
||||
geometry: ['area']
|
||||
}),
|
||||
grill: iD.presetPreset('__test/amenity/bbq', {
|
||||
grill: iD.presetPreset('amenity/bbq', {
|
||||
name: 'Grill',
|
||||
tags: { amenity: 'bbq' },
|
||||
geometry: ['point'],
|
||||
terms: []
|
||||
}),
|
||||
sandpit: iD.presetPreset('__test/amenity/grit_bin', {
|
||||
sandpit: iD.presetPreset('amenity/grit_bin', {
|
||||
name: 'Sandpit',
|
||||
tags: { amenity: 'grit_bin' },
|
||||
geometry: ['point'],
|
||||
terms: []
|
||||
}),
|
||||
residential: iD.presetPreset('__test/highway/residential', {
|
||||
residential: iD.presetPreset('highway/residential', {
|
||||
name: 'Residential Area',
|
||||
tags: { highway: 'residential' },
|
||||
geometry: ['point', 'area'],
|
||||
terms: []
|
||||
}),
|
||||
grass1: iD.presetPreset('__test/landuse/grass1', {
|
||||
grass1: iD.presetPreset('landuse/grass1', {
|
||||
name: 'Grass',
|
||||
tags: { landuse: 'grass' },
|
||||
geometry: ['point', 'area'],
|
||||
terms: []
|
||||
}),
|
||||
grass2: iD.presetPreset('__test/landuse/grass2', {
|
||||
grass2: iD.presetPreset('landuse/grass2', {
|
||||
name: 'Ğṝȁß',
|
||||
tags: { landuse: 'ğṝȁß' },
|
||||
geometry: ['point', 'area'],
|
||||
terms: []
|
||||
}),
|
||||
park: iD.presetPreset('__test/leisure/park', {
|
||||
park: iD.presetPreset('leisure/park', {
|
||||
name: 'Park',
|
||||
tags: { leisure: 'park' },
|
||||
geometry: ['point', 'area'],
|
||||
terms: [ 'grass' ],
|
||||
matchScore: 0.5
|
||||
}),
|
||||
parking: iD.presetPreset('__test/amenity/parking', {
|
||||
parking: iD.presetPreset('amenity/parking', {
|
||||
name: 'Parking',
|
||||
tags: { amenity: 'parking' },
|
||||
geometry: ['point', 'area'],
|
||||
terms: [ 'cars' ]
|
||||
}),
|
||||
soccer: iD.presetPreset('__test/leisure/pitch/soccer', {
|
||||
soccer: iD.presetPreset('leisure/pitch/soccer', {
|
||||
name: 'Soccer Field',
|
||||
tags: { leisure: 'pitch', sport: 'soccer' },
|
||||
geometry: ['point', 'area'],
|
||||
terms: ['fußball']
|
||||
}),
|
||||
football: iD.presetPreset('__test/leisure/pitch/american_football', {
|
||||
football: iD.presetPreset('leisure/pitch/american_football', {
|
||||
name: 'Football Field',
|
||||
tags: { leisure: 'pitch', sport: 'american_football' },
|
||||
geometry: ['point', 'area'],
|
||||
@@ -80,7 +80,7 @@ describe('iD.presetCollection', function() {
|
||||
|
||||
describe('#item', function() {
|
||||
it('fetches a preset by id', function() {
|
||||
expect(c.item('__test/highway/residential')).to.equal(p.residential);
|
||||
expect(c.item('highway/residential')).to.equal(p.residential);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -148,7 +148,7 @@ describe('iD.presetCollection', function() {
|
||||
});
|
||||
|
||||
it('excludes presets with searchable: false', function() {
|
||||
var excluded = iD.presetPreset('__test/excluded', {
|
||||
var excluded = iD.presetPreset('excluded', {
|
||||
name: 'excluded',
|
||||
tags: { amenity: 'excluded' },
|
||||
geometry: ['point'],
|
||||
|
||||
+151
-109
@@ -1,132 +1,162 @@
|
||||
describe('iD.presetIndex', function () {
|
||||
var savedPresets, savedAreaKeys, server;
|
||||
var _savedPresets, _savedAreaKeys;
|
||||
|
||||
before(function () {
|
||||
savedPresets = iD.data.presets;
|
||||
savedAreaKeys = iD.areaKeys;
|
||||
before(function() {
|
||||
_savedPresets = iD.data.preset_presets;
|
||||
_savedAreaKeys = iD.osmAreaKeys;
|
||||
});
|
||||
|
||||
after(function () {
|
||||
iD.data.presets = savedPresets;
|
||||
iD.setAreaKeys(savedAreaKeys);
|
||||
after(function() {
|
||||
iD.data.preset_presets = _savedPresets;
|
||||
iD.osmSetAreaKeys(_savedAreaKeys);
|
||||
});
|
||||
|
||||
|
||||
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'] }
|
||||
}
|
||||
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 () {
|
||||
iD.data.presets = testPresets;
|
||||
it('returns a collection containing presets matching a geometry and tags', function (done) {
|
||||
iD.data.preset_presets = testPresets;
|
||||
var presets = iD.coreContext().init().presets();
|
||||
var way = iD.osmWay({ tags: { highway: 'residential' } });
|
||||
var graph = iD.coreGraph([way]);
|
||||
|
||||
expect(presets.match(way, graph).id).to.eql('residential');
|
||||
window.setTimeout(function() {
|
||||
expect(presets.match(way, graph).id).to.eql('residential');
|
||||
done();
|
||||
}, 20);
|
||||
});
|
||||
|
||||
it('returns the appropriate fallback preset when no tags match', function () {
|
||||
iD.data.presets = testPresets;
|
||||
it('returns the appropriate fallback preset when no tags match', function (done) {
|
||||
iD.data.preset_presets = testPresets;
|
||||
var presets = iD.coreContext().init().presets();
|
||||
var point = iD.osmNode();
|
||||
var line = iD.osmWay({ tags: { foo: 'bar' } });
|
||||
var graph = iD.coreGraph([point, line]);
|
||||
|
||||
expect(presets.match(point, graph).id).to.eql('point');
|
||||
expect(presets.match(line, graph).id).to.eql('line');
|
||||
window.setTimeout(function() {
|
||||
expect(presets.match(point, graph).id).to.eql('point');
|
||||
expect(presets.match(line, graph).id).to.eql('line');
|
||||
done();
|
||||
}, 20);
|
||||
});
|
||||
|
||||
it('matches vertices on a line as points', function () {
|
||||
iD.data.presets = testPresets;
|
||||
it('matches vertices on a line as points', function (done) {
|
||||
iD.data.preset_presets = testPresets;
|
||||
var presets = iD.coreContext().init().presets();
|
||||
var point = iD.osmNode({ tags: { leisure: 'park' } });
|
||||
var line = iD.osmWay({ nodes: [point.id], tags: { 'highway': 'residential' } });
|
||||
var graph = iD.coreGraph([point, line]);
|
||||
|
||||
expect(presets.match(point, graph).id).to.eql('point');
|
||||
window.setTimeout(function() {
|
||||
expect(presets.match(point, graph).id).to.eql('point');
|
||||
done();
|
||||
}, 20);
|
||||
});
|
||||
|
||||
it('matches vertices on an addr:interpolation line as points', function () {
|
||||
iD.data.presets = testPresets;
|
||||
it('matches vertices on an addr:interpolation line as points', function (done) {
|
||||
iD.data.preset_presets = testPresets;
|
||||
var presets = iD.coreContext().init().presets();
|
||||
var point = iD.osmNode({ tags: { leisure: 'park' } });
|
||||
var line = iD.osmWay({ nodes: [point.id], tags: { 'addr:interpolation': 'even' } });
|
||||
var graph = iD.coreGraph([point, line]);
|
||||
|
||||
expect(presets.match(point, graph).id).to.eql('park');
|
||||
window.setTimeout(function() {
|
||||
expect(presets.match(point, graph).id).to.eql('park');
|
||||
done();
|
||||
}, 20);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('#areaKeys', function () {
|
||||
var testPresets = {
|
||||
presets: {
|
||||
'amenity/fuel/shell': { tags: { 'amenity': 'fuel' }, geometry: ['point', 'area'], suggestion: true },
|
||||
'highway/foo': { tags: { 'highway': 'foo' }, geometry: ['area'] },
|
||||
'leisure/track': { tags: { 'leisure': 'track' }, geometry: ['line', 'area'] },
|
||||
'natural': { tags: { 'natural': '*' }, geometry: ['point', 'vertex', 'area'] },
|
||||
'natural/peak': { tags: { 'natural': 'peak' }, geometry: ['point', 'vertex'] },
|
||||
'natural/tree_row': { tags: { 'natural': 'tree_row' }, geometry: ['line'] },
|
||||
'natural/wood': { tags: { 'natural': 'wood' }, geometry: ['point', 'area'] }
|
||||
}
|
||||
'amenity/fuel/shell': { tags: { 'amenity': 'fuel' }, geometry: ['point', 'area'], suggestion: true },
|
||||
'highway/foo': { tags: { 'highway': 'foo' }, geometry: ['area'] },
|
||||
'leisure/track': { tags: { 'leisure': 'track' }, geometry: ['line', 'area'] },
|
||||
'natural': { tags: { 'natural': '*' }, geometry: ['point', 'vertex', 'area'] },
|
||||
'natural/peak': { tags: { 'natural': 'peak' }, geometry: ['point', 'vertex'] },
|
||||
'natural/tree_row': { tags: { 'natural': 'tree_row' }, geometry: ['line'] },
|
||||
'natural/wood': { tags: { 'natural': 'wood' }, geometry: ['point', 'area'] }
|
||||
};
|
||||
|
||||
it('whitelists keys for presets with area geometry', function () {
|
||||
iD.data.presets = testPresets;
|
||||
it('includes keys for presets with area geometry', function (done) {
|
||||
iD.data.preset_presets = testPresets;
|
||||
var presets = iD.coreContext().init().presets();
|
||||
expect(presets.areaKeys()).to.include.keys('natural');
|
||||
window.setTimeout(function() {
|
||||
expect(presets.areaKeys()).to.include.keys('natural');
|
||||
done();
|
||||
}, 20);
|
||||
});
|
||||
|
||||
it('blacklists key-values for presets with a line geometry', function () {
|
||||
iD.data.presets = testPresets;
|
||||
it('discards key-values for presets with a line geometry', function (done) {
|
||||
iD.data.preset_presets = testPresets;
|
||||
var presets = iD.coreContext().init().presets();
|
||||
expect(presets.areaKeys().natural).to.include.keys('tree_row');
|
||||
expect(presets.areaKeys().natural.tree_row).to.be.true;
|
||||
window.setTimeout(function() {
|
||||
expect(presets.areaKeys().natural).to.include.keys('tree_row');
|
||||
expect(presets.areaKeys().natural.tree_row).to.be.true;
|
||||
done();
|
||||
}, 20);
|
||||
});
|
||||
|
||||
it('blacklists key-values for presets with both area and line geometry', function () {
|
||||
iD.data.presets = testPresets;
|
||||
it('discards key-values for presets with both area and line geometry', function (done) {
|
||||
iD.data.preset_presets = testPresets;
|
||||
var presets = iD.coreContext().init().presets();
|
||||
expect(presets.areaKeys().leisure).to.include.keys('track');
|
||||
window.setTimeout(function() {
|
||||
expect(presets.areaKeys().leisure).to.include.keys('track');
|
||||
done();
|
||||
}, 20);
|
||||
});
|
||||
|
||||
it('does not blacklist key-values for presets with neither area nor line geometry', function () {
|
||||
iD.data.presets = testPresets;
|
||||
it('does not discard key-values for presets with neither area nor line geometry', function (done) {
|
||||
iD.data.preset_presets = testPresets;
|
||||
var presets = iD.coreContext().init().presets();
|
||||
expect(presets.areaKeys().natural).not.to.include.keys('peak');
|
||||
window.setTimeout(function() {
|
||||
expect(presets.areaKeys().natural).not.to.include.keys('peak');
|
||||
done();
|
||||
}, 20);
|
||||
});
|
||||
|
||||
it('does not blacklist generic \'*\' key-values', function () {
|
||||
iD.data.presets = testPresets;
|
||||
it('does not discard generic \'*\' key-values', function (done) {
|
||||
iD.data.preset_presets = testPresets;
|
||||
var presets = iD.coreContext().init().presets();
|
||||
expect(presets.areaKeys().natural).not.to.include.keys('natural');
|
||||
window.setTimeout(function() {
|
||||
expect(presets.areaKeys().natural).not.to.include.keys('natural');
|
||||
done();
|
||||
}, 20);
|
||||
});
|
||||
|
||||
it('ignores keys like \'highway\' that are assumed to be lines', function () {
|
||||
iD.data.presets = testPresets;
|
||||
it('ignores keys like \'highway\' that are assumed to be lines', function (done) {
|
||||
iD.data.preset_presets = testPresets;
|
||||
var presets = iD.coreContext().init().presets();
|
||||
expect(presets.areaKeys()).not.to.include.keys('highway');
|
||||
window.setTimeout(function() {
|
||||
expect(presets.areaKeys()).not.to.include.keys('highway');
|
||||
done();
|
||||
}, 20);
|
||||
});
|
||||
|
||||
it('ignores suggestion presets', function () {
|
||||
iD.data.presets = testPresets;
|
||||
it('ignores suggestion presets', function (done) {
|
||||
iD.data.preset_presets = testPresets;
|
||||
var presets = iD.coreContext().init().presets();
|
||||
expect(presets.areaKeys()).not.to.include.keys('amenity');
|
||||
window.setTimeout(function() {
|
||||
expect(presets.areaKeys()).not.to.include.keys('amenity');
|
||||
done();
|
||||
}, 20);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#build', function () {
|
||||
|
||||
describe.skip('#build', function () {
|
||||
it('builds presets from provided', function () {
|
||||
var surfShop = iD.osmNode({ tags: { amenity: 'shop', 'shop:type': 'surf' } });
|
||||
var graph = iD.coreGraph([surfShop]);
|
||||
var presets = iD.coreContext().init().presets();
|
||||
var morePresets = {
|
||||
var presetData = {
|
||||
presets: {
|
||||
'amenity/shop/surf': {
|
||||
tags: { amenity: 'shop', 'shop:type': 'surf' },
|
||||
@@ -136,7 +166,7 @@ describe('iD.presetIndex', function () {
|
||||
};
|
||||
|
||||
expect(presets.match(surfShop, graph)).to.eql(undefined); // no surfshop preset yet...
|
||||
presets.build(morePresets, true);
|
||||
presets.build(presetData, true);
|
||||
expect(presets.match(surfShop, graph).addTags).to.eql({ amenity: 'shop', 'shop:type': 'surf' });
|
||||
});
|
||||
|
||||
@@ -146,7 +176,7 @@ describe('iD.presetIndex', function () {
|
||||
var entities = [surfShop, firstStreetJetty];
|
||||
var graph = iD.coreGraph(entities);
|
||||
var presets = iD.coreContext().init().presets();
|
||||
var morePresets = {
|
||||
var presetData = {
|
||||
presets: {
|
||||
'amenity/shop/surf': {
|
||||
tags: { amenity: 'shop', 'shop:type': 'surf' },
|
||||
@@ -159,7 +189,7 @@ describe('iD.presetIndex', function () {
|
||||
}
|
||||
};
|
||||
|
||||
presets.build(morePresets, false);
|
||||
presets.build(presetData, false);
|
||||
entities.forEach(function (entity) {
|
||||
var preset = presets.match(entity, graph);
|
||||
expect(preset.addable()).to.be.false;
|
||||
@@ -167,64 +197,76 @@ describe('iD.presetIndex', function () {
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('expected matches', function () {
|
||||
var testPresets = {
|
||||
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'] },
|
||||
building: { name: 'Building', tags: { building: 'yes' }, geometry: ['area'] },
|
||||
'type/multipolygon': {
|
||||
name: 'Multipolygon',
|
||||
geometry: ['area', 'relation'],
|
||||
tags: { 'type': 'multipolygon' },
|
||||
searchable: false,
|
||||
matchScore: 0.1
|
||||
},
|
||||
address: {
|
||||
name: 'Address',
|
||||
geometry: ['point', 'vertex', 'area'],
|
||||
tags: { 'addr:*': '*' },
|
||||
matchScore: 0.15
|
||||
},
|
||||
'highway/pedestrian_area': {
|
||||
name: 'Pedestrian Area',
|
||||
geometry: ['area'],
|
||||
tags: { highway: 'pedestrian', area: 'yes' }
|
||||
}
|
||||
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'] },
|
||||
building: { name: 'Building', tags: { building: 'yes' }, geometry: ['area'] },
|
||||
'type/multipolygon': {
|
||||
name: 'Multipolygon',
|
||||
geometry: ['area', 'relation'],
|
||||
tags: { 'type': 'multipolygon' },
|
||||
searchable: false,
|
||||
matchScore: 0.1
|
||||
},
|
||||
address: {
|
||||
name: 'Address',
|
||||
geometry: ['point', 'vertex', 'area'],
|
||||
tags: { 'addr:*': '*' },
|
||||
matchScore: 0.15
|
||||
},
|
||||
'highway/pedestrian_area': {
|
||||
name: 'Pedestrian Area',
|
||||
geometry: ['area'],
|
||||
tags: { highway: 'pedestrian', area: 'yes' }
|
||||
}
|
||||
};
|
||||
|
||||
it('prefers building to multipolygon', function () {
|
||||
iD.data.presets = testPresets;
|
||||
it('prefers building to multipolygon', function (done) {
|
||||
iD.data.preset_presets = testPresets;
|
||||
var presets = iD.coreContext().init().presets();
|
||||
var relation = iD.osmRelation({ tags: { type: 'multipolygon', building: 'yes' } });
|
||||
var graph = iD.coreGraph([relation]);
|
||||
expect(presets.match(relation, graph).id).to.eql('building');
|
||||
window.setTimeout(function() {
|
||||
var match = presets.match(relation, graph);
|
||||
expect(match.id).to.eql('building');
|
||||
done();
|
||||
}, 20);
|
||||
});
|
||||
|
||||
it('prefers building to address', function () {
|
||||
iD.data.presets = testPresets;
|
||||
it('prefers building to address', function (done) {
|
||||
iD.data.preset_presets = testPresets;
|
||||
var presets = iD.coreContext().init().presets();
|
||||
var way = iD.osmWay({ tags: { area: 'yes', building: 'yes', 'addr:housenumber': '1234' } });
|
||||
var graph = iD.coreGraph([way]);
|
||||
expect(presets.match(way, graph).id).to.eql('building');
|
||||
window.setTimeout(function() {
|
||||
var match = presets.match(way, graph);
|
||||
expect(match.id).to.eql('building');
|
||||
done();
|
||||
}, 20);
|
||||
});
|
||||
|
||||
it('prefers pedestrian to area', function () {
|
||||
iD.data.presets = testPresets;
|
||||
it('prefers pedestrian to area', function (done) {
|
||||
iD.data.preset_presets = testPresets;
|
||||
var presets = iD.coreContext().init().presets();
|
||||
var way = iD.osmWay({ tags: { area: 'yes', highway: 'pedestrian' } });
|
||||
var graph = iD.coreGraph([way]);
|
||||
expect(presets.match(way, graph).id).to.eql('highway/pedestrian_area');
|
||||
window.setTimeout(function() {
|
||||
var match = presets.match(way, graph);
|
||||
expect(match.id).to.eql('highway/pedestrian_area');
|
||||
done();
|
||||
}, 20);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('#fromExternal', function () {
|
||||
var morePresets = {
|
||||
describe.skip('#fromExternal', function () {
|
||||
var _server;
|
||||
var presetData = {
|
||||
presets: {
|
||||
'8bc64d6d': {
|
||||
'name': 'Surf Shop',
|
||||
@@ -245,11 +287,11 @@ describe('iD.presetIndex', function () {
|
||||
};
|
||||
|
||||
beforeEach(function () {
|
||||
server = window.fakeFetch().create();
|
||||
_server = window.fakeFetch().create();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
server.restore();
|
||||
_server.restore();
|
||||
});
|
||||
|
||||
it('builds presets w/external sources set to addable', function () {
|
||||
@@ -268,10 +310,10 @@ describe('iD.presetIndex', function () {
|
||||
expect(externalPresets.match(surfShop, graph).id).to.eql('8bc64d6d');
|
||||
});
|
||||
|
||||
server.respondWith('GET', /fake\.json/,
|
||||
[200, { 'Content-Type': 'application/json' }, JSON.stringify(morePresets)]
|
||||
_server.respondWith('GET', /fake\.json/,
|
||||
[200, { 'Content-Type': 'application/json' }, JSON.stringify(presetData)]
|
||||
);
|
||||
server.respond();
|
||||
_server.respond();
|
||||
});
|
||||
|
||||
it('makes only the external presets initially addable', function () {
|
||||
@@ -285,7 +327,7 @@ describe('iD.presetIndex', function () {
|
||||
return presets;
|
||||
}, []);
|
||||
|
||||
var morePresetKeys = Object.keys(morePresets.presets);
|
||||
var morePresetKeys = Object.keys(presetData.presets);
|
||||
expect(morePresetKeys.length).to.eql(external.length);
|
||||
|
||||
morePresetKeys.forEach(function(presetID) {
|
||||
@@ -293,10 +335,10 @@ describe('iD.presetIndex', function () {
|
||||
});
|
||||
});
|
||||
|
||||
server.respondWith('GET', /fake\.json/,
|
||||
[200, { 'Content-Type': 'application/json' }, JSON.stringify(morePresets)]
|
||||
_server.respondWith('GET', /fake\.json/,
|
||||
[200, { 'Content-Type': 'application/json' }, JSON.stringify(presetData)]
|
||||
);
|
||||
server.respond();
|
||||
_server.respond();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -16,6 +16,18 @@ describe('iD.presetPreset', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('#matchAllGeometry', function() {
|
||||
it('returns false if they don\'t all match', function() {
|
||||
var preset = iD.presetPreset('test', {geometry: ['line']});
|
||||
expect(preset.matchAllGeometry(['point','line'])).to.equal(false);
|
||||
});
|
||||
|
||||
it('returns true if they do all match', function() {
|
||||
var preset = iD.presetPreset('test', {geometry: ['point', 'line']});
|
||||
expect(preset.matchAllGeometry(['point','line'])).to.equal(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#matchScore', function() {
|
||||
it('returns -1 if preset does not match tags', function() {
|
||||
var preset = iD.presetPreset('test', {tags: {foo: 'bar'}});
|
||||
@@ -97,15 +109,15 @@ describe('iD.presetPreset', function() {
|
||||
});
|
||||
|
||||
describe('#setTags', function() {
|
||||
var savedAreaKeys;
|
||||
var _savedAreaKeys;
|
||||
|
||||
before(function () {
|
||||
savedAreaKeys = iD.areaKeys;
|
||||
iD.setAreaKeys({ building: {}, natural: {} });
|
||||
_savedAreaKeys = iD.osmAreaKeys;
|
||||
iD.osmSetAreaKeys({ building: {}, natural: {} });
|
||||
});
|
||||
|
||||
after(function () {
|
||||
iD.setAreaKeys(savedAreaKeys);
|
||||
iD.osmSetAreaKeys(_savedAreaKeys);
|
||||
});
|
||||
|
||||
it('adds match tags', function() {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
describe('maprules', function() {
|
||||
var _ruleChecks, savedAreaKeys, validationRules;
|
||||
var _ruleChecks, _savedAreaKeys, validationRules;
|
||||
|
||||
before(function() {
|
||||
savedAreaKeys = iD.areaKeys;
|
||||
iD.setAreaKeys({ building: {}, amenity: {} });
|
||||
_savedAreaKeys = iD.osmAreaKeys;
|
||||
iD.osmSetAreaKeys({ building: {}, amenity: {} });
|
||||
|
||||
iD.services.maprules = iD.serviceMapRules;
|
||||
iD.serviceMapRules.init();
|
||||
@@ -11,7 +11,7 @@ describe('maprules', function() {
|
||||
});
|
||||
|
||||
after(function() {
|
||||
iD.setAreaKeys(savedAreaKeys);
|
||||
iD.osmSetAreaKeys(_savedAreaKeys);
|
||||
delete iD.services.maprules;
|
||||
});
|
||||
|
||||
|
||||
+10
-16
@@ -2,25 +2,19 @@
|
||||
/* eslint no-extend-native:off */
|
||||
iD.debug = true;
|
||||
|
||||
// disable things that use the network
|
||||
iD.data.imagery = [];
|
||||
// Disable things that use the network
|
||||
for (var k in iD.services) { delete iD.services[k]; }
|
||||
|
||||
// run with a minimal set of presets for speed
|
||||
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'] },
|
||||
// for tests related to areaKeys:
|
||||
building: { name: 'Building', tags: { building: 'yes' }, geometry: ['point', 'area'] },
|
||||
man_made: { name: 'Man Made', tags: { man_made: '*' }, geometry: ['vertex', 'point', 'line', 'area'] }
|
||||
}
|
||||
};
|
||||
// Run without data for speed (tests which need data can set it up themselves)
|
||||
|
||||
// creating `coreContext` creates validators and some of the validators try loading these
|
||||
// Initializing `coreContext` initializes `_background`, which tries loading:
|
||||
iD.data.imagery = [];
|
||||
// Initializing `coreContext` initializes `_presets`, which tries loading:
|
||||
iD.data.preset_categories = {};
|
||||
iD.data.preset_defaults = {};
|
||||
iD.data.preset_fields = {};
|
||||
iD.data.preset_presets = {};
|
||||
// Initializing `coreContext` initializes `_validator`, which tries loading:
|
||||
iD.data.deprecated = [];
|
||||
iD.data.nsi_brands = [];
|
||||
iD.data.nsi_filters = { discardNames: [] };
|
||||
|
||||
+43
-42
@@ -1,7 +1,8 @@
|
||||
describe('iD.svgAreas', function () {
|
||||
var context, surface, savedAreaKeys;
|
||||
var context, _surface, _savedAreaKeys;
|
||||
var all = function() { return true; };
|
||||
var none = function() { return false; };
|
||||
|
||||
var projection = d3.geoProjection(function(x, y) { return [x, -y]; })
|
||||
.translate([0, 0])
|
||||
.scale(iD.geoZoomToScale(17))
|
||||
@@ -13,14 +14,14 @@ describe('iD.svgAreas', function () {
|
||||
d3.select(document.createElement('div'))
|
||||
.attr('id', 'map')
|
||||
.call(context.map().centerZoom([0, 0], 17));
|
||||
surface = context.surface();
|
||||
_surface = context.surface();
|
||||
|
||||
savedAreaKeys = iD.areaKeys;
|
||||
iD.setAreaKeys({ building: {}, landuse: {}, natural: {} });
|
||||
_savedAreaKeys = iD.osmAreaKeys;
|
||||
iD.osmSetAreaKeys({ building: {}, landuse: {}, natural: {} });
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
iD.setAreaKeys(savedAreaKeys);
|
||||
iD.osmSetAreaKeys(_savedAreaKeys);
|
||||
});
|
||||
|
||||
|
||||
@@ -30,13 +31,13 @@ describe('iD.svgAreas', function () {
|
||||
iD.osmNode({id: 'b', loc: [1, 0]}),
|
||||
iD.osmNode({id: 'c', loc: [1, 1]}),
|
||||
iD.osmNode({id: 'd', loc: [0, 1]}),
|
||||
iD.osmWay({id: 'w', tags: {building: 'yes'}, nodes: ['a', 'b', 'c', 'a']})
|
||||
iD.osmWay({id: 'w', tags: {area: 'yes', building: 'yes'}, nodes: ['a', 'b', 'c', 'a']})
|
||||
]);
|
||||
|
||||
surface.call(iD.svgAreas(projection, context), graph, [graph.entity('w')], none);
|
||||
_surface.call(iD.svgAreas(projection, context), graph, [graph.entity('w')], none);
|
||||
|
||||
expect(surface.select('path.way').classed('way')).to.be.true;
|
||||
expect(surface.select('path.area').classed('area')).to.be.true;
|
||||
expect(_surface.select('path.way').classed('way')).to.be.true;
|
||||
expect(_surface.select('path.area').classed('area')).to.be.true;
|
||||
});
|
||||
|
||||
it('adds tag classes', function () {
|
||||
@@ -45,13 +46,13 @@ describe('iD.svgAreas', function () {
|
||||
iD.osmNode({id: 'b', loc: [1, 0]}),
|
||||
iD.osmNode({id: 'c', loc: [1, 1]}),
|
||||
iD.osmNode({id: 'd', loc: [0, 1]}),
|
||||
iD.osmWay({id: 'w', tags: {building: 'yes'}, nodes: ['a', 'b', 'c', 'a']})
|
||||
iD.osmWay({id: 'w', tags: {area: 'yes', building: 'yes'}, nodes: ['a', 'b', 'c', 'a']})
|
||||
]);
|
||||
|
||||
surface.call(iD.svgAreas(projection, context), graph, [graph.entity('w')], none);
|
||||
_surface.call(iD.svgAreas(projection, context), graph, [graph.entity('w')], none);
|
||||
|
||||
expect(surface.select('.area').classed('tag-building')).to.be.true;
|
||||
expect(surface.select('.area').classed('tag-building-yes')).to.be.true;
|
||||
expect(_surface.select('.area').classed('tag-building')).to.be.true;
|
||||
expect(_surface.select('.area').classed('tag-building-yes')).to.be.true;
|
||||
});
|
||||
|
||||
it('handles deletion of a way and a member vertex (#1903)', function () {
|
||||
@@ -64,11 +65,11 @@ describe('iD.svgAreas', function () {
|
||||
iD.osmWay({id: 'x', tags: {area: 'yes'}, nodes: ['a', 'b', 'd', 'a']})
|
||||
]);
|
||||
|
||||
surface.call(iD.svgAreas(projection, context), graph, [graph.entity('x')], all);
|
||||
_surface.call(iD.svgAreas(projection, context), graph, [graph.entity('x')], all);
|
||||
graph = graph.remove(graph.entity('x')).remove(graph.entity('d'));
|
||||
|
||||
surface.call(iD.svgAreas(projection, context), graph, [graph.entity('w')], all);
|
||||
expect(surface.select('.area').size()).to.equal(1);
|
||||
_surface.call(iD.svgAreas(projection, context), graph, [graph.entity('w')], all);
|
||||
expect(_surface.select('.area').size()).to.equal(1);
|
||||
});
|
||||
|
||||
describe('z-indexing', function() {
|
||||
@@ -81,38 +82,38 @@ describe('iD.svgAreas', function () {
|
||||
iD.osmNode({id: 'f', loc: [ 0.0004, 0.0002]}),
|
||||
iD.osmNode({id: 'g', loc: [ 0.0004, -0.0002]}),
|
||||
iD.osmNode({id: 'h', loc: [-0.0004, -0.0002]}),
|
||||
iD.osmWay({id: 's', tags: {building: 'yes'}, nodes: ['a', 'b', 'c', 'd', 'a']}),
|
||||
iD.osmWay({id: 'l', tags: {landuse: 'park'}, nodes: ['e', 'f', 'g', 'h', 'e']})
|
||||
iD.osmWay({id: 's', tags: {area: 'yes', building: 'yes'}, nodes: ['a', 'b', 'c', 'd', 'a']}),
|
||||
iD.osmWay({id: 'l', tags: {area: 'yes', landuse: 'park'}, nodes: ['e', 'f', 'g', 'h', 'e']})
|
||||
]);
|
||||
|
||||
it('stacks smaller areas above larger ones in a single render', function () {
|
||||
surface.call(iD.svgAreas(projection, context), graph, [graph.entity('s'), graph.entity('l')], none);
|
||||
_surface.call(iD.svgAreas(projection, context), graph, [graph.entity('s'), graph.entity('l')], none);
|
||||
|
||||
expect(surface.select('.area:nth-child(1)').classed('tag-landuse-park')).to.be.true;
|
||||
expect(surface.select('.area:nth-child(2)').classed('tag-building-yes')).to.be.true;
|
||||
expect(_surface.select('.area:nth-child(1)').classed('tag-landuse-park')).to.be.true;
|
||||
expect(_surface.select('.area:nth-child(2)').classed('tag-building-yes')).to.be.true;
|
||||
});
|
||||
|
||||
it('stacks smaller areas above larger ones in a single render (reverse)', function () {
|
||||
surface.call(iD.svgAreas(projection, context), graph, [graph.entity('l'), graph.entity('s')], none);
|
||||
_surface.call(iD.svgAreas(projection, context), graph, [graph.entity('l'), graph.entity('s')], none);
|
||||
|
||||
expect(surface.select('.area:nth-child(1)').classed('tag-landuse-park')).to.be.true;
|
||||
expect(surface.select('.area:nth-child(2)').classed('tag-building-yes')).to.be.true;
|
||||
expect(_surface.select('.area:nth-child(1)').classed('tag-landuse-park')).to.be.true;
|
||||
expect(_surface.select('.area:nth-child(2)').classed('tag-building-yes')).to.be.true;
|
||||
});
|
||||
|
||||
it('stacks smaller areas above larger ones in separate renders', function () {
|
||||
surface.call(iD.svgAreas(projection, context), graph, [graph.entity('s')], none);
|
||||
surface.call(iD.svgAreas(projection, context), graph, [graph.entity('l')], none);
|
||||
_surface.call(iD.svgAreas(projection, context), graph, [graph.entity('s')], none);
|
||||
_surface.call(iD.svgAreas(projection, context), graph, [graph.entity('l')], none);
|
||||
|
||||
expect(surface.select('.area:nth-child(1)').classed('tag-landuse-park')).to.be.true;
|
||||
expect(surface.select('.area:nth-child(2)').classed('tag-building-yes')).to.be.true;
|
||||
expect(_surface.select('.area:nth-child(1)').classed('tag-landuse-park')).to.be.true;
|
||||
expect(_surface.select('.area:nth-child(2)').classed('tag-building-yes')).to.be.true;
|
||||
});
|
||||
|
||||
it('stacks smaller areas above larger ones in separate renders (reverse)', function () {
|
||||
surface.call(iD.svgAreas(projection, context), graph, [graph.entity('l')], none);
|
||||
surface.call(iD.svgAreas(projection, context), graph, [graph.entity('s')], none);
|
||||
_surface.call(iD.svgAreas(projection, context), graph, [graph.entity('l')], none);
|
||||
_surface.call(iD.svgAreas(projection, context), graph, [graph.entity('s')], none);
|
||||
|
||||
expect(surface.select('.area:nth-child(1)').classed('tag-landuse-park')).to.be.true;
|
||||
expect(surface.select('.area:nth-child(2)').classed('tag-building-yes')).to.be.true;
|
||||
expect(_surface.select('.area:nth-child(1)').classed('tag-landuse-park')).to.be.true;
|
||||
expect(_surface.select('.area:nth-child(2)').classed('tag-building-yes')).to.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -125,9 +126,9 @@ describe('iD.svgAreas', function () {
|
||||
var graph = iD.coreGraph([a, b, c, w, r]);
|
||||
var areas = [w, r];
|
||||
|
||||
surface.call(iD.svgAreas(projection, context), graph, areas, none);
|
||||
_surface.call(iD.svgAreas(projection, context), graph, areas, none);
|
||||
|
||||
expect(surface.select('.fill').classed('relation')).to.be.true;
|
||||
expect(_surface.select('.fill').classed('relation')).to.be.true;
|
||||
});
|
||||
|
||||
it('renders no strokes for multipolygon areas', function () {
|
||||
@@ -139,9 +140,9 @@ describe('iD.svgAreas', function () {
|
||||
var graph = iD.coreGraph([a, b, c, w, r]);
|
||||
var areas = [w, r];
|
||||
|
||||
surface.call(iD.svgAreas(projection, context), graph, areas, none);
|
||||
_surface.call(iD.svgAreas(projection, context), graph, areas, none);
|
||||
|
||||
expect(surface.selectAll('.stroke').size()).to.equal(0);
|
||||
expect(_surface.selectAll('.stroke').size()).to.equal(0);
|
||||
});
|
||||
|
||||
it('renders fill for a multipolygon with tags on the outer way', function() {
|
||||
@@ -152,11 +153,11 @@ describe('iD.svgAreas', function () {
|
||||
var r = iD.osmRelation({members: [{id: w.id, type: 'way'}], tags: {type: 'multipolygon'}});
|
||||
var graph = iD.coreGraph([a, b, c, w, r]);
|
||||
|
||||
surface.call(iD.svgAreas(projection, context), graph, [w, r], none);
|
||||
_surface.call(iD.svgAreas(projection, context), graph, [w, r], none);
|
||||
|
||||
expect(surface.selectAll('.way.fill').size()).to.equal(0);
|
||||
expect(surface.selectAll('.relation.fill').size()).to.equal(1);
|
||||
expect(surface.select('.relation.fill').classed('tag-natural-wood')).to.be.true;
|
||||
expect(_surface.selectAll('.way.fill').size()).to.equal(0);
|
||||
expect(_surface.selectAll('.relation.fill').size()).to.equal(1);
|
||||
expect(_surface.select('.relation.fill').classed('tag-natural-wood')).to.be.true;
|
||||
});
|
||||
|
||||
it('renders no strokes for a multipolygon with tags on the outer way', function() {
|
||||
@@ -167,8 +168,8 @@ describe('iD.svgAreas', function () {
|
||||
var r = iD.osmRelation({members: [{id: w.id, type: 'way'}], tags: {type: 'multipolygon'}});
|
||||
var graph = iD.coreGraph([a, b, c, w, r]);
|
||||
|
||||
surface.call(iD.svgAreas(projection, context), graph, [w, r], none);
|
||||
_surface.call(iD.svgAreas(projection, context), graph, [w, r], none);
|
||||
|
||||
expect(surface.selectAll('.stroke').size()).to.equal(0);
|
||||
expect(_surface.selectAll('.stroke').size()).to.equal(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
describe('iD.validations.mismatched_geometry', function () {
|
||||
var context;
|
||||
var context, _savedAreaKeys;
|
||||
|
||||
beforeEach(function() {
|
||||
_savedAreaKeys = iD.osmAreaKeys;
|
||||
context = iD.coreContext().init();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
iD.osmSetAreaKeys(_savedAreaKeys);
|
||||
});
|
||||
|
||||
|
||||
function createPoint(tags) {
|
||||
var n1 = iD.osmNode({id: 'n-1', loc: [4,4], tags: tags});
|
||||
context.perform(
|
||||
@@ -82,6 +88,7 @@ describe('iD.validations.mismatched_geometry', function () {
|
||||
});
|
||||
|
||||
it('flags open way with area tag', function() {
|
||||
iD.osmSetAreaKeys({ building: {} });
|
||||
createOpenWay({ building: 'yes' });
|
||||
var issues = validate();
|
||||
expect(issues).to.have.lengthOf(1);
|
||||
|
||||
Reference in New Issue
Block a user