Modularize iD.core

This commit is contained in:
Kushan Joshi
2016-06-16 01:53:20 +05:30
parent 2db0f636b1
commit 59e6581aa5
15 changed files with 2398 additions and 130 deletions

View File

@@ -49,7 +49,11 @@ MODULE_TARGETS = \
js/lib/id/util.js \
js/lib/id/validations.js \
js/lib/id/geo.js \
js/lib/id/operations.js
js/lib/id/operations.js \
js/lib/id/core.js
js/lib/id/core.js: modules/
node_modules/.bin/rollup -f umd -n iD modules/core/index.js --no-strict > $@
js/lib/id/actions.js: modules/
node_modules/.bin/rollup -f umd -n iD.actions modules/actions/index.js --no-strict > $@
@@ -115,16 +119,6 @@ dist/iD.js: \
js/id/behavior/paste.js \
js/id/behavior/select.js \
js/id/behavior/tail.js \
js/id/core/connection.js \
js/id/core/difference.js \
js/id/core/entity.js \
js/id/core/graph.js \
js/id/core/history.js \
js/id/core/node.js \
js/id/core/relation.js \
js/id/core/tags.js \
js/id/core/tree.js \
js/id/core/way.js \
js/id/renderer/background.js \
js/id/renderer/background_source.js \
js/id/renderer/features.js \

View File

@@ -34,6 +34,7 @@
<script src='js/lib/marked.js'></script>
<script src='js/id/id.js'></script>
<script src='js/id/id/core.js'></script>
<script src='js/lib/id/actions.js'></script>
<script src='js/lib/id/modes.js'></script>
<script src='js/lib/id/presets.js'></script>
@@ -159,17 +160,6 @@
<script src='js/id/behavior/select.js'></script>
<script src='js/id/behavior/tail.js'></script>
<script src='js/id/core/connection.js'></script>
<script src='js/id/core/difference.js'></script>
<script src='js/id/core/entity.js'></script>
<script src='js/id/core/graph.js'></script>
<script src='js/id/core/history.js'></script>
<script src='js/id/core/node.js'></script>
<script src='js/id/core/relation.js'></script>
<script src='js/id/core/way.js'></script>
<script src='js/id/core/tree.js'></script>
<script src='js/id/core/tags.js'></script>
<script src='js/lib/locale.js'></script>
<script src='data/introGraph.js'></script>
</head>

