diff --git a/modules/core/context.js b/modules/core/context.js index 3614504f9..12afad7b2 100644 --- a/modules/core/context.js +++ b/modules/core/context.js @@ -1,19 +1,47 @@ -import * as d3 from 'd3'; -import _ from 'lodash'; -import { t, currentLocale, addTranslation, setLocale } from '../util/locale'; +import _cloneDeep from 'lodash-es/cloneDeep'; +import _debounce from 'lodash-es/debounce'; +import _each from 'lodash-es/each'; +import _find from 'lodash-es/find'; +import _forOwn from 'lodash-es/forOwn'; +import _isObject from 'lodash-es/isObject'; +import _isString from 'lodash-es/isString'; + +import { dispatch as d3_dispatch } from 'd3-dispatch'; +import { json as d3_json } from 'd3-request'; +import { select as d3_select } from 'd3-selection'; + +import { + t, + currentLocale, + addTranslation, + setLocale +} from '../util/locale'; + import { coreHistory } from './history'; -import { dataLocales, dataEn } from '../../data/index'; + +import { + dataLocales, + dataEn +} from '../../data'; + import { geoRawMercator } from '../geo/raw_mercator'; import { modeSelect } from '../modes/select'; -import { presetIndex } from '../presets/index'; -import { rendererBackground } from '../renderer/background'; -import { rendererFeatures } from '../renderer/features'; -import { rendererMap } from '../renderer/map'; -import { services } from '../services/index'; +import { presetIndex } from '../presets'; + +import { + rendererBackground, + rendererFeatures, + rendererMap +} from '../renderer'; + +import { services } from '../services'; import { uiInit } from '../ui/init'; import { utilDetect } from '../util/detect'; -import { utilRebind } from '../util/rebind'; -import { utilCallWhenIdle } from '../util/index'; + +import { + utilCallWhenIdle, + utilRebind +} from '../util'; export var areaKeys = {}; @@ -28,26 +56,26 @@ export function coreContext() { context.version = '2.4.1'; // create a special translation that contains the keys in place of the strings - var tkeys = _.cloneDeep(dataEn); + var tkeys = _cloneDeep(dataEn); var parents = []; function traverser(v, k, obj) { parents.push(k); - if (_.isObject(v)) { - _.forOwn(v, traverser); - } else if (_.isString(v)) { + if (_isObject(v)) { + _forOwn(v, traverser); + } else if (_isString(v)) { obj[k] = parents.join('.'); } parents.pop(); } - _.forOwn(tkeys, traverser); + _forOwn(tkeys, traverser); addTranslation('_tkeys_', tkeys); addTranslation('en', dataEn); setLocale('en'); - var dispatch = d3.dispatch('enter', 'exit', 'change'); + var dispatch = d3_dispatch('enter', 'exit', 'change'); // https://github.com/openstreetmap/iD/issues/772 // http://mathiasbynens.be/notes/localstorage-pattern#comment-9 @@ -119,7 +147,7 @@ export function coreContext() { if (zoomTo !== false) { this.loadEntity(id, function(err, result) { if (err) return; - var entity = _.find(result.data, function(e) { return e.id === id; }); + var entity = _find(result.data, function(e) { return e.id === id; }); if (entity) { map.zoomTo(entity); } }); } @@ -160,7 +188,7 @@ export function coreContext() { context.save = function() { // no history save, no message onbeforeunload - if (inIntro || d3.select('.modal').size()) return; + if (inIntro || d3_select('.modal').size()) return; var canSave; if (mode && mode.id === 'save') { @@ -295,7 +323,7 @@ export function coreContext() { /* Container */ - var container = d3.select(document.body); + var container = d3_select(document.body); context.container = function(_) { if (!arguments.length) return container; container = _; @@ -350,7 +378,7 @@ export function coreContext() { context.loadLocale = function(callback) { if (locale && locale !== 'en' && dataLocales.hasOwnProperty(locale)) { localePath = localePath || context.asset('locales/' + locale + '.json'); - d3.json(localePath, function(err, result) { + d3_json(localePath, function(err, result) { if (!err) { addTranslation(locale, result[locale]); setLocale(locale); @@ -375,7 +403,7 @@ export function coreContext() { /* reset (aka flush) */ context.reset = context.flush = function() { context.debouncedSave.cancel(); - _.each(services, function(service) { + _each(services, function(service) { if (service && typeof service.reset === 'function') { service.reset(context); } @@ -403,7 +431,7 @@ export function coreContext() { // Debounce save, since it's a synchronous localStorage write, // and history changes can happen frequently (e.g. when dragging). - context.debouncedSave = _.debounce(context.save, 350); + context.debouncedSave = _debounce(context.save, 350); function withDebouncedSave(fn) { return function() { var result = fn.apply(history, arguments); @@ -436,7 +464,7 @@ export function coreContext() { context.zoomOutFurther = map.zoomOutFurther; context.redrawEnable = map.redrawEnable; - _.each(services, function(service) { + _each(services, function(service) { if (service && typeof service.init === 'function') { service.init(context); } diff --git a/modules/core/difference.js b/modules/core/difference.js index cffe3afac..1806de12c 100644 --- a/modules/core/difference.js +++ b/modules/core/difference.js @@ -1,5 +1,8 @@ -import * as d3 from 'd3'; -import _ from 'lodash'; +import _difference from 'lodash-es/difference'; +import _each from 'lodash-es/each'; +import _omit from 'lodash-es/omit'; +import _isEqual from 'lodash-es/isEqual'; +import _values from 'lodash-es/values'; /* @@ -17,11 +20,11 @@ export function coreDifference(base, head) { function changed(h, b) { - return h !== b && !_.isEqual(_.omit(h, 'v'), _.omit(b, 'v')); + return h !== b && !_isEqual(_omit(h, 'v'), _omit(b, 'v')); } - _.each(head.entities, function(h, id) { + _each(head.entities, function(h, id) { var b = base.entities[id]; if (changed(h, b)) { changes[id] = {base: b, head: h}; @@ -30,7 +33,7 @@ export function coreDifference(base, head) { }); - _.each(base.entities, function(b, id) { + _each(base.entities, function(b, id) { var h = head.entities[id]; if (!changes[id] && changed(h, b)) { changes[id] = {base: b, head: h}; @@ -64,7 +67,7 @@ export function coreDifference(base, head) { difference.extantIDs = function() { var result = []; - _.each(changes, function(change, id) { + _each(changes, function(change, id) { if (change.head) result.push(id); }); return result; @@ -73,7 +76,7 @@ export function coreDifference(base, head) { difference.modified = function() { var result = []; - _.each(changes, function(change) { + _each(changes, function(change) { if (change.base && change.head) result.push(change.head); }); return result; @@ -82,7 +85,7 @@ export function coreDifference(base, head) { difference.created = function() { var result = []; - _.each(changes, function(change) { + _each(changes, function(change) { if (!change.base && change.head) result.push(change.head); }); return result; @@ -91,7 +94,7 @@ export function coreDifference(base, head) { difference.deleted = function() { var result = []; - _.each(changes, function(change) { + _each(changes, function(change) { if (change.base && !change.head) result.push(change.base); }); return result; @@ -117,7 +120,7 @@ export function coreDifference(base, head) { } } - _.each(changes, function(change) { + _each(changes, function(change) { if (change.head && change.head.geometry(head) !== 'vertex') { addEntity(change.head, head, change.base ? 'modified' : 'created'); @@ -125,8 +128,8 @@ export function coreDifference(base, head) { addEntity(change.base, base, 'deleted'); } else if (change.base && change.head) { // modified vertex - var moved = !_.isEqual(change.base.loc, change.head.loc), - retagged = !_.isEqual(change.base.tags, change.head.tags); + var moved = !_isEqual(change.base.loc, change.head.loc), + retagged = !_isEqual(change.base.tags, change.head.tags); if (moved) { addParents(change.head); @@ -144,7 +147,7 @@ export function coreDifference(base, head) { } }); - return d3.values(relevant); + return _values(relevant); }; @@ -170,12 +173,12 @@ export function coreDifference(base, head) { nb = b ? b.nodes : [], diff, i; - diff = _.difference(nh, nb); + diff = _difference(nh, nb); for (i = 0; i < diff.length; i++) { result[diff[i]] = head.hasEntity(diff[i]); } - diff = _.difference(nb, nh); + diff = _difference(nb, nh); for (i = 0; i < diff.length; i++) { result[diff[i]] = head.hasEntity(diff[i]); } diff --git a/modules/core/graph.js b/modules/core/graph.js index 19897b520..bfe2c1cf2 100644 --- a/modules/core/graph.js +++ b/modules/core/graph.js @@ -1,6 +1,10 @@ -import _ from 'lodash'; +import _assign from 'lodash-es/assign'; +import _difference from 'lodash-es/difference'; +import _includes from 'lodash-es/includes'; +import _without from 'lodash-es/without'; + import { debug } from '../index'; -import { utilGetPrototypeOf } from '../util/index'; +import { utilGetPrototypeOf } from '../util'; export function coreGraph(other, mutable) { @@ -8,9 +12,9 @@ export function coreGraph(other, mutable) { if (other instanceof coreGraph) { var base = other.base(); - this.entities = _.assign(Object.create(base.entities), other.entities); - this._parentWays = _.assign(Object.create(base.parentWays), other._parentWays); - this._parentRels = _.assign(Object.create(base.parentRels), other._parentRels); + this.entities = _assign(Object.create(base.entities), other.entities); + this._parentWays = _assign(Object.create(base.parentWays), other._parentWays); + this._parentRels = _assign(Object.create(base.parentRels), other._parentRels); } else { this.entities = Object.create({}); @@ -173,7 +177,7 @@ coreGraph.prototype = { if (base.parentWays[child]) { for (k = 0; k < base.parentWays[child].length; k++) { id = base.parentWays[child][k]; - if (!this.entities.hasOwnProperty(id) && !_.includes(this._parentWays[child], id)) { + if (!this.entities.hasOwnProperty(id) && !_includes(this._parentWays[child], id)) { this._parentWays[child].push(id); } } @@ -186,7 +190,7 @@ coreGraph.prototype = { if (base.parentRels[child]) { for (k = 0; k < base.parentRels[child].length; k++) { id = base.parentRels[child][k]; - if (!this.entities.hasOwnProperty(id) && !_.includes(this._parentRels[child], id)) { + if (!this.entities.hasOwnProperty(id) && !_includes(this._parentRels[child], id)) { this._parentRels[child].push(id); } } @@ -214,8 +218,8 @@ coreGraph.prototype = { // Update parentWays if (oldentity && entity) { - removed = _.difference(oldentity.nodes, entity.nodes); - added = _.difference(entity.nodes, oldentity.nodes); + removed = _difference(oldentity.nodes, entity.nodes); + added = _difference(entity.nodes, oldentity.nodes); } else if (oldentity) { removed = oldentity.nodes; added = []; @@ -224,10 +228,10 @@ coreGraph.prototype = { added = entity.nodes; } for (i = 0; i < removed.length; i++) { - parentWays[removed[i]] = _.without(parentWays[removed[i]], oldentity.id); + parentWays[removed[i]] = _without(parentWays[removed[i]], oldentity.id); } for (i = 0; i < added.length; i++) { - ways = _.without(parentWays[added[i]], entity.id); + ways = _without(parentWays[added[i]], entity.id); ways.push(entity.id); parentWays[added[i]] = ways; } @@ -236,8 +240,8 @@ coreGraph.prototype = { // Update parentRels if (oldentity && entity) { - removed = _.difference(oldentity.members, entity.members); - added = _.difference(entity.members, oldentity); + removed = _difference(oldentity.members, entity.members); + added = _difference(entity.members, oldentity); } else if (oldentity) { removed = oldentity.members; added = []; @@ -246,10 +250,10 @@ coreGraph.prototype = { added = entity.members; } for (i = 0; i < removed.length; i++) { - parentRels[removed[i].id] = _.without(parentRels[removed[i].id], oldentity.id); + parentRels[removed[i].id] = _without(parentRels[removed[i].id], oldentity.id); } for (i = 0; i < added.length; i++) { - rels = _.without(parentRels[added[i].id], entity.id); + rels = _without(parentRels[added[i].id], entity.id); rels.push(entity.id); parentRels[added[i].id] = rels; } diff --git a/modules/core/history.js b/modules/core/history.js index 7c69eaa76..47d9f3f49 100644 --- a/modules/core/history.js +++ b/modules/core/history.js @@ -1,18 +1,39 @@ -import * as d3 from 'd3'; -import _ from 'lodash'; +import _cloneDeep from 'lodash-es/cloneDeep'; +import _cloneDeepWith from 'lodash-es/cloneDeepWith'; +import _difference from 'lodash-es/difference'; +import _filter from 'lodash-es/filter'; +import _flatten from 'lodash-es/flatten'; +import _groupBy from 'lodash-es/groupBy'; +import _isFunction from 'lodash-es/isFunction'; +import _isEmpty from 'lodash-es/isEmpty'; +import _forEach from 'lodash-es/forEach'; +import _map from 'lodash-es/map'; +import _omit from 'lodash-es/omit'; +import _reject from 'lodash-es/reject'; +import _values from 'lodash-es/values'; +import _without from 'lodash-es/without'; +import _uniq from 'lodash-es/uniq'; + +import { dispatch as d3_dispatch } from 'd3-dispatch'; +import { easeLinear as d3_easeLinear } from 'd3-ease'; +import { select as d3_select } from 'd3-selection'; + import * as Validations from '../validations/index'; import { coreDifference } from './difference'; import { coreGraph } from './graph'; import { coreTree } from './tree'; import { osmEntity } from '../osm/entity'; -import { uiLoading } from '../ui/index'; -import { utilSessionMutex } from '../util/index'; -import { utilRebind } from '../util/rebind'; +import { uiLoading } from '../ui'; + +import { + utilRebind, + utilSessionMutex +} from '../util'; export function coreHistory(context) { var imageryUsed = ['Bing'], - dispatch = d3.dispatch('change', 'undone', 'redone'), + dispatch = d3_dispatch('change', 'undone', 'redone'), lock = utilSessionMutex('lock'), duration = 150, checkpoints = {}, @@ -25,7 +46,7 @@ export function coreHistory(context) { var annotation; - if (!_.isFunction(_.last(actions))) { + if (!_isFunction(actions[actions.length - 1])) { annotation = actions.pop(); } @@ -105,7 +126,7 @@ export function coreHistory(context) { merge: function(entities, extent) { - stack[0].graph.rebase(entities, _.map(stack, 'graph'), false); + stack[0].graph.rebase(entities, _map(stack, 'graph'), false); tree.rebase(entities, false); dispatch.call('change', this, undefined, extent); @@ -114,22 +135,22 @@ export function coreHistory(context) { perform: function() { // complete any transition already in progress - d3.select(document).interrupt('history.perform'); + d3_select(document).interrupt('history.perform'); var transitionable = false, action0 = arguments[0]; if (arguments.length === 1 || - arguments.length === 2 && !_.isFunction(arguments[1])) { + arguments.length === 2 && !_isFunction(arguments[1])) { transitionable = !!action0.transitionable; } if (transitionable) { var origArguments = arguments; - d3.select(document) + d3_select(document) .transition('history.perform') .duration(duration) - .ease(d3.easeLinear) + .ease(d3_easeLinear) .tween('history.tween', function() { return function(t) { if (t < 1) _overwrite([action0], t); @@ -149,20 +170,20 @@ export function coreHistory(context) { replace: function() { - d3.select(document).interrupt('history.perform'); + d3_select(document).interrupt('history.perform'); return _replace(arguments, 1); }, // Same as calling pop and then perform overwrite: function() { - d3.select(document).interrupt('history.perform'); + d3_select(document).interrupt('history.perform'); return _overwrite(arguments, 1); }, pop: function(n) { - d3.select(document).interrupt('history.perform'); + d3_select(document).interrupt('history.perform'); var previous = stack[index].graph; if (isNaN(+n) || +n < 0) { @@ -178,7 +199,7 @@ export function coreHistory(context) { // Back to the previous annotated state or index = 0. undo: function() { - d3.select(document).interrupt('history.perform'); + d3_select(document).interrupt('history.perform'); var previous = stack[index].graph; while (index > 0) { @@ -193,7 +214,7 @@ export function coreHistory(context) { // Forward to the next annotated state. redo: function() { - d3.select(document).interrupt('history.perform'); + d3_select(document).interrupt('history.perform'); var previous = stack[index].graph; var tryIndex = index; @@ -259,10 +280,9 @@ export function coreHistory(context) { validate: function(changes) { - return _(Validations) - .map(function(fn) { return fn()(changes, stack[index].graph); }) - .flatten() - .value(); + return _flatten( + _map(Validations, function(fn) { return fn()(changes, stack[index].graph); }) + ); }, @@ -276,12 +296,8 @@ export function coreHistory(context) { imageryUsed = sources; return history; } else { - return _(stack.slice(1, index + 1)) - .map('imageryUsed') - .flatten() - .uniq() - .without(undefined, 'Custom') - .value(); + var arr = _map(stack.slice(1, index + 1), 'imageryUsed'); + return _without(_uniq(_flatten(arr)), 'Custom'); } }, @@ -289,7 +305,7 @@ export function coreHistory(context) { // save the current history state checkpoint: function(key) { checkpoints[key] = { - stack: _.cloneDeep(stack), + stack: _cloneDeep(stack), index: index }; return history; @@ -299,7 +315,7 @@ export function coreHistory(context) { // restore history state to a given checkpoint or reset completely reset: function(key) { if (key !== undefined && checkpoints.hasOwnProperty(key)) { - stack = _.cloneDeep(checkpoints[key].stack); + stack = _cloneDeep(checkpoints[key].stack); index = checkpoints[key].index; } else { stack = [{graph: coreGraph()}]; @@ -319,15 +335,15 @@ export function coreHistory(context) { baseEntities = {}; // clone base entities.. - _.forEach(graph.base().entities, function(entity) { - var copy = _.cloneDeepWith(entity, customizer); + _forEach(graph.base().entities, function(entity) { + var copy = _cloneDeepWith(entity, customizer); baseEntities[copy.id] = copy; }); // replace base entities with head entities.. - _.forEach(graph.entities, function(entity, id) { + _forEach(graph.entities, function(entity, id) { if (entity) { - var copy = _.cloneDeepWith(entity, customizer); + var copy = _cloneDeepWith(entity, customizer); baseEntities[copy.id] = copy; } else { delete baseEntities[id]; @@ -335,7 +351,7 @@ export function coreHistory(context) { }); // swap temporary for permanent ids.. - _.forEach(baseEntities, function(entity) { + _forEach(baseEntities, function(entity) { if (Array.isArray(entity.nodes)) { entity.nodes = entity.nodes.map(function(node) { return permIds[node] || node; @@ -353,8 +369,8 @@ export function coreHistory(context) { function customizer(src) { - var copy = _.omit(_.cloneDeep(src), ['type', 'user', 'v', 'version', 'visible']); - if (_.isEmpty(copy.tags)) { + var copy = _omit(_cloneDeep(src), ['type', 'user', 'v', 'version', 'visible']); + if (_isEmpty(copy.tags)) { delete copy.tags; } @@ -386,7 +402,7 @@ export function coreHistory(context) { var s = stack.map(function(i) { var modified = [], deleted = []; - _.forEach(i.graph.entities, function(entity, id) { + _forEach(i.graph.entities, function(entity, id) { if (entity) { var key = osmEntity.key(entity); allEntities[key] = entity; @@ -401,7 +417,7 @@ export function coreHistory(context) { baseEntities[id] = base.graph.entities[id]; } // get originals of parent entities too - _.forEach(base.graph._parentWays[id], function(parentId) { + _forEach(base.graph._parentWays[id], function(parentId) { if (parentId in base.graph.entities) { baseEntities[parentId] = base.graph.entities[parentId]; } @@ -420,8 +436,8 @@ export function coreHistory(context) { return JSON.stringify({ version: 3, - entities: _.values(allEntities), - baseEntities: _.values(baseEntities), + entities: _values(allEntities), + baseEntities: _values(baseEntities), stack: s, nextIDs: osmEntity.id.next, index: index @@ -448,22 +464,17 @@ export function coreHistory(context) { // 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 osmEntity(d); }); - stack[0].graph.rebase(baseEntities, _.map(stack, 'graph'), true); + stack[0].graph.rebase(baseEntities, _map(stack, 'graph'), true); tree.rebase(baseEntities, true); // When we restore a modified way, we also need to fetch any missing // childnodes that would normally have been downloaded with it.. #2142 if (loadChildNodes) { var osm = context.connection(); - var missing = _(baseEntities) - .filter({ type: 'way' }) - .map('nodes') - .flatten() - .uniq() - .reject(function(n) { return stack[0].graph.hasEntity(n); }) - .value(); + var nodes = _flatten(_uniq(_map(_filter(baseEntities, { type: 'way' }), 'nodes'))); + var missing = _reject(nodes, function(n) { return stack[0].graph.hasEntity(n); }); - if (!_.isEmpty(missing) && osm) { + if (!_isEmpty(missing) && osm) { loadComplete = false; context.redrawEnable(false); @@ -472,20 +483,20 @@ export function coreHistory(context) { var childNodesLoaded = function(err, result) { if (!err) { - var visible = _.groupBy(result.data, 'visible'); - if (!_.isEmpty(visible.true)) { - missing = _.difference(missing, _.map(visible.true, 'id')); - stack[0].graph.rebase(visible.true, _.map(stack, 'graph'), true); + var visible = _groupBy(result.data, 'visible'); + if (!_isEmpty(visible.true)) { + missing = _difference(missing, _map(visible.true, 'id')); + stack[0].graph.rebase(visible.true, _map(stack, 'graph'), true); tree.rebase(visible.true, true); } // fetch older versions of nodes that were deleted.. - _.each(visible.false, function(entity) { + _forEach(visible.false, function(entity) { osm.loadEntityVersion(entity.id, +entity.version - 1, childNodesLoaded); }); } - if (err || _.isEmpty(missing)) { + if (err || _isEmpty(missing)) { loading.close(); context.redrawEnable(true); dispatch.call('change'); diff --git a/modules/core/tree.js b/modules/core/tree.js index 24decfdf6..839f51125 100644 --- a/modules/core/tree.js +++ b/modules/core/tree.js @@ -1,7 +1,8 @@ -import _ from 'lodash'; -import { coreDifference } from './difference'; +import _map from 'lodash-es/map'; import rbush from 'rbush'; +import { coreDifference } from './difference'; + export function coreTree(head) { var rtree = rbush(), @@ -59,7 +60,7 @@ export function coreTree(head) { updateParents(entity, insertions, {}); } - rtree.load(_.map(insertions, entityBBox)); + rtree.load(_map(insertions, entityBBox)); return tree; }; @@ -87,7 +88,7 @@ export function coreTree(head) { insertions[entity.id] = entity; }); - rtree.load(_.map(insertions, entityBBox)); + rtree.load(_map(insertions, entityBBox)); } return rtree.search(extent.bbox()).map(function(bbox) {