mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-14 09:42:56 +00:00
410 lines
12 KiB
JavaScript
410 lines
12 KiB
JavaScript
window.iD = function () {
|
|
window.locale.en = iD.data.en;
|
|
window.locale.current('en');
|
|
|
|
var context = {},
|
|
storage;
|
|
|
|
// https://github.com/openstreetmap/iD/issues/772
|
|
// http://mathiasbynens.be/notes/localstorage-pattern#comment-9
|
|
try { storage = localStorage; } catch (e) {}
|
|
storage = storage || (function() {
|
|
var s = {};
|
|
return {
|
|
getItem: function(k) { return s[k]; },
|
|
setItem: function(k, v) { s[k] = v; },
|
|
removeItem: function(k) { delete s[k]; }
|
|
};
|
|
})();
|
|
|
|
context.storage = function(k, v) {
|
|
try {
|
|
if (arguments.length === 1) return storage.getItem(k);
|
|
else if (v === null) storage.removeItem(k);
|
|
else storage.setItem(k, v);
|
|
} catch(e) {
|
|
// localstorage quota exceeded
|
|
/* jshint devel:true */
|
|
if (typeof console !== 'undefined') console.error('localStorage quota exceeded');
|
|
/* jshint devel:false */
|
|
}
|
|
};
|
|
|
|
/* Accessor for setting minimum zoom for editing features. */
|
|
|
|
var minEditableZoom = 16;
|
|
context.minEditableZoom = function(_) {
|
|
if (!arguments.length) return minEditableZoom;
|
|
minEditableZoom = _;
|
|
connection.tileZoom(_);
|
|
return context;
|
|
};
|
|
|
|
var history = iD.History(context),
|
|
dispatch = d3.dispatch('enter', 'exit'),
|
|
mode,
|
|
container,
|
|
ui = iD.ui(context),
|
|
connection = iD.Connection(),
|
|
locale = iD.detect().locale,
|
|
localePath;
|
|
|
|
if (locale && iD.data.locales.indexOf(locale) === -1) {
|
|
locale = locale.split('-')[0];
|
|
}
|
|
|
|
context.preauth = function(options) {
|
|
connection.switch(options);
|
|
return context;
|
|
};
|
|
|
|
context.locale = function(loc, path) {
|
|
locale = loc;
|
|
localePath = path;
|
|
|
|
// Also set iD.detect().locale (unless we detected 'en-us' and openstreetmap wants 'en')..
|
|
if (!(loc.toLowerCase() === 'en' && iD.detect().locale.toLowerCase() === 'en-us')) {
|
|
iD.detect().locale = loc;
|
|
}
|
|
|
|
return context;
|
|
};
|
|
|
|
context.loadLocale = function(cb) {
|
|
if (locale && locale !== 'en' && iD.data.locales.indexOf(locale) !== -1) {
|
|
localePath = localePath || context.assetPath() + 'locales/' + locale + '.json';
|
|
d3.json(localePath, function(err, result) {
|
|
window.locale[locale] = result;
|
|
window.locale.current(locale);
|
|
cb();
|
|
});
|
|
} else {
|
|
cb();
|
|
}
|
|
};
|
|
|
|
/* Straight accessors. Avoid using these if you can. */
|
|
context.ui = function() { return ui; };
|
|
context.connection = function() { return connection; };
|
|
context.history = function() { return history; };
|
|
|
|
/* Connection */
|
|
function entitiesLoaded(err, result) {
|
|
if (!err) history.merge(result.data, result.extent);
|
|
}
|
|
|
|
context.loadTiles = function(projection, dimensions, callback) {
|
|
function done(err, result) {
|
|
entitiesLoaded(err, result);
|
|
if (callback) callback(err, result);
|
|
}
|
|
connection.loadTiles(projection, dimensions, done);
|
|
};
|
|
|
|
context.loadEntity = function(id, callback) {
|
|
function done(err, result) {
|
|
entitiesLoaded(err, result);
|
|
if (callback) callback(err, result);
|
|
}
|
|
connection.loadEntity(id, done);
|
|
};
|
|
|
|
context.zoomToEntity = function(id, zoomTo) {
|
|
if (zoomTo !== false) {
|
|
this.loadEntity(id, function(err, result) {
|
|
if (err) return;
|
|
var entity = _.find(result.data, function(e) { return e.id === id; });
|
|
if (entity) { map.zoomTo(entity); }
|
|
});
|
|
}
|
|
|
|
map.on('drawn.zoomToEntity', function() {
|
|
if (!context.hasEntity(id)) return;
|
|
map.on('drawn.zoomToEntity', null);
|
|
context.on('enter.zoomToEntity', null);
|
|
context.enter(iD.modes.Select(context, [id]));
|
|
});
|
|
|
|
context.on('enter.zoomToEntity', function() {
|
|
if (mode.id !== 'browse') {
|
|
map.on('drawn.zoomToEntity', null);
|
|
context.on('enter.zoomToEntity', null);
|
|
}
|
|
});
|
|
};
|
|
|
|
/* History */
|
|
context.graph = history.graph;
|
|
context.changes = history.changes;
|
|
context.intersects = history.intersects;
|
|
|
|
var inIntro = false;
|
|
|
|
context.inIntro = function(_) {
|
|
if (!arguments.length) return inIntro;
|
|
inIntro = _;
|
|
return context;
|
|
};
|
|
|
|
context.save = function() {
|
|
if (inIntro || (mode && mode.id === 'save')) return;
|
|
history.save();
|
|
if (history.hasChanges()) return t('save.unsaved_changes');
|
|
};
|
|
|
|
context.flush = function() {
|
|
connection.flush();
|
|
features.reset();
|
|
history.reset();
|
|
return context;
|
|
};
|
|
|
|
// Debounce save, since it's a synchronous localStorage write,
|
|
// and history changes can happen frequently (e.g. when dragging).
|
|
var debouncedSave = _.debounce(context.save, 350);
|
|
function withDebouncedSave(fn) {
|
|
return function() {
|
|
var result = fn.apply(history, arguments);
|
|
debouncedSave();
|
|
return result;
|
|
};
|
|
}
|
|
|
|
context.perform = withDebouncedSave(history.perform);
|
|
context.replace = withDebouncedSave(history.replace);
|
|
context.pop = withDebouncedSave(history.pop);
|
|
context.overwrite = withDebouncedSave(history.overwrite);
|
|
context.undo = withDebouncedSave(history.undo);
|
|
context.redo = withDebouncedSave(history.redo);
|
|
|
|
/* Graph */
|
|
context.hasEntity = function(id) {
|
|
return history.graph().hasEntity(id);
|
|
};
|
|
|
|
context.entity = function(id) {
|
|
return history.graph().entity(id);
|
|
};
|
|
|
|
context.childNodes = function(way) {
|
|
return history.graph().childNodes(way);
|
|
};
|
|
|
|
context.geometry = function(id) {
|
|
return context.entity(id).geometry(history.graph());
|
|
};
|
|
|
|
/* Modes */
|
|
context.enter = function(newMode) {
|
|
if (mode) {
|
|
mode.exit();
|
|
dispatch.exit(mode);
|
|
}
|
|
|
|
mode = newMode;
|
|
mode.enter();
|
|
dispatch.enter(mode);
|
|
};
|
|
|
|
context.mode = function() {
|
|
return mode;
|
|
};
|
|
|
|
context.selectedIDs = function() {
|
|
if (mode && mode.selectedIDs) {
|
|
return mode.selectedIDs();
|
|
} else {
|
|
return [];
|
|
}
|
|
};
|
|
|
|
/* Behaviors */
|
|
context.install = function(behavior) {
|
|
context.surface().call(behavior);
|
|
};
|
|
|
|
context.uninstall = function(behavior) {
|
|
context.surface().call(behavior.off);
|
|
};
|
|
|
|
/* Copy/Paste */
|
|
var copyIDs = [], copyGraph;
|
|
context.copyGraph = function() { return copyGraph; };
|
|
context.copyIDs = function(_) {
|
|
if (!arguments.length) return copyIDs;
|
|
copyIDs = _;
|
|
copyGraph = history.graph();
|
|
return context;
|
|
};
|
|
|
|
/* Projection */
|
|
context.projection = iD.geo.RawMercator();
|
|
|
|
/* Background */
|
|
var background = iD.Background(context);
|
|
context.background = function() { return background; };
|
|
|
|
/* Features */
|
|
var features = iD.Features(context);
|
|
context.features = function() { return features; };
|
|
context.hasHiddenConnections = function(id) {
|
|
var graph = history.graph(),
|
|
entity = graph.entity(id);
|
|
return features.hasHiddenConnections(entity, graph);
|
|
};
|
|
|
|
/* Map */
|
|
var map = iD.Map(context);
|
|
context.map = function() { return map; };
|
|
context.layers = function() { return map.layers; };
|
|
context.surface = function() { return map.surface; };
|
|
context.editable = function() { return map.editable(); };
|
|
context.mouse = map.mouse;
|
|
context.extent = map.extent;
|
|
context.pan = map.pan;
|
|
context.zoomIn = map.zoomIn;
|
|
context.zoomOut = map.zoomOut;
|
|
context.zoomInFurther = map.zoomInFurther;
|
|
context.zoomOutFurther = map.zoomOutFurther;
|
|
|
|
context.surfaceRect = function() {
|
|
// Work around a bug in Firefox.
|
|
// http://stackoverflow.com/questions/18153989/
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=530985
|
|
return context.surface().node().parentNode.getBoundingClientRect();
|
|
};
|
|
|
|
/* Presets */
|
|
var presets = iD.presets();
|
|
|
|
context.presets = function(_) {
|
|
if (!arguments.length) return presets;
|
|
presets.load(_);
|
|
iD.areaKeys = presets.areaKeys();
|
|
return context;
|
|
};
|
|
|
|
context.imagery = function(_) {
|
|
background.load(_);
|
|
return context;
|
|
};
|
|
|
|
context.container = function(_) {
|
|
if (!arguments.length) return container;
|
|
container = _;
|
|
container.classed('id-container', true);
|
|
return context;
|
|
};
|
|
|
|
/* Taginfo */
|
|
var taginfo;
|
|
context.taginfo = function(_) {
|
|
if (!arguments.length) return taginfo;
|
|
taginfo = _;
|
|
return context;
|
|
};
|
|
|
|
var embed = false;
|
|
context.embed = function(_) {
|
|
if (!arguments.length) return embed;
|
|
embed = _;
|
|
return context;
|
|
};
|
|
|
|
var assetPath = '';
|
|
context.assetPath = function(_) {
|
|
if (!arguments.length) return assetPath;
|
|
assetPath = _;
|
|
return context;
|
|
};
|
|
|
|
var assetMap = {};
|
|
context.assetMap = function(_) {
|
|
if (!arguments.length) return assetMap;
|
|
assetMap = _;
|
|
return context;
|
|
};
|
|
|
|
context.imagePath = function(_) {
|
|
var asset = 'img/' + _;
|
|
return assetMap[asset] || assetPath + asset;
|
|
};
|
|
|
|
return d3.rebind(context, dispatch, 'on');
|
|
};
|
|
|
|
iD.version = '1.7.3';
|
|
|
|
(function() {
|
|
var detected = {};
|
|
|
|
var ua = navigator.userAgent,
|
|
m = null;
|
|
|
|
m = ua.match(/Trident\/.*rv:([0-9]{1,}[\.0-9]{0,})/i); // IE11+
|
|
if (m !== null) {
|
|
detected.browser = 'msie';
|
|
detected.version = m[1];
|
|
}
|
|
if (!detected.browser) {
|
|
m = ua.match(/(opr)\/?\s*(\.?\d+(\.\d+)*)/i); // Opera 15+
|
|
if (m !== null) {
|
|
detected.browser = 'Opera';
|
|
detected.version = m[2];
|
|
}
|
|
}
|
|
if (!detected.browser) {
|
|
m = ua.match(/(opera|chrome|safari|firefox|msie)\/?\s*(\.?\d+(\.\d+)*)/i);
|
|
if (m !== null) {
|
|
detected.browser = m[1];
|
|
detected.version = m[2];
|
|
m = ua.match(/version\/([\.\d]+)/i);
|
|
if (m !== null) detected.version = m[1];
|
|
}
|
|
}
|
|
if (!detected.browser) {
|
|
detected.browser = navigator.appName;
|
|
detected.version = navigator.appVersion;
|
|
}
|
|
|
|
// keep major.minor version only..
|
|
detected.version = detected.version.split(/\W/).slice(0,2).join('.');
|
|
|
|
if (detected.browser.toLowerCase() === 'msie') {
|
|
detected.browser = 'Internet Explorer';
|
|
detected.support = parseFloat(detected.version) > 9;
|
|
} else {
|
|
detected.support = true;
|
|
}
|
|
|
|
// Added due to incomplete svg style support. See #715
|
|
detected.opera = (detected.browser.toLowerCase() === 'opera' && parseFloat(detected.version) < 15 );
|
|
|
|
detected.locale = navigator.language || navigator.userLanguage || 'en-US';
|
|
|
|
detected.filedrop = (window.FileReader && 'ondrop' in window);
|
|
|
|
function nav(x) {
|
|
return navigator.userAgent.indexOf(x) !== -1;
|
|
}
|
|
|
|
if (nav('Win')) {
|
|
detected.os = 'win';
|
|
detected.platform = 'Windows';
|
|
}
|
|
else if (nav('Mac')) {
|
|
detected.os = 'mac';
|
|
detected.platform = 'Macintosh';
|
|
}
|
|
else if (nav('X11') || nav('Linux')) {
|
|
detected.os = 'linux';
|
|
detected.platform = 'Linux';
|
|
}
|
|
else {
|
|
detected.os = 'win';
|
|
detected.platform = 'Unknown';
|
|
}
|
|
|
|
iD.detect = function() { return detected; };
|
|
})();
|