2259
js/lib/id/core.js Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,9 @@
iD.Connection = function(useHttps) {
import { Entity } from './entity';
import { Way } from './way';
import { Relation } from './relation';
import { Node } from './node';
export function Connection(useHttps) {
if (typeof useHttps !== 'boolean') {
useHttps = window.location.protocol === 'https:';
}
@@ -55,8 +60,8 @@ iD.Connection = function(useHttps) {
};
connection.loadEntity = function(id, callback) {
var type = iD.Entity.id.type(id),
osmID = iD.Entity.id.toOSM(id);
var type = Entity.id.type(id),
osmID = Entity.id.toOSM(id);
connection.loadFromURL(
url + '/api/0.6/' + type + '/' + osmID + (type !== 'node' ? '/full' : ''),
@@ -66,8 +71,8 @@ iD.Connection = function(useHttps) {
};
connection.loadEntityVersion = function(id, version, callback) {
var type = iD.Entity.id.type(id),
osmID = iD.Entity.id.toOSM(id);
var type = Entity.id.type(id),
osmID = Entity.id.toOSM(id);
connection.loadFromURL(
url + '/api/0.6/' + type + '/' + osmID + '/' + version,
@@ -77,9 +82,9 @@ iD.Connection = function(useHttps) {
};
connection.loadMultiple = function(ids, callback) {
_.each(_.groupBy(_.uniq(ids), iD.Entity.id.type), function(v, k) {
_.each(_.groupBy(_.uniq(ids), Entity.id.type), function(v, k) {
var type = k + 's',
osmIDs = _.map(v, iD.Entity.id.toOSM);
osmIDs = _.map(v, Entity.id.toOSM);
_.each(_.chunk(osmIDs, 150), function(arr) {
connection.loadFromURL(
@@ -145,8 +150,8 @@ iD.Connection = function(useHttps) {
var parsers = {
node: function nodeData(obj) {
var attrs = obj.attributes;
return new iD.Node({
id: iD.Entity.id.fromOSM(nodeStr, attrs.id.value),
return new Node({
id: Entity.id.fromOSM(nodeStr, attrs.id.value),
loc: getLoc(attrs),
version: attrs.version.value,
user: attrs.user && attrs.user.value,
@@ -157,8 +162,8 @@ iD.Connection = function(useHttps) {
way: function wayData(obj) {
var attrs = obj.attributes;
return new iD.Way({
id: iD.Entity.id.fromOSM(wayStr, attrs.id.value),
return new Way({
id: Entity.id.fromOSM(wayStr, attrs.id.value),
version: attrs.version.value,
user: attrs.user && attrs.user.value,
tags: getTags(obj),
@@ -169,8 +174,8 @@ iD.Connection = function(useHttps) {
relation: function relationData(obj) {
var attrs = obj.attributes;
return new iD.Relation({
id: iD.Entity.id.fromOSM(relationStr, attrs.id.value),
return new Relation({
id: Entity.id.fromOSM(relationStr, attrs.id.value),
version: attrs.version.value,
user: attrs.user && attrs.user.value,
tags: getTags(obj),
@@ -466,4 +471,4 @@ iD.Connection = function(useHttps) {
};
return d3.rebind(connection, event, 'on');
};
}

View File

@@ -6,7 +6,7 @@
of entities that will require a redraw, taking into account
child and parent relationships.
*/
iD.Difference = function(base, head) {
export function Difference(base, head) {
var changes = {}, length = 0;
function changed(h, b) {
@@ -173,4 +173,4 @@ iD.Difference = function(base, head) {
};
return difference;
};
}

View File

@@ -1,42 +1,44 @@
iD.Entity = function(attrs) {
import { interestingTag } from './tags';
export function Entity(attrs) {
// For prototypal inheritance.
if (this instanceof iD.Entity) return;
if (this instanceof Entity) return;
// Create the appropriate subtype.
if (attrs && attrs.type) {
return iD.Entity[attrs.type].apply(this, arguments);
return Entity[attrs.type].apply(this, arguments);
} else if (attrs && attrs.id) {
return iD.Entity[iD.Entity.id.type(attrs.id)].apply(this, arguments);
return Entity[Entity.id.type(attrs.id)].apply(this, arguments);
}
// Initialize a generic Entity (used only in tests).
return (new iD.Entity()).initialize(arguments);
return (new Entity()).initialize(arguments);
}
Entity.id = function(type) {
return Entity.id.fromOSM(type, Entity.id.next[type]--);
};
iD.Entity.id = function(type) {
return iD.Entity.id.fromOSM(type, iD.Entity.id.next[type]--);
};
Entity.id.next = {node: -1, way: -1, relation: -1};
iD.Entity.id.next = {node: -1, way: -1, relation: -1};
iD.Entity.id.fromOSM = function(type, id) {
Entity.id.fromOSM = function(type, id) {
return type[0] + id;
};
iD.Entity.id.toOSM = function(id) {
Entity.id.toOSM = function(id) {
return id.slice(1);
};
iD.Entity.id.type = function(id) {
Entity.id.type = function(id) {
return {'n': 'node', 'w': 'way', 'r': 'relation'}[id[0]];
};
// A function suitable for use as the second argument to d3.selection#data().
iD.Entity.key = function(entity) {
Entity.key = function(entity) {
return entity.id + 'v' + (entity.v || 0);
};
iD.Entity.prototype = {
Entity.prototype = {
tags: {},
initialize: function(sources) {
@@ -54,7 +56,7 @@ iD.Entity.prototype = {
}
if (!this.id && this.type) {
this.id = iD.Entity.id(this.type);
this.id = Entity.id(this.type);
}
if (!this.hasOwnProperty('visible')) {
this.visible = true;
@@ -76,14 +78,14 @@ iD.Entity.prototype = {
if (copies[this.id])
return copies[this.id];
var copy = iD.Entity(this, {id: undefined, user: undefined, version: undefined});
var copy = Entity(this, {id: undefined, user: undefined, version: undefined});
copies[this.id] = copy;
return copy;
},
osmId: function() {
return iD.Entity.id.toOSM(this.id);
return Entity.id.toOSM(this.id);
},
isNew: function() {
@@ -91,7 +93,7 @@ iD.Entity.prototype = {
},
update: function(attrs) {
return iD.Entity(this, attrs, {v: 1 + (this.v || 0)});
return Entity(this, attrs, {v: 1 + (this.v || 0)});
},
mergeTags: function(tags) {
@@ -120,7 +122,7 @@ iD.Entity.prototype = {
},
hasInterestingTags: function() {
return _.keys(this.tags).some(iD.interestingTag);
return _.keys(this.tags).some(interestingTag);
},
isHighwayIntersection: function() {

View File

@@ -1,7 +1,7 @@
iD.Graph = function(other, mutable) {
if (!(this instanceof iD.Graph)) return new iD.Graph(other, mutable);
export function Graph(other, mutable) {
if (!(this instanceof Graph)) return new Graph(other, mutable);
if (other instanceof iD.Graph) {
if (other instanceof Graph) {
var base = other.base();
this.entities = _.assign(Object.create(base.entities), other.entities);
this._parentWays = _.assign(Object.create(base.parentWays), other._parentWays);
@@ -17,9 +17,9 @@ iD.Graph = function(other, mutable) {
this.transients = {};
this._childNodes = {};
this.frozen = !mutable;
};
}
iD.Graph.prototype = {
Graph.prototype = {
hasEntity: function(id) {
return this.entities[id];
},
@@ -263,7 +263,7 @@ iD.Graph.prototype = {
},
update: function() {
var graph = this.frozen ? iD.Graph(this, true) : this;
var graph = this.frozen ? Graph(this, true) : this;
for (var i = 0; i < arguments.length; i++) {
arguments[i].call(graph, graph);

View File

@@ -1,4 +1,9 @@
iD.History = function(context) {
import { Entity } from './entity';
import { Graph } from './graph';
import { Difference } from './difference';
import { Tree } from './tree';
export function History(context) {
var stack, index, tree,
imageryUsed = ['Bing'],
dispatch = d3.dispatch('change', 'undone', 'redone'),
@@ -26,7 +31,7 @@ iD.History = function(context) {
}
function change(previous) {
var difference = iD.Difference(previous, history.graph());
var difference = Difference(previous, history.graph());
dispatch.change(difference);
return difference;
}
@@ -144,7 +149,7 @@ iD.History = function(context) {
difference: function() {
var base = stack[0].graph,
head = stack[index].graph;
return iD.Difference(base, head);
return Difference(base, head);
},
changes: function(action) {
@@ -155,7 +160,7 @@ iD.History = function(context) {
head = action(head);
}
var difference = iD.Difference(base, head);
var difference = Difference(base, head);
return {
modified: difference.modified(),
@@ -190,9 +195,9 @@ iD.History = function(context) {
},
reset: function() {
stack = [{graph: iD.Graph()}];
stack = [{graph: Graph()}];
index = 0;
tree = iD.Tree(stack[0].graph);
tree = Tree(stack[0].graph);
dispatch.change();
return history;
},
@@ -209,7 +214,7 @@ iD.History = function(context) {
_.forEach(i.graph.entities, function(entity, id) {
if (entity) {
var key = iD.Entity.key(entity);
var key = Entity.key(entity);
allEntities[key] = entity;
modified.push(key);
} else {
@@ -244,7 +249,7 @@ iD.History = function(context) {
entities: _.values(allEntities),
baseEntities: _.values(baseEntities),
stack: s,
nextIDs: iD.Entity.id.next,
nextIDs: Entity.id.next,
index: index
});
},
@@ -253,21 +258,21 @@ iD.History = function(context) {
var h = JSON.parse(json),
loadComplete = true;
iD.Entity.id.next = h.nextIDs;
Entity.id.next = h.nextIDs;
index = h.index;
if (h.version === 2 || h.version === 3) {
var allEntities = {};
h.entities.forEach(function(entity) {
allEntities[iD.Entity.key(entity)] = iD.Entity(entity);
allEntities[Entity.key(entity)] = Entity(entity);
});
if (h.version === 3) {
// This merges originals for changed entities into the base of
// the stack even if the current stack doesn't have them (for
// example when iD has been restarted in a different region)
var baseEntities = h.baseEntities.map(function(d) { return iD.Entity(d); });
var baseEntities = h.baseEntities.map(function(d) { return Entity(d); });
stack[0].graph.rebase(baseEntities, _.map(stack, 'graph'), true);
tree.rebase(baseEntities, true);
@@ -334,7 +339,7 @@ iD.History = function(context) {
}
return {
graph: iD.Graph(stack[0].graph).load(entities),
graph: Graph(stack[0].graph).load(entities),
annotation: d.annotation,
imageryUsed: d.imageryUsed
};
@@ -346,10 +351,10 @@ iD.History = function(context) {
for (var i in d.entities) {
var entity = d.entities[i];
entities[i] = entity === 'undefined' ? undefined : iD.Entity(entity);
entities[i] = entity === 'undefined' ? undefined : Entity(entity);
}
d.graph = iD.Graph(stack[0].graph).load(entities);
d.graph = Graph(stack[0].graph).load(entities);
return d;
});
}
@@ -401,4 +406,4 @@ iD.History = function(context) {
history.reset();
return d3.rebind(history, dispatch, 'on');
};
}

10
modules/core/index.js Normal file
View File

@@ -0,0 +1,10 @@
export { Connection } from './connection';
export { Difference } from './difference';
export { Entity } from './entity';
export { Graph } from './graph';
export { History } from './history';
export { Node } from './node';
export { Relation } from './relation';
export { oneWayTags, pavedTags, interestingTag } from './tags';
export { Tree } from './tree';
export { Way } from './way';

View File

@@ -1,14 +1,18 @@
iD.Node = iD.Entity.node = function iD_Node() {
if (!(this instanceof iD_Node)) {
return (new iD_Node()).initialize(arguments);
// iD.Node = iD.Entity.node;
import { Entity } from './entity';
export function Node() {
if (!(this instanceof Node)) {
return (new Node()).initialize(arguments);
} else if (arguments.length) {
this.initialize(arguments);
}
};
}
iD.Node.prototype = Object.create(iD.Entity.prototype);
Entity.node = Node;
_.extend(iD.Node.prototype, {
Node.prototype = Object.create(Entity.prototype);
_.extend(Node.prototype, {
type: 'node',
extent: function() {

View File

@@ -1,22 +1,25 @@
iD.Relation = iD.Entity.relation = function iD_Relation() {
if (!(this instanceof iD_Relation)) {
return (new iD_Relation()).initialize(arguments);
import { Entity } from './entity';
export function Relation() {
if (!(this instanceof Relation)) {
return (new Relation()).initialize(arguments);
} else if (arguments.length) {
this.initialize(arguments);
}
};
}
Entity.relation = Relation;
iD.Relation.prototype = Object.create(iD.Entity.prototype);
Relation.prototype = Object.create(Entity.prototype);
iD.Relation.creationOrder = function(a, b) {
var aId = parseInt(iD.Entity.id.toOSM(a.id), 10);
var bId = parseInt(iD.Entity.id.toOSM(b.id), 10);
Relation.creationOrder = function(a, b) {
var aId = parseInt(Entity.id.toOSM(a.id), 10);
var bId = parseInt(Entity.id.toOSM(b.id), 10);
if (aId < 0 || bId < 0) return aId - bId;
return bId - aId;
};
_.extend(iD.Relation.prototype, {
_.extend(Relation.prototype, {
type: 'relation',
members: [],
@@ -24,7 +27,7 @@ _.extend(iD.Relation.prototype, {
if (copies[this.id])
return copies[this.id];
var copy = iD.Entity.prototype.copy.call(this, resolver, copies);
var copy = Entity.prototype.copy.call(this, resolver, copies);
var members = this.members.map(function(member) {
return _.extend({}, member, {id: resolver.entity(member.id).copy(resolver, copies).id});
@@ -154,7 +157,7 @@ _.extend(iD.Relation.prototype, {
'@id': this.osmId(),
'@version': this.version || 0,
member: _.map(this.members, function(member) {
return { keyAttributes: { type: member.type, role: member.role, ref: iD.Entity.id.toOSM(member.id) } };
return { keyAttributes: { type: member.type, role: member.role, ref: Entity.id.toOSM(member.id) } };
}),
tag: _.map(this.tags, function(v, k) {
return { keyAttributes: { k: k, v: v } };

View File

@@ -1,4 +1,13 @@
iD.oneWayTags = {
export function interestingTag(key) {
return key !== 'attribution' &&
key !== 'created_by' &&
key !== 'source' &&
key !== 'odbl' &&
key.indexOf('tiger:') !== 0;
}
export var oneWayTags = {
'aerialway': {
'chair_lift': true,
'mixed_lift': true,
@@ -30,7 +39,7 @@ iD.oneWayTags = {
}
};
iD.pavedTags = {
export var pavedTags = {
'surface': {
'paved': true,
'asphalt': true,
@@ -40,12 +49,3 @@ iD.pavedTags = {
'grade1': true
}
};
iD.interestingTag = function (key) {
return key !== 'attribution' &&
key !== 'created_by' &&
key !== 'source' &&
key !== 'odbl' &&
key.indexOf('tiger:') !== 0;
};

View File

@@ -1,4 +1,6 @@
iD.Tree = function(head) {
import { Difference } from './difference';
export function Tree(head) {
var rtree = rbush(),
rectangles = {};
@@ -59,7 +61,7 @@ iD.Tree = function(head) {
tree.intersects = function(extent, graph) {
if (graph !== head) {
var diff = iD.Difference(head, graph),
var diff = Difference(head, graph),
insertions = {};
head = graph;
@@ -88,4 +90,4 @@ iD.Tree = function(head) {
};
return tree;
};
}

View File

@@ -1,14 +1,18 @@
iD.Way = iD.Entity.way = function iD_Way() {
if (!(this instanceof iD_Way)) {
return (new iD_Way()).initialize(arguments);
import { Entity } from './entity';
import { oneWayTags } from './tags';
export function Way() {
if (!(this instanceof Way)) {
return (new Way()).initialize(arguments);
} else if (arguments.length) {
this.initialize(arguments);
}
};
}
iD.Way.prototype = Object.create(iD.Entity.prototype);
Entity.way = Way;
_.extend(iD.Way.prototype, {
Way.prototype = Object.create(Entity.prototype);
_.extend(Way.prototype, {
type: 'way',
nodes: [],
@@ -16,7 +20,7 @@ _.extend(iD.Way.prototype, {
if (copies[this.id])
return copies[this.id];
var copy = iD.Entity.prototype.copy.call(this, resolver, copies);
var copy = Entity.prototype.copy.call(this, resolver, copies);
var nodes = this.nodes.map(function(id) {
return resolver.entity(id).copy(resolver, copies).id;
@@ -88,7 +92,7 @@ _.extend(iD.Way.prototype, {
// implied oneway tag..
for (var key in this.tags) {
if (key in iD.oneWayTags && (this.tags[key] in iD.oneWayTags[key]))
if (key in oneWayTags && (this.tags[key] in oneWayTags[key]))
return true;
}
return false;
@@ -202,7 +206,7 @@ _.extend(iD.Way.prototype, {
'@id': this.osmId(),
'@version': this.version || 0,
nd: _.map(this.nodes, function(id) {
return { keyAttributes: { ref: iD.Entity.id.toOSM(id) } };
return { keyAttributes: { ref: Entity.id.toOSM(id) } };
}),
tag: _.map(this.tags, function(v, k) {
return { keyAttributes: { k: k, v: v } };

View File

@@ -41,6 +41,7 @@
<script src='../js/lib/osmauth.js'></script>
<script src='../js/id/id.js'></script>
<script src='../js/lib/id/core.js'></script>
<script src='../js/lib/id/actions.js'></script>
<script src='../js/lib/id/modes.js'></script>
<script src='../js/lib/id/presets.js'></script>
@@ -144,17 +145,6 @@
<script src='../js/id/behavior/select.js'></script>
<script src='../js/id/behavior/tail.js'></script>
<script src='../js/id/core/connection.js'></script>
<script src='../js/id/core/difference.js'></script>
<script src='../js/id/core/entity.js'></script>
<script src='../js/id/core/graph.js'></script>
<script src='../js/id/core/history.js'></script>
<script src='../js/id/core/node.js'></script>
<script src='../js/id/core/relation.js'></script>
<script src='../js/id/core/way.js'></script>
<script src='../js/id/core/tree.js'></script>
<script src='../js/id/core/tags.js'></script>
<script src='../js/lib/locale.js'></script>
<script src='../data/data_dev.js'></script>