mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-09 03:25:37 +02:00
Merge branch 'develop' into decouple-presets
This commit is contained in:
@@ -19,12 +19,16 @@
|
||||
"array-callback-return": "warn",
|
||||
"arrow-spacing": "warn",
|
||||
"block-scoped-var": "error",
|
||||
"block-spacing": ["warn", "always"],
|
||||
"brace-style": ["warn", "1tbs", { "allowSingleLine": true }],
|
||||
"class-methods-use-this": "error",
|
||||
"complexity": ["warn", 50],
|
||||
"curly": ["warn", "multi-line"],
|
||||
"default-case-last": "error",
|
||||
"default-param-last": "error",
|
||||
"dot-notation": "error",
|
||||
"eqeqeq": ["error", "smart"],
|
||||
"func-call-spacing": ["warn", "never"],
|
||||
"grouped-accessor-pairs": "error",
|
||||
"indent": ["off", 4],
|
||||
"keyword-spacing": "error",
|
||||
|
||||
@@ -36,6 +36,35 @@ _Breaking developer changes, which may affect downstream projects or sites that
|
||||
[@xxxx]: https://github.com/xxxx
|
||||
-->
|
||||
|
||||
# 2.19.5
|
||||
##### 2020-Nov-9
|
||||
|
||||
#### :sparkles: Usability & Accessibility
|
||||
* Enable loading iD with a feature selected even when zoomed out ([#8122])
|
||||
|
||||
[#8122]: https://github.com/openstreetmap/iD/issues/8122
|
||||
|
||||
#### :bug: Bugfixes
|
||||
* Fix an issue where some fields that allow multiple values would not show existing tags ([#8155])
|
||||
* Fix a bug where points could move back unexpectedly when changing their tags after dragging them ([#7606])
|
||||
* Fix rare instances where iD could add an invalid localized name tag ([#8165])
|
||||
|
||||
[#8155]: https://github.com/openstreetmap/iD/issues/8155
|
||||
[#7606]: https://github.com/openstreetmap/iD/issues/7606
|
||||
[#8165]: https://github.com/openstreetmap/iD/issues/8165
|
||||
|
||||
#### :earth_asia: Localization
|
||||
* Support dozens of additional languages in the Multilingual Name field ([#8165])
|
||||
|
||||
[#8165]: https://github.com/openstreetmap/iD/issues/8165
|
||||
|
||||
#### :rocket: Presets
|
||||
* Indicate the units for the Capacity field on storage tank presets ([#8078], [#8112], thanks [@karmanya007])
|
||||
|
||||
[#8078]: https://github.com/openstreetmap/iD/issues/8078
|
||||
[#8112]: https://github.com/openstreetmap/iD/issues/8112
|
||||
[@karmanya007]: https://github.com/karmanya007
|
||||
|
||||
# 2.19.4
|
||||
##### 2020-Nov-2
|
||||
|
||||
|
||||
+152
-1852
File diff suppressed because it is too large
Load Diff
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -8,8 +8,9 @@ export function actionDeleteMember(relationId, memberIndex) {
|
||||
|
||||
graph = graph.replace(relation);
|
||||
|
||||
if (relation.isDegenerate())
|
||||
if (relation.isDegenerate()) {
|
||||
graph = actionDeleteRelation(relation.id)(graph);
|
||||
}
|
||||
|
||||
return graph;
|
||||
};
|
||||
|
||||
@@ -80,8 +80,7 @@ export function actionDisconnect(nodeId, newNodeId) {
|
||||
|
||||
action.disabled = function(graph) {
|
||||
var connections = action.connections(graph);
|
||||
if (connections.length === 0)
|
||||
return 'not_connected';
|
||||
if (connections.length === 0) return 'not_connected';
|
||||
|
||||
var parentWays = graph.parentWays(graph.entity(nodeId));
|
||||
var seenRelationIds = {};
|
||||
@@ -105,8 +104,7 @@ export function actionDisconnect(nodeId, newNodeId) {
|
||||
});
|
||||
});
|
||||
|
||||
if (sharedRelation)
|
||||
return 'relation';
|
||||
if (sharedRelation) return 'relation';
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -256,11 +256,13 @@ export function behaviorSelect(context) {
|
||||
|
||||
var datum = pointerInfo.firstEvent.target.__data__;
|
||||
var entity = (datum && datum.properties && datum.properties.entity) || datum;
|
||||
if (context.graph().hasEntity(entity.id)) return {
|
||||
pointerId: pointerId,
|
||||
entityId: entity.id,
|
||||
selected: selectedIDs.indexOf(entity.id) !== -1
|
||||
};
|
||||
if (context.graph().hasEntity(entity.id)) {
|
||||
return {
|
||||
pointerId: pointerId,
|
||||
entityId: entity.id,
|
||||
selected: selectedIDs.indexOf(entity.id) !== -1
|
||||
};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ export function coreContext() {
|
||||
let context = utilRebind({}, dispatch, 'on');
|
||||
let _deferred = new Set();
|
||||
|
||||
context.version = '2.19.5-dev';
|
||||
context.version = '2.20.0-dev';
|
||||
context.privacyVersion = '20200407';
|
||||
|
||||
// iD will alter the hash so cache the parameters intended to setup the session
|
||||
@@ -177,10 +177,13 @@ export function coreContext() {
|
||||
_deferred.add(handle);
|
||||
};
|
||||
|
||||
// Download the full entity and its parent relations. The callback may be called multiple times.
|
||||
context.loadEntity = (entityID, callback) => {
|
||||
if (_connection) {
|
||||
const cid = _connection.getConnectionId();
|
||||
_connection.loadEntity(entityID, afterLoad(cid, callback));
|
||||
// We need to fetch the parent relations separately.
|
||||
_connection.loadEntityRelations(entityID, afterLoad(cid, callback));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -213,8 +213,9 @@ export function coreDifference(base, head) {
|
||||
|
||||
if (extent &&
|
||||
(!h || !h.intersects(extent, head)) &&
|
||||
(!b || !b.intersects(extent, base)))
|
||||
(!b || !b.intersects(extent, base))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
result[id] = h;
|
||||
|
||||
|
||||
@@ -143,8 +143,7 @@ coreGraph.prototype = {
|
||||
for (i = 0; i < entities.length; i++) {
|
||||
var entity = entities[i];
|
||||
|
||||
if (!entity.visible || (!force && base.entities[entity.id]))
|
||||
continue;
|
||||
if (!entity.visible || (!force && base.entities[entity.id])) continue;
|
||||
|
||||
// Merging data into the base graph
|
||||
base.entities[entity.id] = entity;
|
||||
|
||||
+8
-4
@@ -326,14 +326,18 @@ export function geoViewportEdge(point, dimensions) {
|
||||
var x = 0;
|
||||
var y = 0;
|
||||
|
||||
if (point[0] > dimensions[0] - pad[1])
|
||||
if (point[0] > dimensions[0] - pad[1]) {
|
||||
x = -10;
|
||||
if (point[0] < pad[3])
|
||||
}
|
||||
if (point[0] < pad[3]) {
|
||||
x = 10;
|
||||
if (point[1] > dimensions[1] - pad[2])
|
||||
}
|
||||
if (point[1] > dimensions[1] - pad[2]) {
|
||||
y = -10;
|
||||
if (point[1] < pad[0])
|
||||
}
|
||||
if (point[1] < pad[0]) {
|
||||
y = 10;
|
||||
}
|
||||
|
||||
if (x || y) {
|
||||
return [x, y];
|
||||
|
||||
@@ -114,8 +114,7 @@ osmEntity.prototype = {
|
||||
|
||||
|
||||
copy: function(resolver, copies) {
|
||||
if (copies[this.id])
|
||||
return copies[this.id];
|
||||
if (copies[this.id]) return copies[this.id];
|
||||
|
||||
var copy = osmEntity(this, { id: undefined, user: undefined, version: undefined });
|
||||
copies[this.id] = copy;
|
||||
|
||||
@@ -441,8 +441,7 @@ export function osmIntersection(graph, startVertexId, maxDistance) {
|
||||
}
|
||||
|
||||
// stop looking if we find a "direct" restriction (matching FROM, VIA, TO)
|
||||
if (restrict && restrict.direct)
|
||||
break;
|
||||
if (restrict && restrict.direct) break;
|
||||
}
|
||||
|
||||
nextWays.push({ way: way, restrict: restrict });
|
||||
@@ -607,19 +606,25 @@ export function osmInferRestriction(graph, turn, projection) {
|
||||
var angle = (geoAngle(fromVertex, fromNode, projection) -
|
||||
geoAngle(toVertex, toNode, projection)) * 180 / Math.PI;
|
||||
|
||||
while (angle < 0)
|
||||
while (angle < 0) {
|
||||
angle += 360;
|
||||
}
|
||||
|
||||
if (fromNode === toNode)
|
||||
if (fromNode === toNode) {
|
||||
return 'no_u_turn';
|
||||
if ((angle < 23 || angle > 336) && fromOneWay && toOneWay)
|
||||
}
|
||||
if ((angle < 23 || angle > 336) && fromOneWay && toOneWay) {
|
||||
return 'no_u_turn'; // wider tolerance for u-turn if both ways are oneway
|
||||
if ((angle < 40 || angle > 319) && fromOneWay && toOneWay && turn.from.vertex !== turn.to.vertex)
|
||||
}
|
||||
if ((angle < 40 || angle > 319) && fromOneWay && toOneWay && turn.from.vertex !== turn.to.vertex) {
|
||||
return 'no_u_turn'; // even wider tolerance for u-turn if there is a via way (from !== to)
|
||||
if (angle < 158)
|
||||
}
|
||||
if (angle < 158) {
|
||||
return 'no_right_turn';
|
||||
if (angle > 202)
|
||||
}
|
||||
if (angle > 202) {
|
||||
return 'no_left_turn';
|
||||
}
|
||||
|
||||
return 'no_straight_on';
|
||||
}
|
||||
|
||||
+22
-20
@@ -136,23 +136,19 @@ function parseLaneDirections(tags, isOneWay, laneCount) {
|
||||
forward = 0;
|
||||
bothways = 0;
|
||||
backward = laneCount;
|
||||
}
|
||||
else if (isOneWay) {
|
||||
} else if (isOneWay) {
|
||||
forward = laneCount;
|
||||
bothways = 0;
|
||||
backward = 0;
|
||||
}
|
||||
else if (isNaN(forward) && isNaN(backward)) {
|
||||
} else if (isNaN(forward) && isNaN(backward)) {
|
||||
backward = Math.floor((laneCount - bothways) / 2);
|
||||
forward = laneCount - bothways - backward;
|
||||
}
|
||||
else if (isNaN(forward)) {
|
||||
} else if (isNaN(forward)) {
|
||||
if (backward > laneCount - bothways) {
|
||||
backward = laneCount - bothways;
|
||||
}
|
||||
forward = laneCount - bothways - backward;
|
||||
}
|
||||
else if (isNaN(backward)) {
|
||||
} else if (isNaN(backward)) {
|
||||
if (forward > laneCount - bothways) {
|
||||
forward = laneCount - bothways;
|
||||
}
|
||||
@@ -229,16 +225,22 @@ function parseBicycleWay(tag) {
|
||||
|
||||
|
||||
function mapToLanesObj(lanesObj, data, key) {
|
||||
if (data.forward) data.forward.forEach(function(l, i) {
|
||||
if (!lanesObj.forward[i]) lanesObj.forward[i] = {};
|
||||
lanesObj.forward[i][key] = l;
|
||||
});
|
||||
if (data.backward) data.backward.forEach(function(l, i) {
|
||||
if (!lanesObj.backward[i]) lanesObj.backward[i] = {};
|
||||
lanesObj.backward[i][key] = l;
|
||||
});
|
||||
if (data.unspecified) data.unspecified.forEach(function(l, i) {
|
||||
if (!lanesObj.unspecified[i]) lanesObj.unspecified[i] = {};
|
||||
lanesObj.unspecified[i][key] = l;
|
||||
});
|
||||
if (data.forward) {
|
||||
data.forward.forEach(function(l, i) {
|
||||
if (!lanesObj.forward[i]) lanesObj.forward[i] = {};
|
||||
lanesObj.forward[i][key] = l;
|
||||
});
|
||||
}
|
||||
if (data.backward) {
|
||||
data.backward.forEach(function(l, i) {
|
||||
if (!lanesObj.backward[i]) lanesObj.backward[i] = {};
|
||||
lanesObj.backward[i][key] = l;
|
||||
});
|
||||
}
|
||||
if (data.unspecified) {
|
||||
data.unspecified.forEach(function(l, i) {
|
||||
if (!lanesObj.unspecified[i]) lanesObj.unspecified[i] = {};
|
||||
lanesObj.unspecified[i][key] = l;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+25
-18
@@ -40,24 +40,31 @@ export function osmOldMultipolygonOuterMemberOfRelation(entity, graph) {
|
||||
// For fixing up rendering of multipolygons with tags on the outer member.
|
||||
// https://github.com/openstreetmap/iD/issues/613
|
||||
export function osmIsOldMultipolygonOuterMember(entity, graph) {
|
||||
if (entity.type !== 'way' || Object.keys(entity.tags).filter(osmIsInterestingTag).length === 0)
|
||||
if (entity.type !== 'way' ||
|
||||
Object.keys(entity.tags).filter(osmIsInterestingTag).length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var parents = graph.parentRelations(entity);
|
||||
if (parents.length !== 1)
|
||||
return false;
|
||||
if (parents.length !== 1) return false;
|
||||
|
||||
var parent = parents[0];
|
||||
if (!parent.isMultipolygon() || Object.keys(parent.tags).filter(osmIsInterestingTag).length > 1)
|
||||
if (!parent.isMultipolygon() ||
|
||||
Object.keys(parent.tags).filter(osmIsInterestingTag).length > 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var members = parent.members, member;
|
||||
for (var i = 0; i < members.length; i++) {
|
||||
member = members[i];
|
||||
if (member.id === entity.id && member.role && member.role !== 'outer')
|
||||
return false; // Not outer member
|
||||
if (member.id !== entity.id && (!member.role || member.role === 'outer'))
|
||||
return false; // Not a simple multipolygon
|
||||
if (member.id === entity.id && member.role && member.role !== 'outer') {
|
||||
// Not outer member
|
||||
return false;
|
||||
}
|
||||
if (member.id !== entity.id && (!member.role || member.role === 'outer')) {
|
||||
// Not a simple multipolygon
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return parent;
|
||||
@@ -65,33 +72,33 @@ export function osmIsOldMultipolygonOuterMember(entity, graph) {
|
||||
|
||||
|
||||
export function osmOldMultipolygonOuterMember(entity, graph) {
|
||||
if (entity.type !== 'way')
|
||||
return false;
|
||||
if (entity.type !== 'way') return false;
|
||||
|
||||
var parents = graph.parentRelations(entity);
|
||||
if (parents.length !== 1)
|
||||
return false;
|
||||
if (parents.length !== 1) return false;
|
||||
|
||||
var parent = parents[0];
|
||||
if (!parent.isMultipolygon() || Object.keys(parent.tags).filter(osmIsInterestingTag).length > 1)
|
||||
if (!parent.isMultipolygon() ||
|
||||
Object.keys(parent.tags).filter(osmIsInterestingTag).length > 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var members = parent.members, member, outerMember;
|
||||
for (var i = 0; i < members.length; i++) {
|
||||
member = members[i];
|
||||
if (!member.role || member.role === 'outer') {
|
||||
if (outerMember)
|
||||
return false; // Not a simple multipolygon
|
||||
if (outerMember) return false; // Not a simple multipolygon
|
||||
outerMember = member;
|
||||
}
|
||||
}
|
||||
|
||||
if (!outerMember)
|
||||
return false;
|
||||
if (!outerMember) return false;
|
||||
|
||||
var outerEntity = graph.hasEntity(outerMember.id);
|
||||
if (!outerEntity || !Object.keys(outerEntity.tags).filter(osmIsInterestingTag).length)
|
||||
if (!outerEntity ||
|
||||
!Object.keys(outerEntity.tags).filter(osmIsInterestingTag).length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return outerEntity;
|
||||
}
|
||||
|
||||
@@ -330,14 +330,16 @@ Object.assign(osmRelation.prototype, {
|
||||
|
||||
for (o = 0; o < outers.length; o++) {
|
||||
outer = outers[o];
|
||||
if (geoPolygonContainsPolygon(outer, inner))
|
||||
if (geoPolygonContainsPolygon(outer, inner)) {
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
for (o = 0; o < outers.length; o++) {
|
||||
outer = outers[o];
|
||||
if (geoPolygonIntersectsPolygon(outer, inner, false))
|
||||
if (geoPolygonIntersectsPolygon(outer, inner, false)) {
|
||||
return o;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -155,8 +155,10 @@ Object.assign(osmWay.prototype, {
|
||||
|
||||
// implied oneway tag..
|
||||
for (var key in this.tags) {
|
||||
if (key in osmOneWayTags && (this.tags[key] in osmOneWayTags[key]))
|
||||
if (key in osmOneWayTags &&
|
||||
(this.tags[key] in osmOneWayTags[key])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
@@ -232,10 +234,8 @@ Object.assign(osmWay.prototype, {
|
||||
},
|
||||
|
||||
isArea: function() {
|
||||
if (this.tags.area === 'yes')
|
||||
return true;
|
||||
if (!this.isClosed() || this.tags.area === 'no')
|
||||
return false;
|
||||
if (this.tags.area === 'yes') return true;
|
||||
if (!this.isClosed() || this.tags.area === 'no') return false;
|
||||
return this.tagSuggestingArea() !== null;
|
||||
},
|
||||
|
||||
|
||||
+91
-33
@@ -232,6 +232,17 @@ var jsonparsers = {
|
||||
tags: obj.tags,
|
||||
members: getMembersJSON(obj)
|
||||
});
|
||||
},
|
||||
|
||||
user: function parseUser(obj, uid) {
|
||||
return {
|
||||
id: uid,
|
||||
display_name: obj.display_name,
|
||||
account_created: obj.account_created,
|
||||
image_url: obj.img && obj.img.href,
|
||||
changesets_count: obj.changesets && obj.changesets.count && obj.changesets.count.toString() || '0',
|
||||
active_blocks: obj.blocks && obj.blocks.received && obj.blocks.received.active && obj.blocks.received.active.toString() || '0'
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -242,11 +253,9 @@ function parseJSON(payload, callback, options) {
|
||||
}
|
||||
|
||||
var json = payload;
|
||||
if (typeof json !== 'object')
|
||||
json = JSON.parse(payload);
|
||||
if (typeof json !== 'object') json = JSON.parse(payload);
|
||||
|
||||
if (!json.elements)
|
||||
return callback({ message: 'No JSON', status: -1 });
|
||||
if (!json.elements) return callback({ message: 'No JSON', status: -1 });
|
||||
|
||||
var children = json.elements;
|
||||
|
||||
@@ -278,6 +287,46 @@ function parseJSON(payload, callback, options) {
|
||||
}
|
||||
}
|
||||
|
||||
function parseUserJSON(payload, callback, options) {
|
||||
options = Object.assign({ skipSeen: true }, options);
|
||||
if (!payload) {
|
||||
return callback({ message: 'No JSON', status: -1 });
|
||||
}
|
||||
|
||||
var json = payload;
|
||||
if (typeof json !== 'object') json = JSON.parse(payload);
|
||||
|
||||
if (!json.elements) return callback({ message: 'No JSON', status: -1 });
|
||||
|
||||
if (!json.users && !json.user) return callback({ message: 'No JSON', status: -1 });
|
||||
|
||||
var objs = json.users || [json];
|
||||
|
||||
var handle = window.requestIdleCallback(function() {
|
||||
var results = [];
|
||||
var result;
|
||||
for (var i = 0; i < objs.length; i++) {
|
||||
result = parseObj(objs[i]);
|
||||
if (result) results.push(result);
|
||||
}
|
||||
callback(null, results);
|
||||
});
|
||||
|
||||
_deferred.add(handle);
|
||||
|
||||
function parseObj(obj) {
|
||||
var uid = obj.user.id && obj.user.id.toString();
|
||||
if (options.skipSeen && _userCache.user[uid]) {
|
||||
delete _userCache.toLoad[uid];
|
||||
return null;
|
||||
}
|
||||
var user = jsonparsers.user(obj.user, uid);
|
||||
_userCache.user[uid] = user;
|
||||
delete _userCache.toLoad[uid];
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
||||
var parsers = {
|
||||
node: function nodeData(obj, uid) {
|
||||
var attrs = obj.attributes;
|
||||
@@ -635,7 +684,8 @@ export default {
|
||||
},
|
||||
|
||||
|
||||
// Load a single entity by id (ways and relations use the `/full` call)
|
||||
// Load a single entity by id (ways and relations use the `/full` call to include
|
||||
// nodes and members). Parent relations are not included, see `loadEntityRelations`.
|
||||
// GET /api/0.6/node/#id
|
||||
// GET /api/0.6/[way|relation]/#id/full
|
||||
loadEntity: function(id, callback) {
|
||||
@@ -670,6 +720,23 @@ export default {
|
||||
},
|
||||
|
||||
|
||||
// Load the relations of a single entity with the given.
|
||||
// GET /api/0.6/[node|way|relation]/#id/relations
|
||||
loadEntityRelations: function(id, callback) {
|
||||
var type = osmEntity.id.type(id);
|
||||
var osmID = osmEntity.id.toOSM(id);
|
||||
var options = { skipSeen: false };
|
||||
|
||||
this.loadFromAPI(
|
||||
'/api/0.6/' + type + '/' + osmID + '/relations.json',
|
||||
function(err, entities) {
|
||||
if (callback) callback(err, { data: entities });
|
||||
},
|
||||
options
|
||||
);
|
||||
},
|
||||
|
||||
|
||||
// Load multiple entities in chunks
|
||||
// (note: callback may be called multiple times)
|
||||
// Unlike `loadEntity`, child nodes and members are not fetched
|
||||
@@ -790,21 +857,18 @@ export default {
|
||||
|
||||
utilArrayChunk(toLoad, 150).forEach(function(arr) {
|
||||
oauth.xhr(
|
||||
{ method: 'GET', path: '/api/0.6/users?users=' + arr.join() },
|
||||
{ method: 'GET', path: '/api/0.6/users.json?users=' + arr.join() },
|
||||
wrapcb(this, done, _connectionID)
|
||||
);
|
||||
}.bind(this));
|
||||
|
||||
function done(err, xml) {
|
||||
if (err) { return callback(err); }
|
||||
function done(err, payload) {
|
||||
if (err) return callback(err);
|
||||
|
||||
var options = { skipSeen: true };
|
||||
return parseXML(xml, function(err, results) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
} else {
|
||||
return callback(undefined, results);
|
||||
}
|
||||
return parseUserJSON(payload, function(err, results) {
|
||||
if (err) return callback(err);
|
||||
return callback(undefined, results);
|
||||
}, options);
|
||||
}
|
||||
},
|
||||
@@ -819,20 +883,17 @@ export default {
|
||||
}
|
||||
|
||||
oauth.xhr(
|
||||
{ method: 'GET', path: '/api/0.6/user/' + uid },
|
||||
{ method: 'GET', path: '/api/0.6/user/' + uid + '.json' },
|
||||
wrapcb(this, done, _connectionID)
|
||||
);
|
||||
|
||||
function done(err, xml) {
|
||||
if (err) { return callback(err); }
|
||||
function done(err, payload) {
|
||||
if (err) return callback(err);
|
||||
|
||||
var options = { skipSeen: true };
|
||||
return parseXML(xml, function(err, results) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
} else {
|
||||
return callback(undefined, results[0]);
|
||||
}
|
||||
return parseUserJSON(payload, function(err, results) {
|
||||
if (err) return callback(err);
|
||||
return callback(undefined, results[0]);
|
||||
}, options);
|
||||
}
|
||||
},
|
||||
@@ -846,21 +907,18 @@ export default {
|
||||
}
|
||||
|
||||
oauth.xhr(
|
||||
{ method: 'GET', path: '/api/0.6/user/details' },
|
||||
{ method: 'GET', path: '/api/0.6/user/details.json' },
|
||||
wrapcb(this, done, _connectionID)
|
||||
);
|
||||
|
||||
function done(err, xml) {
|
||||
if (err) { return callback(err); }
|
||||
function done(err, payload) {
|
||||
if (err) return callback(err);
|
||||
|
||||
var options = { skipSeen: false };
|
||||
return parseXML(xml, function(err, results) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
} else {
|
||||
_userDetails = results[0];
|
||||
return callback(undefined, _userDetails);
|
||||
}
|
||||
return parseUserJSON(payload, function(err, results) {
|
||||
if (err) return callback(err);
|
||||
_userDetails = results[0];
|
||||
return callback(undefined, _userDetails);
|
||||
}, options);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -315,8 +315,7 @@ export function svgLabels(projection, context) {
|
||||
var preset = geometry === 'area' && presetManager.match(entity, graph);
|
||||
var icon = preset && !shouldSkipIcon(preset) && preset.icon;
|
||||
|
||||
if (!icon && !utilDisplayName(entity))
|
||||
continue;
|
||||
if (!icon && !utilDisplayName(entity)) continue;
|
||||
|
||||
for (k = 0; k < labelStack.length; k++) {
|
||||
var matchGeom = labelStack[k][0];
|
||||
|
||||
@@ -185,10 +185,11 @@ export function svgLines(projection, context) {
|
||||
var layer = this.parentNode.__data__;
|
||||
var data = pathdata[layer] || [];
|
||||
return data.filter(function(d) {
|
||||
if (isSelected)
|
||||
if (isSelected) {
|
||||
return context.selectedIDs().indexOf(d.id) !== -1;
|
||||
else
|
||||
} else {
|
||||
return context.selectedIDs().indexOf(d.id) === -1;
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@@ -83,8 +83,7 @@ export function svgMidpoints(projection, context) {
|
||||
point = geoLineIntersection([a.loc, b.loc], [poly[k], poly[k + 1]]);
|
||||
if (point &&
|
||||
geoVecLength(projection(a.loc), projection(point)) > 20 &&
|
||||
geoVecLength(projection(b.loc), projection(point)) > 20)
|
||||
{
|
||||
geoVecLength(projection(b.loc), projection(point)) > 20) {
|
||||
loc = point;
|
||||
break;
|
||||
}
|
||||
@@ -106,8 +105,7 @@ export function svgMidpoints(projection, context) {
|
||||
|
||||
|
||||
function midpointFilter(d) {
|
||||
if (midpoints[d.id])
|
||||
return true;
|
||||
if (midpoints[d.id]) return true;
|
||||
|
||||
for (var i = 0; i < d.parents.length; i++) {
|
||||
if (filter(d.parents[i])) {
|
||||
|
||||
@@ -118,8 +118,7 @@ export function svgTagClasses() {
|
||||
|
||||
if (v === 'yes') { // e.g. `railway=rail + abandoned=yes`
|
||||
status = k;
|
||||
}
|
||||
else if (primary && primary === v) { // e.g. `railway=rail + abandoned=railway`
|
||||
} else if (primary && primary === v) { // e.g. `railway=rail + abandoned=railway`
|
||||
status = k;
|
||||
} else if (!primary && primaries.indexOf(v) !== -1) { // e.g. `abandoned=railway`
|
||||
status = k;
|
||||
|
||||
@@ -193,8 +193,7 @@ export function uiCurtain(containerNode) {
|
||||
if (tooltipBox.left + tooltipBox.width + tooltipArrow + tooltipWidth > w - 70) {
|
||||
side = 'left';
|
||||
pos = [tooltipBox.left - tooltipWidth - tooltipArrow, tipY];
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
side = 'right';
|
||||
pos = [tooltipBox.left + tooltipBox.width + tooltipArrow, tipY];
|
||||
}
|
||||
@@ -217,8 +216,7 @@ export function uiCurtain(containerNode) {
|
||||
if (side === 'left' || side === 'right') {
|
||||
if (pos[1] < 60) {
|
||||
shiftY = 60 - pos[1];
|
||||
}
|
||||
else if (pos[1] + tip.height > h - 100) {
|
||||
} else if (pos[1] + tip.height > h - 100) {
|
||||
shiftY = h - pos[1] - tip.height - 100;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,11 +270,15 @@ export function uiEntityEditor(context) {
|
||||
|
||||
entityEditor.entityIDs = function(val) {
|
||||
if (!arguments.length) return _entityIDs;
|
||||
|
||||
// always reload these even if the entityIDs are unchanged, since we
|
||||
// could be reselecting after something like dragging a node
|
||||
_base = context.graph();
|
||||
_coalesceChanges = false;
|
||||
|
||||
if (val && _entityIDs && utilArrayIdentical(_entityIDs, val)) return entityEditor; // exit early if no change
|
||||
|
||||
_entityIDs = val;
|
||||
_base = context.graph();
|
||||
_coalesceChanges = false;
|
||||
|
||||
loadActivePresets(true);
|
||||
|
||||
|
||||
@@ -91,16 +91,12 @@ export function uiFieldAddress(field, context) {
|
||||
|
||||
function isAddressable(d) {
|
||||
if (d.tags.name) {
|
||||
if (d.tags.admin_level === '8' && d.tags.boundary === 'administrative')
|
||||
return true;
|
||||
if (d.tags.border_type === 'city')
|
||||
return true;
|
||||
if (d.tags.place === 'city' || d.tags.place === 'town' || d.tags.place === 'village')
|
||||
return true;
|
||||
if (d.tags.admin_level === '8' && d.tags.boundary === 'administrative') return true;
|
||||
if (d.tags.border_type === 'city') return true;
|
||||
if (d.tags.place === 'city' || d.tags.place === 'town' || d.tags.place === 'village') return true;
|
||||
}
|
||||
|
||||
if (d.tags['addr:city'])
|
||||
return true;
|
||||
if (d.tags['addr:city']) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -534,8 +534,10 @@ export function uiFieldRestrictions(field, context) {
|
||||
for (var i = 0; i < datum.via.ways.length; i++) {
|
||||
var prev = names[names.length - 1];
|
||||
var curr = displayName(datum.via.ways[i], vgraph);
|
||||
if (!prev || curr !== prev) // collapse identical names
|
||||
if (!prev || curr !== prev) {
|
||||
// collapse identical names
|
||||
names.push(curr);
|
||||
}
|
||||
}
|
||||
|
||||
help
|
||||
|
||||
@@ -86,8 +86,10 @@ export function uiImproveOsmDetails(context) {
|
||||
if (entity) {
|
||||
context.enter(modeSelect(context, [entityID]));
|
||||
} else {
|
||||
context.loadEntity(entityID, () => {
|
||||
context.enter(modeSelect(context, [entityID]));
|
||||
context.loadEntity(entityID, (err, result) => {
|
||||
if (err) return;
|
||||
const entity = result.data.find(e => e.id === entityID);
|
||||
if (entity) context.enter(modeSelect(context, [entityID]));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -49,7 +49,8 @@ var helpStringReplacements;
|
||||
// with custom `replacements`
|
||||
export function helpHtml(id, replacements) {
|
||||
// only load these the first time
|
||||
if (!helpStringReplacements) helpStringReplacements = {
|
||||
if (!helpStringReplacements) {
|
||||
helpStringReplacements = {
|
||||
// insert icons corresponding to various UI elements
|
||||
point_icon: icon('#iD-icon-point', 'inline'),
|
||||
line_icon: icon('#iD-icon-line', 'inline'),
|
||||
@@ -144,7 +145,8 @@ export function helpHtml(id, replacements) {
|
||||
start_the_walkthrough: t.html('splash.walkthrough'),
|
||||
help: t.html('help.title'),
|
||||
ok: t.html('intro.ok')
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
var reps;
|
||||
if (replacements) {
|
||||
@@ -255,10 +257,11 @@ export function selectMenuItem(context, operation) {
|
||||
|
||||
export function transitionTime(point1, point2) {
|
||||
var distance = geoSphericalDistance(point1, point2);
|
||||
if (distance === 0)
|
||||
if (distance === 0) {
|
||||
return 0;
|
||||
else if (distance < 80)
|
||||
} else if (distance < 80) {
|
||||
return 500;
|
||||
else
|
||||
} else {
|
||||
return 1000;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,12 +211,13 @@ export function uiIntroLine(context, reveal) {
|
||||
reveal('.surface', continueLineText);
|
||||
|
||||
context.on('enter.intro', function(mode) {
|
||||
if (mode.id === 'draw-line')
|
||||
if (mode.id === 'draw-line') {
|
||||
return;
|
||||
else if (mode.id === 'select')
|
||||
} else if (mode.id === 'select') {
|
||||
return continueTo(chooseCategoryRoad);
|
||||
else
|
||||
} else {
|
||||
return chapter.restart();
|
||||
}
|
||||
});
|
||||
|
||||
function continueTo(nextStep) {
|
||||
|
||||
@@ -91,8 +91,10 @@ export function uiKeepRightDetails(context) {
|
||||
if (entity) {
|
||||
context.enter(modeSelect(context, [entityID]));
|
||||
} else {
|
||||
context.loadEntity(entityID, () => {
|
||||
context.enter(modeSelect(context, [entityID]));
|
||||
context.loadEntity(entityID, (err, result) => {
|
||||
if (err) return;
|
||||
const entity = result.data.find(e => e.id === entityID);
|
||||
if (entity) context.enter(modeSelect(context, [entityID]));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -169,8 +169,10 @@ export function uiOsmoseDetails(context) {
|
||||
if (entity) {
|
||||
context.enter(modeSelect(context, [entityID]));
|
||||
} else {
|
||||
context.loadEntity(entityID, () => {
|
||||
context.enter(modeSelect(context, [entityID]));
|
||||
context.loadEntity(entityID, (err, result) => {
|
||||
if (err) return;
|
||||
const entity = result.data.find(e => e.id === entityID);
|
||||
if (entity) context.enter(modeSelect(context, [entityID]));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -23,18 +23,12 @@ export function uiPresetIcon() {
|
||||
|
||||
|
||||
function getIcon(p, geom) {
|
||||
if (isSmall() && p.isFallback && p.isFallback())
|
||||
return 'iD-icon-' + p.id;
|
||||
else if (p.icon)
|
||||
return p.icon;
|
||||
else if (geom === 'line')
|
||||
return 'iD-other-line';
|
||||
else if (geom === 'vertex')
|
||||
return p.isFallback() ? '' : 'temaki-vertex';
|
||||
else if (isSmall() && geom === 'point')
|
||||
return '';
|
||||
else
|
||||
return 'maki-marker-stroked';
|
||||
if (isSmall() && p.isFallback && p.isFallback()) return 'iD-icon-' + p.id;
|
||||
if (p.icon) return p.icon;
|
||||
if (geom === 'line') return 'iD-other-line';
|
||||
if (geom === 'vertex') return p.isFallback() ? '' : 'temaki-vertex';
|
||||
if (isSmall() && geom === 'point') return '';
|
||||
return 'maki-marker-stroked';
|
||||
}
|
||||
|
||||
|
||||
|
||||
+10
-3
@@ -31,9 +31,16 @@ export var JXON = new (function () {
|
||||
if (bChildren) {
|
||||
for (var oNode, nItem = 0; nItem < oParentNode.childNodes.length; nItem++) {
|
||||
oNode = oParentNode.childNodes.item(nItem);
|
||||
if (oNode.nodeType === 4) { sCollectedTxt += oNode.nodeValue; } /* nodeType is 'CDATASection' (4) */
|
||||
else if (oNode.nodeType === 3) { sCollectedTxt += oNode.nodeValue.trim(); } /* nodeType is 'Text' (3) */
|
||||
else if (oNode.nodeType === 1 && !oNode.prefix) { aCache.push(oNode); } /* nodeType is 'Element' (1) */
|
||||
if (oNode.nodeType === 4) {
|
||||
/* nodeType is 'CDATASection' (4) */
|
||||
sCollectedTxt += oNode.nodeValue;
|
||||
} else if (oNode.nodeType === 3) {
|
||||
/* nodeType is 'Text' (3) */
|
||||
sCollectedTxt += oNode.nodeValue.trim();
|
||||
} else if (oNode.nodeType === 1 && !oNode.prefix) {
|
||||
/* nodeType is 'Element' (1) */
|
||||
aCache.push(oNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -60,11 +60,15 @@ export function utilKeybinding(namespace) {
|
||||
if (binding.event.key === undefined) {
|
||||
isMatch = false;
|
||||
} else if (Array.isArray(binding.event.key)) {
|
||||
if (binding.event.key.map(function(s) { return s.toLowerCase(); }).indexOf(event.key.toLowerCase()) === -1)
|
||||
if (binding.event.key.map(function(s) {
|
||||
return s.toLowerCase();
|
||||
}).indexOf(event.key.toLowerCase()) === -1) {
|
||||
isMatch = false;
|
||||
}
|
||||
} else {
|
||||
if (event.key.toLowerCase() !== binding.event.key.toLowerCase())
|
||||
if (event.key.toLowerCase() !== binding.event.key.toLowerCase()) {
|
||||
isMatch = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -365,8 +365,7 @@ export function utilPrefixDOMProperty(property) {
|
||||
var n = prefixes.length;
|
||||
var s = document.body;
|
||||
|
||||
if (property in s)
|
||||
return property;
|
||||
if (property in s) return property;
|
||||
|
||||
property = property.substr(0, 1).toUpperCase() + property.substr(1);
|
||||
|
||||
|
||||
@@ -152,8 +152,14 @@ export function utilZoomPan() {
|
||||
b = typeof transform === 'function' ? transform.apply(that, args) : transform,
|
||||
i = interpolate(a.invert(p).concat(w / a.k), b.invert(p).concat(w / b.k));
|
||||
return function(t) {
|
||||
if (t === 1) t = b; // Avoid rounding error on end.
|
||||
else { var l = i(t), k = w / l[2]; t = new Transform(k, p[0] - l[0] * k, p[1] - l[1] * k); }
|
||||
if (t === 1) {
|
||||
// Avoid rounding error on end.
|
||||
t = b;
|
||||
} else {
|
||||
var l = i(t);
|
||||
var k = w / l[2];
|
||||
t = new Transform(k, p[0] - l[0] * k, p[1] - l[1] * k);
|
||||
}
|
||||
g.zoom(null, null, t);
|
||||
};
|
||||
});
|
||||
@@ -297,8 +303,9 @@ export function utilZoomPan() {
|
||||
} else if (g.pointer0) {
|
||||
p = g.pointer0[0];
|
||||
l = g.pointer0[1];
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
else return;
|
||||
g.zoom(d3_event, 'touch', constrain(translate(t, p, l), g.extent, translateExtent));
|
||||
}
|
||||
|
||||
@@ -320,8 +327,9 @@ export function utilZoomPan() {
|
||||
g.pointer0 = g.pointer1;
|
||||
delete g.pointer1;
|
||||
}
|
||||
if (g.pointer0) g.pointer0[1] = _transform.invert(g.pointer0[0]);
|
||||
else {
|
||||
if (g.pointer0) {
|
||||
g.pointer0[1] = _transform.invert(g.pointer0[0]);
|
||||
} else {
|
||||
g.end(d3_event);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "iD",
|
||||
"version": "2.19.5-dev",
|
||||
"version": "2.20.0-dev",
|
||||
"description": "A friendly editor for OpenStreetMap",
|
||||
"main": "dist/iD.min.js",
|
||||
"repository": "github:openstreetmap/iD",
|
||||
|
||||
@@ -234,12 +234,12 @@ describe('maprules', function() {
|
||||
});
|
||||
});
|
||||
describe('greaterThan', function() {
|
||||
it ('is true when a tag value is greater than the selector value', function() {
|
||||
it('is true when a tag value is greater than the selector value', function() {
|
||||
var selectorTags = { lanes: 5 };
|
||||
var tags = { lanes : 6 };
|
||||
expect(_ruleChecks.greaterThan(selectorTags)(tags)).to.be.true;
|
||||
});
|
||||
it ('is false when a tag value is less than or equal to the selector value', function() {
|
||||
it('is false when a tag value is less than or equal to the selector value', function() {
|
||||
var selectorTags = { lanes: 5 };
|
||||
[4, 5].forEach(function(val) {
|
||||
expect(_ruleChecks.greaterThan(selectorTags)({ lanes: val })).to.be.false;
|
||||
@@ -247,25 +247,25 @@ describe('maprules', function() {
|
||||
});
|
||||
});
|
||||
describe('greaterThanEqual', function() {
|
||||
it ('is true when a tag value is greater than or equal to the selector value', function() {
|
||||
it('is true when a tag value is greater than or equal to the selector value', function() {
|
||||
var selectorTags = { lanes: 5 };
|
||||
[5, 6].forEach(function(val) {
|
||||
expect(_ruleChecks.greaterThanEqual(selectorTags)({ lanes: val })).to.be.true;
|
||||
});
|
||||
});
|
||||
it ('is false when a tag value is less than the selector value', function () {
|
||||
it('is false when a tag value is less than the selector value', function () {
|
||||
var selectorTags = { lanes: 5 };
|
||||
var tags = { lanes: 4 };
|
||||
expect(_ruleChecks.greaterThanEqual(selectorTags)(tags)).to.be.false;
|
||||
});
|
||||
});
|
||||
describe('lessThan', function() {
|
||||
it ('is true when a tag value is less than the selector value', function() {
|
||||
it('is true when a tag value is less than the selector value', function() {
|
||||
var selectorTags = { lanes: 5 };
|
||||
var tags = { lanes: 4 };
|
||||
expect(_ruleChecks.lessThan(selectorTags)(tags)).to.be.true;
|
||||
});
|
||||
it ('is false when a tag value is greater than or equal to the selector value', function() {
|
||||
it('is false when a tag value is greater than or equal to the selector value', function() {
|
||||
var selectorTags = { lanes: 5 };
|
||||
[6, 7].forEach(function(val) {
|
||||
expect(_ruleChecks.lessThan(selectorTags)({ lanes: val })).to.be.false;
|
||||
@@ -273,13 +273,13 @@ describe('maprules', function() {
|
||||
});
|
||||
});
|
||||
describe('lessThanEqual', function() {
|
||||
it ('is true when a tag value is less than or equal to the selector value', function() {
|
||||
it('is true when a tag value is less than or equal to the selector value', function() {
|
||||
var selectorTags = { lanes: 5 };
|
||||
[4, 5].forEach(function(val) {
|
||||
expect(_ruleChecks.lessThanEqual(selectorTags)({ lanes: val })).to.be.true;
|
||||
});
|
||||
});
|
||||
it ('is false when a tag value is greater than the selector value', function() {
|
||||
it('is false when a tag value is greater than the selector value', function() {
|
||||
var selectorTags = { lanes: 5 };
|
||||
var tags = { lanes: 6 };
|
||||
expect(_ruleChecks.lessThanEqual(selectorTags)(tags)).to.be.false;
|
||||
@@ -287,22 +287,22 @@ describe('maprules', function() {
|
||||
});
|
||||
describe('positiveRegex', function() {
|
||||
var positiveRegex = { amenity: ['^hospital$','^clinic$']};
|
||||
it ('is true when tag value matches positiveRegex', function() {
|
||||
it('is true when tag value matches positiveRegex', function() {
|
||||
var tags = { amenity: 'hospital' };
|
||||
expect(_ruleChecks.positiveRegex(positiveRegex)(tags)).to.be.true;
|
||||
});
|
||||
it ('is false when tag value does not match negative regex', function() {
|
||||
it('is false when tag value does not match negative regex', function() {
|
||||
var tags = { amenity: 'school' };
|
||||
expect(_ruleChecks.positiveRegex(positiveRegex)(tags)).to.be.false;
|
||||
});
|
||||
});
|
||||
describe('negativeRegex', function() {
|
||||
var negativeRegex = { bicycle: [ 'use_path', 'designated' ] };
|
||||
it ('is true when tag value does not match negativeRegex', function() {
|
||||
it('is true when tag value does not match negativeRegex', function() {
|
||||
var tags = { bicycle: 'yes' };
|
||||
expect(_ruleChecks.negativeRegex(negativeRegex)(tags)).to.be.true;
|
||||
});
|
||||
it ('is false when tag value matches negativeRegex', function() {
|
||||
it('is false when tag value matches negativeRegex', function() {
|
||||
var tags = { bicycle: 'designated' };
|
||||
expect(_ruleChecks.negativeRegex(negativeRegex)(tags)).to.be.false;
|
||||
});
|
||||
@@ -450,7 +450,7 @@ describe('maprules', function() {
|
||||
expect(rule.matches(entities[i])).to.be.true;
|
||||
});
|
||||
});
|
||||
it ('is true when at least one rule check is \'false\'', function() {
|
||||
it('is true when at least one rule check is \'false\'', function() {
|
||||
var selector = {
|
||||
geometry: 'way',
|
||||
equals: { highway: 'residential' },
|
||||
|
||||
Reference in New Issue
Block a user