/g, ".")).reverse();
let stringsKey = locale2;
if (stringsKey.toLowerCase() === "en-us")
stringsKey = "en";
let result = _localeStrings && _localeStrings[scopeId] && _localeStrings[scopeId][stringsKey];
while (result !== void 0 && path.length) {
result = result[path.pop()];
}
if (result !== void 0) {
if (replacements) {
if (typeof result === "object" && Object.keys(result).length) {
const number3 = Object.values(replacements).find(function(value) {
return typeof value === "number";
});
if (number3 !== void 0) {
const rule = pluralRule(number3, locale2);
if (result[rule]) {
result = result[rule];
} else {
result = Object.values(result)[0];
}
}
}
if (typeof result === "string") {
for (let key in replacements) {
let value = replacements[key];
if (typeof value === "number") {
if (value.toLocaleString) {
value = value.toLocaleString(locale2, {
style: "decimal",
useGrouping: true,
minimumFractionDigits: 0
});
} else {
value = value.toString();
}
}
const token = `{${key}}`;
const regex = new RegExp(token, "g");
result = result.replace(regex, value);
}
}
}
if (typeof result === "string") {
return {
text: result,
locale: locale2
};
}
}
let index = _localeCodes.indexOf(locale2);
if (index >= 0 && index < _localeCodes.length - 1) {
let fallback = _localeCodes[index + 1];
return localizer.tInfo(origStringId, replacements, fallback);
}
if (replacements && "default" in replacements) {
return {
text: replacements.default,
locale: null
};
}
const missing = `Missing ${locale2} translation: ${origStringId}`;
if (typeof console !== "undefined")
console.error(missing);
return {
text: missing,
locale: "en"
};
};
localizer.hasTextForStringId = function(stringId) {
return !!localizer.tInfo(stringId, { default: "nothing found" }).locale;
};
localizer.t = function(stringId, replacements, locale2) {
return localizer.tInfo(stringId, replacements, locale2).text;
};
localizer.t.html = function(stringId, replacements, locale2) {
replacements = Object.assign({}, replacements);
for (var k in replacements) {
if (typeof replacements[k] === "string") {
replacements[k] = escape_default(replacements[k]);
}
if (typeof replacements[k] === "object" && typeof replacements[k].html === "string") {
replacements[k] = replacements[k].html;
}
}
const info = localizer.tInfo(stringId, replacements, locale2);
if (info.text) {
return `${info.text}`;
} else {
return "";
}
};
localizer.t.append = function(stringId, replacements, locale2) {
return function(selection2) {
const info = localizer.tInfo(stringId, replacements, locale2);
return selection2.append("span").attr("class", "localized-text").attr("lang", info.locale || "und").text((replacements && replacements.prefix || "") + info.text + (replacements && replacements.suffix || ""));
};
};
localizer.languageName = (code, options2) => {
if (_languageNames[code]) {
return _languageNames[code];
}
if (options2 && options2.localOnly)
return null;
const langInfo = _dataLanguages[code];
if (langInfo) {
if (langInfo.nativeName) {
return localizer.t("translate.language_and_code", { language: langInfo.nativeName, code });
} else if (langInfo.base && langInfo.script) {
const base = langInfo.base;
if (_languageNames[base]) {
const scriptCode = langInfo.script;
const script = _scriptNames[scriptCode] || scriptCode;
return localizer.t("translate.language_and_code", { language: _languageNames[base], code: script });
} else if (_dataLanguages[base] && _dataLanguages[base].nativeName) {
return localizer.t("translate.language_and_code", { language: _dataLanguages[base].nativeName, code });
}
}
}
return code;
};
return localizer;
}
// modules/presets/collection.js
function presetCollection(collection) {
const MAXRESULTS = 50;
let _this = {};
let _memo = {};
_this.collection = collection;
_this.item = (id2) => {
if (_memo[id2])
return _memo[id2];
const found = _this.collection.find((d) => d.id === id2);
if (found)
_memo[id2] = found;
return found;
};
_this.index = (id2) => _this.collection.findIndex((d) => d.id === id2);
_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 id2 = geometry;
if (id2 === "vertex")
id2 = "point";
return _this.item(id2);
};
_this.search = (value, geometry, loc) => {
if (!value)
return _this;
value = value.toLowerCase().trim();
function leading(a) {
const index = a.indexOf(value);
return index === 0 || a[index - 1] === " ";
}
function leadingStrict(a) {
const index = a.indexOf(value);
return index === 0;
}
function sortPresets(nameProp, aliasesProp) {
return function sortNames(a, b) {
let aCompare = a[nameProp]();
let bCompare = b[nameProp]();
if (aliasesProp) {
const findMatchingAlias = (strings) => {
if (strings.some((s) => s === value)) {
return strings.find((s) => s === value);
} else {
return strings.find((s) => s.includes(value));
}
};
aCompare = findMatchingAlias([aCompare].concat(a[aliasesProp]()));
bCompare = findMatchingAlias([bCompare].concat(b[aliasesProp]()));
}
if (value === aCompare)
return -1;
if (value === bCompare)
return 1;
let i2 = b.originalScore - a.originalScore;
if (i2 !== 0)
return i2;
i2 = aCompare.indexOf(value) - bCompare.indexOf(value);
if (i2 !== 0)
return i2;
return aCompare.length - bCompare.length;
};
}
let pool = _this.collection;
if (Array.isArray(loc)) {
const validLocations = _mainLocations.locationsAt(loc);
pool = pool.filter((a) => !a.locationSetID || validLocations[a.locationSetID]);
}
const searchable = pool.filter((a) => a.searchable !== false && a.suggestion !== true);
const suggestions = pool.filter((a) => a.suggestion === true);
const leadingNames = searchable.filter((a) => leading(a.searchName()) || a.searchAliases().some(leading)).sort(sortPresets("searchName", "searchAliases"));
const leadingSuggestions = suggestions.filter((a) => leadingStrict(a.searchName())).sort(sortPresets("searchName"));
const leadingNamesStripped = searchable.filter((a) => leading(a.searchNameStripped()) || a.searchAliasesStripped().some(leading)).sort(sortPresets("searchNameStripped", "searchAliasesStripped"));
const leadingSuggestionsStripped = suggestions.filter((a) => leadingStrict(a.searchNameStripped())).sort(sortPresets("searchNameStripped"));
const leadingTerms = searchable.filter((a) => (a.terms() || []).some(leading));
const leadingSuggestionTerms = suggestions.filter((a) => (a.terms() || []).some(leading));
const leadingTagValues = searchable.filter((a) => Object.values(a.tags || {}).filter((val) => val !== "*").some(leading));
const similarName = searchable.map((a) => ({ preset: a, dist: utilEditDistance(value, a.searchName()) })).filter((a) => a.dist + Math.min(value.length - a.preset.searchName().length, 0) < 3).sort((a, b) => a.dist - b.dist).map((a) => a.preset);
const similarSuggestions = suggestions.map((a) => ({ preset: a, dist: utilEditDistance(value, a.searchName()) })).filter((a) => a.dist + Math.min(value.length - a.preset.searchName().length, 0) < 1).sort((a, b) => a.dist - b.dist).map((a) => a.preset);
const similarTerms = searchable.filter((a) => {
return (a.terms() || []).some((b) => {
return utilEditDistance(value, b) + Math.min(value.length - b.length, 0) < 3;
});
});
let leadingTagKeyValues = [];
if (value.includes("=")) {
leadingTagKeyValues = searchable.filter((a) => a.tags && Object.keys(a.tags).some((key) => key + "=" + a.tags[key] === value)).concat(searchable.filter((a) => a.tags && Object.keys(a.tags).some((key) => leading(key + "=" + a.tags[key]))));
}
let results = leadingNames.concat(leadingSuggestions, leadingNamesStripped, leadingSuggestionsStripped, leadingTerms, leadingSuggestionTerms, leadingTagValues, similarName, similarSuggestions, similarTerms, leadingTagKeyValues).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));
};
return _this;
}
// modules/presets/category.js
function presetCategory(categoryID, category, allPresets) {
let _this = Object.assign({}, category);
let _searchName;
let _searchNameStripped;
_this.id = categoryID;
_this.members = presetCollection((category.members || []).map((presetID) => allPresets[presetID]).filter(Boolean));
_this.geometry = _this.members.collection.reduce((acc, preset) => {
for (let i2 in preset.geometry) {
const geometry = preset.geometry[i2];
if (acc.indexOf(geometry) === -1) {
acc.push(geometry);
}
}
return acc;
}, []);
_this.matchGeometry = (geom) => _this.geometry.indexOf(geom) >= 0;
_this.matchAllGeometry = (geometries) => _this.members.collection.some((preset) => preset.matchAllGeometry(geometries));
_this.matchScore = () => -1;
_this.name = () => _t(`_tagging.presets.categories.${categoryID}.name`, { "default": categoryID });
_this.nameLabel = () => _t.html(`_tagging.presets.categories.${categoryID}.name`, { "default": categoryID });
_this.terms = () => [];
_this.searchName = () => {
if (!_searchName) {
_searchName = (_this.suggestion ? _this.originalName : _this.name()).toLowerCase();
}
return _searchName;
};
_this.searchNameStripped = () => {
if (!_searchNameStripped) {
_searchNameStripped = _this.searchName();
if (_searchNameStripped.normalize)
_searchNameStripped = _searchNameStripped.normalize("NFD");
_searchNameStripped = _searchNameStripped.replace(/[\u0300-\u036f]/g, "");
}
return _searchNameStripped;
};
_this.searchAliases = () => [];
_this.searchAliasesStripped = () => [];
return _this;
}
// modules/presets/field.js
function presetField(fieldID, field) {
let _this = Object.assign({}, field);
_this.id = fieldID;
_this.safeid = utilSafeClassName(fieldID);
_this.matchGeometry = (geom) => !_this.geometry || _this.geometry.indexOf(geom) !== -1;
_this.matchAllGeometry = (geometries) => {
return !_this.geometry || geometries.every((geom) => _this.geometry.indexOf(geom) !== -1);
};
_this.t = (scope, options2) => _t(`_tagging.presets.fields.${fieldID}.${scope}`, options2);
_this.t.html = (scope, options2) => _t.html(`_tagging.presets.fields.${fieldID}.${scope}`, options2);
_this.hasTextForStringId = (scope) => _mainLocalizer.hasTextForStringId(`_tagging.presets.fields.${fieldID}.${scope}`);
_this.title = () => _this.overrideLabel || _this.t("label", { "default": fieldID });
_this.label = () => _this.overrideLabel || _this.t.html("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*/);
_this.increment = _this.type === "number" ? _this.increment || 1 : void 0;
return _this;
}
// modules/presets/preset.js
function presetPreset(presetID, preset, addable, allFields, allPresets) {
allFields = allFields || {};
allPresets = allPresets || {};
let _this = Object.assign({}, preset);
let _addable = addable || false;
let _resolvedFields;
let _resolvedMoreFields;
let _searchName;
let _searchNameStripped;
let _searchAliases;
let _searchAliasesStripped;
_this.id = presetID;
_this.safeid = utilSafeClassName(presetID);
_this.originalTerms = (_this.terms || []).join();
_this.originalName = _this.name || "";
_this.originalAliases = (_this.aliases || []).join("\n");
_this.originalScore = _this.matchScore || 1;
_this.originalReference = _this.reference || {};
_this.originalFields = _this.fields || [];
_this.originalMoreFields = _this.moreFields || [];
_this.fields = () => _resolvedFields || (_resolvedFields = resolve("fields"));
_this.moreFields = () => _resolvedMoreFields || (_resolvedMoreFields = resolve("moreFields"));
_this.resetFields = () => _resolvedFields = _resolvedMoreFields = null;
_this.tags = _this.tags || {};
_this.addTags = _this.addTags || _this.tags;
_this.removeTags = _this.removeTags || _this.addTags;
_this.geometry = _this.geometry || [];
_this.matchGeometry = (geom) => _this.geometry.indexOf(geom) >= 0;
_this.matchAllGeometry = (geoms) => geoms.every(_this.matchGeometry);
_this.matchScore = (entityTags) => {
const tags = _this.tags;
let seen = {};
let score = 0;
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;
}
}
const addTags = _this.addTags;
for (let k in addTags) {
if (!seen[k] && entityTags[k] === addTags[k]) {
score += _this.originalScore;
}
}
if (_this.searchable === false) {
score *= 0.999;
}
return score;
};
_this.t = (scope, options2) => {
const textID = `_tagging.presets.presets.${presetID}.${scope}`;
return _t(textID, options2);
};
_this.t.html = (scope, options2) => {
const textID = `_tagging.presets.presets.${presetID}.${scope}`;
return _t.html(textID, options2);
};
_this.name = () => {
return _this.t("name", { "default": _this.originalName });
};
_this.nameLabel = () => {
return _this.t.html("name", { "default": _this.originalName });
};
_this.subtitle = () => {
if (_this.suggestion) {
let path = presetID.split("/");
path.pop();
return _t("_tagging.presets.presets." + path.join("/") + ".name");
}
return null;
};
_this.subtitleLabel = () => {
if (_this.suggestion) {
let path = presetID.split("/");
path.pop();
return _t.html("_tagging.presets.presets." + path.join("/") + ".name");
}
return null;
};
_this.aliases = () => {
return _this.t("aliases", { "default": _this.originalAliases }).trim().split(/\s*[\r\n]+\s*/);
};
_this.terms = () => _this.t("terms", { "default": _this.originalTerms }).toLowerCase().trim().split(/\s*,+\s*/);
_this.searchName = () => {
if (!_searchName) {
_searchName = (_this.suggestion ? _this.originalName : _this.name()).toLowerCase();
}
return _searchName;
};
_this.searchNameStripped = () => {
if (!_searchNameStripped) {
_searchNameStripped = stripDiacritics(_this.searchName());
}
return _searchNameStripped;
};
_this.searchAliases = () => {
if (!_searchAliases) {
_searchAliases = _this.aliases().map((alias) => alias.toLowerCase());
}
return _searchAliases;
};
_this.searchAliasesStripped = () => {
if (!_searchAliasesStripped) {
_searchAliasesStripped = _this.searchAliases();
_searchAliasesStripped = _searchAliasesStripped.map(stripDiacritics);
}
return _searchAliasesStripped;
};
_this.isFallback = () => {
const tagCount = Object.keys(_this.tags).length;
return tagCount === 0 || tagCount === 1 && _this.tags.hasOwnProperty("area");
};
_this.addable = function(val) {
if (!arguments.length)
return _addable;
_addable = val;
return _this;
};
_this.reference = () => {
const qid = _this.tags.wikidata || _this.tags["flag:wikidata"] || _this.tags["brand:wikidata"] || _this.tags["network:wikidata"] || _this.tags["operator:wikidata"];
if (qid) {
return { qid };
}
let key = _this.originalReference.key || Object.keys(utilObjectOmit(_this.tags, "name"))[0];
let value = _this.originalReference.value || _this.tags[key];
if (value === "*") {
return { key };
} else {
return { key, value };
}
};
_this.unsetTags = (tags, geometry, ignoringKeys, skipFieldDefaults) => {
let removeTags = ignoringKeys ? utilObjectOmit(_this.removeTags, ignoringKeys) : _this.removeTags;
tags = utilObjectOmit(tags, Object.keys(removeTags));
if (geometry && !skipFieldDefaults) {
_this.fields().forEach((field) => {
if (field.matchGeometry(geometry) && field.key && field.default === tags[field.key]) {
delete tags[field.key];
}
});
}
delete tags.area;
return tags;
};
_this.setTags = (tags, geometry, skipFieldDefaults) => {
const addTags = _this.addTags;
tags = Object.assign({}, tags);
for (let k in addTags) {
if (addTags[k] === "*") {
if (_this.tags[k] || !tags[k]) {
tags[k] = "yes";
}
} else {
tags[k] = addTags[k];
}
}
if (!addTags.hasOwnProperty("area")) {
delete tags.area;
if (geometry === "area") {
let needsAreaTag = true;
for (let k in addTags) {
if (_this.geometry.indexOf("line") === -1 && k in osmAreaKeys || k in osmAreaKeysExceptions && addTags[k] in osmAreaKeysExceptions[k]) {
needsAreaTag = false;
break;
}
}
if (needsAreaTag) {
tags.area = "yes";
}
}
}
if (geometry && !skipFieldDefaults) {
_this.fields().forEach((field) => {
if (field.matchGeometry(geometry) && field.key && !tags[field.key] && field.default) {
tags[field.key] = field.default;
}
});
}
return tags;
};
function resolve(which) {
const fieldIDs = which === "fields" ? _this.originalFields : _this.originalMoreFields;
let resolved = [];
fieldIDs.forEach((fieldID) => {
const match = fieldID.match(/\{(.*)\}/);
if (match !== null) {
resolved = resolved.concat(inheritFields(match[1], which));
} else if (allFields[fieldID]) {
resolved.push(allFields[fieldID]);
} else {
console.log(`Cannot resolve "${fieldID}" found in ${_this.id}.${which}`);
}
});
if (!resolved.length) {
const endIndex = _this.id.lastIndexOf("/");
const parentID = endIndex && _this.id.substring(0, endIndex);
if (parentID) {
resolved = inheritFields(parentID, which);
}
}
return utilArrayUniq(resolved);
function inheritFields(presetID2, which2) {
const parent = allPresets[presetID2];
if (!parent)
return [];
if (which2 === "fields") {
return parent.fields().filter(shouldInherit);
} else if (which2 === "moreFields") {
return parent.moreFields();
} else {
return [];
}
}
function shouldInherit(f2) {
if (f2.key && _this.tags[f2.key] !== void 0 && f2.type !== "multiCombo" && f2.type !== "semiCombo" && f2.type !== "manyCombo" && f2.type !== "check")
return false;
return true;
}
}
function stripDiacritics(s) {
if (s.normalize)
s = s.normalize("NFD");
s = s.replace(/[\u0300-\u036f]/g, "");
return s;
}
return _this;
}
// modules/presets/index.js
var _mainPresetIndex = presetIndex();
function presetIndex() {
const dispatch10 = dispatch_default("favoritePreset", "recentsChange");
const MAXRECENTS = 30;
const POINT = presetPreset("point", { name: "Point", tags: {}, geometry: ["point", "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 });
let _this = presetCollection([POINT, LINE, AREA, RELATION]);
let _presets = { point: POINT, line: LINE, area: AREA, relation: RELATION };
let _defaults = {
point: presetCollection([POINT]),
vertex: presetCollection([POINT]),
line: presetCollection([LINE]),
area: presetCollection([AREA]),
relation: presetCollection([RELATION])
};
let _fields = {};
let _categories = {};
let _universal = [];
let _addablePresetIDs = null;
let _recents;
let _favorites;
let _geometryIndex = { point: {}, vertex: {}, line: {}, area: {}, relation: {} };
let _loadPromise;
_this.ensureLoaded = () => {
if (_loadPromise)
return _loadPromise;
return _loadPromise = Promise.all([
_mainFileFetcher.get("preset_categories"),
_mainFileFetcher.get("preset_defaults"),
_mainFileFetcher.get("preset_presets"),
_mainFileFetcher.get("preset_fields")
]).then((vals) => {
_this.merge({
categories: vals[0],
defaults: vals[1],
presets: vals[2],
fields: vals[3]
});
osmSetAreaKeys(_this.areaKeys());
osmSetPointTags(_this.pointTags());
osmSetVertexTags(_this.vertexTags());
});
};
_this.merge = (d) => {
let newLocationSets = [];
if (d.fields) {
Object.keys(d.fields).forEach((fieldID) => {
let f2 = d.fields[fieldID];
if (f2) {
f2 = presetField(fieldID, f2);
if (f2.locationSet)
newLocationSets.push(f2);
_fields[fieldID] = f2;
} else {
delete _fields[fieldID];
}
});
}
if (d.presets) {
Object.keys(d.presets).forEach((presetID) => {
let p = d.presets[presetID];
if (p) {
const isAddable = !_addablePresetIDs || _addablePresetIDs.has(presetID);
p = presetPreset(presetID, p, isAddable, _fields, _presets);
if (p.locationSet)
newLocationSets.push(p);
_presets[presetID] = p;
} else {
const existing = _presets[presetID];
if (existing && !existing.isFallback()) {
delete _presets[presetID];
}
}
});
}
if (d.categories) {
Object.keys(d.categories).forEach((categoryID) => {
let c = d.categories[categoryID];
if (c) {
c = presetCategory(categoryID, c, _presets);
if (c.locationSet)
newLocationSets.push(c);
_categories[categoryID] = c;
} else {
delete _categories[categoryID];
}
});
}
_this.collection = Object.values(_presets).concat(Object.values(_categories));
if (d.defaults) {
Object.keys(d.defaults).forEach((geometry) => {
const def = d.defaults[geometry];
if (Array.isArray(def)) {
_defaults[geometry] = presetCollection(def.map((id2) => _presets[id2] || _categories[id2]).filter(Boolean));
} else {
delete _defaults[geometry];
}
});
}
_universal = Object.values(_fields).filter((field) => field.universal);
Object.values(_presets).forEach((preset) => preset.resetFields());
_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] || {};
let value = preset.tags[key];
(g[key][value] = g[key][value] || []).push(preset);
}
});
});
if (d.featureCollection && Array.isArray(d.featureCollection.features)) {
_mainLocations.mergeCustomGeoJSON(d.featureCollection);
}
if (newLocationSets.length) {
_mainLocations.mergeLocationSets(newLocationSets);
}
return _this;
};
_this.match = (entity, resolver) => {
return resolver.transient(entity, "presetMatch", () => {
let geometry = entity.geometry(resolver);
if (geometry === "vertex" && entity.isOnAddressLine(resolver)) {
geometry = "point";
}
const entityExtent = entity.extent(resolver);
return _this.matchTags(entity.tags, geometry, entityExtent.center());
});
};
_this.matchTags = (tags, geometry, loc) => {
const keyIndex = _geometryIndex[geometry];
let bestScore = -1;
let bestMatch;
let matchCandidates = [];
for (let k in tags) {
let indexMatches = [];
let valueIndex = keyIndex[k];
if (!valueIndex)
continue;
let keyValueMatches = valueIndex[tags[k]];
if (keyValueMatches)
indexMatches.push(...keyValueMatches);
let keyStarMatches = valueIndex["*"];
if (keyStarMatches)
indexMatches.push(...keyStarMatches);
if (indexMatches.length === 0)
continue;
for (let i2 = 0; i2 < indexMatches.length; i2++) {
const candidate = indexMatches[i2];
const score = candidate.matchScore(tags);
if (score === -1) {
continue;
}
matchCandidates.push({ score, candidate });
if (score > bestScore) {
bestScore = score;
bestMatch = candidate;
}
}
}
if (bestMatch && bestMatch.locationSetID && bestMatch.locationSetID !== "+[Q2]" && Array.isArray(loc)) {
let validLocations = _mainLocations.locationsAt(loc);
if (!validLocations[bestMatch.locationSetID]) {
matchCandidates.sort((a, b) => a.score < b.score ? 1 : -1);
for (let i2 = 0; i2 < matchCandidates.length; i2++) {
const candidateScore = matchCandidates[i2];
if (!candidateScore.candidate.locationSetID || validLocations[candidateScore.candidate.locationSetID]) {
bestMatch = candidateScore.candidate;
bestScore = candidateScore.score;
break;
}
}
}
}
if (!bestMatch || bestMatch.isFallback()) {
for (let k in tags) {
if (/^addr:/.test(k) && keyIndex["addr:*"] && keyIndex["addr:*"]["*"]) {
bestMatch = keyIndex["addr:*"]["*"][0];
break;
}
}
}
return bestMatch || _this.fallback(geometry);
};
_this.allowsVertex = (entity, resolver) => {
if (entity.type !== "node")
return false;
if (Object.keys(entity.tags).length === 0)
return true;
return resolver.transient(entity, "vertexMatch", () => {
if (entity.isOnAddressLine(resolver))
return true;
const geometries = osmNodeGeometriesForTags(entity.tags);
if (geometries.vertex)
return true;
if (geometries.point)
return false;
return true;
});
};
_this.areaKeys = () => {
const ignore = {
barrier: true,
highway: true,
footway: true,
railway: true,
junction: true,
type: true
};
let areaKeys = {};
const presets = _this.collection.filter((p) => !p.suggestion && !p.replacement);
presets.forEach((p) => {
const keys = p.tags && Object.keys(p.tags);
const key = keys && keys.length && keys[0];
if (!key)
return;
if (ignore[key])
return;
if (p.geometry.indexOf("area") !== -1) {
areaKeys[key] = areaKeys[key] || {};
}
});
presets.forEach((p) => {
let key;
for (key in p.addTags) {
const value = p.addTags[key];
if (key in areaKeys && p.geometry.indexOf("line") !== -1 && value !== "*") {
areaKeys[key][value] = true;
}
}
});
return areaKeys;
};
_this.pointTags = () => {
return _this.collection.reduce((pointTags, d) => {
if (d.suggestion || d.replacement || d.searchable === false)
return pointTags;
const keys = d.tags && Object.keys(d.tags);
const key = keys && keys.length && keys[0];
if (!key)
return pointTags;
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) => {
if (d.suggestion || d.replacement || d.searchable === false)
return vertexTags;
const keys = d.tags && Object.keys(d.tags);
const key = keys && keys.length && keys[0];
if (!key)
return vertexTags;
if (d.geometry.indexOf("vertex") !== -1) {
vertexTags[key] = vertexTags[key] || {};
vertexTags[key][d.tags[key]] = true;
}
return vertexTags;
}, {});
};
_this.field = (id2) => _fields[id2];
_this.universal = () => _universal;
_this.defaults = (geometry, n2, startWithRecents, loc) => {
let recents = [];
if (startWithRecents) {
recents = _this.recent().matchGeometry(geometry).collection.slice(0, 4);
}
let defaults2;
if (_addablePresetIDs) {
defaults2 = Array.from(_addablePresetIDs).map(function(id2) {
var preset = _this.item(id2);
if (preset && preset.matchGeometry(geometry))
return preset;
return null;
}).filter(Boolean);
} else {
defaults2 = _defaults[geometry].collection.concat(_this.fallback(geometry));
}
let result = presetCollection(utilArrayUniq(recents.concat(defaults2)).slice(0, n2 - 1));
if (Array.isArray(loc)) {
const validLocations = _mainLocations.locationsAt(loc);
result.collection = result.collection.filter((a) => !a.locationSetID || validLocations[a.locationSetID]);
}
return result;
};
_this.addablePresetIDs = function(val) {
if (!arguments.length)
return _addablePresetIDs;
if (Array.isArray(val))
val = new Set(val);
_addablePresetIDs = val;
if (_addablePresetIDs) {
_this.collection.forEach((p) => {
if (p.addable)
p.addable(_addablePresetIDs.has(p.id));
});
} else {
_this.collection.forEach((p) => {
if (p.addable)
p.addable(true);
});
}
return _this;
};
_this.recent = () => {
return presetCollection(utilArrayUniq(_this.getRecents().map((d) => d.preset)));
};
function RibbonItem(preset, source) {
let item = {};
item.preset = preset;
item.source = source;
item.isFavorite = () => item.source === "favorite";
item.isRecent = () => item.source === "recent";
item.matches = (preset2) => item.preset.id === preset2.id;
item.minified = () => ({ pID: item.preset.id });
return item;
}
function ribbonItemForMinified(d, source) {
if (d && d.pID) {
const preset = _this.item(d.pID);
if (!preset)
return null;
return RibbonItem(preset, source);
}
return null;
}
_this.getGenericRibbonItems = () => {
return ["point", "line", "area"].map((id2) => RibbonItem(_this.item(id2), "generic"));
};
_this.getAddable = () => {
if (!_addablePresetIDs)
return [];
return _addablePresetIDs.map((id2) => {
const preset = _this.item(id2);
if (preset)
return RibbonItem(preset, "addable");
return null;
}).filter(Boolean);
};
function setRecents(items) {
_recents = items;
const minifiedItems = items.map((d) => d.minified());
corePreferences("preset_recents", JSON.stringify(minifiedItems));
dispatch10.call("recentsChange");
}
_this.getRecents = () => {
if (!_recents) {
_recents = (JSON.parse(corePreferences("preset_recents")) || []).reduce((acc, d) => {
let item = ribbonItemForMinified(d, "recent");
if (item && item.preset.addable())
acc.push(item);
return acc;
}, []);
}
return _recents;
};
_this.addRecent = (preset, besidePreset, after) => {
const recents = _this.getRecents();
const beforeItem = _this.recentMatching(besidePreset);
let toIndex = recents.indexOf(beforeItem);
if (after)
toIndex += 1;
const newItem = RibbonItem(preset, "recent");
recents.splice(toIndex, 0, newItem);
setRecents(recents);
};
_this.removeRecent = (preset) => {
const item = _this.recentMatching(preset);
if (item) {
let items = _this.getRecents();
items.splice(items.indexOf(item), 1);
setRecents(items);
}
};
_this.recentMatching = (preset) => {
const items = _this.getRecents();
for (let i2 in items) {
if (items[i2].matches(preset)) {
return items[i2];
}
}
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) => {
if (preset.searchable === false)
return;
let items = _this.getRecents();
let item = _this.recentMatching(preset);
if (item) {
items.splice(items.indexOf(item), 1);
} else {
item = RibbonItem(preset, "recent");
}
while (items.length >= MAXRECENTS) {
items.pop();
}
items.unshift(item);
setRecents(items);
};
function setFavorites(items) {
_favorites = items;
const minifiedItems = items.map((d) => d.minified());
corePreferences("preset_favorites", JSON.stringify(minifiedItems));
dispatch10.call("favoritePreset");
}
_this.addFavorite = (preset, besidePreset, after) => {
const favorites = _this.getFavorites();
const beforeItem = _this.favoriteMatching(besidePreset);
let toIndex = favorites.indexOf(beforeItem);
if (after)
toIndex += 1;
const newItem = RibbonItem(preset, "favorite");
favorites.splice(toIndex, 0, newItem);
setFavorites(favorites);
};
_this.toggleFavorite = (preset) => {
const favs = _this.getFavorites();
const favorite = _this.favoriteMatching(preset);
if (favorite) {
favs.splice(favs.indexOf(favorite), 1);
} else {
if (favs.length === 10) {
favs.pop();
}
favs.push(RibbonItem(preset, "favorite"));
}
setFavorites(favs);
};
_this.removeFavorite = (preset) => {
const item = _this.favoriteMatching(preset);
if (item) {
const items = _this.getFavorites();
items.splice(items.indexOf(item), 1);
setFavorites(items);
}
};
_this.getFavorites = () => {
if (!_favorites) {
let rawFavorites = JSON.parse(corePreferences("preset_favorites"));
if (!rawFavorites) {
rawFavorites = [];
corePreferences("preset_favorites", JSON.stringify(rawFavorites));
}
_favorites = rawFavorites.reduce((output, d) => {
const item = ribbonItemForMinified(d, "favorite");
if (item && item.preset.addable())
output.push(item);
return output;
}, []);
}
return _favorites;
};
_this.favoriteMatching = (preset) => {
const favs = _this.getFavorites();
for (let index in favs) {
if (favs[index].matches(preset)) {
return favs[index];
}
}
return null;
};
return utilRebind(_this, dispatch10, "on");
}
// modules/util/util.js
function utilTagText(entity) {
var obj = entity && entity.tags || {};
return Object.keys(obj).map(function(k) {
return k + "=" + obj[k];
}).join(", ");
}
function utilTotalExtent(array2, graph) {
var extent = geoExtent();
var val, entity;
for (var i2 = 0; i2 < array2.length; i2++) {
val = array2[i2];
entity = typeof val === "string" ? graph.hasEntity(val) : val;
if (entity) {
extent._extend(entity.extent(graph));
}
}
return extent;
}
function utilTagDiff(oldTags, newTags) {
var tagDiff = [];
var keys = utilArrayUnion(Object.keys(oldTags), Object.keys(newTags)).sort();
keys.forEach(function(k) {
var oldVal = oldTags[k];
var newVal = newTags[k];
if ((oldVal || oldVal === "") && (newVal === void 0 || newVal !== oldVal)) {
tagDiff.push({
type: "-",
key: k,
oldVal,
newVal,
display: "- " + k + "=" + oldVal
});
}
if ((newVal || newVal === "") && (oldVal === void 0 || newVal !== oldVal)) {
tagDiff.push({
type: "+",
key: k,
oldVal,
newVal,
display: "+ " + k + "=" + newVal
});
}
});
return tagDiff;
}
function utilEntitySelector(ids) {
return ids.length ? "." + ids.join(",.") : "nothing";
}
function utilEntityOrMemberSelector(ids, graph) {
var seen = new Set(ids);
ids.forEach(collectShallowDescendants);
return utilEntitySelector(Array.from(seen));
function collectShallowDescendants(id2) {
var entity = graph.hasEntity(id2);
if (!entity || entity.type !== "relation")
return;
entity.members.map(function(member) {
return member.id;
}).forEach(function(id3) {
seen.add(id3);
});
}
}
function utilEntityOrDeepMemberSelector(ids, graph) {
return utilEntitySelector(utilEntityAndDeepMemberIDs(ids, graph));
}
function utilEntityAndDeepMemberIDs(ids, graph) {
var seen = /* @__PURE__ */ new Set();
ids.forEach(collectDeepDescendants);
return Array.from(seen);
function collectDeepDescendants(id2) {
if (seen.has(id2))
return;
seen.add(id2);
var entity = graph.hasEntity(id2);
if (!entity || entity.type !== "relation")
return;
entity.members.map(function(member) {
return member.id;
}).forEach(collectDeepDescendants);
}
}
function utilDeepMemberSelector(ids, graph, skipMultipolgonMembers) {
var idsSet = new Set(ids);
var seen = /* @__PURE__ */ new Set();
var returners = /* @__PURE__ */ new Set();
ids.forEach(collectDeepDescendants);
return utilEntitySelector(Array.from(returners));
function collectDeepDescendants(id2) {
if (seen.has(id2))
return;
seen.add(id2);
if (!idsSet.has(id2)) {
returners.add(id2);
}
var entity = graph.hasEntity(id2);
if (!entity || entity.type !== "relation")
return;
if (skipMultipolgonMembers && entity.isMultipolygon())
return;
entity.members.map(function(member) {
return member.id;
}).forEach(collectDeepDescendants);
}
}
function utilHighlightEntities(ids, highlighted, context) {
context.surface().selectAll(utilEntityOrDeepMemberSelector(ids, context.graph())).classed("highlighted", highlighted);
}
function utilGetAllNodes(ids, graph) {
var seen = /* @__PURE__ */ new Set();
var nodes = /* @__PURE__ */ new Set();
ids.forEach(collectNodes);
return Array.from(nodes);
function collectNodes(id2) {
if (seen.has(id2))
return;
seen.add(id2);
var entity = graph.hasEntity(id2);
if (!entity)
return;
if (entity.type === "node") {
nodes.add(entity);
} else if (entity.type === "way") {
entity.nodes.forEach(collectNodes);
} else {
entity.members.map(function(member) {
return member.id;
}).forEach(collectNodes);
}
}
}
function utilDisplayName(entity) {
var localizedNameKey = "name:" + _mainLocalizer.languageCode().toLowerCase();
var name2 = entity.tags[localizedNameKey] || entity.tags.name || "";
if (name2)
return name2;
var tags = {
direction: entity.tags.direction,
from: entity.tags.from,
network: entity.tags.cycle_network || entity.tags.network,
ref: entity.tags.ref,
to: entity.tags.to,
via: entity.tags.via
};
var keyComponents = [];
if (tags.network) {
keyComponents.push("network");
}
if (tags.ref) {
keyComponents.push("ref");
}
if (entity.tags.route) {
if (tags.direction) {
keyComponents.push("direction");
} else if (tags.from && tags.to) {
keyComponents.push("from");
keyComponents.push("to");
if (tags.via) {
keyComponents.push("via");
}
}
}
if (keyComponents.length) {
name2 = _t("inspector.display_name." + keyComponents.join("_"), tags);
}
return name2;
}
function utilDisplayNameForPath(entity) {
var name2 = utilDisplayName(entity);
var isFirefox = utilDetect().browser.toLowerCase().indexOf("firefox") > -1;
var isNewChromium = Number(utilDetect().version.split(".")[0]) >= 96;
if (!isFirefox && !isNewChromium && name2 && rtlRegex.test(name2)) {
name2 = fixRTLTextForSvg(name2);
}
return name2;
}
function utilDisplayType(id2) {
return {
n: _t("inspector.node"),
w: _t("inspector.way"),
r: _t("inspector.relation")
}[id2.charAt(0)];
}
function utilDisplayLabel(entity, graphOrGeometry, verbose) {
var result;
var displayName = utilDisplayName(entity);
var preset = typeof graphOrGeometry === "string" ? _mainPresetIndex.matchTags(entity.tags, graphOrGeometry) : _mainPresetIndex.match(entity, graphOrGeometry);
var presetName = preset && (preset.suggestion ? preset.subtitle() : preset.name());
if (verbose) {
result = [presetName, displayName].filter(Boolean).join(" ");
} else {
result = displayName || presetName;
}
return result || utilDisplayType(entity.id);
}
function utilEntityRoot(entityType) {
return {
node: "n",
way: "w",
relation: "r"
}[entityType];
}
function utilCombinedTags(entityIDs, graph) {
var tags = {};
var tagCounts = {};
var allKeys = /* @__PURE__ */ new Set();
var entities = entityIDs.map(function(entityID) {
return graph.hasEntity(entityID);
}).filter(Boolean);
entities.forEach(function(entity) {
var keys = Object.keys(entity.tags).filter(Boolean);
keys.forEach(function(key2) {
allKeys.add(key2);
});
});
entities.forEach(function(entity) {
allKeys.forEach(function(key2) {
var value = entity.tags[key2];
if (!tags.hasOwnProperty(key2)) {
tags[key2] = value;
} else {
if (!Array.isArray(tags[key2])) {
if (tags[key2] !== value) {
tags[key2] = [tags[key2], value];
}
} else {
if (tags[key2].indexOf(value) === -1) {
tags[key2].push(value);
}
}
}
var tagHash = key2 + "=" + value;
if (!tagCounts[tagHash])
tagCounts[tagHash] = 0;
tagCounts[tagHash] += 1;
});
});
for (var key in tags) {
if (!Array.isArray(tags[key]))
continue;
tags[key] = tags[key].sort(function(val1, val2) {
var key2 = key2;
var count2 = tagCounts[key2 + "=" + val2];
var count1 = tagCounts[key2 + "=" + val1];
if (count2 !== count1) {
return count2 - count1;
}
if (val2 && val1) {
return val1.localeCompare(val2);
}
return val1 ? 1 : -1;
});
}
return tags;
}
function utilStringQs(str2) {
var i2 = 0;
while (i2 < str2.length && (str2[i2] === "?" || str2[i2] === "#"))
i2++;
str2 = str2.slice(i2);
return str2.split("&").reduce(function(obj, pair2) {
var parts = pair2.split("=");
if (parts.length === 2) {
obj[parts[0]] = parts[1] === null ? "" : decodeURIComponent(parts[1]);
}
return obj;
}, {});
}
function utilQsString(obj, noencode) {
function softEncode(s) {
return encodeURIComponent(s).replace(/(%2F|%3A|%2C|%7B|%7D)/g, decodeURIComponent);
}
return Object.keys(obj).sort().map(function(key) {
return encodeURIComponent(key) + "=" + (noencode ? softEncode(obj[key]) : encodeURIComponent(obj[key]));
}).join("&");
}
function utilPrefixDOMProperty(property) {
var prefixes2 = ["webkit", "ms", "moz", "o"];
var i2 = -1;
var n2 = prefixes2.length;
var s = document.body;
if (property in s)
return property;
property = property.substr(0, 1).toUpperCase() + property.substr(1);
while (++i2 < n2) {
if (prefixes2[i2] + property in s) {
return prefixes2[i2] + property;
}
}
return false;
}
function utilPrefixCSSProperty(property) {
var prefixes2 = ["webkit", "ms", "Moz", "O"];
var i2 = -1;
var n2 = prefixes2.length;
var s = document.body.style;
if (property.toLowerCase() in s) {
return property.toLowerCase();
}
while (++i2 < n2) {
if (prefixes2[i2] + property in s) {
return "-" + prefixes2[i2].toLowerCase() + property.replace(/([A-Z])/g, "-$1").toLowerCase();
}
}
return false;
}
var transformProperty;
function utilSetTransform(el, x, y, scale) {
var prop = transformProperty = transformProperty || utilPrefixCSSProperty("Transform");
var translate = utilDetect().opera ? "translate(" + x + "px," + y + "px)" : "translate3d(" + x + "px," + y + "px,0)";
return el.style(prop, translate + (scale ? " scale(" + scale + ")" : ""));
}
function utilEditDistance(a, b) {
a = (0, import_diacritics.remove)(a.toLowerCase());
b = (0, import_diacritics.remove)(b.toLowerCase());
if (a.length === 0)
return b.length;
if (b.length === 0)
return a.length;
var matrix = [];
var i2, j2;
for (i2 = 0; i2 <= b.length; i2++) {
matrix[i2] = [i2];
}
for (j2 = 0; j2 <= a.length; j2++) {
matrix[0][j2] = j2;
}
for (i2 = 1; i2 <= b.length; i2++) {
for (j2 = 1; j2 <= a.length; j2++) {
if (b.charAt(i2 - 1) === a.charAt(j2 - 1)) {
matrix[i2][j2] = matrix[i2 - 1][j2 - 1];
} else {
matrix[i2][j2] = Math.min(matrix[i2 - 1][j2 - 1] + 1, Math.min(matrix[i2][j2 - 1] + 1, matrix[i2 - 1][j2] + 1));
}
}
}
return matrix[b.length][a.length];
}
function utilFastMouse(container) {
var rect = container.getBoundingClientRect();
var rectLeft = rect.left;
var rectTop = rect.top;
var clientLeft = +container.clientLeft;
var clientTop = +container.clientTop;
return function(e) {
return [
e.clientX - rectLeft - clientLeft,
e.clientY - rectTop - clientTop
];
};
}
function utilAsyncMap(inputs, func, callback) {
var remaining = inputs.length;
var results = [];
var errors = [];
inputs.forEach(function(d, i2) {
func(d, function done(err, data) {
errors[i2] = err;
results[i2] = data;
remaining--;
if (!remaining)
callback(errors, results);
});
});
}
function utilWrap(index, length) {
if (index < 0) {
index += Math.ceil(-index / length) * length;
}
return index % length;
}
function utilFunctor(value) {
if (typeof value === "function")
return value;
return function() {
return value;
};
}
function utilNoAuto(selection2) {
var isText = selection2.size() && selection2.node().tagName.toLowerCase() === "textarea";
return selection2.attr("autocomplete", "new-password").attr("autocorrect", "off").attr("autocapitalize", "off").attr("spellcheck", isText ? "true" : "false");
}
function utilHashcode(str2) {
var hash = 0;
if (str2.length === 0) {
return hash;
}
for (var i2 = 0; i2 < str2.length; i2++) {
var char = str2.charCodeAt(i2);
hash = (hash << 5) - hash + char;
hash = hash & hash;
}
return hash;
}
function utilSafeClassName(str2) {
return str2.toLowerCase().replace(/[^a-z0-9]+/g, "_");
}
function utilUniqueDomId(val) {
return "ideditor-" + utilSafeClassName(val.toString()) + "-" + new Date().getTime().toString();
}
function utilUnicodeCharsCount(str2) {
return Array.from(str2).length;
}
function utilUnicodeCharsTruncated(str2, limit) {
return Array.from(str2).slice(0, limit).join("");
}
function toNumericID(id2) {
var match = id2.match(/^[cnwr](-?\d+)$/);
if (match) {
return parseInt(match[1], 10);
}
return NaN;
}
function compareNumericIDs(left, right) {
if (isNaN(left) && isNaN(right))
return -1;
if (isNaN(left))
return 1;
if (isNaN(right))
return -1;
if (Math.sign(left) !== Math.sign(right))
return -Math.sign(left);
if (Math.sign(left) < 0)
return Math.sign(right - left);
return Math.sign(left - right);
}
function utilCompareIDs(left, right) {
return compareNumericIDs(toNumericID(left), toNumericID(right));
}
function utilOldestID(ids) {
if (ids.length === 0) {
return void 0;
}
var oldestIDIndex = 0;
var oldestID = toNumericID(ids[0]);
for (var i2 = 1; i2 < ids.length; i2++) {
var num = toNumericID(ids[i2]);
if (compareNumericIDs(oldestID, num) === 1) {
oldestIDIndex = i2;
oldestID = num;
}
}
return ids[oldestIDIndex];
}
// modules/osm/entity.js
function osmEntity(attrs) {
if (this instanceof osmEntity)
return;
if (attrs && attrs.type) {
return osmEntity[attrs.type].apply(this, arguments);
} else if (attrs && attrs.id) {
return osmEntity[osmEntity.id.type(attrs.id)].apply(this, arguments);
}
return new osmEntity().initialize(arguments);
}
osmEntity.id = function(type3) {
return osmEntity.id.fromOSM(type3, osmEntity.id.next[type3]--);
};
osmEntity.id.next = {
changeset: -1,
node: -1,
way: -1,
relation: -1
};
osmEntity.id.fromOSM = function(type3, id2) {
return type3[0] + id2;
};
osmEntity.id.toOSM = function(id2) {
var match = id2.match(/^[cnwr](-?\d+)$/);
if (match) {
return match[1];
}
return "";
};
osmEntity.id.type = function(id2) {
return { "c": "changeset", "n": "node", "w": "way", "r": "relation" }[id2[0]];
};
osmEntity.key = function(entity) {
return entity.id + "v" + (entity.v || 0);
};
var _deprecatedTagValuesByKey;
osmEntity.deprecatedTagValuesByKey = function(dataDeprecated) {
if (!_deprecatedTagValuesByKey) {
_deprecatedTagValuesByKey = {};
dataDeprecated.forEach(function(d) {
var oldKeys = Object.keys(d.old);
if (oldKeys.length === 1) {
var oldKey = oldKeys[0];
var oldValue = d.old[oldKey];
if (oldValue !== "*") {
if (!_deprecatedTagValuesByKey[oldKey]) {
_deprecatedTagValuesByKey[oldKey] = [oldValue];
} else {
_deprecatedTagValuesByKey[oldKey].push(oldValue);
}
}
}
});
}
return _deprecatedTagValuesByKey;
};
osmEntity.prototype = {
tags: {},
initialize: function(sources) {
for (var i2 = 0; i2 < sources.length; ++i2) {
var source = sources[i2];
for (var prop in source) {
if (Object.prototype.hasOwnProperty.call(source, prop)) {
if (source[prop] === void 0) {
delete this[prop];
} else {
this[prop] = source[prop];
}
}
}
}
if (!this.id && this.type) {
this.id = osmEntity.id(this.type);
}
if (!this.hasOwnProperty("visible")) {
this.visible = true;
}
if (debug) {
Object.freeze(this);
Object.freeze(this.tags);
if (this.loc)
Object.freeze(this.loc);
if (this.nodes)
Object.freeze(this.nodes);
if (this.members)
Object.freeze(this.members);
}
return this;
},
copy: function(resolver, copies) {
if (copies[this.id])
return copies[this.id];
var copy2 = osmEntity(this, { id: void 0, user: void 0, version: void 0 });
copies[this.id] = copy2;
return copy2;
},
osmId: function() {
return osmEntity.id.toOSM(this.id);
},
isNew: function() {
var osmId = osmEntity.id.toOSM(this.id);
return osmId.length === 0 || osmId[0] === "-";
},
update: function(attrs) {
return osmEntity(this, attrs, { v: 1 + (this.v || 0) });
},
mergeTags: function(tags) {
var merged = Object.assign({}, this.tags);
var changed = false;
for (var k in tags) {
var t1 = merged[k];
var t2 = tags[k];
if (!t1) {
changed = true;
merged[k] = t2;
} else if (t1 !== t2) {
changed = true;
merged[k] = utilUnicodeCharsTruncated(utilArrayUnion(t1.split(/;\s*/), t2.split(/;\s*/)).join(";"), 255);
}
}
return changed ? this.update({ tags: merged }) : this;
},
intersects: function(extent, resolver) {
return this.extent(resolver).intersects(extent);
},
hasNonGeometryTags: function() {
return Object.keys(this.tags).some(function(k) {
return k !== "area";
});
},
hasParentRelations: function(resolver) {
return resolver.parentRelations(this).length > 0;
},
hasInterestingTags: function() {
return Object.keys(this.tags).some(osmIsInterestingTag);
},
isHighwayIntersection: function() {
return false;
},
isDegenerate: function() {
return true;
},
deprecatedTags: function(dataDeprecated) {
var tags = this.tags;
if (Object.keys(tags).length === 0)
return [];
var deprecated = [];
dataDeprecated.forEach(function(d) {
var oldKeys = Object.keys(d.old);
if (d.replace) {
var hasExistingValues = Object.keys(d.replace).some(function(replaceKey) {
if (!tags[replaceKey] || d.old[replaceKey])
return false;
var replaceValue = d.replace[replaceKey];
if (replaceValue === "*")
return false;
if (replaceValue === tags[replaceKey])
return false;
return true;
});
if (hasExistingValues)
return;
}
var matchesDeprecatedTags = oldKeys.every(function(oldKey) {
if (!tags[oldKey])
return false;
if (d.old[oldKey] === "*")
return true;
if (d.old[oldKey] === tags[oldKey])
return true;
var vals = tags[oldKey].split(";").filter(Boolean);
if (vals.length === 0) {
return false;
} else if (vals.length > 1) {
return vals.indexOf(d.old[oldKey]) !== -1;
} else {
if (tags[oldKey] === d.old[oldKey]) {
if (d.replace && d.old[oldKey] === d.replace[oldKey]) {
var replaceKeys = Object.keys(d.replace);
return !replaceKeys.every(function(replaceKey) {
return tags[replaceKey] === d.replace[replaceKey];
});
} else {
return true;
}
}
}
return false;
});
if (matchesDeprecatedTags) {
deprecated.push(d);
}
});
return deprecated;
}
};
// modules/osm/lanes.js
function osmLanes(entity) {
if (entity.type !== "way")
return null;
if (!entity.tags.highway)
return null;
var tags = entity.tags;
var isOneWay = entity.isOneWay();
var laneCount = getLaneCount(tags, isOneWay);
var maxspeed = parseMaxspeed(tags);
var laneDirections = parseLaneDirections(tags, isOneWay, laneCount);
var forward = laneDirections.forward;
var backward = laneDirections.backward;
var bothways = laneDirections.bothways;
var turnLanes = {};
turnLanes.unspecified = parseTurnLanes(tags["turn:lanes"]);
turnLanes.forward = parseTurnLanes(tags["turn:lanes:forward"]);
turnLanes.backward = parseTurnLanes(tags["turn:lanes:backward"]);
var maxspeedLanes = {};
maxspeedLanes.unspecified = parseMaxspeedLanes(tags["maxspeed:lanes"], maxspeed);
maxspeedLanes.forward = parseMaxspeedLanes(tags["maxspeed:lanes:forward"], maxspeed);
maxspeedLanes.backward = parseMaxspeedLanes(tags["maxspeed:lanes:backward"], maxspeed);
var psvLanes = {};
psvLanes.unspecified = parseMiscLanes(tags["psv:lanes"]);
psvLanes.forward = parseMiscLanes(tags["psv:lanes:forward"]);
psvLanes.backward = parseMiscLanes(tags["psv:lanes:backward"]);
var busLanes = {};
busLanes.unspecified = parseMiscLanes(tags["bus:lanes"]);
busLanes.forward = parseMiscLanes(tags["bus:lanes:forward"]);
busLanes.backward = parseMiscLanes(tags["bus:lanes:backward"]);
var taxiLanes = {};
taxiLanes.unspecified = parseMiscLanes(tags["taxi:lanes"]);
taxiLanes.forward = parseMiscLanes(tags["taxi:lanes:forward"]);
taxiLanes.backward = parseMiscLanes(tags["taxi:lanes:backward"]);
var hovLanes = {};
hovLanes.unspecified = parseMiscLanes(tags["hov:lanes"]);
hovLanes.forward = parseMiscLanes(tags["hov:lanes:forward"]);
hovLanes.backward = parseMiscLanes(tags["hov:lanes:backward"]);
var hgvLanes = {};
hgvLanes.unspecified = parseMiscLanes(tags["hgv:lanes"]);
hgvLanes.forward = parseMiscLanes(tags["hgv:lanes:forward"]);
hgvLanes.backward = parseMiscLanes(tags["hgv:lanes:backward"]);
var bicyclewayLanes = {};
bicyclewayLanes.unspecified = parseBicycleWay(tags["bicycleway:lanes"]);
bicyclewayLanes.forward = parseBicycleWay(tags["bicycleway:lanes:forward"]);
bicyclewayLanes.backward = parseBicycleWay(tags["bicycleway:lanes:backward"]);
var lanesObj = {
forward: [],
backward: [],
unspecified: []
};
mapToLanesObj(lanesObj, turnLanes, "turnLane");
mapToLanesObj(lanesObj, maxspeedLanes, "maxspeed");
mapToLanesObj(lanesObj, psvLanes, "psv");
mapToLanesObj(lanesObj, busLanes, "bus");
mapToLanesObj(lanesObj, taxiLanes, "taxi");
mapToLanesObj(lanesObj, hovLanes, "hov");
mapToLanesObj(lanesObj, hgvLanes, "hgv");
mapToLanesObj(lanesObj, bicyclewayLanes, "bicycleway");
return {
metadata: {
count: laneCount,
oneway: isOneWay,
forward,
backward,
bothways,
turnLanes,
maxspeed,
maxspeedLanes,
psvLanes,
busLanes,
taxiLanes,
hovLanes,
hgvLanes,
bicyclewayLanes
},
lanes: lanesObj
};
}
function getLaneCount(tags, isOneWay) {
var count;
if (tags.lanes) {
count = parseInt(tags.lanes, 10);
if (count > 0) {
return count;
}
}
switch (tags.highway) {
case "trunk":
case "motorway":
count = isOneWay ? 2 : 4;
break;
default:
count = isOneWay ? 1 : 2;
break;
}
return count;
}
function parseMaxspeed(tags) {
var maxspeed = tags.maxspeed;
if (!maxspeed)
return;
var maxspeedRegex = /^([0-9][\.0-9]+?)(?:[ ]?(?:km\/h|kmh|kph|mph|knots))?$/;
if (!maxspeedRegex.test(maxspeed))
return;
return parseInt(maxspeed, 10);
}
function parseLaneDirections(tags, isOneWay, laneCount) {
var forward = parseInt(tags["lanes:forward"], 10);
var backward = parseInt(tags["lanes:backward"], 10);
var bothways = parseInt(tags["lanes:both_ways"], 10) > 0 ? 1 : 0;
if (parseInt(tags.oneway, 10) === -1) {
forward = 0;
bothways = 0;
backward = laneCount;
} else if (isOneWay) {
forward = laneCount;
bothways = 0;
backward = 0;
} else if (isNaN(forward) && isNaN(backward)) {
backward = Math.floor((laneCount - bothways) / 2);
forward = laneCount - bothways - backward;
} else if (isNaN(forward)) {
if (backward > laneCount - bothways) {
backward = laneCount - bothways;
}
forward = laneCount - bothways - backward;
} else if (isNaN(backward)) {
if (forward > laneCount - bothways) {
forward = laneCount - bothways;
}
backward = laneCount - bothways - forward;
}
return {
forward,
backward,
bothways
};
}
function parseTurnLanes(tag) {
if (!tag)
return;
var validValues = [
"left",
"slight_left",
"sharp_left",
"through",
"right",
"slight_right",
"sharp_right",
"reverse",
"merge_to_left",
"merge_to_right",
"none"
];
return tag.split("|").map(function(s) {
if (s === "")
s = "none";
return s.split(";").map(function(d) {
return validValues.indexOf(d) === -1 ? "unknown" : d;
});
});
}
function parseMaxspeedLanes(tag, maxspeed) {
if (!tag)
return;
return tag.split("|").map(function(s) {
if (s === "none")
return s;
var m = parseInt(s, 10);
if (s === "" || m === maxspeed)
return null;
return isNaN(m) ? "unknown" : m;
});
}
function parseMiscLanes(tag) {
if (!tag)
return;
var validValues = [
"yes",
"no",
"designated"
];
return tag.split("|").map(function(s) {
if (s === "")
s = "no";
return validValues.indexOf(s) === -1 ? "unknown" : s;
});
}
function parseBicycleWay(tag) {
if (!tag)
return;
var validValues = [
"yes",
"no",
"designated",
"lane"
];
return tag.split("|").map(function(s) {
if (s === "")
s = "no";
return validValues.indexOf(s) === -1 ? "unknown" : s;
});
}
function mapToLanesObj(lanesObj, data, key) {
if (data.forward) {
data.forward.forEach(function(l, i2) {
if (!lanesObj.forward[i2])
lanesObj.forward[i2] = {};
lanesObj.forward[i2][key] = l;
});
}
if (data.backward) {
data.backward.forEach(function(l, i2) {
if (!lanesObj.backward[i2])
lanesObj.backward[i2] = {};
lanesObj.backward[i2][key] = l;
});
}
if (data.unspecified) {
data.unspecified.forEach(function(l, i2) {
if (!lanesObj.unspecified[i2])
lanesObj.unspecified[i2] = {};
lanesObj.unspecified[i2][key] = l;
});
}
}
// modules/osm/way.js
function osmWay() {
if (!(this instanceof osmWay)) {
return new osmWay().initialize(arguments);
} else if (arguments.length) {
this.initialize(arguments);
}
}
osmEntity.way = osmWay;
osmWay.prototype = Object.create(osmEntity.prototype);
Object.assign(osmWay.prototype, {
type: "way",
nodes: [],
copy: function(resolver, copies) {
if (copies[this.id])
return copies[this.id];
var copy2 = osmEntity.prototype.copy.call(this, resolver, copies);
var nodes = this.nodes.map(function(id2) {
return resolver.entity(id2).copy(resolver, copies).id;
});
copy2 = copy2.update({ nodes });
copies[this.id] = copy2;
return copy2;
},
extent: function(resolver) {
return resolver.transient(this, "extent", function() {
var extent = geoExtent();
for (var i2 = 0; i2 < this.nodes.length; i2++) {
var node = resolver.hasEntity(this.nodes[i2]);
if (node) {
extent._extend(node.extent());
}
}
return extent;
});
},
first: function() {
return this.nodes[0];
},
last: function() {
return this.nodes[this.nodes.length - 1];
},
contains: function(node) {
return this.nodes.indexOf(node) >= 0;
},
affix: function(node) {
if (this.nodes[0] === node)
return "prefix";
if (this.nodes[this.nodes.length - 1] === node)
return "suffix";
},
layer: function() {
if (isFinite(this.tags.layer)) {
return Math.max(-10, Math.min(+this.tags.layer, 10));
}
if (this.tags.covered === "yes")
return -1;
if (this.tags.location === "overground")
return 1;
if (this.tags.location === "underground")
return -1;
if (this.tags.location === "underwater")
return -10;
if (this.tags.power === "line")
return 10;
if (this.tags.power === "minor_line")
return 10;
if (this.tags.aerialway)
return 10;
if (this.tags.bridge)
return 1;
if (this.tags.cutting)
return -1;
if (this.tags.tunnel)
return -1;
if (this.tags.waterway)
return -1;
if (this.tags.man_made === "pipeline")
return -10;
if (this.tags.boundary)
return -10;
return 0;
},
impliedLineWidthMeters: function() {
var averageWidths = {
highway: {
motorway: 5,
motorway_link: 5,
trunk: 4.5,
trunk_link: 4.5,
primary: 4,
secondary: 4,
tertiary: 4,
primary_link: 4,
secondary_link: 4,
tertiary_link: 4,
unclassified: 4,
road: 4,
living_street: 4,
bus_guideway: 4,
pedestrian: 4,
residential: 3.5,
service: 3.5,
track: 3,
cycleway: 2.5,
bridleway: 2,
corridor: 2,
steps: 2,
path: 1.5,
footway: 1.5
},
railway: {
rail: 2.5,
light_rail: 2.5,
tram: 2.5,
subway: 2.5,
monorail: 2.5,
funicular: 2.5,
disused: 2.5,
preserved: 2.5,
miniature: 1.5,
narrow_gauge: 1.5
},
waterway: {
river: 50,
canal: 25,
stream: 5,
tidal_channel: 5,
fish_pass: 2.5,
drain: 2.5,
ditch: 1.5
}
};
for (var key in averageWidths) {
if (this.tags[key] && averageWidths[key][this.tags[key]]) {
var width = averageWidths[key][this.tags[key]];
if (key === "highway") {
var laneCount = this.tags.lanes && parseInt(this.tags.lanes, 10);
if (!laneCount)
laneCount = this.isOneWay() ? 1 : 2;
return width * laneCount;
}
return width;
}
}
return null;
},
isOneWay: function() {
var values = {
"yes": true,
"1": true,
"-1": true,
"reversible": true,
"alternating": true,
"no": false,
"0": false
};
if (values[this.tags.oneway] !== void 0) {
return values[this.tags.oneway];
}
for (var key in this.tags) {
if (key in osmOneWayTags && this.tags[key] in osmOneWayTags[key]) {
return true;
}
}
return false;
},
sidednessIdentifier: function() {
for (var key in this.tags) {
var value = this.tags[key];
if (key in osmRightSideIsInsideTags && value in osmRightSideIsInsideTags[key]) {
if (osmRightSideIsInsideTags[key][value] === true) {
return key;
} else {
return osmRightSideIsInsideTags[key][value];
}
}
}
return null;
},
isSided: function() {
if (this.tags.two_sided === "yes") {
return false;
}
return this.sidednessIdentifier() !== null;
},
lanes: function() {
return osmLanes(this);
},
isClosed: function() {
return this.nodes.length > 1 && this.first() === this.last();
},
isConvex: function(resolver) {
if (!this.isClosed() || this.isDegenerate())
return null;
var nodes = utilArrayUniq(resolver.childNodes(this));
var coords = nodes.map(function(n2) {
return n2.loc;
});
var curr = 0;
var prev = 0;
for (var i2 = 0; i2 < coords.length; i2++) {
var o = coords[(i2 + 1) % coords.length];
var a = coords[i2];
var b = coords[(i2 + 2) % coords.length];
var res = geoVecCross(a, b, o);
curr = res > 0 ? 1 : res < 0 ? -1 : 0;
if (curr === 0) {
continue;
} else if (prev && curr !== prev) {
return false;
}
prev = curr;
}
return true;
},
tagSuggestingArea: function() {
return osmTagSuggestingArea(this.tags);
},
isArea: function() {
if (this.tags.area === "yes")
return true;
if (!this.isClosed() || this.tags.area === "no")
return false;
return this.tagSuggestingArea() !== null;
},
isDegenerate: function() {
return new Set(this.nodes).size < (this.isArea() ? 3 : 2);
},
areAdjacent: function(n1, n2) {
for (var i2 = 0; i2 < this.nodes.length; i2++) {
if (this.nodes[i2] === n1) {
if (this.nodes[i2 - 1] === n2)
return true;
if (this.nodes[i2 + 1] === n2)
return true;
}
}
return false;
},
geometry: function(graph) {
return graph.transient(this, "geometry", function() {
return this.isArea() ? "area" : "line";
});
},
segments: function(graph) {
function segmentExtent(graph2) {
var n1 = graph2.hasEntity(this.nodes[0]);
var n2 = graph2.hasEntity(this.nodes[1]);
return n1 && n2 && geoExtent([
[
Math.min(n1.loc[0], n2.loc[0]),
Math.min(n1.loc[1], n2.loc[1])
],
[
Math.max(n1.loc[0], n2.loc[0]),
Math.max(n1.loc[1], n2.loc[1])
]
]);
}
return graph.transient(this, "segments", function() {
var segments = [];
for (var i2 = 0; i2 < this.nodes.length - 1; i2++) {
segments.push({
id: this.id + "-" + i2,
wayId: this.id,
index: i2,
nodes: [this.nodes[i2], this.nodes[i2 + 1]],
extent: segmentExtent
});
}
return segments;
});
},
close: function() {
if (this.isClosed() || !this.nodes.length)
return this;
var nodes = this.nodes.slice();
nodes = nodes.filter(noRepeatNodes);
nodes.push(nodes[0]);
return this.update({ nodes });
},
unclose: function() {
if (!this.isClosed())
return this;
var nodes = this.nodes.slice();
var connector = this.first();
var i2 = nodes.length - 1;
while (i2 > 0 && nodes.length > 1 && nodes[i2] === connector) {
nodes.splice(i2, 1);
i2 = nodes.length - 1;
}
nodes = nodes.filter(noRepeatNodes);
return this.update({ nodes });
},
addNode: function(id2, index) {
var nodes = this.nodes.slice();
var isClosed = this.isClosed();
var max3 = isClosed ? nodes.length - 1 : nodes.length;
if (index === void 0) {
index = max3;
}
if (index < 0 || index > max3) {
throw new RangeError("index " + index + " out of range 0.." + max3);
}
if (isClosed) {
var connector = this.first();
var i2 = 1;
while (i2 < nodes.length && nodes.length > 2 && nodes[i2] === connector) {
nodes.splice(i2, 1);
if (index > i2)
index--;
}
i2 = nodes.length - 1;
while (i2 > 0 && nodes.length > 1 && nodes[i2] === connector) {
nodes.splice(i2, 1);
if (index > i2)
index--;
i2 = nodes.length - 1;
}
}
nodes.splice(index, 0, id2);
nodes = nodes.filter(noRepeatNodes);
if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
nodes.push(nodes[0]);
}
return this.update({ nodes });
},
updateNode: function(id2, index) {
var nodes = this.nodes.slice();
var isClosed = this.isClosed();
var max3 = nodes.length - 1;
if (index === void 0 || index < 0 || index > max3) {
throw new RangeError("index " + index + " out of range 0.." + max3);
}
if (isClosed) {
var connector = this.first();
var i2 = 1;
while (i2 < nodes.length && nodes.length > 2 && nodes[i2] === connector) {
nodes.splice(i2, 1);
if (index > i2)
index--;
}
i2 = nodes.length - 1;
while (i2 > 0 && nodes.length > 1 && nodes[i2] === connector) {
nodes.splice(i2, 1);
if (index === i2)
index = 0;
i2 = nodes.length - 1;
}
}
nodes.splice(index, 1, id2);
nodes = nodes.filter(noRepeatNodes);
if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
nodes.push(nodes[0]);
}
return this.update({ nodes });
},
replaceNode: function(needleID, replacementID) {
var nodes = this.nodes.slice();
var isClosed = this.isClosed();
for (var i2 = 0; i2 < nodes.length; i2++) {
if (nodes[i2] === needleID) {
nodes[i2] = replacementID;
}
}
nodes = nodes.filter(noRepeatNodes);
if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
nodes.push(nodes[0]);
}
return this.update({ nodes });
},
removeNode: function(id2) {
var nodes = this.nodes.slice();
var isClosed = this.isClosed();
nodes = nodes.filter(function(node) {
return node !== id2;
}).filter(noRepeatNodes);
if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
nodes.push(nodes[0]);
}
return this.update({ nodes });
},
asJXON: function(changeset_id) {
var r = {
way: {
"@id": this.osmId(),
"@version": this.version || 0,
nd: this.nodes.map(function(id2) {
return { keyAttributes: { ref: osmEntity.id.toOSM(id2) } };
}, this),
tag: Object.keys(this.tags).map(function(k) {
return { keyAttributes: { k, v: this.tags[k] } };
}, this)
}
};
if (changeset_id) {
r.way["@changeset"] = changeset_id;
}
return r;
},
asGeoJSON: function(resolver) {
return resolver.transient(this, "GeoJSON", function() {
var coordinates = resolver.childNodes(this).map(function(n2) {
return n2.loc;
});
if (this.isArea() && this.isClosed()) {
return {
type: "Polygon",
coordinates: [coordinates]
};
} else {
return {
type: "LineString",
coordinates
};
}
});
},
area: function(resolver) {
return resolver.transient(this, "area", function() {
var nodes = resolver.childNodes(this);
var json = {
type: "Polygon",
coordinates: [nodes.map(function(n2) {
return n2.loc;
})]
};
if (!this.isClosed() && nodes.length) {
json.coordinates[0].push(nodes[0].loc);
}
var area = area_default(json);
if (area > 2 * Math.PI) {
json.coordinates[0] = json.coordinates[0].reverse();
area = area_default(json);
}
return isNaN(area) ? 0 : area;
});
}
});
function noRepeatNodes(node, i2, arr) {
return i2 === 0 || node !== arr[i2 - 1];
}
// modules/osm/multipolygon.js
function osmOldMultipolygonOuterMemberOfRelation(entity, graph) {
if (entity.type !== "relation" || !entity.isMultipolygon() || Object.keys(entity.tags).filter(osmIsInterestingTag).length > 1) {
return false;
}
var outerMember;
for (var memberIndex in entity.members) {
var member = entity.members[memberIndex];
if (!member.role || member.role === "outer") {
if (outerMember)
return false;
if (member.type !== "way")
return false;
if (!graph.hasEntity(member.id))
return false;
outerMember = graph.entity(member.id);
if (Object.keys(outerMember.tags).filter(osmIsInterestingTag).length === 0) {
return false;
}
}
}
return outerMember;
}
function osmIsOldMultipolygonOuterMember(entity, graph) {
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;
var parent = parents[0];
if (!parent.isMultipolygon() || Object.keys(parent.tags).filter(osmIsInterestingTag).length > 1) {
return false;
}
var members = parent.members, member;
for (var i2 = 0; i2 < members.length; i2++) {
member = members[i2];
if (member.id === entity.id && member.role && member.role !== "outer") {
return false;
}
if (member.id !== entity.id && (!member.role || member.role === "outer")) {
return false;
}
}
return parent;
}
function osmOldMultipolygonOuterMember(entity, graph) {
if (entity.type !== "way")
return false;
var parents = graph.parentRelations(entity);
if (parents.length !== 1)
return false;
var parent = parents[0];
if (!parent.isMultipolygon() || Object.keys(parent.tags).filter(osmIsInterestingTag).length > 1) {
return false;
}
var members = parent.members, member, outerMember;
for (var i2 = 0; i2 < members.length; i2++) {
member = members[i2];
if (!member.role || member.role === "outer") {
if (outerMember)
return false;
outerMember = member;
}
}
if (!outerMember)
return false;
var outerEntity = graph.hasEntity(outerMember.id);
if (!outerEntity || !Object.keys(outerEntity.tags).filter(osmIsInterestingTag).length) {
return false;
}
return outerEntity;
}
function osmJoinWays(toJoin, graph) {
function resolve(member) {
return graph.childNodes(graph.entity(member.id));
}
function reverse(item2) {
var action = actionReverse(item2.id, { reverseOneway: true });
sequences.actions.push(action);
return item2 instanceof osmWay ? action(graph).entity(item2.id) : item2;
}
toJoin = toJoin.filter(function(member) {
return member.type === "way" && graph.hasEntity(member.id);
});
var i2;
var joinAsMembers = true;
for (i2 = 0; i2 < toJoin.length; i2++) {
if (toJoin[i2] instanceof osmWay) {
joinAsMembers = false;
break;
}
}
var sequences = [];
sequences.actions = [];
while (toJoin.length) {
var item = toJoin.shift();
var currWays = [item];
var currNodes = resolve(item).slice();
while (toJoin.length) {
var start2 = currNodes[0];
var end = currNodes[currNodes.length - 1];
var fn = null;
var nodes = null;
for (i2 = 0; i2 < toJoin.length; i2++) {
item = toJoin[i2];
nodes = resolve(item);
if (joinAsMembers && currWays.length === 1 && nodes[0] !== end && nodes[nodes.length - 1] !== end && (nodes[nodes.length - 1] === start2 || nodes[0] === start2)) {
currWays[0] = reverse(currWays[0]);
currNodes.reverse();
start2 = currNodes[0];
end = currNodes[currNodes.length - 1];
}
if (nodes[0] === end) {
fn = currNodes.push;
nodes = nodes.slice(1);
break;
} else if (nodes[nodes.length - 1] === end) {
fn = currNodes.push;
nodes = nodes.slice(0, -1).reverse();
item = reverse(item);
break;
} else if (nodes[nodes.length - 1] === start2) {
fn = currNodes.unshift;
nodes = nodes.slice(0, -1);
break;
} else if (nodes[0] === start2) {
fn = currNodes.unshift;
nodes = nodes.slice(1).reverse();
item = reverse(item);
break;
} else {
fn = nodes = null;
}
}
if (!nodes) {
break;
}
fn.apply(currWays, [item]);
fn.apply(currNodes, nodes);
toJoin.splice(i2, 1);
}
currWays.nodes = currNodes;
sequences.push(currWays);
}
return sequences;
}
// modules/actions/add_member.js
function actionAddMember(relationId, member, memberIndex, insertPair) {
return function action(graph) {
var relation = graph.entity(relationId);
var isPTv2 = /stop|platform/.test(member.role);
if ((isNaN(memberIndex) || insertPair) && member.type === "way" && !isPTv2) {
graph = addWayMember(relation, graph);
} else {
if (isPTv2 && isNaN(memberIndex)) {
memberIndex = 0;
}
graph = graph.replace(relation.addMember(member, memberIndex));
}
return graph;
};
function addWayMember(relation, graph) {
var groups, tempWay, insertPairIsReversed, item, i2, j2, k;
var PTv2members = [];
var members = [];
for (i2 = 0; i2 < relation.members.length; i2++) {
var m = relation.members[i2];
if (/stop|platform/.test(m.role)) {
PTv2members.push(m);
} else {
members.push(m);
}
}
relation = relation.update({ members });
if (insertPair) {
tempWay = osmWay({ id: "wTemp", nodes: insertPair.nodes });
graph = graph.replace(tempWay);
var tempMember = { id: tempWay.id, type: "way", role: member.role };
var tempRelation = relation.replaceMember({ id: insertPair.originalID }, tempMember, true);
groups = utilArrayGroupBy(tempRelation.members, "type");
groups.way = groups.way || [];
var originalWay = graph.entity(insertPair.originalID);
var insertedWay = graph.entity(insertPair.insertedID);
insertPairIsReversed = originalWay.nodes.length > 0 && insertedWay.nodes.length > 0 && insertedWay.nodes[insertedWay.nodes.length - 1] === originalWay.nodes[0] && originalWay.nodes[originalWay.nodes.length - 1] !== insertedWay.nodes[0];
} else {
groups = utilArrayGroupBy(relation.members, "type");
groups.way = groups.way || [];
groups.way.push(member);
}
members = withIndex(groups.way);
var joined = osmJoinWays(members, graph);
for (i2 = 0; i2 < joined.length; i2++) {
var segment = joined[i2];
var nodes = segment.nodes.slice();
var startIndex = segment[0].index;
for (j2 = 0; j2 < members.length; j2++) {
if (members[j2].index === startIndex) {
break;
}
}
for (k = 0; k < segment.length; k++) {
item = segment[k];
var way = graph.entity(item.id);
if (tempWay && item.id === tempWay.id) {
var reverse = nodes[0].id !== insertPair.nodes[0] ^ insertPairIsReversed;
if (reverse) {
item.pair = [
{ id: insertPair.insertedID, type: "way", role: item.role },
{ id: insertPair.originalID, type: "way", role: item.role }
];
} else {
item.pair = [
{ id: insertPair.originalID, type: "way", role: item.role },
{ id: insertPair.insertedID, type: "way", role: item.role }
];
}
}
if (k > 0) {
if (j2 + k >= members.length || item.index !== members[j2 + k].index) {
moveMember(members, item.index, j2 + k);
}
}
nodes.splice(0, way.nodes.length - 1);
}
}
if (tempWay) {
graph = graph.remove(tempWay);
}
var wayMembers = [];
for (i2 = 0; i2 < members.length; i2++) {
item = members[i2];
if (item.index === -1)
continue;
if (item.pair) {
wayMembers.push(item.pair[0]);
wayMembers.push(item.pair[1]);
} else {
wayMembers.push(utilObjectOmit(item, ["index"]));
}
}
var newMembers = PTv2members.concat(groups.node || [], wayMembers, groups.relation || []);
return graph.replace(relation.update({ members: newMembers }));
function moveMember(arr, findIndex, toIndex) {
var i3;
for (i3 = 0; i3 < arr.length; i3++) {
if (arr[i3].index === findIndex) {
break;
}
}
var item2 = Object.assign({}, arr[i3]);
arr[i3].index = -1;
item2.index = toIndex;
arr.splice(toIndex, 0, item2);
}
function withIndex(arr) {
var result = new Array(arr.length);
for (var i3 = 0; i3 < arr.length; i3++) {
result[i3] = Object.assign({}, arr[i3]);
result[i3].index = i3;
}
return result;
}
}
}
// modules/actions/add_midpoint.js
function actionAddMidpoint(midpoint, node) {
return function(graph) {
graph = graph.replace(node.move(midpoint.loc));
var parents = utilArrayIntersection(graph.parentWays(graph.entity(midpoint.edge[0])), graph.parentWays(graph.entity(midpoint.edge[1])));
parents.forEach(function(way) {
for (var i2 = 0; i2 < way.nodes.length - 1; i2++) {
if (geoEdgeEqual([way.nodes[i2], way.nodes[i2 + 1]], midpoint.edge)) {
graph = graph.replace(graph.entity(way.id).addNode(node.id, i2 + 1));
return;
}
}
});
return graph;
};
}
// modules/actions/add_vertex.js
function actionAddVertex(wayId, nodeId, index) {
return function(graph) {
return graph.replace(graph.entity(wayId).addNode(nodeId, index));
};
}
// modules/actions/change_member.js
function actionChangeMember(relationId, member, memberIndex) {
return function(graph) {
return graph.replace(graph.entity(relationId).updateMember(member, memberIndex));
};
}
// modules/actions/change_preset.js
function actionChangePreset(entityID, oldPreset, newPreset, skipFieldDefaults) {
return function action(graph) {
var entity = graph.entity(entityID);
var geometry = entity.geometry(graph);
var tags = entity.tags;
if (oldPreset)
tags = oldPreset.unsetTags(tags, geometry, newPreset && newPreset.addTags ? Object.keys(newPreset.addTags) : null);
if (newPreset)
tags = newPreset.setTags(tags, geometry, skipFieldDefaults);
return graph.replace(entity.update({ tags }));
};
}
// modules/actions/change_tags.js
function actionChangeTags(entityId, tags) {
return function(graph) {
var entity = graph.entity(entityId);
return graph.replace(entity.update({ tags }));
};
}
// modules/osm/node.js
function osmNode() {
if (!(this instanceof osmNode)) {
return new osmNode().initialize(arguments);
} else if (arguments.length) {
this.initialize(arguments);
}
}
osmEntity.node = osmNode;
osmNode.prototype = Object.create(osmEntity.prototype);
Object.assign(osmNode.prototype, {
type: "node",
loc: [9999, 9999],
extent: function() {
return new geoExtent(this.loc);
},
geometry: function(graph) {
return graph.transient(this, "geometry", function() {
return graph.isPoi(this) ? "point" : "vertex";
});
},
move: function(loc) {
return this.update({ loc });
},
isDegenerate: function() {
return !(Array.isArray(this.loc) && this.loc.length === 2 && this.loc[0] >= -180 && this.loc[0] <= 180 && this.loc[1] >= -90 && this.loc[1] <= 90);
},
directions: function(resolver, projection2) {
var val;
var i2;
if (this.isHighwayIntersection(resolver) && (this.tags.stop || "").toLowerCase() === "all") {
val = "all";
} else {
val = (this.tags.direction || "").toLowerCase();
var re2 = /:direction$/i;
var keys = Object.keys(this.tags);
for (i2 = 0; i2 < keys.length; i2++) {
if (re2.test(keys[i2])) {
val = this.tags[keys[i2]].toLowerCase();
break;
}
}
}
if (val === "")
return [];
var cardinal = {
north: 0,
n: 0,
northnortheast: 22,
nne: 22,
northeast: 45,
ne: 45,
eastnortheast: 67,
ene: 67,
east: 90,
e: 90,
eastsoutheast: 112,
ese: 112,
southeast: 135,
se: 135,
southsoutheast: 157,
sse: 157,
south: 180,
s: 180,
southsouthwest: 202,
ssw: 202,
southwest: 225,
sw: 225,
westsouthwest: 247,
wsw: 247,
west: 270,
w: 270,
westnorthwest: 292,
wnw: 292,
northwest: 315,
nw: 315,
northnorthwest: 337,
nnw: 337
};
var values = val.split(";");
var results = [];
values.forEach(function(v) {
if (cardinal[v] !== void 0) {
v = cardinal[v];
}
if (v !== "" && !isNaN(+v)) {
results.push(+v);
return;
}
var lookBackward = this.tags["traffic_sign:backward"] || v === "backward" || v === "both" || v === "all";
var lookForward = this.tags["traffic_sign:forward"] || v === "forward" || v === "both" || v === "all";
if (!lookForward && !lookBackward)
return;
var nodeIds = {};
resolver.parentWays(this).forEach(function(parent) {
var nodes = parent.nodes;
for (i2 = 0; i2 < nodes.length; i2++) {
if (nodes[i2] === this.id) {
if (lookForward && i2 > 0) {
nodeIds[nodes[i2 - 1]] = true;
}
if (lookBackward && i2 < nodes.length - 1) {
nodeIds[nodes[i2 + 1]] = true;
}
}
}
}, this);
Object.keys(nodeIds).forEach(function(nodeId) {
results.push(geoAngle(this, resolver.entity(nodeId), projection2) * (180 / Math.PI) + 90);
}, this);
}, this);
return utilArrayUniq(results);
},
isCrossing: function() {
return this.tags.highway === "crossing" || this.tags.railway && this.tags.railway.indexOf("crossing") !== -1;
},
isEndpoint: function(resolver) {
return resolver.transient(this, "isEndpoint", function() {
var id2 = this.id;
return resolver.parentWays(this).filter(function(parent) {
return !parent.isClosed() && !!parent.affix(id2);
}).length > 0;
});
},
isConnected: function(resolver) {
return resolver.transient(this, "isConnected", function() {
var parents = resolver.parentWays(this);
if (parents.length > 1) {
for (var i2 in parents) {
if (parents[i2].geometry(resolver) === "line" && parents[i2].hasInterestingTags())
return true;
}
} else if (parents.length === 1) {
var way = parents[0];
var nodes = way.nodes.slice();
if (way.isClosed()) {
nodes.pop();
}
return nodes.indexOf(this.id) !== nodes.lastIndexOf(this.id);
}
return false;
});
},
parentIntersectionWays: function(resolver) {
return resolver.transient(this, "parentIntersectionWays", function() {
return resolver.parentWays(this).filter(function(parent) {
return (parent.tags.highway || parent.tags.waterway || parent.tags.railway || parent.tags.aeroway) && parent.geometry(resolver) === "line";
});
});
},
isIntersection: function(resolver) {
return this.parentIntersectionWays(resolver).length > 1;
},
isHighwayIntersection: function(resolver) {
return resolver.transient(this, "isHighwayIntersection", function() {
return resolver.parentWays(this).filter(function(parent) {
return parent.tags.highway && parent.geometry(resolver) === "line";
}).length > 1;
});
},
isOnAddressLine: function(resolver) {
return resolver.transient(this, "isOnAddressLine", function() {
return resolver.parentWays(this).filter(function(parent) {
return parent.tags.hasOwnProperty("addr:interpolation") && parent.geometry(resolver) === "line";
}).length > 0;
});
},
asJXON: function(changeset_id) {
var r = {
node: {
"@id": this.osmId(),
"@lon": this.loc[0],
"@lat": this.loc[1],
"@version": this.version || 0,
tag: Object.keys(this.tags).map(function(k) {
return { keyAttributes: { k, v: this.tags[k] } };
}, this)
}
};
if (changeset_id)
r.node["@changeset"] = changeset_id;
return r;
},
asGeoJSON: function() {
return {
type: "Point",
coordinates: this.loc
};
}
});
// modules/actions/circularize.js
function actionCircularize(wayId, projection2, maxAngle) {
maxAngle = (maxAngle || 20) * Math.PI / 180;
var action = function(graph, t) {
if (t === null || !isFinite(t))
t = 1;
t = Math.min(Math.max(+t, 0), 1);
var way = graph.entity(wayId);
var origNodes = {};
graph.childNodes(way).forEach(function(node2) {
if (!origNodes[node2.id])
origNodes[node2.id] = node2;
});
if (!way.isConvex(graph)) {
graph = action.makeConvex(graph);
}
var nodes = utilArrayUniq(graph.childNodes(way));
var keyNodes = nodes.filter(function(n2) {
return graph.parentWays(n2).length !== 1;
});
var points = nodes.map(function(n2) {
return projection2(n2.loc);
});
var keyPoints = keyNodes.map(function(n2) {
return projection2(n2.loc);
});
var centroid = points.length === 2 ? geoVecInterp(points[0], points[1], 0.5) : centroid_default2(points);
var radius = median(points, function(p) {
return geoVecLength(centroid, p);
});
var sign2 = area_default3(points) > 0 ? 1 : -1;
var ids, i2, j2, k;
if (!keyNodes.length) {
keyNodes = [nodes[0]];
keyPoints = [points[0]];
}
if (keyNodes.length === 1) {
var index = nodes.indexOf(keyNodes[0]);
var oppositeIndex = Math.floor((index + nodes.length / 2) % nodes.length);
keyNodes.push(nodes[oppositeIndex]);
keyPoints.push(points[oppositeIndex]);
}
for (i2 = 0; i2 < keyPoints.length; i2++) {
var nextKeyNodeIndex = (i2 + 1) % keyNodes.length;
var startNode = keyNodes[i2];
var endNode = keyNodes[nextKeyNodeIndex];
var startNodeIndex = nodes.indexOf(startNode);
var endNodeIndex = nodes.indexOf(endNode);
var numberNewPoints = -1;
var indexRange = endNodeIndex - startNodeIndex;
var nearNodes = {};
var inBetweenNodes = [];
var startAngle, endAngle, totalAngle, eachAngle;
var angle2, loc, node, origNode;
if (indexRange < 0) {
indexRange += nodes.length;
}
var distance = geoVecLength(centroid, keyPoints[i2]) || 1e-4;
keyPoints[i2] = [
centroid[0] + (keyPoints[i2][0] - centroid[0]) / distance * radius,
centroid[1] + (keyPoints[i2][1] - centroid[1]) / distance * radius
];
loc = projection2.invert(keyPoints[i2]);
node = keyNodes[i2];
origNode = origNodes[node.id];
node = node.move(geoVecInterp(origNode.loc, loc, t));
graph = graph.replace(node);
startAngle = Math.atan2(keyPoints[i2][1] - centroid[1], keyPoints[i2][0] - centroid[0]);
endAngle = Math.atan2(keyPoints[nextKeyNodeIndex][1] - centroid[1], keyPoints[nextKeyNodeIndex][0] - centroid[0]);
totalAngle = endAngle - startAngle;
if (totalAngle * sign2 > 0) {
totalAngle = -sign2 * (2 * Math.PI - Math.abs(totalAngle));
}
do {
numberNewPoints++;
eachAngle = totalAngle / (indexRange + numberNewPoints);
} while (Math.abs(eachAngle) > maxAngle);
for (j2 = 1; j2 < indexRange; j2++) {
angle2 = startAngle + j2 * eachAngle;
loc = projection2.invert([
centroid[0] + Math.cos(angle2) * radius,
centroid[1] + Math.sin(angle2) * radius
]);
node = nodes[(j2 + startNodeIndex) % nodes.length];
origNode = origNodes[node.id];
nearNodes[node.id] = angle2;
node = node.move(geoVecInterp(origNode.loc, loc, t));
graph = graph.replace(node);
}
for (j2 = 0; j2 < numberNewPoints; j2++) {
angle2 = startAngle + (indexRange + j2) * eachAngle;
loc = projection2.invert([
centroid[0] + Math.cos(angle2) * radius,
centroid[1] + Math.sin(angle2) * radius
]);
var min3 = Infinity;
for (var nodeId in nearNodes) {
var nearAngle = nearNodes[nodeId];
var dist = Math.abs(nearAngle - angle2);
if (dist < min3) {
min3 = dist;
origNode = origNodes[nodeId];
}
}
node = osmNode({ loc: geoVecInterp(origNode.loc, loc, t) });
graph = graph.replace(node);
nodes.splice(endNodeIndex + j2, 0, node);
inBetweenNodes.push(node.id);
}
if (indexRange === 1 && inBetweenNodes.length) {
var startIndex1 = way.nodes.lastIndexOf(startNode.id);
var endIndex1 = way.nodes.lastIndexOf(endNode.id);
var wayDirection1 = endIndex1 - startIndex1;
if (wayDirection1 < -1) {
wayDirection1 = 1;
}
var parentWays = graph.parentWays(keyNodes[i2]);
for (j2 = 0; j2 < parentWays.length; j2++) {
var sharedWay = parentWays[j2];
if (sharedWay === way)
continue;
if (sharedWay.areAdjacent(startNode.id, endNode.id)) {
var startIndex2 = sharedWay.nodes.lastIndexOf(startNode.id);
var endIndex2 = sharedWay.nodes.lastIndexOf(endNode.id);
var wayDirection2 = endIndex2 - startIndex2;
var insertAt = endIndex2;
if (wayDirection2 < -1) {
wayDirection2 = 1;
}
if (wayDirection1 !== wayDirection2) {
inBetweenNodes.reverse();
insertAt = startIndex2;
}
for (k = 0; k < inBetweenNodes.length; k++) {
sharedWay = sharedWay.addNode(inBetweenNodes[k], insertAt + k);
}
graph = graph.replace(sharedWay);
}
}
}
}
ids = nodes.map(function(n2) {
return n2.id;
});
ids.push(ids[0]);
way = way.update({ nodes: ids });
graph = graph.replace(way);
return graph;
};
action.makeConvex = function(graph) {
var way = graph.entity(wayId);
var nodes = utilArrayUniq(graph.childNodes(way));
var points = nodes.map(function(n2) {
return projection2(n2.loc);
});
var sign2 = area_default3(points) > 0 ? 1 : -1;
var hull = hull_default(points);
var i2, j2;
if (sign2 === -1) {
nodes.reverse();
points.reverse();
}
for (i2 = 0; i2 < hull.length - 1; i2++) {
var startIndex = points.indexOf(hull[i2]);
var endIndex = points.indexOf(hull[i2 + 1]);
var indexRange = endIndex - startIndex;
if (indexRange < 0) {
indexRange += nodes.length;
}
for (j2 = 1; j2 < indexRange; j2++) {
var point = geoVecInterp(hull[i2], hull[i2 + 1], j2 / indexRange);
var node = nodes[(j2 + startIndex) % nodes.length].move(projection2.invert(point));
graph = graph.replace(node);
}
}
return graph;
};
action.disabled = function(graph) {
if (!graph.entity(wayId).isClosed()) {
return "not_closed";
}
var way = graph.entity(wayId);
var nodes = utilArrayUniq(graph.childNodes(way));
var points = nodes.map(function(n2) {
return projection2(n2.loc);
});
var hull = hull_default(points);
var epsilonAngle = Math.PI / 180;
if (hull.length !== points.length || hull.length < 3) {
return false;
}
var centroid = centroid_default2(points);
var radius = geoVecLengthSquare(centroid, points[0]);
var i2, actualPoint;
for (i2 = 0; i2 < hull.length; i2++) {
actualPoint = hull[i2];
var actualDist = geoVecLengthSquare(actualPoint, centroid);
var diff = Math.abs(actualDist - radius);
if (diff > 0.05 * radius) {
return false;
}
}
for (i2 = 0; i2 < hull.length; i2++) {
actualPoint = hull[i2];
var nextPoint = hull[(i2 + 1) % hull.length];
var startAngle = Math.atan2(actualPoint[1] - centroid[1], actualPoint[0] - centroid[0]);
var endAngle = Math.atan2(nextPoint[1] - centroid[1], nextPoint[0] - centroid[0]);
var angle2 = endAngle - startAngle;
if (angle2 < 0) {
angle2 = -angle2;
}
if (angle2 > Math.PI) {
angle2 = 2 * Math.PI - angle2;
}
if (angle2 > maxAngle + epsilonAngle) {
return false;
}
}
return "already_circular";
};
action.transitionable = true;
return action;
}
// modules/actions/delete_way.js
function actionDeleteWay(wayID) {
function canDeleteNode(node, graph) {
if (graph.parentWays(node).length || graph.parentRelations(node).length)
return false;
var geometries = osmNodeGeometriesForTags(node.tags);
if (geometries.point)
return false;
if (geometries.vertex)
return true;
return !node.hasInterestingTags();
}
var action = function(graph) {
var way = graph.entity(wayID);
graph.parentRelations(way).forEach(function(parent) {
parent = parent.removeMembersWithID(wayID);
graph = graph.replace(parent);
if (parent.isDegenerate()) {
graph = actionDeleteRelation(parent.id)(graph);
}
});
new Set(way.nodes).forEach(function(nodeID) {
graph = graph.replace(way.removeNode(nodeID));
var node = graph.entity(nodeID);
if (canDeleteNode(node, graph)) {
graph = graph.remove(node);
}
});
return graph.remove(way);
};
return action;
}
// modules/actions/delete_multiple.js
function actionDeleteMultiple(ids) {
var actions = {
way: actionDeleteWay,
node: actionDeleteNode,
relation: actionDeleteRelation
};
var action = function(graph) {
ids.forEach(function(id2) {
if (graph.hasEntity(id2)) {
graph = actions[graph.entity(id2).type](id2)(graph);
}
});
return graph;
};
return action;
}
// modules/actions/delete_relation.js
function actionDeleteRelation(relationID, allowUntaggedMembers) {
function canDeleteEntity(entity, graph) {
return !graph.parentWays(entity).length && !graph.parentRelations(entity).length && (!entity.hasInterestingTags() && !allowUntaggedMembers);
}
var action = function(graph) {
var relation = graph.entity(relationID);
graph.parentRelations(relation).forEach(function(parent) {
parent = parent.removeMembersWithID(relationID);
graph = graph.replace(parent);
if (parent.isDegenerate()) {
graph = actionDeleteRelation(parent.id)(graph);
}
});
var memberIDs = utilArrayUniq(relation.members.map(function(m) {
return m.id;
}));
memberIDs.forEach(function(memberID) {
graph = graph.replace(relation.removeMembersWithID(memberID));
var entity = graph.entity(memberID);
if (canDeleteEntity(entity, graph)) {
graph = actionDeleteMultiple([memberID])(graph);
}
});
return graph.remove(relation);
};
return action;
}
// modules/actions/delete_node.js
function actionDeleteNode(nodeId) {
var action = function(graph) {
var node = graph.entity(nodeId);
graph.parentWays(node).forEach(function(parent) {
parent = parent.removeNode(nodeId);
graph = graph.replace(parent);
if (parent.isDegenerate()) {
graph = actionDeleteWay(parent.id)(graph);
}
});
graph.parentRelations(node).forEach(function(parent) {
parent = parent.removeMembersWithID(nodeId);
graph = graph.replace(parent);
if (parent.isDegenerate()) {
graph = actionDeleteRelation(parent.id)(graph);
}
});
return graph.remove(node);
};
return action;
}
// modules/actions/connect.js
function actionConnect(nodeIDs) {
var action = function(graph) {
var survivor;
var node;
var parents;
var i2, j2;
nodeIDs.reverse();
var interestingIDs = [];
for (i2 = 0; i2 < nodeIDs.length; i2++) {
node = graph.entity(nodeIDs[i2]);
if (node.hasInterestingTags()) {
if (!node.isNew()) {
interestingIDs.push(node.id);
}
}
}
survivor = graph.entity(utilOldestID(interestingIDs.length > 0 ? interestingIDs : nodeIDs));
for (i2 = 0; i2 < nodeIDs.length; i2++) {
node = graph.entity(nodeIDs[i2]);
if (node.id === survivor.id)
continue;
parents = graph.parentWays(node);
for (j2 = 0; j2 < parents.length; j2++) {
graph = graph.replace(parents[j2].replaceNode(node.id, survivor.id));
}
parents = graph.parentRelations(node);
for (j2 = 0; j2 < parents.length; j2++) {
graph = graph.replace(parents[j2].replaceMember(node, survivor));
}
survivor = survivor.mergeTags(node.tags);
graph = actionDeleteNode(node.id)(graph);
}
graph = graph.replace(survivor);
parents = graph.parentWays(survivor);
for (i2 = 0; i2 < parents.length; i2++) {
if (parents[i2].isDegenerate()) {
graph = actionDeleteWay(parents[i2].id)(graph);
}
}
return graph;
};
action.disabled = function(graph) {
var seen = {};
var restrictionIDs = [];
var survivor;
var node, way;
var relations, relation, role;
var i2, j2, k;
survivor = graph.entity(utilOldestID(nodeIDs));
for (i2 = 0; i2 < nodeIDs.length; i2++) {
node = graph.entity(nodeIDs[i2]);
relations = graph.parentRelations(node);
for (j2 = 0; j2 < relations.length; j2++) {
relation = relations[j2];
role = relation.memberById(node.id).role || "";
if (relation.hasFromViaTo()) {
restrictionIDs.push(relation.id);
}
if (seen[relation.id] !== void 0 && seen[relation.id] !== role) {
return "relation";
} else {
seen[relation.id] = role;
}
}
}
for (i2 = 0; i2 < nodeIDs.length; i2++) {
node = graph.entity(nodeIDs[i2]);
var parents = graph.parentWays(node);
for (j2 = 0; j2 < parents.length; j2++) {
var parent = parents[j2];
relations = graph.parentRelations(parent);
for (k = 0; k < relations.length; k++) {
relation = relations[k];
if (relation.hasFromViaTo()) {
restrictionIDs.push(relation.id);
}
}
}
}
restrictionIDs = utilArrayUniq(restrictionIDs);
for (i2 = 0; i2 < restrictionIDs.length; i2++) {
relation = graph.entity(restrictionIDs[i2]);
if (!relation.isComplete(graph))
continue;
var memberWays = relation.members.filter(function(m) {
return m.type === "way";
}).map(function(m) {
return graph.entity(m.id);
});
memberWays = utilArrayUniq(memberWays);
var f2 = relation.memberByRole("from");
var t = relation.memberByRole("to");
var isUturn = f2.id === t.id;
var nodes = { from: [], via: [], to: [], keyfrom: [], keyto: [] };
for (j2 = 0; j2 < relation.members.length; j2++) {
collectNodes(relation.members[j2], nodes);
}
nodes.keyfrom = utilArrayUniq(nodes.keyfrom.filter(hasDuplicates));
nodes.keyto = utilArrayUniq(nodes.keyto.filter(hasDuplicates));
var filter2 = keyNodeFilter(nodes.keyfrom, nodes.keyto);
nodes.from = nodes.from.filter(filter2);
nodes.via = nodes.via.filter(filter2);
nodes.to = nodes.to.filter(filter2);
var connectFrom = false;
var connectVia = false;
var connectTo = false;
var connectKeyFrom = false;
var connectKeyTo = false;
for (j2 = 0; j2 < nodeIDs.length; j2++) {
var n2 = nodeIDs[j2];
if (nodes.from.indexOf(n2) !== -1) {
connectFrom = true;
}
if (nodes.via.indexOf(n2) !== -1) {
connectVia = true;
}
if (nodes.to.indexOf(n2) !== -1) {
connectTo = true;
}
if (nodes.keyfrom.indexOf(n2) !== -1) {
connectKeyFrom = true;
}
if (nodes.keyto.indexOf(n2) !== -1) {
connectKeyTo = true;
}
}
if (connectFrom && connectTo && !isUturn) {
return "restriction";
}
if (connectFrom && connectVia) {
return "restriction";
}
if (connectTo && connectVia) {
return "restriction";
}
if (connectKeyFrom || connectKeyTo) {
if (nodeIDs.length !== 2) {
return "restriction";
}
var n0 = null;
var n1 = null;
for (j2 = 0; j2 < memberWays.length; j2++) {
way = memberWays[j2];
if (way.contains(nodeIDs[0])) {
n0 = nodeIDs[0];
}
if (way.contains(nodeIDs[1])) {
n1 = nodeIDs[1];
}
}
if (n0 && n1) {
var ok = false;
for (j2 = 0; j2 < memberWays.length; j2++) {
way = memberWays[j2];
if (way.areAdjacent(n0, n1)) {
ok = true;
break;
}
}
if (!ok) {
return "restriction";
}
}
}
for (j2 = 0; j2 < memberWays.length; j2++) {
way = memberWays[j2].update({});
for (k = 0; k < nodeIDs.length; k++) {
if (nodeIDs[k] === survivor.id)
continue;
if (way.areAdjacent(nodeIDs[k], survivor.id)) {
way = way.removeNode(nodeIDs[k]);
} else {
way = way.replaceNode(nodeIDs[k], survivor.id);
}
}
if (way.isDegenerate()) {
return "restriction";
}
}
}
return false;
function hasDuplicates(n3, i3, arr) {
return arr.indexOf(n3) !== arr.lastIndexOf(n3);
}
function keyNodeFilter(froms, tos) {
return function(n3) {
return froms.indexOf(n3) === -1 && tos.indexOf(n3) === -1;
};
}
function collectNodes(member, collection) {
var entity = graph.hasEntity(member.id);
if (!entity)
return;
var role2 = member.role || "";
if (!collection[role2]) {
collection[role2] = [];
}
if (member.type === "node") {
collection[role2].push(member.id);
if (role2 === "via") {
collection.keyfrom.push(member.id);
collection.keyto.push(member.id);
}
} else if (member.type === "way") {
collection[role2].push.apply(collection[role2], entity.nodes);
if (role2 === "from" || role2 === "via") {
collection.keyfrom.push(entity.first());
collection.keyfrom.push(entity.last());
}
if (role2 === "to" || role2 === "via") {
collection.keyto.push(entity.first());
collection.keyto.push(entity.last());
}
}
}
};
return action;
}
// modules/actions/copy_entities.js
function actionCopyEntities(ids, fromGraph) {
var _copies = {};
var action = function(graph) {
ids.forEach(function(id3) {
fromGraph.entity(id3).copy(fromGraph, _copies);
});
for (var id2 in _copies) {
graph = graph.replace(_copies[id2]);
}
return graph;
};
action.copies = function() {
return _copies;
};
return action;
}
// modules/actions/delete_member.js
function actionDeleteMember(relationId, memberIndex) {
return function(graph) {
var relation = graph.entity(relationId).removeMember(memberIndex);
graph = graph.replace(relation);
if (relation.isDegenerate()) {
graph = actionDeleteRelation(relation.id)(graph);
}
return graph;
};
}
// modules/actions/discard_tags.js
function actionDiscardTags(difference, discardTags) {
discardTags = discardTags || {};
return (graph) => {
difference.modified().forEach(checkTags);
difference.created().forEach(checkTags);
return graph;
function checkTags(entity) {
const keys = Object.keys(entity.tags);
let didDiscard = false;
let tags = {};
for (let i2 = 0; i2 < keys.length; i2++) {
const k = keys[i2];
if (discardTags[k] || !entity.tags[k]) {
didDiscard = true;
} else {
tags[k] = entity.tags[k];
}
}
if (didDiscard) {
graph = graph.replace(entity.update({ tags }));
}
}
};
}
// modules/actions/disconnect.js
function actionDisconnect(nodeId, newNodeId) {
var wayIds;
var disconnectableRelationTypes = {
"associatedStreet": true,
"enforcement": true,
"site": true
};
var action = function(graph) {
var node = graph.entity(nodeId);
var connections = action.connections(graph);
connections.forEach(function(connection) {
var way = graph.entity(connection.wayID);
var newNode = osmNode({ id: newNodeId, loc: node.loc, tags: node.tags });
graph = graph.replace(newNode);
if (connection.index === 0 && way.isArea()) {
graph = graph.replace(way.replaceNode(way.nodes[0], newNode.id));
} else if (way.isClosed() && connection.index === way.nodes.length - 1) {
graph = graph.replace(way.unclose().addNode(newNode.id));
} else {
graph = graph.replace(way.updateNode(newNode.id, connection.index));
}
});
return graph;
};
action.connections = function(graph) {
var candidates = [];
var keeping = false;
var parentWays = graph.parentWays(graph.entity(nodeId));
var way, waynode;
for (var i2 = 0; i2 < parentWays.length; i2++) {
way = parentWays[i2];
if (wayIds && wayIds.indexOf(way.id) === -1) {
keeping = true;
continue;
}
if (way.isArea() && way.nodes[0] === nodeId) {
candidates.push({ wayID: way.id, index: 0 });
} else {
for (var j2 = 0; j2 < way.nodes.length; j2++) {
waynode = way.nodes[j2];
if (waynode === nodeId) {
if (way.isClosed() && parentWays.length > 1 && wayIds && wayIds.indexOf(way.id) !== -1 && j2 === way.nodes.length - 1) {
continue;
}
candidates.push({ wayID: way.id, index: j2 });
}
}
}
}
return keeping ? candidates : candidates.slice(1);
};
action.disabled = function(graph) {
var connections = action.connections(graph);
if (connections.length === 0)
return "not_connected";
var parentWays = graph.parentWays(graph.entity(nodeId));
var seenRelationIds = {};
var sharedRelation;
parentWays.forEach(function(way) {
var relations = graph.parentRelations(way);
relations.filter((relation) => !disconnectableRelationTypes[relation.tags.type]).forEach(function(relation) {
if (relation.id in seenRelationIds) {
if (wayIds) {
if (wayIds.indexOf(way.id) !== -1 || wayIds.indexOf(seenRelationIds[relation.id]) !== -1) {
sharedRelation = relation;
}
} else {
sharedRelation = relation;
}
} else {
seenRelationIds[relation.id] = way.id;
}
});
});
if (sharedRelation)
return "relation";
};
action.limitWays = function(val) {
if (!arguments.length)
return wayIds;
wayIds = val;
return action;
};
return action;
}
// modules/actions/extract.js
function actionExtract(entityID, projection2) {
var extractedNodeID;
var action = function(graph) {
var entity = graph.entity(entityID);
if (entity.type === "node") {
return extractFromNode(entity, graph);
}
return extractFromWayOrRelation(entity, graph);
};
function extractFromNode(node, graph) {
extractedNodeID = node.id;
var replacement = osmNode({ loc: node.loc });
graph = graph.replace(replacement);
graph = graph.parentWays(node).reduce(function(accGraph, parentWay) {
return accGraph.replace(parentWay.replaceNode(entityID, replacement.id));
}, graph);
return graph.parentRelations(node).reduce(function(accGraph, parentRel) {
return accGraph.replace(parentRel.replaceMember(node, replacement));
}, graph);
}
function extractFromWayOrRelation(entity, graph) {
var fromGeometry = entity.geometry(graph);
var keysToCopyAndRetain = ["source", "wheelchair"];
var keysToRetain = ["area"];
var buildingKeysToRetain = ["architect", "building", "height", "layer"];
var extractedLoc = path_default(projection2).centroid(entity.asGeoJSON(graph));
extractedLoc = extractedLoc && projection2.invert(extractedLoc);
if (!extractedLoc || !isFinite(extractedLoc[0]) || !isFinite(extractedLoc[1])) {
extractedLoc = entity.extent(graph).center();
}
var indoorAreaValues = {
area: true,
corridor: true,
elevator: true,
level: true,
room: true
};
var isBuilding = entity.tags.building && entity.tags.building !== "no" || entity.tags["building:part"] && entity.tags["building:part"] !== "no";
var isIndoorArea = fromGeometry === "area" && entity.tags.indoor && indoorAreaValues[entity.tags.indoor];
var entityTags = Object.assign({}, entity.tags);
var pointTags = {};
for (var key in entityTags) {
if (entity.type === "relation" && key === "type") {
continue;
}
if (keysToRetain.indexOf(key) !== -1) {
continue;
}
if (isBuilding) {
if (buildingKeysToRetain.indexOf(key) !== -1 || key.match(/^building:.{1,}/) || key.match(/^roof:.{1,}/))
continue;
}
if (isIndoorArea && key === "indoor") {
continue;
}
pointTags[key] = entityTags[key];
if (keysToCopyAndRetain.indexOf(key) !== -1 || key.match(/^addr:.{1,}/)) {
continue;
} else if (isIndoorArea && key === "level") {
continue;
}
delete entityTags[key];
}
if (!isBuilding && !isIndoorArea && fromGeometry === "area") {
entityTags.area = "yes";
}
var replacement = osmNode({ loc: extractedLoc, tags: pointTags });
graph = graph.replace(replacement);
extractedNodeID = replacement.id;
return graph.replace(entity.update({ tags: entityTags }));
}
action.getExtractedNodeID = function() {
return extractedNodeID;
};
return action;
}
// modules/actions/join.js
function actionJoin(ids) {
function groupEntitiesByGeometry(graph) {
var entities = ids.map(function(id2) {
return graph.entity(id2);
});
return Object.assign({ line: [] }, utilArrayGroupBy(entities, function(entity) {
return entity.geometry(graph);
}));
}
var action = function(graph) {
var ways = ids.map(graph.entity, graph);
var survivorID = utilOldestID(ways.map((way) => way.id));
ways.sort(function(a, b) {
var aSided = a.isSided();
var bSided = b.isSided();
return aSided && !bSided ? -1 : bSided && !aSided ? 1 : 0;
});
var sequences = osmJoinWays(ways, graph);
var joined = sequences[0];
graph = sequences.actions.reduce(function(g, action2) {
return action2(g);
}, graph);
var survivor = graph.entity(survivorID);
survivor = survivor.update({ nodes: joined.nodes.map(function(n2) {
return n2.id;
}) });
graph = graph.replace(survivor);
joined.forEach(function(way) {
if (way.id === survivorID)
return;
graph.parentRelations(way).forEach(function(parent) {
graph = graph.replace(parent.replaceMember(way, survivor));
});
survivor = survivor.mergeTags(way.tags);
graph = graph.replace(survivor);
graph = actionDeleteWay(way.id)(graph);
});
function checkForSimpleMultipolygon() {
if (!survivor.isClosed())
return;
var multipolygons = graph.parentMultipolygons(survivor).filter(function(multipolygon2) {
return multipolygon2.members.length === 1;
});
if (multipolygons.length !== 1)
return;
var multipolygon = multipolygons[0];
for (var key in survivor.tags) {
if (multipolygon.tags[key] && multipolygon.tags[key] !== survivor.tags[key])
return;
}
survivor = survivor.mergeTags(multipolygon.tags);
graph = graph.replace(survivor);
graph = actionDeleteRelation(multipolygon.id, true)(graph);
var tags = Object.assign({}, survivor.tags);
if (survivor.geometry(graph) !== "area") {
tags.area = "yes";
}
delete tags.type;
survivor = survivor.update({ tags });
graph = graph.replace(survivor);
}
checkForSimpleMultipolygon();
return graph;
};
action.resultingWayNodesLength = function(graph) {
return ids.reduce(function(count, id2) {
return count + graph.entity(id2).nodes.length;
}, 0) - ids.length - 1;
};
action.disabled = function(graph) {
var geometries = groupEntitiesByGeometry(graph);
if (ids.length < 2 || ids.length !== geometries.line.length) {
return "not_eligible";
}
var joined = osmJoinWays(ids.map(graph.entity, graph), graph);
if (joined.length > 1) {
return "not_adjacent";
}
var i2;
var sortedParentRelations = function(id2) {
return graph.parentRelations(graph.entity(id2)).filter((rel) => !rel.isRestriction() && !rel.isConnectivity()).sort((a, b) => a.id - b.id);
};
var relsA = sortedParentRelations(ids[0]);
for (i2 = 1; i2 < ids.length; i2++) {
var relsB = sortedParentRelations(ids[i2]);
if (!utilArrayIdentical(relsA, relsB)) {
return "conflicting_relations";
}
}
for (i2 = 0; i2 < ids.length - 1; i2++) {
for (var j2 = i2 + 1; j2 < ids.length; j2++) {
var path1 = graph.childNodes(graph.entity(ids[i2])).map(function(e) {
return e.loc;
});
var path2 = graph.childNodes(graph.entity(ids[j2])).map(function(e) {
return e.loc;
});
var intersections = geoPathIntersections(path1, path2);
var common = utilArrayIntersection(joined[0].nodes.map(function(n2) {
return n2.loc.toString();
}), intersections.map(function(n2) {
return n2.toString();
}));
if (common.length !== intersections.length) {
return "paths_intersect";
}
}
}
var nodeIds = joined[0].nodes.map(function(n2) {
return n2.id;
}).slice(1, -1);
var relation;
var tags = {};
var conflicting = false;
joined[0].forEach(function(way) {
var parents = graph.parentRelations(way);
parents.forEach(function(parent) {
if ((parent.isRestriction() || parent.isConnectivity()) && parent.members.some(function(m) {
return nodeIds.indexOf(m.id) >= 0;
})) {
relation = parent;
}
});
for (var k in way.tags) {
if (!(k in tags)) {
tags[k] = way.tags[k];
} else if (tags[k] && osmIsInterestingTag(k) && tags[k] !== way.tags[k]) {
conflicting = true;
}
}
});
if (relation) {
return relation.isRestriction() ? "restriction" : "connectivity";
}
if (conflicting) {
return "conflicting_tags";
}
};
return action;
}
// modules/actions/merge.js
function actionMerge(ids) {
function groupEntitiesByGeometry(graph) {
var entities = ids.map(function(id2) {
return graph.entity(id2);
});
return Object.assign({ point: [], area: [], line: [], relation: [] }, utilArrayGroupBy(entities, function(entity) {
return entity.geometry(graph);
}));
}
var action = function(graph) {
var geometries = groupEntitiesByGeometry(graph);
var target = geometries.area[0] || geometries.line[0];
var points = geometries.point;
points.forEach(function(point) {
target = target.mergeTags(point.tags);
graph = graph.replace(target);
graph.parentRelations(point).forEach(function(parent) {
graph = graph.replace(parent.replaceMember(point, target));
});
var nodes = utilArrayUniq(graph.childNodes(target));
var removeNode = point;
if (!point.isNew()) {
var inserted = false;
var canBeReplaced = function(node2) {
return !(graph.parentWays(node2).length > 1 || graph.parentRelations(node2).length);
};
var replaceNode = function(node2) {
graph = graph.replace(point.update({ tags: node2.tags, loc: node2.loc }));
target = target.replaceNode(node2.id, point.id);
graph = graph.replace(target);
removeNode = node2;
inserted = true;
};
var i2;
var node;
for (i2 = 0; i2 < nodes.length; i2++) {
node = nodes[i2];
if (canBeReplaced(node) && node.isNew()) {
replaceNode(node);
break;
}
}
if (!inserted && point.hasInterestingTags()) {
for (i2 = 0; i2 < nodes.length; i2++) {
node = nodes[i2];
if (canBeReplaced(node) && !node.hasInterestingTags()) {
replaceNode(node);
break;
}
}
if (!inserted) {
for (i2 = 0; i2 < nodes.length; i2++) {
node = nodes[i2];
if (canBeReplaced(node) && utilCompareIDs(point.id, node.id) < 0) {
replaceNode(node);
break;
}
}
}
}
}
graph = graph.remove(removeNode);
});
if (target.tags.area === "yes") {
var tags = Object.assign({}, target.tags);
delete tags.area;
if (osmTagSuggestingArea(tags)) {
target = target.update({ tags });
graph = graph.replace(target);
}
}
return graph;
};
action.disabled = function(graph) {
var geometries = groupEntitiesByGeometry(graph);
if (geometries.point.length === 0 || geometries.area.length + geometries.line.length !== 1 || geometries.relation.length !== 0) {
return "not_eligible";
}
};
return action;
}
// modules/actions/merge_nodes.js
function actionMergeNodes(nodeIDs, loc) {
function chooseLoc(graph) {
if (!nodeIDs.length)
return null;
var sum = [0, 0];
var interestingCount = 0;
var interestingLoc;
for (var i2 = 0; i2 < nodeIDs.length; i2++) {
var node = graph.entity(nodeIDs[i2]);
if (node.hasInterestingTags()) {
interestingLoc = ++interestingCount === 1 ? node.loc : null;
}
sum = geoVecAdd(sum, node.loc);
}
return interestingLoc || geoVecScale(sum, 1 / nodeIDs.length);
}
var action = function(graph) {
if (nodeIDs.length < 2)
return graph;
var toLoc = loc;
if (!toLoc) {
toLoc = chooseLoc(graph);
}
for (var i2 = 0; i2 < nodeIDs.length; i2++) {
var node = graph.entity(nodeIDs[i2]);
if (node.loc !== toLoc) {
graph = graph.replace(node.move(toLoc));
}
}
return actionConnect(nodeIDs)(graph);
};
action.disabled = function(graph) {
if (nodeIDs.length < 2)
return "not_eligible";
for (var i2 = 0; i2 < nodeIDs.length; i2++) {
var entity = graph.entity(nodeIDs[i2]);
if (entity.type !== "node")
return "not_eligible";
}
return actionConnect(nodeIDs).disabled(graph);
};
return action;
}
// modules/osm/changeset.js
function osmChangeset() {
if (!(this instanceof osmChangeset)) {
return new osmChangeset().initialize(arguments);
} else if (arguments.length) {
this.initialize(arguments);
}
}
osmEntity.changeset = osmChangeset;
osmChangeset.prototype = Object.create(osmEntity.prototype);
Object.assign(osmChangeset.prototype, {
type: "changeset",
extent: function() {
return new geoExtent();
},
geometry: function() {
return "changeset";
},
asJXON: function() {
return {
osm: {
changeset: {
tag: Object.keys(this.tags).map(function(k) {
return { "@k": k, "@v": this.tags[k] };
}, this),
"@version": 0.6,
"@generator": "iD"
}
}
};
},
osmChangeJXON: function(changes) {
var changeset_id = this.id;
function nest(x, order) {
var groups = {};
for (var i2 = 0; i2 < x.length; i2++) {
var tagName = Object.keys(x[i2])[0];
if (!groups[tagName])
groups[tagName] = [];
groups[tagName].push(x[i2][tagName]);
}
var ordered = {};
order.forEach(function(o) {
if (groups[o])
ordered[o] = groups[o];
});
return ordered;
}
function sort(changes2) {
function resolve(item) {
return relations.find(function(relation2) {
return item.keyAttributes.type === "relation" && item.keyAttributes.ref === relation2["@id"];
});
}
function isNew(item) {
return !sorted[item["@id"]] && !processing.find(function(proc) {
return proc["@id"] === item["@id"];
});
}
var processing = [];
var sorted = {};
var relations = changes2.relation;
if (!relations)
return changes2;
for (var i2 = 0; i2 < relations.length; i2++) {
var relation = relations[i2];
if (!sorted[relation["@id"]]) {
processing.push(relation);
}
while (processing.length > 0) {
var next = processing[0], deps = next.member.map(resolve).filter(Boolean).filter(isNew);
if (deps.length === 0) {
sorted[next["@id"]] = next;
processing.shift();
} else {
processing = deps.concat(processing);
}
}
}
changes2.relation = Object.values(sorted);
return changes2;
}
function rep2(entity) {
return entity.asJXON(changeset_id);
}
return {
osmChange: {
"@version": 0.6,
"@generator": "iD",
"create": sort(nest(changes.created.map(rep2), ["node", "way", "relation"])),
"modify": nest(changes.modified.map(rep2), ["node", "way", "relation"]),
"delete": Object.assign(nest(changes.deleted.map(rep2), ["relation", "way", "node"]), { "@if-unused": true })
}
};
},
asGeoJSON: function() {
return {};
}
});
// modules/osm/note.js
function osmNote() {
if (!(this instanceof osmNote)) {
return new osmNote().initialize(arguments);
} else if (arguments.length) {
this.initialize(arguments);
}
}
osmNote.id = function() {
return osmNote.id.next--;
};
osmNote.id.next = -1;
Object.assign(osmNote.prototype, {
type: "note",
initialize: function(sources) {
for (var i2 = 0; i2 < sources.length; ++i2) {
var source = sources[i2];
for (var prop in source) {
if (Object.prototype.hasOwnProperty.call(source, prop)) {
if (source[prop] === void 0) {
delete this[prop];
} else {
this[prop] = source[prop];
}
}
}
}
if (!this.id) {
this.id = osmNote.id().toString();
}
return this;
},
extent: function() {
return new geoExtent(this.loc);
},
update: function(attrs) {
return osmNote(this, attrs);
},
isNew: function() {
return this.id < 0;
},
move: function(loc) {
return this.update({ loc });
}
});
// modules/osm/relation.js
function osmRelation() {
if (!(this instanceof osmRelation)) {
return new osmRelation().initialize(arguments);
} else if (arguments.length) {
this.initialize(arguments);
}
}
osmEntity.relation = osmRelation;
osmRelation.prototype = Object.create(osmEntity.prototype);
osmRelation.creationOrder = function(a, b) {
var aId = parseInt(osmEntity.id.toOSM(a.id), 10);
var bId = parseInt(osmEntity.id.toOSM(b.id), 10);
if (aId < 0 || bId < 0)
return aId - bId;
return bId - aId;
};
Object.assign(osmRelation.prototype, {
type: "relation",
members: [],
copy: function(resolver, copies) {
if (copies[this.id])
return copies[this.id];
var copy2 = osmEntity.prototype.copy.call(this, resolver, copies);
var members = this.members.map(function(member) {
return Object.assign({}, member, { id: resolver.entity(member.id).copy(resolver, copies).id });
});
copy2 = copy2.update({ members });
copies[this.id] = copy2;
return copy2;
},
extent: function(resolver, memo) {
return resolver.transient(this, "extent", function() {
if (memo && memo[this.id])
return geoExtent();
memo = memo || {};
memo[this.id] = true;
var extent = geoExtent();
for (var i2 = 0; i2 < this.members.length; i2++) {
var member = resolver.hasEntity(this.members[i2].id);
if (member) {
extent._extend(member.extent(resolver, memo));
}
}
return extent;
});
},
geometry: function(graph) {
return graph.transient(this, "geometry", function() {
return this.isMultipolygon() ? "area" : "relation";
});
},
isDegenerate: function() {
return this.members.length === 0;
},
indexedMembers: function() {
var result = new Array(this.members.length);
for (var i2 = 0; i2 < this.members.length; i2++) {
result[i2] = Object.assign({}, this.members[i2], { index: i2 });
}
return result;
},
memberByRole: function(role) {
for (var i2 = 0; i2 < this.members.length; i2++) {
if (this.members[i2].role === role) {
return Object.assign({}, this.members[i2], { index: i2 });
}
}
},
membersByRole: function(role) {
var result = [];
for (var i2 = 0; i2 < this.members.length; i2++) {
if (this.members[i2].role === role) {
result.push(Object.assign({}, this.members[i2], { index: i2 }));
}
}
return result;
},
memberById: function(id2) {
for (var i2 = 0; i2 < this.members.length; i2++) {
if (this.members[i2].id === id2) {
return Object.assign({}, this.members[i2], { index: i2 });
}
}
},
memberByIdAndRole: function(id2, role) {
for (var i2 = 0; i2 < this.members.length; i2++) {
if (this.members[i2].id === id2 && this.members[i2].role === role) {
return Object.assign({}, this.members[i2], { index: i2 });
}
}
},
addMember: function(member, index) {
var members = this.members.slice();
members.splice(index === void 0 ? members.length : index, 0, member);
return this.update({ members });
},
updateMember: function(member, index) {
var members = this.members.slice();
members.splice(index, 1, Object.assign({}, members[index], member));
return this.update({ members });
},
removeMember: function(index) {
var members = this.members.slice();
members.splice(index, 1);
return this.update({ members });
},
removeMembersWithID: function(id2) {
var members = this.members.filter(function(m) {
return m.id !== id2;
});
return this.update({ members });
},
moveMember: function(fromIndex, toIndex) {
var members = this.members.slice();
members.splice(toIndex, 0, members.splice(fromIndex, 1)[0]);
return this.update({ members });
},
replaceMember: function(needle, replacement, keepDuplicates) {
if (!this.memberById(needle.id))
return this;
var members = [];
for (var i2 = 0; i2 < this.members.length; i2++) {
var member = this.members[i2];
if (member.id !== needle.id) {
members.push(member);
} else if (keepDuplicates || !this.memberByIdAndRole(replacement.id, member.role)) {
members.push({ id: replacement.id, type: replacement.type, role: member.role });
}
}
return this.update({ members });
},
asJXON: function(changeset_id) {
var r = {
relation: {
"@id": this.osmId(),
"@version": this.version || 0,
member: this.members.map(function(member) {
return {
keyAttributes: {
type: member.type,
role: member.role,
ref: osmEntity.id.toOSM(member.id)
}
};
}, this),
tag: Object.keys(this.tags).map(function(k) {
return { keyAttributes: { k, v: this.tags[k] } };
}, this)
}
};
if (changeset_id) {
r.relation["@changeset"] = changeset_id;
}
return r;
},
asGeoJSON: function(resolver) {
return resolver.transient(this, "GeoJSON", function() {
if (this.isMultipolygon()) {
return {
type: "MultiPolygon",
coordinates: this.multipolygon(resolver)
};
} else {
return {
type: "FeatureCollection",
properties: this.tags,
features: this.members.map(function(member) {
return Object.assign({ role: member.role }, resolver.entity(member.id).asGeoJSON(resolver));
})
};
}
});
},
area: function(resolver) {
return resolver.transient(this, "area", function() {
return area_default(this.asGeoJSON(resolver));
});
},
isMultipolygon: function() {
return this.tags.type === "multipolygon";
},
isComplete: function(resolver) {
for (var i2 = 0; i2 < this.members.length; i2++) {
if (!resolver.hasEntity(this.members[i2].id)) {
return false;
}
}
return true;
},
hasFromViaTo: function() {
return this.members.some(function(m) {
return m.role === "from";
}) && this.members.some(function(m) {
return m.role === "via";
}) && this.members.some(function(m) {
return m.role === "to";
});
},
isRestriction: function() {
return !!(this.tags.type && this.tags.type.match(/^restriction:?/));
},
isValidRestriction: function() {
if (!this.isRestriction())
return false;
var froms = this.members.filter(function(m) {
return m.role === "from";
});
var vias = this.members.filter(function(m) {
return m.role === "via";
});
var tos = this.members.filter(function(m) {
return m.role === "to";
});
if (froms.length !== 1 && this.tags.restriction !== "no_entry")
return false;
if (froms.some(function(m) {
return m.type !== "way";
}))
return false;
if (tos.length !== 1 && this.tags.restriction !== "no_exit")
return false;
if (tos.some(function(m) {
return m.type !== "way";
}))
return false;
if (vias.length === 0)
return false;
if (vias.length > 1 && vias.some(function(m) {
return m.type !== "way";
}))
return false;
return true;
},
isConnectivity: function() {
return !!(this.tags.type && this.tags.type.match(/^connectivity:?/));
},
multipolygon: function(resolver) {
var outers = this.members.filter(function(m) {
return (m.role || "outer") === "outer";
});
var inners = this.members.filter(function(m) {
return m.role === "inner";
});
outers = osmJoinWays(outers, resolver);
inners = osmJoinWays(inners, resolver);
var sequenceToLineString = function(sequence) {
if (sequence.nodes.length > 2 && sequence.nodes[0] !== sequence.nodes[sequence.nodes.length - 1]) {
sequence.nodes.push(sequence.nodes[0]);
}
return sequence.nodes.map(function(node) {
return node.loc;
});
};
outers = outers.map(sequenceToLineString);
inners = inners.map(sequenceToLineString);
var result = outers.map(function(o2) {
return [area_default({ type: "Polygon", coordinates: [o2] }) > 2 * Math.PI ? o2.reverse() : o2];
});
function findOuter(inner2) {
var o2, outer;
for (o2 = 0; o2 < outers.length; o2++) {
outer = outers[o2];
if (geoPolygonContainsPolygon(outer, inner2)) {
return o2;
}
}
for (o2 = 0; o2 < outers.length; o2++) {
outer = outers[o2];
if (geoPolygonIntersectsPolygon(outer, inner2, false)) {
return o2;
}
}
}
for (var i2 = 0; i2 < inners.length; i2++) {
var inner = inners[i2];
if (area_default({ type: "Polygon", coordinates: [inner] }) < 2 * Math.PI) {
inner = inner.reverse();
}
var o = findOuter(inners[i2]);
if (o !== void 0) {
result[o].push(inners[i2]);
} else {
result.push([inners[i2]]);
}
}
return result;
}
});
// modules/osm/qa_item.js
var QAItem = class {
constructor(loc, service, itemType, id2, props) {
this.loc = loc;
this.service = service.title;
this.itemType = itemType;
this.id = id2 ? id2 : `${QAItem.id()}`;
this.update(props);
if (service && typeof service.getIcon === "function") {
this.icon = service.getIcon(itemType);
}
}
update(props) {
const { loc, service, itemType, id: id2 } = this;
Object.keys(props).forEach((prop) => this[prop] = props[prop]);
this.loc = loc;
this.service = service;
this.itemType = itemType;
this.id = id2;
return this;
}
static id() {
return this.nextId--;
}
};
QAItem.nextId = -1;
// modules/actions/split.js
function actionSplit(nodeIds, newWayIds) {
if (typeof nodeIds === "string")
nodeIds = [nodeIds];
var _wayIDs;
var _keepHistoryOn = "longest";
var _createdWayIDs = [];
function dist(graph, nA, nB) {
var locA = graph.entity(nA).loc;
var locB = graph.entity(nB).loc;
var epsilon3 = 1e-6;
return locA && locB ? geoSphericalDistance(locA, locB) : epsilon3;
}
function splitArea(nodes, idxA, graph) {
var lengths = new Array(nodes.length);
var length;
var i2;
var best = 0;
var idxB;
function wrap2(index) {
return utilWrap(index, nodes.length);
}
length = 0;
for (i2 = wrap2(idxA + 1); i2 !== idxA; i2 = wrap2(i2 + 1)) {
length += dist(graph, nodes[i2], nodes[wrap2(i2 - 1)]);
lengths[i2] = length;
}
length = 0;
for (i2 = wrap2(idxA - 1); i2 !== idxA; i2 = wrap2(i2 - 1)) {
length += dist(graph, nodes[i2], nodes[wrap2(i2 + 1)]);
if (length < lengths[i2]) {
lengths[i2] = length;
}
}
for (i2 = 0; i2 < nodes.length; i2++) {
var cost = lengths[i2] / dist(graph, nodes[idxA], nodes[i2]);
if (cost > best) {
idxB = i2;
best = cost;
}
}
return idxB;
}
function totalLengthBetweenNodes(graph, nodes) {
var totalLength = 0;
for (var i2 = 0; i2 < nodes.length - 1; i2++) {
totalLength += dist(graph, nodes[i2], nodes[i2 + 1]);
}
return totalLength;
}
function split(graph, nodeId, wayA, newWayId) {
var wayB = osmWay({ id: newWayId, tags: wayA.tags });
var origNodes = wayA.nodes.slice();
var nodesA;
var nodesB;
var isArea = wayA.isArea();
var isOuter = osmIsOldMultipolygonOuterMember(wayA, graph);
if (wayA.isClosed()) {
var nodes = wayA.nodes.slice(0, -1);
var idxA = nodes.indexOf(nodeId);
var idxB = splitArea(nodes, idxA, graph);
if (idxB < idxA) {
nodesA = nodes.slice(idxA).concat(nodes.slice(0, idxB + 1));
nodesB = nodes.slice(idxB, idxA + 1);
} else {
nodesA = nodes.slice(idxA, idxB + 1);
nodesB = nodes.slice(idxB).concat(nodes.slice(0, idxA + 1));
}
} else {
var idx = wayA.nodes.indexOf(nodeId, 1);
nodesA = wayA.nodes.slice(0, idx + 1);
nodesB = wayA.nodes.slice(idx);
}
var lengthA = totalLengthBetweenNodes(graph, nodesA);
var lengthB = totalLengthBetweenNodes(graph, nodesB);
if (_keepHistoryOn === "longest" && lengthB > lengthA) {
wayA = wayA.update({ nodes: nodesB });
wayB = wayB.update({ nodes: nodesA });
var temp = lengthA;
lengthA = lengthB;
lengthB = temp;
} else {
wayA = wayA.update({ nodes: nodesA });
wayB = wayB.update({ nodes: nodesB });
}
if (wayA.tags.step_count) {
var stepCount = parseFloat(wayA.tags.step_count);
if (stepCount && isFinite(stepCount) && stepCount > 0 && Math.round(stepCount) === stepCount) {
var tagsA = Object.assign({}, wayA.tags);
var tagsB = Object.assign({}, wayB.tags);
var ratioA = lengthA / (lengthA + lengthB);
var countA = Math.round(stepCount * ratioA);
tagsA.step_count = countA.toString();
tagsB.step_count = (stepCount - countA).toString();
wayA = wayA.update({ tags: tagsA });
wayB = wayB.update({ tags: tagsB });
}
}
graph = graph.replace(wayA);
graph = graph.replace(wayB);
graph.parentRelations(wayA).forEach(function(relation) {
var member;
if (relation.hasFromViaTo()) {
var f2 = relation.memberByRole("from");
var v = relation.membersByRole("via");
var t = relation.memberByRole("to");
var i2;
if (f2.id === wayA.id || t.id === wayA.id) {
var keepB = false;
if (v.length === 1 && v[0].type === "node") {
keepB = wayB.contains(v[0].id);
} else {
for (i2 = 0; i2 < v.length; i2++) {
if (v[i2].type === "way") {
var wayVia = graph.hasEntity(v[i2].id);
if (wayVia && utilArrayIntersection(wayB.nodes, wayVia.nodes).length) {
keepB = true;
break;
}
}
}
}
if (keepB) {
relation = relation.replaceMember(wayA, wayB);
graph = graph.replace(relation);
}
} else {
for (i2 = 0; i2 < v.length; i2++) {
if (v[i2].type === "way" && v[i2].id === wayA.id) {
member = {
id: wayB.id,
type: "way",
role: "via"
};
graph = actionAddMember(relation.id, member, v[i2].index + 1)(graph);
break;
}
}
}
} else {
if (relation === isOuter) {
graph = graph.replace(relation.mergeTags(wayA.tags));
graph = graph.replace(wayA.update({ tags: {} }));
graph = graph.replace(wayB.update({ tags: {} }));
}
member = {
id: wayB.id,
type: "way",
role: relation.memberById(wayA.id).role
};
var insertPair = {
originalID: wayA.id,
insertedID: wayB.id,
nodes: origNodes
};
graph = actionAddMember(relation.id, member, void 0, insertPair)(graph);
}
});
if (!isOuter && isArea) {
var multipolygon = osmRelation({
tags: Object.assign({}, wayA.tags, { type: "multipolygon" }),
members: [
{ id: wayA.id, role: "outer", type: "way" },
{ id: wayB.id, role: "outer", type: "way" }
]
});
graph = graph.replace(multipolygon);
graph = graph.replace(wayA.update({ tags: {} }));
graph = graph.replace(wayB.update({ tags: {} }));
}
_createdWayIDs.push(wayB.id);
return graph;
}
var action = function(graph) {
_createdWayIDs = [];
var newWayIndex = 0;
for (var i2 = 0; i2 < nodeIds.length; i2++) {
var nodeId = nodeIds[i2];
var candidates = action.waysForNode(nodeId, graph);
for (var j2 = 0; j2 < candidates.length; j2++) {
graph = split(graph, nodeId, candidates[j2], newWayIds && newWayIds[newWayIndex]);
newWayIndex += 1;
}
}
return graph;
};
action.getCreatedWayIDs = function() {
return _createdWayIDs;
};
action.waysForNode = function(nodeId, graph) {
var node = graph.entity(nodeId);
var splittableParents = graph.parentWays(node).filter(isSplittable);
if (!_wayIDs) {
var hasLine = splittableParents.some(function(parent) {
return parent.geometry(graph) === "line";
});
if (hasLine) {
return splittableParents.filter(function(parent) {
return parent.geometry(graph) === "line";
});
}
}
return splittableParents;
function isSplittable(parent) {
if (_wayIDs && _wayIDs.indexOf(parent.id) === -1)
return false;
if (parent.isClosed())
return true;
for (var i2 = 1; i2 < parent.nodes.length - 1; i2++) {
if (parent.nodes[i2] === nodeId)
return true;
}
return false;
}
};
action.ways = function(graph) {
return utilArrayUniq([].concat.apply([], nodeIds.map(function(nodeId) {
return action.waysForNode(nodeId, graph);
})));
};
action.disabled = function(graph) {
for (var i2 = 0; i2 < nodeIds.length; i2++) {
var nodeId = nodeIds[i2];
var candidates = action.waysForNode(nodeId, graph);
if (candidates.length === 0 || _wayIDs && _wayIDs.length !== candidates.length) {
return "not_eligible";
}
}
};
action.limitWays = function(val) {
if (!arguments.length)
return _wayIDs;
_wayIDs = val;
return action;
};
action.keepHistoryOn = function(val) {
if (!arguments.length)
return _keepHistoryOn;
_keepHistoryOn = val;
return action;
};
return action;
}
// modules/core/graph.js
function coreGraph(other, mutable) {
if (!(this instanceof coreGraph))
return new coreGraph(other, mutable);
if (other instanceof coreGraph) {
var base = other.base();
this.entities = Object.assign(Object.create(base.entities), other.entities);
this._parentWays = Object.assign(Object.create(base.parentWays), other._parentWays);
this._parentRels = Object.assign(Object.create(base.parentRels), other._parentRels);
} else {
this.entities = /* @__PURE__ */ Object.create({});
this._parentWays = /* @__PURE__ */ Object.create({});
this._parentRels = /* @__PURE__ */ Object.create({});
this.rebase(other || [], [this]);
}
this.transients = {};
this._childNodes = {};
this.frozen = !mutable;
}
coreGraph.prototype = {
hasEntity: function(id2) {
return this.entities[id2];
},
entity: function(id2) {
var entity = this.entities[id2];
if (!entity) {
entity = this.entities.__proto__[id2];
}
if (!entity) {
throw new Error("entity " + id2 + " not found");
}
return entity;
},
geometry: function(id2) {
return this.entity(id2).geometry(this);
},
transient: function(entity, key, fn) {
var id2 = entity.id;
var transients = this.transients[id2] || (this.transients[id2] = {});
if (transients[key] !== void 0) {
return transients[key];
}
transients[key] = fn.call(entity);
return transients[key];
},
parentWays: function(entity) {
var parents = this._parentWays[entity.id];
var result = [];
if (parents) {
parents.forEach(function(id2) {
result.push(this.entity(id2));
}, this);
}
return result;
},
isPoi: function(entity) {
var parents = this._parentWays[entity.id];
return !parents || parents.size === 0;
},
isShared: function(entity) {
var parents = this._parentWays[entity.id];
return parents && parents.size > 1;
},
parentRelations: function(entity) {
var parents = this._parentRels[entity.id];
var result = [];
if (parents) {
parents.forEach(function(id2) {
result.push(this.entity(id2));
}, this);
}
return result;
},
parentMultipolygons: function(entity) {
return this.parentRelations(entity).filter(function(relation) {
return relation.isMultipolygon();
});
},
childNodes: function(entity) {
if (this._childNodes[entity.id])
return this._childNodes[entity.id];
if (!entity.nodes)
return [];
var nodes = [];
for (var i2 = 0; i2 < entity.nodes.length; i2++) {
nodes[i2] = this.entity(entity.nodes[i2]);
}
if (debug)
Object.freeze(nodes);
this._childNodes[entity.id] = nodes;
return this._childNodes[entity.id];
},
base: function() {
return {
"entities": Object.getPrototypeOf(this.entities),
"parentWays": Object.getPrototypeOf(this._parentWays),
"parentRels": Object.getPrototypeOf(this._parentRels)
};
},
rebase: function(entities, stack, force) {
var base = this.base();
var i2, j2, k, id2;
for (i2 = 0; i2 < entities.length; i2++) {
var entity = entities[i2];
if (!entity.visible || !force && base.entities[entity.id])
continue;
base.entities[entity.id] = entity;
this._updateCalculated(void 0, entity, base.parentWays, base.parentRels);
if (entity.type === "way") {
for (j2 = 0; j2 < entity.nodes.length; j2++) {
id2 = entity.nodes[j2];
for (k = 1; k < stack.length; k++) {
var ents = stack[k].entities;
if (ents.hasOwnProperty(id2) && ents[id2] === void 0) {
delete ents[id2];
}
}
}
}
}
for (i2 = 0; i2 < stack.length; i2++) {
stack[i2]._updateRebased();
}
},
_updateRebased: function() {
var base = this.base();
Object.keys(this._parentWays).forEach(function(child) {
if (base.parentWays[child]) {
base.parentWays[child].forEach(function(id2) {
if (!this.entities.hasOwnProperty(id2)) {
this._parentWays[child].add(id2);
}
}, this);
}
}, this);
Object.keys(this._parentRels).forEach(function(child) {
if (base.parentRels[child]) {
base.parentRels[child].forEach(function(id2) {
if (!this.entities.hasOwnProperty(id2)) {
this._parentRels[child].add(id2);
}
}, this);
}
}, this);
this.transients = {};
},
_updateCalculated: function(oldentity, entity, parentWays, parentRels) {
parentWays = parentWays || this._parentWays;
parentRels = parentRels || this._parentRels;
var type3 = entity && entity.type || oldentity && oldentity.type;
var removed, added, i2;
if (type3 === "way") {
if (oldentity && entity) {
removed = utilArrayDifference(oldentity.nodes, entity.nodes);
added = utilArrayDifference(entity.nodes, oldentity.nodes);
} else if (oldentity) {
removed = oldentity.nodes;
added = [];
} else if (entity) {
removed = [];
added = entity.nodes;
}
for (i2 = 0; i2 < removed.length; i2++) {
parentWays[removed[i2]] = new Set(parentWays[removed[i2]]);
parentWays[removed[i2]].delete(oldentity.id);
}
for (i2 = 0; i2 < added.length; i2++) {
parentWays[added[i2]] = new Set(parentWays[added[i2]]);
parentWays[added[i2]].add(entity.id);
}
} else if (type3 === "relation") {
var oldentityMemberIDs = oldentity ? oldentity.members.map(function(m) {
return m.id;
}) : [];
var entityMemberIDs = entity ? entity.members.map(function(m) {
return m.id;
}) : [];
if (oldentity && entity) {
removed = utilArrayDifference(oldentityMemberIDs, entityMemberIDs);
added = utilArrayDifference(entityMemberIDs, oldentityMemberIDs);
} else if (oldentity) {
removed = oldentityMemberIDs;
added = [];
} else if (entity) {
removed = [];
added = entityMemberIDs;
}
for (i2 = 0; i2 < removed.length; i2++) {
parentRels[removed[i2]] = new Set(parentRels[removed[i2]]);
parentRels[removed[i2]].delete(oldentity.id);
}
for (i2 = 0; i2 < added.length; i2++) {
parentRels[added[i2]] = new Set(parentRels[added[i2]]);
parentRels[added[i2]].add(entity.id);
}
}
},
replace: function(entity) {
if (this.entities[entity.id] === entity)
return this;
return this.update(function() {
this._updateCalculated(this.entities[entity.id], entity);
this.entities[entity.id] = entity;
});
},
remove: function(entity) {
return this.update(function() {
this._updateCalculated(entity, void 0);
this.entities[entity.id] = void 0;
});
},
revert: function(id2) {
var baseEntity = this.base().entities[id2];
var headEntity = this.entities[id2];
if (headEntity === baseEntity)
return this;
return this.update(function() {
this._updateCalculated(headEntity, baseEntity);
delete this.entities[id2];
});
},
update: function() {
var graph = this.frozen ? coreGraph(this, true) : this;
for (var i2 = 0; i2 < arguments.length; i2++) {
arguments[i2].call(graph, graph);
}
if (this.frozen)
graph.frozen = true;
return graph;
},
load: function(entities) {
var base = this.base();
this.entities = Object.create(base.entities);
for (var i2 in entities) {
this.entities[i2] = entities[i2];
this._updateCalculated(base.entities[i2], this.entities[i2]);
}
return this;
}
};
// modules/osm/intersection.js
function osmTurn(turn) {
if (!(this instanceof osmTurn)) {
return new osmTurn(turn);
}
Object.assign(this, turn);
}
function osmIntersection(graph, startVertexId, maxDistance) {
maxDistance = maxDistance || 30;
var vgraph = coreGraph();
var i2, j2, k;
function memberOfRestriction(entity) {
return graph.parentRelations(entity).some(function(r) {
return r.isRestriction();
});
}
function isRoad(way2) {
if (way2.isArea() || way2.isDegenerate())
return false;
var roads = {
"motorway": true,
"motorway_link": true,
"trunk": true,
"trunk_link": true,
"primary": true,
"primary_link": true,
"secondary": true,
"secondary_link": true,
"tertiary": true,
"tertiary_link": true,
"residential": true,
"unclassified": true,
"living_street": true,
"service": true,
"road": true,
"track": true
};
return roads[way2.tags.highway];
}
var startNode = graph.entity(startVertexId);
var checkVertices = [startNode];
var checkWays;
var vertices = [];
var vertexIds = [];
var vertex;
var ways = [];
var wayIds = [];
var way;
var nodes = [];
var node;
var parents = [];
var parent;
var actions = [];
while (checkVertices.length) {
vertex = checkVertices.pop();
checkWays = graph.parentWays(vertex);
var hasWays = false;
for (i2 = 0; i2 < checkWays.length; i2++) {
way = checkWays[i2];
if (!isRoad(way) && !memberOfRestriction(way))
continue;
ways.push(way);
hasWays = true;
nodes = utilArrayUniq(graph.childNodes(way));
for (j2 = 0; j2 < nodes.length; j2++) {
node = nodes[j2];
if (node === vertex)
continue;
if (vertices.indexOf(node) !== -1)
continue;
if (geoSphericalDistance(node.loc, startNode.loc) > maxDistance)
continue;
var hasParents = false;
parents = graph.parentWays(node);
for (k = 0; k < parents.length; k++) {
parent = parents[k];
if (parent === way)
continue;
if (ways.indexOf(parent) !== -1)
continue;
if (!isRoad(parent))
continue;
hasParents = true;
break;
}
if (hasParents) {
checkVertices.push(node);
}
}
}
if (hasWays) {
vertices.push(vertex);
}
}
vertices = utilArrayUniq(vertices);
ways = utilArrayUniq(ways);
ways.forEach(function(way2) {
graph.childNodes(way2).forEach(function(node2) {
vgraph = vgraph.replace(node2);
});
vgraph = vgraph.replace(way2);
graph.parentRelations(way2).forEach(function(relation) {
if (relation.isRestriction()) {
if (relation.isValidRestriction(graph)) {
vgraph = vgraph.replace(relation);
} else if (relation.isComplete(graph)) {
actions.push(actionDeleteRelation(relation.id));
}
}
});
});
ways.forEach(function(w) {
var way2 = vgraph.entity(w.id);
if (way2.tags.oneway === "-1") {
var action = actionReverse(way2.id, { reverseOneway: true });
actions.push(action);
vgraph = action(vgraph);
}
});
var origCount = osmEntity.id.next.way;
vertices.forEach(function(v) {
var splitAll = actionSplit([v.id]).keepHistoryOn("first");
if (!splitAll.disabled(vgraph)) {
splitAll.ways(vgraph).forEach(function(way2) {
var splitOne = actionSplit([v.id]).limitWays([way2.id]).keepHistoryOn("first");
actions.push(splitOne);
vgraph = splitOne(vgraph);
});
}
});
osmEntity.id.next.way = origCount;
vertexIds = vertices.map(function(v) {
return v.id;
});
vertices = [];
ways = [];
vertexIds.forEach(function(id2) {
var vertex2 = vgraph.entity(id2);
var parents2 = vgraph.parentWays(vertex2);
vertices.push(vertex2);
ways = ways.concat(parents2);
});
vertices = utilArrayUniq(vertices);
ways = utilArrayUniq(ways);
vertexIds = vertices.map(function(v) {
return v.id;
});
wayIds = ways.map(function(w) {
return w.id;
});
function withMetadata(way2, vertexIds2) {
var __oneWay = way2.isOneWay();
var __first = vertexIds2.indexOf(way2.first()) !== -1;
var __last = vertexIds2.indexOf(way2.last()) !== -1;
var __via = __first && __last;
var __from = __first && !__oneWay || __last;
var __to = __first || __last && !__oneWay;
return way2.update({
__first,
__last,
__from,
__via,
__to,
__oneWay
});
}
ways = [];
wayIds.forEach(function(id2) {
var way2 = withMetadata(vgraph.entity(id2), vertexIds);
vgraph = vgraph.replace(way2);
ways.push(way2);
});
var keepGoing;
var removeWayIds = [];
var removeVertexIds = [];
do {
keepGoing = false;
checkVertices = vertexIds.slice();
for (i2 = 0; i2 < checkVertices.length; i2++) {
var vertexId = checkVertices[i2];
vertex = vgraph.hasEntity(vertexId);
if (!vertex) {
if (vertexIds.indexOf(vertexId) !== -1) {
vertexIds.splice(vertexIds.indexOf(vertexId), 1);
}
removeVertexIds.push(vertexId);
continue;
}
parents = vgraph.parentWays(vertex);
if (parents.length < 3) {
if (vertexIds.indexOf(vertexId) !== -1) {
vertexIds.splice(vertexIds.indexOf(vertexId), 1);
}
}
if (parents.length === 2) {
var a = parents[0];
var b = parents[1];
var aIsLeaf = a && !a.__via;
var bIsLeaf = b && !b.__via;
var leaf, survivor;
if (aIsLeaf && !bIsLeaf) {
leaf = a;
survivor = b;
} else if (!aIsLeaf && bIsLeaf) {
leaf = b;
survivor = a;
}
if (leaf && survivor) {
survivor = withMetadata(survivor, vertexIds);
vgraph = vgraph.replace(survivor).remove(leaf);
removeWayIds.push(leaf.id);
keepGoing = true;
}
}
parents = vgraph.parentWays(vertex);
if (parents.length < 2) {
if (vertexIds.indexOf(vertexId) !== -1) {
vertexIds.splice(vertexIds.indexOf(vertexId), 1);
}
removeVertexIds.push(vertexId);
keepGoing = true;
}
if (parents.length < 1) {
vgraph = vgraph.remove(vertex);
}
}
} while (keepGoing);
vertices = vertices.filter(function(vertex2) {
return removeVertexIds.indexOf(vertex2.id) === -1;
}).map(function(vertex2) {
return vgraph.entity(vertex2.id);
});
ways = ways.filter(function(way2) {
return removeWayIds.indexOf(way2.id) === -1;
}).map(function(way2) {
return vgraph.entity(way2.id);
});
var intersection = {
graph: vgraph,
actions,
vertices,
ways
};
intersection.turns = function(fromWayId, maxViaWay) {
if (!fromWayId)
return [];
if (!maxViaWay)
maxViaWay = 0;
var vgraph2 = intersection.graph;
var keyVertexIds = intersection.vertices.map(function(v) {
return v.id;
});
var start2 = vgraph2.entity(fromWayId);
if (!start2 || !(start2.__from || start2.__via))
return [];
var maxPathLength = maxViaWay * 2 + 3;
var turns = [];
step(start2);
return turns;
function step(entity, currPath, currRestrictions, matchedRestriction) {
currPath = (currPath || []).slice();
if (currPath.length >= maxPathLength)
return;
currPath.push(entity.id);
currRestrictions = (currRestrictions || []).slice();
var i3, j3;
if (entity.type === "node") {
var parents2 = vgraph2.parentWays(entity);
var nextWays = [];
for (i3 = 0; i3 < parents2.length; i3++) {
var way2 = parents2[i3];
if (way2.__oneWay && way2.nodes[0] !== entity.id)
continue;
if (currPath.indexOf(way2.id) !== -1 && currPath.length >= 3)
continue;
var restrict = null;
for (j3 = 0; j3 < currRestrictions.length; j3++) {
var restriction = currRestrictions[j3];
var f2 = restriction.memberByRole("from");
var v = restriction.membersByRole("via");
var t = restriction.memberByRole("to");
var isOnly = /^only_/.test(restriction.tags.restriction);
var matchesFrom = f2.id === fromWayId;
var matchesViaTo = false;
var isAlongOnlyPath = false;
if (t.id === way2.id) {
if (v.length === 1 && v[0].type === "node") {
matchesViaTo = v[0].id === entity.id && (matchesFrom && currPath.length === 2 || !matchesFrom && currPath.length > 2);
} else {
var pathVias = [];
for (k = 2; k < currPath.length; k += 2) {
pathVias.push(currPath[k]);
}
var restrictionVias = [];
for (k = 0; k < v.length; k++) {
if (v[k].type === "way") {
restrictionVias.push(v[k].id);
}
}
var diff = utilArrayDifference(pathVias, restrictionVias);
matchesViaTo = !diff.length;
}
} else if (isOnly) {
for (k = 0; k < v.length; k++) {
if (v[k].type === "way" && v[k].id === way2.id) {
isAlongOnlyPath = true;
break;
}
}
}
if (matchesViaTo) {
if (isOnly) {
restrict = { id: restriction.id, direct: matchesFrom, from: f2.id, only: true, end: true };
} else {
restrict = { id: restriction.id, direct: matchesFrom, from: f2.id, no: true, end: true };
}
} else {
if (isAlongOnlyPath) {
restrict = { id: restriction.id, direct: false, from: f2.id, only: true, end: false };
} else if (isOnly) {
restrict = { id: restriction.id, direct: false, from: f2.id, no: true, end: true };
}
}
if (restrict && restrict.direct)
break;
}
nextWays.push({ way: way2, restrict });
}
nextWays.forEach(function(nextWay) {
step(nextWay.way, currPath, currRestrictions, nextWay.restrict);
});
} else {
if (currPath.length >= 3) {
var turnPath = currPath.slice();
if (matchedRestriction && matchedRestriction.direct === false) {
for (i3 = 0; i3 < turnPath.length; i3++) {
if (turnPath[i3] === matchedRestriction.from) {
turnPath = turnPath.slice(i3);
break;
}
}
}
var turn = pathToTurn(turnPath);
if (turn) {
if (matchedRestriction) {
turn.restrictionID = matchedRestriction.id;
turn.no = matchedRestriction.no;
turn.only = matchedRestriction.only;
turn.direct = matchedRestriction.direct;
}
turns.push(osmTurn(turn));
}
if (currPath[0] === currPath[2])
return;
}
if (matchedRestriction && matchedRestriction.end)
return;
var n1 = vgraph2.entity(entity.first());
var n2 = vgraph2.entity(entity.last());
var dist = geoSphericalDistance(n1.loc, n2.loc);
var nextNodes = [];
if (currPath.length > 1) {
if (dist > maxDistance)
return;
if (!entity.__via)
return;
}
if (!entity.__oneWay && keyVertexIds.indexOf(n1.id) !== -1 && currPath.indexOf(n1.id) === -1) {
nextNodes.push(n1);
}
if (keyVertexIds.indexOf(n2.id) !== -1 && currPath.indexOf(n2.id) === -1) {
nextNodes.push(n2);
}
nextNodes.forEach(function(nextNode) {
var fromRestrictions = vgraph2.parentRelations(entity).filter(function(r) {
if (!r.isRestriction())
return false;
var f3 = r.memberByRole("from");
if (!f3 || f3.id !== entity.id)
return false;
var isOnly2 = /^only_/.test(r.tags.restriction);
if (!isOnly2)
return true;
var isOnlyVia = false;
var v2 = r.membersByRole("via");
if (v2.length === 1 && v2[0].type === "node") {
isOnlyVia = v2[0].id === nextNode.id;
} else {
for (var i4 = 0; i4 < v2.length; i4++) {
if (v2[i4].type !== "way")
continue;
var viaWay = vgraph2.entity(v2[i4].id);
if (viaWay.first() === nextNode.id || viaWay.last() === nextNode.id) {
isOnlyVia = true;
break;
}
}
}
return isOnlyVia;
});
step(nextNode, currPath, currRestrictions.concat(fromRestrictions), false);
});
}
}
function pathToTurn(path) {
if (path.length < 3)
return;
var fromWayId2, fromNodeId, fromVertexId;
var toWayId, toNodeId, toVertexId;
var viaWayIds, viaNodeId, isUturn;
fromWayId2 = path[0];
toWayId = path[path.length - 1];
if (path.length === 3 && fromWayId2 === toWayId) {
var way2 = vgraph2.entity(fromWayId2);
if (way2.__oneWay)
return null;
isUturn = true;
viaNodeId = fromVertexId = toVertexId = path[1];
fromNodeId = toNodeId = adjacentNode(fromWayId2, viaNodeId);
} else {
isUturn = false;
fromVertexId = path[1];
fromNodeId = adjacentNode(fromWayId2, fromVertexId);
toVertexId = path[path.length - 2];
toNodeId = adjacentNode(toWayId, toVertexId);
if (path.length === 3) {
viaNodeId = path[1];
} else {
viaWayIds = path.filter(function(entityId) {
return entityId[0] === "w";
});
viaWayIds = viaWayIds.slice(1, viaWayIds.length - 1);
}
}
return {
key: path.join("_"),
path,
from: { node: fromNodeId, way: fromWayId2, vertex: fromVertexId },
via: { node: viaNodeId, ways: viaWayIds },
to: { node: toNodeId, way: toWayId, vertex: toVertexId },
u: isUturn
};
function adjacentNode(wayId, affixId) {
var nodes2 = vgraph2.entity(wayId).nodes;
return affixId === nodes2[0] ? nodes2[1] : nodes2[nodes2.length - 2];
}
}
};
return intersection;
}
function osmInferRestriction(graph, turn, projection2) {
var fromWay = graph.entity(turn.from.way);
var fromNode = graph.entity(turn.from.node);
var fromVertex = graph.entity(turn.from.vertex);
var toWay = graph.entity(turn.to.way);
var toNode = graph.entity(turn.to.node);
var toVertex = graph.entity(turn.to.vertex);
var fromOneWay = fromWay.tags.oneway === "yes";
var toOneWay = toWay.tags.oneway === "yes";
var angle2 = (geoAngle(fromVertex, fromNode, projection2) - geoAngle(toVertex, toNode, projection2)) * 180 / Math.PI;
while (angle2 < 0) {
angle2 += 360;
}
if (fromNode === toNode) {
return "no_u_turn";
}
if ((angle2 < 23 || angle2 > 336) && fromOneWay && toOneWay) {
return "no_u_turn";
}
if ((angle2 < 40 || angle2 > 319) && fromOneWay && toOneWay && turn.from.vertex !== turn.to.vertex) {
return "no_u_turn";
}
if (angle2 < 158) {
return "no_right_turn";
}
if (angle2 > 202) {
return "no_left_turn";
}
return "no_straight_on";
}
// modules/actions/merge_polygon.js
function actionMergePolygon(ids, newRelationId) {
function groupEntities(graph) {
var entities = ids.map(function(id2) {
return graph.entity(id2);
});
var geometryGroups = utilArrayGroupBy(entities, function(entity) {
if (entity.type === "way" && entity.isClosed()) {
return "closedWay";
} else if (entity.type === "relation" && entity.isMultipolygon()) {
return "multipolygon";
} else {
return "other";
}
});
return Object.assign({ closedWay: [], multipolygon: [], other: [] }, geometryGroups);
}
var action = function(graph) {
var entities = groupEntities(graph);
var polygons = entities.multipolygon.reduce(function(polygons2, m) {
return polygons2.concat(osmJoinWays(m.members, graph));
}, []).concat(entities.closedWay.map(function(d) {
var member = [{ id: d.id }];
member.nodes = graph.childNodes(d);
return member;
}));
var contained = polygons.map(function(w, i2) {
return polygons.map(function(d, n2) {
if (i2 === n2)
return null;
return geoPolygonContainsPolygon(d.nodes.map(function(n3) {
return n3.loc;
}), w.nodes.map(function(n3) {
return n3.loc;
}));
});
});
var members = [];
var outer = true;
while (polygons.length) {
extractUncontained(polygons);
polygons = polygons.filter(isContained);
contained = contained.filter(isContained).map(filterContained);
}
function isContained(d, i2) {
return contained[i2].some(function(val) {
return val;
});
}
function filterContained(d) {
return d.filter(isContained);
}
function extractUncontained(polygons2) {
polygons2.forEach(function(d, i2) {
if (!isContained(d, i2)) {
d.forEach(function(member) {
members.push({
type: "way",
id: member.id,
role: outer ? "outer" : "inner"
});
});
}
});
outer = !outer;
}
var relation;
if (entities.multipolygon.length > 0) {
var oldestID = utilOldestID(entities.multipolygon.map((entity) => entity.id));
relation = entities.multipolygon.find((entity) => entity.id === oldestID);
} else {
relation = osmRelation({ id: newRelationId, tags: { type: "multipolygon" } });
}
entities.multipolygon.forEach(function(m) {
if (m.id !== relation.id) {
relation = relation.mergeTags(m.tags);
graph = graph.remove(m);
}
});
entities.closedWay.forEach(function(way) {
function isThisOuter(m) {
return m.id === way.id && m.role !== "inner";
}
if (members.some(isThisOuter)) {
relation = relation.mergeTags(way.tags);
graph = graph.replace(way.update({ tags: {} }));
}
});
return graph.replace(relation.update({
members,
tags: utilObjectOmit(relation.tags, ["area"])
}));
};
action.disabled = function(graph) {
var entities = groupEntities(graph);
if (entities.other.length > 0 || entities.closedWay.length + entities.multipolygon.length < 2) {
return "not_eligible";
}
if (!entities.multipolygon.every(function(r) {
return r.isComplete(graph);
})) {
return "incomplete_relation";
}
if (!entities.multipolygon.length) {
var sharedMultipolygons = [];
entities.closedWay.forEach(function(way, i2) {
if (i2 === 0) {
sharedMultipolygons = graph.parentMultipolygons(way);
} else {
sharedMultipolygons = utilArrayIntersection(sharedMultipolygons, graph.parentMultipolygons(way));
}
});
sharedMultipolygons = sharedMultipolygons.filter(function(relation) {
return relation.members.length === entities.closedWay.length;
});
if (sharedMultipolygons.length) {
return "not_eligible";
}
} else if (entities.closedWay.some(function(way) {
return utilArrayIntersection(graph.parentMultipolygons(way), entities.multipolygon).length;
})) {
return "not_eligible";
}
};
return action;
}
// modules/actions/merge_remote_changes.js
var import_fast_deep_equal = __toESM(require_fast_deep_equal());
// node_modules/node-diff3/index.mjs
function LCS(buffer1, buffer2) {
let equivalenceClasses = {};
for (let j2 = 0; j2 < buffer2.length; j2++) {
const item = buffer2[j2];
if (equivalenceClasses[item]) {
equivalenceClasses[item].push(j2);
} else {
equivalenceClasses[item] = [j2];
}
}
const NULLRESULT = { buffer1index: -1, buffer2index: -1, chain: null };
let candidates = [NULLRESULT];
for (let i2 = 0; i2 < buffer1.length; i2++) {
const item = buffer1[i2];
const buffer2indices = equivalenceClasses[item] || [];
let r = 0;
let c = candidates[0];
for (let jx = 0; jx < buffer2indices.length; jx++) {
const j2 = buffer2indices[jx];
let s;
for (s = r; s < candidates.length; s++) {
if (candidates[s].buffer2index < j2 && (s === candidates.length - 1 || candidates[s + 1].buffer2index > j2)) {
break;
}
}
if (s < candidates.length) {
const newCandidate = { buffer1index: i2, buffer2index: j2, chain: candidates[s] };
if (r === candidates.length) {
candidates.push(c);
} else {
candidates[r] = c;
}
r = s + 1;
c = newCandidate;
if (r === candidates.length) {
break;
}
}
}
candidates[r] = c;
}
return candidates[candidates.length - 1];
}
function diffIndices(buffer1, buffer2) {
const lcs = LCS(buffer1, buffer2);
let result = [];
let tail1 = buffer1.length;
let tail2 = buffer2.length;
for (let candidate = lcs; candidate !== null; candidate = candidate.chain) {
const mismatchLength1 = tail1 - candidate.buffer1index - 1;
const mismatchLength2 = tail2 - candidate.buffer2index - 1;
tail1 = candidate.buffer1index;
tail2 = candidate.buffer2index;
if (mismatchLength1 || mismatchLength2) {
result.push({
buffer1: [tail1 + 1, mismatchLength1],
buffer1Content: buffer1.slice(tail1 + 1, tail1 + 1 + mismatchLength1),
buffer2: [tail2 + 1, mismatchLength2],
buffer2Content: buffer2.slice(tail2 + 1, tail2 + 1 + mismatchLength2)
});
}
}
result.reverse();
return result;
}
function diff3MergeRegions(a, o, b) {
let hunks = [];
function addHunk(h, ab) {
hunks.push({
ab,
oStart: h.buffer1[0],
oLength: h.buffer1[1],
abStart: h.buffer2[0],
abLength: h.buffer2[1]
});
}
diffIndices(o, a).forEach((item) => addHunk(item, "a"));
diffIndices(o, b).forEach((item) => addHunk(item, "b"));
hunks.sort((x, y) => x.oStart - y.oStart);
let results = [];
let currOffset = 0;
function advanceTo(endOffset) {
if (endOffset > currOffset) {
results.push({
stable: true,
buffer: "o",
bufferStart: currOffset,
bufferLength: endOffset - currOffset,
bufferContent: o.slice(currOffset, endOffset)
});
currOffset = endOffset;
}
}
while (hunks.length) {
let hunk = hunks.shift();
let regionStart = hunk.oStart;
let regionEnd = hunk.oStart + hunk.oLength;
let regionHunks = [hunk];
advanceTo(regionStart);
while (hunks.length) {
const nextHunk = hunks[0];
const nextHunkStart = nextHunk.oStart;
if (nextHunkStart > regionEnd)
break;
regionEnd = Math.max(regionEnd, nextHunkStart + nextHunk.oLength);
regionHunks.push(hunks.shift());
}
if (regionHunks.length === 1) {
if (hunk.abLength > 0) {
const buffer = hunk.ab === "a" ? a : b;
results.push({
stable: true,
buffer: hunk.ab,
bufferStart: hunk.abStart,
bufferLength: hunk.abLength,
bufferContent: buffer.slice(hunk.abStart, hunk.abStart + hunk.abLength)
});
}
} else {
let bounds = {
a: [a.length, -1, o.length, -1],
b: [b.length, -1, o.length, -1]
};
while (regionHunks.length) {
hunk = regionHunks.shift();
const oStart = hunk.oStart;
const oEnd = oStart + hunk.oLength;
const abStart = hunk.abStart;
const abEnd = abStart + hunk.abLength;
let b2 = bounds[hunk.ab];
b2[0] = Math.min(abStart, b2[0]);
b2[1] = Math.max(abEnd, b2[1]);
b2[2] = Math.min(oStart, b2[2]);
b2[3] = Math.max(oEnd, b2[3]);
}
const aStart = bounds.a[0] + (regionStart - bounds.a[2]);
const aEnd = bounds.a[1] + (regionEnd - bounds.a[3]);
const bStart = bounds.b[0] + (regionStart - bounds.b[2]);
const bEnd = bounds.b[1] + (regionEnd - bounds.b[3]);
let result = {
stable: false,
aStart,
aLength: aEnd - aStart,
aContent: a.slice(aStart, aEnd),
oStart: regionStart,
oLength: regionEnd - regionStart,
oContent: o.slice(regionStart, regionEnd),
bStart,
bLength: bEnd - bStart,
bContent: b.slice(bStart, bEnd)
};
results.push(result);
}
currOffset = regionEnd;
}
advanceTo(o.length);
return results;
}
function diff3Merge(a, o, b, options2) {
let defaults2 = {
excludeFalseConflicts: true,
stringSeparator: /\s+/
};
options2 = Object.assign(defaults2, options2);
if (typeof a === "string")
a = a.split(options2.stringSeparator);
if (typeof o === "string")
o = o.split(options2.stringSeparator);
if (typeof b === "string")
b = b.split(options2.stringSeparator);
let results = [];
const regions = diff3MergeRegions(a, o, b);
let okBuffer = [];
function flushOk() {
if (okBuffer.length) {
results.push({ ok: okBuffer });
}
okBuffer = [];
}
function isFalseConflict(a2, b2) {
if (a2.length !== b2.length)
return false;
for (let i2 = 0; i2 < a2.length; i2++) {
if (a2[i2] !== b2[i2])
return false;
}
return true;
}
regions.forEach((region) => {
if (region.stable) {
okBuffer.push(...region.bufferContent);
} else {
if (options2.excludeFalseConflicts && isFalseConflict(region.aContent, region.bContent)) {
okBuffer.push(...region.aContent);
} else {
flushOk();
results.push({
conflict: {
a: region.aContent,
aIndex: region.aStart,
o: region.oContent,
oIndex: region.oStart,
b: region.bContent,
bIndex: region.bStart
}
});
}
}
});
flushOk();
return results;
}
// modules/actions/merge_remote_changes.js
var import_lodash = __toESM(require_lodash());
function actionMergeRemoteChanges(id2, localGraph, remoteGraph, discardTags, formatUser) {
discardTags = discardTags || {};
var _option = "safe";
var _conflicts = [];
function user(d) {
return typeof formatUser === "function" ? formatUser(d) : (0, import_lodash.escape)(d);
}
function mergeLocation(remote, target) {
function pointEqual(a, b) {
var epsilon3 = 1e-6;
return Math.abs(a[0] - b[0]) < epsilon3 && Math.abs(a[1] - b[1]) < epsilon3;
}
if (_option === "force_local" || pointEqual(target.loc, remote.loc)) {
return target;
}
if (_option === "force_remote") {
return target.update({ loc: remote.loc });
}
_conflicts.push(_t.html("merge_remote_changes.conflict.location", { user: { html: user(remote.user) } }));
return target;
}
function mergeNodes(base, remote, target) {
if (_option === "force_local" || (0, import_fast_deep_equal.default)(target.nodes, remote.nodes)) {
return target;
}
if (_option === "force_remote") {
return target.update({ nodes: remote.nodes });
}
var ccount = _conflicts.length;
var o = base.nodes || [];
var a = target.nodes || [];
var b = remote.nodes || [];
var nodes = [];
var hunks = diff3Merge(a, o, b, { excludeFalseConflicts: true });
for (var i2 = 0; i2 < hunks.length; i2++) {
var hunk = hunks[i2];
if (hunk.ok) {
nodes.push.apply(nodes, hunk.ok);
} else {
var c = hunk.conflict;
if ((0, import_fast_deep_equal.default)(c.o, c.a)) {
nodes.push.apply(nodes, c.b);
} else if ((0, import_fast_deep_equal.default)(c.o, c.b)) {
nodes.push.apply(nodes, c.a);
} else {
_conflicts.push(_t.html("merge_remote_changes.conflict.nodelist", { user: { html: user(remote.user) } }));
break;
}
}
}
return _conflicts.length === ccount ? target.update({ nodes }) : target;
}
function mergeChildren(targetWay, children2, updates, graph) {
function isUsed(node2, targetWay2) {
var hasInterestingParent = graph.parentWays(node2).some(function(way) {
return way.id !== targetWay2.id;
});
return node2.hasInterestingTags() || hasInterestingParent || graph.parentRelations(node2).length > 0;
}
var ccount = _conflicts.length;
for (var i2 = 0; i2 < children2.length; i2++) {
var id3 = children2[i2];
var node = graph.hasEntity(id3);
if (targetWay.nodes.indexOf(id3) === -1) {
if (node && !isUsed(node, targetWay)) {
updates.removeIds.push(id3);
}
continue;
}
var local = localGraph.hasEntity(id3);
var remote = remoteGraph.hasEntity(id3);
var target;
if (_option === "force_remote" && remote && remote.visible) {
updates.replacements.push(remote);
} else if (_option === "force_local" && local) {
target = osmEntity(local);
if (remote) {
target = target.update({ version: remote.version });
}
updates.replacements.push(target);
} else if (_option === "safe" && local && remote && local.version !== remote.version) {
target = osmEntity(local, { version: remote.version });
if (remote.visible) {
target = mergeLocation(remote, target);
} else {
_conflicts.push(_t.html("merge_remote_changes.conflict.deleted", { user: { html: user(remote.user) } }));
}
if (_conflicts.length !== ccount)
break;
updates.replacements.push(target);
}
}
return targetWay;
}
function updateChildren(updates, graph) {
for (var i2 = 0; i2 < updates.replacements.length; i2++) {
graph = graph.replace(updates.replacements[i2]);
}
if (updates.removeIds.length) {
graph = actionDeleteMultiple(updates.removeIds)(graph);
}
return graph;
}
function mergeMembers(remote, target) {
if (_option === "force_local" || (0, import_fast_deep_equal.default)(target.members, remote.members)) {
return target;
}
if (_option === "force_remote") {
return target.update({ members: remote.members });
}
_conflicts.push(_t.html("merge_remote_changes.conflict.memberlist", { user: { html: user(remote.user) } }));
return target;
}
function mergeTags(base, remote, target) {
if (_option === "force_local" || (0, import_fast_deep_equal.default)(target.tags, remote.tags)) {
return target;
}
if (_option === "force_remote") {
return target.update({ tags: remote.tags });
}
var ccount = _conflicts.length;
var o = base.tags || {};
var a = target.tags || {};
var b = remote.tags || {};
var keys = utilArrayUnion(utilArrayUnion(Object.keys(o), Object.keys(a)), Object.keys(b)).filter(function(k2) {
return !discardTags[k2];
});
var tags = Object.assign({}, a);
var changed = false;
for (var i2 = 0; i2 < keys.length; i2++) {
var k = keys[i2];
if (o[k] !== b[k] && a[k] !== b[k]) {
if (o[k] !== a[k]) {
_conflicts.push(_t.html("merge_remote_changes.conflict.tags", { tag: k, local: a[k], remote: b[k], user: { html: user(remote.user) } }));
} else {
if (b.hasOwnProperty(k)) {
tags[k] = b[k];
} else {
delete tags[k];
}
changed = true;
}
}
}
return changed && _conflicts.length === ccount ? target.update({ tags }) : target;
}
var action = function(graph) {
var updates = { replacements: [], removeIds: [] };
var base = graph.base().entities[id2];
var local = localGraph.entity(id2);
var remote = remoteGraph.entity(id2);
var target = osmEntity(local, { version: remote.version });
if (!remote.visible) {
if (_option === "force_remote") {
return actionDeleteMultiple([id2])(graph);
} else if (_option === "force_local") {
if (target.type === "way") {
target = mergeChildren(target, utilArrayUniq(local.nodes), updates, graph);
graph = updateChildren(updates, graph);
}
return graph.replace(target);
} else {
_conflicts.push(_t.html("merge_remote_changes.conflict.deleted", { user: { html: user(remote.user) } }));
return graph;
}
}
if (target.type === "node") {
target = mergeLocation(remote, target);
} else if (target.type === "way") {
graph.rebase(remoteGraph.childNodes(remote), [graph], false);
target = mergeNodes(base, remote, target);
target = mergeChildren(target, utilArrayUnion(local.nodes, remote.nodes), updates, graph);
} else if (target.type === "relation") {
target = mergeMembers(remote, target);
}
target = mergeTags(base, remote, target);
if (!_conflicts.length) {
graph = updateChildren(updates, graph).replace(target);
}
return graph;
};
action.withOption = function(opt) {
_option = opt;
return action;
};
action.conflicts = function() {
return _conflicts;
};
return action;
}
// modules/actions/move.js
function actionMove(moveIDs, tryDelta, projection2, cache) {
var _delta = tryDelta;
function setupCache(graph) {
function canMove(nodeID) {
if (moveIDs.indexOf(nodeID) !== -1)
return true;
var parents = graph.parentWays(graph.entity(nodeID));
if (parents.length < 3)
return true;
var parentsMoving = parents.every(function(way) {
return cache.moving[way.id];
});
if (!parentsMoving)
delete cache.moving[nodeID];
return parentsMoving;
}
function cacheEntities(ids) {
for (var i2 = 0; i2 < ids.length; i2++) {
var id2 = ids[i2];
if (cache.moving[id2])
continue;
cache.moving[id2] = true;
var entity = graph.hasEntity(id2);
if (!entity)
continue;
if (entity.type === "node") {
cache.nodes.push(id2);
cache.startLoc[id2] = entity.loc;
} else if (entity.type === "way") {
cache.ways.push(id2);
cacheEntities(entity.nodes);
} else {
cacheEntities(entity.members.map(function(member) {
return member.id;
}));
}
}
}
function cacheIntersections(ids) {
function isEndpoint(way2, id3) {
return !way2.isClosed() && !!way2.affix(id3);
}
for (var i2 = 0; i2 < ids.length; i2++) {
var id2 = ids[i2];
var childNodes = graph.childNodes(graph.entity(id2));
for (var j2 = 0; j2 < childNodes.length; j2++) {
var node = childNodes[j2];
var parents = graph.parentWays(node);
if (parents.length !== 2)
continue;
var moved = graph.entity(id2);
var unmoved = null;
for (var k = 0; k < parents.length; k++) {
var way = parents[k];
if (!cache.moving[way.id]) {
unmoved = way;
break;
}
}
if (!unmoved)
continue;
if (utilArrayIntersection(moved.nodes, unmoved.nodes).length > 2)
continue;
if (moved.isArea() || unmoved.isArea())
continue;
cache.intersections.push({
nodeId: node.id,
movedId: moved.id,
unmovedId: unmoved.id,
movedIsEP: isEndpoint(moved, node.id),
unmovedIsEP: isEndpoint(unmoved, node.id)
});
}
}
}
if (!cache) {
cache = {};
}
if (!cache.ok) {
cache.moving = {};
cache.intersections = [];
cache.replacedVertex = {};
cache.startLoc = {};
cache.nodes = [];
cache.ways = [];
cacheEntities(moveIDs);
cacheIntersections(cache.ways);
cache.nodes = cache.nodes.filter(canMove);
cache.ok = true;
}
}
function replaceMovedVertex(nodeId, wayId, graph, delta) {
var way = graph.entity(wayId);
var moved = graph.entity(nodeId);
var movedIndex = way.nodes.indexOf(nodeId);
var len, prevIndex, nextIndex;
if (way.isClosed()) {
len = way.nodes.length - 1;
prevIndex = (movedIndex + len - 1) % len;
nextIndex = (movedIndex + len + 1) % len;
} else {
len = way.nodes.length;
prevIndex = movedIndex - 1;
nextIndex = movedIndex + 1;
}
var prev = graph.hasEntity(way.nodes[prevIndex]);
var next = graph.hasEntity(way.nodes[nextIndex]);
if (!prev || !next)
return graph;
var key = wayId + "_" + nodeId;
var orig = cache.replacedVertex[key];
if (!orig) {
orig = osmNode();
cache.replacedVertex[key] = orig;
cache.startLoc[orig.id] = cache.startLoc[nodeId];
}
var start2, end;
if (delta) {
start2 = projection2(cache.startLoc[nodeId]);
end = projection2.invert(geoVecAdd(start2, delta));
} else {
end = cache.startLoc[nodeId];
}
orig = orig.move(end);
var angle2 = Math.abs(geoAngle(orig, prev, projection2) - geoAngle(orig, next, projection2)) * 180 / Math.PI;
if (angle2 > 175 && angle2 < 185)
return graph;
var p1 = [prev.loc, orig.loc, moved.loc, next.loc].map(projection2);
var p2 = [prev.loc, moved.loc, orig.loc, next.loc].map(projection2);
var d1 = geoPathLength(p1);
var d2 = geoPathLength(p2);
var insertAt = d1 <= d2 ? movedIndex : nextIndex;
if (way.isClosed() && insertAt === 0)
insertAt = len;
way = way.addNode(orig.id, insertAt);
return graph.replace(orig).replace(way);
}
function removeDuplicateVertices(wayId, graph) {
var way = graph.entity(wayId);
var epsilon3 = 1e-6;
var prev, curr;
function isInteresting(node, graph2) {
return graph2.parentWays(node).length > 1 || graph2.parentRelations(node).length || node.hasInterestingTags();
}
for (var i2 = 0; i2 < way.nodes.length; i2++) {
curr = graph.entity(way.nodes[i2]);
if (prev && curr && geoVecEqual(prev.loc, curr.loc, epsilon3)) {
if (!isInteresting(prev, graph)) {
way = way.removeNode(prev.id);
graph = graph.replace(way).remove(prev);
} else if (!isInteresting(curr, graph)) {
way = way.removeNode(curr.id);
graph = graph.replace(way).remove(curr);
}
}
prev = curr;
}
return graph;
}
function unZorroIntersection(intersection, graph) {
var vertex = graph.entity(intersection.nodeId);
var way1 = graph.entity(intersection.movedId);
var way2 = graph.entity(intersection.unmovedId);
var isEP1 = intersection.movedIsEP;
var isEP2 = intersection.unmovedIsEP;
if (isEP1 && isEP2)
return graph;
var nodes1 = graph.childNodes(way1).filter(function(n2) {
return n2 !== vertex;
});
var nodes2 = graph.childNodes(way2).filter(function(n2) {
return n2 !== vertex;
});
if (way1.isClosed() && way1.first() === vertex.id)
nodes1.push(nodes1[0]);
if (way2.isClosed() && way2.first() === vertex.id)
nodes2.push(nodes2[0]);
var edge1 = !isEP1 && geoChooseEdge(nodes1, projection2(vertex.loc), projection2);
var edge2 = !isEP2 && geoChooseEdge(nodes2, projection2(vertex.loc), projection2);
var loc;
if (!isEP1 && !isEP2) {
var epsilon3 = 1e-6, maxIter = 10;
for (var i2 = 0; i2 < maxIter; i2++) {
loc = geoVecInterp(edge1.loc, edge2.loc, 0.5);
edge1 = geoChooseEdge(nodes1, projection2(loc), projection2);
edge2 = geoChooseEdge(nodes2, projection2(loc), projection2);
if (Math.abs(edge1.distance - edge2.distance) < epsilon3)
break;
}
} else if (!isEP1) {
loc = edge1.loc;
} else {
loc = edge2.loc;
}
graph = graph.replace(vertex.move(loc));
if (!isEP1 && edge1.index !== way1.nodes.indexOf(vertex.id)) {
way1 = way1.removeNode(vertex.id).addNode(vertex.id, edge1.index);
graph = graph.replace(way1);
}
if (!isEP2 && edge2.index !== way2.nodes.indexOf(vertex.id)) {
way2 = way2.removeNode(vertex.id).addNode(vertex.id, edge2.index);
graph = graph.replace(way2);
}
return graph;
}
function cleanupIntersections(graph) {
for (var i2 = 0; i2 < cache.intersections.length; i2++) {
var obj = cache.intersections[i2];
graph = replaceMovedVertex(obj.nodeId, obj.movedId, graph, _delta);
graph = replaceMovedVertex(obj.nodeId, obj.unmovedId, graph, null);
graph = unZorroIntersection(obj, graph);
graph = removeDuplicateVertices(obj.movedId, graph);
graph = removeDuplicateVertices(obj.unmovedId, graph);
}
return graph;
}
function limitDelta(graph) {
function moveNode(loc) {
return geoVecAdd(projection2(loc), _delta);
}
for (var i2 = 0; i2 < cache.intersections.length; i2++) {
var obj = cache.intersections[i2];
if (obj.movedIsEP && obj.unmovedIsEP)
continue;
if (!obj.movedIsEP)
continue;
var node = graph.entity(obj.nodeId);
var start2 = projection2(node.loc);
var end = geoVecAdd(start2, _delta);
var movedNodes = graph.childNodes(graph.entity(obj.movedId));
var movedPath = movedNodes.map(function(n2) {
return moveNode(n2.loc);
});
var unmovedNodes = graph.childNodes(graph.entity(obj.unmovedId));
var unmovedPath = unmovedNodes.map(function(n2) {
return projection2(n2.loc);
});
var hits = geoPathIntersections(movedPath, unmovedPath);
for (var j2 = 0; i2 < hits.length; i2++) {
if (geoVecEqual(hits[j2], end))
continue;
var edge = geoChooseEdge(unmovedNodes, end, projection2);
_delta = geoVecSubtract(projection2(edge.loc), start2);
}
}
}
var action = function(graph) {
if (_delta[0] === 0 && _delta[1] === 0)
return graph;
setupCache(graph);
if (cache.intersections.length) {
limitDelta(graph);
}
for (var i2 = 0; i2 < cache.nodes.length; i2++) {
var node = graph.entity(cache.nodes[i2]);
var start2 = projection2(node.loc);
var end = geoVecAdd(start2, _delta);
graph = graph.replace(node.move(projection2.invert(end)));
}
if (cache.intersections.length) {
graph = cleanupIntersections(graph);
}
return graph;
};
action.delta = function() {
return _delta;
};
return action;
}
// modules/actions/move_member.js
function actionMoveMember(relationId, fromIndex, toIndex) {
return function(graph) {
return graph.replace(graph.entity(relationId).moveMember(fromIndex, toIndex));
};
}
// modules/actions/move_node.js
function actionMoveNode(nodeID, toLoc) {
var action = function(graph, t) {
if (t === null || !isFinite(t))
t = 1;
t = Math.min(Math.max(+t, 0), 1);
var node = graph.entity(nodeID);
return graph.replace(node.move(geoVecInterp(node.loc, toLoc, t)));
};
action.transitionable = true;
return action;
}
// modules/actions/noop.js
function actionNoop() {
return function(graph) {
return graph;
};
}
// modules/actions/orthogonalize.js
function actionOrthogonalize(wayID, projection2, vertexID, degThresh, ep) {
var epsilon3 = ep || 1e-4;
var threshold = degThresh || 13;
var lowerThreshold = Math.cos((90 - threshold) * Math.PI / 180);
var upperThreshold = Math.cos(threshold * Math.PI / 180);
var action = function(graph, t) {
if (t === null || !isFinite(t))
t = 1;
t = Math.min(Math.max(+t, 0), 1);
var way = graph.entity(wayID);
way = way.removeNode("");
if (way.tags.nonsquare) {
var tags = Object.assign({}, way.tags);
delete tags.nonsquare;
way = way.update({ tags });
}
graph = graph.replace(way);
var isClosed = way.isClosed();
var nodes = graph.childNodes(way).slice();
if (isClosed)
nodes.pop();
if (vertexID !== void 0) {
nodes = nodeSubset(nodes, vertexID, isClosed);
if (nodes.length !== 3)
return graph;
}
var nodeCount = {};
var points = [];
var corner = { i: 0, dotp: 1 };
var node, point, loc, score, motions, i2, j2;
for (i2 = 0; i2 < nodes.length; i2++) {
node = nodes[i2];
nodeCount[node.id] = (nodeCount[node.id] || 0) + 1;
points.push({ id: node.id, coord: projection2(node.loc) });
}
if (points.length === 3) {
for (i2 = 0; i2 < 1e3; i2++) {
motions = points.map(calcMotion);
points[corner.i].coord = geoVecAdd(points[corner.i].coord, motions[corner.i]);
score = corner.dotp;
if (score < epsilon3) {
break;
}
}
node = graph.entity(nodes[corner.i].id);
loc = projection2.invert(points[corner.i].coord);
graph = graph.replace(node.move(geoVecInterp(node.loc, loc, t)));
} else {
var straights = [];
var simplified = [];
for (i2 = 0; i2 < points.length; i2++) {
point = points[i2];
var dotp = 0;
if (isClosed || i2 > 0 && i2 < points.length - 1) {
var a = points[(i2 - 1 + points.length) % points.length];
var b = points[(i2 + 1) % points.length];
dotp = Math.abs(geoOrthoNormalizedDotProduct(a.coord, b.coord, point.coord));
}
if (dotp > upperThreshold) {
straights.push(point);
} else {
simplified.push(point);
}
}
var bestPoints = clonePoints(simplified);
var originalPoints = clonePoints(simplified);
score = Infinity;
for (i2 = 0; i2 < 1e3; i2++) {
motions = simplified.map(calcMotion);
for (j2 = 0; j2 < motions.length; j2++) {
simplified[j2].coord = geoVecAdd(simplified[j2].coord, motions[j2]);
}
var newScore = geoOrthoCalcScore(simplified, isClosed, epsilon3, threshold);
if (newScore < score) {
bestPoints = clonePoints(simplified);
score = newScore;
}
if (score < epsilon3) {
break;
}
}
var bestCoords = bestPoints.map(function(p) {
return p.coord;
});
if (isClosed)
bestCoords.push(bestCoords[0]);
for (i2 = 0; i2 < bestPoints.length; i2++) {
point = bestPoints[i2];
if (!geoVecEqual(originalPoints[i2].coord, point.coord)) {
node = graph.entity(point.id);
loc = projection2.invert(point.coord);
graph = graph.replace(node.move(geoVecInterp(node.loc, loc, t)));
}
}
for (i2 = 0; i2 < straights.length; i2++) {
point = straights[i2];
if (nodeCount[point.id] > 1)
continue;
node = graph.entity(point.id);
if (t === 1 && graph.parentWays(node).length === 1 && graph.parentRelations(node).length === 0 && !node.hasInterestingTags()) {
graph = actionDeleteNode(node.id)(graph);
} else {
var choice = geoVecProject(point.coord, bestCoords);
if (choice) {
loc = projection2.invert(choice.target);
graph = graph.replace(node.move(geoVecInterp(node.loc, loc, t)));
}
}
}
}
return graph;
function clonePoints(array2) {
return array2.map(function(p) {
return { id: p.id, coord: [p.coord[0], p.coord[1]] };
});
}
function calcMotion(point2, i3, array2) {
if (!isClosed && (i3 === 0 || i3 === array2.length - 1))
return [0, 0];
if (nodeCount[array2[i3].id] > 1)
return [0, 0];
var a2 = array2[(i3 - 1 + array2.length) % array2.length].coord;
var origin = point2.coord;
var b2 = array2[(i3 + 1) % array2.length].coord;
var p = geoVecSubtract(a2, origin);
var q = geoVecSubtract(b2, origin);
var scale = 2 * Math.min(geoVecLength(p), geoVecLength(q));
p = geoVecNormalize(p);
q = geoVecNormalize(q);
var dotp2 = p[0] * q[0] + p[1] * q[1];
var val = Math.abs(dotp2);
if (val < lowerThreshold) {
corner.i = i3;
corner.dotp = val;
var vec = geoVecNormalize(geoVecAdd(p, q));
return geoVecScale(vec, 0.1 * dotp2 * scale);
}
return [0, 0];
}
};
function nodeSubset(nodes, vertexID2, isClosed) {
var first = isClosed ? 0 : 1;
var last = isClosed ? nodes.length : nodes.length - 1;
for (var i2 = first; i2 < last; i2++) {
if (nodes[i2].id === vertexID2) {
return [
nodes[(i2 - 1 + nodes.length) % nodes.length],
nodes[i2],
nodes[(i2 + 1) % nodes.length]
];
}
}
return [];
}
action.disabled = function(graph) {
var way = graph.entity(wayID);
way = way.removeNode("");
graph = graph.replace(way);
var isClosed = way.isClosed();
var nodes = graph.childNodes(way).slice();
if (isClosed)
nodes.pop();
var allowStraightAngles = false;
if (vertexID !== void 0) {
allowStraightAngles = true;
nodes = nodeSubset(nodes, vertexID, isClosed);
if (nodes.length !== 3)
return "end_vertex";
}
var coords = nodes.map(function(n2) {
return projection2(n2.loc);
});
var score = geoOrthoCanOrthogonalize(coords, isClosed, epsilon3, threshold, allowStraightAngles);
if (score === null) {
return "not_squarish";
} else if (score === 0) {
return "square_enough";
} else {
return false;
}
};
action.transitionable = true;
return action;
}
// modules/actions/restrict_turn.js
function actionRestrictTurn(turn, restrictionType, restrictionID) {
return function(graph) {
var fromWay = graph.entity(turn.from.way);
var toWay = graph.entity(turn.to.way);
var viaNode = turn.via.node && graph.entity(turn.via.node);
var viaWays = turn.via.ways && turn.via.ways.map(function(id2) {
return graph.entity(id2);
});
var members = [];
members.push({ id: fromWay.id, type: "way", role: "from" });
if (viaNode) {
members.push({ id: viaNode.id, type: "node", role: "via" });
} else if (viaWays) {
viaWays.forEach(function(viaWay) {
members.push({ id: viaWay.id, type: "way", role: "via" });
});
}
members.push({ id: toWay.id, type: "way", role: "to" });
return graph.replace(osmRelation({
id: restrictionID,
tags: {
type: "restriction",
restriction: restrictionType
},
members
}));
};
}
// modules/actions/revert.js
function actionRevert(id2) {
var action = function(graph) {
var entity = graph.hasEntity(id2), base = graph.base().entities[id2];
if (entity && !base) {
if (entity.type === "node") {
graph.parentWays(entity).forEach(function(parent) {
parent = parent.removeNode(id2);
graph = graph.replace(parent);
if (parent.isDegenerate()) {
graph = actionDeleteWay(parent.id)(graph);
}
});
}
graph.parentRelations(entity).forEach(function(parent) {
parent = parent.removeMembersWithID(id2);
graph = graph.replace(parent);
if (parent.isDegenerate()) {
graph = actionDeleteRelation(parent.id)(graph);
}
});
}
return graph.revert(id2);
};
return action;
}
// modules/actions/rotate.js
function actionRotate(rotateIds, pivot, angle2, projection2) {
var action = function(graph) {
return graph.update(function(graph2) {
utilGetAllNodes(rotateIds, graph2).forEach(function(node) {
var point = geoRotate([projection2(node.loc)], angle2, pivot)[0];
graph2 = graph2.replace(node.move(projection2.invert(point)));
});
});
};
return action;
}
// modules/actions/scale.js
function actionScale(ids, pivotLoc, scaleFactor, projection2) {
return function(graph) {
return graph.update(function(graph2) {
let point, radial;
utilGetAllNodes(ids, graph2).forEach(function(node) {
point = projection2(node.loc);
radial = [
point[0] - pivotLoc[0],
point[1] - pivotLoc[1]
];
point = [
pivotLoc[0] + scaleFactor * radial[0],
pivotLoc[1] + scaleFactor * radial[1]
];
graph2 = graph2.replace(node.move(projection2.invert(point)));
});
});
};
}
// modules/actions/straighten_nodes.js
function actionStraightenNodes(nodeIDs, projection2) {
function positionAlongWay(a, o, b) {
return geoVecDot(a, b, o) / geoVecDot(b, b, o);
}
function getEndpoints(points) {
var ssr = geoGetSmallestSurroundingRectangle(points);
var p1 = [(ssr.poly[0][0] + ssr.poly[1][0]) / 2, (ssr.poly[0][1] + ssr.poly[1][1]) / 2];
var q1 = [(ssr.poly[2][0] + ssr.poly[3][0]) / 2, (ssr.poly[2][1] + ssr.poly[3][1]) / 2];
var p2 = [(ssr.poly[3][0] + ssr.poly[4][0]) / 2, (ssr.poly[3][1] + ssr.poly[4][1]) / 2];
var q2 = [(ssr.poly[1][0] + ssr.poly[2][0]) / 2, (ssr.poly[1][1] + ssr.poly[2][1]) / 2];
var isLong = geoVecLength(p1, q1) > geoVecLength(p2, q2);
if (isLong) {
return [p1, q1];
}
return [p2, q2];
}
var action = function(graph, t) {
if (t === null || !isFinite(t))
t = 1;
t = Math.min(Math.max(+t, 0), 1);
var nodes = nodeIDs.map(function(id2) {
return graph.entity(id2);
});
var points = nodes.map(function(n2) {
return projection2(n2.loc);
});
var endpoints = getEndpoints(points);
var startPoint = endpoints[0];
var endPoint = endpoints[1];
for (var i2 = 0; i2 < points.length; i2++) {
var node = nodes[i2];
var point = points[i2];
var u = positionAlongWay(point, startPoint, endPoint);
var point2 = geoVecInterp(startPoint, endPoint, u);
var loc2 = projection2.invert(point2);
graph = graph.replace(node.move(geoVecInterp(node.loc, loc2, t)));
}
return graph;
};
action.disabled = function(graph) {
var nodes = nodeIDs.map(function(id2) {
return graph.entity(id2);
});
var points = nodes.map(function(n2) {
return projection2(n2.loc);
});
var endpoints = getEndpoints(points);
var startPoint = endpoints[0];
var endPoint = endpoints[1];
var maxDistance = 0;
for (var i2 = 0; i2 < points.length; i2++) {
var point = points[i2];
var u = positionAlongWay(point, startPoint, endPoint);
var p = geoVecInterp(startPoint, endPoint, u);
var dist = geoVecLength(p, point);
if (!isNaN(dist) && dist > maxDistance) {
maxDistance = dist;
}
}
if (maxDistance < 1e-4) {
return "straight_enough";
}
};
action.transitionable = true;
return action;
}
// modules/actions/straighten_way.js
function actionStraightenWay(selectedIDs, projection2) {
function positionAlongWay(a, o, b) {
return geoVecDot(a, b, o) / geoVecDot(b, b, o);
}
function allNodes(graph) {
var nodes = [];
var startNodes = [];
var endNodes = [];
var remainingWays = [];
var selectedWays = selectedIDs.filter(function(w) {
return graph.entity(w).type === "way";
});
var selectedNodes = selectedIDs.filter(function(n2) {
return graph.entity(n2).type === "node";
});
for (var i2 = 0; i2 < selectedWays.length; i2++) {
var way = graph.entity(selectedWays[i2]);
nodes = way.nodes.slice(0);
remainingWays.push(nodes);
startNodes.push(nodes[0]);
endNodes.push(nodes[nodes.length - 1]);
}
startNodes = startNodes.filter(function(n2) {
return startNodes.indexOf(n2) === startNodes.lastIndexOf(n2);
});
endNodes = endNodes.filter(function(n2) {
return endNodes.indexOf(n2) === endNodes.lastIndexOf(n2);
});
var currNode = utilArrayDifference(startNodes, endNodes).concat(utilArrayDifference(endNodes, startNodes))[0];
var nextWay = [];
nodes = [];
var getNextWay = function(currNode2, remainingWays2) {
return remainingWays2.filter(function(way2) {
return way2[0] === currNode2 || way2[way2.length - 1] === currNode2;
})[0];
};
while (remainingWays.length) {
nextWay = getNextWay(currNode, remainingWays);
remainingWays = utilArrayDifference(remainingWays, [nextWay]);
if (nextWay[0] !== currNode) {
nextWay.reverse();
}
nodes = nodes.concat(nextWay);
currNode = nodes[nodes.length - 1];
}
if (selectedNodes.length === 2) {
var startNodeIdx = nodes.indexOf(selectedNodes[0]);
var endNodeIdx = nodes.indexOf(selectedNodes[1]);
var sortedStartEnd = [startNodeIdx, endNodeIdx];
sortedStartEnd.sort(function(a, b) {
return a - b;
});
nodes = nodes.slice(sortedStartEnd[0], sortedStartEnd[1] + 1);
}
return nodes.map(function(n2) {
return graph.entity(n2);
});
}
function shouldKeepNode(node, graph) {
return graph.parentWays(node).length > 1 || graph.parentRelations(node).length || node.hasInterestingTags();
}
var action = function(graph, t) {
if (t === null || !isFinite(t))
t = 1;
t = Math.min(Math.max(+t, 0), 1);
var nodes = allNodes(graph);
var points = nodes.map(function(n2) {
return projection2(n2.loc);
});
var startPoint = points[0];
var endPoint = points[points.length - 1];
var toDelete = [];
var i2;
for (i2 = 1; i2 < points.length - 1; i2++) {
var node = nodes[i2];
var point = points[i2];
if (t < 1 || shouldKeepNode(node, graph)) {
var u = positionAlongWay(point, startPoint, endPoint);
var p = geoVecInterp(startPoint, endPoint, u);
var loc2 = projection2.invert(p);
graph = graph.replace(node.move(geoVecInterp(node.loc, loc2, t)));
} else {
if (toDelete.indexOf(node) === -1) {
toDelete.push(node);
}
}
}
for (i2 = 0; i2 < toDelete.length; i2++) {
graph = actionDeleteNode(toDelete[i2].id)(graph);
}
return graph;
};
action.disabled = function(graph) {
var nodes = allNodes(graph);
var points = nodes.map(function(n2) {
return projection2(n2.loc);
});
var startPoint = points[0];
var endPoint = points[points.length - 1];
var threshold = 0.2 * geoVecLength(startPoint, endPoint);
var i2;
if (threshold === 0) {
return "too_bendy";
}
var maxDistance = 0;
for (i2 = 1; i2 < points.length - 1; i2++) {
var point = points[i2];
var u = positionAlongWay(point, startPoint, endPoint);
var p = geoVecInterp(startPoint, endPoint, u);
var dist = geoVecLength(p, point);
if (isNaN(dist) || dist > threshold) {
return "too_bendy";
} else if (dist > maxDistance) {
maxDistance = dist;
}
}
var keepingAllNodes = nodes.every(function(node, i3) {
return i3 === 0 || i3 === nodes.length - 1 || shouldKeepNode(node, graph);
});
if (maxDistance < 1e-4 && keepingAllNodes) {
return "straight_enough";
}
};
action.transitionable = true;
return action;
}
// modules/actions/unrestrict_turn.js
function actionUnrestrictTurn(turn) {
return function(graph) {
return actionDeleteRelation(turn.restrictionID)(graph);
};
}
// modules/actions/reflect.js
function actionReflect(reflectIds, projection2) {
var _useLongAxis = true;
var action = function(graph, t) {
if (t === null || !isFinite(t))
t = 1;
t = Math.min(Math.max(+t, 0), 1);
var nodes = utilGetAllNodes(reflectIds, graph);
var points = nodes.map(function(n2) {
return projection2(n2.loc);
});
var ssr = geoGetSmallestSurroundingRectangle(points);
var p1 = [(ssr.poly[0][0] + ssr.poly[1][0]) / 2, (ssr.poly[0][1] + ssr.poly[1][1]) / 2];
var q1 = [(ssr.poly[2][0] + ssr.poly[3][0]) / 2, (ssr.poly[2][1] + ssr.poly[3][1]) / 2];
var p2 = [(ssr.poly[3][0] + ssr.poly[4][0]) / 2, (ssr.poly[3][1] + ssr.poly[4][1]) / 2];
var q2 = [(ssr.poly[1][0] + ssr.poly[2][0]) / 2, (ssr.poly[1][1] + ssr.poly[2][1]) / 2];
var p, q;
var isLong = geoVecLength(p1, q1) > geoVecLength(p2, q2);
if (_useLongAxis && isLong || !_useLongAxis && !isLong) {
p = p1;
q = q1;
} else {
p = p2;
q = q2;
}
var dx = q[0] - p[0];
var dy = q[1] - p[1];
var a = (dx * dx - dy * dy) / (dx * dx + dy * dy);
var b = 2 * dx * dy / (dx * dx + dy * dy);
for (var i2 = 0; i2 < nodes.length; i2++) {
var node = nodes[i2];
var c = projection2(node.loc);
var c2 = [
a * (c[0] - p[0]) + b * (c[1] - p[1]) + p[0],
b * (c[0] - p[0]) - a * (c[1] - p[1]) + p[1]
];
var loc2 = projection2.invert(c2);
node = node.move(geoVecInterp(node.loc, loc2, t));
graph = graph.replace(node);
}
return graph;
};
action.useLongAxis = function(val) {
if (!arguments.length)
return _useLongAxis;
_useLongAxis = val;
return action;
};
action.transitionable = true;
return action;
}
// modules/actions/upgrade_tags.js
function actionUpgradeTags(entityId, oldTags, replaceTags) {
return function(graph) {
var entity = graph.entity(entityId);
var tags = Object.assign({}, entity.tags);
var transferValue;
var semiIndex;
for (var oldTagKey in oldTags) {
if (!(oldTagKey in tags))
continue;
if (oldTags[oldTagKey] === "*") {
transferValue = tags[oldTagKey];
delete tags[oldTagKey];
} else if (oldTags[oldTagKey] === tags[oldTagKey]) {
delete tags[oldTagKey];
} else {
var vals = tags[oldTagKey].split(";").filter(Boolean);
var oldIndex = vals.indexOf(oldTags[oldTagKey]);
if (vals.length === 1 || oldIndex === -1) {
delete tags[oldTagKey];
} else {
if (replaceTags && replaceTags[oldTagKey]) {
semiIndex = oldIndex;
}
vals.splice(oldIndex, 1);
tags[oldTagKey] = vals.join(";");
}
}
}
if (replaceTags) {
for (var replaceKey in replaceTags) {
var replaceValue = replaceTags[replaceKey];
if (replaceValue === "*") {
if (tags[replaceKey] && tags[replaceKey] !== "no") {
continue;
} else {
tags[replaceKey] = "yes";
}
} else if (replaceValue === "$1") {
tags[replaceKey] = transferValue;
} else {
if (tags[replaceKey] && oldTags[replaceKey] && semiIndex !== void 0) {
var existingVals = tags[replaceKey].split(";").filter(Boolean);
if (existingVals.indexOf(replaceValue) === -1) {
existingVals.splice(semiIndex, 0, replaceValue);
tags[replaceKey] = existingVals.join(";");
}
} else {
tags[replaceKey] = replaceValue;
}
}
}
}
return graph.replace(entity.update({ tags }));
};
}
// modules/behavior/edit.js
function behaviorEdit(context) {
function behavior() {
context.map().minzoom(context.minEditableZoom());
}
behavior.off = function() {
context.map().minzoom(0);
};
return behavior;
}
// modules/behavior/hover.js
function behaviorHover(context) {
var dispatch10 = dispatch_default("hover");
var _selection = select_default2(null);
var _newNodeId = null;
var _initialNodeID = null;
var _altDisables;
var _ignoreVertex;
var _targets = [];
var _pointerPrefix = "PointerEvent" in window ? "pointer" : "mouse";
function keydown(d3_event) {
if (_altDisables && d3_event.keyCode === utilKeybinding.modifierCodes.alt) {
_selection.selectAll(".hover").classed("hover-suppressed", true).classed("hover", false);
_selection.classed("hover-disabled", true);
dispatch10.call("hover", this, null);
}
}
function keyup(d3_event) {
if (_altDisables && d3_event.keyCode === utilKeybinding.modifierCodes.alt) {
_selection.selectAll(".hover-suppressed").classed("hover-suppressed", false).classed("hover", true);
_selection.classed("hover-disabled", false);
dispatch10.call("hover", this, _targets);
}
}
function behavior(selection2) {
_selection = selection2;
_targets = [];
if (_initialNodeID) {
_newNodeId = _initialNodeID;
_initialNodeID = null;
} else {
_newNodeId = null;
}
_selection.on(_pointerPrefix + "over.hover", pointerover).on(_pointerPrefix + "out.hover", pointerout).on(_pointerPrefix + "down.hover", pointerover);
select_default2(window).on(_pointerPrefix + "up.hover pointercancel.hover", pointerout, true).on("keydown.hover", keydown).on("keyup.hover", keyup);
function eventTarget(d3_event) {
var datum2 = d3_event.target && d3_event.target.__data__;
if (typeof datum2 !== "object")
return null;
if (!(datum2 instanceof osmEntity) && datum2.properties && datum2.properties.entity instanceof osmEntity) {
return datum2.properties.entity;
}
return datum2;
}
function pointerover(d3_event) {
if (context.mode().id.indexOf("drag") === -1 && (!d3_event.pointerType || d3_event.pointerType === "mouse") && d3_event.buttons)
return;
var target = eventTarget(d3_event);
if (target && _targets.indexOf(target) === -1) {
_targets.push(target);
updateHover(d3_event, _targets);
}
}
function pointerout(d3_event) {
var target = eventTarget(d3_event);
var index = _targets.indexOf(target);
if (index !== -1) {
_targets.splice(index);
updateHover(d3_event, _targets);
}
}
function allowsVertex(d) {
return d.geometry(context.graph()) === "vertex" || _mainPresetIndex.allowsVertex(d, context.graph());
}
function modeAllowsHover(target) {
var mode = context.mode();
if (mode.id === "add-point") {
return mode.preset.matchGeometry("vertex") || target.type !== "way" && target.geometry(context.graph()) !== "vertex";
}
return true;
}
function updateHover(d3_event, targets) {
_selection.selectAll(".hover").classed("hover", false);
_selection.selectAll(".hover-suppressed").classed("hover-suppressed", false);
var mode = context.mode();
if (!_newNodeId && (mode.id === "draw-line" || mode.id === "draw-area")) {
var node = targets.find(function(target) {
return target instanceof osmEntity && target.type === "node";
});
_newNodeId = node && node.id;
}
targets = targets.filter(function(datum3) {
if (datum3 instanceof osmEntity) {
return datum3.id !== _newNodeId && (datum3.type !== "node" || !_ignoreVertex || allowsVertex(datum3)) && modeAllowsHover(datum3);
}
return true;
});
var selector = "";
for (var i2 in targets) {
var datum2 = targets[i2];
if (datum2.__featurehash__) {
selector += ", .data" + datum2.__featurehash__;
} else if (datum2 instanceof QAItem) {
selector += ", ." + datum2.service + ".itemId-" + datum2.id;
} else if (datum2 instanceof osmNote) {
selector += ", .note-" + datum2.id;
} else if (datum2 instanceof osmEntity) {
selector += ", ." + datum2.id;
if (datum2.type === "relation") {
for (var j2 in datum2.members) {
selector += ", ." + datum2.members[j2].id;
}
}
}
}
var suppressed = _altDisables && d3_event && d3_event.altKey;
if (selector.trim().length) {
selector = selector.slice(1);
_selection.selectAll(selector).classed(suppressed ? "hover-suppressed" : "hover", true);
}
dispatch10.call("hover", this, !suppressed && targets);
}
}
behavior.off = function(selection2) {
selection2.selectAll(".hover").classed("hover", false);
selection2.selectAll(".hover-suppressed").classed("hover-suppressed", false);
selection2.classed("hover-disabled", false);
selection2.on(_pointerPrefix + "over.hover", null).on(_pointerPrefix + "out.hover", null).on(_pointerPrefix + "down.hover", null);
select_default2(window).on(_pointerPrefix + "up.hover pointercancel.hover", null, true).on("keydown.hover", null).on("keyup.hover", null);
};
behavior.altDisables = function(val) {
if (!arguments.length)
return _altDisables;
_altDisables = val;
return behavior;
};
behavior.ignoreVertex = function(val) {
if (!arguments.length)
return _ignoreVertex;
_ignoreVertex = val;
return behavior;
};
behavior.initialNodeID = function(nodeId) {
_initialNodeID = nodeId;
return behavior;
};
return utilRebind(behavior, dispatch10, "on");
}
// modules/behavior/draw.js
var _disableSpace = false;
var _lastSpace = null;
function behaviorDraw(context) {
var dispatch10 = dispatch_default("move", "down", "downcancel", "click", "clickWay", "clickNode", "undo", "cancel", "finish");
var keybinding = utilKeybinding("draw");
var _hover = behaviorHover(context).altDisables(true).ignoreVertex(true).on("hover", context.ui().sidebar.hover);
var _edit = behaviorEdit(context);
var _closeTolerance = 4;
var _tolerance = 12;
var _mouseLeave = false;
var _lastMouse = null;
var _lastPointerUpEvent;
var _downPointer;
var _pointerPrefix = "PointerEvent" in window ? "pointer" : "mouse";
function datum2(d3_event) {
var mode = context.mode();
var isNote = mode && mode.id.indexOf("note") !== -1;
if (d3_event.altKey || isNote)
return {};
var element;
if (d3_event.type === "keydown") {
element = _lastMouse && _lastMouse.target;
} else {
element = d3_event.target;
}
var d = element.__data__;
return d && d.properties && d.properties.target ? d : {};
}
function pointerdown(d3_event) {
if (_downPointer)
return;
var pointerLocGetter = utilFastMouse(this);
_downPointer = {
id: d3_event.pointerId || "mouse",
pointerLocGetter,
downTime: +new Date(),
downLoc: pointerLocGetter(d3_event)
};
dispatch10.call("down", this, d3_event, datum2(d3_event));
}
function pointerup(d3_event) {
if (!_downPointer || _downPointer.id !== (d3_event.pointerId || "mouse"))
return;
var downPointer = _downPointer;
_downPointer = null;
_lastPointerUpEvent = d3_event;
if (downPointer.isCancelled)
return;
var t2 = +new Date();
var p2 = downPointer.pointerLocGetter(d3_event);
var dist = geoVecLength(downPointer.downLoc, p2);
if (dist < _closeTolerance || dist < _tolerance && t2 - downPointer.downTime < 500) {
select_default2(window).on("click.draw-block", function() {
d3_event.stopPropagation();
}, true);
context.map().dblclickZoomEnable(false);
window.setTimeout(function() {
context.map().dblclickZoomEnable(true);
select_default2(window).on("click.draw-block", null);
}, 500);
click(d3_event, p2);
}
}
function pointermove(d3_event) {
if (_downPointer && _downPointer.id === (d3_event.pointerId || "mouse") && !_downPointer.isCancelled) {
var p2 = _downPointer.pointerLocGetter(d3_event);
var dist = geoVecLength(_downPointer.downLoc, p2);
if (dist >= _closeTolerance) {
_downPointer.isCancelled = true;
dispatch10.call("downcancel", this);
}
}
if (d3_event.pointerType && d3_event.pointerType !== "mouse" || d3_event.buttons || _downPointer)
return;
if (_lastPointerUpEvent && _lastPointerUpEvent.pointerType !== "mouse" && d3_event.timeStamp - _lastPointerUpEvent.timeStamp < 100)
return;
_lastMouse = d3_event;
dispatch10.call("move", this, d3_event, datum2(d3_event));
}
function pointercancel(d3_event) {
if (_downPointer && _downPointer.id === (d3_event.pointerId || "mouse")) {
if (!_downPointer.isCancelled) {
dispatch10.call("downcancel", this);
}
_downPointer = null;
}
}
function mouseenter() {
_mouseLeave = false;
}
function mouseleave() {
_mouseLeave = true;
}
function allowsVertex(d) {
return d.geometry(context.graph()) === "vertex" || _mainPresetIndex.allowsVertex(d, context.graph());
}
function click(d3_event, loc) {
var d = datum2(d3_event);
var target = d && d.properties && d.properties.entity;
var mode = context.mode();
if (target && target.type === "node" && allowsVertex(target)) {
dispatch10.call("clickNode", this, target, d);
return;
} else if (target && target.type === "way" && (mode.id !== "add-point" || mode.preset.matchGeometry("vertex"))) {
var choice = geoChooseEdge(context.graph().childNodes(target), loc, context.projection, context.activeID());
if (choice) {
var edge = [target.nodes[choice.index - 1], target.nodes[choice.index]];
dispatch10.call("clickWay", this, choice.loc, edge, d);
return;
}
} else if (mode.id !== "add-point" || mode.preset.matchGeometry("point")) {
var locLatLng = context.projection.invert(loc);
dispatch10.call("click", this, locLatLng, d);
}
}
function space(d3_event) {
d3_event.preventDefault();
d3_event.stopPropagation();
var currSpace = context.map().mouse();
if (_disableSpace && _lastSpace) {
var dist = geoVecLength(_lastSpace, currSpace);
if (dist > _tolerance) {
_disableSpace = false;
}
}
if (_disableSpace || _mouseLeave || !_lastMouse)
return;
_lastSpace = currSpace;
_disableSpace = true;
select_default2(window).on("keyup.space-block", function() {
d3_event.preventDefault();
d3_event.stopPropagation();
_disableSpace = false;
select_default2(window).on("keyup.space-block", null);
});
var loc = context.map().mouse() || context.projection(context.map().center());
click(d3_event, loc);
}
function backspace(d3_event) {
d3_event.preventDefault();
dispatch10.call("undo");
}
function del(d3_event) {
d3_event.preventDefault();
dispatch10.call("cancel");
}
function ret(d3_event) {
d3_event.preventDefault();
dispatch10.call("finish");
}
function behavior(selection2) {
context.install(_hover);
context.install(_edit);
_downPointer = null;
keybinding.on("\u232B", backspace).on("\u2326", del).on("\u238B", ret).on("\u21A9", ret).on("space", space).on("\u2325space", space);
selection2.on("mouseenter.draw", mouseenter).on("mouseleave.draw", mouseleave).on(_pointerPrefix + "down.draw", pointerdown).on(_pointerPrefix + "move.draw", pointermove);
select_default2(window).on(_pointerPrefix + "up.draw", pointerup, true).on("pointercancel.draw", pointercancel, true);
select_default2(document).call(keybinding);
return behavior;
}
behavior.off = function(selection2) {
context.ui().sidebar.hover.cancel();
context.uninstall(_hover);
context.uninstall(_edit);
selection2.on("mouseenter.draw", null).on("mouseleave.draw", null).on(_pointerPrefix + "down.draw", null).on(_pointerPrefix + "move.draw", null);
select_default2(window).on(_pointerPrefix + "up.draw", null).on("pointercancel.draw", null);
select_default2(document).call(keybinding.unbind);
};
behavior.hover = function() {
return _hover;
};
return utilRebind(behavior, dispatch10, "on");
}
// modules/behavior/breathe.js
var import_fast_deep_equal2 = __toESM(require_fast_deep_equal());
// node_modules/d3-scale/src/init.js
function initRange(domain2, range3) {
switch (arguments.length) {
case 0:
break;
case 1:
this.range(domain2);
break;
default:
this.range(range3).domain(domain2);
break;
}
return this;
}
// node_modules/d3-scale/src/constant.js
function constants(x) {
return function() {
return x;
};
}
// node_modules/d3-scale/src/number.js
function number2(x) {
return +x;
}
// node_modules/d3-scale/src/continuous.js
var unit = [0, 1];
function identity3(x) {
return x;
}
function normalize(a, b) {
return (b -= a = +a) ? function(x) {
return (x - a) / b;
} : constants(isNaN(b) ? NaN : 0.5);
}
function clamper(a, b) {
var t;
if (a > b)
t = a, a = b, b = t;
return function(x) {
return Math.max(a, Math.min(b, x));
};
}
function bimap(domain2, range3, interpolate) {
var d0 = domain2[0], d1 = domain2[1], r0 = range3[0], r1 = range3[1];
if (d1 < d0)
d0 = normalize(d1, d0), r0 = interpolate(r1, r0);
else
d0 = normalize(d0, d1), r0 = interpolate(r0, r1);
return function(x) {
return r0(d0(x));
};
}
function polymap(domain2, range3, interpolate) {
var j2 = Math.min(domain2.length, range3.length) - 1, d = new Array(j2), r = new Array(j2), i2 = -1;
if (domain2[j2] < domain2[0]) {
domain2 = domain2.slice().reverse();
range3 = range3.slice().reverse();
}
while (++i2 < j2) {
d[i2] = normalize(domain2[i2], domain2[i2 + 1]);
r[i2] = interpolate(range3[i2], range3[i2 + 1]);
}
return function(x) {
var i3 = bisect_default(domain2, x, 1, j2) - 1;
return r[i3](d[i3](x));
};
}
function copy(source, target) {
return target.domain(source.domain()).range(source.range()).interpolate(source.interpolate()).clamp(source.clamp()).unknown(source.unknown());
}
function transformer2() {
var domain2 = unit, range3 = unit, interpolate = value_default, transform2, untransform, unknown, clamp3 = identity3, piecewise, output, input;
function rescale() {
var n2 = Math.min(domain2.length, range3.length);
if (clamp3 !== identity3)
clamp3 = clamper(domain2[0], domain2[n2 - 1]);
piecewise = n2 > 2 ? polymap : bimap;
output = input = null;
return scale;
}
function scale(x) {
return x == null || isNaN(x = +x) ? unknown : (output || (output = piecewise(domain2.map(transform2), range3, interpolate)))(transform2(clamp3(x)));
}
scale.invert = function(y) {
return clamp3(untransform((input || (input = piecewise(range3, domain2.map(transform2), number_default)))(y)));
};
scale.domain = function(_) {
return arguments.length ? (domain2 = Array.from(_, number2), rescale()) : domain2.slice();
};
scale.range = function(_) {
return arguments.length ? (range3 = Array.from(_), rescale()) : range3.slice();
};
scale.rangeRound = function(_) {
return range3 = Array.from(_), interpolate = round_default, rescale();
};
scale.clamp = function(_) {
return arguments.length ? (clamp3 = _ ? true : identity3, rescale()) : clamp3 !== identity3;
};
scale.interpolate = function(_) {
return arguments.length ? (interpolate = _, rescale()) : interpolate;
};
scale.unknown = function(_) {
return arguments.length ? (unknown = _, scale) : unknown;
};
return function(t, u) {
transform2 = t, untransform = u;
return rescale();
};
}
function continuous() {
return transformer2()(identity3, identity3);
}
// node_modules/d3-format/src/formatDecimal.js
function formatDecimal_default(x) {
return Math.abs(x = Math.round(x)) >= 1e21 ? x.toLocaleString("en").replace(/,/g, "") : x.toString(10);
}
function formatDecimalParts(x, p) {
if ((i2 = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0)
return null;
var i2, coefficient = x.slice(0, i2);
return [
coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient,
+x.slice(i2 + 1)
];
}
// node_modules/d3-format/src/exponent.js
function exponent_default(x) {
return x = formatDecimalParts(Math.abs(x)), x ? x[1] : NaN;
}
// node_modules/d3-format/src/formatGroup.js
function formatGroup_default(grouping, thousands) {
return function(value, width) {
var i2 = value.length, t = [], j2 = 0, g = grouping[0], length = 0;
while (i2 > 0 && g > 0) {
if (length + g + 1 > width)
g = Math.max(1, width - length);
t.push(value.substring(i2 -= g, i2 + g));
if ((length += g + 1) > width)
break;
g = grouping[j2 = (j2 + 1) % grouping.length];
}
return t.reverse().join(thousands);
};
}
// node_modules/d3-format/src/formatNumerals.js
function formatNumerals_default(numerals) {
return function(value) {
return value.replace(/[0-9]/g, function(i2) {
return numerals[+i2];
});
};
}
// node_modules/d3-format/src/formatSpecifier.js
var re = /^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;
function formatSpecifier(specifier) {
if (!(match = re.exec(specifier)))
throw new Error("invalid format: " + specifier);
var match;
return new FormatSpecifier({
fill: match[1],
align: match[2],
sign: match[3],
symbol: match[4],
zero: match[5],
width: match[6],
comma: match[7],
precision: match[8] && match[8].slice(1),
trim: match[9],
type: match[10]
});
}
formatSpecifier.prototype = FormatSpecifier.prototype;
function FormatSpecifier(specifier) {
this.fill = specifier.fill === void 0 ? " " : specifier.fill + "";
this.align = specifier.align === void 0 ? ">" : specifier.align + "";
this.sign = specifier.sign === void 0 ? "-" : specifier.sign + "";
this.symbol = specifier.symbol === void 0 ? "" : specifier.symbol + "";
this.zero = !!specifier.zero;
this.width = specifier.width === void 0 ? void 0 : +specifier.width;
this.comma = !!specifier.comma;
this.precision = specifier.precision === void 0 ? void 0 : +specifier.precision;
this.trim = !!specifier.trim;
this.type = specifier.type === void 0 ? "" : specifier.type + "";
}
FormatSpecifier.prototype.toString = function() {
return this.fill + this.align + this.sign + this.symbol + (this.zero ? "0" : "") + (this.width === void 0 ? "" : Math.max(1, this.width | 0)) + (this.comma ? "," : "") + (this.precision === void 0 ? "" : "." + Math.max(0, this.precision | 0)) + (this.trim ? "~" : "") + this.type;
};
// node_modules/d3-format/src/formatTrim.js
function formatTrim_default(s) {
out:
for (var n2 = s.length, i2 = 1, i0 = -1, i1; i2 < n2; ++i2) {
switch (s[i2]) {
case ".":
i0 = i1 = i2;
break;
case "0":
if (i0 === 0)
i0 = i2;
i1 = i2;
break;
default:
if (!+s[i2])
break out;
if (i0 > 0)
i0 = 0;
break;
}
}
return i0 > 0 ? s.slice(0, i0) + s.slice(i1 + 1) : s;
}
// node_modules/d3-format/src/formatPrefixAuto.js
var prefixExponent;
function formatPrefixAuto_default(x, p) {
var d = formatDecimalParts(x, p);
if (!d)
return x + "";
var coefficient = d[0], exponent = d[1], i2 = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1, n2 = coefficient.length;
return i2 === n2 ? coefficient : i2 > n2 ? coefficient + new Array(i2 - n2 + 1).join("0") : i2 > 0 ? coefficient.slice(0, i2) + "." + coefficient.slice(i2) : "0." + new Array(1 - i2).join("0") + formatDecimalParts(x, Math.max(0, p + i2 - 1))[0];
}
// node_modules/d3-format/src/formatRounded.js
function formatRounded_default(x, p) {
var d = formatDecimalParts(x, p);
if (!d)
return x + "";
var coefficient = d[0], exponent = d[1];
return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1) : coefficient + new Array(exponent - coefficient.length + 2).join("0");
}
// node_modules/d3-format/src/formatTypes.js
var formatTypes_default = {
"%": (x, p) => (x * 100).toFixed(p),
"b": (x) => Math.round(x).toString(2),
"c": (x) => x + "",
"d": formatDecimal_default,
"e": (x, p) => x.toExponential(p),
"f": (x, p) => x.toFixed(p),
"g": (x, p) => x.toPrecision(p),
"o": (x) => Math.round(x).toString(8),
"p": (x, p) => formatRounded_default(x * 100, p),
"r": formatRounded_default,
"s": formatPrefixAuto_default,
"X": (x) => Math.round(x).toString(16).toUpperCase(),
"x": (x) => Math.round(x).toString(16)
};
// node_modules/d3-format/src/identity.js
function identity_default3(x) {
return x;
}
// node_modules/d3-format/src/locale.js
var map = Array.prototype.map;
var prefixes = ["y", "z", "a", "f", "p", "n", "\xB5", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y"];
function locale_default(locale2) {
var group = locale2.grouping === void 0 || locale2.thousands === void 0 ? identity_default3 : formatGroup_default(map.call(locale2.grouping, Number), locale2.thousands + ""), currencyPrefix = locale2.currency === void 0 ? "" : locale2.currency[0] + "", currencySuffix = locale2.currency === void 0 ? "" : locale2.currency[1] + "", decimal = locale2.decimal === void 0 ? "." : locale2.decimal + "", numerals = locale2.numerals === void 0 ? identity_default3 : formatNumerals_default(map.call(locale2.numerals, String)), percent = locale2.percent === void 0 ? "%" : locale2.percent + "", minus = locale2.minus === void 0 ? "\u2212" : locale2.minus + "", nan = locale2.nan === void 0 ? "NaN" : locale2.nan + "";
function newFormat(specifier) {
specifier = formatSpecifier(specifier);
var fill = specifier.fill, align = specifier.align, sign2 = specifier.sign, symbol = specifier.symbol, zero3 = specifier.zero, width = specifier.width, comma = specifier.comma, precision2 = specifier.precision, trim = specifier.trim, type3 = specifier.type;
if (type3 === "n")
comma = true, type3 = "g";
else if (!formatTypes_default[type3])
precision2 === void 0 && (precision2 = 12), trim = true, type3 = "g";
if (zero3 || fill === "0" && align === "=")
zero3 = true, fill = "0", align = "=";
var prefix = symbol === "$" ? currencyPrefix : symbol === "#" && /[boxX]/.test(type3) ? "0" + type3.toLowerCase() : "", suffix = symbol === "$" ? currencySuffix : /[%p]/.test(type3) ? percent : "";
var formatType = formatTypes_default[type3], maybeSuffix = /[defgprs%]/.test(type3);
precision2 = precision2 === void 0 ? 6 : /[gprs]/.test(type3) ? Math.max(1, Math.min(21, precision2)) : Math.max(0, Math.min(20, precision2));
function format2(value) {
var valuePrefix = prefix, valueSuffix = suffix, i2, n2, c;
if (type3 === "c") {
valueSuffix = formatType(value) + valueSuffix;
value = "";
} else {
value = +value;
var valueNegative = value < 0 || 1 / value < 0;
value = isNaN(value) ? nan : formatType(Math.abs(value), precision2);
if (trim)
value = formatTrim_default(value);
if (valueNegative && +value === 0 && sign2 !== "+")
valueNegative = false;
valuePrefix = (valueNegative ? sign2 === "(" ? sign2 : minus : sign2 === "-" || sign2 === "(" ? "" : sign2) + valuePrefix;
valueSuffix = (type3 === "s" ? prefixes[8 + prefixExponent / 3] : "") + valueSuffix + (valueNegative && sign2 === "(" ? ")" : "");
if (maybeSuffix) {
i2 = -1, n2 = value.length;
while (++i2 < n2) {
if (c = value.charCodeAt(i2), 48 > c || c > 57) {
valueSuffix = (c === 46 ? decimal + value.slice(i2 + 1) : value.slice(i2)) + valueSuffix;
value = value.slice(0, i2);
break;
}
}
}
}
if (comma && !zero3)
value = group(value, Infinity);
var length = valuePrefix.length + value.length + valueSuffix.length, padding = length < width ? new Array(width - length + 1).join(fill) : "";
if (comma && zero3)
value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = "";
switch (align) {
case "<":
value = valuePrefix + value + valueSuffix + padding;
break;
case "=":
value = valuePrefix + padding + value + valueSuffix;
break;
case "^":
value = padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length);
break;
default:
value = padding + valuePrefix + value + valueSuffix;
break;
}
return numerals(value);
}
format2.toString = function() {
return specifier + "";
};
return format2;
}
function formatPrefix2(specifier, value) {
var f2 = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)), e = Math.max(-8, Math.min(8, Math.floor(exponent_default(value) / 3))) * 3, k = Math.pow(10, -e), prefix = prefixes[8 + e / 3];
return function(value2) {
return f2(k * value2) + prefix;
};
}
return {
format: newFormat,
formatPrefix: formatPrefix2
};
}
// node_modules/d3-format/src/defaultLocale.js
var locale;
var format;
var formatPrefix;
defaultLocale({
thousands: ",",
grouping: [3],
currency: ["$", ""]
});
function defaultLocale(definition) {
locale = locale_default(definition);
format = locale.format;
formatPrefix = locale.formatPrefix;
return locale;
}
// node_modules/d3-format/src/precisionFixed.js
function precisionFixed_default(step) {
return Math.max(0, -exponent_default(Math.abs(step)));
}
// node_modules/d3-format/src/precisionPrefix.js
function precisionPrefix_default(step, value) {
return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent_default(value) / 3))) * 3 - exponent_default(Math.abs(step)));
}
// node_modules/d3-format/src/precisionRound.js
function precisionRound_default(step, max3) {
step = Math.abs(step), max3 = Math.abs(max3) - step;
return Math.max(0, exponent_default(max3) - exponent_default(step)) + 1;
}
// node_modules/d3-scale/src/tickFormat.js
function tickFormat(start2, stop, count, specifier) {
var step = tickStep(start2, stop, count), precision2;
specifier = formatSpecifier(specifier == null ? ",f" : specifier);
switch (specifier.type) {
case "s": {
var value = Math.max(Math.abs(start2), Math.abs(stop));
if (specifier.precision == null && !isNaN(precision2 = precisionPrefix_default(step, value)))
specifier.precision = precision2;
return formatPrefix(specifier, value);
}
case "":
case "e":
case "g":
case "p":
case "r": {
if (specifier.precision == null && !isNaN(precision2 = precisionRound_default(step, Math.max(Math.abs(start2), Math.abs(stop)))))
specifier.precision = precision2 - (specifier.type === "e");
break;
}
case "f":
case "%": {
if (specifier.precision == null && !isNaN(precision2 = precisionFixed_default(step)))
specifier.precision = precision2 - (specifier.type === "%") * 2;
break;
}
}
return format(specifier);
}
// node_modules/d3-scale/src/linear.js
function linearish(scale) {
var domain2 = scale.domain;
scale.ticks = function(count) {
var d = domain2();
return ticks(d[0], d[d.length - 1], count == null ? 10 : count);
};
scale.tickFormat = function(count, specifier) {
var d = domain2();
return tickFormat(d[0], d[d.length - 1], count == null ? 10 : count, specifier);
};
scale.nice = function(count) {
if (count == null)
count = 10;
var d = domain2();
var i0 = 0;
var i1 = d.length - 1;
var start2 = d[i0];
var stop = d[i1];
var prestep;
var step;
var maxIter = 10;
if (stop < start2) {
step = start2, start2 = stop, stop = step;
step = i0, i0 = i1, i1 = step;
}
while (maxIter-- > 0) {
step = tickIncrement(start2, stop, count);
if (step === prestep) {
d[i0] = start2;
d[i1] = stop;
return domain2(d);
} else if (step > 0) {
start2 = Math.floor(start2 / step) * step;
stop = Math.ceil(stop / step) * step;
} else if (step < 0) {
start2 = Math.ceil(start2 * step) / step;
stop = Math.floor(stop * step) / step;
} else {
break;
}
prestep = step;
}
return scale;
};
return scale;
}
function linear3() {
var scale = continuous();
scale.copy = function() {
return copy(scale, linear3());
};
initRange.apply(scale, arguments);
return linearish(scale);
}
// node_modules/d3-scale/src/quantize.js
function quantize() {
var x05 = 0, x12 = 1, n2 = 1, domain2 = [0.5], range3 = [0, 1], unknown;
function scale(x) {
return x != null && x <= x ? range3[bisect_default(domain2, x, 0, n2)] : unknown;
}
function rescale() {
var i2 = -1;
domain2 = new Array(n2);
while (++i2 < n2)
domain2[i2] = ((i2 + 1) * x12 - (i2 - n2) * x05) / (n2 + 1);
return scale;
}
scale.domain = function(_) {
return arguments.length ? ([x05, x12] = _, x05 = +x05, x12 = +x12, rescale()) : [x05, x12];
};
scale.range = function(_) {
return arguments.length ? (n2 = (range3 = Array.from(_)).length - 1, rescale()) : range3.slice();
};
scale.invertExtent = function(y) {
var i2 = range3.indexOf(y);
return i2 < 0 ? [NaN, NaN] : i2 < 1 ? [x05, domain2[0]] : i2 >= n2 ? [domain2[n2 - 1], x12] : [domain2[i2 - 1], domain2[i2]];
};
scale.unknown = function(_) {
return arguments.length ? (unknown = _, scale) : scale;
};
scale.thresholds = function() {
return domain2.slice();
};
scale.copy = function() {
return quantize().domain([x05, x12]).range(range3).unknown(unknown);
};
return initRange.apply(linearish(scale), arguments);
}
// modules/behavior/breathe.js
function behaviorBreathe() {
var duration = 800;
var steps = 4;
var selector = ".selected.shadow, .selected .shadow";
var _selected = select_default2(null);
var _classed = "";
var _params = {};
var _done = false;
var _timer;
function ratchetyInterpolator(a, b, steps2, units) {
a = parseFloat(a);
b = parseFloat(b);
var sample = quantize().domain([0, 1]).range(quantize_default(number_default(a, b), steps2));
return function(t) {
return String(sample(t)) + (units || "");
};
}
function reset(selection2) {
selection2.style("stroke-opacity", null).style("stroke-width", null).style("fill-opacity", null).style("r", null);
}
function setAnimationParams(transition2, fromTo) {
var toFrom = fromTo === "from" ? "to" : "from";
transition2.styleTween("stroke-opacity", function(d) {
return ratchetyInterpolator(_params[d.id][toFrom].opacity, _params[d.id][fromTo].opacity, steps);
}).styleTween("stroke-width", function(d) {
return ratchetyInterpolator(_params[d.id][toFrom].width, _params[d.id][fromTo].width, steps, "px");
}).styleTween("fill-opacity", function(d) {
return ratchetyInterpolator(_params[d.id][toFrom].opacity, _params[d.id][fromTo].opacity, steps);
}).styleTween("r", function(d) {
return ratchetyInterpolator(_params[d.id][toFrom].width, _params[d.id][fromTo].width, steps, "px");
});
}
function calcAnimationParams(selection2) {
selection2.call(reset).each(function(d) {
var s = select_default2(this);
var tag = s.node().tagName;
var p = { "from": {}, "to": {} };
var opacity;
var width;
if (tag === "circle") {
opacity = parseFloat(s.style("fill-opacity") || 0.5);
width = parseFloat(s.style("r") || 15.5);
} else {
opacity = parseFloat(s.style("stroke-opacity") || 0.7);
width = parseFloat(s.style("stroke-width") || 10);
}
p.tag = tag;
p.from.opacity = opacity * 0.6;
p.to.opacity = opacity * 1.25;
p.from.width = width * 0.7;
p.to.width = width * (tag === "circle" ? 1.5 : 1);
_params[d.id] = p;
});
}
function run(surface, fromTo) {
var toFrom = fromTo === "from" ? "to" : "from";
var currSelected = surface.selectAll(selector);
var currClassed = surface.attr("class");
if (_done || currSelected.empty()) {
_selected.call(reset);
_selected = select_default2(null);
return;
}
if (!(0, import_fast_deep_equal2.default)(currSelected.data(), _selected.data()) || currClassed !== _classed) {
_selected.call(reset);
_classed = currClassed;
_selected = currSelected.call(calcAnimationParams);
}
var didCallNextRun = false;
_selected.transition().duration(duration).call(setAnimationParams, fromTo).on("end", function() {
if (!didCallNextRun) {
surface.call(run, toFrom);
didCallNextRun = true;
}
if (!select_default2(this).classed("selected")) {
reset(select_default2(this));
}
});
}
function behavior(surface) {
_done = false;
_timer = timer(function() {
if (surface.selectAll(selector).empty()) {
return false;
}
surface.call(run, "from");
_timer.stop();
return true;
}, 20);
}
behavior.restartIfNeeded = function(surface) {
if (_selected.empty()) {
surface.call(run, "from");
if (_timer) {
_timer.stop();
}
}
};
behavior.off = function() {
_done = true;
if (_timer) {
_timer.stop();
}
_selected.interrupt().call(reset);
};
return behavior;
}
// modules/behavior/operation.js
function behaviorOperation(context) {
var _operation;
function keypress(d3_event) {
if (!context.map().withinEditableZoom())
return;
if (_operation.availableForKeypress && !_operation.availableForKeypress())
return;
d3_event.preventDefault();
var disabled = _operation.disabled();
if (disabled) {
context.ui().flash.duration(4e3).iconName("#iD-operation-" + _operation.id).iconClass("operation disabled").label(_operation.tooltip)();
} else {
context.ui().flash.duration(2e3).iconName("#iD-operation-" + _operation.id).iconClass("operation").label(_operation.annotation() || _operation.title)();
if (_operation.point)
_operation.point(null);
_operation();
}
}
function behavior() {
if (_operation && _operation.available()) {
context.keybinding().on(_operation.keys, keypress);
}
return behavior;
}
behavior.off = function() {
context.keybinding().off(_operation.keys);
};
behavior.which = function(_) {
if (!arguments.length)
return _operation;
_operation = _;
return behavior;
};
return behavior;
}
// modules/operations/circularize.js
function operationCircularize(context, selectedIDs) {
var _extent;
var _actions = selectedIDs.map(getAction).filter(Boolean);
var _amount = _actions.length === 1 ? "single" : "multiple";
var _coords = utilGetAllNodes(selectedIDs, context.graph()).map(function(n2) {
return n2.loc;
});
function getAction(entityID) {
var entity = context.entity(entityID);
if (entity.type !== "way" || new Set(entity.nodes).size <= 1)
return null;
if (!_extent) {
_extent = entity.extent(context.graph());
} else {
_extent = _extent.extend(entity.extent(context.graph()));
}
return actionCircularize(entityID, context.projection);
}
var operation = function() {
if (!_actions.length)
return;
var combinedAction = function(graph, t) {
_actions.forEach(function(action) {
if (!action.disabled(graph)) {
graph = action(graph, t);
}
});
return graph;
};
combinedAction.transitionable = true;
context.perform(combinedAction, operation.annotation());
window.setTimeout(function() {
context.validator().validate();
}, 300);
};
operation.available = function() {
return _actions.length && selectedIDs.length === _actions.length;
};
operation.disabled = function() {
if (!_actions.length)
return "";
var actionDisableds = _actions.map(function(action) {
return action.disabled(context.graph());
}).filter(Boolean);
if (actionDisableds.length === _actions.length) {
if (new Set(actionDisableds).size > 1) {
return "multiple_blockers";
}
return actionDisableds[0];
} else if (_extent.percentContainedIn(context.map().extent()) < 0.8) {
return "too_large";
} else if (someMissing()) {
return "not_downloaded";
} else if (selectedIDs.some(context.hasHiddenConnections)) {
return "connected_to_hidden";
}
return false;
function someMissing() {
if (context.inIntro())
return false;
var osm = context.connection();
if (osm) {
var missing = _coords.filter(function(loc) {
return !osm.isDataLoaded(loc);
});
if (missing.length) {
missing.forEach(function(loc) {
context.loadTileAtLoc(loc);
});
return true;
}
}
return false;
}
};
operation.tooltip = function() {
var disable = operation.disabled();
return disable ? _t("operations.circularize." + disable + "." + _amount) : _t("operations.circularize.description." + _amount);
};
operation.annotation = function() {
return _t("operations.circularize.annotation.feature", { n: _actions.length });
};
operation.id = "circularize";
operation.keys = [_t("operations.circularize.key")];
operation.title = _t("operations.circularize.title");
operation.behavior = behaviorOperation(context).which(operation);
return operation;
}
// modules/ui/cmd.js
var uiCmd = function(code) {
var detected = utilDetect();
if (detected.os === "mac") {
return code;
}
if (detected.os === "win") {
if (code === "\u2318\u21E7Z")
return "Ctrl+Y";
}
var result = "", replacements = {
"\u2318": "Ctrl",
"\u21E7": "Shift",
"\u2325": "Alt",
"\u232B": "Backspace",
"\u2326": "Delete"
};
for (var i2 = 0; i2 < code.length; i2++) {
if (code[i2] in replacements) {
result += replacements[code[i2]] + (i2 < code.length - 1 ? "+" : "");
} else {
result += code[i2];
}
}
return result;
};
uiCmd.display = function(code) {
if (code.length !== 1)
return code;
var detected = utilDetect();
var mac = detected.os === "mac";
var replacements = {
"\u2318": mac ? "\u2318 " + _t("shortcuts.key.cmd") : _t("shortcuts.key.ctrl"),
"\u21E7": mac ? "\u21E7 " + _t("shortcuts.key.shift") : _t("shortcuts.key.shift"),
"\u2325": mac ? "\u2325 " + _t("shortcuts.key.option") : _t("shortcuts.key.alt"),
"\u2303": mac ? "\u2303 " + _t("shortcuts.key.ctrl") : _t("shortcuts.key.ctrl"),
"\u232B": mac ? "\u232B " + _t("shortcuts.key.delete") : _t("shortcuts.key.backspace"),
"\u2326": mac ? "\u2326 " + _t("shortcuts.key.del") : _t("shortcuts.key.del"),
"\u2196": mac ? "\u2196 " + _t("shortcuts.key.pgup") : _t("shortcuts.key.pgup"),
"\u2198": mac ? "\u2198 " + _t("shortcuts.key.pgdn") : _t("shortcuts.key.pgdn"),
"\u21DE": mac ? "\u21DE " + _t("shortcuts.key.home") : _t("shortcuts.key.home"),
"\u21DF": mac ? "\u21DF " + _t("shortcuts.key.end") : _t("shortcuts.key.end"),
"\u21B5": mac ? "\u23CE " + _t("shortcuts.key.return") : _t("shortcuts.key.enter"),
"\u238B": mac ? "\u238B " + _t("shortcuts.key.esc") : _t("shortcuts.key.esc"),
"\u2630": mac ? "\u2630 " + _t("shortcuts.key.menu") : _t("shortcuts.key.menu")
};
return replacements[code] || code;
};
// modules/operations/delete.js
function operationDelete(context, selectedIDs) {
var multi = selectedIDs.length === 1 ? "single" : "multiple";
var action = actionDeleteMultiple(selectedIDs);
var nodes = utilGetAllNodes(selectedIDs, context.graph());
var coords = nodes.map(function(n2) {
return n2.loc;
});
var extent = utilTotalExtent(selectedIDs, context.graph());
var operation = function() {
var nextSelectedID;
var nextSelectedLoc;
if (selectedIDs.length === 1) {
var id2 = selectedIDs[0];
var entity = context.entity(id2);
var geometry = entity.geometry(context.graph());
var parents = context.graph().parentWays(entity);
var parent = parents[0];
if (geometry === "vertex") {
var nodes2 = parent.nodes;
var i2 = nodes2.indexOf(id2);
if (i2 === 0) {
i2++;
} else if (i2 === nodes2.length - 1) {
i2--;
} else {
var a = geoSphericalDistance(entity.loc, context.entity(nodes2[i2 - 1]).loc);
var b = geoSphericalDistance(entity.loc, context.entity(nodes2[i2 + 1]).loc);
i2 = a < b ? i2 - 1 : i2 + 1;
}
nextSelectedID = nodes2[i2];
nextSelectedLoc = context.entity(nextSelectedID).loc;
}
}
context.perform(action, operation.annotation());
context.validator().validate();
if (nextSelectedID && nextSelectedLoc) {
if (context.hasEntity(nextSelectedID)) {
context.enter(modeSelect(context, [nextSelectedID]).follow(true));
} else {
context.map().centerEase(nextSelectedLoc);
context.enter(modeBrowse(context));
}
} else {
context.enter(modeBrowse(context));
}
};
operation.available = function() {
return true;
};
operation.disabled = function() {
if (extent.percentContainedIn(context.map().extent()) < 0.8) {
return "too_large";
} else if (someMissing()) {
return "not_downloaded";
} else if (selectedIDs.some(context.hasHiddenConnections)) {
return "connected_to_hidden";
} else if (selectedIDs.some(protectedMember)) {
return "part_of_relation";
} else if (selectedIDs.some(incompleteRelation)) {
return "incomplete_relation";
} else if (selectedIDs.some(hasWikidataTag)) {
return "has_wikidata_tag";
}
return false;
function someMissing() {
if (context.inIntro())
return false;
var osm = context.connection();
if (osm) {
var missing = coords.filter(function(loc) {
return !osm.isDataLoaded(loc);
});
if (missing.length) {
missing.forEach(function(loc) {
context.loadTileAtLoc(loc);
});
return true;
}
}
return false;
}
function hasWikidataTag(id2) {
var entity = context.entity(id2);
return entity.tags.wikidata && entity.tags.wikidata.trim().length > 0;
}
function incompleteRelation(id2) {
var entity = context.entity(id2);
return entity.type === "relation" && !entity.isComplete(context.graph());
}
function protectedMember(id2) {
var entity = context.entity(id2);
if (entity.type !== "way")
return false;
var parents = context.graph().parentRelations(entity);
for (var i2 = 0; i2 < parents.length; i2++) {
var parent = parents[i2];
var type3 = parent.tags.type;
var role = parent.memberById(id2).role || "outer";
if (type3 === "route" || type3 === "boundary" || type3 === "multipolygon" && role === "outer") {
return true;
}
}
return false;
}
};
operation.tooltip = function() {
var disable = operation.disabled();
return disable ? _t("operations.delete." + disable + "." + multi) : _t("operations.delete.description." + multi);
};
operation.annotation = function() {
return selectedIDs.length === 1 ? _t("operations.delete.annotation." + context.graph().geometry(selectedIDs[0])) : _t("operations.delete.annotation.feature", { n: selectedIDs.length });
};
operation.id = "delete";
operation.keys = [uiCmd("\u2318\u232B"), uiCmd("\u2318\u2326"), uiCmd("\u2326")];
operation.title = _t("operations.delete.title");
operation.behavior = behaviorOperation(context).which(operation);
return operation;
}
// modules/operations/orthogonalize.js
function operationOrthogonalize(context, selectedIDs) {
var _extent;
var _type;
var _actions = selectedIDs.map(chooseAction).filter(Boolean);
var _amount = _actions.length === 1 ? "single" : "multiple";
var _coords = utilGetAllNodes(selectedIDs, context.graph()).map(function(n2) {
return n2.loc;
});
function chooseAction(entityID) {
var entity = context.entity(entityID);
var geometry = entity.geometry(context.graph());
if (!_extent) {
_extent = entity.extent(context.graph());
} else {
_extent = _extent.extend(entity.extent(context.graph()));
}
if (entity.type === "way" && new Set(entity.nodes).size > 2) {
if (_type && _type !== "feature")
return null;
_type = "feature";
return actionOrthogonalize(entityID, context.projection);
} else if (geometry === "vertex") {
if (_type && _type !== "corner")
return null;
_type = "corner";
var graph = context.graph();
var parents = graph.parentWays(entity);
if (parents.length === 1) {
var way = parents[0];
if (way.nodes.indexOf(entityID) !== -1) {
return actionOrthogonalize(way.id, context.projection, entityID);
}
}
}
return null;
}
var operation = function() {
if (!_actions.length)
return;
var combinedAction = function(graph, t) {
_actions.forEach(function(action) {
if (!action.disabled(graph)) {
graph = action(graph, t);
}
});
return graph;
};
combinedAction.transitionable = true;
context.perform(combinedAction, operation.annotation());
window.setTimeout(function() {
context.validator().validate();
}, 300);
};
operation.available = function() {
return _actions.length && selectedIDs.length === _actions.length;
};
operation.disabled = function() {
if (!_actions.length)
return "";
var actionDisableds = _actions.map(function(action) {
return action.disabled(context.graph());
}).filter(Boolean);
if (actionDisableds.length === _actions.length) {
if (new Set(actionDisableds).size > 1) {
return "multiple_blockers";
}
return actionDisableds[0];
} else if (_extent && _extent.percentContainedIn(context.map().extent()) < 0.8) {
return "too_large";
} else if (someMissing()) {
return "not_downloaded";
} else if (selectedIDs.some(context.hasHiddenConnections)) {
return "connected_to_hidden";
}
return false;
function someMissing() {
if (context.inIntro())
return false;
var osm = context.connection();
if (osm) {
var missing = _coords.filter(function(loc) {
return !osm.isDataLoaded(loc);
});
if (missing.length) {
missing.forEach(function(loc) {
context.loadTileAtLoc(loc);
});
return true;
}
}
return false;
}
};
operation.tooltip = function() {
var disable = operation.disabled();
return disable ? _t("operations.orthogonalize." + disable + "." + _amount) : _t("operations.orthogonalize.description." + _type + "." + _amount);
};
operation.annotation = function() {
return _t("operations.orthogonalize.annotation." + _type, { n: _actions.length });
};
operation.id = "orthogonalize";
operation.keys = [_t("operations.orthogonalize.key")];
operation.title = _t("operations.orthogonalize.title");
operation.behavior = behaviorOperation(context).which(operation);
return operation;
}
// modules/operations/reflect.js
function operationReflectShort(context, selectedIDs) {
return operationReflect(context, selectedIDs, "short");
}
function operationReflectLong(context, selectedIDs) {
return operationReflect(context, selectedIDs, "long");
}
function operationReflect(context, selectedIDs, axis) {
axis = axis || "long";
var multi = selectedIDs.length === 1 ? "single" : "multiple";
var nodes = utilGetAllNodes(selectedIDs, context.graph());
var coords = nodes.map(function(n2) {
return n2.loc;
});
var extent = utilTotalExtent(selectedIDs, context.graph());
var operation = function() {
var action = actionReflect(selectedIDs, context.projection).useLongAxis(Boolean(axis === "long"));
context.perform(action, operation.annotation());
window.setTimeout(function() {
context.validator().validate();
}, 300);
};
operation.available = function() {
return nodes.length >= 3;
};
operation.disabled = function() {
if (extent.percentContainedIn(context.map().extent()) < 0.8) {
return "too_large";
} else if (someMissing()) {
return "not_downloaded";
} else if (selectedIDs.some(context.hasHiddenConnections)) {
return "connected_to_hidden";
} else if (selectedIDs.some(incompleteRelation)) {
return "incomplete_relation";
}
return false;
function someMissing() {
if (context.inIntro())
return false;
var osm = context.connection();
if (osm) {
var missing = coords.filter(function(loc) {
return !osm.isDataLoaded(loc);
});
if (missing.length) {
missing.forEach(function(loc) {
context.loadTileAtLoc(loc);
});
return true;
}
}
return false;
}
function incompleteRelation(id2) {
var entity = context.entity(id2);
return entity.type === "relation" && !entity.isComplete(context.graph());
}
};
operation.tooltip = function() {
var disable = operation.disabled();
return disable ? _t("operations.reflect." + disable + "." + multi) : _t("operations.reflect.description." + axis + "." + multi);
};
operation.annotation = function() {
return _t("operations.reflect.annotation." + axis + ".feature", { n: selectedIDs.length });
};
operation.id = "reflect-" + axis;
operation.keys = [_t("operations.reflect.key." + axis)];
operation.title = _t("operations.reflect.title." + axis);
operation.behavior = behaviorOperation(context).which(operation);
return operation;
}
// modules/operations/move.js
function operationMove(context, selectedIDs) {
var multi = selectedIDs.length === 1 ? "single" : "multiple";
var nodes = utilGetAllNodes(selectedIDs, context.graph());
var coords = nodes.map(function(n2) {
return n2.loc;
});
var extent = utilTotalExtent(selectedIDs, context.graph());
var operation = function() {
context.enter(modeMove(context, selectedIDs));
};
operation.available = function() {
return selectedIDs.length > 0;
};
operation.disabled = function() {
if (extent.percentContainedIn(context.map().extent()) < 0.8) {
return "too_large";
} else if (someMissing()) {
return "not_downloaded";
} else if (selectedIDs.some(context.hasHiddenConnections)) {
return "connected_to_hidden";
} else if (selectedIDs.some(incompleteRelation)) {
return "incomplete_relation";
}
return false;
function someMissing() {
if (context.inIntro())
return false;
var osm = context.connection();
if (osm) {
var missing = coords.filter(function(loc) {
return !osm.isDataLoaded(loc);
});
if (missing.length) {
missing.forEach(function(loc) {
context.loadTileAtLoc(loc);
});
return true;
}
}
return false;
}
function incompleteRelation(id2) {
var entity = context.entity(id2);
return entity.type === "relation" && !entity.isComplete(context.graph());
}
};
operation.tooltip = function() {
var disable = operation.disabled();
return disable ? _t("operations.move." + disable + "." + multi) : _t("operations.move.description." + multi);
};
operation.annotation = function() {
return selectedIDs.length === 1 ? _t("operations.move.annotation." + context.graph().geometry(selectedIDs[0])) : _t("operations.move.annotation.feature", { n: selectedIDs.length });
};
operation.id = "move";
operation.keys = [_t("operations.move.key")];
operation.title = _t("operations.move.title");
operation.behavior = behaviorOperation(context).which(operation);
operation.mouseOnly = true;
return operation;
}
// modules/modes/rotate.js
function modeRotate(context, entityIDs) {
var _tolerancePx = 4;
var mode = {
id: "rotate",
button: "browse"
};
var keybinding = utilKeybinding("rotate");
var behaviors = [
behaviorEdit(context),
operationCircularize(context, entityIDs).behavior,
operationDelete(context, entityIDs).behavior,
operationMove(context, entityIDs).behavior,
operationOrthogonalize(context, entityIDs).behavior,
operationReflectLong(context, entityIDs).behavior,
operationReflectShort(context, entityIDs).behavior
];
var annotation = entityIDs.length === 1 ? _t("operations.rotate.annotation." + context.graph().geometry(entityIDs[0])) : _t("operations.rotate.annotation.feature", { n: entityIDs.length });
var _prevGraph;
var _prevAngle;
var _prevTransform;
var _pivot;
var _pointerPrefix = "PointerEvent" in window ? "pointer" : "mouse";
function doRotate(d3_event) {
var fn;
if (context.graph() !== _prevGraph) {
fn = context.perform;
} else {
fn = context.replace;
}
var projection2 = context.projection;
var currTransform = projection2.transform();
if (!_prevTransform || currTransform.k !== _prevTransform.k || currTransform.x !== _prevTransform.x || currTransform.y !== _prevTransform.y) {
var nodes = utilGetAllNodes(entityIDs, context.graph());
var points = nodes.map(function(n2) {
return projection2(n2.loc);
});
_pivot = getPivot(points);
_prevAngle = void 0;
}
var currMouse = context.map().mouse(d3_event);
var currAngle = Math.atan2(currMouse[1] - _pivot[1], currMouse[0] - _pivot[0]);
if (typeof _prevAngle === "undefined")
_prevAngle = currAngle;
var delta = currAngle - _prevAngle;
fn(actionRotate(entityIDs, _pivot, delta, projection2));
_prevTransform = currTransform;
_prevAngle = currAngle;
_prevGraph = context.graph();
}
function getPivot(points) {
var _pivot2;
if (points.length === 1) {
_pivot2 = points[0];
} else if (points.length === 2) {
_pivot2 = geoVecInterp(points[0], points[1], 0.5);
} else {
var polygonHull = hull_default(points);
if (polygonHull.length === 2) {
_pivot2 = geoVecInterp(points[0], points[1], 0.5);
} else {
_pivot2 = centroid_default2(hull_default(points));
}
}
return _pivot2;
}
function finish(d3_event) {
d3_event.stopPropagation();
context.replace(actionNoop(), annotation);
context.enter(modeSelect(context, entityIDs));
}
function cancel() {
if (_prevGraph)
context.pop();
context.enter(modeSelect(context, entityIDs));
}
function undone() {
context.enter(modeBrowse(context));
}
mode.enter = function() {
_prevGraph = null;
context.features().forceVisible(entityIDs);
behaviors.forEach(context.install);
var downEvent;
context.surface().on(_pointerPrefix + "down.modeRotate", function(d3_event) {
downEvent = d3_event;
});
select_default2(window).on(_pointerPrefix + "move.modeRotate", doRotate, true).on(_pointerPrefix + "up.modeRotate", function(d3_event) {
if (!downEvent)
return;
var mapNode = context.container().select(".main-map").node();
var pointGetter = utilFastMouse(mapNode);
var p1 = pointGetter(downEvent);
var p2 = pointGetter(d3_event);
var dist = geoVecLength(p1, p2);
if (dist <= _tolerancePx)
finish(d3_event);
downEvent = null;
}, true);
context.history().on("undone.modeRotate", undone);
keybinding.on("\u238B", cancel).on("\u21A9", finish);
select_default2(document).call(keybinding);
};
mode.exit = function() {
behaviors.forEach(context.uninstall);
context.surface().on(_pointerPrefix + "down.modeRotate", null);
select_default2(window).on(_pointerPrefix + "move.modeRotate", null, true).on(_pointerPrefix + "up.modeRotate", null, true);
context.history().on("undone.modeRotate", null);
select_default2(document).call(keybinding.unbind);
context.features().forceVisible([]);
};
mode.selectedIDs = function() {
if (!arguments.length)
return entityIDs;
return mode;
};
return mode;
}
// modules/operations/rotate.js
function operationRotate(context, selectedIDs) {
var multi = selectedIDs.length === 1 ? "single" : "multiple";
var nodes = utilGetAllNodes(selectedIDs, context.graph());
var coords = nodes.map(function(n2) {
return n2.loc;
});
var extent = utilTotalExtent(selectedIDs, context.graph());
var operation = function() {
context.enter(modeRotate(context, selectedIDs));
};
operation.available = function() {
return nodes.length >= 2;
};
operation.disabled = function() {
if (extent.percentContainedIn(context.map().extent()) < 0.8) {
return "too_large";
} else if (someMissing()) {
return "not_downloaded";
} else if (selectedIDs.some(context.hasHiddenConnections)) {
return "connected_to_hidden";
} else if (selectedIDs.some(incompleteRelation)) {
return "incomplete_relation";
}
return false;
function someMissing() {
if (context.inIntro())
return false;
var osm = context.connection();
if (osm) {
var missing = coords.filter(function(loc) {
return !osm.isDataLoaded(loc);
});
if (missing.length) {
missing.forEach(function(loc) {
context.loadTileAtLoc(loc);
});
return true;
}
}
return false;
}
function incompleteRelation(id2) {
var entity = context.entity(id2);
return entity.type === "relation" && !entity.isComplete(context.graph());
}
};
operation.tooltip = function() {
var disable = operation.disabled();
return disable ? _t("operations.rotate." + disable + "." + multi) : _t("operations.rotate.description." + multi);
};
operation.annotation = function() {
return selectedIDs.length === 1 ? _t("operations.rotate.annotation." + context.graph().geometry(selectedIDs[0])) : _t("operations.rotate.annotation.feature", { n: selectedIDs.length });
};
operation.id = "rotate";
operation.keys = [_t("operations.rotate.key")];
operation.title = _t("operations.rotate.title");
operation.behavior = behaviorOperation(context).which(operation);
operation.mouseOnly = true;
return operation;
}
// modules/modes/move.js
function modeMove(context, entityIDs, baseGraph) {
var _tolerancePx = 4;
var mode = {
id: "move",
button: "browse"
};
var keybinding = utilKeybinding("move");
var behaviors = [
behaviorEdit(context),
operationCircularize(context, entityIDs).behavior,
operationDelete(context, entityIDs).behavior,
operationOrthogonalize(context, entityIDs).behavior,
operationReflectLong(context, entityIDs).behavior,
operationReflectShort(context, entityIDs).behavior,
operationRotate(context, entityIDs).behavior
];
var annotation = entityIDs.length === 1 ? _t("operations.move.annotation." + context.graph().geometry(entityIDs[0])) : _t("operations.move.annotation.feature", { n: entityIDs.length });
var _prevGraph;
var _cache4;
var _origin;
var _nudgeInterval;
var _pointerPrefix = "PointerEvent" in window ? "pointer" : "mouse";
function doMove(nudge) {
nudge = nudge || [0, 0];
var fn;
if (_prevGraph !== context.graph()) {
_cache4 = {};
_origin = context.map().mouseCoordinates();
fn = context.perform;
} else {
fn = context.overwrite;
}
var currMouse = context.map().mouse();
var origMouse = context.projection(_origin);
var delta = geoVecSubtract(geoVecSubtract(currMouse, origMouse), nudge);
fn(actionMove(entityIDs, delta, context.projection, _cache4));
_prevGraph = context.graph();
}
function startNudge(nudge) {
if (_nudgeInterval)
window.clearInterval(_nudgeInterval);
_nudgeInterval = window.setInterval(function() {
context.map().pan(nudge);
doMove(nudge);
}, 50);
}
function stopNudge() {
if (_nudgeInterval) {
window.clearInterval(_nudgeInterval);
_nudgeInterval = null;
}
}
function move() {
doMove();
var nudge = geoViewportEdge(context.map().mouse(), context.map().dimensions());
if (nudge) {
startNudge(nudge);
} else {
stopNudge();
}
}
function finish(d3_event) {
d3_event.stopPropagation();
context.replace(actionNoop(), annotation);
context.enter(modeSelect(context, entityIDs));
stopNudge();
}
function cancel() {
if (baseGraph) {
while (context.graph() !== baseGraph)
context.pop();
context.enter(modeBrowse(context));
} else {
if (_prevGraph)
context.pop();
context.enter(modeSelect(context, entityIDs));
}
stopNudge();
}
function undone() {
context.enter(modeBrowse(context));
}
mode.enter = function() {
_origin = context.map().mouseCoordinates();
_prevGraph = null;
_cache4 = {};
context.features().forceVisible(entityIDs);
behaviors.forEach(context.install);
var downEvent;
context.surface().on(_pointerPrefix + "down.modeMove", function(d3_event) {
downEvent = d3_event;
});
select_default2(window).on(_pointerPrefix + "move.modeMove", move, true).on(_pointerPrefix + "up.modeMove", function(d3_event) {
if (!downEvent)
return;
var mapNode = context.container().select(".main-map").node();
var pointGetter = utilFastMouse(mapNode);
var p1 = pointGetter(downEvent);
var p2 = pointGetter(d3_event);
var dist = geoVecLength(p1, p2);
if (dist <= _tolerancePx)
finish(d3_event);
downEvent = null;
}, true);
context.history().on("undone.modeMove", undone);
keybinding.on("\u238B", cancel).on("\u21A9", finish);
select_default2(document).call(keybinding);
};
mode.exit = function() {
stopNudge();
behaviors.forEach(function(behavior) {
context.uninstall(behavior);
});
context.surface().on(_pointerPrefix + "down.modeMove", null);
select_default2(window).on(_pointerPrefix + "move.modeMove", null, true).on(_pointerPrefix + "up.modeMove", null, true);
context.history().on("undone.modeMove", null);
select_default2(document).call(keybinding.unbind);
context.features().forceVisible([]);
};
mode.selectedIDs = function() {
if (!arguments.length)
return entityIDs;
return mode;
};
return mode;
}
// modules/behavior/paste.js
function behaviorPaste(context) {
function doPaste(d3_event) {
if (!context.map().withinEditableZoom())
return;
d3_event.preventDefault();
var baseGraph = context.graph();
var mouse = context.map().mouse();
var projection2 = context.projection;
var viewport = geoExtent(projection2.clipExtent()).polygon();
if (!geoPointInPolygon(mouse, viewport))
return;
var oldIDs = context.copyIDs();
if (!oldIDs.length)
return;
var extent = geoExtent();
var oldGraph = context.copyGraph();
var newIDs = [];
var action = actionCopyEntities(oldIDs, oldGraph);
context.perform(action);
var copies = action.copies();
var originals = /* @__PURE__ */ new Set();
Object.values(copies).forEach(function(entity) {
originals.add(entity.id);
});
for (var id2 in copies) {
var oldEntity = oldGraph.entity(id2);
var newEntity = copies[id2];
extent._extend(oldEntity.extent(oldGraph));
var parents = context.graph().parentWays(newEntity);
var parentCopied = parents.some(function(parent) {
return originals.has(parent.id);
});
if (!parentCopied) {
newIDs.push(newEntity.id);
}
}
var copyPoint = context.copyLonLat() && projection2(context.copyLonLat()) || projection2(extent.center());
var delta = geoVecSubtract(mouse, copyPoint);
context.perform(actionMove(newIDs, delta, projection2));
context.enter(modeMove(context, newIDs, baseGraph));
}
function behavior() {
context.keybinding().on(uiCmd("\u2318V"), doPaste);
return behavior;
}
behavior.off = function() {
context.keybinding().off(uiCmd("\u2318V"));
};
return behavior;
}
// modules/behavior/drag.js
function behaviorDrag() {
var dispatch10 = dispatch_default("start", "move", "end");
var _tolerancePx = 1;
var _penTolerancePx = 4;
var _origin = null;
var _selector = "";
var _targetNode;
var _targetEntity;
var _surface;
var _pointerId;
var _pointerPrefix = "PointerEvent" in window ? "pointer" : "mouse";
var d3_event_userSelectProperty = utilPrefixCSSProperty("UserSelect");
var d3_event_userSelectSuppress = function() {
var selection2 = selection_default();
var select = selection2.style(d3_event_userSelectProperty);
selection2.style(d3_event_userSelectProperty, "none");
return function() {
selection2.style(d3_event_userSelectProperty, select);
};
};
function pointerdown(d3_event) {
if (_pointerId)
return;
_pointerId = d3_event.pointerId || "mouse";
_targetNode = this;
var pointerLocGetter = utilFastMouse(_surface || _targetNode.parentNode);
var offset;
var startOrigin = pointerLocGetter(d3_event);
var started = false;
var selectEnable = d3_event_userSelectSuppress();
select_default2(window).on(_pointerPrefix + "move.drag", pointermove).on(_pointerPrefix + "up.drag pointercancel.drag", pointerup, true);
if (_origin) {
offset = _origin.call(_targetNode, _targetEntity);
offset = [offset[0] - startOrigin[0], offset[1] - startOrigin[1]];
} else {
offset = [0, 0];
}
d3_event.stopPropagation();
function pointermove(d3_event2) {
if (_pointerId !== (d3_event2.pointerId || "mouse"))
return;
var p = pointerLocGetter(d3_event2);
if (!started) {
var dist = geoVecLength(startOrigin, p);
var tolerance = d3_event2.pointerType === "pen" ? _penTolerancePx : _tolerancePx;
if (dist < tolerance)
return;
started = true;
dispatch10.call("start", this, d3_event2, _targetEntity);
} else {
startOrigin = p;
d3_event2.stopPropagation();
d3_event2.preventDefault();
var dx = p[0] - startOrigin[0];
var dy = p[1] - startOrigin[1];
dispatch10.call("move", this, d3_event2, _targetEntity, [p[0] + offset[0], p[1] + offset[1]], [dx, dy]);
}
}
function pointerup(d3_event2) {
if (_pointerId !== (d3_event2.pointerId || "mouse"))
return;
_pointerId = null;
if (started) {
dispatch10.call("end", this, d3_event2, _targetEntity);
d3_event2.preventDefault();
}
select_default2(window).on(_pointerPrefix + "move.drag", null).on(_pointerPrefix + "up.drag pointercancel.drag", null);
selectEnable();
}
}
function behavior(selection2) {
var matchesSelector = utilPrefixDOMProperty("matchesSelector");
var delegate = pointerdown;
if (_selector) {
delegate = function(d3_event) {
var root3 = this;
var target = d3_event.target;
for (; target && target !== root3; target = target.parentNode) {
var datum2 = target.__data__;
_targetEntity = datum2 instanceof osmNote ? datum2 : datum2 && datum2.properties && datum2.properties.entity;
if (_targetEntity && target[matchesSelector](_selector)) {
return pointerdown.call(target, d3_event);
}
}
};
}
selection2.on(_pointerPrefix + "down.drag" + _selector, delegate);
}
behavior.off = function(selection2) {
selection2.on(_pointerPrefix + "down.drag" + _selector, null);
};
behavior.selector = function(_) {
if (!arguments.length)
return _selector;
_selector = _;
return behavior;
};
behavior.origin = function(_) {
if (!arguments.length)
return _origin;
_origin = _;
return behavior;
};
behavior.cancel = function() {
select_default2(window).on(_pointerPrefix + "move.drag", null).on(_pointerPrefix + "up.drag pointercancel.drag", null);
return behavior;
};
behavior.targetNode = function(_) {
if (!arguments.length)
return _targetNode;
_targetNode = _;
return behavior;
};
behavior.targetEntity = function(_) {
if (!arguments.length)
return _targetEntity;
_targetEntity = _;
return behavior;
};
behavior.surface = function(_) {
if (!arguments.length)
return _surface;
_surface = _;
return behavior;
};
return utilRebind(behavior, dispatch10, "on");
}
// modules/modes/drag_node.js
function modeDragNode(context) {
var mode = {
id: "drag-node",
button: "browse"
};
var hover = behaviorHover(context).altDisables(true).on("hover", context.ui().sidebar.hover);
var edit2 = behaviorEdit(context);
var _nudgeInterval;
var _restoreSelectedIDs = [];
var _wasMidpoint = false;
var _isCancelled = false;
var _activeEntity;
var _startLoc;
var _lastLoc;
function startNudge(d3_event, entity, nudge) {
if (_nudgeInterval)
window.clearInterval(_nudgeInterval);
_nudgeInterval = window.setInterval(function() {
context.map().pan(nudge);
doMove(d3_event, entity, nudge);
}, 50);
}
function stopNudge() {
if (_nudgeInterval) {
window.clearInterval(_nudgeInterval);
_nudgeInterval = null;
}
}
function moveAnnotation(entity) {
return _t("operations.move.annotation." + entity.geometry(context.graph()));
}
function connectAnnotation(nodeEntity, targetEntity) {
var nodeGeometry = nodeEntity.geometry(context.graph());
var targetGeometry = targetEntity.geometry(context.graph());
if (nodeGeometry === "vertex" && targetGeometry === "vertex") {
var nodeParentWayIDs = context.graph().parentWays(nodeEntity);
var targetParentWayIDs = context.graph().parentWays(targetEntity);
var sharedParentWays = utilArrayIntersection(nodeParentWayIDs, targetParentWayIDs);
if (sharedParentWays.length !== 0) {
if (sharedParentWays[0].areAdjacent(nodeEntity.id, targetEntity.id)) {
return _t("operations.connect.annotation.from_vertex.to_adjacent_vertex");
}
return _t("operations.connect.annotation.from_vertex.to_sibling_vertex");
}
}
return _t("operations.connect.annotation.from_" + nodeGeometry + ".to_" + targetGeometry);
}
function shouldSnapToNode(target) {
if (!_activeEntity)
return false;
return _activeEntity.geometry(context.graph()) !== "vertex" || (target.geometry(context.graph()) === "vertex" || _mainPresetIndex.allowsVertex(target, context.graph()));
}
function origin(entity) {
return context.projection(entity.loc);
}
function keydown(d3_event) {
if (d3_event.keyCode === utilKeybinding.modifierCodes.alt) {
if (context.surface().classed("nope")) {
context.surface().classed("nope-suppressed", true);
}
context.surface().classed("nope", false).classed("nope-disabled", true);
}
}
function keyup(d3_event) {
if (d3_event.keyCode === utilKeybinding.modifierCodes.alt) {
if (context.surface().classed("nope-suppressed")) {
context.surface().classed("nope", true);
}
context.surface().classed("nope-suppressed", false).classed("nope-disabled", false);
}
}
function start2(d3_event, entity) {
_wasMidpoint = entity.type === "midpoint";
var hasHidden = context.features().hasHiddenConnections(entity, context.graph());
_isCancelled = !context.editable() || d3_event.shiftKey || hasHidden;
if (_isCancelled) {
if (hasHidden) {
context.ui().flash.duration(4e3).iconName("#iD-icon-no").label(_t("modes.drag_node.connected_to_hidden"))();
}
return drag.cancel();
}
if (_wasMidpoint) {
var midpoint = entity;
entity = osmNode();
context.perform(actionAddMidpoint(midpoint, entity));
entity = context.entity(entity.id);
var vertex = context.surface().selectAll("." + entity.id);
drag.targetNode(vertex.node()).targetEntity(entity);
} else {
context.perform(actionNoop());
}
_activeEntity = entity;
_startLoc = entity.loc;
hover.ignoreVertex(entity.geometry(context.graph()) === "vertex");
context.surface().selectAll("." + _activeEntity.id).classed("active", true);
context.enter(mode);
}
function datum2(d3_event) {
if (!d3_event || d3_event.altKey) {
return {};
} else {
var d = d3_event.target.__data__;
return d && d.properties && d.properties.target ? d : {};
}
}
function doMove(d3_event, entity, nudge) {
nudge = nudge || [0, 0];
var currPoint = d3_event && d3_event.point || context.projection(_lastLoc);
var currMouse = geoVecSubtract(currPoint, nudge);
var loc = context.projection.invert(currMouse);
var target, edge;
if (!_nudgeInterval) {
var d = datum2(d3_event);
target = d && d.properties && d.properties.entity;
var targetLoc = target && target.loc;
var targetNodes = d && d.properties && d.properties.nodes;
if (targetLoc) {
if (shouldSnapToNode(target)) {
loc = targetLoc;
}
} else if (targetNodes) {
edge = geoChooseEdge(targetNodes, context.map().mouse(), context.projection, end.id);
if (edge) {
loc = edge.loc;
}
}
}
context.replace(actionMoveNode(entity.id, loc));
var isInvalid = false;
if (target) {
isInvalid = hasRelationConflict(entity, target, edge, context.graph());
}
if (!isInvalid) {
isInvalid = hasInvalidGeometry(entity, context.graph());
}
var nope = context.surface().classed("nope");
if (isInvalid === "relation" || isInvalid === "restriction") {
if (!nope) {
context.ui().flash.duration(4e3).iconName("#iD-icon-no").label(_t.html("operations.connect." + isInvalid, { relation: _mainPresetIndex.item("type/restriction").name() }))();
}
} else if (isInvalid) {
var errorID = isInvalid === "line" ? "lines" : "areas";
context.ui().flash.duration(3e3).iconName("#iD-icon-no").label(_t.html("self_intersection.error." + errorID))();
} else {
if (nope) {
context.ui().flash.duration(1).label("")();
}
}
var nopeDisabled = context.surface().classed("nope-disabled");
if (nopeDisabled) {
context.surface().classed("nope", false).classed("nope-suppressed", isInvalid);
} else {
context.surface().classed("nope", isInvalid).classed("nope-suppressed", false);
}
_lastLoc = loc;
}
function hasRelationConflict(entity, target, edge, graph) {
var testGraph = graph.update();
if (edge) {
var midpoint = osmNode();
var action = actionAddMidpoint({
loc: edge.loc,
edge: [target.nodes[edge.index - 1], target.nodes[edge.index]]
}, midpoint);
testGraph = action(testGraph);
target = midpoint;
}
var ids = [entity.id, target.id];
return actionConnect(ids).disabled(testGraph);
}
function hasInvalidGeometry(entity, graph) {
var parents = graph.parentWays(entity);
var i2, j2, k;
for (i2 = 0; i2 < parents.length; i2++) {
var parent = parents[i2];
var nodes = [];
var activeIndex = null;
var relations = graph.parentRelations(parent);
for (j2 = 0; j2 < relations.length; j2++) {
if (!relations[j2].isMultipolygon())
continue;
var rings = osmJoinWays(relations[j2].members, graph);
for (k = 0; k < rings.length; k++) {
nodes = rings[k].nodes;
if (nodes.find(function(n2) {
return n2.id === entity.id;
})) {
activeIndex = k;
if (geoHasSelfIntersections(nodes, entity.id)) {
return "multipolygonMember";
}
}
rings[k].coords = nodes.map(function(n2) {
return n2.loc;
});
}
for (k = 0; k < rings.length; k++) {
if (k === activeIndex)
continue;
if (geoHasLineIntersections(rings[activeIndex].nodes, rings[k].nodes, entity.id)) {
return "multipolygonRing";
}
}
}
if (activeIndex === null) {
nodes = parent.nodes.map(function(nodeID) {
return graph.entity(nodeID);
});
if (nodes.length && geoHasSelfIntersections(nodes, entity.id)) {
return parent.geometry(graph);
}
}
}
return false;
}
function move(d3_event, entity, point) {
if (_isCancelled)
return;
d3_event.stopPropagation();
context.surface().classed("nope-disabled", d3_event.altKey);
_lastLoc = context.projection.invert(point);
doMove(d3_event, entity);
var nudge = geoViewportEdge(point, context.map().dimensions());
if (nudge) {
startNudge(d3_event, entity, nudge);
} else {
stopNudge();
}
}
function end(d3_event, entity) {
if (_isCancelled)
return;
var wasPoint = entity.geometry(context.graph()) === "point";
var d = datum2(d3_event);
var nope = d && d.properties && d.properties.nope || context.surface().classed("nope");
var target = d && d.properties && d.properties.entity;
if (nope) {
context.perform(_actionBounceBack(entity.id, _startLoc));
} else if (target && target.type === "way") {
var choice = geoChooseEdge(context.graph().childNodes(target), context.map().mouse(), context.projection, entity.id);
context.replace(actionAddMidpoint({
loc: choice.loc,
edge: [target.nodes[choice.index - 1], target.nodes[choice.index]]
}, entity), connectAnnotation(entity, target));
} else if (target && target.type === "node" && shouldSnapToNode(target)) {
context.replace(actionConnect([target.id, entity.id]), connectAnnotation(entity, target));
} else if (_wasMidpoint) {
context.replace(actionNoop(), _t("operations.add.annotation.vertex"));
} else {
context.replace(actionNoop(), moveAnnotation(entity));
}
if (wasPoint) {
context.enter(modeSelect(context, [entity.id]));
} else {
var reselection = _restoreSelectedIDs.filter(function(id2) {
return context.graph().hasEntity(id2);
});
if (reselection.length) {
context.enter(modeSelect(context, reselection));
} else {
context.enter(modeBrowse(context));
}
}
}
function _actionBounceBack(nodeID, toLoc) {
var moveNode = actionMoveNode(nodeID, toLoc);
var action = function(graph, t) {
if (t === 1)
context.pop();
return moveNode(graph, t);
};
action.transitionable = true;
return action;
}
function cancel() {
drag.cancel();
context.enter(modeBrowse(context));
}
var drag = behaviorDrag().selector(".layer-touch.points .target").surface(context.container().select(".main-map").node()).origin(origin).on("start", start2).on("move", move).on("end", end);
mode.enter = function() {
context.install(hover);
context.install(edit2);
select_default2(window).on("keydown.dragNode", keydown).on("keyup.dragNode", keyup);
context.history().on("undone.drag-node", cancel);
};
mode.exit = function() {
context.ui().sidebar.hover.cancel();
context.uninstall(hover);
context.uninstall(edit2);
select_default2(window).on("keydown.dragNode", null).on("keyup.dragNode", null);
context.history().on("undone.drag-node", null);
_activeEntity = null;
context.surface().classed("nope", false).classed("nope-suppressed", false).classed("nope-disabled", false).selectAll(".active").classed("active", false);
stopNudge();
};
mode.selectedIDs = function() {
if (!arguments.length)
return _activeEntity ? [_activeEntity.id] : [];
return mode;
};
mode.activeID = function() {
if (!arguments.length)
return _activeEntity && _activeEntity.id;
return mode;
};
mode.restoreSelectedIDs = function(_) {
if (!arguments.length)
return _restoreSelectedIDs;
_restoreSelectedIDs = _;
return mode;
};
mode.behavior = drag;
return mode;
}
// modules/services/keepRight.js
var import_rbush = __toESM(require_rbush_min());
// node_modules/d3-fetch/src/text.js
function responseText(response) {
if (!response.ok)
throw new Error(response.status + " " + response.statusText);
return response.text();
}
function text_default3(input, init2) {
return fetch(input, init2).then(responseText);
}
// node_modules/d3-fetch/src/json.js
function responseJson(response) {
if (!response.ok)
throw new Error(response.status + " " + response.statusText);
if (response.status === 204 || response.status === 205)
return;
return response.json();
}
function json_default(input, init2) {
return fetch(input, init2).then(responseJson);
}
// node_modules/d3-fetch/src/xml.js
function parser(type3) {
return (input, init2) => text_default3(input, init2).then((text2) => new DOMParser().parseFromString(text2, type3));
}
var xml_default = parser("application/xml");
var html = parser("text/html");
var svg = parser("image/svg+xml");
// modules/services/keepRight.js
var tiler = utilTiler();
var dispatch2 = dispatch_default("loaded");
var _tileZoom = 14;
var _krUrlRoot = "https://www.keepright.at";
var _krData = { errorTypes: {}, localizeStrings: {} };
var _cache;
var _krRuleset = [
30,
40,
50,
60,
70,
90,
100,
110,
120,
130,
150,
160,
170,
180,
190,
191,
192,
193,
194,
195,
196,
197,
198,
200,
201,
202,
203,
204,
205,
206,
207,
208,
210,
220,
230,
231,
232,
270,
280,
281,
282,
283,
284,
285,
290,
291,
292,
293,
294,
295,
296,
297,
298,
300,
310,
311,
312,
313,
320,
350,
360,
370,
380,
390,
400,
401,
402,
410,
411,
412,
413
];
function abortRequest(controller) {
if (controller) {
controller.abort();
}
}
function abortUnwantedRequests(cache, tiles) {
Object.keys(cache.inflightTile).forEach((k) => {
const wanted = tiles.find((tile) => k === tile.id);
if (!wanted) {
abortRequest(cache.inflightTile[k]);
delete cache.inflightTile[k];
}
});
}
function encodeIssueRtree(d) {
return { minX: d.loc[0], minY: d.loc[1], maxX: d.loc[0], maxY: d.loc[1], data: d };
}
function updateRtree(item, replace) {
_cache.rtree.remove(item, (a, b) => a.data.id === b.data.id);
if (replace) {
_cache.rtree.insert(item);
}
}
function tokenReplacements(d) {
if (!(d instanceof QAItem))
return;
const replacements = {};
const issueTemplate = _krData.errorTypes[d.whichType];
if (!issueTemplate) {
console.log("No Template: ", d.whichType);
console.log(" ", d.description);
return;
}
if (!issueTemplate.regex)
return;
const errorRegex = new RegExp(issueTemplate.regex, "i");
const errorMatch = errorRegex.exec(d.description);
if (!errorMatch) {
console.log("Unmatched: ", d.whichType);
console.log(" ", d.description);
console.log(" ", errorRegex);
return;
}
for (let i2 = 1; i2 < errorMatch.length; i2++) {
let capture = errorMatch[i2];
let idType;
idType = "IDs" in issueTemplate ? issueTemplate.IDs[i2 - 1] : "";
if (idType && capture) {
capture = parseError(capture, idType);
} else {
const compare = capture.toLowerCase();
if (_krData.localizeStrings[compare]) {
capture = _t("QA.keepRight.error_parts." + _krData.localizeStrings[compare]);
} else {
capture = unescape_default(capture);
}
}
replacements["var" + i2] = capture;
}
return replacements;
}
function parseError(capture, idType) {
const compare = capture.toLowerCase();
if (_krData.localizeStrings[compare]) {
capture = _t("QA.keepRight.error_parts." + _krData.localizeStrings[compare]);
}
switch (idType) {
case "this":
capture = linkErrorObject2(capture);
break;
case "url":
capture = linkURL(capture);
break;
case "n":
case "w":
case "r":
capture = linkEntity2(idType + capture);
break;
case "20":
capture = parse20(capture);
break;
case "211":
capture = parse211(capture);
break;
case "231":
capture = parse231(capture);
break;
case "294":
capture = parse294(capture);
break;
case "370":
capture = parse370(capture);
break;
}
return capture;
function linkErrorObject2(d) {
return { html: `${d}` };
}
function linkEntity2(d) {
return { html: `${d}` };
}
function linkURL(d) {
return { html: `${d}` };
}
function parse211(capture2) {
let newList = [];
const items = capture2.split(", ");
items.forEach((item) => {
let id2 = linkEntity2("n" + item.slice(1));
newList.push(id2);
});
return newList.join(", ");
}
function parse231(capture2) {
let newList = [];
const items = capture2.split("),");
items.forEach((item) => {
const match = item.match(/\#(\d+)\((.+)\)?/);
if (match !== null && match.length > 2) {
newList.push(linkEntity2("w" + match[1]) + " " + _t("QA.keepRight.errorTypes.231.layer", { layer: match[2] }));
}
});
return newList.join(", ");
}
function parse294(capture2) {
let newList = [];
const items = capture2.split(",");
items.forEach((item) => {
item = item.split(" ");
const role = `"${item[0]}"`;
const idType2 = item[1].slice(0, 1);
let id2 = item[2].slice(1);
id2 = linkEntity2(idType2 + id2);
newList.push(`${role} ${item[1]} ${id2}`);
});
return newList.join(", ");
}
function parse370(capture2) {
if (!capture2)
return "";
const match = capture2.match(/\(including the name (\'.+\')\)/);
if (match && match.length) {
return _t("QA.keepRight.errorTypes.370.including_the_name", { name: match[1] });
}
return "";
}
function parse20(capture2) {
let newList = [];
const items = capture2.split(",");
items.forEach((item) => {
const id2 = linkEntity2("n" + item.slice(1));
newList.push(id2);
});
return newList.join(", ");
}
}
var keepRight_default = {
title: "keepRight",
init() {
_mainFileFetcher.get("keepRight").then((d) => _krData = d);
if (!_cache) {
this.reset();
}
this.event = utilRebind(this, dispatch2, "on");
},
reset() {
if (_cache) {
Object.values(_cache.inflightTile).forEach(abortRequest);
}
_cache = {
data: {},
loadedTile: {},
inflightTile: {},
inflightPost: {},
closed: {},
rtree: new import_rbush.default()
};
},
loadIssues(projection2) {
const options2 = {
format: "geojson",
ch: _krRuleset
};
const tiles = tiler.zoomExtent([_tileZoom, _tileZoom]).getTiles(projection2);
abortUnwantedRequests(_cache, tiles);
tiles.forEach((tile) => {
if (_cache.loadedTile[tile.id] || _cache.inflightTile[tile.id])
return;
const [left, top, right, bottom] = tile.extent.rectangle();
const params = Object.assign({}, options2, { left, bottom, right, top });
const url = `${_krUrlRoot}/export.php?` + utilQsString(params);
const controller = new AbortController();
_cache.inflightTile[tile.id] = controller;
json_default(url, { signal: controller.signal }).then((data) => {
delete _cache.inflightTile[tile.id];
_cache.loadedTile[tile.id] = true;
if (!data || !data.features || !data.features.length) {
throw new Error("No Data");
}
data.features.forEach((feature3) => {
const {
properties: {
error_type: itemType,
error_id: id2,
comment = null,
object_id: objectId,
object_type: objectType,
schema,
title
}
} = feature3;
let {
geometry: { coordinates: loc },
properties: { description: description2 = "" }
} = feature3;
const issueTemplate = _krData.errorTypes[itemType];
const parentIssueType = (Math.floor(itemType / 10) * 10).toString();
const whichType = issueTemplate ? itemType : parentIssueType;
const whichTemplate = _krData.errorTypes[whichType];
switch (whichType) {
case "170":
description2 = `This feature has a FIXME tag: ${description2}`;
break;
case "292":
case "293":
description2 = description2.replace("A turn-", "This turn-");
break;
case "294":
case "295":
case "296":
case "297":
case "298":
description2 = `This turn-restriction~${description2}`;
break;
case "300":
description2 = "This highway is missing a maxspeed tag";
break;
case "411":
case "412":
case "413":
description2 = `This feature~${description2}`;
break;
}
let coincident = false;
do {
let delta = coincident ? [1e-5, 0] : [0, 1e-5];
loc = geoVecAdd(loc, delta);
let bbox = geoExtent(loc).bbox();
coincident = _cache.rtree.search(bbox).length;
} while (coincident);
let d = new QAItem(loc, this, itemType, id2, {
comment,
description: description2,
whichType,
parentIssueType,
severity: whichTemplate.severity || "error",
objectId,
objectType,
schema,
title
});
d.replacements = tokenReplacements(d);
_cache.data[id2] = d;
_cache.rtree.insert(encodeIssueRtree(d));
});
dispatch2.call("loaded");
}).catch(() => {
delete _cache.inflightTile[tile.id];
_cache.loadedTile[tile.id] = true;
});
});
},
postUpdate(d, callback) {
if (_cache.inflightPost[d.id]) {
return callback({ message: "Error update already inflight", status: -2 }, d);
}
const params = { schema: d.schema, id: d.id };
if (d.newStatus) {
params.st = d.newStatus;
}
if (d.newComment !== void 0) {
params.co = d.newComment;
}
const url = `${_krUrlRoot}/comment.php?` + utilQsString(params);
const controller = new AbortController();
_cache.inflightPost[d.id] = controller;
json_default(url, { signal: controller.signal }).finally(() => {
delete _cache.inflightPost[d.id];
if (d.newStatus === "ignore") {
this.removeItem(d);
} else if (d.newStatus === "ignore_t") {
this.removeItem(d);
_cache.closed[`${d.schema}:${d.id}`] = true;
} else {
d = this.replaceItem(d.update({
comment: d.newComment,
newComment: void 0,
newState: void 0
}));
}
if (callback)
callback(null, d);
});
},
getItems(projection2) {
const viewport = projection2.clipExtent();
const min3 = [viewport[0][0], viewport[1][1]];
const max3 = [viewport[1][0], viewport[0][1]];
const bbox = geoExtent(projection2.invert(min3), projection2.invert(max3)).bbox();
return _cache.rtree.search(bbox).map((d) => d.data);
},
getError(id2) {
return _cache.data[id2];
},
replaceItem(item) {
if (!(item instanceof QAItem) || !item.id)
return;
_cache.data[item.id] = item;
updateRtree(encodeIssueRtree(item), true);
return item;
},
removeItem(item) {
if (!(item instanceof QAItem) || !item.id)
return;
delete _cache.data[item.id];
updateRtree(encodeIssueRtree(item), false);
},
issueURL(item) {
return `${_krUrlRoot}/report_map.php?schema=${item.schema}&error=${item.id}`;
},
getClosedIDs() {
return Object.keys(_cache.closed).sort();
}
};
// modules/services/improveOSM.js
var import_rbush2 = __toESM(require_rbush_min());
var tiler2 = utilTiler();
var dispatch3 = dispatch_default("loaded");
var _tileZoom2 = 14;
var _impOsmUrls = {
ow: "https://grab.community.improve-osm.org/directionOfFlowService",
mr: "https://grab.community.improve-osm.org/missingGeoService",
tr: "https://grab.community.improve-osm.org/turnRestrictionService"
};
var _impOsmData = { icons: {} };
var _cache2;
function abortRequest2(i2) {
Object.values(i2).forEach((controller) => {
if (controller) {
controller.abort();
}
});
}
function abortUnwantedRequests2(cache, tiles) {
Object.keys(cache.inflightTile).forEach((k) => {
const wanted = tiles.find((tile) => k === tile.id);
if (!wanted) {
abortRequest2(cache.inflightTile[k]);
delete cache.inflightTile[k];
}
});
}
function encodeIssueRtree2(d) {
return { minX: d.loc[0], minY: d.loc[1], maxX: d.loc[0], maxY: d.loc[1], data: d };
}
function updateRtree2(item, replace) {
_cache2.rtree.remove(item, (a, b) => a.data.id === b.data.id);
if (replace) {
_cache2.rtree.insert(item);
}
}
function linkErrorObject(d) {
return { html: `${d}` };
}
function linkEntity(d) {
return { html: `${d}` };
}
function pointAverage(points) {
if (points.length) {
const sum = points.reduce((acc, point) => geoVecAdd(acc, [point.lon, point.lat]), [0, 0]);
return geoVecScale(sum, 1 / points.length);
} else {
return [0, 0];
}
}
function relativeBearing(p1, p2) {
let angle2 = Math.atan2(p2.lon - p1.lon, p2.lat - p1.lat);
if (angle2 < 0) {
angle2 += 2 * Math.PI;
}
return angle2 * 180 / Math.PI;
}
function cardinalDirection(bearing) {
const dir = 45 * Math.round(bearing / 45);
const compass = {
0: "north",
45: "northeast",
90: "east",
135: "southeast",
180: "south",
225: "southwest",
270: "west",
315: "northwest",
360: "north"
};
return _t(`QA.improveOSM.directions.${compass[dir]}`);
}
function preventCoincident(loc, bumpUp) {
let coincident = false;
do {
let delta = coincident ? [1e-5, 0] : bumpUp ? [0, 1e-5] : [0, 0];
loc = geoVecAdd(loc, delta);
let bbox = geoExtent(loc).bbox();
coincident = _cache2.rtree.search(bbox).length;
} while (coincident);
return loc;
}
var improveOSM_default = {
title: "improveOSM",
init() {
_mainFileFetcher.get("qa_data").then((d) => _impOsmData = d.improveOSM);
if (!_cache2) {
this.reset();
}
this.event = utilRebind(this, dispatch3, "on");
},
reset() {
if (_cache2) {
Object.values(_cache2.inflightTile).forEach(abortRequest2);
}
_cache2 = {
data: {},
loadedTile: {},
inflightTile: {},
inflightPost: {},
closed: {},
rtree: new import_rbush2.default()
};
},
loadIssues(projection2) {
const options2 = {
client: "iD",
status: "OPEN",
zoom: "19"
};
const tiles = tiler2.zoomExtent([_tileZoom2, _tileZoom2]).getTiles(projection2);
abortUnwantedRequests2(_cache2, tiles);
tiles.forEach((tile) => {
if (_cache2.loadedTile[tile.id] || _cache2.inflightTile[tile.id])
return;
const [east, north, west, south] = tile.extent.rectangle();
const params = Object.assign({}, options2, { east, south, west, north });
const requests = {};
Object.keys(_impOsmUrls).forEach((k) => {
const kParams = Object.assign({}, params, k === "mr" ? { type: "PARKING,ROAD,BOTH,PATH" } : { confidenceLevel: "C1" });
const url = `${_impOsmUrls[k]}/search?` + utilQsString(kParams);
const controller = new AbortController();
requests[k] = controller;
json_default(url, { signal: controller.signal }).then((data) => {
delete _cache2.inflightTile[tile.id][k];
if (!Object.keys(_cache2.inflightTile[tile.id]).length) {
delete _cache2.inflightTile[tile.id];
_cache2.loadedTile[tile.id] = true;
}
if (data.roadSegments) {
data.roadSegments.forEach((feature3) => {
const { points, wayId, fromNodeId, toNodeId } = feature3;
const itemId = `${wayId}${fromNodeId}${toNodeId}`;
let mid = points.length / 2;
let loc;
if (mid % 1 === 0) {
loc = pointAverage([points[mid - 1], points[mid]]);
} else {
mid = points[Math.floor(mid)];
loc = [mid.lon, mid.lat];
}
loc = preventCoincident(loc, false);
let d = new QAItem(loc, this, k, itemId, {
issueKey: k,
identifier: {
wayId,
fromNodeId,
toNodeId
},
objectId: wayId,
objectType: "way"
});
d.replacements = {
percentage: feature3.percentOfTrips,
num_trips: feature3.numberOfTrips,
highway: linkErrorObject(_t("QA.keepRight.error_parts.highway")),
from_node: linkEntity("n" + feature3.fromNodeId),
to_node: linkEntity("n" + feature3.toNodeId)
};
_cache2.data[d.id] = d;
_cache2.rtree.insert(encodeIssueRtree2(d));
});
}
if (data.tiles) {
data.tiles.forEach((feature3) => {
const { type: type3, x, y, numberOfTrips } = feature3;
const geoType = type3.toLowerCase();
const itemId = `${geoType}${x}${y}${numberOfTrips}`;
let loc = pointAverage(feature3.points);
loc = preventCoincident(loc, false);
let d = new QAItem(loc, this, `${k}-${geoType}`, itemId, {
issueKey: k,
identifier: { x, y }
});
d.replacements = {
num_trips: numberOfTrips,
geometry_type: _t(`QA.improveOSM.geometry_types.${geoType}`)
};
if (numberOfTrips === -1) {
d.desc = _t("QA.improveOSM.error_types.mr.description_alt", d.replacements);
}
_cache2.data[d.id] = d;
_cache2.rtree.insert(encodeIssueRtree2(d));
});
}
if (data.entities) {
data.entities.forEach((feature3) => {
const { point, id: id2, segments, numberOfPasses, turnType } = feature3;
const itemId = `${id2.replace(/[,:+#]/g, "_")}`;
const loc = preventCoincident([point.lon, point.lat], true);
const ids = id2.split(",");
const from_way = ids[0];
const via_node = ids[3];
const to_way = ids[2].split(":")[1];
let d = new QAItem(loc, this, k, itemId, {
issueKey: k,
identifier: id2,
objectId: via_node,
objectType: "node"
});
const [p1, p2] = segments[0].points;
const dir_of_travel = cardinalDirection(relativeBearing(p1, p2));
d.replacements = {
num_passed: numberOfPasses,
num_trips: segments[0].numberOfTrips,
turn_restriction: turnType.toLowerCase(),
from_way: linkEntity("w" + from_way),
to_way: linkEntity("w" + to_way),
travel_direction: dir_of_travel,
junction: linkErrorObject(_t("QA.keepRight.error_parts.this_node"))
};
_cache2.data[d.id] = d;
_cache2.rtree.insert(encodeIssueRtree2(d));
dispatch3.call("loaded");
});
}
}).catch(() => {
delete _cache2.inflightTile[tile.id][k];
if (!Object.keys(_cache2.inflightTile[tile.id]).length) {
delete _cache2.inflightTile[tile.id];
_cache2.loadedTile[tile.id] = true;
}
});
});
_cache2.inflightTile[tile.id] = requests;
});
},
getComments(item) {
if (item.comments) {
return Promise.resolve(item);
}
const key = item.issueKey;
let qParams = {};
if (key === "ow") {
qParams = item.identifier;
} else if (key === "mr") {
qParams.tileX = item.identifier.x;
qParams.tileY = item.identifier.y;
} else if (key === "tr") {
qParams.targetId = item.identifier;
}
const url = `${_impOsmUrls[key]}/retrieveComments?` + utilQsString(qParams);
const cacheComments = (data) => {
item.comments = data.comments ? data.comments.reverse() : [];
this.replaceItem(item);
};
return json_default(url).then(cacheComments).then(() => item);
},
postUpdate(d, callback) {
if (!osm_default.authenticated()) {
return callback({ message: "Not Authenticated", status: -3 }, d);
}
if (_cache2.inflightPost[d.id]) {
return callback({ message: "Error update already inflight", status: -2 }, d);
}
osm_default.userDetails(sendPayload.bind(this));
function sendPayload(err, user) {
if (err) {
return callback(err, d);
}
const key = d.issueKey;
const url = `${_impOsmUrls[key]}/comment`;
const payload = {
username: user.display_name,
targetIds: [d.identifier]
};
if (d.newStatus) {
payload.status = d.newStatus;
payload.text = "status changed";
}
if (d.newComment) {
payload.text = d.newComment;
}
const controller = new AbortController();
_cache2.inflightPost[d.id] = controller;
const options2 = {
method: "POST",
signal: controller.signal,
body: JSON.stringify(payload)
};
json_default(url, options2).then(() => {
delete _cache2.inflightPost[d.id];
if (!d.newStatus) {
const now3 = new Date();
let comments = d.comments ? d.comments : [];
comments.push({
username: payload.username,
text: payload.text,
timestamp: now3.getTime() / 1e3
});
this.replaceItem(d.update({
comments,
newComment: void 0
}));
} else {
this.removeItem(d);
if (d.newStatus === "SOLVED") {
if (!(d.issueKey in _cache2.closed)) {
_cache2.closed[d.issueKey] = 0;
}
_cache2.closed[d.issueKey] += 1;
}
}
if (callback)
callback(null, d);
}).catch((err2) => {
delete _cache2.inflightPost[d.id];
if (callback)
callback(err2.message);
});
}
},
getItems(projection2) {
const viewport = projection2.clipExtent();
const min3 = [viewport[0][0], viewport[1][1]];
const max3 = [viewport[1][0], viewport[0][1]];
const bbox = geoExtent(projection2.invert(min3), projection2.invert(max3)).bbox();
return _cache2.rtree.search(bbox).map((d) => d.data);
},
getError(id2) {
return _cache2.data[id2];
},
getIcon(itemType) {
return _impOsmData.icons[itemType];
},
replaceItem(issue) {
if (!(issue instanceof QAItem) || !issue.id)
return;
_cache2.data[issue.id] = issue;
updateRtree2(encodeIssueRtree2(issue), true);
return issue;
},
removeItem(issue) {
if (!(issue instanceof QAItem) || !issue.id)
return;
delete _cache2.data[issue.id];
updateRtree2(encodeIssueRtree2(issue), false);
},
getClosedCounts() {
return _cache2.closed;
}
};
// modules/services/osmose.js
var import_rbush3 = __toESM(require_rbush_min());
// node_modules/marked/lib/marked.esm.js
function getDefaults() {
return {
baseUrl: null,
breaks: false,
extensions: null,
gfm: true,
headerIds: true,
headerPrefix: "",
highlight: null,
langPrefix: "language-",
mangle: true,
pedantic: false,
renderer: null,
sanitize: false,
sanitizer: null,
silent: false,
smartLists: false,
smartypants: false,
tokenizer: null,
walkTokens: null,
xhtml: false
};
}
var defaults = getDefaults();
function changeDefaults(newDefaults) {
defaults = newDefaults;
}
var escapeTest = /[&<>"']/;
var escapeReplace = /[&<>"']/g;
var escapeTestNoEncode = /[<>"']|&(?!#?\w+;)/;
var escapeReplaceNoEncode = /[<>"']|&(?!#?\w+;)/g;
var escapeReplacements = {
"&": "&",
"<": "<",
">": ">",
'"': """,
"'": "'"
};
var getEscapeReplacement = (ch) => escapeReplacements[ch];
function escape4(html2, encode) {
if (encode) {
if (escapeTest.test(html2)) {
return html2.replace(escapeReplace, getEscapeReplacement);
}
} else {
if (escapeTestNoEncode.test(html2)) {
return html2.replace(escapeReplaceNoEncode, getEscapeReplacement);
}
}
return html2;
}
var unescapeTest = /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig;
function unescape3(html2) {
return html2.replace(unescapeTest, (_, n2) => {
n2 = n2.toLowerCase();
if (n2 === "colon")
return ":";
if (n2.charAt(0) === "#") {
return n2.charAt(1) === "x" ? String.fromCharCode(parseInt(n2.substring(2), 16)) : String.fromCharCode(+n2.substring(1));
}
return "";
});
}
var caret = /(^|[^\[])\^/g;
function edit(regex, opt) {
regex = typeof regex === "string" ? regex : regex.source;
opt = opt || "";
const obj = {
replace: (name2, val) => {
val = val.source || val;
val = val.replace(caret, "$1");
regex = regex.replace(name2, val);
return obj;
},
getRegex: () => {
return new RegExp(regex, opt);
}
};
return obj;
}
var nonWordAndColonTest = /[^\w:]/g;
var originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;
function cleanUrl(sanitize, base, href) {
if (sanitize) {
let prot;
try {
prot = decodeURIComponent(unescape3(href)).replace(nonWordAndColonTest, "").toLowerCase();
} catch (e) {
return null;
}
if (prot.indexOf("javascript:") === 0 || prot.indexOf("vbscript:") === 0 || prot.indexOf("data:") === 0) {
return null;
}
}
if (base && !originIndependentUrl.test(href)) {
href = resolveUrl(base, href);
}
try {
href = encodeURI(href).replace(/%25/g, "%");
} catch (e) {
return null;
}
return href;
}
var baseUrls = {};
var justDomain = /^[^:]+:\/*[^/]*$/;
var protocol = /^([^:]+:)[\s\S]*$/;
var domain = /^([^:]+:\/*[^/]*)[\s\S]*$/;
function resolveUrl(base, href) {
if (!baseUrls[" " + base]) {
if (justDomain.test(base)) {
baseUrls[" " + base] = base + "/";
} else {
baseUrls[" " + base] = rtrim(base, "/", true);
}
}
base = baseUrls[" " + base];
const relativeBase = base.indexOf(":") === -1;
if (href.substring(0, 2) === "//") {
if (relativeBase) {
return href;
}
return base.replace(protocol, "$1") + href;
} else if (href.charAt(0) === "/") {
if (relativeBase) {
return href;
}
return base.replace(domain, "$1") + href;
} else {
return base + href;
}
}
var noopTest = { exec: function noopTest2() {
} };
function merge2(obj) {
let i2 = 1, target, key;
for (; i2 < arguments.length; i2++) {
target = arguments[i2];
for (key in target) {
if (Object.prototype.hasOwnProperty.call(target, key)) {
obj[key] = target[key];
}
}
}
return obj;
}
function splitCells(tableRow, count) {
const row = tableRow.replace(/\|/g, (match, offset, str2) => {
let escaped = false, curr = offset;
while (--curr >= 0 && str2[curr] === "\\")
escaped = !escaped;
if (escaped) {
return "|";
} else {
return " |";
}
}), cells = row.split(/ \|/);
let i2 = 0;
if (!cells[0].trim()) {
cells.shift();
}
if (cells.length > 0 && !cells[cells.length - 1].trim()) {
cells.pop();
}
if (cells.length > count) {
cells.splice(count);
} else {
while (cells.length < count)
cells.push("");
}
for (; i2 < cells.length; i2++) {
cells[i2] = cells[i2].trim().replace(/\\\|/g, "|");
}
return cells;
}
function rtrim(str2, c, invert) {
const l = str2.length;
if (l === 0) {
return "";
}
let suffLen = 0;
while (suffLen < l) {
const currChar = str2.charAt(l - suffLen - 1);
if (currChar === c && !invert) {
suffLen++;
} else if (currChar !== c && invert) {
suffLen++;
} else {
break;
}
}
return str2.slice(0, l - suffLen);
}
function findClosingBracket(str2, b) {
if (str2.indexOf(b[1]) === -1) {
return -1;
}
const l = str2.length;
let level = 0, i2 = 0;
for (; i2 < l; i2++) {
if (str2[i2] === "\\") {
i2++;
} else if (str2[i2] === b[0]) {
level++;
} else if (str2[i2] === b[1]) {
level--;
if (level < 0) {
return i2;
}
}
}
return -1;
}
function checkSanitizeDeprecation(opt) {
if (opt && opt.sanitize && !opt.silent) {
console.warn("marked(): sanitize and sanitizer parameters are deprecated since version 0.7.0, should not be used and will be removed in the future. Read more here: https://marked.js.org/#/USING_ADVANCED.md#options");
}
}
function repeatString(pattern, count) {
if (count < 1) {
return "";
}
let result = "";
while (count > 1) {
if (count & 1) {
result += pattern;
}
count >>= 1;
pattern += pattern;
}
return result + pattern;
}
function outputLink(cap, link2, raw, lexer2) {
const href = link2.href;
const title = link2.title ? escape4(link2.title) : null;
const text2 = cap[1].replace(/\\([\[\]])/g, "$1");
if (cap[0].charAt(0) !== "!") {
lexer2.state.inLink = true;
const token = {
type: "link",
raw,
href,
title,
text: text2,
tokens: lexer2.inlineTokens(text2, [])
};
lexer2.state.inLink = false;
return token;
}
return {
type: "image",
raw,
href,
title,
text: escape4(text2)
};
}
function indentCodeCompensation(raw, text2) {
const matchIndentToCode = raw.match(/^(\s+)(?:```)/);
if (matchIndentToCode === null) {
return text2;
}
const indentToCode = matchIndentToCode[1];
return text2.split("\n").map((node) => {
const matchIndentInNode = node.match(/^\s+/);
if (matchIndentInNode === null) {
return node;
}
const [indentInNode] = matchIndentInNode;
if (indentInNode.length >= indentToCode.length) {
return node.slice(indentToCode.length);
}
return node;
}).join("\n");
}
var Tokenizer = class {
constructor(options2) {
this.options = options2 || defaults;
}
space(src) {
const cap = this.rules.block.newline.exec(src);
if (cap && cap[0].length > 0) {
return {
type: "space",
raw: cap[0]
};
}
}
code(src) {
const cap = this.rules.block.code.exec(src);
if (cap) {
const text2 = cap[0].replace(/^ {1,4}/gm, "");
return {
type: "code",
raw: cap[0],
codeBlockStyle: "indented",
text: !this.options.pedantic ? rtrim(text2, "\n") : text2
};
}
}
fences(src) {
const cap = this.rules.block.fences.exec(src);
if (cap) {
const raw = cap[0];
const text2 = indentCodeCompensation(raw, cap[3] || "");
return {
type: "code",
raw,
lang: cap[2] ? cap[2].trim() : cap[2],
text: text2
};
}
}
heading(src) {
const cap = this.rules.block.heading.exec(src);
if (cap) {
let text2 = cap[2].trim();
if (/#$/.test(text2)) {
const trimmed = rtrim(text2, "#");
if (this.options.pedantic) {
text2 = trimmed.trim();
} else if (!trimmed || / $/.test(trimmed)) {
text2 = trimmed.trim();
}
}
const token = {
type: "heading",
raw: cap[0],
depth: cap[1].length,
text: text2,
tokens: []
};
this.lexer.inline(token.text, token.tokens);
return token;
}
}
hr(src) {
const cap = this.rules.block.hr.exec(src);
if (cap) {
return {
type: "hr",
raw: cap[0]
};
}
}
blockquote(src) {
const cap = this.rules.block.blockquote.exec(src);
if (cap) {
const text2 = cap[0].replace(/^ *>[ \t]?/gm, "");
return {
type: "blockquote",
raw: cap[0],
tokens: this.lexer.blockTokens(text2, []),
text: text2
};
}
}
list(src) {
let cap = this.rules.block.list.exec(src);
if (cap) {
let raw, istask, ischecked, indent2, i2, blankLine, endsWithBlankLine, line, nextLine, rawLine, itemContents, endEarly;
let bull = cap[1].trim();
const isordered = bull.length > 1;
const list = {
type: "list",
raw: "",
ordered: isordered,
start: isordered ? +bull.slice(0, -1) : "",
loose: false,
items: []
};
bull = isordered ? `\\d{1,9}\\${bull.slice(-1)}` : `\\${bull}`;
if (this.options.pedantic) {
bull = isordered ? bull : "[*+-]";
}
const itemRegex = new RegExp(`^( {0,3}${bull})((?:[ ][^\\n]*)?(?:\\n|$))`);
while (src) {
endEarly = false;
if (!(cap = itemRegex.exec(src))) {
break;
}
if (this.rules.block.hr.test(src)) {
break;
}
raw = cap[0];
src = src.substring(raw.length);
line = cap[2].split("\n", 1)[0];
nextLine = src.split("\n", 1)[0];
if (this.options.pedantic) {
indent2 = 2;
itemContents = line.trimLeft();
} else {
indent2 = cap[2].search(/[^ ]/);
indent2 = indent2 > 4 ? 1 : indent2;
itemContents = line.slice(indent2);
indent2 += cap[1].length;
}
blankLine = false;
if (!line && /^ *$/.test(nextLine)) {
raw += nextLine + "\n";
src = src.substring(nextLine.length + 1);
endEarly = true;
}
if (!endEarly) {
const nextBulletRegex = new RegExp(`^ {0,${Math.min(3, indent2 - 1)}}(?:[*+-]|\\d{1,9}[.)])((?: [^\\n]*)?(?:\\n|$))`);
const hrRegex = new RegExp(`^ {0,${Math.min(3, indent2 - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`);
while (src) {
rawLine = src.split("\n", 1)[0];
line = rawLine;
if (this.options.pedantic) {
line = line.replace(/^ {1,4}(?=( {4})*[^ ])/g, " ");
}
if (nextBulletRegex.test(line)) {
break;
}
if (hrRegex.test(src)) {
break;
}
if (line.search(/[^ ]/) >= indent2 || !line.trim()) {
itemContents += "\n" + line.slice(indent2);
} else if (!blankLine) {
itemContents += "\n" + line;
} else {
break;
}
if (!blankLine && !line.trim()) {
blankLine = true;
}
raw += rawLine + "\n";
src = src.substring(rawLine.length + 1);
}
}
if (!list.loose) {
if (endsWithBlankLine) {
list.loose = true;
} else if (/\n *\n *$/.test(raw)) {
endsWithBlankLine = true;
}
}
if (this.options.gfm) {
istask = /^\[[ xX]\] /.exec(itemContents);
if (istask) {
ischecked = istask[0] !== "[ ] ";
itemContents = itemContents.replace(/^\[[ xX]\] +/, "");
}
}
list.items.push({
type: "list_item",
raw,
task: !!istask,
checked: ischecked,
loose: false,
text: itemContents
});
list.raw += raw;
}
list.items[list.items.length - 1].raw = raw.trimRight();
list.items[list.items.length - 1].text = itemContents.trimRight();
list.raw = list.raw.trimRight();
const l = list.items.length;
for (i2 = 0; i2 < l; i2++) {
this.lexer.state.top = false;
list.items[i2].tokens = this.lexer.blockTokens(list.items[i2].text, []);
const spacers = list.items[i2].tokens.filter((t) => t.type === "space");
const hasMultipleLineBreaks = spacers.every((t) => {
const chars = t.raw.split("");
let lineBreaks = 0;
for (const char of chars) {
if (char === "\n") {
lineBreaks += 1;
}
if (lineBreaks > 1) {
return true;
}
}
return false;
});
if (!list.loose && spacers.length && hasMultipleLineBreaks) {
list.loose = true;
list.items[i2].loose = true;
}
}
return list;
}
}
html(src) {
const cap = this.rules.block.html.exec(src);
if (cap) {
const token = {
type: "html",
raw: cap[0],
pre: !this.options.sanitizer && (cap[1] === "pre" || cap[1] === "script" || cap[1] === "style"),
text: cap[0]
};
if (this.options.sanitize) {
token.type = "paragraph";
token.text = this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape4(cap[0]);
token.tokens = [];
this.lexer.inline(token.text, token.tokens);
}
return token;
}
}
def(src) {
const cap = this.rules.block.def.exec(src);
if (cap) {
if (cap[3])
cap[3] = cap[3].substring(1, cap[3].length - 1);
const tag = cap[1].toLowerCase().replace(/\s+/g, " ");
return {
type: "def",
tag,
raw: cap[0],
href: cap[2],
title: cap[3]
};
}
}
table(src) {
const cap = this.rules.block.table.exec(src);
if (cap) {
const item = {
type: "table",
header: splitCells(cap[1]).map((c) => {
return { text: c };
}),
align: cap[2].replace(/^ *|\| *$/g, "").split(/ *\| */),
rows: cap[3] && cap[3].trim() ? cap[3].replace(/\n[ \t]*$/, "").split("\n") : []
};
if (item.header.length === item.align.length) {
item.raw = cap[0];
let l = item.align.length;
let i2, j2, k, row;
for (i2 = 0; i2 < l; i2++) {
if (/^ *-+: *$/.test(item.align[i2])) {
item.align[i2] = "right";
} else if (/^ *:-+: *$/.test(item.align[i2])) {
item.align[i2] = "center";
} else if (/^ *:-+ *$/.test(item.align[i2])) {
item.align[i2] = "left";
} else {
item.align[i2] = null;
}
}
l = item.rows.length;
for (i2 = 0; i2 < l; i2++) {
item.rows[i2] = splitCells(item.rows[i2], item.header.length).map((c) => {
return { text: c };
});
}
l = item.header.length;
for (j2 = 0; j2 < l; j2++) {
item.header[j2].tokens = [];
this.lexer.inline(item.header[j2].text, item.header[j2].tokens);
}
l = item.rows.length;
for (j2 = 0; j2 < l; j2++) {
row = item.rows[j2];
for (k = 0; k < row.length; k++) {
row[k].tokens = [];
this.lexer.inline(row[k].text, row[k].tokens);
}
}
return item;
}
}
}
lheading(src) {
const cap = this.rules.block.lheading.exec(src);
if (cap) {
const token = {
type: "heading",
raw: cap[0],
depth: cap[2].charAt(0) === "=" ? 1 : 2,
text: cap[1],
tokens: []
};
this.lexer.inline(token.text, token.tokens);
return token;
}
}
paragraph(src) {
const cap = this.rules.block.paragraph.exec(src);
if (cap) {
const token = {
type: "paragraph",
raw: cap[0],
text: cap[1].charAt(cap[1].length - 1) === "\n" ? cap[1].slice(0, -1) : cap[1],
tokens: []
};
this.lexer.inline(token.text, token.tokens);
return token;
}
}
text(src) {
const cap = this.rules.block.text.exec(src);
if (cap) {
const token = {
type: "text",
raw: cap[0],
text: cap[0],
tokens: []
};
this.lexer.inline(token.text, token.tokens);
return token;
}
}
escape(src) {
const cap = this.rules.inline.escape.exec(src);
if (cap) {
return {
type: "escape",
raw: cap[0],
text: escape4(cap[1])
};
}
}
tag(src) {
const cap = this.rules.inline.tag.exec(src);
if (cap) {
if (!this.lexer.state.inLink && /^/i.test(cap[0])) {
this.lexer.state.inLink = false;
}
if (!this.lexer.state.inRawBlock && /^<(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {
this.lexer.state.inRawBlock = true;
} else if (this.lexer.state.inRawBlock && /^<\/(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {
this.lexer.state.inRawBlock = false;
}
return {
type: this.options.sanitize ? "text" : "html",
raw: cap[0],
inLink: this.lexer.state.inLink,
inRawBlock: this.lexer.state.inRawBlock,
text: this.options.sanitize ? this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape4(cap[0]) : cap[0]
};
}
}
link(src) {
const cap = this.rules.inline.link.exec(src);
if (cap) {
const trimmedUrl = cap[2].trim();
if (!this.options.pedantic && /^$/.test(trimmedUrl)) {
return;
}
const rtrimSlash = rtrim(trimmedUrl.slice(0, -1), "\\");
if ((trimmedUrl.length - rtrimSlash.length) % 2 === 0) {
return;
}
} else {
const lastParenIndex = findClosingBracket(cap[2], "()");
if (lastParenIndex > -1) {
const start2 = cap[0].indexOf("!") === 0 ? 5 : 4;
const linkLen = start2 + cap[1].length + lastParenIndex;
cap[2] = cap[2].substring(0, lastParenIndex);
cap[0] = cap[0].substring(0, linkLen).trim();
cap[3] = "";
}
}
let href = cap[2];
let title = "";
if (this.options.pedantic) {
const link2 = /^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(href);
if (link2) {
href = link2[1];
title = link2[3];
}
} else {
title = cap[3] ? cap[3].slice(1, -1) : "";
}
href = href.trim();
if (/^$/.test(trimmedUrl)) {
href = href.slice(1);
} else {
href = href.slice(1, -1);
}
}
return outputLink(cap, {
href: href ? href.replace(this.rules.inline._escapes, "$1") : href,
title: title ? title.replace(this.rules.inline._escapes, "$1") : title
}, cap[0], this.lexer);
}
}
reflink(src, links) {
let cap;
if ((cap = this.rules.inline.reflink.exec(src)) || (cap = this.rules.inline.nolink.exec(src))) {
let link2 = (cap[2] || cap[1]).replace(/\s+/g, " ");
link2 = links[link2.toLowerCase()];
if (!link2 || !link2.href) {
const text2 = cap[0].charAt(0);
return {
type: "text",
raw: text2,
text: text2
};
}
return outputLink(cap, link2, cap[0], this.lexer);
}
}
emStrong(src, maskedSrc, prevChar = "") {
let match = this.rules.inline.emStrong.lDelim.exec(src);
if (!match)
return;
if (match[3] && prevChar.match(/[\p{L}\p{N}]/u))
return;
const nextChar = match[1] || match[2] || "";
if (!nextChar || nextChar && (prevChar === "" || this.rules.inline.punctuation.exec(prevChar))) {
const lLength = match[0].length - 1;
let rDelim, rLength, delimTotal = lLength, midDelimTotal = 0;
const endReg = match[0][0] === "*" ? this.rules.inline.emStrong.rDelimAst : this.rules.inline.emStrong.rDelimUnd;
endReg.lastIndex = 0;
maskedSrc = maskedSrc.slice(-1 * src.length + lLength);
while ((match = endReg.exec(maskedSrc)) != null) {
rDelim = match[1] || match[2] || match[3] || match[4] || match[5] || match[6];
if (!rDelim)
continue;
rLength = rDelim.length;
if (match[3] || match[4]) {
delimTotal += rLength;
continue;
} else if (match[5] || match[6]) {
if (lLength % 3 && !((lLength + rLength) % 3)) {
midDelimTotal += rLength;
continue;
}
}
delimTotal -= rLength;
if (delimTotal > 0)
continue;
rLength = Math.min(rLength, rLength + delimTotal + midDelimTotal);
if (Math.min(lLength, rLength) % 2) {
const text3 = src.slice(1, lLength + match.index + rLength);
return {
type: "em",
raw: src.slice(0, lLength + match.index + rLength + 1),
text: text3,
tokens: this.lexer.inlineTokens(text3, [])
};
}
const text2 = src.slice(2, lLength + match.index + rLength - 1);
return {
type: "strong",
raw: src.slice(0, lLength + match.index + rLength + 1),
text: text2,
tokens: this.lexer.inlineTokens(text2, [])
};
}
}
}
codespan(src) {
const cap = this.rules.inline.code.exec(src);
if (cap) {
let text2 = cap[2].replace(/\n/g, " ");
const hasNonSpaceChars = /[^ ]/.test(text2);
const hasSpaceCharsOnBothEnds = /^ /.test(text2) && / $/.test(text2);
if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) {
text2 = text2.substring(1, text2.length - 1);
}
text2 = escape4(text2, true);
return {
type: "codespan",
raw: cap[0],
text: text2
};
}
}
br(src) {
const cap = this.rules.inline.br.exec(src);
if (cap) {
return {
type: "br",
raw: cap[0]
};
}
}
del(src) {
const cap = this.rules.inline.del.exec(src);
if (cap) {
return {
type: "del",
raw: cap[0],
text: cap[2],
tokens: this.lexer.inlineTokens(cap[2], [])
};
}
}
autolink(src, mangle2) {
const cap = this.rules.inline.autolink.exec(src);
if (cap) {
let text2, href;
if (cap[2] === "@") {
text2 = escape4(this.options.mangle ? mangle2(cap[1]) : cap[1]);
href = "mailto:" + text2;
} else {
text2 = escape4(cap[1]);
href = text2;
}
return {
type: "link",
raw: cap[0],
text: text2,
href,
tokens: [
{
type: "text",
raw: text2,
text: text2
}
]
};
}
}
url(src, mangle2) {
let cap;
if (cap = this.rules.inline.url.exec(src)) {
let text2, href;
if (cap[2] === "@") {
text2 = escape4(this.options.mangle ? mangle2(cap[0]) : cap[0]);
href = "mailto:" + text2;
} else {
let prevCapZero;
do {
prevCapZero = cap[0];
cap[0] = this.rules.inline._backpedal.exec(cap[0])[0];
} while (prevCapZero !== cap[0]);
text2 = escape4(cap[0]);
if (cap[1] === "www.") {
href = "http://" + text2;
} else {
href = text2;
}
}
return {
type: "link",
raw: cap[0],
text: text2,
href,
tokens: [
{
type: "text",
raw: text2,
text: text2
}
]
};
}
}
inlineText(src, smartypants2) {
const cap = this.rules.inline.text.exec(src);
if (cap) {
let text2;
if (this.lexer.state.inRawBlock) {
text2 = this.options.sanitize ? this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape4(cap[0]) : cap[0];
} else {
text2 = escape4(this.options.smartypants ? smartypants2(cap[0]) : cap[0]);
}
return {
type: "text",
raw: cap[0],
text: text2
};
}
}
};
var block = {
newline: /^(?: *(?:\n|$))+/,
code: /^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/,
fences: /^ {0,3}(`{3,}(?=[^`\n]*\n)|~{3,})([^\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?=\n|$)|$)/,
hr: /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,
heading: /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,
blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,
list: /^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/,
html: "^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:\\1>[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|\\n*|$)|\\n*|$)|?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n *)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)|(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$))",
def: /^ {0,3}\[(label)\]: *(?:\n *)?([^\s>]+)>?(?:(?: +(?:\n *)?| *\n *)(title))? *(?:\n+|$)/,
table: noopTest,
lheading: /^([^\n]+)\n {0,3}(=+|-+) *(?:\n+|$)/,
_paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,
text: /^[^\n]+/
};
block._label = /(?!\s*\])(?:\\.|[^\[\]\\])+/;
block._title = /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/;
block.def = edit(block.def).replace("label", block._label).replace("title", block._title).getRegex();
block.bullet = /(?:[*+-]|\d{1,9}[.)])/;
block.listItemStart = edit(/^( *)(bull) */).replace("bull", block.bullet).getRegex();
block.list = edit(block.list).replace(/bull/g, block.bullet).replace("hr", "\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))").replace("def", "\\n+(?=" + block.def.source + ")").getRegex();
block._tag = "address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul";
block._comment = /|$)/;
block.html = edit(block.html, "i").replace("comment", block._comment).replace("tag", block._tag).replace("attribute", / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex();
block.paragraph = edit(block._paragraph).replace("hr", block.hr).replace("heading", " {0,3}#{1,6} ").replace("|lheading", "").replace("|table", "").replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", "?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", block._tag).getRegex();
block.blockquote = edit(block.blockquote).replace("paragraph", block.paragraph).getRegex();
block.normal = merge2({}, block);
block.gfm = merge2({}, block.normal, {
table: "^ *([^\\n ].*\\|.*)\\n {0,3}(?:\\| *)?(:?-+:? *(?:\\| *:?-+:? *)*)(?:\\| *)?(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)"
});
block.gfm.table = edit(block.gfm.table).replace("hr", block.hr).replace("heading", " {0,3}#{1,6} ").replace("blockquote", " {0,3}>").replace("code", " {4}[^\\n]").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", "?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", block._tag).getRegex();
block.gfm.paragraph = edit(block._paragraph).replace("hr", block.hr).replace("heading", " {0,3}#{1,6} ").replace("|lheading", "").replace("table", block.gfm.table).replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", "?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", block._tag).getRegex();
block.pedantic = merge2({}, block.normal, {
html: edit(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?\\1> *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment", block._comment).replace(/tag/g, "(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),
def: /^ *\[([^\]]+)\]: *([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,
heading: /^(#{1,6})(.*)(?:\n+|$)/,
fences: noopTest,
paragraph: edit(block.normal._paragraph).replace("hr", block.hr).replace("heading", " *#{1,6} *[^\n]").replace("lheading", block.lheading).replace("blockquote", " {0,3}>").replace("|fences", "").replace("|list", "").replace("|html", "").getRegex()
});
var inline = {
escape: /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,
autolink: /^<(scheme:[^\s\x00-\x1f<>]*|email)>/,
url: noopTest,
tag: "^comment|^[a-zA-Z][\\w:-]*\\s*>|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^",
link: /^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/,
reflink: /^!?\[(label)\]\[(ref)\]/,
nolink: /^!?\[(ref)\](?:\[\])?/,
reflinkSearch: "reflink|nolink(?!\\()",
emStrong: {
lDelim: /^(?:\*+(?:([punct_])|[^\s*]))|^_+(?:([punct*])|([^\s_]))/,
rDelimAst: /^[^_*]*?\_\_[^_*]*?\*[^_*]*?(?=\_\_)|[^*]+(?=[^*])|[punct_](\*+)(?=[\s]|$)|[^punct*_\s](\*+)(?=[punct_\s]|$)|[punct_\s](\*+)(?=[^punct*_\s])|[\s](\*+)(?=[punct_])|[punct_](\*+)(?=[punct_])|[^punct*_\s](\*+)(?=[^punct*_\s])/,
rDelimUnd: /^[^_*]*?\*\*[^_*]*?\_[^_*]*?(?=\*\*)|[^_]+(?=[^_])|[punct*](\_+)(?=[\s]|$)|[^punct*_\s](\_+)(?=[punct*\s]|$)|[punct*\s](\_+)(?=[^punct*_\s])|[\s](\_+)(?=[punct*])|[punct*](\_+)(?=[punct*])/
},
code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,
br: /^( {2,}|\\)\n(?!\s*$)/,
del: noopTest,
text: /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\?@\\[\\]`^{|}~";
inline.punctuation = edit(inline.punctuation).replace(/punctuation/g, inline._punctuation).getRegex();
inline.blockSkip = /\[[^\]]*?\]\([^\)]*?\)|`[^`]*?`|<[^>]*?>/g;
inline.escapedEmSt = /\\\*|\\_/g;
inline._comment = edit(block._comment).replace("(?:-->|$)", "-->").getRegex();
inline.emStrong.lDelim = edit(inline.emStrong.lDelim).replace(/punct/g, inline._punctuation).getRegex();
inline.emStrong.rDelimAst = edit(inline.emStrong.rDelimAst, "g").replace(/punct/g, inline._punctuation).getRegex();
inline.emStrong.rDelimUnd = edit(inline.emStrong.rDelimUnd, "g").replace(/punct/g, inline._punctuation).getRegex();
inline._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g;
inline._scheme = /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/;
inline._email = /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/;
inline.autolink = edit(inline.autolink).replace("scheme", inline._scheme).replace("email", inline._email).getRegex();
inline._attribute = /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/;
inline.tag = edit(inline.tag).replace("comment", inline._comment).replace("attribute", inline._attribute).getRegex();
inline._label = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/;
inline._href = /<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/;
inline._title = /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/;
inline.link = edit(inline.link).replace("label", inline._label).replace("href", inline._href).replace("title", inline._title).getRegex();
inline.reflink = edit(inline.reflink).replace("label", inline._label).replace("ref", block._label).getRegex();
inline.nolink = edit(inline.nolink).replace("ref", block._label).getRegex();
inline.reflinkSearch = edit(inline.reflinkSearch, "g").replace("reflink", inline.reflink).replace("nolink", inline.nolink).getRegex();
inline.normal = merge2({}, inline);
inline.pedantic = merge2({}, inline.normal, {
strong: {
start: /^__|\*\*/,
middle: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
endAst: /\*\*(?!\*)/g,
endUnd: /__(?!_)/g
},
em: {
start: /^_|\*/,
middle: /^()\*(?=\S)([\s\S]*?\S)\*(?!\*)|^_(?=\S)([\s\S]*?\S)_(?!_)/,
endAst: /\*(?!\*)/g,
endUnd: /_(?!_)/g
},
link: edit(/^!?\[(label)\]\((.*?)\)/).replace("label", inline._label).getRegex(),
reflink: edit(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label", inline._label).getRegex()
});
inline.gfm = merge2({}, inline.normal, {
escape: edit(inline.escape).replace("])", "~|])").getRegex(),
_extended_email: /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/,
url: /^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,
_backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,
del: /^(~~?)(?=[^\s~])([\s\S]*?[^\s~])\1(?=[^~]|$)/,
text: /^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\ 0.5) {
ch = "x" + ch.toString(16);
}
out += "" + ch + ";";
}
return out;
}
var Lexer = class {
constructor(options2) {
this.tokens = [];
this.tokens.links = /* @__PURE__ */ Object.create(null);
this.options = options2 || defaults;
this.options.tokenizer = this.options.tokenizer || new Tokenizer();
this.tokenizer = this.options.tokenizer;
this.tokenizer.options = this.options;
this.tokenizer.lexer = this;
this.inlineQueue = [];
this.state = {
inLink: false,
inRawBlock: false,
top: true
};
const rules = {
block: block.normal,
inline: inline.normal
};
if (this.options.pedantic) {
rules.block = block.pedantic;
rules.inline = inline.pedantic;
} else if (this.options.gfm) {
rules.block = block.gfm;
if (this.options.breaks) {
rules.inline = inline.breaks;
} else {
rules.inline = inline.gfm;
}
}
this.tokenizer.rules = rules;
}
static get rules() {
return {
block,
inline
};
}
static lex(src, options2) {
const lexer2 = new Lexer(options2);
return lexer2.lex(src);
}
static lexInline(src, options2) {
const lexer2 = new Lexer(options2);
return lexer2.inlineTokens(src);
}
lex(src) {
src = src.replace(/\r\n|\r/g, "\n");
this.blockTokens(src, this.tokens);
let next;
while (next = this.inlineQueue.shift()) {
this.inlineTokens(next.src, next.tokens);
}
return this.tokens;
}
blockTokens(src, tokens = []) {
if (this.options.pedantic) {
src = src.replace(/\t/g, " ").replace(/^ +$/gm, "");
} else {
src = src.replace(/^( *)(\t+)/gm, (_, leading, tabs) => {
return leading + " ".repeat(tabs.length);
});
}
let token, lastToken, cutSrc, lastParagraphClipped;
while (src) {
if (this.options.extensions && this.options.extensions.block && this.options.extensions.block.some((extTokenizer) => {
if (token = extTokenizer.call({ lexer: this }, src, tokens)) {
src = src.substring(token.raw.length);
tokens.push(token);
return true;
}
return false;
})) {
continue;
}
if (token = this.tokenizer.space(src)) {
src = src.substring(token.raw.length);
if (token.raw.length === 1 && tokens.length > 0) {
tokens[tokens.length - 1].raw += "\n";
} else {
tokens.push(token);
}
continue;
}
if (token = this.tokenizer.code(src)) {
src = src.substring(token.raw.length);
lastToken = tokens[tokens.length - 1];
if (lastToken && (lastToken.type === "paragraph" || lastToken.type === "text")) {
lastToken.raw += "\n" + token.raw;
lastToken.text += "\n" + token.text;
this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;
} else {
tokens.push(token);
}
continue;
}
if (token = this.tokenizer.fences(src)) {
src = src.substring(token.raw.length);
tokens.push(token);
continue;
}
if (token = this.tokenizer.heading(src)) {
src = src.substring(token.raw.length);
tokens.push(token);
continue;
}
if (token = this.tokenizer.hr(src)) {
src = src.substring(token.raw.length);
tokens.push(token);
continue;
}
if (token = this.tokenizer.blockquote(src)) {
src = src.substring(token.raw.length);
tokens.push(token);
continue;
}
if (token = this.tokenizer.list(src)) {
src = src.substring(token.raw.length);
tokens.push(token);
continue;
}
if (token = this.tokenizer.html(src)) {
src = src.substring(token.raw.length);
tokens.push(token);
continue;
}
if (token = this.tokenizer.def(src)) {
src = src.substring(token.raw.length);
lastToken = tokens[tokens.length - 1];
if (lastToken && (lastToken.type === "paragraph" || lastToken.type === "text")) {
lastToken.raw += "\n" + token.raw;
lastToken.text += "\n" + token.raw;
this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;
} else if (!this.tokens.links[token.tag]) {
this.tokens.links[token.tag] = {
href: token.href,
title: token.title
};
}
continue;
}
if (token = this.tokenizer.table(src)) {
src = src.substring(token.raw.length);
tokens.push(token);
continue;
}
if (token = this.tokenizer.lheading(src)) {
src = src.substring(token.raw.length);
tokens.push(token);
continue;
}
cutSrc = src;
if (this.options.extensions && this.options.extensions.startBlock) {
let startIndex = Infinity;
const tempSrc = src.slice(1);
let tempStart;
this.options.extensions.startBlock.forEach(function(getStartIndex) {
tempStart = getStartIndex.call({ lexer: this }, tempSrc);
if (typeof tempStart === "number" && tempStart >= 0) {
startIndex = Math.min(startIndex, tempStart);
}
});
if (startIndex < Infinity && startIndex >= 0) {
cutSrc = src.substring(0, startIndex + 1);
}
}
if (this.state.top && (token = this.tokenizer.paragraph(cutSrc))) {
lastToken = tokens[tokens.length - 1];
if (lastParagraphClipped && lastToken.type === "paragraph") {
lastToken.raw += "\n" + token.raw;
lastToken.text += "\n" + token.text;
this.inlineQueue.pop();
this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;
} else {
tokens.push(token);
}
lastParagraphClipped = cutSrc.length !== src.length;
src = src.substring(token.raw.length);
continue;
}
if (token = this.tokenizer.text(src)) {
src = src.substring(token.raw.length);
lastToken = tokens[tokens.length - 1];
if (lastToken && lastToken.type === "text") {
lastToken.raw += "\n" + token.raw;
lastToken.text += "\n" + token.text;
this.inlineQueue.pop();
this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;
} else {
tokens.push(token);
}
continue;
}
if (src) {
const errMsg = "Infinite loop on byte: " + src.charCodeAt(0);
if (this.options.silent) {
console.error(errMsg);
break;
} else {
throw new Error(errMsg);
}
}
}
this.state.top = true;
return tokens;
}
inline(src, tokens) {
this.inlineQueue.push({ src, tokens });
}
inlineTokens(src, tokens = []) {
let token, lastToken, cutSrc;
let maskedSrc = src;
let match;
let keepPrevChar, prevChar;
if (this.tokens.links) {
const links = Object.keys(this.tokens.links);
if (links.length > 0) {
while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) {
if (links.includes(match[0].slice(match[0].lastIndexOf("[") + 1, -1))) {
maskedSrc = maskedSrc.slice(0, match.index) + "[" + repeatString("a", match[0].length - 2) + "]" + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex);
}
}
}
}
while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) {
maskedSrc = maskedSrc.slice(0, match.index) + "[" + repeatString("a", match[0].length - 2) + "]" + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
}
while ((match = this.tokenizer.rules.inline.escapedEmSt.exec(maskedSrc)) != null) {
maskedSrc = maskedSrc.slice(0, match.index) + "++" + maskedSrc.slice(this.tokenizer.rules.inline.escapedEmSt.lastIndex);
}
while (src) {
if (!keepPrevChar) {
prevChar = "";
}
keepPrevChar = false;
if (this.options.extensions && this.options.extensions.inline && this.options.extensions.inline.some((extTokenizer) => {
if (token = extTokenizer.call({ lexer: this }, src, tokens)) {
src = src.substring(token.raw.length);
tokens.push(token);
return true;
}
return false;
})) {
continue;
}
if (token = this.tokenizer.escape(src)) {
src = src.substring(token.raw.length);
tokens.push(token);
continue;
}
if (token = this.tokenizer.tag(src)) {
src = src.substring(token.raw.length);
lastToken = tokens[tokens.length - 1];
if (lastToken && token.type === "text" && lastToken.type === "text") {
lastToken.raw += token.raw;
lastToken.text += token.text;
} else {
tokens.push(token);
}
continue;
}
if (token = this.tokenizer.link(src)) {
src = src.substring(token.raw.length);
tokens.push(token);
continue;
}
if (token = this.tokenizer.reflink(src, this.tokens.links)) {
src = src.substring(token.raw.length);
lastToken = tokens[tokens.length - 1];
if (lastToken && token.type === "text" && lastToken.type === "text") {
lastToken.raw += token.raw;
lastToken.text += token.text;
} else {
tokens.push(token);
}
continue;
}
if (token = this.tokenizer.emStrong(src, maskedSrc, prevChar)) {
src = src.substring(token.raw.length);
tokens.push(token);
continue;
}
if (token = this.tokenizer.codespan(src)) {
src = src.substring(token.raw.length);
tokens.push(token);
continue;
}
if (token = this.tokenizer.br(src)) {
src = src.substring(token.raw.length);
tokens.push(token);
continue;
}
if (token = this.tokenizer.del(src)) {
src = src.substring(token.raw.length);
tokens.push(token);
continue;
}
if (token = this.tokenizer.autolink(src, mangle)) {
src = src.substring(token.raw.length);
tokens.push(token);
continue;
}
if (!this.state.inLink && (token = this.tokenizer.url(src, mangle))) {
src = src.substring(token.raw.length);
tokens.push(token);
continue;
}
cutSrc = src;
if (this.options.extensions && this.options.extensions.startInline) {
let startIndex = Infinity;
const tempSrc = src.slice(1);
let tempStart;
this.options.extensions.startInline.forEach(function(getStartIndex) {
tempStart = getStartIndex.call({ lexer: this }, tempSrc);
if (typeof tempStart === "number" && tempStart >= 0) {
startIndex = Math.min(startIndex, tempStart);
}
});
if (startIndex < Infinity && startIndex >= 0) {
cutSrc = src.substring(0, startIndex + 1);
}
}
if (token = this.tokenizer.inlineText(cutSrc, smartypants)) {
src = src.substring(token.raw.length);
if (token.raw.slice(-1) !== "_") {
prevChar = token.raw.slice(-1);
}
keepPrevChar = true;
lastToken = tokens[tokens.length - 1];
if (lastToken && lastToken.type === "text") {
lastToken.raw += token.raw;
lastToken.text += token.text;
} else {
tokens.push(token);
}
continue;
}
if (src) {
const errMsg = "Infinite loop on byte: " + src.charCodeAt(0);
if (this.options.silent) {
console.error(errMsg);
break;
} else {
throw new Error(errMsg);
}
}
}
return tokens;
}
};
var Renderer = class {
constructor(options2) {
this.options = options2 || defaults;
}
code(code, infostring, escaped) {
const lang = (infostring || "").match(/\S*/)[0];
if (this.options.highlight) {
const out = this.options.highlight(code, lang);
if (out != null && out !== code) {
escaped = true;
code = out;
}
}
code = code.replace(/\n$/, "") + "\n";
if (!lang) {
return "" + (escaped ? code : escape4(code, true)) + "
\n";
}
return '' + (escaped ? code : escape4(code, true)) + "
\n";
}
blockquote(quote2) {
return `
${quote2}
`;
}
html(html2) {
return html2;
}
heading(text2, level, raw, slugger) {
if (this.options.headerIds) {
const id2 = this.options.headerPrefix + slugger.slug(raw);
return `${text2}
`;
}
return `${text2}
`;
}
hr() {
return this.options.xhtml ? "
\n" : "
\n";
}
list(body, ordered, start2) {
const type3 = ordered ? "ol" : "ul", startatt = ordered && start2 !== 1 ? ' start="' + start2 + '"' : "";
return "<" + type3 + startatt + ">\n" + body + "" + type3 + ">\n";
}
listitem(text2) {
return `${text2}
`;
}
checkbox(checked) {
return " ";
}
paragraph(text2) {
return `${text2}
`;
}
table(header, body) {
if (body)
body = `${body}`;
return "\n\n" + header + "\n" + body + "
\n";
}
tablerow(content) {
return `
${content}
`;
}
tablecell(content, flags) {
const type3 = flags.header ? "th" : "td";
const tag = flags.align ? `<${type3} align="${flags.align}">` : `<${type3}>`;
return tag + content + `${type3}>
`;
}
strong(text2) {
return `${text2}`;
}
em(text2) {
return `${text2}`;
}
codespan(text2) {
return `${text2}
`;
}
br() {
return this.options.xhtml ? "
" : "
";
}
del(text2) {
return `${text2}`;
}
link(href, title, text2) {
href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
if (href === null) {
return text2;
}
let out = '" + text2 + "";
return out;
}
image(href, title, text2) {
href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
if (href === null) {
return text2;
}
let out = `
" : ">";
return out;
}
text(text2) {
return text2;
}
};
var TextRenderer = class {
strong(text2) {
return text2;
}
em(text2) {
return text2;
}
codespan(text2) {
return text2;
}
del(text2) {
return text2;
}
html(text2) {
return text2;
}
text(text2) {
return text2;
}
link(href, title, text2) {
return "" + text2;
}
image(href, title, text2) {
return "" + text2;
}
br() {
return "";
}
};
var Slugger = class {
constructor() {
this.seen = {};
}
serialize(value) {
return value.toLowerCase().trim().replace(/<[!\/a-z].*?>/ig, "").replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g, "").replace(/\s/g, "-");
}
getNextSafeSlug(originalSlug, isDryRun) {
let slug = originalSlug;
let occurenceAccumulator = 0;
if (this.seen.hasOwnProperty(slug)) {
occurenceAccumulator = this.seen[originalSlug];
do {
occurenceAccumulator++;
slug = originalSlug + "-" + occurenceAccumulator;
} while (this.seen.hasOwnProperty(slug));
}
if (!isDryRun) {
this.seen[originalSlug] = occurenceAccumulator;
this.seen[slug] = 0;
}
return slug;
}
slug(value, options2 = {}) {
const slug = this.serialize(value);
return this.getNextSafeSlug(slug, options2.dryrun);
}
};
var Parser = class {
constructor(options2) {
this.options = options2 || defaults;
this.options.renderer = this.options.renderer || new Renderer();
this.renderer = this.options.renderer;
this.renderer.options = this.options;
this.textRenderer = new TextRenderer();
this.slugger = new Slugger();
}
static parse(tokens, options2) {
const parser3 = new Parser(options2);
return parser3.parse(tokens);
}
static parseInline(tokens, options2) {
const parser3 = new Parser(options2);
return parser3.parseInline(tokens);
}
parse(tokens, top = true) {
let out = "", i2, j2, k, l2, l3, row, cell, header, body, token, ordered, start2, loose, itemBody, item, checked, task, checkbox, ret;
const l = tokens.length;
for (i2 = 0; i2 < l; i2++) {
token = tokens[i2];
if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[token.type]) {
ret = this.options.extensions.renderers[token.type].call({ parser: this }, token);
if (ret !== false || !["space", "hr", "heading", "code", "table", "blockquote", "list", "html", "paragraph", "text"].includes(token.type)) {
out += ret || "";
continue;
}
}
switch (token.type) {
case "space": {
continue;
}
case "hr": {
out += this.renderer.hr();
continue;
}
case "heading": {
out += this.renderer.heading(this.parseInline(token.tokens), token.depth, unescape3(this.parseInline(token.tokens, this.textRenderer)), this.slugger);
continue;
}
case "code": {
out += this.renderer.code(token.text, token.lang, token.escaped);
continue;
}
case "table": {
header = "";
cell = "";
l2 = token.header.length;
for (j2 = 0; j2 < l2; j2++) {
cell += this.renderer.tablecell(this.parseInline(token.header[j2].tokens), { header: true, align: token.align[j2] });
}
header += this.renderer.tablerow(cell);
body = "";
l2 = token.rows.length;
for (j2 = 0; j2 < l2; j2++) {
row = token.rows[j2];
cell = "";
l3 = row.length;
for (k = 0; k < l3; k++) {
cell += this.renderer.tablecell(this.parseInline(row[k].tokens), { header: false, align: token.align[k] });
}
body += this.renderer.tablerow(cell);
}
out += this.renderer.table(header, body);
continue;
}
case "blockquote": {
body = this.parse(token.tokens);
out += this.renderer.blockquote(body);
continue;
}
case "list": {
ordered = token.ordered;
start2 = token.start;
loose = token.loose;
l2 = token.items.length;
body = "";
for (j2 = 0; j2 < l2; j2++) {
item = token.items[j2];
checked = item.checked;
task = item.task;
itemBody = "";
if (item.task) {
checkbox = this.renderer.checkbox(checked);
if (loose) {
if (item.tokens.length > 0 && item.tokens[0].type === "paragraph") {
item.tokens[0].text = checkbox + " " + item.tokens[0].text;
if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === "text") {
item.tokens[0].tokens[0].text = checkbox + " " + item.tokens[0].tokens[0].text;
}
} else {
item.tokens.unshift({
type: "text",
text: checkbox
});
}
} else {
itemBody += checkbox;
}
}
itemBody += this.parse(item.tokens, loose);
body += this.renderer.listitem(itemBody, task, checked);
}
out += this.renderer.list(body, ordered, start2);
continue;
}
case "html": {
out += this.renderer.html(token.text);
continue;
}
case "paragraph": {
out += this.renderer.paragraph(this.parseInline(token.tokens));
continue;
}
case "text": {
body = token.tokens ? this.parseInline(token.tokens) : token.text;
while (i2 + 1 < l && tokens[i2 + 1].type === "text") {
token = tokens[++i2];
body += "\n" + (token.tokens ? this.parseInline(token.tokens) : token.text);
}
out += top ? this.renderer.paragraph(body) : body;
continue;
}
default: {
const errMsg = 'Token with "' + token.type + '" type was not found.';
if (this.options.silent) {
console.error(errMsg);
return;
} else {
throw new Error(errMsg);
}
}
}
}
return out;
}
parseInline(tokens, renderer) {
renderer = renderer || this.renderer;
let out = "", i2, token, ret;
const l = tokens.length;
for (i2 = 0; i2 < l; i2++) {
token = tokens[i2];
if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[token.type]) {
ret = this.options.extensions.renderers[token.type].call({ parser: this }, token);
if (ret !== false || !["escape", "html", "link", "image", "strong", "em", "codespan", "br", "del", "text"].includes(token.type)) {
out += ret || "";
continue;
}
}
switch (token.type) {
case "escape": {
out += renderer.text(token.text);
break;
}
case "html": {
out += renderer.html(token.text);
break;
}
case "link": {
out += renderer.link(token.href, token.title, this.parseInline(token.tokens, renderer));
break;
}
case "image": {
out += renderer.image(token.href, token.title, token.text);
break;
}
case "strong": {
out += renderer.strong(this.parseInline(token.tokens, renderer));
break;
}
case "em": {
out += renderer.em(this.parseInline(token.tokens, renderer));
break;
}
case "codespan": {
out += renderer.codespan(token.text);
break;
}
case "br": {
out += renderer.br();
break;
}
case "del": {
out += renderer.del(this.parseInline(token.tokens, renderer));
break;
}
case "text": {
out += renderer.text(token.text);
break;
}
default: {
const errMsg = 'Token with "' + token.type + '" type was not found.';
if (this.options.silent) {
console.error(errMsg);
return;
} else {
throw new Error(errMsg);
}
}
}
}
return out;
}
};
function marked(src, opt, callback) {
if (typeof src === "undefined" || src === null) {
throw new Error("marked(): input parameter is undefined or null");
}
if (typeof src !== "string") {
throw new Error("marked(): input parameter is of type " + Object.prototype.toString.call(src) + ", string expected");
}
if (typeof opt === "function") {
callback = opt;
opt = null;
}
opt = merge2({}, marked.defaults, opt || {});
checkSanitizeDeprecation(opt);
if (callback) {
const highlight = opt.highlight;
let tokens;
try {
tokens = Lexer.lex(src, opt);
} catch (e) {
return callback(e);
}
const done = function(err) {
let out;
if (!err) {
try {
if (opt.walkTokens) {
marked.walkTokens(tokens, opt.walkTokens);
}
out = Parser.parse(tokens, opt);
} catch (e) {
err = e;
}
}
opt.highlight = highlight;
return err ? callback(err) : callback(null, out);
};
if (!highlight || highlight.length < 3) {
return done();
}
delete opt.highlight;
if (!tokens.length)
return done();
let pending = 0;
marked.walkTokens(tokens, function(token) {
if (token.type === "code") {
pending++;
setTimeout(() => {
highlight(token.text, token.lang, function(err, code) {
if (err) {
return done(err);
}
if (code != null && code !== token.text) {
token.text = code;
token.escaped = true;
}
pending--;
if (pending === 0) {
done();
}
});
}, 0);
}
});
if (pending === 0) {
done();
}
return;
}
try {
const tokens = Lexer.lex(src, opt);
if (opt.walkTokens) {
marked.walkTokens(tokens, opt.walkTokens);
}
return Parser.parse(tokens, opt);
} catch (e) {
e.message += "\nPlease report this to https://github.com/markedjs/marked.";
if (opt.silent) {
return "An error occurred:
" + escape4(e.message + "", true) + "
";
}
throw e;
}
}
marked.options = marked.setOptions = function(opt) {
merge2(marked.defaults, opt);
changeDefaults(marked.defaults);
return marked;
};
marked.getDefaults = getDefaults;
marked.defaults = defaults;
marked.use = function(...args) {
const opts = merge2({}, ...args);
const extensions = marked.defaults.extensions || { renderers: {}, childTokens: {} };
let hasExtensions;
args.forEach((pack) => {
if (pack.extensions) {
hasExtensions = true;
pack.extensions.forEach((ext) => {
if (!ext.name) {
throw new Error("extension name required");
}
if (ext.renderer) {
const prevRenderer = extensions.renderers ? extensions.renderers[ext.name] : null;
if (prevRenderer) {
extensions.renderers[ext.name] = function(...args2) {
let ret = ext.renderer.apply(this, args2);
if (ret === false) {
ret = prevRenderer.apply(this, args2);
}
return ret;
};
} else {
extensions.renderers[ext.name] = ext.renderer;
}
}
if (ext.tokenizer) {
if (!ext.level || ext.level !== "block" && ext.level !== "inline") {
throw new Error("extension level must be 'block' or 'inline'");
}
if (extensions[ext.level]) {
extensions[ext.level].unshift(ext.tokenizer);
} else {
extensions[ext.level] = [ext.tokenizer];
}
if (ext.start) {
if (ext.level === "block") {
if (extensions.startBlock) {
extensions.startBlock.push(ext.start);
} else {
extensions.startBlock = [ext.start];
}
} else if (ext.level === "inline") {
if (extensions.startInline) {
extensions.startInline.push(ext.start);
} else {
extensions.startInline = [ext.start];
}
}
}
}
if (ext.childTokens) {
extensions.childTokens[ext.name] = ext.childTokens;
}
});
}
if (pack.renderer) {
const renderer = marked.defaults.renderer || new Renderer();
for (const prop in pack.renderer) {
const prevRenderer = renderer[prop];
renderer[prop] = (...args2) => {
let ret = pack.renderer[prop].apply(renderer, args2);
if (ret === false) {
ret = prevRenderer.apply(renderer, args2);
}
return ret;
};
}
opts.renderer = renderer;
}
if (pack.tokenizer) {
const tokenizer = marked.defaults.tokenizer || new Tokenizer();
for (const prop in pack.tokenizer) {
const prevTokenizer = tokenizer[prop];
tokenizer[prop] = (...args2) => {
let ret = pack.tokenizer[prop].apply(tokenizer, args2);
if (ret === false) {
ret = prevTokenizer.apply(tokenizer, args2);
}
return ret;
};
}
opts.tokenizer = tokenizer;
}
if (pack.walkTokens) {
const walkTokens2 = marked.defaults.walkTokens;
opts.walkTokens = function(token) {
pack.walkTokens.call(this, token);
if (walkTokens2) {
walkTokens2.call(this, token);
}
};
}
if (hasExtensions) {
opts.extensions = extensions;
}
marked.setOptions(opts);
});
};
marked.walkTokens = function(tokens, callback) {
for (const token of tokens) {
callback.call(marked, token);
switch (token.type) {
case "table": {
for (const cell of token.header) {
marked.walkTokens(cell.tokens, callback);
}
for (const row of token.rows) {
for (const cell of row) {
marked.walkTokens(cell.tokens, callback);
}
}
break;
}
case "list": {
marked.walkTokens(token.items, callback);
break;
}
default: {
if (marked.defaults.extensions && marked.defaults.extensions.childTokens && marked.defaults.extensions.childTokens[token.type]) {
marked.defaults.extensions.childTokens[token.type].forEach(function(childTokens) {
marked.walkTokens(token[childTokens], callback);
});
} else if (token.tokens) {
marked.walkTokens(token.tokens, callback);
}
}
}
}
};
marked.parseInline = function(src, opt) {
if (typeof src === "undefined" || src === null) {
throw new Error("marked.parseInline(): input parameter is undefined or null");
}
if (typeof src !== "string") {
throw new Error("marked.parseInline(): input parameter is of type " + Object.prototype.toString.call(src) + ", string expected");
}
opt = merge2({}, marked.defaults, opt || {});
checkSanitizeDeprecation(opt);
try {
const tokens = Lexer.lexInline(src, opt);
if (opt.walkTokens) {
marked.walkTokens(tokens, opt.walkTokens);
}
return Parser.parseInline(tokens, opt);
} catch (e) {
e.message += "\nPlease report this to https://github.com/markedjs/marked.";
if (opt.silent) {
return "An error occurred:
" + escape4(e.message + "", true) + "
";
}
throw e;
}
};
marked.Parser = Parser;
marked.parser = Parser.parse;
marked.Renderer = Renderer;
marked.TextRenderer = TextRenderer;
marked.Lexer = Lexer;
marked.lexer = Lexer.lex;
marked.Tokenizer = Tokenizer;
marked.Slugger = Slugger;
marked.parse = marked;
var options = marked.options;
var setOptions = marked.setOptions;
var use = marked.use;
var walkTokens = marked.walkTokens;
var parseInline = marked.parseInline;
var parser2 = Parser.parse;
var lexer = Lexer.lex;
// modules/services/osmose.js
var tiler3 = utilTiler();
var dispatch4 = dispatch_default("loaded");
var _tileZoom3 = 14;
var _osmoseUrlRoot = "https://osmose.openstreetmap.fr/api/0.3";
var _osmoseData = { icons: {}, items: [] };
var _cache3;
function abortRequest3(controller) {
if (controller) {
controller.abort();
}
}
function abortUnwantedRequests3(cache, tiles) {
Object.keys(cache.inflightTile).forEach((k) => {
let wanted = tiles.find((tile) => k === tile.id);
if (!wanted) {
abortRequest3(cache.inflightTile[k]);
delete cache.inflightTile[k];
}
});
}
function encodeIssueRtree3(d) {
return { minX: d.loc[0], minY: d.loc[1], maxX: d.loc[0], maxY: d.loc[1], data: d };
}
function updateRtree3(item, replace) {
_cache3.rtree.remove(item, (a, b) => a.data.id === b.data.id);
if (replace) {
_cache3.rtree.insert(item);
}
}
function preventCoincident2(loc) {
let coincident = false;
do {
let delta = coincident ? [1e-5, 0] : [0, 1e-5];
loc = geoVecAdd(loc, delta);
let bbox = geoExtent(loc).bbox();
coincident = _cache3.rtree.search(bbox).length;
} while (coincident);
return loc;
}
var osmose_default = {
title: "osmose",
init() {
_mainFileFetcher.get("qa_data").then((d) => {
_osmoseData = d.osmose;
_osmoseData.items = Object.keys(d.osmose.icons).map((s) => s.split("-")[0]).reduce((unique, item) => unique.indexOf(item) !== -1 ? unique : [...unique, item], []);
});
if (!_cache3) {
this.reset();
}
this.event = utilRebind(this, dispatch4, "on");
},
reset() {
let _strings = {};
let _colors = {};
if (_cache3) {
Object.values(_cache3.inflightTile).forEach(abortRequest3);
_strings = _cache3.strings;
_colors = _cache3.colors;
}
_cache3 = {
data: {},
loadedTile: {},
inflightTile: {},
inflightPost: {},
closed: {},
rtree: new import_rbush3.default(),
strings: _strings,
colors: _colors
};
},
loadIssues(projection2) {
let params = {
item: _osmoseData.items
};
let tiles = tiler3.zoomExtent([_tileZoom3, _tileZoom3]).getTiles(projection2);
abortUnwantedRequests3(_cache3, tiles);
tiles.forEach((tile) => {
if (_cache3.loadedTile[tile.id] || _cache3.inflightTile[tile.id])
return;
let [x, y, z] = tile.xyz;
let url = `${_osmoseUrlRoot}/issues/${z}/${x}/${y}.json?` + utilQsString(params);
let controller = new AbortController();
_cache3.inflightTile[tile.id] = controller;
json_default(url, { signal: controller.signal }).then((data) => {
delete _cache3.inflightTile[tile.id];
_cache3.loadedTile[tile.id] = true;
if (data.features) {
data.features.forEach((issue) => {
const { item, class: cl, uuid: id2 } = issue.properties;
const itemType = `${item}-${cl}`;
if (itemType in _osmoseData.icons) {
let loc = issue.geometry.coordinates;
loc = preventCoincident2(loc);
let d = new QAItem(loc, this, itemType, id2, { item });
if (item === 8300 || item === 8360) {
d.elems = [];
}
_cache3.data[d.id] = d;
_cache3.rtree.insert(encodeIssueRtree3(d));
}
});
}
dispatch4.call("loaded");
}).catch(() => {
delete _cache3.inflightTile[tile.id];
_cache3.loadedTile[tile.id] = true;
});
});
},
loadIssueDetail(issue) {
if (issue.elems !== void 0) {
return Promise.resolve(issue);
}
const url = `${_osmoseUrlRoot}/issue/${issue.id}?langs=${_mainLocalizer.localeCode()}`;
const cacheDetails = (data) => {
issue.elems = data.elems.map((e) => e.type.substring(0, 1) + e.id);
issue.detail = data.subtitle ? marked(data.subtitle.auto) : "";
this.replaceItem(issue);
};
return json_default(url).then(cacheDetails).then(() => issue);
},
loadStrings(locale2 = _mainLocalizer.localeCode()) {
const items = Object.keys(_osmoseData.icons);
if (locale2 in _cache3.strings && Object.keys(_cache3.strings[locale2]).length === items.length) {
return Promise.resolve(_cache3.strings[locale2]);
}
if (!(locale2 in _cache3.strings)) {
_cache3.strings[locale2] = {};
}
const allRequests = items.map((itemType) => {
if (itemType in _cache3.strings[locale2])
return null;
const cacheData = (data) => {
const [cat = { items: [] }] = data.categories;
const [item2 = { class: [] }] = cat.items;
const [cl2 = null] = item2.class;
if (!cl2) {
console.log(`Osmose strings request (${itemType}) had unexpected data`);
return;
}
const { item: itemInt, color: color2 } = item2;
if (/^#[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}/.test(color2)) {
_cache3.colors[itemInt] = color2;
}
const { title, detail, fix, trap } = cl2;
let issueStrings = {};
if (title)
issueStrings.title = title.auto;
if (detail)
issueStrings.detail = marked(detail.auto);
if (trap)
issueStrings.trap = marked(trap.auto);
if (fix)
issueStrings.fix = marked(fix.auto);
_cache3.strings[locale2][itemType] = issueStrings;
};
const [item, cl] = itemType.split("-");
const url = `${_osmoseUrlRoot}/items/${item}/class/${cl}?langs=${locale2}`;
return json_default(url).then(cacheData);
}).filter(Boolean);
return Promise.all(allRequests).then(() => _cache3.strings[locale2]);
},
getStrings(itemType, locale2 = _mainLocalizer.localeCode()) {
return locale2 in _cache3.strings ? _cache3.strings[locale2][itemType] : {};
},
getColor(itemType) {
return itemType in _cache3.colors ? _cache3.colors[itemType] : "#FFFFFF";
},
postUpdate(issue, callback) {
if (_cache3.inflightPost[issue.id]) {
return callback({ message: "Issue update already inflight", status: -2 }, issue);
}
const url = `${_osmoseUrlRoot}/issue/${issue.id}/${issue.newStatus}`;
const controller = new AbortController();
const after = () => {
delete _cache3.inflightPost[issue.id];
this.removeItem(issue);
if (issue.newStatus === "done") {
if (!(issue.item in _cache3.closed)) {
_cache3.closed[issue.item] = 0;
}
_cache3.closed[issue.item] += 1;
}
if (callback)
callback(null, issue);
};
_cache3.inflightPost[issue.id] = controller;
fetch(url, { signal: controller.signal }).then(after).catch((err) => {
delete _cache3.inflightPost[issue.id];
if (callback)
callback(err.message);
});
},
getItems(projection2) {
const viewport = projection2.clipExtent();
const min3 = [viewport[0][0], viewport[1][1]];
const max3 = [viewport[1][0], viewport[0][1]];
const bbox = geoExtent(projection2.invert(min3), projection2.invert(max3)).bbox();
return _cache3.rtree.search(bbox).map((d) => d.data);
},
getError(id2) {
return _cache3.data[id2];
},
getIcon(itemType) {
return _osmoseData.icons[itemType];
},
replaceItem(item) {
if (!(item instanceof QAItem) || !item.id)
return;
_cache3.data[item.id] = item;
updateRtree3(encodeIssueRtree3(item), true);
return item;
},
removeItem(item) {
if (!(item instanceof QAItem) || !item.id)
return;
delete _cache3.data[item.id];
updateRtree3(encodeIssueRtree3(item), false);
},
getClosedCounts() {
return _cache3.closed;
},
itemURL(item) {
return `https://osmose.openstreetmap.fr/en/error/${item.id}`;
}
};
// modules/services/mapillary.js
var import_pbf = __toESM(require_pbf());
var import_rbush4 = __toESM(require_rbush_min());
var import_vector_tile = __toESM(require_vector_tile());
var accessToken = "MLY|4100327730013843|5bb78b81720791946a9a7b956c57b7cf";
var apiUrl = "https://graph.mapillary.com/";
var baseTileUrl = "https://tiles.mapillary.com/maps/vtp";
var mapFeatureTileUrl = `${baseTileUrl}/mly_map_feature_point/2/{z}/{x}/{y}?access_token=${accessToken}`;
var tileUrl = `${baseTileUrl}/mly1_public/2/{z}/{x}/{y}?access_token=${accessToken}`;
var trafficSignTileUrl = `${baseTileUrl}/mly_map_feature_traffic_sign/2/{z}/{x}/{y}?access_token=${accessToken}`;
var viewercss = "mapillary-js/mapillary.css";
var viewerjs = "mapillary-js/mapillary.js";
var minZoom = 14;
var dispatch5 = dispatch_default("change", "loadedImages", "loadedSigns", "loadedMapFeatures", "bearingChanged", "imageChanged");
var _loadViewerPromise;
var _mlyActiveImage;
var _mlyCache;
var _mlyFallback = false;
var _mlyHighlightedDetection;
var _mlyShowFeatureDetections = false;
var _mlyShowSignDetections = false;
var _mlyViewer;
var _mlyViewerFilter = ["all"];
function loadTiles(which, url, maxZoom2, projection2) {
const tiler8 = utilTiler().zoomExtent([minZoom, maxZoom2]).skipNullIsland(true);
const tiles = tiler8.getTiles(projection2);
tiles.forEach(function(tile) {
loadTile(which, url, tile);
});
}
function loadTile(which, url, tile) {
const cache = _mlyCache.requests;
const tileId = `${tile.id}-${which}`;
if (cache.loaded[tileId] || cache.inflight[tileId])
return;
const controller = new AbortController();
cache.inflight[tileId] = controller;
const requestUrl = url.replace("{x}", tile.xyz[0]).replace("{y}", tile.xyz[1]).replace("{z}", tile.xyz[2]);
fetch(requestUrl, { signal: controller.signal }).then(function(response) {
if (!response.ok) {
throw new Error(response.status + " " + response.statusText);
}
cache.loaded[tileId] = true;
delete cache.inflight[tileId];
return response.arrayBuffer();
}).then(function(data) {
if (!data) {
throw new Error("No Data");
}
loadTileDataToCache(data, tile, which);
if (which === "images") {
dispatch5.call("loadedImages");
} else if (which === "signs") {
dispatch5.call("loadedSigns");
} else if (which === "points") {
dispatch5.call("loadedMapFeatures");
}
}).catch(function() {
cache.loaded[tileId] = true;
delete cache.inflight[tileId];
});
}
function loadTileDataToCache(data, tile, which) {
const vectorTile = new import_vector_tile.VectorTile(new import_pbf.default(data));
let features2, cache, layer, i2, feature3, loc, d;
if (vectorTile.layers.hasOwnProperty("image")) {
features2 = [];
cache = _mlyCache.images;
layer = vectorTile.layers.image;
for (i2 = 0; i2 < layer.length; i2++) {
feature3 = layer.feature(i2).toGeoJSON(tile.xyz[0], tile.xyz[1], tile.xyz[2]);
loc = feature3.geometry.coordinates;
d = {
loc,
captured_at: feature3.properties.captured_at,
ca: feature3.properties.compass_angle,
id: feature3.properties.id,
is_pano: feature3.properties.is_pano,
sequence_id: feature3.properties.sequence_id
};
cache.forImageId[d.id] = d;
features2.push({
minX: loc[0],
minY: loc[1],
maxX: loc[0],
maxY: loc[1],
data: d
});
}
if (cache.rtree) {
cache.rtree.load(features2);
}
}
if (vectorTile.layers.hasOwnProperty("sequence")) {
features2 = [];
cache = _mlyCache.sequences;
layer = vectorTile.layers.sequence;
for (i2 = 0; i2 < layer.length; i2++) {
feature3 = layer.feature(i2).toGeoJSON(tile.xyz[0], tile.xyz[1], tile.xyz[2]);
if (cache.lineString[feature3.properties.id]) {
cache.lineString[feature3.properties.id].push(feature3);
} else {
cache.lineString[feature3.properties.id] = [feature3];
}
}
}
if (vectorTile.layers.hasOwnProperty("point")) {
features2 = [];
cache = _mlyCache[which];
layer = vectorTile.layers.point;
for (i2 = 0; i2 < layer.length; i2++) {
feature3 = layer.feature(i2).toGeoJSON(tile.xyz[0], tile.xyz[1], tile.xyz[2]);
loc = feature3.geometry.coordinates;
d = {
loc,
id: feature3.properties.id,
first_seen_at: feature3.properties.first_seen_at,
last_seen_at: feature3.properties.last_seen_at,
value: feature3.properties.value
};
features2.push({
minX: loc[0],
minY: loc[1],
maxX: loc[0],
maxY: loc[1],
data: d
});
}
if (cache.rtree) {
cache.rtree.load(features2);
}
}
if (vectorTile.layers.hasOwnProperty("traffic_sign")) {
features2 = [];
cache = _mlyCache[which];
layer = vectorTile.layers.traffic_sign;
for (i2 = 0; i2 < layer.length; i2++) {
feature3 = layer.feature(i2).toGeoJSON(tile.xyz[0], tile.xyz[1], tile.xyz[2]);
loc = feature3.geometry.coordinates;
d = {
loc,
id: feature3.properties.id,
first_seen_at: feature3.properties.first_seen_at,
last_seen_at: feature3.properties.last_seen_at,
value: feature3.properties.value
};
features2.push({
minX: loc[0],
minY: loc[1],
maxX: loc[0],
maxY: loc[1],
data: d
});
}
if (cache.rtree) {
cache.rtree.load(features2);
}
}
}
function loadData(url) {
return fetch(url).then(function(response) {
if (!response.ok) {
throw new Error(response.status + " " + response.statusText);
}
return response.json();
}).then(function(result) {
if (!result) {
return [];
}
return result.data || [];
});
}
function partitionViewport(projection2) {
const z = geoScaleToZoom(projection2.scale());
const z2 = Math.ceil(z * 2) / 2 + 2.5;
const tiler8 = utilTiler().zoomExtent([z2, z2]);
return tiler8.getTiles(projection2).map(function(tile) {
return tile.extent;
});
}
function searchLimited(limit, projection2, rtree) {
limit = limit || 5;
return partitionViewport(projection2).reduce(function(result, extent) {
const found = rtree.search(extent.bbox()).slice(0, limit).map(function(d) {
return d.data;
});
return found.length ? result.concat(found) : result;
}, []);
}
var mapillary_default = {
init: function() {
if (!_mlyCache) {
this.reset();
}
this.event = utilRebind(this, dispatch5, "on");
},
reset: function() {
if (_mlyCache) {
Object.values(_mlyCache.requests.inflight).forEach(function(request3) {
request3.abort();
});
}
_mlyCache = {
images: { rtree: new import_rbush4.default(), forImageId: {} },
image_detections: { forImageId: {} },
signs: { rtree: new import_rbush4.default() },
points: { rtree: new import_rbush4.default() },
sequences: { rtree: new import_rbush4.default(), lineString: {} },
requests: { loaded: {}, inflight: {} }
};
_mlyActiveImage = null;
},
images: function(projection2) {
const limit = 5;
return searchLimited(limit, projection2, _mlyCache.images.rtree);
},
signs: function(projection2) {
const limit = 5;
return searchLimited(limit, projection2, _mlyCache.signs.rtree);
},
mapFeatures: function(projection2) {
const limit = 5;
return searchLimited(limit, projection2, _mlyCache.points.rtree);
},
cachedImage: function(imageId) {
return _mlyCache.images.forImageId[imageId];
},
sequences: function(projection2) {
const viewport = projection2.clipExtent();
const min3 = [viewport[0][0], viewport[1][1]];
const max3 = [viewport[1][0], viewport[0][1]];
const bbox = geoExtent(projection2.invert(min3), projection2.invert(max3)).bbox();
const sequenceIds = {};
let lineStrings = [];
_mlyCache.images.rtree.search(bbox).forEach(function(d) {
if (d.data.sequence_id) {
sequenceIds[d.data.sequence_id] = true;
}
});
Object.keys(sequenceIds).forEach(function(sequenceId) {
if (_mlyCache.sequences.lineString[sequenceId]) {
lineStrings = lineStrings.concat(_mlyCache.sequences.lineString[sequenceId]);
}
});
return lineStrings;
},
loadImages: function(projection2) {
loadTiles("images", tileUrl, 14, projection2);
},
loadSigns: function(projection2) {
loadTiles("signs", trafficSignTileUrl, 14, projection2);
},
loadMapFeatures: function(projection2) {
loadTiles("points", mapFeatureTileUrl, 14, projection2);
},
ensureViewerLoaded: function(context) {
if (_loadViewerPromise)
return _loadViewerPromise;
const wrap2 = context.container().select(".photoviewer").selectAll(".mly-wrapper").data([0]);
wrap2.enter().append("div").attr("id", "ideditor-mly").attr("class", "photo-wrapper mly-wrapper").classed("hide", true);
const that = this;
_loadViewerPromise = new Promise((resolve, reject) => {
let loadedCount = 0;
function loaded() {
loadedCount += 1;
if (loadedCount === 2)
resolve();
}
const head = select_default2("head");
head.selectAll("#ideditor-mapillary-viewercss").data([0]).enter().append("link").attr("id", "ideditor-mapillary-viewercss").attr("rel", "stylesheet").attr("crossorigin", "anonymous").attr("href", context.asset(viewercss)).on("load.serviceMapillary", loaded).on("error.serviceMapillary", function() {
reject();
});
head.selectAll("#ideditor-mapillary-viewerjs").data([0]).enter().append("script").attr("id", "ideditor-mapillary-viewerjs").attr("crossorigin", "anonymous").attr("src", context.asset(viewerjs)).on("load.serviceMapillary", loaded).on("error.serviceMapillary", function() {
reject();
});
}).catch(function() {
_loadViewerPromise = null;
}).then(function() {
that.initViewer(context);
});
return _loadViewerPromise;
},
loadSignResources: function(context) {
context.ui().svgDefs.addSprites(["mapillary-sprite"], false);
return this;
},
loadObjectResources: function(context) {
context.ui().svgDefs.addSprites(["mapillary-object-sprite"], false);
return this;
},
resetTags: function() {
if (_mlyViewer && !_mlyFallback) {
_mlyViewer.getComponent("tag").removeAll();
}
},
showFeatureDetections: function(value) {
_mlyShowFeatureDetections = value;
if (!_mlyShowFeatureDetections && !_mlyShowSignDetections) {
this.resetTags();
}
},
showSignDetections: function(value) {
_mlyShowSignDetections = value;
if (!_mlyShowFeatureDetections && !_mlyShowSignDetections) {
this.resetTags();
}
},
filterViewer: function(context) {
const showsPano = context.photos().showsPanoramic();
const showsFlat = context.photos().showsFlat();
const fromDate = context.photos().fromDate();
const toDate = context.photos().toDate();
const filter2 = ["all"];
if (!showsPano)
filter2.push(["!=", "cameraType", "spherical"]);
if (!showsFlat && showsPano)
filter2.push(["==", "pano", true]);
if (fromDate) {
filter2.push([">=", "capturedAt", new Date(fromDate).getTime()]);
}
if (toDate) {
filter2.push([">=", "capturedAt", new Date(toDate).getTime()]);
}
if (_mlyViewer) {
_mlyViewer.setFilter(filter2);
}
_mlyViewerFilter = filter2;
return filter2;
},
showViewer: function(context) {
const wrap2 = context.container().select(".photoviewer").classed("hide", false);
const isHidden = wrap2.selectAll(".photo-wrapper.mly-wrapper.hide").size();
if (isHidden && _mlyViewer) {
wrap2.selectAll(".photo-wrapper:not(.mly-wrapper)").classed("hide", true);
wrap2.selectAll(".photo-wrapper.mly-wrapper").classed("hide", false);
_mlyViewer.resize();
}
return this;
},
hideViewer: function(context) {
_mlyActiveImage = null;
if (!_mlyFallback && _mlyViewer) {
_mlyViewer.getComponent("sequence").stop();
}
const viewer = context.container().select(".photoviewer");
if (!viewer.empty())
viewer.datum(null);
viewer.classed("hide", true).selectAll(".photo-wrapper").classed("hide", true);
this.updateUrlImage(null);
dispatch5.call("imageChanged");
dispatch5.call("loadedMapFeatures");
dispatch5.call("loadedSigns");
return this.setStyles(context, null);
},
updateUrlImage: function(imageId) {
if (!window.mocha) {
const hash = utilStringQs(window.location.hash);
if (imageId) {
hash.photo = "mapillary/" + imageId;
} else {
delete hash.photo;
}
window.location.replace("#" + utilQsString(hash, true));
}
},
highlightDetection: function(detection) {
if (detection) {
_mlyHighlightedDetection = detection.id;
}
return this;
},
initViewer: function(context) {
const that = this;
if (!window.mapillary)
return;
const opts = {
accessToken,
component: {
cover: false,
keyboard: false,
tag: true
},
container: "ideditor-mly"
};
if (!mapillary.isSupported() && mapillary.isFallbackSupported()) {
_mlyFallback = true;
opts.component = {
cover: false,
direction: false,
imagePlane: false,
keyboard: false,
mouse: false,
sequence: false,
tag: false,
image: true,
navigation: true
};
}
_mlyViewer = new mapillary.Viewer(opts);
_mlyViewer.on("image", imageChanged);
_mlyViewer.on("bearing", bearingChanged);
if (_mlyViewerFilter) {
_mlyViewer.setFilter(_mlyViewerFilter);
}
context.ui().photoviewer.on("resize.mapillary", function() {
if (_mlyViewer)
_mlyViewer.resize();
});
function imageChanged(node) {
that.resetTags();
const image = node.image;
that.setActiveImage(image);
that.setStyles(context, null);
const loc = [image.originalLngLat.lng, image.originalLngLat.lat];
context.map().centerEase(loc);
that.updateUrlImage(image.id);
if (_mlyShowFeatureDetections || _mlyShowSignDetections) {
that.updateDetections(image.id, `${apiUrl}/${image.id}/detections?access_token=${accessToken}&fields=id,image,geometry,value`);
}
dispatch5.call("imageChanged");
}
function bearingChanged(e) {
dispatch5.call("bearingChanged", void 0, e);
}
},
selectImage: function(context, imageId) {
if (_mlyViewer && imageId) {
_mlyViewer.moveTo(imageId).catch(function(e) {
console.error("mly3", e);
});
}
return this;
},
getActiveImage: function() {
return _mlyActiveImage;
},
getDetections: function(id2) {
return loadData(`${apiUrl}/${id2}/detections?access_token=${accessToken}&fields=id,value,image`);
},
setActiveImage: function(image) {
if (image) {
_mlyActiveImage = {
ca: image.originalCompassAngle,
id: image.id,
loc: [image.originalLngLat.lng, image.originalLngLat.lat],
is_pano: image.cameraType === "spherical",
sequence_id: image.sequenceId
};
} else {
_mlyActiveImage = null;
}
},
setStyles: function(context, hovered) {
const hoveredImageId = hovered && hovered.id;
const hoveredSequenceId = hovered && hovered.sequence_id;
const selectedSequenceId = _mlyActiveImage && _mlyActiveImage.sequence_id;
context.container().selectAll(".layer-mapillary .viewfield-group").classed("highlighted", function(d) {
return d.sequence_id === selectedSequenceId || d.id === hoveredImageId;
}).classed("hovered", function(d) {
return d.id === hoveredImageId;
});
context.container().selectAll(".layer-mapillary .sequence").classed("highlighted", function(d) {
return d.properties.id === hoveredSequenceId;
}).classed("currentView", function(d) {
return d.properties.id === selectedSequenceId;
});
return this;
},
updateDetections: function(imageId, url) {
if (!_mlyViewer || _mlyFallback)
return;
if (!imageId)
return;
const cache = _mlyCache.image_detections;
if (cache.forImageId[imageId]) {
showDetections(_mlyCache.image_detections.forImageId[imageId]);
} else {
loadData(url).then((detections) => {
detections.forEach(function(detection) {
if (!cache.forImageId[imageId]) {
cache.forImageId[imageId] = [];
}
cache.forImageId[imageId].push({
geometry: detection.geometry,
id: detection.id,
image_id: imageId,
value: detection.value
});
});
showDetections(_mlyCache.image_detections.forImageId[imageId] || []);
});
}
function showDetections(detections) {
const tagComponent = _mlyViewer.getComponent("tag");
detections.forEach(function(data) {
const tag = makeTag(data);
if (tag) {
tagComponent.add([tag]);
}
});
}
function makeTag(data) {
const valueParts = data.value.split("--");
if (!valueParts.length)
return;
let tag;
let text2;
let color2 = 16777215;
if (_mlyHighlightedDetection === data.id) {
color2 = 16776960;
text2 = valueParts[1];
if (text2 === "flat" || text2 === "discrete" || text2 === "sign") {
text2 = valueParts[2];
}
text2 = text2.replace(/-/g, " ");
text2 = text2.charAt(0).toUpperCase() + text2.slice(1);
_mlyHighlightedDetection = null;
}
var decodedGeometry = window.atob(data.geometry);
var uintArray = new Uint8Array(decodedGeometry.length);
for (var i2 = 0; i2 < decodedGeometry.length; i2++) {
uintArray[i2] = decodedGeometry.charCodeAt(i2);
}
const tile = new import_vector_tile.VectorTile(new import_pbf.default(uintArray.buffer));
const layer = tile.layers["mpy-or"];
const geometries = layer.feature(0).loadGeometry();
const polygon2 = geometries.map((ring) => ring.map((point) => [point.x / layer.extent, point.y / layer.extent]));
tag = new mapillary.OutlineTag(data.id, new mapillary.PolygonGeometry(polygon2[0]), {
text: text2,
textColor: color2,
lineColor: color2,
lineWidth: 2,
fillColor: color2,
fillOpacity: 0.3
});
return tag;
}
},
cache: function() {
return _mlyCache;
}
};
// modules/core/validation/models.js
function validationIssue(attrs) {
this.type = attrs.type;
this.subtype = attrs.subtype;
this.severity = attrs.severity;
this.message = attrs.message;
this.reference = attrs.reference;
this.entityIds = attrs.entityIds;
this.loc = attrs.loc;
this.data = attrs.data;
this.dynamicFixes = attrs.dynamicFixes;
this.hash = attrs.hash;
this.id = generateID.apply(this);
this.key = generateKey.apply(this);
this.autoFix = null;
function generateID() {
var parts = [this.type];
if (this.hash) {
parts.push(this.hash);
}
if (this.subtype) {
parts.push(this.subtype);
}
if (this.entityIds) {
var entityKeys = this.entityIds.slice().sort();
parts.push.apply(parts, entityKeys);
}
return parts.join(":");
}
function generateKey() {
return this.id + ":" + Date.now().toString();
}
this.extent = function(resolver) {
if (this.loc) {
return geoExtent(this.loc);
}
if (this.entityIds && this.entityIds.length) {
return this.entityIds.reduce(function(extent, entityId) {
return extent.extend(resolver.entity(entityId).extent(resolver));
}, geoExtent());
}
return null;
};
this.fixes = function(context) {
var fixes = this.dynamicFixes ? this.dynamicFixes(context) : [];
var issue = this;
if (issue.severity === "warning") {
fixes.push(new validationIssueFix({
title: _t.html("issues.fix.ignore_issue.title"),
icon: "iD-icon-close",
onClick: function() {
context.validator().ignoreIssue(this.issue.id);
}
}));
}
fixes.forEach(function(fix) {
fix.id = fix.title;
fix.issue = issue;
if (fix.autoArgs) {
issue.autoFix = fix;
}
});
return fixes;
};
}
function validationIssueFix(attrs) {
this.title = attrs.title;
this.onClick = attrs.onClick;
this.disabledReason = attrs.disabledReason;
this.icon = attrs.icon;
this.entityIds = attrs.entityIds || [];
this.autoArgs = attrs.autoArgs;
this.issue = null;
}
// modules/services/maprules.js
var buildRuleChecks = function() {
return {
equals: function(equals) {
return function(tags) {
return Object.keys(equals).every(function(k) {
return equals[k] === tags[k];
});
};
},
notEquals: function(notEquals) {
return function(tags) {
return Object.keys(notEquals).some(function(k) {
return notEquals[k] !== tags[k];
});
};
},
absence: function(absence) {
return function(tags) {
return Object.keys(tags).indexOf(absence) === -1;
};
},
presence: function(presence) {
return function(tags) {
return Object.keys(tags).indexOf(presence) > -1;
};
},
greaterThan: function(greaterThan) {
var key = Object.keys(greaterThan)[0];
var value = greaterThan[key];
return function(tags) {
return tags[key] > value;
};
},
greaterThanEqual: function(greaterThanEqual) {
var key = Object.keys(greaterThanEqual)[0];
var value = greaterThanEqual[key];
return function(tags) {
return tags[key] >= value;
};
},
lessThan: function(lessThan) {
var key = Object.keys(lessThan)[0];
var value = lessThan[key];
return function(tags) {
return tags[key] < value;
};
},
lessThanEqual: function(lessThanEqual) {
var key = Object.keys(lessThanEqual)[0];
var value = lessThanEqual[key];
return function(tags) {
return tags[key] <= value;
};
},
positiveRegex: function(positiveRegex) {
var tagKey = Object.keys(positiveRegex)[0];
var expression = positiveRegex[tagKey].join("|");
var regex = new RegExp(expression);
return function(tags) {
return regex.test(tags[tagKey]);
};
},
negativeRegex: function(negativeRegex) {
var tagKey = Object.keys(negativeRegex)[0];
var expression = negativeRegex[tagKey].join("|");
var regex = new RegExp(expression);
return function(tags) {
return !regex.test(tags[tagKey]);
};
}
};
};
var buildLineKeys = function() {
return {
highway: {
rest_area: true,
services: true
},
railway: {
roundhouse: true,
station: true,
traverser: true,
turntable: true,
wash: true
}
};
};
var maprules_default = {
init: function() {
this._ruleChecks = buildRuleChecks();
this._validationRules = [];
this._areaKeys = osmAreaKeys;
this._lineKeys = buildLineKeys();
},
filterRuleChecks: function(selector) {
var _ruleChecks = this._ruleChecks;
return Object.keys(selector).reduce(function(rules, key) {
if (["geometry", "error", "warning"].indexOf(key) === -1) {
rules.push(_ruleChecks[key](selector[key]));
}
return rules;
}, []);
},
buildTagMap: function(selector) {
var getRegexValues = function(regexes) {
return regexes.map(function(regex) {
return regex.replace(/\$|\^/g, "");
});
};
var tagMap = Object.keys(selector).reduce(function(expectedTags, key) {
var values;
var isRegex = /regex/gi.test(key);
var isEqual = /equals/gi.test(key);
if (isRegex || isEqual) {
Object.keys(selector[key]).forEach(function(selectorKey) {
values = isEqual ? [selector[key][selectorKey]] : getRegexValues(selector[key][selectorKey]);
if (expectedTags.hasOwnProperty(selectorKey)) {
values = values.concat(expectedTags[selectorKey]);
}
expectedTags[selectorKey] = values;
});
} else if (/(greater|less)Than(Equal)?|presence/g.test(key)) {
var tagKey = /presence/.test(key) ? selector[key] : Object.keys(selector[key])[0];
values = [selector[key][tagKey]];
if (expectedTags.hasOwnProperty(tagKey)) {
values = values.concat(expectedTags[tagKey]);
}
expectedTags[tagKey] = values;
}
return expectedTags;
}, {});
return tagMap;
},
inferGeometry: function(tagMap) {
var _lineKeys = this._lineKeys;
var _areaKeys = this._areaKeys;
var keyValueDoesNotImplyArea = function(key2) {
return utilArrayIntersection(tagMap[key2], Object.keys(_areaKeys[key2])).length > 0;
};
var keyValueImpliesLine = function(key2) {
return utilArrayIntersection(tagMap[key2], Object.keys(_lineKeys[key2])).length > 0;
};
if (tagMap.hasOwnProperty("area")) {
if (tagMap.area.indexOf("yes") > -1) {
return "area";
}
if (tagMap.area.indexOf("no") > -1) {
return "line";
}
}
for (var key in tagMap) {
if (key in _areaKeys && !keyValueDoesNotImplyArea(key)) {
return "area";
}
if (key in _lineKeys && keyValueImpliesLine(key)) {
return "area";
}
}
return "line";
},
addRule: function(selector) {
var rule = {
checks: this.filterRuleChecks(selector),
matches: function(entity) {
return this.checks.every(function(check) {
return check(entity.tags);
});
},
inferredGeometry: this.inferGeometry(this.buildTagMap(selector), this._areaKeys),
geometryMatches: function(entity, graph) {
if (entity.type === "node" || entity.type === "relation") {
return selector.geometry === entity.type;
} else if (entity.type === "way") {
return this.inferredGeometry === entity.geometry(graph);
}
},
findIssues: function(entity, graph, issues) {
if (this.geometryMatches(entity, graph) && this.matches(entity)) {
var severity = Object.keys(selector).indexOf("error") > -1 ? "error" : "warning";
var message = selector[severity];
issues.push(new validationIssue({
type: "maprules",
severity,
message: function() {
return message;
},
entityIds: [entity.id]
}));
}
}
};
this._validationRules.push(rule);
},
clearRules: function() {
this._validationRules = [];
},
validationRules: function() {
return this._validationRules;
},
ruleChecks: function() {
return this._ruleChecks;
}
};
// modules/services/nominatim.js
var import_rbush5 = __toESM(require_rbush_min());
var apibase = "https://nominatim.openstreetmap.org/";
var _inflight = {};
var _nominatimCache;
var nominatim_default = {
init: function() {
_inflight = {};
_nominatimCache = new import_rbush5.default();
},
reset: function() {
Object.values(_inflight).forEach(function(controller) {
controller.abort();
});
_inflight = {};
_nominatimCache = new import_rbush5.default();
},
countryCode: function(location, callback) {
this.reverse(location, function(err, result) {
if (err) {
return callback(err);
} else if (result.address) {
return callback(null, result.address.country_code);
} else {
return callback("Unable to geocode", null);
}
});
},
reverse: function(loc, callback) {
var cached = _nominatimCache.search({ minX: loc[0], minY: loc[1], maxX: loc[0], maxY: loc[1] });
if (cached.length > 0) {
if (callback)
callback(null, cached[0].data);
return;
}
var params = { zoom: 13, format: "json", addressdetails: 1, lat: loc[1], lon: loc[0] };
var url = apibase + "reverse?" + utilQsString(params);
if (_inflight[url])
return;
var controller = new AbortController();
_inflight[url] = controller;
json_default(url, { signal: controller.signal }).then(function(result) {
delete _inflight[url];
if (result && result.error) {
throw new Error(result.error);
}
var extent = geoExtent(loc).padByMeters(200);
_nominatimCache.insert(Object.assign(extent.bbox(), { data: result }));
if (callback)
callback(null, result);
}).catch(function(err) {
delete _inflight[url];
if (err.name === "AbortError")
return;
if (callback)
callback(err.message);
});
},
search: function(val, callback) {
var searchVal = encodeURIComponent(val);
var url = apibase + "search/" + searchVal + "?limit=10&format=json";
if (_inflight[url])
return;
var controller = new AbortController();
_inflight[url] = controller;
json_default(url, { signal: controller.signal }).then(function(result) {
delete _inflight[url];
if (result && result.error) {
throw new Error(result.error);
}
if (callback)
callback(null, result);
}).catch(function(err) {
delete _inflight[url];
if (err.name === "AbortError")
return;
if (callback)
callback(err.message);
});
}
};
// node_modules/name-suggestion-index/lib/matcher.js
var import_which_polygon3 = __toESM(require_which_polygon(), 1);
// node_modules/name-suggestion-index/lib/simplify.js
var import_diacritics2 = __toESM(require_diacritics(), 1);
function simplify(str2) {
if (typeof str2 !== "string")
return "";
return import_diacritics2.default.remove(str2.replace(/&/g, "and").replace(/İ/ig, "i").replace(/[\s\-=_!"#%'*{},.\/:;?\(\)\[\]@\\$\^*+<>«»~`’\u00a1\u00a7\u00b6\u00b7\u00bf\u037e\u0387\u055a-\u055f\u0589\u05c0\u05c3\u05c6\u05f3\u05f4\u0609\u060a\u060c\u060d\u061b\u061e\u061f\u066a-\u066d\u06d4\u0700-\u070d\u07f7-\u07f9\u0830-\u083e\u085e\u0964\u0965\u0970\u0af0\u0df4\u0e4f\u0e5a\u0e5b\u0f04-\u0f12\u0f14\u0f85\u0fd0-\u0fd4\u0fd9\u0fda\u104a-\u104f\u10fb\u1360-\u1368\u166d\u166e\u16eb-\u16ed\u1735\u1736\u17d4-\u17d6\u17d8-\u17da\u1800-\u1805\u1807-\u180a\u1944\u1945\u1a1e\u1a1f\u1aa0-\u1aa6\u1aa8-\u1aad\u1b5a-\u1b60\u1bfc-\u1bff\u1c3b-\u1c3f\u1c7e\u1c7f\u1cc0-\u1cc7\u1cd3\u2000-\u206f\u2cf9-\u2cfc\u2cfe\u2cff\u2d70\u2e00-\u2e7f\u3001-\u3003\u303d\u30fb\ua4fe\ua4ff\ua60d-\ua60f\ua673\ua67e\ua6f2-\ua6f7\ua874-\ua877\ua8ce\ua8cf\ua8f8-\ua8fa\ua92e\ua92f\ua95f\ua9c1-\ua9cd\ua9de\ua9df\uaa5c-\uaa5f\uaade\uaadf\uaaf0\uaaf1\uabeb\ufe10-\ufe16\ufe19\ufe30\ufe45\ufe46\ufe49-\ufe4c\ufe50-\ufe52\ufe54-\ufe57\ufe5f-\ufe61\ufe68\ufe6a\ufe6b\ufeff\uff01-\uff03\uff05-\uff07\uff0a\uff0c\uff0e\uff0f\uff1a\uff1b\uff1f\uff20\uff3c\uff61\uff64\uff65]+/g, "").toLowerCase());
}
// node_modules/name-suggestion-index/config/matchGroups.json
var matchGroups = {
adult_gaming_centre: [
"amenity/casino",
"amenity/gambling",
"leisure/adult_gaming_centre"
],
beauty: [
"shop/beauty",
"shop/hairdresser_supply"
],
bed: [
"shop/bed",
"shop/furniture"
],
beverages: [
"shop/alcohol",
"shop/beer",
"shop/beverages",
"shop/wine"
],
camping: [
"tourism/camp_site",
"tourism/caravan_site"
],
car_parts: [
"shop/car_parts",
"shop/car_repair",
"shop/tires",
"shop/tyres"
],
clinic: [
"amenity/clinic",
"amenity/doctors",
"healthcare/clinic",
"healthcare/laboratory",
"healthcare/physiotherapist",
"healthcare/sample_collection",
"healthcare/dialysis"
],
convenience: [
"shop/beauty",
"shop/chemist",
"shop/convenience",
"shop/cosmetics",
"shop/grocery",
"shop/newsagent",
"shop/perfumery"
],
coworking: [
"amenity/coworking_space",
"office/coworking",
"office/coworking_space"
],
dentist: [
"amenity/dentist",
"amenity/doctors",
"healthcare/dentist"
],
electronics: [
"office/telecommunication",
"shop/computer",
"shop/electronics",
"shop/hifi",
"shop/mobile",
"shop/mobile_phone",
"shop/telecommunication"
],
fabric: [
"shop/fabric",
"shop/haberdashery",
"shop/sewing"
],
fashion: [
"shop/accessories",
"shop/bag",
"shop/boutique",
"shop/clothes",
"shop/department_store",
"shop/fashion",
"shop/fashion_accessories",
"shop/sports",
"shop/shoes"
],
financial: [
"amenity/bank",
"office/accountant",
"office/financial",
"office/financial_advisor",
"office/tax_advisor",
"shop/tax"
],
fitness: [
"leisure/fitness_centre",
"leisure/fitness_center",
"leisure/sports_centre",
"leisure/sports_center"
],
food: [
"amenity/bar",
"amenity/cafe",
"amenity/fast_food",
"amenity/ice_cream",
"amenity/pub",
"amenity/restaurant",
"shop/bakery",
"shop/candy",
"shop/chocolate",
"shop/coffee",
"shop/confectionary",
"shop/confectionery",
"shop/food",
"shop/ice_cream",
"shop/pastry",
"shop/tea"
],
fuel: [
"amenity/fuel",
"shop/gas",
"shop/convenience;gas",
"shop/gas;convenience"
],
gift: [
"shop/gift",
"shop/card",
"shop/cards",
"shop/stationery"
],
hardware: [
"shop/bathroom_furnishing",
"shop/carpet",
"shop/diy",
"shop/doityourself",
"shop/doors",
"shop/electrical",
"shop/flooring",
"shop/hardware",
"shop/hardware_store",
"shop/power_tools",
"shop/tool_hire",
"shop/tools",
"shop/trade"
],
health_food: [
"shop/health",
"shop/health_food",
"shop/herbalist",
"shop/nutrition_supplements"
],
hobby: [
"shop/electronics",
"shop/hobby",
"shop/books",
"shop/games",
"shop/collector",
"shop/toys",
"shop/model",
"shop/video_games",
"shop/anime"
],
hospital: [
"amenity/doctors",
"amenity/hospital",
"healthcare/hospital"
],
houseware: [
"shop/houseware",
"shop/interior_decoration"
],
lifeboat_station: [
"amenity/lifeboat_station",
"emergency/lifeboat_station",
"emergency/marine_rescue"
],
lodging: [
"tourism/hotel",
"tourism/motel"
],
money_transfer: [
"amenity/money_transfer",
"shop/money_transfer"
],
office_supplies: [
"shop/office_supplies",
"shop/stationary",
"shop/stationery"
],
outdoor: [
"shop/clothes",
"shop/outdoor",
"shop/sports"
],
parcel_locker: [
"amenity/parcel_locker",
"amenity/vending_machine"
],
pharmacy: [
"amenity/doctors",
"amenity/pharmacy",
"healthcare/pharmacy"
],
playground: [
"amenity/theme_park",
"leisure/amusement_arcade",
"leisure/playground"
],
rental: [
"amenity/bicycle_rental",
"amenity/boat_rental",
"amenity/car_rental",
"amenity/truck_rental",
"amenity/vehicle_rental",
"shop/rental"
],
school: [
"amenity/childcare",
"amenity/college",
"amenity/kindergarten",
"amenity/language_school",
"amenity/prep_school",
"amenity/school",
"amenity/university"
],
storage: [
"shop/storage_units",
"shop/storage_rental"
],
substation: [
"power/station",
"power/substation",
"power/sub_station"
],
supermarket: [
"shop/food",
"shop/frozen_food",
"shop/greengrocer",
"shop/grocery",
"shop/supermarket",
"shop/wholesale"
],
variety_store: [
"shop/variety_store",
"shop/discount",
"shop/convenience"
],
vending: [
"amenity/vending_machine",
"shop/vending_machine"
],
weight_loss: [
"amenity/clinic",
"amenity/doctors",
"amenity/weight_clinic",
"healthcare/counselling",
"leisure/fitness_centre",
"office/therapist",
"shop/beauty",
"shop/diet",
"shop/food",
"shop/health_food",
"shop/herbalist",
"shop/nutrition",
"shop/nutrition_supplements",
"shop/weight_loss"
],
wholesale: [
"shop/wholesale",
"shop/supermarket",
"shop/department_store"
]
};
var matchGroups_default = {
matchGroups
};
// node_modules/name-suggestion-index/config/genericWords.json
var genericWords = [
"^(barn|bazaa?r|bench|bou?tique|building|casa|church)$",
"^(baseball|basketball|football|soccer|softball|tennis(halle)?)\\s?(field|court)?$",
"^(club|green|out|ware)\\s?house$",
"^(driveway|el \xE1rbol|fountain|generic|golf|government|graveyard)$",
"^(fixme|n\\s?\\/?\\s?a|name|no\\s?name|none|null|temporary|test|unknown)$",
"^(hofladen|librairie|magazine?|maison)$",
"^(mobile home|skate)?\\s?park$",
"^(obuwie|pond|pool|sale|shops?|sklep|stores?)$",
"^\\?+$",
"^private$",
"^tattoo( studio)?$",
"^windmill$",
"^\u0446\u0435\u0440\u043A\u043E\u0432\u043D\u0430\u044F( \u043B\u0430\u0432\u043A\u0430)?$"
];
var genericWords_default = {
genericWords
};
// node_modules/name-suggestion-index/config/trees.json
var trees = {
brands: {
emoji: "\u{1F354}",
mainTag: "brand:wikidata",
sourceTags: ["brand", "name"],
nameTags: {
primary: "^(name|name:\\w+)$",
alternate: "^(brand|brand:\\w+|operator|operator:\\w+|\\w+_name|\\w+_name:\\w+)$"
}
},
flags: {
emoji: "\u{1F6A9}",
mainTag: "flag:wikidata",
nameTags: {
primary: "^(flag:name|flag:name:\\w+)$",
alternate: "^(country|country:\\w+|flag|flag:\\w+|subject|subject:\\w+)$"
}
},
operators: {
emoji: "\u{1F4BC}",
mainTag: "operator:wikidata",
sourceTags: ["operator"],
nameTags: {
primary: "^(name|name:\\w+|operator|operator:\\w+)$",
alternate: "^(brand|brand:\\w+|\\w+_name|\\w+_name:\\w+)$"
}
},
transit: {
emoji: "\u{1F687}",
mainTag: "network:wikidata",
sourceTags: ["network"],
nameTags: {
primary: "^network$",
alternate: "^(operator|operator:\\w+|network:\\w+|\\w+_name|\\w+_name:\\w+)$"
}
}
};
var trees_default = {
trees
};
// node_modules/name-suggestion-index/lib/matcher.js
var matchGroups2 = matchGroups_default.matchGroups;
var trees2 = trees_default.trees;
var Matcher = class {
constructor() {
this.matchIndex = void 0;
this.genericWords = /* @__PURE__ */ new Map();
(genericWords_default.genericWords || []).forEach((s) => this.genericWords.set(s, new RegExp(s, "i")));
this.itemLocation = void 0;
this.locationSets = void 0;
this.locationIndex = void 0;
this.warnings = [];
}
buildMatchIndex(data) {
const that = this;
if (that.matchIndex)
return;
that.matchIndex = /* @__PURE__ */ new Map();
const seenTree = /* @__PURE__ */ new Map();
Object.keys(data).forEach((tkv) => {
const category = data[tkv];
const parts = tkv.split("/", 3);
const t = parts[0];
const k = parts[1];
const v = parts[2];
const thiskv = `${k}/${v}`;
const tree = trees2[t];
let branch = that.matchIndex.get(thiskv);
if (!branch) {
branch = {
primary: /* @__PURE__ */ new Map(),
alternate: /* @__PURE__ */ new Map(),
excludeGeneric: /* @__PURE__ */ new Map(),
excludeNamed: /* @__PURE__ */ new Map()
};
that.matchIndex.set(thiskv, branch);
}
const properties = category.properties || {};
const exclude = properties.exclude || {};
(exclude.generic || []).forEach((s) => branch.excludeGeneric.set(s, new RegExp(s, "i")));
(exclude.named || []).forEach((s) => branch.excludeNamed.set(s, new RegExp(s, "i")));
const excludeRegexes = [...branch.excludeGeneric.values(), ...branch.excludeNamed.values()];
let items = category.items;
if (!Array.isArray(items) || !items.length)
return;
const primaryName = new RegExp(tree.nameTags.primary, "i");
const alternateName = new RegExp(tree.nameTags.alternate, "i");
const notName = /:(colou?r|type|forward|backward|left|right|etymology|pronunciation|wikipedia)$/i;
const skipGenericKV = skipGenericKVMatches(t, k, v);
const genericKV = /* @__PURE__ */ new Set([`${k}/yes`, `building/yes`]);
const matchGroupKV = /* @__PURE__ */ new Set();
Object.values(matchGroups2).forEach((matchGroup) => {
const inGroup = matchGroup.some((otherkv) => otherkv === thiskv);
if (!inGroup)
return;
matchGroup.forEach((otherkv) => {
if (otherkv === thiskv)
return;
matchGroupKV.add(otherkv);
const otherk = otherkv.split("/", 2)[0];
genericKV.add(`${otherk}/yes`);
});
});
items.forEach((item) => {
if (!item.id)
return;
if (Array.isArray(item.matchTags) && item.matchTags.length) {
item.matchTags = item.matchTags.filter((matchTag) => !matchGroupKV.has(matchTag) && !genericKV.has(matchTag));
if (!item.matchTags.length)
delete item.matchTags;
}
let kvTags = [`${thiskv}`].concat(item.matchTags || []);
if (!skipGenericKV) {
kvTags = kvTags.concat(Array.from(genericKV));
}
Object.keys(item.tags).forEach((osmkey) => {
if (notName.test(osmkey))
return;
const osmvalue = item.tags[osmkey];
if (!osmvalue || excludeRegexes.some((regex) => regex.test(osmvalue)))
return;
if (primaryName.test(osmkey)) {
kvTags.forEach((kv) => insertName("primary", t, kv, simplify(osmvalue), item.id));
} else if (alternateName.test(osmkey)) {
kvTags.forEach((kv) => insertName("alternate", t, kv, simplify(osmvalue), item.id));
}
});
let keepMatchNames = /* @__PURE__ */ new Set();
(item.matchNames || []).forEach((matchName) => {
const nsimple = simplify(matchName);
kvTags.forEach((kv) => {
const branch2 = that.matchIndex.get(kv);
const primaryLeaf = branch2 && branch2.primary.get(nsimple);
const alternateLeaf = branch2 && branch2.alternate.get(nsimple);
const inPrimary = primaryLeaf && primaryLeaf.has(item.id);
const inAlternate = alternateLeaf && alternateLeaf.has(item.id);
if (!inPrimary && !inAlternate) {
insertName("alternate", t, kv, nsimple, item.id);
keepMatchNames.add(matchName);
}
});
});
if (keepMatchNames.size) {
item.matchNames = Array.from(keepMatchNames);
} else {
delete item.matchNames;
}
});
});
function insertName(which, t, kv, nsimple, itemID) {
if (!nsimple) {
that.warnings.push(`Warning: skipping empty ${which} name for item ${t}/${kv}: ${itemID}`);
return;
}
let branch = that.matchIndex.get(kv);
if (!branch) {
branch = {
primary: /* @__PURE__ */ new Map(),
alternate: /* @__PURE__ */ new Map(),
excludeGeneric: /* @__PURE__ */ new Map(),
excludeNamed: /* @__PURE__ */ new Map()
};
that.matchIndex.set(kv, branch);
}
let leaf = branch[which].get(nsimple);
if (!leaf) {
leaf = /* @__PURE__ */ new Set();
branch[which].set(nsimple, leaf);
}
leaf.add(itemID);
if (!/yes$/.test(kv)) {
const kvnsimple = `${kv}/${nsimple}`;
const existing = seenTree.get(kvnsimple);
if (existing && existing !== t) {
const items = Array.from(leaf);
that.warnings.push(`Duplicate cache key "${kvnsimple}" in trees "${t}" and "${existing}", check items: ${items}`);
return;
}
seenTree.set(kvnsimple, t);
}
}
function skipGenericKVMatches(t, k, v) {
return t === "flags" || t === "transit" || k === "landuse" || v === "atm" || v === "bicycle_parking" || v === "car_sharing" || v === "caravan_site" || v === "charging_station" || v === "dog_park" || v === "parking" || v === "phone" || v === "playground" || v === "post_box" || v === "public_bookcase" || v === "recycling" || v === "vending_machine";
}
}
buildLocationIndex(data, loco) {
const that = this;
if (that.locationIndex)
return;
that.itemLocation = /* @__PURE__ */ new Map();
that.locationSets = /* @__PURE__ */ new Map();
Object.keys(data).forEach((tkv) => {
const items = data[tkv].items;
if (!Array.isArray(items) || !items.length)
return;
items.forEach((item) => {
if (that.itemLocation.has(item.id))
return;
let resolved;
try {
resolved = loco.resolveLocationSet(item.locationSet);
} catch (err) {
console.warn(`buildLocationIndex: ${err.message}`);
}
if (!resolved || !resolved.id)
return;
that.itemLocation.set(item.id, resolved.id);
if (that.locationSets.has(resolved.id))
return;
let feature3 = _cloneDeep2(resolved.feature);
feature3.id = resolved.id;
feature3.properties.id = resolved.id;
if (!feature3.geometry.coordinates.length || !feature3.properties.area) {
console.warn(`buildLocationIndex: locationSet ${resolved.id} for ${item.id} resolves to an empty feature:`);
console.warn(JSON.stringify(feature3));
return;
}
that.locationSets.set(resolved.id, feature3);
});
});
that.locationIndex = (0, import_which_polygon3.default)({ type: "FeatureCollection", features: [...that.locationSets.values()] });
function _cloneDeep2(obj) {
return JSON.parse(JSON.stringify(obj));
}
}
match(k, v, n2, loc) {
const that = this;
if (!that.matchIndex) {
throw new Error("match: matchIndex not built.");
}
let matchLocations;
if (Array.isArray(loc) && that.locationIndex) {
matchLocations = that.locationIndex([loc[0], loc[1], loc[0], loc[1]], true);
}
const nsimple = simplify(n2);
let seen = /* @__PURE__ */ new Set();
let results = [];
gatherResults("primary");
gatherResults("alternate");
if (results.length)
return results;
gatherResults("exclude");
return results.length ? results : null;
function gatherResults(which) {
const kv = `${k}/${v}`;
let didMatch = tryMatch(which, kv);
if (didMatch)
return;
for (let mg in matchGroups2) {
const matchGroup = matchGroups2[mg];
const inGroup = matchGroup.some((otherkv) => otherkv === kv);
if (!inGroup)
continue;
for (let i2 = 0; i2 < matchGroup.length; i2++) {
const otherkv = matchGroup[i2];
if (otherkv === kv)
continue;
didMatch = tryMatch(which, otherkv);
if (didMatch)
return;
}
}
if (which === "exclude") {
const regex = [...that.genericWords.values()].find((regex2) => regex2.test(n2));
if (regex) {
results.push({ match: "excludeGeneric", pattern: String(regex) });
return;
}
}
}
function tryMatch(which, kv) {
const branch = that.matchIndex.get(kv);
if (!branch)
return;
if (which === "exclude") {
let regex = [...branch.excludeNamed.values()].find((regex2) => regex2.test(n2));
if (regex) {
results.push({ match: "excludeNamed", pattern: String(regex), kv });
return;
}
regex = [...branch.excludeGeneric.values()].find((regex2) => regex2.test(n2));
if (regex) {
results.push({ match: "excludeGeneric", pattern: String(regex), kv });
return;
}
return;
}
const leaf = branch[which].get(nsimple);
if (!leaf || !leaf.size)
return;
let hits = Array.from(leaf).map((itemID) => {
let area = Infinity;
if (that.itemLocation && that.locationSets) {
const location = that.locationSets.get(that.itemLocation.get(itemID));
area = location && location.properties.area || Infinity;
}
return { match: which, itemID, area, kv, nsimple };
});
let sortFn = byAreaDescending;
if (matchLocations) {
hits = hits.filter(isValidLocation);
sortFn = byAreaAscending;
}
if (!hits.length)
return;
hits.sort(sortFn).forEach((hit) => {
if (seen.has(hit.itemID))
return;
seen.add(hit.itemID);
results.push(hit);
});
return true;
function isValidLocation(hit) {
if (!that.itemLocation)
return true;
return matchLocations.find((props) => props.id === that.itemLocation.get(hit.itemID));
}
function byAreaAscending(hitA, hitB) {
return hitA.area - hitB.area;
}
function byAreaDescending(hitA, hitB) {
return hitB.area - hitA.area;
}
}
}
getWarnings() {
return this.warnings;
}
};
// modules/services/nsi.js
var import_vparse2 = __toESM(require_vparse());
// modules/core/difference.js
var import_fast_deep_equal3 = __toESM(require_fast_deep_equal());
function coreDifference(base, head) {
var _changes = {};
var _didChange = {};
var _diff = {};
function checkEntityID(id2) {
var h = head.entities[id2];
var b = base.entities[id2];
if (h === b)
return;
if (_changes[id2])
return;
if (!h && b) {
_changes[id2] = { base: b, head: h };
_didChange.deletion = true;
return;
}
if (h && !b) {
_changes[id2] = { base: b, head: h };
_didChange.addition = true;
return;
}
if (h && b) {
if (h.members && b.members && !(0, import_fast_deep_equal3.default)(h.members, b.members)) {
_changes[id2] = { base: b, head: h };
_didChange.geometry = true;
_didChange.properties = true;
return;
}
if (h.loc && b.loc && !geoVecEqual(h.loc, b.loc)) {
_changes[id2] = { base: b, head: h };
_didChange.geometry = true;
}
if (h.nodes && b.nodes && !(0, import_fast_deep_equal3.default)(h.nodes, b.nodes)) {
_changes[id2] = { base: b, head: h };
_didChange.geometry = true;
}
if (h.tags && b.tags && !(0, import_fast_deep_equal3.default)(h.tags, b.tags)) {
_changes[id2] = { base: b, head: h };
_didChange.properties = true;
}
}
}
function load() {
var ids = utilArrayUniq(Object.keys(head.entities).concat(Object.keys(base.entities)));
for (var i2 = 0; i2 < ids.length; i2++) {
checkEntityID(ids[i2]);
}
}
load();
_diff.length = function length() {
return Object.keys(_changes).length;
};
_diff.changes = function changes() {
return _changes;
};
_diff.didChange = _didChange;
_diff.extantIDs = function extantIDs(includeRelMembers) {
var result = /* @__PURE__ */ new Set();
Object.keys(_changes).forEach(function(id2) {
if (_changes[id2].head) {
result.add(id2);
}
var h = _changes[id2].head;
var b = _changes[id2].base;
var entity = h || b;
if (includeRelMembers && entity.type === "relation") {
var mh = h ? h.members.map(function(m) {
return m.id;
}) : [];
var mb = b ? b.members.map(function(m) {
return m.id;
}) : [];
utilArrayUnion(mh, mb).forEach(function(memberID) {
if (head.hasEntity(memberID)) {
result.add(memberID);
}
});
}
});
return Array.from(result);
};
_diff.modified = function modified() {
var result = [];
Object.values(_changes).forEach(function(change) {
if (change.base && change.head) {
result.push(change.head);
}
});
return result;
};
_diff.created = function created() {
var result = [];
Object.values(_changes).forEach(function(change) {
if (!change.base && change.head) {
result.push(change.head);
}
});
return result;
};
_diff.deleted = function deleted() {
var result = [];
Object.values(_changes).forEach(function(change) {
if (change.base && !change.head) {
result.push(change.base);
}
});
return result;
};
_diff.summary = function summary() {
var relevant = {};
var keys = Object.keys(_changes);
for (var i2 = 0; i2 < keys.length; i2++) {
var change = _changes[keys[i2]];
if (change.head && change.head.geometry(head) !== "vertex") {
addEntity(change.head, head, change.base ? "modified" : "created");
} else if (change.base && change.base.geometry(base) !== "vertex") {
addEntity(change.base, base, "deleted");
} else if (change.base && change.head) {
var moved = !(0, import_fast_deep_equal3.default)(change.base.loc, change.head.loc);
var retagged = !(0, import_fast_deep_equal3.default)(change.base.tags, change.head.tags);
if (moved) {
addParents(change.head);
}
if (retagged || moved && change.head.hasInterestingTags()) {
addEntity(change.head, head, "modified");
}
} else if (change.head && change.head.hasInterestingTags()) {
addEntity(change.head, head, "created");
} else if (change.base && change.base.hasInterestingTags()) {
addEntity(change.base, base, "deleted");
}
}
return Object.values(relevant);
function addEntity(entity, graph, changeType) {
relevant[entity.id] = {
entity,
graph,
changeType
};
}
function addParents(entity) {
var parents = head.parentWays(entity);
for (var j2 = parents.length - 1; j2 >= 0; j2--) {
var parent = parents[j2];
if (!(parent.id in relevant)) {
addEntity(parent, head, "modified");
}
}
}
};
_diff.complete = function complete(extent) {
var result = {};
var id2, change;
for (id2 in _changes) {
change = _changes[id2];
var h = change.head;
var b = change.base;
var entity = h || b;
var i2;
if (extent && (!h || !h.intersects(extent, head)) && (!b || !b.intersects(extent, base))) {
continue;
}
result[id2] = h;
if (entity.type === "way") {
var nh = h ? h.nodes : [];
var nb = b ? b.nodes : [];
var diff;
diff = utilArrayDifference(nh, nb);
for (i2 = 0; i2 < diff.length; i2++) {
result[diff[i2]] = head.hasEntity(diff[i2]);
}
diff = utilArrayDifference(nb, nh);
for (i2 = 0; i2 < diff.length; i2++) {
result[diff[i2]] = head.hasEntity(diff[i2]);
}
}
if (entity.type === "relation" && entity.isMultipolygon()) {
var mh = h ? h.members.map(function(m) {
return m.id;
}) : [];
var mb = b ? b.members.map(function(m) {
return m.id;
}) : [];
var ids = utilArrayUnion(mh, mb);
for (i2 = 0; i2 < ids.length; i2++) {
var member = head.hasEntity(ids[i2]);
if (!member)
continue;
if (extent && !member.intersects(extent, head))
continue;
result[ids[i2]] = member;
}
}
addParents(head.parentWays(entity), result);
addParents(head.parentRelations(entity), result);
}
return result;
function addParents(parents, result2) {
for (var i3 = 0; i3 < parents.length; i3++) {
var parent = parents[i3];
if (parent.id in result2)
continue;
result2[parent.id] = parent;
addParents(head.parentRelations(parent), result2);
}
}
};
return _diff;
}
// modules/core/tree.js
var import_rbush6 = __toESM(require_rbush_min());
function coreTree(head) {
var _rtree = new import_rbush6.default();
var _bboxes = {};
var _segmentsRTree = new import_rbush6.default();
var _segmentsBBoxes = {};
var _segmentsByWayId = {};
var tree = {};
function entityBBox(entity) {
var bbox = entity.extent(head).bbox();
bbox.id = entity.id;
_bboxes[entity.id] = bbox;
return bbox;
}
function segmentBBox(segment) {
var extent = segment.extent(head);
if (!extent)
return null;
var bbox = extent.bbox();
bbox.segment = segment;
_segmentsBBoxes[segment.id] = bbox;
return bbox;
}
function removeEntity(entity) {
_rtree.remove(_bboxes[entity.id]);
delete _bboxes[entity.id];
if (_segmentsByWayId[entity.id]) {
_segmentsByWayId[entity.id].forEach(function(segment) {
_segmentsRTree.remove(_segmentsBBoxes[segment.id]);
delete _segmentsBBoxes[segment.id];
});
delete _segmentsByWayId[entity.id];
}
}
function loadEntities(entities) {
_rtree.load(entities.map(entityBBox));
var segments = [];
entities.forEach(function(entity) {
if (entity.segments) {
var entitySegments = entity.segments(head);
_segmentsByWayId[entity.id] = entitySegments;
segments = segments.concat(entitySegments);
}
});
if (segments.length)
_segmentsRTree.load(segments.map(segmentBBox).filter(Boolean));
}
function updateParents(entity, insertions, memo) {
head.parentWays(entity).forEach(function(way) {
if (_bboxes[way.id]) {
removeEntity(way);
insertions[way.id] = way;
}
updateParents(way, insertions, memo);
});
head.parentRelations(entity).forEach(function(relation) {
if (memo[entity.id])
return;
memo[entity.id] = true;
if (_bboxes[relation.id]) {
removeEntity(relation);
insertions[relation.id] = relation;
}
updateParents(relation, insertions, memo);
});
}
tree.rebase = function(entities, force) {
var insertions = {};
for (var i2 = 0; i2 < entities.length; i2++) {
var entity = entities[i2];
if (!entity.visible)
continue;
if (head.entities.hasOwnProperty(entity.id) || _bboxes[entity.id]) {
if (!force) {
continue;
} else if (_bboxes[entity.id]) {
removeEntity(entity);
}
}
insertions[entity.id] = entity;
updateParents(entity, insertions, {});
}
loadEntities(Object.values(insertions));
return tree;
};
function updateToGraph(graph) {
if (graph === head)
return;
var diff = coreDifference(head, graph);
head = graph;
var changed = diff.didChange;
if (!changed.addition && !changed.deletion && !changed.geometry)
return;
var insertions = {};
if (changed.deletion) {
diff.deleted().forEach(function(entity) {
removeEntity(entity);
});
}
if (changed.geometry) {
diff.modified().forEach(function(entity) {
removeEntity(entity);
insertions[entity.id] = entity;
updateParents(entity, insertions, {});
});
}
if (changed.addition) {
diff.created().forEach(function(entity) {
insertions[entity.id] = entity;
});
}
loadEntities(Object.values(insertions));
}
tree.intersects = function(extent, graph) {
updateToGraph(graph);
return _rtree.search(extent.bbox()).map(function(bbox) {
return graph.entity(bbox.id);
});
};
tree.waySegments = function(extent, graph) {
updateToGraph(graph);
return _segmentsRTree.search(extent.bbox()).map(function(bbox) {
return bbox.segment;
});
};
return tree;
}
// modules/svg/icon.js
function svgIcon(name2, svgklass, useklass) {
return function drawIcon(selection2) {
selection2.selectAll("svg.icon" + (svgklass ? "." + svgklass.split(" ")[0] : "")).data([0]).enter().append("svg").attr("class", "icon " + (svgklass || "")).append("use").attr("xlink:href", name2).attr("class", useklass);
};
}
// modules/ui/modal.js
function uiModal(selection2, blocking) {
let keybinding = utilKeybinding("modal");
let previous = selection2.select("div.modal");
let animate = previous.empty();
previous.transition().duration(200).style("opacity", 0).remove();
let shaded = selection2.append("div").attr("class", "shaded").style("opacity", 0);
shaded.close = () => {
shaded.transition().duration(200).style("opacity", 0).remove();
modal.transition().duration(200).style("top", "0px");
select_default2(document).call(keybinding.unbind);
};
let modal = shaded.append("div").attr("class", "modal fillL");
modal.append("input").attr("class", "keytrap keytrap-first").on("focus.keytrap", moveFocusToLast);
if (!blocking) {
shaded.on("click.remove-modal", (d3_event) => {
if (d3_event.target === this) {
shaded.close();
}
});
modal.append("button").attr("class", "close").attr("title", _t("icons.close")).on("click", shaded.close).call(svgIcon("#iD-icon-close"));
keybinding.on("\u232B", shaded.close).on("\u238B", shaded.close);
select_default2(document).call(keybinding);
}
modal.append("div").attr("class", "content");
modal.append("input").attr("class", "keytrap keytrap-last").on("focus.keytrap", moveFocusToFirst);
if (animate) {
shaded.transition().style("opacity", 1);
} else {
shaded.style("opacity", 1);
}
return shaded;
function moveFocusToFirst() {
let node = modal.select("a, button, input:not(.keytrap), select, textarea").node();
if (node) {
node.focus();
} else {
select_default2(this).node().blur();
}
}
function moveFocusToLast() {
let nodes = modal.selectAll("a, button, input:not(.keytrap), select, textarea").nodes();
if (nodes.length) {
nodes[nodes.length - 1].focus();
} else {
select_default2(this).node().blur();
}
}
}
// modules/ui/loading.js
function uiLoading(context) {
let _modalSelection = select_default2(null);
let _message = "";
let _blocking = false;
let loading = (selection2) => {
_modalSelection = uiModal(selection2, _blocking);
let loadertext = _modalSelection.select(".content").classed("loading-modal", true).append("div").attr("class", "modal-section fillL");
loadertext.append("img").attr("class", "loader").attr("src", context.imagePath("loader-white.gif"));
loadertext.append("h3").html(_message);
_modalSelection.select("button.close").attr("class", "hide");
return loading;
};
loading.message = function(val) {
if (!arguments.length)
return _message;
_message = val;
return loading;
};
loading.blocking = function(val) {
if (!arguments.length)
return _blocking;
_blocking = val;
return loading;
};
loading.close = () => {
_modalSelection.remove();
};
loading.isShown = () => {
return _modalSelection && !_modalSelection.empty() && _modalSelection.node().parentNode;
};
return loading;
}
// modules/core/history.js
function coreHistory(context) {
var dispatch10 = dispatch_default("reset", "change", "merge", "restore", "undone", "redone", "storage_error");
var lock = utilSessionMutex("lock");
var _hasUnresolvedRestorableChanges = lock.lock() && !!corePreferences(getKey("saved_history"));
var duration = 150;
var _imageryUsed = [];
var _photoOverlaysUsed = [];
var _checkpoints = {};
var _pausedGraph;
var _stack;
var _index;
var _tree;
function _act(actions, t) {
actions = Array.prototype.slice.call(actions);
var annotation;
if (typeof actions[actions.length - 1] !== "function") {
annotation = actions.pop();
}
var graph = _stack[_index].graph;
for (var i2 = 0; i2 < actions.length; i2++) {
graph = actions[i2](graph, t);
}
return {
graph,
annotation,
imageryUsed: _imageryUsed,
photoOverlaysUsed: _photoOverlaysUsed,
transform: context.projection.transform(),
selectedIDs: context.selectedIDs()
};
}
function _perform(args, t) {
var previous = _stack[_index].graph;
_stack = _stack.slice(0, _index + 1);
var actionResult = _act(args, t);
_stack.push(actionResult);
_index++;
return change(previous);
}
function _replace(args, t) {
var previous = _stack[_index].graph;
var actionResult = _act(args, t);
_stack[_index] = actionResult;
return change(previous);
}
function _overwrite(args, t) {
var previous = _stack[_index].graph;
if (_index > 0) {
_index--;
_stack.pop();
}
_stack = _stack.slice(0, _index + 1);
var actionResult = _act(args, t);
_stack.push(actionResult);
_index++;
return change(previous);
}
function change(previous) {
var difference = coreDifference(previous, history.graph());
if (!_pausedGraph) {
dispatch10.call("change", this, difference);
}
return difference;
}
function getKey(n2) {
return "iD_" + window.location.origin + "_" + n2;
}
var history = {
graph: function() {
return _stack[_index].graph;
},
tree: function() {
return _tree;
},
base: function() {
return _stack[0].graph;
},
merge: function(entities) {
var stack = _stack.map(function(state) {
return state.graph;
});
_stack[0].graph.rebase(entities, stack, false);
_tree.rebase(entities, false);
dispatch10.call("merge", this, entities);
},
perform: function() {
select_default2(document).interrupt("history.perform");
var transitionable = false;
var action0 = arguments[0];
if (arguments.length === 1 || arguments.length === 2 && typeof arguments[1] !== "function") {
transitionable = !!action0.transitionable;
}
if (transitionable) {
var origArguments = arguments;
select_default2(document).transition("history.perform").duration(duration).ease(linear2).tween("history.tween", function() {
return function(t) {
if (t < 1)
_overwrite([action0], t);
};
}).on("start", function() {
_perform([action0], 0);
}).on("end interrupt", function() {
_overwrite(origArguments, 1);
});
} else {
return _perform(arguments);
}
},
replace: function() {
select_default2(document).interrupt("history.perform");
return _replace(arguments, 1);
},
overwrite: function() {
select_default2(document).interrupt("history.perform");
return _overwrite(arguments, 1);
},
pop: function(n2) {
select_default2(document).interrupt("history.perform");
var previous = _stack[_index].graph;
if (isNaN(+n2) || +n2 < 0) {
n2 = 1;
}
while (n2-- > 0 && _index > 0) {
_index--;
_stack.pop();
}
return change(previous);
},
undo: function() {
select_default2(document).interrupt("history.perform");
var previousStack = _stack[_index];
var previous = previousStack.graph;
while (_index > 0) {
_index--;
if (_stack[_index].annotation)
break;
}
dispatch10.call("undone", this, _stack[_index], previousStack);
return change(previous);
},
redo: function() {
select_default2(document).interrupt("history.perform");
var previousStack = _stack[_index];
var previous = previousStack.graph;
var tryIndex = _index;
while (tryIndex < _stack.length - 1) {
tryIndex++;
if (_stack[tryIndex].annotation) {
_index = tryIndex;
dispatch10.call("redone", this, _stack[_index], previousStack);
break;
}
}
return change(previous);
},
pauseChangeDispatch: function() {
if (!_pausedGraph) {
_pausedGraph = _stack[_index].graph;
}
},
resumeChangeDispatch: function() {
if (_pausedGraph) {
var previous = _pausedGraph;
_pausedGraph = null;
return change(previous);
}
},
undoAnnotation: function() {
var i2 = _index;
while (i2 >= 0) {
if (_stack[i2].annotation)
return _stack[i2].annotation;
i2--;
}
},
redoAnnotation: function() {
var i2 = _index + 1;
while (i2 <= _stack.length - 1) {
if (_stack[i2].annotation)
return _stack[i2].annotation;
i2++;
}
},
intersects: function(extent) {
return _tree.intersects(extent, _stack[_index].graph);
},
difference: function() {
var base = _stack[0].graph;
var head = _stack[_index].graph;
return coreDifference(base, head);
},
changes: function(action) {
var base = _stack[0].graph;
var head = _stack[_index].graph;
if (action) {
head = action(head);
}
var difference = coreDifference(base, head);
return {
modified: difference.modified(),
created: difference.created(),
deleted: difference.deleted()
};
},
hasChanges: function() {
return this.difference().length() > 0;
},
imageryUsed: function(sources) {
if (sources) {
_imageryUsed = sources;
return history;
} else {
var s = /* @__PURE__ */ new Set();
_stack.slice(1, _index + 1).forEach(function(state) {
state.imageryUsed.forEach(function(source) {
if (source !== "Custom") {
s.add(source);
}
});
});
return Array.from(s);
}
},
photoOverlaysUsed: function(sources) {
if (sources) {
_photoOverlaysUsed = sources;
return history;
} else {
var s = /* @__PURE__ */ new Set();
_stack.slice(1, _index + 1).forEach(function(state) {
if (state.photoOverlaysUsed && Array.isArray(state.photoOverlaysUsed)) {
state.photoOverlaysUsed.forEach(function(photoOverlay) {
s.add(photoOverlay);
});
}
});
return Array.from(s);
}
},
checkpoint: function(key) {
_checkpoints[key] = {
stack: _stack,
index: _index
};
return history;
},
reset: function(key) {
if (key !== void 0 && _checkpoints.hasOwnProperty(key)) {
_stack = _checkpoints[key].stack;
_index = _checkpoints[key].index;
} else {
_stack = [{ graph: coreGraph() }];
_index = 0;
_tree = coreTree(_stack[0].graph);
_checkpoints = {};
}
dispatch10.call("reset");
dispatch10.call("change");
return history;
},
toIntroGraph: function() {
var nextID = { n: 0, r: 0, w: 0 };
var permIDs = {};
var graph = this.graph();
var baseEntities = {};
Object.values(graph.base().entities).forEach(function(entity) {
var copy2 = copyIntroEntity(entity);
baseEntities[copy2.id] = copy2;
});
Object.keys(graph.entities).forEach(function(id2) {
var entity = graph.entities[id2];
if (entity) {
var copy2 = copyIntroEntity(entity);
baseEntities[copy2.id] = copy2;
} else {
delete baseEntities[id2];
}
});
Object.values(baseEntities).forEach(function(entity) {
if (Array.isArray(entity.nodes)) {
entity.nodes = entity.nodes.map(function(node) {
return permIDs[node] || node;
});
}
if (Array.isArray(entity.members)) {
entity.members = entity.members.map(function(member) {
member.id = permIDs[member.id] || member.id;
return member;
});
}
});
return JSON.stringify({ dataIntroGraph: baseEntities });
function copyIntroEntity(source) {
var copy2 = utilObjectOmit(source, ["type", "user", "v", "version", "visible"]);
if (copy2.tags && !Object.keys(copy2.tags)) {
delete copy2.tags;
}
if (Array.isArray(copy2.loc)) {
copy2.loc[0] = +copy2.loc[0].toFixed(6);
copy2.loc[1] = +copy2.loc[1].toFixed(6);
}
var match = source.id.match(/([nrw])-\d*/);
if (match !== null) {
var nrw = match[1];
var permID;
do {
permID = nrw + ++nextID[nrw];
} while (baseEntities.hasOwnProperty(permID));
copy2.id = permIDs[source.id] = permID;
}
return copy2;
}
},
toJSON: function() {
if (!this.hasChanges())
return;
var allEntities = {};
var baseEntities = {};
var base = _stack[0];
var s = _stack.map(function(i2) {
var modified = [];
var deleted = [];
Object.keys(i2.graph.entities).forEach(function(id2) {
var entity = i2.graph.entities[id2];
if (entity) {
var key = osmEntity.key(entity);
allEntities[key] = entity;
modified.push(key);
} else {
deleted.push(id2);
}
if (id2 in base.graph.entities) {
baseEntities[id2] = base.graph.entities[id2];
}
if (entity && entity.nodes) {
entity.nodes.forEach(function(nodeID) {
if (nodeID in base.graph.entities) {
baseEntities[nodeID] = base.graph.entities[nodeID];
}
});
}
var baseParents = base.graph._parentWays[id2];
if (baseParents) {
baseParents.forEach(function(parentID) {
if (parentID in base.graph.entities) {
baseEntities[parentID] = base.graph.entities[parentID];
}
});
}
});
var x = {};
if (modified.length)
x.modified = modified;
if (deleted.length)
x.deleted = deleted;
if (i2.imageryUsed)
x.imageryUsed = i2.imageryUsed;
if (i2.photoOverlaysUsed)
x.photoOverlaysUsed = i2.photoOverlaysUsed;
if (i2.annotation)
x.annotation = i2.annotation;
if (i2.transform)
x.transform = i2.transform;
if (i2.selectedIDs)
x.selectedIDs = i2.selectedIDs;
return x;
});
return JSON.stringify({
version: 3,
entities: Object.values(allEntities),
baseEntities: Object.values(baseEntities),
stack: s,
nextIDs: osmEntity.id.next,
index: _index,
timestamp: new Date().getTime()
});
},
fromJSON: function(json, loadChildNodes) {
var h = JSON.parse(json);
var loadComplete = true;
osmEntity.id.next = h.nextIDs;
_index = h.index;
if (h.version === 2 || h.version === 3) {
var allEntities = {};
h.entities.forEach(function(entity) {
allEntities[osmEntity.key(entity)] = osmEntity(entity);
});
if (h.version === 3) {
var baseEntities = h.baseEntities.map(function(d) {
return osmEntity(d);
});
var stack = _stack.map(function(state) {
return state.graph;
});
_stack[0].graph.rebase(baseEntities, stack, true);
_tree.rebase(baseEntities, true);
if (loadChildNodes) {
var osm = context.connection();
var baseWays = baseEntities.filter(function(e) {
return e.type === "way";
});
var nodeIDs = baseWays.reduce(function(acc, way) {
return utilArrayUnion(acc, way.nodes);
}, []);
var missing = nodeIDs.filter(function(n2) {
return !_stack[0].graph.hasEntity(n2);
});
if (missing.length && osm) {
loadComplete = false;
context.map().redrawEnable(false);
var loading = uiLoading(context).blocking(true);
context.container().call(loading);
var childNodesLoaded = function(err, result) {
if (!err) {
var visibleGroups = utilArrayGroupBy(result.data, "visible");
var visibles = visibleGroups.true || [];
var invisibles = visibleGroups.false || [];
if (visibles.length) {
var visibleIDs = visibles.map(function(entity) {
return entity.id;
});
var stack2 = _stack.map(function(state) {
return state.graph;
});
missing = utilArrayDifference(missing, visibleIDs);
_stack[0].graph.rebase(visibles, stack2, true);
_tree.rebase(visibles, true);
}
invisibles.forEach(function(entity) {
osm.loadEntityVersion(entity.id, +entity.version - 1, childNodesLoaded);
});
}
if (err || !missing.length) {
loading.close();
context.map().redrawEnable(true);
dispatch10.call("change");
dispatch10.call("restore", this);
}
};
osm.loadMultiple(missing, childNodesLoaded);
}
}
}
_stack = h.stack.map(function(d) {
var entities = {}, entity;
if (d.modified) {
d.modified.forEach(function(key) {
entity = allEntities[key];
entities[entity.id] = entity;
});
}
if (d.deleted) {
d.deleted.forEach(function(id2) {
entities[id2] = void 0;
});
}
return {
graph: coreGraph(_stack[0].graph).load(entities),
annotation: d.annotation,
imageryUsed: d.imageryUsed,
photoOverlaysUsed: d.photoOverlaysUsed,
transform: d.transform,
selectedIDs: d.selectedIDs
};
});
} else {
_stack = h.stack.map(function(d) {
var entities = {};
for (var i2 in d.entities) {
var entity = d.entities[i2];
entities[i2] = entity === "undefined" ? void 0 : osmEntity(entity);
}
d.graph = coreGraph(_stack[0].graph).load(entities);
return d;
});
}
var transform2 = _stack[_index].transform;
if (transform2) {
context.map().transformEase(transform2, 0);
}
if (loadComplete) {
dispatch10.call("change");
dispatch10.call("restore", this);
}
return history;
},
lock: function() {
return lock.lock();
},
unlock: function() {
lock.unlock();
},
save: function() {
if (lock.locked() && !_hasUnresolvedRestorableChanges) {
const success = corePreferences(getKey("saved_history"), history.toJSON() || null);
if (!success)
dispatch10.call("storage_error");
}
return history;
},
clearSaved: function() {
context.debouncedSave.cancel();
if (lock.locked()) {
_hasUnresolvedRestorableChanges = false;
corePreferences(getKey("saved_history"), null);
corePreferences("comment", null);
corePreferences("hashtags", null);
corePreferences("source", null);
}
return history;
},
savedHistoryJSON: function() {
return corePreferences(getKey("saved_history"));
},
hasRestorableChanges: function() {
return _hasUnresolvedRestorableChanges;
},
restore: function() {
if (lock.locked()) {
_hasUnresolvedRestorableChanges = false;
var json = this.savedHistoryJSON();
if (json)
history.fromJSON(json, true);
}
},
_getKey: getKey
};
history.reset();
return utilRebind(history, dispatch10, "on");
}
// modules/validations/index.js
var validations_exports = {};
__export(validations_exports, {
validationAlmostJunction: () => validationAlmostJunction,
validationCloseNodes: () => validationCloseNodes,
validationCrossingWays: () => validationCrossingWays,
validationDisconnectedWay: () => validationDisconnectedWay,
validationFormatting: () => validationFormatting,
validationHelpRequest: () => validationHelpRequest,
validationImpossibleOneway: () => validationImpossibleOneway,
validationIncompatibleSource: () => validationIncompatibleSource,
validationMaprules: () => validationMaprules,
validationMismatchedGeometry: () => validationMismatchedGeometry,
validationMissingRole: () => validationMissingRole,
validationMissingTag: () => validationMissingTag,
validationOutdatedTags: () => validationOutdatedTags,
validationPrivateData: () => validationPrivateData,
validationSuspiciousName: () => validationSuspiciousName,
validationUnsquareWay: () => validationUnsquareWay
});
// modules/validations/almost_junction.js
function validationAlmostJunction(context) {
const type3 = "almost_junction";
const EXTEND_TH_METERS = 5;
const WELD_TH_METERS = 0.75;
const CLOSE_NODE_TH = EXTEND_TH_METERS - WELD_TH_METERS;
const SIG_ANGLE_TH = Math.atan(WELD_TH_METERS / EXTEND_TH_METERS);
function isHighway(entity) {
return entity.type === "way" && osmRoutableHighwayTagValues[entity.tags.highway];
}
function isTaggedAsNotContinuing(node) {
return node.tags.noexit === "yes" || node.tags.amenity === "parking_entrance" || node.tags.entrance && node.tags.entrance !== "no";
}
const validation = function checkAlmostJunction(entity, graph) {
if (!isHighway(entity))
return [];
if (entity.isDegenerate())
return [];
const tree = context.history().tree();
const extendableNodeInfos = findConnectableEndNodesByExtension(entity);
let issues = [];
extendableNodeInfos.forEach((extendableNodeInfo) => {
issues.push(new validationIssue({
type: type3,
subtype: "highway-highway",
severity: "warning",
message: function(context2) {
const entity1 = context2.hasEntity(this.entityIds[0]);
if (this.entityIds[0] === this.entityIds[2]) {
return entity1 ? _t.html("issues.almost_junction.self.message", {
feature: utilDisplayLabel(entity1, context2.graph())
}) : "";
} else {
const entity2 = context2.hasEntity(this.entityIds[2]);
return entity1 && entity2 ? _t.html("issues.almost_junction.message", {
feature: utilDisplayLabel(entity1, context2.graph()),
feature2: utilDisplayLabel(entity2, context2.graph())
}) : "";
}
},
reference: showReference,
entityIds: [
entity.id,
extendableNodeInfo.node.id,
extendableNodeInfo.wid
],
loc: extendableNodeInfo.node.loc,
hash: JSON.stringify(extendableNodeInfo.node.loc),
data: {
midId: extendableNodeInfo.mid.id,
edge: extendableNodeInfo.edge,
cross_loc: extendableNodeInfo.cross_loc
},
dynamicFixes: makeFixes
}));
});
return issues;
function makeFixes(context2) {
let fixes = [new validationIssueFix({
icon: "iD-icon-abutment",
title: _t.html("issues.fix.connect_features.title"),
onClick: function(context3) {
const annotation = _t("issues.fix.connect_almost_junction.annotation");
const [, endNodeId, crossWayId] = this.issue.entityIds;
const midNode = context3.entity(this.issue.data.midId);
const endNode = context3.entity(endNodeId);
const crossWay = context3.entity(crossWayId);
const nearEndNodes = findNearbyEndNodes(endNode, crossWay);
if (nearEndNodes.length > 0) {
const collinear = findSmallJoinAngle(midNode, endNode, nearEndNodes);
if (collinear) {
context3.perform(actionMergeNodes([collinear.id, endNode.id], collinear.loc), annotation);
return;
}
}
const targetEdge = this.issue.data.edge;
const crossLoc = this.issue.data.cross_loc;
const edgeNodes = [context3.entity(targetEdge[0]), context3.entity(targetEdge[1])];
const closestNodeInfo = geoSphericalClosestNode(edgeNodes, crossLoc);
if (closestNodeInfo.distance < WELD_TH_METERS) {
context3.perform(actionMergeNodes([closestNodeInfo.node.id, endNode.id], closestNodeInfo.node.loc), annotation);
} else {
context3.perform(actionAddMidpoint({ loc: crossLoc, edge: targetEdge }, endNode), annotation);
}
}
})];
const node = context2.hasEntity(this.entityIds[1]);
if (node && !node.hasInterestingTags()) {
fixes.push(new validationIssueFix({
icon: "maki-barrier",
title: _t.html("issues.fix.tag_as_disconnected.title"),
onClick: function(context3) {
const nodeID = this.issue.entityIds[1];
const tags = Object.assign({}, context3.entity(nodeID).tags);
tags.noexit = "yes";
context3.perform(actionChangeTags(nodeID, tags), _t("issues.fix.tag_as_disconnected.annotation"));
}
}));
}
return fixes;
}
function showReference(selection2) {
selection2.selectAll(".issue-reference").data([0]).enter().append("div").attr("class", "issue-reference").call(_t.append("issues.almost_junction.highway-highway.reference"));
}
function isExtendableCandidate(node, way) {
const osm = services.osm;
if (osm && !osm.isDataLoaded(node.loc)) {
return false;
}
if (isTaggedAsNotContinuing(node) || graph.parentWays(node).length !== 1) {
return false;
}
let occurrences = 0;
for (const index in way.nodes) {
if (way.nodes[index] === node.id) {
occurrences += 1;
if (occurrences > 1) {
return false;
}
}
}
return true;
}
function findConnectableEndNodesByExtension(way) {
let results = [];
if (way.isClosed())
return results;
let testNodes;
const indices = [0, way.nodes.length - 1];
indices.forEach((nodeIndex) => {
const nodeID = way.nodes[nodeIndex];
const node = graph.entity(nodeID);
if (!isExtendableCandidate(node, way))
return;
const connectionInfo = canConnectByExtend(way, nodeIndex);
if (!connectionInfo)
return;
testNodes = graph.childNodes(way).slice();
testNodes[nodeIndex] = testNodes[nodeIndex].move(connectionInfo.cross_loc);
if (geoHasSelfIntersections(testNodes, nodeID))
return;
results.push(connectionInfo);
});
return results;
}
function findNearbyEndNodes(node, way) {
return [
way.nodes[0],
way.nodes[way.nodes.length - 1]
].map((d) => graph.entity(d)).filter((d) => {
return d.id !== node.id && geoSphericalDistance(node.loc, d.loc) <= CLOSE_NODE_TH;
});
}
function findSmallJoinAngle(midNode, tipNode, endNodes) {
let joinTo;
let minAngle = Infinity;
endNodes.forEach((endNode) => {
const a1 = geoAngle(midNode, tipNode, context.projection) + Math.PI;
const a2 = geoAngle(midNode, endNode, context.projection) + Math.PI;
const diff = Math.max(a1, a2) - Math.min(a1, a2);
if (diff < minAngle) {
joinTo = endNode;
minAngle = diff;
}
});
if (minAngle <= SIG_ANGLE_TH)
return joinTo;
return null;
}
function hasTag(tags, key) {
return tags[key] !== void 0 && tags[key] !== "no";
}
function canConnectWays(way, way2) {
if (way.id === way2.id)
return true;
if ((hasTag(way.tags, "bridge") || hasTag(way2.tags, "bridge")) && !(hasTag(way.tags, "bridge") && hasTag(way2.tags, "bridge")))
return false;
if ((hasTag(way.tags, "tunnel") || hasTag(way2.tags, "tunnel")) && !(hasTag(way.tags, "tunnel") && hasTag(way2.tags, "tunnel")))
return false;
const layer1 = way.tags.layer || "0", layer2 = way2.tags.layer || "0";
if (layer1 !== layer2)
return false;
const level1 = way.tags.level || "0", level2 = way2.tags.level || "0";
if (level1 !== level2)
return false;
return true;
}
function canConnectByExtend(way, endNodeIdx) {
const tipNid = way.nodes[endNodeIdx];
const midNid = endNodeIdx === 0 ? way.nodes[1] : way.nodes[way.nodes.length - 2];
const tipNode = graph.entity(tipNid);
const midNode = graph.entity(midNid);
const lon = tipNode.loc[0];
const lat = tipNode.loc[1];
const lon_range = geoMetersToLon(EXTEND_TH_METERS, lat) / 2;
const lat_range = geoMetersToLat(EXTEND_TH_METERS) / 2;
const queryExtent = geoExtent([
[lon - lon_range, lat - lat_range],
[lon + lon_range, lat + lat_range]
]);
const edgeLen = geoSphericalDistance(midNode.loc, tipNode.loc);
const t = EXTEND_TH_METERS / edgeLen + 1;
const extTipLoc = geoVecInterp(midNode.loc, tipNode.loc, t);
const segmentInfos = tree.waySegments(queryExtent, graph);
for (let i2 = 0; i2 < segmentInfos.length; i2++) {
let segmentInfo = segmentInfos[i2];
let way2 = graph.entity(segmentInfo.wayId);
if (!isHighway(way2))
continue;
if (!canConnectWays(way, way2))
continue;
let nAid = segmentInfo.nodes[0], nBid = segmentInfo.nodes[1];
if (nAid === tipNid || nBid === tipNid)
continue;
let nA = graph.entity(nAid), nB = graph.entity(nBid);
let crossLoc = geoLineIntersection([tipNode.loc, extTipLoc], [nA.loc, nB.loc]);
if (crossLoc) {
return {
mid: midNode,
node: tipNode,
wid: way2.id,
edge: [nA.id, nB.id],
cross_loc: crossLoc
};
}
}
return null;
}
};
validation.type = type3;
return validation;
}
// modules/validations/close_nodes.js
function validationCloseNodes(context) {
var type3 = "close_nodes";
var pointThresholdMeters = 0.2;
var validation = function(entity, graph) {
if (entity.type === "node") {
return getIssuesForNode(entity);
} else if (entity.type === "way") {
return getIssuesForWay(entity);
}
return [];
function getIssuesForNode(node) {
var parentWays = graph.parentWays(node);
if (parentWays.length) {
return getIssuesForVertex(node, parentWays);
} else {
return getIssuesForDetachedPoint(node);
}
}
function wayTypeFor(way) {
if (way.tags.boundary && way.tags.boundary !== "no")
return "boundary";
if (way.tags.indoor && way.tags.indoor !== "no")
return "indoor";
if (way.tags.building && way.tags.building !== "no" || way.tags["building:part"] && way.tags["building:part"] !== "no")
return "building";
if (osmPathHighwayTagValues[way.tags.highway])
return "path";
var parentRelations = graph.parentRelations(way);
for (var i2 in parentRelations) {
var relation = parentRelations[i2];
if (relation.tags.type === "boundary")
return "boundary";
if (relation.isMultipolygon()) {
if (relation.tags.indoor && relation.tags.indoor !== "no")
return "indoor";
if (relation.tags.building && relation.tags.building !== "no" || relation.tags["building:part"] && relation.tags["building:part"] !== "no")
return "building";
}
}
return "other";
}
function shouldCheckWay(way) {
if (way.nodes.length <= 2 || way.isClosed() && way.nodes.length <= 4)
return false;
var bbox = way.extent(graph).bbox();
var hypotenuseMeters = geoSphericalDistance([bbox.minX, bbox.minY], [bbox.maxX, bbox.maxY]);
if (hypotenuseMeters < 1.5)
return false;
return true;
}
function getIssuesForWay(way) {
if (!shouldCheckWay(way))
return [];
var issues = [], nodes = graph.childNodes(way);
for (var i2 = 0; i2 < nodes.length - 1; i2++) {
var node1 = nodes[i2];
var node2 = nodes[i2 + 1];
var issue = getWayIssueIfAny(node1, node2, way);
if (issue)
issues.push(issue);
}
return issues;
}
function getIssuesForVertex(node, parentWays) {
var issues = [];
function checkForCloseness(node1, node2, way) {
var issue = getWayIssueIfAny(node1, node2, way);
if (issue)
issues.push(issue);
}
for (var i2 = 0; i2 < parentWays.length; i2++) {
var parentWay = parentWays[i2];
if (!shouldCheckWay(parentWay))
continue;
var lastIndex = parentWay.nodes.length - 1;
for (var j2 = 0; j2 < parentWay.nodes.length; j2++) {
if (j2 !== 0) {
if (parentWay.nodes[j2 - 1] === node.id) {
checkForCloseness(node, graph.entity(parentWay.nodes[j2]), parentWay);
}
}
if (j2 !== lastIndex) {
if (parentWay.nodes[j2 + 1] === node.id) {
checkForCloseness(graph.entity(parentWay.nodes[j2]), node, parentWay);
}
}
}
}
return issues;
}
function thresholdMetersForWay(way) {
if (!shouldCheckWay(way))
return 0;
var wayType = wayTypeFor(way);
if (wayType === "boundary")
return 0;
if (wayType === "indoor")
return 0.01;
if (wayType === "building")
return 0.05;
if (wayType === "path")
return 0.1;
return 0.2;
}
function getIssuesForDetachedPoint(node) {
var issues = [];
var lon = node.loc[0];
var lat = node.loc[1];
var lon_range = geoMetersToLon(pointThresholdMeters, lat) / 2;
var lat_range = geoMetersToLat(pointThresholdMeters) / 2;
var queryExtent = geoExtent([
[lon - lon_range, lat - lat_range],
[lon + lon_range, lat + lat_range]
]);
var intersected = context.history().tree().intersects(queryExtent, graph);
for (var j2 = 0; j2 < intersected.length; j2++) {
var nearby = intersected[j2];
if (nearby.id === node.id)
continue;
if (nearby.type !== "node" || nearby.geometry(graph) !== "point")
continue;
if (nearby.loc === node.loc || geoSphericalDistance(node.loc, nearby.loc) < pointThresholdMeters) {
var zAxisKeys = { layer: true, level: true, "addr:housenumber": true, "addr:unit": true };
var zAxisDifferentiates = false;
for (var key in zAxisKeys) {
var nodeValue = node.tags[key] || "0";
var nearbyValue = nearby.tags[key] || "0";
if (nodeValue !== nearbyValue) {
zAxisDifferentiates = true;
break;
}
}
if (zAxisDifferentiates)
continue;
issues.push(new validationIssue({
type: type3,
subtype: "detached",
severity: "warning",
message: function(context2) {
var entity2 = context2.hasEntity(this.entityIds[0]), entity22 = context2.hasEntity(this.entityIds[1]);
return entity2 && entity22 ? _t.html("issues.close_nodes.detached.message", {
feature: utilDisplayLabel(entity2, context2.graph()),
feature2: utilDisplayLabel(entity22, context2.graph())
}) : "";
},
reference: showReference,
entityIds: [node.id, nearby.id],
dynamicFixes: function() {
return [
new validationIssueFix({
icon: "iD-operation-disconnect",
title: _t.html("issues.fix.move_points_apart.title")
}),
new validationIssueFix({
icon: "iD-icon-layers",
title: _t.html("issues.fix.use_different_layers_or_levels.title")
})
];
}
}));
}
}
return issues;
function showReference(selection2) {
var referenceText = _t("issues.close_nodes.detached.reference");
selection2.selectAll(".issue-reference").data([0]).enter().append("div").attr("class", "issue-reference").html(referenceText);
}
}
function getWayIssueIfAny(node1, node2, way) {
if (node1.id === node2.id || node1.hasInterestingTags() && node2.hasInterestingTags()) {
return null;
}
if (node1.loc !== node2.loc) {
var parentWays1 = graph.parentWays(node1);
var parentWays2 = new Set(graph.parentWays(node2));
var sharedWays = parentWays1.filter(function(parentWay) {
return parentWays2.has(parentWay);
});
var thresholds = sharedWays.map(function(parentWay) {
return thresholdMetersForWay(parentWay);
});
var threshold = Math.min(...thresholds);
var distance = geoSphericalDistance(node1.loc, node2.loc);
if (distance > threshold)
return null;
}
return new validationIssue({
type: type3,
subtype: "vertices",
severity: "warning",
message: function(context2) {
var entity2 = context2.hasEntity(this.entityIds[0]);
return entity2 ? _t.html("issues.close_nodes.message", { way: utilDisplayLabel(entity2, context2.graph()) }) : "";
},
reference: showReference,
entityIds: [way.id, node1.id, node2.id],
loc: node1.loc,
dynamicFixes: function() {
return [
new validationIssueFix({
icon: "iD-icon-plus",
title: _t.html("issues.fix.merge_points.title"),
onClick: function(context2) {
var entityIds = this.issue.entityIds;
var action = actionMergeNodes([entityIds[1], entityIds[2]]);
context2.perform(action, _t("issues.fix.merge_close_vertices.annotation"));
}
}),
new validationIssueFix({
icon: "iD-operation-disconnect",
title: _t.html("issues.fix.move_points_apart.title")
})
];
}
});
function showReference(selection2) {
var referenceText = _t("issues.close_nodes.reference");
selection2.selectAll(".issue-reference").data([0]).enter().append("div").attr("class", "issue-reference").html(referenceText);
}
}
};
validation.type = type3;
return validation;
}
// modules/validations/crossing_ways.js
function validationCrossingWays(context) {
var type3 = "crossing_ways";
function getFeatureWithFeatureTypeTagsForWay(way, graph) {
if (getFeatureType(way, graph) === null) {
var parentRels = graph.parentRelations(way);
for (var i2 = 0; i2 < parentRels.length; i2++) {
var rel = parentRels[i2];
if (getFeatureType(rel, graph) !== null) {
return rel;
}
}
}
return way;
}
function hasTag(tags, key) {
return tags[key] !== void 0 && tags[key] !== "no";
}
function taggedAsIndoor(tags) {
return hasTag(tags, "indoor") || hasTag(tags, "level") || tags.highway === "corridor";
}
function allowsBridge(featureType) {
return featureType === "highway" || featureType === "railway" || featureType === "waterway";
}
function allowsTunnel(featureType) {
return featureType === "highway" || featureType === "railway" || featureType === "waterway";
}
var ignoredBuildings = {
demolished: true,
dismantled: true,
proposed: true,
razed: true
};
function getFeatureType(entity, graph) {
var geometry = entity.geometry(graph);
if (geometry !== "line" && geometry !== "area")
return null;
var tags = entity.tags;
if (hasTag(tags, "building") && !ignoredBuildings[tags.building])
return "building";
if (hasTag(tags, "highway") && osmRoutableHighwayTagValues[tags.highway])
return "highway";
if (geometry !== "line")
return null;
if (hasTag(tags, "railway") && osmRailwayTrackTagValues[tags.railway])
return "railway";
if (hasTag(tags, "waterway") && osmFlowingWaterwayTagValues[tags.waterway])
return "waterway";
return null;
}
function isLegitCrossing(tags1, featureType1, tags2, featureType2) {
var level1 = tags1.level || "0";
var level2 = tags2.level || "0";
if (taggedAsIndoor(tags1) && taggedAsIndoor(tags2) && level1 !== level2) {
return true;
}
var layer1 = tags1.layer || "0";
var layer2 = tags2.layer || "0";
if (allowsBridge(featureType1) && allowsBridge(featureType2)) {
if (hasTag(tags1, "bridge") && !hasTag(tags2, "bridge"))
return true;
if (!hasTag(tags1, "bridge") && hasTag(tags2, "bridge"))
return true;
if (hasTag(tags1, "bridge") && hasTag(tags2, "bridge") && layer1 !== layer2)
return true;
} else if (allowsBridge(featureType1) && hasTag(tags1, "bridge"))
return true;
else if (allowsBridge(featureType2) && hasTag(tags2, "bridge"))
return true;
if (allowsTunnel(featureType1) && allowsTunnel(featureType2)) {
if (hasTag(tags1, "tunnel") && !hasTag(tags2, "tunnel"))
return true;
if (!hasTag(tags1, "tunnel") && hasTag(tags2, "tunnel"))
return true;
if (hasTag(tags1, "tunnel") && hasTag(tags2, "tunnel") && layer1 !== layer2)
return true;
} else if (allowsTunnel(featureType1) && hasTag(tags1, "tunnel"))
return true;
else if (allowsTunnel(featureType2) && hasTag(tags2, "tunnel"))
return true;
if (featureType1 === "waterway" && featureType2 === "highway" && tags2.man_made === "pier")
return true;
if (featureType2 === "waterway" && featureType1 === "highway" && tags1.man_made === "pier")
return true;
if (featureType1 === "building" || featureType2 === "building" || taggedAsIndoor(tags1) || taggedAsIndoor(tags2)) {
if (layer1 !== layer2)
return true;
}
return false;
}
var highwaysDisallowingFords = {
motorway: true,
motorway_link: true,
trunk: true,
trunk_link: true,
primary: true,
primary_link: true,
secondary: true,
secondary_link: true
};
var nonCrossingHighways = { track: true };
function tagsForConnectionNodeIfAllowed(entity1, entity2, graph) {
var featureType1 = getFeatureType(entity1, graph);
var featureType2 = getFeatureType(entity2, graph);
var geometry1 = entity1.geometry(graph);
var geometry2 = entity2.geometry(graph);
var bothLines = geometry1 === "line" && geometry2 === "line";
if (featureType1 === featureType2) {
if (featureType1 === "highway") {
var entity1IsPath = osmPathHighwayTagValues[entity1.tags.highway];
var entity2IsPath = osmPathHighwayTagValues[entity2.tags.highway];
if ((entity1IsPath || entity2IsPath) && entity1IsPath !== entity2IsPath) {
var roadFeature = entity1IsPath ? entity2 : entity1;
if (nonCrossingHighways[roadFeature.tags.highway]) {
return {};
}
var pathFeature = entity1IsPath ? entity1 : entity2;
if (["marked", "unmarked"].indexOf(pathFeature.tags.crossing) !== -1) {
return bothLines ? { highway: "crossing", crossing: pathFeature.tags.crossing } : {};
}
return bothLines ? { highway: "crossing" } : {};
}
return {};
}
if (featureType1 === "waterway")
return {};
if (featureType1 === "railway")
return {};
} else {
var featureTypes = [featureType1, featureType2];
if (featureTypes.indexOf("highway") !== -1) {
if (featureTypes.indexOf("railway") !== -1) {
if (!bothLines)
return {};
var isTram = entity1.tags.railway === "tram" || entity2.tags.railway === "tram";
if (osmPathHighwayTagValues[entity1.tags.highway] || osmPathHighwayTagValues[entity2.tags.highway]) {
if (isTram)
return { railway: "tram_crossing" };
return { railway: "crossing" };
} else {
if (isTram)
return { railway: "tram_level_crossing" };
return { railway: "level_crossing" };
}
}
if (featureTypes.indexOf("waterway") !== -1) {
if (hasTag(entity1.tags, "tunnel") && hasTag(entity2.tags, "tunnel"))
return null;
if (hasTag(entity1.tags, "bridge") && hasTag(entity2.tags, "bridge"))
return null;
if (highwaysDisallowingFords[entity1.tags.highway] || highwaysDisallowingFords[entity2.tags.highway]) {
return null;
}
return bothLines ? { ford: "yes" } : {};
}
}
}
return null;
}
function findCrossingsByWay(way1, graph, tree) {
var edgeCrossInfos = [];
if (way1.type !== "way")
return edgeCrossInfos;
var taggedFeature1 = getFeatureWithFeatureTypeTagsForWay(way1, graph);
var way1FeatureType = getFeatureType(taggedFeature1, graph);
if (way1FeatureType === null)
return edgeCrossInfos;
var checkedSingleCrossingWays = {};
var i2, j2;
var extent;
var n1, n2, nA, nB, nAId, nBId;
var segment1, segment2;
var oneOnly;
var segmentInfos, segment2Info, way2, taggedFeature2, way2FeatureType;
var way1Nodes = graph.childNodes(way1);
var comparedWays = {};
for (i2 = 0; i2 < way1Nodes.length - 1; i2++) {
n1 = way1Nodes[i2];
n2 = way1Nodes[i2 + 1];
extent = geoExtent([
[
Math.min(n1.loc[0], n2.loc[0]),
Math.min(n1.loc[1], n2.loc[1])
],
[
Math.max(n1.loc[0], n2.loc[0]),
Math.max(n1.loc[1], n2.loc[1])
]
]);
segmentInfos = tree.waySegments(extent, graph);
for (j2 = 0; j2 < segmentInfos.length; j2++) {
segment2Info = segmentInfos[j2];
if (segment2Info.wayId === way1.id)
continue;
if (checkedSingleCrossingWays[segment2Info.wayId])
continue;
comparedWays[segment2Info.wayId] = true;
way2 = graph.hasEntity(segment2Info.wayId);
if (!way2)
continue;
taggedFeature2 = getFeatureWithFeatureTypeTagsForWay(way2, graph);
way2FeatureType = getFeatureType(taggedFeature2, graph);
if (way2FeatureType === null || isLegitCrossing(taggedFeature1.tags, way1FeatureType, taggedFeature2.tags, way2FeatureType)) {
continue;
}
oneOnly = way1FeatureType === "building" || way2FeatureType === "building";
nAId = segment2Info.nodes[0];
nBId = segment2Info.nodes[1];
if (nAId === n1.id || nAId === n2.id || nBId === n1.id || nBId === n2.id) {
continue;
}
nA = graph.hasEntity(nAId);
if (!nA)
continue;
nB = graph.hasEntity(nBId);
if (!nB)
continue;
segment1 = [n1.loc, n2.loc];
segment2 = [nA.loc, nB.loc];
var point = geoLineIntersection(segment1, segment2);
if (point) {
edgeCrossInfos.push({
wayInfos: [
{
way: way1,
featureType: way1FeatureType,
edge: [n1.id, n2.id]
},
{
way: way2,
featureType: way2FeatureType,
edge: [nA.id, nB.id]
}
],
crossPoint: point
});
if (oneOnly) {
checkedSingleCrossingWays[way2.id] = true;
break;
}
}
}
}
return edgeCrossInfos;
}
function waysToCheck(entity, graph) {
var featureType = getFeatureType(entity, graph);
if (!featureType)
return [];
if (entity.type === "way") {
return [entity];
} else if (entity.type === "relation") {
return entity.members.reduce(function(array2, member) {
if (member.type === "way" && (!member.role || member.role === "outer" || member.role === "inner")) {
var entity2 = graph.hasEntity(member.id);
if (entity2 && array2.indexOf(entity2) === -1) {
array2.push(entity2);
}
}
return array2;
}, []);
}
return [];
}
var validation = function checkCrossingWays(entity, graph) {
var tree = context.history().tree();
var ways = waysToCheck(entity, graph);
var issues = [];
var wayIndex, crossingIndex, crossings;
for (wayIndex in ways) {
crossings = findCrossingsByWay(ways[wayIndex], graph, tree);
for (crossingIndex in crossings) {
issues.push(createIssue(crossings[crossingIndex], graph));
}
}
return issues;
};
function createIssue(crossing, graph) {
crossing.wayInfos.sort(function(way1Info, way2Info) {
var type1 = way1Info.featureType;
var type22 = way2Info.featureType;
if (type1 === type22) {
return utilDisplayLabel(way1Info.way, graph) > utilDisplayLabel(way2Info.way, graph);
} else if (type1 === "waterway") {
return true;
} else if (type22 === "waterway") {
return false;
}
return type1 < type22;
});
var entities = crossing.wayInfos.map(function(wayInfo) {
return getFeatureWithFeatureTypeTagsForWay(wayInfo.way, graph);
});
var edges = [crossing.wayInfos[0].edge, crossing.wayInfos[1].edge];
var featureTypes = [crossing.wayInfos[0].featureType, crossing.wayInfos[1].featureType];
var connectionTags = tagsForConnectionNodeIfAllowed(entities[0], entities[1], graph);
var featureType1 = crossing.wayInfos[0].featureType;
var featureType2 = crossing.wayInfos[1].featureType;
var isCrossingIndoors = taggedAsIndoor(entities[0].tags) && taggedAsIndoor(entities[1].tags);
var isCrossingTunnels = allowsTunnel(featureType1) && hasTag(entities[0].tags, "tunnel") && allowsTunnel(featureType2) && hasTag(entities[1].tags, "tunnel");
var isCrossingBridges = allowsBridge(featureType1) && hasTag(entities[0].tags, "bridge") && allowsBridge(featureType2) && hasTag(entities[1].tags, "bridge");
var subtype = [featureType1, featureType2].sort().join("-");
var crossingTypeID = subtype;
if (isCrossingIndoors) {
crossingTypeID = "indoor-indoor";
} else if (isCrossingTunnels) {
crossingTypeID = "tunnel-tunnel";
} else if (isCrossingBridges) {
crossingTypeID = "bridge-bridge";
}
if (connectionTags && (isCrossingIndoors || isCrossingTunnels || isCrossingBridges)) {
crossingTypeID += "_connectable";
}
var uniqueID = crossing.crossPoint[0].toFixed(4) + "," + crossing.crossPoint[1].toFixed(4);
return new validationIssue({
type: type3,
subtype,
severity: "warning",
message: function(context2) {
var graph2 = context2.graph();
var entity1 = graph2.hasEntity(this.entityIds[0]), entity2 = graph2.hasEntity(this.entityIds[1]);
return entity1 && entity2 ? _t.html("issues.crossing_ways.message", {
feature: utilDisplayLabel(entity1, graph2),
feature2: utilDisplayLabel(entity2, graph2)
}) : "";
},
reference: showReference,
entityIds: entities.map(function(entity) {
return entity.id;
}),
data: {
edges,
featureTypes,
connectionTags
},
hash: uniqueID,
loc: crossing.crossPoint,
dynamicFixes: function(context2) {
var mode = context2.mode();
if (!mode || mode.id !== "select" || mode.selectedIDs().length !== 1)
return [];
var selectedIndex = this.entityIds[0] === mode.selectedIDs()[0] ? 0 : 1;
var selectedFeatureType = this.data.featureTypes[selectedIndex];
var otherFeatureType = this.data.featureTypes[selectedIndex === 0 ? 1 : 0];
var fixes = [];
if (connectionTags) {
fixes.push(makeConnectWaysFix(this.data.connectionTags));
}
if (isCrossingIndoors) {
fixes.push(new validationIssueFix({
icon: "iD-icon-layers",
title: _t.html("issues.fix.use_different_levels.title")
}));
} else if (isCrossingTunnels || isCrossingBridges || featureType1 === "building" || featureType2 === "building") {
fixes.push(makeChangeLayerFix("higher"));
fixes.push(makeChangeLayerFix("lower"));
} else if (context2.graph().geometry(this.entityIds[0]) === "line" && context2.graph().geometry(this.entityIds[1]) === "line") {
if (allowsBridge(selectedFeatureType) && selectedFeatureType !== "waterway") {
fixes.push(makeAddBridgeOrTunnelFix("add_a_bridge", "temaki-bridge", "bridge"));
}
var skipTunnelFix = otherFeatureType === "waterway" && selectedFeatureType !== "waterway";
if (allowsTunnel(selectedFeatureType) && !skipTunnelFix) {
fixes.push(makeAddBridgeOrTunnelFix("add_a_tunnel", "temaki-tunnel", "tunnel"));
}
}
fixes.push(new validationIssueFix({
icon: "iD-operation-move",
title: _t.html("issues.fix.reposition_features.title")
}));
return fixes;
}
});
function showReference(selection2) {
selection2.selectAll(".issue-reference").data([0]).enter().append("div").attr("class", "issue-reference").call(_t.append("issues.crossing_ways." + crossingTypeID + ".reference"));
}
}
function makeAddBridgeOrTunnelFix(fixTitleID, iconName, bridgeOrTunnel) {
return new validationIssueFix({
icon: iconName,
title: _t.html("issues.fix." + fixTitleID + ".title"),
onClick: function(context2) {
var mode = context2.mode();
if (!mode || mode.id !== "select")
return;
var selectedIDs = mode.selectedIDs();
if (selectedIDs.length !== 1)
return;
var selectedWayID = selectedIDs[0];
if (!context2.hasEntity(selectedWayID))
return;
var resultWayIDs = [selectedWayID];
var edge, crossedEdge, crossedWayID;
if (this.issue.entityIds[0] === selectedWayID) {
edge = this.issue.data.edges[0];
crossedEdge = this.issue.data.edges[1];
crossedWayID = this.issue.entityIds[1];
} else {
edge = this.issue.data.edges[1];
crossedEdge = this.issue.data.edges[0];
crossedWayID = this.issue.entityIds[0];
}
var crossingLoc = this.issue.loc;
var projection2 = context2.projection;
var action = function actionAddStructure(graph) {
var edgeNodes = [graph.entity(edge[0]), graph.entity(edge[1])];
var crossedWay = graph.hasEntity(crossedWayID);
var structLengthMeters = crossedWay && crossedWay.tags.width && parseFloat(crossedWay.tags.width);
if (!structLengthMeters) {
structLengthMeters = crossedWay && crossedWay.impliedLineWidthMeters();
}
if (structLengthMeters) {
if (getFeatureType(crossedWay, graph) === "railway") {
structLengthMeters *= 2;
}
} else {
structLengthMeters = 8;
}
var a1 = geoAngle(edgeNodes[0], edgeNodes[1], projection2) + Math.PI;
var a2 = geoAngle(graph.entity(crossedEdge[0]), graph.entity(crossedEdge[1]), projection2) + Math.PI;
var crossingAngle = Math.max(a1, a2) - Math.min(a1, a2);
if (crossingAngle > Math.PI)
crossingAngle -= Math.PI;
structLengthMeters = structLengthMeters / 2 / Math.sin(crossingAngle) * 2;
structLengthMeters += 4;
structLengthMeters = Math.min(Math.max(structLengthMeters, 4), 50);
function geomToProj(geoPoint) {
return [
geoLonToMeters(geoPoint[0], geoPoint[1]),
geoLatToMeters(geoPoint[1])
];
}
function projToGeom(projPoint) {
var lat = geoMetersToLat(projPoint[1]);
return [
geoMetersToLon(projPoint[0], lat),
lat
];
}
var projEdgeNode1 = geomToProj(edgeNodes[0].loc);
var projEdgeNode2 = geomToProj(edgeNodes[1].loc);
var projectedAngle = geoVecAngle(projEdgeNode1, projEdgeNode2);
var projectedCrossingLoc = geomToProj(crossingLoc);
var linearToSphericalMetersRatio = geoVecLength(projEdgeNode1, projEdgeNode2) / geoSphericalDistance(edgeNodes[0].loc, edgeNodes[1].loc);
function locSphericalDistanceFromCrossingLoc(angle2, distanceMeters) {
var lengthSphericalMeters = distanceMeters * linearToSphericalMetersRatio;
return projToGeom([
projectedCrossingLoc[0] + Math.cos(angle2) * lengthSphericalMeters,
projectedCrossingLoc[1] + Math.sin(angle2) * lengthSphericalMeters
]);
}
var endpointLocGetter1 = function(lengthMeters) {
return locSphericalDistanceFromCrossingLoc(projectedAngle, lengthMeters);
};
var endpointLocGetter2 = function(lengthMeters) {
return locSphericalDistanceFromCrossingLoc(projectedAngle + Math.PI, lengthMeters);
};
var minEdgeLengthMeters = 0.55;
function determineEndpoint(edge2, endNode, locGetter) {
var newNode;
var idealLengthMeters = structLengthMeters / 2;
var crossingToEdgeEndDistance = geoSphericalDistance(crossingLoc, endNode.loc);
if (crossingToEdgeEndDistance - idealLengthMeters > minEdgeLengthMeters) {
var idealNodeLoc = locGetter(idealLengthMeters);
newNode = osmNode();
graph = actionAddMidpoint({ loc: idealNodeLoc, edge: edge2 }, newNode)(graph);
} else {
var edgeCount = 0;
endNode.parentIntersectionWays(graph).forEach(function(way) {
way.nodes.forEach(function(nodeID) {
if (nodeID === endNode.id) {
if (endNode.id === way.first() && endNode.id !== way.last() || endNode.id === way.last() && endNode.id !== way.first()) {
edgeCount += 1;
} else {
edgeCount += 2;
}
}
});
});
if (edgeCount >= 3) {
var insetLength = crossingToEdgeEndDistance - minEdgeLengthMeters;
if (insetLength > minEdgeLengthMeters) {
var insetNodeLoc = locGetter(insetLength);
newNode = osmNode();
graph = actionAddMidpoint({ loc: insetNodeLoc, edge: edge2 }, newNode)(graph);
}
}
}
if (!newNode)
newNode = endNode;
var splitAction = actionSplit([newNode.id]).limitWays(resultWayIDs);
graph = splitAction(graph);
if (splitAction.getCreatedWayIDs().length) {
resultWayIDs.push(splitAction.getCreatedWayIDs()[0]);
}
return newNode;
}
var structEndNode1 = determineEndpoint(edge, edgeNodes[1], endpointLocGetter1);
var structEndNode2 = determineEndpoint([edgeNodes[0].id, structEndNode1.id], edgeNodes[0], endpointLocGetter2);
var structureWay = resultWayIDs.map(function(id2) {
return graph.entity(id2);
}).find(function(way) {
return way.nodes.indexOf(structEndNode1.id) !== -1 && way.nodes.indexOf(structEndNode2.id) !== -1;
});
var tags = Object.assign({}, structureWay.tags);
if (bridgeOrTunnel === "bridge") {
tags.bridge = "yes";
tags.layer = "1";
} else {
var tunnelValue = "yes";
if (getFeatureType(structureWay, graph) === "waterway") {
tunnelValue = "culvert";
}
tags.tunnel = tunnelValue;
tags.layer = "-1";
}
graph = actionChangeTags(structureWay.id, tags)(graph);
return graph;
};
context2.perform(action, _t("issues.fix." + fixTitleID + ".annotation"));
context2.enter(modeSelect(context2, resultWayIDs));
}
});
}
function makeConnectWaysFix(connectionTags) {
var fixTitleID = "connect_features";
if (connectionTags.ford) {
fixTitleID = "connect_using_ford";
}
return new validationIssueFix({
icon: "iD-icon-crossing",
title: _t.html("issues.fix." + fixTitleID + ".title"),
onClick: function(context2) {
var loc = this.issue.loc;
var connectionTags2 = this.issue.data.connectionTags;
var edges = this.issue.data.edges;
context2.perform(function actionConnectCrossingWays(graph) {
var node = osmNode({ loc, tags: connectionTags2 });
graph = graph.replace(node);
var nodesToMerge = [node.id];
var mergeThresholdInMeters = 0.75;
edges.forEach(function(edge) {
var edgeNodes = [graph.entity(edge[0]), graph.entity(edge[1])];
var nearby = geoSphericalClosestNode(edgeNodes, loc);
if ((!nearby.node.hasInterestingTags() || nearby.node.isCrossing()) && nearby.distance < mergeThresholdInMeters) {
nodesToMerge.push(nearby.node.id);
} else {
graph = actionAddMidpoint({ loc, edge }, node)(graph);
}
});
if (nodesToMerge.length > 1) {
graph = actionMergeNodes(nodesToMerge, loc)(graph);
}
return graph;
}, _t("issues.fix.connect_crossing_features.annotation"));
}
});
}
function makeChangeLayerFix(higherOrLower) {
return new validationIssueFix({
icon: "iD-icon-" + (higherOrLower === "higher" ? "up" : "down"),
title: _t.html("issues.fix.tag_this_as_" + higherOrLower + ".title"),
onClick: function(context2) {
var mode = context2.mode();
if (!mode || mode.id !== "select")
return;
var selectedIDs = mode.selectedIDs();
if (selectedIDs.length !== 1)
return;
var selectedID = selectedIDs[0];
if (!this.issue.entityIds.some(function(entityId) {
return entityId === selectedID;
}))
return;
var entity = context2.hasEntity(selectedID);
if (!entity)
return;
var tags = Object.assign({}, entity.tags);
var layer = tags.layer && Number(tags.layer);
if (layer && !isNaN(layer)) {
if (higherOrLower === "higher") {
layer += 1;
} else {
layer -= 1;
}
} else {
if (higherOrLower === "higher") {
layer = 1;
} else {
layer = -1;
}
}
tags.layer = layer.toString();
context2.perform(actionChangeTags(entity.id, tags), _t("operations.change_tags.annotation"));
}
});
}
validation.type = type3;
return validation;
}
// modules/behavior/draw_way.js
function behaviorDrawWay(context, wayID, mode, startGraph) {
const keybinding = utilKeybinding("drawWay");
var dispatch10 = dispatch_default("rejectedSelfIntersection");
var behavior = behaviorDraw(context);
var _nodeIndex;
var _origWay;
var _wayGeometry;
var _headNodeID;
var _annotation;
var _pointerHasMoved = false;
var _drawNode;
var _didResolveTempEdit = false;
function createDrawNode(loc) {
_drawNode = osmNode({ loc });
context.pauseChangeDispatch();
context.replace(function actionAddDrawNode(graph) {
var way = graph.entity(wayID);
return graph.replace(_drawNode).replace(way.addNode(_drawNode.id, _nodeIndex));
}, _annotation);
context.resumeChangeDispatch();
setActiveElements();
}
function removeDrawNode() {
context.pauseChangeDispatch();
context.replace(function actionDeleteDrawNode(graph) {
var way = graph.entity(wayID);
return graph.replace(way.removeNode(_drawNode.id)).remove(_drawNode);
}, _annotation);
_drawNode = void 0;
context.resumeChangeDispatch();
}
function keydown(d3_event) {
if (d3_event.keyCode === utilKeybinding.modifierCodes.alt) {
if (context.surface().classed("nope")) {
context.surface().classed("nope-suppressed", true);
}
context.surface().classed("nope", false).classed("nope-disabled", true);
}
}
function keyup(d3_event) {
if (d3_event.keyCode === utilKeybinding.modifierCodes.alt) {
if (context.surface().classed("nope-suppressed")) {
context.surface().classed("nope", true);
}
context.surface().classed("nope-suppressed", false).classed("nope-disabled", false);
}
}
function allowsVertex(d) {
return d.geometry(context.graph()) === "vertex" || _mainPresetIndex.allowsVertex(d, context.graph());
}
function move(d3_event, datum2) {
var loc = context.map().mouseCoordinates();
if (!_drawNode)
createDrawNode(loc);
context.surface().classed("nope-disabled", d3_event.altKey);
var targetLoc = datum2 && datum2.properties && datum2.properties.entity && allowsVertex(datum2.properties.entity) && datum2.properties.entity.loc;
var targetNodes = datum2 && datum2.properties && datum2.properties.nodes;
if (targetLoc) {
loc = targetLoc;
} else if (targetNodes) {
var choice = geoChooseEdge(targetNodes, context.map().mouse(), context.projection, _drawNode.id);
if (choice) {
loc = choice.loc;
}
}
context.replace(actionMoveNode(_drawNode.id, loc), _annotation);
_drawNode = context.entity(_drawNode.id);
checkGeometry(true);
}
function checkGeometry(includeDrawNode) {
var nopeDisabled = context.surface().classed("nope-disabled");
var isInvalid = isInvalidGeometry(includeDrawNode);
if (nopeDisabled) {
context.surface().classed("nope", false).classed("nope-suppressed", isInvalid);
} else {
context.surface().classed("nope", isInvalid).classed("nope-suppressed", false);
}
}
function isInvalidGeometry(includeDrawNode) {
var testNode = _drawNode;
var parentWay = context.graph().entity(wayID);
var nodes = context.graph().childNodes(parentWay).slice();
if (includeDrawNode) {
if (parentWay.isClosed()) {
nodes.pop();
}
} else {
if (parentWay.isClosed()) {
if (nodes.length < 3)
return false;
if (_drawNode)
nodes.splice(-2, 1);
testNode = nodes[nodes.length - 2];
} else {
return false;
}
}
return testNode && geoHasSelfIntersections(nodes, testNode.id);
}
function undone() {
_didResolveTempEdit = true;
context.pauseChangeDispatch();
var nextMode;
if (context.graph() === startGraph) {
nextMode = modeSelect(context, [wayID]);
} else {
context.pop(1);
nextMode = mode;
}
context.perform(actionNoop());
context.pop(1);
context.resumeChangeDispatch();
context.enter(nextMode);
}
function setActiveElements() {
if (!_drawNode)
return;
context.surface().selectAll("." + _drawNode.id).classed("active", true);
}
function resetToStartGraph() {
while (context.graph() !== startGraph) {
context.pop();
}
}
var drawWay = function(surface) {
_drawNode = void 0;
_didResolveTempEdit = false;
_origWay = context.entity(wayID);
if (typeof _nodeIndex === "number") {
_headNodeID = _origWay.nodes[_nodeIndex];
} else if (_origWay.isClosed()) {
_headNodeID = _origWay.nodes[_origWay.nodes.length - 2];
} else {
_headNodeID = _origWay.nodes[_origWay.nodes.length - 1];
}
_wayGeometry = _origWay.geometry(context.graph());
_annotation = _t((_origWay.nodes.length === (_origWay.isClosed() ? 2 : 1) ? "operations.start.annotation." : "operations.continue.annotation.") + _wayGeometry);
_pointerHasMoved = false;
context.pauseChangeDispatch();
context.perform(actionNoop(), _annotation);
context.resumeChangeDispatch();
behavior.hover().initialNodeID(_headNodeID);
behavior.on("move", function() {
_pointerHasMoved = true;
move.apply(this, arguments);
}).on("down", function() {
move.apply(this, arguments);
}).on("downcancel", function() {
if (_drawNode)
removeDrawNode();
}).on("click", drawWay.add).on("clickWay", drawWay.addWay).on("clickNode", drawWay.addNode).on("undo", context.undo).on("cancel", drawWay.cancel).on("finish", drawWay.finish);
select_default2(window).on("keydown.drawWay", keydown).on("keyup.drawWay", keyup);
context.map().dblclickZoomEnable(false).on("drawn.draw", setActiveElements);
setActiveElements();
surface.call(behavior);
context.history().on("undone.draw", undone);
};
drawWay.off = function(surface) {
if (!_didResolveTempEdit) {
context.pauseChangeDispatch();
resetToStartGraph();
context.resumeChangeDispatch();
}
_drawNode = void 0;
_nodeIndex = void 0;
context.map().on("drawn.draw", null);
surface.call(behavior.off).selectAll(".active").classed("active", false);
surface.classed("nope", false).classed("nope-suppressed", false).classed("nope-disabled", false);
select_default2(window).on("keydown.drawWay", null).on("keyup.drawWay", null);
context.history().on("undone.draw", null);
};
function attemptAdd(d, loc, doAdd) {
if (_drawNode) {
context.replace(actionMoveNode(_drawNode.id, loc), _annotation);
_drawNode = context.entity(_drawNode.id);
} else {
createDrawNode(loc);
}
checkGeometry(true);
if (d && d.properties && d.properties.nope || context.surface().classed("nope")) {
if (!_pointerHasMoved) {
removeDrawNode();
}
dispatch10.call("rejectedSelfIntersection", this);
return;
}
context.pauseChangeDispatch();
doAdd();
_didResolveTempEdit = true;
context.resumeChangeDispatch();
context.enter(mode);
}
drawWay.add = function(loc, d) {
attemptAdd(d, loc, function() {
});
};
drawWay.addWay = function(loc, edge, d) {
attemptAdd(d, loc, function() {
context.replace(actionAddMidpoint({ loc, edge }, _drawNode), _annotation);
});
};
drawWay.addNode = function(node, d) {
if (node.id === _headNodeID || _origWay.isClosed() && node.id === _origWay.first()) {
drawWay.finish();
return;
}
attemptAdd(d, node.loc, function() {
context.replace(function actionReplaceDrawNode(graph) {
graph = graph.replace(graph.entity(wayID).removeNode(_drawNode.id)).remove(_drawNode);
return graph.replace(graph.entity(wayID).addNode(node.id, _nodeIndex));
}, _annotation);
});
};
function getFeatureType(ways) {
if (ways.every((way) => way.isClosed()))
return "area";
if (ways.every((way) => !way.isClosed()))
return "line";
return "generic";
}
function followMode() {
if (_didResolveTempEdit)
return;
try {
const isDrawingArea = _origWay.nodes[0] === _origWay.nodes.slice(-1)[0];
const [secondLastNodeId, lastNodeId] = _origWay.nodes.slice(isDrawingArea ? -3 : -2);
const historyGraph = context.history().graph();
if (!lastNodeId || !secondLastNodeId || !historyGraph.hasEntity(lastNodeId) || !historyGraph.hasEntity(secondLastNodeId)) {
context.ui().flash.duration(4e3).iconName("#iD-icon-no").label(_t.html("operations.follow.error.needs_more_initial_nodes"))();
return;
}
const lastNodesParents = historyGraph.parentWays(historyGraph.entity(lastNodeId)).filter((w) => w.id !== wayID);
const secondLastNodesParents = historyGraph.parentWays(historyGraph.entity(secondLastNodeId)).filter((w) => w.id !== wayID);
const featureType = getFeatureType(lastNodesParents);
if (lastNodesParents.length !== 1 || secondLastNodesParents.length === 0) {
context.ui().flash.duration(4e3).iconName("#iD-icon-no").label(_t.html(`operations.follow.error.intersection_of_multiple_ways.${featureType}`))();
return;
}
if (!secondLastNodesParents.some((n2) => n2.id === lastNodesParents[0].id)) {
context.ui().flash.duration(4e3).iconName("#iD-icon-no").label(_t.html(`operations.follow.error.intersection_of_different_ways.${featureType}`))();
return;
}
const way = lastNodesParents[0];
const indexOfLast = way.nodes.indexOf(lastNodeId);
const indexOfSecondLast = way.nodes.indexOf(secondLastNodeId);
const isDescendingPastZero = indexOfLast === way.nodes.length - 2 && indexOfSecondLast === 0;
let nextNodeIndex = indexOfLast + (indexOfLast > indexOfSecondLast && !isDescendingPastZero ? 1 : -1);
if (nextNodeIndex === -1)
nextNodeIndex = indexOfSecondLast === 1 ? way.nodes.length - 2 : 1;
const nextNode = historyGraph.entity(way.nodes[nextNodeIndex]);
drawWay.addNode(nextNode, {
geometry: { type: "Point", coordinates: nextNode.loc },
id: nextNode.id,
properties: { target: true, entity: nextNode }
});
} catch (ex) {
context.ui().flash.duration(4e3).iconName("#iD-icon-no").label(_t.html("operations.follow.error.unknown"))();
}
}
keybinding.on(_t("operations.follow.key"), followMode);
select_default2(document).call(keybinding);
drawWay.finish = function() {
checkGeometry(false);
if (context.surface().classed("nope")) {
dispatch10.call("rejectedSelfIntersection", this);
return;
}
context.pauseChangeDispatch();
context.pop(1);
_didResolveTempEdit = true;
context.resumeChangeDispatch();
var way = context.hasEntity(wayID);
if (!way || way.isDegenerate()) {
drawWay.cancel();
return;
}
window.setTimeout(function() {
context.map().dblclickZoomEnable(true);
}, 1e3);
var isNewFeature = !mode.isContinuing;
context.enter(modeSelect(context, [wayID]).newFeature(isNewFeature));
};
drawWay.cancel = function() {
context.pauseChangeDispatch();
resetToStartGraph();
context.resumeChangeDispatch();
window.setTimeout(function() {
context.map().dblclickZoomEnable(true);
}, 1e3);
context.surface().classed("nope", false).classed("nope-disabled", false).classed("nope-suppressed", false);
context.enter(modeBrowse(context));
};
drawWay.nodeIndex = function(val) {
if (!arguments.length)
return _nodeIndex;
_nodeIndex = val;
return drawWay;
};
drawWay.activeID = function() {
if (!arguments.length)
return _drawNode && _drawNode.id;
return drawWay;
};
return utilRebind(drawWay, dispatch10, "on");
}
// modules/modes/draw_line.js
function modeDrawLine(context, wayID, startGraph, button, affix, continuing) {
var mode = {
button,
id: "draw-line"
};
var behavior = behaviorDrawWay(context, wayID, mode, startGraph).on("rejectedSelfIntersection.modeDrawLine", function() {
context.ui().flash.iconName("#iD-icon-no").label(_t.html("self_intersection.error.lines"))();
});
mode.wayID = wayID;
mode.isContinuing = continuing;
mode.enter = function() {
behavior.nodeIndex(affix === "prefix" ? 0 : void 0);
context.install(behavior);
};
mode.exit = function() {
context.uninstall(behavior);
};
mode.selectedIDs = function() {
return [wayID];
};
mode.activeID = function() {
return behavior && behavior.activeID() || [];
};
return mode;
}
// modules/validations/disconnected_way.js
function validationDisconnectedWay() {
var type3 = "disconnected_way";
function isTaggedAsHighway(entity) {
return osmRoutableHighwayTagValues[entity.tags.highway];
}
var validation = function checkDisconnectedWay(entity, graph) {
var routingIslandWays = routingIslandForEntity(entity);
if (!routingIslandWays)
return [];
return [new validationIssue({
type: type3,
subtype: "highway",
severity: "warning",
message: function(context) {
var entity2 = this.entityIds.length && context.hasEntity(this.entityIds[0]);
var label = entity2 && utilDisplayLabel(entity2, context.graph());
return _t.html("issues.disconnected_way.routable.message", { count: this.entityIds.length, highway: label });
},
reference: showReference,
entityIds: Array.from(routingIslandWays).map(function(way) {
return way.id;
}),
dynamicFixes: makeFixes
})];
function makeFixes(context) {
var fixes = [];
var singleEntity = this.entityIds.length === 1 && context.hasEntity(this.entityIds[0]);
if (singleEntity) {
if (singleEntity.type === "way" && !singleEntity.isClosed()) {
var textDirection = _mainLocalizer.textDirection();
var startFix = makeContinueDrawingFixIfAllowed(textDirection, singleEntity.first(), "start");
if (startFix)
fixes.push(startFix);
var endFix = makeContinueDrawingFixIfAllowed(textDirection, singleEntity.last(), "end");
if (endFix)
fixes.push(endFix);
}
if (!fixes.length) {
fixes.push(new validationIssueFix({
title: _t.html("issues.fix.connect_feature.title")
}));
}
fixes.push(new validationIssueFix({
icon: "iD-operation-delete",
title: _t.html("issues.fix.delete_feature.title"),
entityIds: [singleEntity.id],
onClick: function(context2) {
var id2 = this.issue.entityIds[0];
var operation = operationDelete(context2, [id2]);
if (!operation.disabled()) {
operation();
}
}
}));
} else {
fixes.push(new validationIssueFix({
title: _t.html("issues.fix.connect_features.title")
}));
}
return fixes;
}
function showReference(selection2) {
selection2.selectAll(".issue-reference").data([0]).enter().append("div").attr("class", "issue-reference").call(_t.append("issues.disconnected_way.routable.reference"));
}
function routingIslandForEntity(entity2) {
var routingIsland = /* @__PURE__ */ new Set();
var waysToCheck = [];
function queueParentWays(node) {
graph.parentWays(node).forEach(function(parentWay) {
if (!routingIsland.has(parentWay) && isRoutableWay(parentWay, false)) {
routingIsland.add(parentWay);
waysToCheck.push(parentWay);
}
});
}
if (entity2.type === "way" && isRoutableWay(entity2, true)) {
routingIsland.add(entity2);
waysToCheck.push(entity2);
} else if (entity2.type === "node" && isRoutableNode(entity2)) {
routingIsland.add(entity2);
queueParentWays(entity2);
} else {
return null;
}
while (waysToCheck.length) {
var wayToCheck = waysToCheck.pop();
var childNodes = graph.childNodes(wayToCheck);
for (var i2 in childNodes) {
var vertex = childNodes[i2];
if (isConnectedVertex(vertex)) {
return null;
}
if (isRoutableNode(vertex)) {
routingIsland.add(vertex);
}
queueParentWays(vertex);
}
}
return routingIsland;
}
function isConnectedVertex(vertex) {
var osm = services.osm;
if (osm && !osm.isDataLoaded(vertex.loc))
return true;
if (vertex.tags.entrance && vertex.tags.entrance !== "no")
return true;
if (vertex.tags.amenity === "parking_entrance")
return true;
return false;
}
function isRoutableNode(node) {
if (node.tags.highway === "elevator")
return true;
return false;
}
function isRoutableWay(way, ignoreInnerWays) {
if (isTaggedAsHighway(way) || way.tags.route === "ferry")
return true;
return graph.parentRelations(way).some(function(parentRelation) {
if (parentRelation.tags.type === "route" && parentRelation.tags.route === "ferry")
return true;
if (parentRelation.isMultipolygon() && isTaggedAsHighway(parentRelation) && (!ignoreInnerWays || parentRelation.memberById(way.id).role !== "inner"))
return true;
return false;
});
}
function makeContinueDrawingFixIfAllowed(textDirection, vertexID, whichEnd) {
var vertex = graph.hasEntity(vertexID);
if (!vertex || vertex.tags.noexit === "yes")
return null;
var useLeftContinue = whichEnd === "start" && textDirection === "ltr" || whichEnd === "end" && textDirection === "rtl";
return new validationIssueFix({
icon: "iD-operation-continue" + (useLeftContinue ? "-left" : ""),
title: _t.html("issues.fix.continue_from_" + whichEnd + ".title"),
entityIds: [vertexID],
onClick: function(context) {
var wayId = this.issue.entityIds[0];
var way = context.hasEntity(wayId);
var vertexId = this.entityIds[0];
var vertex2 = context.hasEntity(vertexId);
if (!way || !vertex2)
return;
var map2 = context.map();
if (!context.editable() || !map2.trimmedExtent().contains(vertex2.loc)) {
map2.zoomToEase(vertex2);
}
context.enter(modeDrawLine(context, wayId, context.graph(), "line", way.affix(vertexId), true));
}
});
}
};
validation.type = type3;
return validation;
}
// modules/validations/invalid_format.js
function validationFormatting() {
var type3 = "invalid_format";
var validation = function(entity) {
var issues = [];
function isValidEmail(email) {
var valid_email = /^[^\(\)\\,":;<>@\[\]]+@[^\(\)\\,":;<>@\[\]\.]+(?:\.[a-z0-9-]+)*$/i;
return !email || valid_email.test(email);
}
function showReferenceEmail(selection2) {
selection2.selectAll(".issue-reference").data([0]).enter().append("div").attr("class", "issue-reference").call(_t.append("issues.invalid_format.email.reference"));
}
if (entity.tags.email) {
var emails = entity.tags.email.split(";").map(function(s) {
return s.trim();
}).filter(function(x) {
return !isValidEmail(x);
});
if (emails.length) {
issues.push(new validationIssue({
type: type3,
subtype: "email",
severity: "warning",
message: function(context) {
var entity2 = context.hasEntity(this.entityIds[0]);
return entity2 ? _t.html("issues.invalid_format.email.message" + this.data, { feature: utilDisplayLabel(entity2, context.graph()), email: emails.join(", ") }) : "";
},
reference: showReferenceEmail,
entityIds: [entity.id],
hash: emails.join(),
data: emails.length > 1 ? "_multi" : ""
}));
}
}
return issues;
};
validation.type = type3;
return validation;
}
// modules/validations/help_request.js
function validationHelpRequest(context) {
var type3 = "help_request";
var validation = function checkFixmeTag(entity) {
if (!entity.tags.fixme)
return [];
if (entity.version === void 0)
return [];
if (entity.v !== void 0) {
var baseEntity = context.history().base().hasEntity(entity.id);
if (!baseEntity || !baseEntity.tags.fixme)
return [];
}
return [new validationIssue({
type: type3,
subtype: "fixme_tag",
severity: "warning",
message: function(context2) {
var entity2 = context2.hasEntity(this.entityIds[0]);
return entity2 ? _t.html("issues.fixme_tag.message", {
feature: utilDisplayLabel(entity2, context2.graph(), true)
}) : "";
},
dynamicFixes: function() {
return [
new validationIssueFix({
title: _t.html("issues.fix.address_the_concern.title")
})
];
},
reference: showReference,
entityIds: [entity.id]
})];
function showReference(selection2) {
selection2.selectAll(".issue-reference").data([0]).enter().append("div").attr("class", "issue-reference").call(_t.append("issues.fixme_tag.reference"));
}
};
validation.type = type3;
return validation;
}
// modules/validations/impossible_oneway.js
function validationImpossibleOneway() {
var type3 = "impossible_oneway";
var validation = function checkImpossibleOneway(entity, graph) {
if (entity.type !== "way" || entity.geometry(graph) !== "line")
return [];
if (entity.isClosed())
return [];
if (!typeForWay(entity))
return [];
if (!isOneway(entity))
return [];
var firstIssues = issuesForNode(entity, entity.first());
var lastIssues = issuesForNode(entity, entity.last());
return firstIssues.concat(lastIssues);
function typeForWay(way) {
if (way.geometry(graph) !== "line")
return null;
if (osmRoutableHighwayTagValues[way.tags.highway])
return "highway";
if (osmFlowingWaterwayTagValues[way.tags.waterway])
return "waterway";
return null;
}
function isOneway(way) {
if (way.tags.oneway === "yes")
return true;
if (way.tags.oneway)
return false;
for (var key in way.tags) {
if (osmOneWayTags[key] && osmOneWayTags[key][way.tags[key]]) {
return true;
}
}
return false;
}
function nodeOccursMoreThanOnce(way, nodeID) {
var occurrences = 0;
for (var index in way.nodes) {
if (way.nodes[index] === nodeID) {
occurrences += 1;
if (occurrences > 1)
return true;
}
}
return false;
}
function isConnectedViaOtherTypes(way, node) {
var wayType = typeForWay(way);
if (wayType === "highway") {
if (node.tags.entrance && node.tags.entrance !== "no")
return true;
if (node.tags.amenity === "parking_entrance")
return true;
} else if (wayType === "waterway") {
if (node.id === way.first()) {
if (node.tags.natural === "spring")
return true;
} else {
if (node.tags.manhole === "drain")
return true;
}
}
return graph.parentWays(node).some(function(parentWay) {
if (parentWay.id === way.id)
return false;
if (wayType === "highway") {
if (parentWay.geometry(graph) === "area" && osmRoutableHighwayTagValues[parentWay.tags.highway])
return true;
if (parentWay.tags.route === "ferry")
return true;
return graph.parentRelations(parentWay).some(function(parentRelation) {
if (parentRelation.tags.type === "route" && parentRelation.tags.route === "ferry")
return true;
return parentRelation.isMultipolygon() && osmRoutableHighwayTagValues[parentRelation.tags.highway];
});
} else if (wayType === "waterway") {
if (parentWay.tags.natural === "water" || parentWay.tags.natural === "coastline")
return true;
}
return false;
});
}
function issuesForNode(way, nodeID) {
var isFirst = nodeID === way.first();
var wayType = typeForWay(way);
if (nodeOccursMoreThanOnce(way, nodeID))
return [];
var osm = services.osm;
if (!osm)
return [];
var node = graph.hasEntity(nodeID);
if (!node || !osm.isDataLoaded(node.loc))
return [];
if (isConnectedViaOtherTypes(way, node))
return [];
var attachedWaysOfSameType = graph.parentWays(node).filter(function(parentWay) {
if (parentWay.id === way.id)
return false;
return typeForWay(parentWay) === wayType;
});
if (wayType === "waterway" && attachedWaysOfSameType.length === 0)
return [];
var attachedOneways = attachedWaysOfSameType.filter(function(attachedWay) {
return isOneway(attachedWay);
});
if (attachedOneways.length < attachedWaysOfSameType.length)
return [];
if (attachedOneways.length) {
var connectedEndpointsOkay = attachedOneways.some(function(attachedOneway) {
if ((isFirst ? attachedOneway.first() : attachedOneway.last()) !== nodeID)
return true;
if (nodeOccursMoreThanOnce(attachedOneway, nodeID))
return true;
return false;
});
if (connectedEndpointsOkay)
return [];
}
var placement = isFirst ? "start" : "end", messageID = wayType + ".", referenceID = wayType + ".";
if (wayType === "waterway") {
messageID += "connected." + placement;
referenceID += "connected";
} else {
messageID += placement;
referenceID += placement;
}
return [new validationIssue({
type: type3,
subtype: wayType,
severity: "warning",
message: function(context) {
var entity2 = context.hasEntity(this.entityIds[0]);
return entity2 ? _t.html("issues.impossible_oneway." + messageID + ".message", {
feature: utilDisplayLabel(entity2, context.graph())
}) : "";
},
reference: getReference(referenceID),
entityIds: [way.id, node.id],
dynamicFixes: function() {
var fixes = [];
if (attachedOneways.length) {
fixes.push(new validationIssueFix({
icon: "iD-operation-reverse",
title: _t.html("issues.fix.reverse_feature.title"),
entityIds: [way.id],
onClick: function(context) {
var id2 = this.issue.entityIds[0];
context.perform(actionReverse(id2), _t("operations.reverse.annotation.line", { n: 1 }));
}
}));
}
if (node.tags.noexit !== "yes") {
var textDirection = _mainLocalizer.textDirection();
var useLeftContinue = isFirst && textDirection === "ltr" || !isFirst && textDirection === "rtl";
fixes.push(new validationIssueFix({
icon: "iD-operation-continue" + (useLeftContinue ? "-left" : ""),
title: _t.html("issues.fix.continue_from_" + (isFirst ? "start" : "end") + ".title"),
onClick: function(context) {
var entityID = this.issue.entityIds[0];
var vertexID = this.issue.entityIds[1];
var way2 = context.entity(entityID);
var vertex = context.entity(vertexID);
continueDrawing(way2, vertex, context);
}
}));
}
return fixes;
},
loc: node.loc
})];
function getReference(referenceID2) {
return function showReference(selection2) {
selection2.selectAll(".issue-reference").data([0]).enter().append("div").attr("class", "issue-reference").call(_t.append("issues.impossible_oneway." + referenceID2 + ".reference"));
};
}
}
};
function continueDrawing(way, vertex, context) {
var map2 = context.map();
if (!context.editable() || !map2.trimmedExtent().contains(vertex.loc)) {
map2.zoomToEase(vertex);
}
context.enter(modeDrawLine(context, way.id, context.graph(), "line", way.affix(vertex.id), true));
}
validation.type = type3;
return validation;
}
// modules/validations/incompatible_source.js
function validationIncompatibleSource() {
const type3 = "incompatible_source";
const incompatibleRules = [
{
id: "amap",
regex: /(^amap$|^amap\.com|autonavi|mapabc|高德)/i
},
{
id: "baidu",
regex: /(baidu|mapbar|百度)/i
},
{
id: "google",
regex: /google/i,
exceptRegex: /((books|drive)\.google|google\s?(books|drive|plus))|(esri\/Google_Africa_Buildings)/i
}
];
const validation = function checkIncompatibleSource(entity) {
const entitySources = entity.tags && entity.tags.source && entity.tags.source.split(";");
if (!entitySources)
return [];
const entityID = entity.id;
return entitySources.map((source) => {
const matchRule = incompatibleRules.find((rule) => {
if (!rule.regex.test(source))
return false;
if (rule.exceptRegex && rule.exceptRegex.test(source))
return false;
return true;
});
if (!matchRule)
return null;
return new validationIssue({
type: type3,
severity: "warning",
message: (context) => {
const entity2 = context.hasEntity(entityID);
return entity2 ? _t.html("issues.incompatible_source.feature.message", {
feature: utilDisplayLabel(entity2, context.graph(), true),
value: source
}) : "";
},
reference: getReference(matchRule.id),
entityIds: [entityID],
hash: source,
dynamicFixes: () => {
return [
new validationIssueFix({ title: _t.html("issues.fix.remove_proprietary_data.title") })
];
}
});
}).filter(Boolean);
function getReference(id2) {
return function showReference(selection2) {
selection2.selectAll(".issue-reference").data([0]).enter().append("div").attr("class", "issue-reference").call(_t.append(`issues.incompatible_source.reference.${id2}`));
};
}
};
validation.type = type3;
return validation;
}
// modules/validations/maprules.js
function validationMaprules() {
var type3 = "maprules";
var validation = function checkMaprules(entity, graph) {
if (!services.maprules)
return [];
var rules = services.maprules.validationRules();
var issues = [];
for (var i2 = 0; i2 < rules.length; i2++) {
var rule = rules[i2];
rule.findIssues(entity, graph, issues);
}
return issues;
};
validation.type = type3;
return validation;
}
// modules/validations/mismatched_geometry.js
var import_fast_deep_equal4 = __toESM(require_fast_deep_equal());
function validationMismatchedGeometry() {
var type3 = "mismatched_geometry";
function tagSuggestingLineIsArea(entity) {
if (entity.type !== "way" || entity.isClosed())
return null;
var tagSuggestingArea = entity.tagSuggestingArea();
if (!tagSuggestingArea) {
return null;
}
var asLine = _mainPresetIndex.matchTags(tagSuggestingArea, "line");
var asArea = _mainPresetIndex.matchTags(tagSuggestingArea, "area");
if (asLine && asArea && asLine === asArea) {
return null;
}
return tagSuggestingArea;
}
function makeConnectEndpointsFixOnClick(way, graph) {
if (way.nodes.length < 3)
return null;
var nodes = graph.childNodes(way), testNodes;
var firstToLastDistanceMeters = geoSphericalDistance(nodes[0].loc, nodes[nodes.length - 1].loc);
if (firstToLastDistanceMeters < 0.75) {
testNodes = nodes.slice();
testNodes.pop();
testNodes.push(testNodes[0]);
if (!geoHasSelfIntersections(testNodes, testNodes[0].id)) {
return function(context) {
var way2 = context.entity(this.issue.entityIds[0]);
context.perform(actionMergeNodes([way2.nodes[0], way2.nodes[way2.nodes.length - 1]], nodes[0].loc), _t("issues.fix.connect_endpoints.annotation"));
};
}
}
testNodes = nodes.slice();
testNodes.push(testNodes[0]);
if (!geoHasSelfIntersections(testNodes, testNodes[0].id)) {
return function(context) {
var wayId = this.issue.entityIds[0];
var way2 = context.entity(wayId);
var nodeId = way2.nodes[0];
var index = way2.nodes.length;
context.perform(actionAddVertex(wayId, nodeId, index), _t("issues.fix.connect_endpoints.annotation"));
};
}
}
function lineTaggedAsAreaIssue(entity) {
var tagSuggestingArea = tagSuggestingLineIsArea(entity);
if (!tagSuggestingArea)
return null;
return new validationIssue({
type: type3,
subtype: "area_as_line",
severity: "warning",
message: function(context) {
var entity2 = context.hasEntity(this.entityIds[0]);
return entity2 ? _t.html("issues.tag_suggests_area.message", {
feature: utilDisplayLabel(entity2, "area", true),
tag: utilTagText({ tags: tagSuggestingArea })
}) : "";
},
reference: showReference,
entityIds: [entity.id],
hash: JSON.stringify(tagSuggestingArea),
dynamicFixes: function(context) {
var fixes = [];
var entity2 = context.entity(this.entityIds[0]);
var connectEndsOnClick = makeConnectEndpointsFixOnClick(entity2, context.graph());
fixes.push(new validationIssueFix({
title: _t.html("issues.fix.connect_endpoints.title"),
onClick: connectEndsOnClick
}));
fixes.push(new validationIssueFix({
icon: "iD-operation-delete",
title: _t.html("issues.fix.remove_tag.title"),
onClick: function(context2) {
var entityId = this.issue.entityIds[0];
var entity3 = context2.entity(entityId);
var tags = Object.assign({}, entity3.tags);
for (var key in tagSuggestingArea) {
delete tags[key];
}
context2.perform(actionChangeTags(entityId, tags), _t("issues.fix.remove_tag.annotation"));
}
}));
return fixes;
}
});
function showReference(selection2) {
selection2.selectAll(".issue-reference").data([0]).enter().append("div").attr("class", "issue-reference").call(_t.append("issues.tag_suggests_area.reference"));
}
}
function vertexPointIssue(entity, graph) {
if (entity.type !== "node")
return null;
if (Object.keys(entity.tags).length === 0)
return null;
if (entity.isOnAddressLine(graph))
return null;
var geometry = entity.geometry(graph);
var allowedGeometries = osmNodeGeometriesForTags(entity.tags);
if (geometry === "point" && !allowedGeometries.point && allowedGeometries.vertex) {
return new validationIssue({
type: type3,
subtype: "vertex_as_point",
severity: "warning",
message: function(context) {
var entity2 = context.hasEntity(this.entityIds[0]);
return entity2 ? _t.html("issues.vertex_as_point.message", {
feature: utilDisplayLabel(entity2, "vertex", true)
}) : "";
},
reference: function showReference(selection2) {
selection2.selectAll(".issue-reference").data([0]).enter().append("div").attr("class", "issue-reference").call(_t.append("issues.vertex_as_point.reference"));
},
entityIds: [entity.id]
});
} else if (geometry === "vertex" && !allowedGeometries.vertex && allowedGeometries.point) {
return new validationIssue({
type: type3,
subtype: "point_as_vertex",
severity: "warning",
message: function(context) {
var entity2 = context.hasEntity(this.entityIds[0]);
return entity2 ? _t.html("issues.point_as_vertex.message", {
feature: utilDisplayLabel(entity2, "point", true)
}) : "";
},
reference: function showReference(selection2) {
selection2.selectAll(".issue-reference").data([0]).enter().append("div").attr("class", "issue-reference").call(_t.append("issues.point_as_vertex.reference"));
},
entityIds: [entity.id],
dynamicFixes: extractPointDynamicFixes
});
}
return null;
}
function otherMismatchIssue(entity, graph) {
if (!entity.hasInterestingTags())
return null;
if (entity.type !== "node" && entity.type !== "way")
return null;
if (entity.type === "node" && entity.isOnAddressLine(graph))
return null;
var sourceGeom = entity.geometry(graph);
var targetGeoms = entity.type === "way" ? ["point", "vertex"] : ["line", "area"];
if (sourceGeom === "area")
targetGeoms.unshift("line");
var asSource = _mainPresetIndex.match(entity, graph);
var targetGeom = targetGeoms.find((nodeGeom) => {
var asTarget = _mainPresetIndex.matchTags(entity.tags, nodeGeom);
if (!asSource || !asTarget || asSource === asTarget || (0, import_fast_deep_equal4.default)(asSource.tags, asTarget.tags))
return false;
if (asTarget.isFallback())
return false;
var primaryKey = Object.keys(asTarget.tags)[0];
if (primaryKey === "building")
return false;
if (asTarget.tags[primaryKey] === "*")
return false;
return asSource.isFallback() || asSource.tags[primaryKey] === "*";
});
if (!targetGeom)
return null;
var subtype = targetGeom + "_as_" + sourceGeom;
if (targetGeom === "vertex")
targetGeom = "point";
if (sourceGeom === "vertex")
sourceGeom = "point";
var referenceId = targetGeom + "_as_" + sourceGeom;
var dynamicFixes;
if (targetGeom === "point") {
dynamicFixes = extractPointDynamicFixes;
} else if (sourceGeom === "area" && targetGeom === "line") {
dynamicFixes = lineToAreaDynamicFixes;
}
return new validationIssue({
type: type3,
subtype,
severity: "warning",
message: function(context) {
var entity2 = context.hasEntity(this.entityIds[0]);
return entity2 ? _t.html("issues." + referenceId + ".message", {
feature: utilDisplayLabel(entity2, targetGeom, true)
}) : "";
},
reference: function showReference(selection2) {
selection2.selectAll(".issue-reference").data([0]).enter().append("div").attr("class", "issue-reference").call(_t.append("issues.mismatched_geometry.reference"));
},
entityIds: [entity.id],
dynamicFixes
});
}
function lineToAreaDynamicFixes(context) {
var convertOnClick;
var entityId = this.entityIds[0];
var entity = context.entity(entityId);
var tags = Object.assign({}, entity.tags);
delete tags.area;
if (!osmTagSuggestingArea(tags)) {
convertOnClick = function(context2) {
var entityId2 = this.issue.entityIds[0];
var entity2 = context2.entity(entityId2);
var tags2 = Object.assign({}, entity2.tags);
if (tags2.area) {
delete tags2.area;
}
context2.perform(actionChangeTags(entityId2, tags2), _t("issues.fix.convert_to_line.annotation"));
};
}
return [
new validationIssueFix({
icon: "iD-icon-line",
title: _t.html("issues.fix.convert_to_line.title"),
onClick: convertOnClick
})
];
}
function extractPointDynamicFixes(context) {
var entityId = this.entityIds[0];
var extractOnClick = null;
if (!context.hasHiddenConnections(entityId)) {
extractOnClick = function(context2) {
var entityId2 = this.issue.entityIds[0];
var action = actionExtract(entityId2, context2.projection);
context2.perform(action, _t("operations.extract.annotation", { n: 1 }));
context2.enter(modeSelect(context2, [action.getExtractedNodeID()]));
};
}
return [
new validationIssueFix({
icon: "iD-operation-extract",
title: _t.html("issues.fix.extract_point.title"),
onClick: extractOnClick
})
];
}
function unclosedMultipolygonPartIssues(entity, graph) {
if (entity.type !== "relation" || !entity.isMultipolygon() || entity.isDegenerate() || !entity.isComplete(graph))
return [];
var sequences = osmJoinWays(entity.members, graph);
var issues = [];
for (var i2 in sequences) {
var sequence = sequences[i2];
if (!sequence.nodes)
continue;
var firstNode = sequence.nodes[0];
var lastNode = sequence.nodes[sequence.nodes.length - 1];
if (firstNode === lastNode)
continue;
var issue = new validationIssue({
type: type3,
subtype: "unclosed_multipolygon_part",
severity: "warning",
message: function(context) {
var entity2 = context.hasEntity(this.entityIds[0]);
return entity2 ? _t.html("issues.unclosed_multipolygon_part.message", {
feature: utilDisplayLabel(entity2, context.graph(), true)
}) : "";
},
reference: showReference,
loc: sequence.nodes[0].loc,
entityIds: [entity.id],
hash: sequence.map(function(way) {
return way.id;
}).join()
});
issues.push(issue);
}
return issues;
function showReference(selection2) {
selection2.selectAll(".issue-reference").data([0]).enter().append("div").attr("class", "issue-reference").call(_t.append("issues.unclosed_multipolygon_part.reference"));
}
}
var validation = function checkMismatchedGeometry(entity, graph) {
var vertexPoint = vertexPointIssue(entity, graph);
if (vertexPoint)
return [vertexPoint];
var lineAsArea = lineTaggedAsAreaIssue(entity);
if (lineAsArea)
return [lineAsArea];
var mismatch = otherMismatchIssue(entity, graph);
if (mismatch)
return [mismatch];
return unclosedMultipolygonPartIssues(entity, graph);
};
validation.type = type3;
return validation;
}
// modules/validations/missing_role.js
function validationMissingRole() {
var type3 = "missing_role";
var validation = function checkMissingRole(entity, graph) {
var issues = [];
if (entity.type === "way") {
graph.parentRelations(entity).forEach(function(relation) {
if (!relation.isMultipolygon())
return;
var member = relation.memberById(entity.id);
if (member && isMissingRole(member)) {
issues.push(makeIssue(entity, relation, member));
}
});
} else if (entity.type === "relation" && entity.isMultipolygon()) {
entity.indexedMembers().forEach(function(member) {
var way = graph.hasEntity(member.id);
if (way && isMissingRole(member)) {
issues.push(makeIssue(way, entity, member));
}
});
}
return issues;
};
function isMissingRole(member) {
return !member.role || !member.role.trim().length;
}
function makeIssue(way, relation, member) {
return new validationIssue({
type: type3,
severity: "warning",
message: function(context) {
var member2 = context.hasEntity(this.entityIds[1]), relation2 = context.hasEntity(this.entityIds[0]);
return member2 && relation2 ? _t.html("issues.missing_role.message", {
member: utilDisplayLabel(member2, context.graph()),
relation: utilDisplayLabel(relation2, context.graph())
}) : "";
},
reference: showReference,
entityIds: [relation.id, way.id],
data: {
member
},
hash: member.index.toString(),
dynamicFixes: function() {
return [
makeAddRoleFix("inner"),
makeAddRoleFix("outer"),
new validationIssueFix({
icon: "iD-operation-delete",
title: _t.html("issues.fix.remove_from_relation.title"),
onClick: function(context) {
context.perform(actionDeleteMember(this.issue.entityIds[0], this.issue.data.member.index), _t("operations.delete_member.annotation", {
n: 1
}));
}
})
];
}
});
function showReference(selection2) {
selection2.selectAll(".issue-reference").data([0]).enter().append("div").attr("class", "issue-reference").call(_t.append("issues.missing_role.multipolygon.reference"));
}
}
function makeAddRoleFix(role) {
return new validationIssueFix({
title: _t.html("issues.fix.set_as_" + role + ".title"),
onClick: function(context) {
var oldMember = this.issue.data.member;
var member = { id: this.issue.entityIds[1], type: oldMember.type, role };
context.perform(actionChangeMember(this.issue.entityIds[0], member, oldMember.index), _t("operations.change_role.annotation", {
n: 1
}));
}
});
}
validation.type = type3;
return validation;
}
// modules/validations/missing_tag.js
function validationMissingTag(context) {
var type3 = "missing_tag";
function hasDescriptiveTags(entity, graph) {
var onlyAttributeKeys = ["description", "name", "note", "start_date"];
var entityDescriptiveKeys = Object.keys(entity.tags).filter(function(k) {
if (k === "area" || !osmIsInterestingTag(k))
return false;
return !onlyAttributeKeys.some(function(attributeKey) {
return k === attributeKey || k.indexOf(attributeKey + ":") === 0;
});
});
if (entity.type === "relation" && entityDescriptiveKeys.length === 1 && entity.tags.type === "multipolygon") {
return osmOldMultipolygonOuterMemberOfRelation(entity, graph);
}
return entityDescriptiveKeys.length > 0;
}
function isUnknownRoad(entity) {
return entity.type === "way" && entity.tags.highway === "road";
}
function isUntypedRelation(entity) {
return entity.type === "relation" && !entity.tags.type;
}
var validation = function checkMissingTag(entity, graph) {
var subtype;
var osm = context.connection();
var isUnloadedNode = entity.type === "node" && osm && !osm.isDataLoaded(entity.loc);
if (!isUnloadedNode && entity.geometry(graph) !== "vertex" && !entity.hasParentRelations(graph)) {
if (Object.keys(entity.tags).length === 0) {
subtype = "any";
} else if (!hasDescriptiveTags(entity, graph)) {
subtype = "descriptive";
} else if (isUntypedRelation(entity)) {
subtype = "relation_type";
}
}
if (!subtype && isUnknownRoad(entity)) {
subtype = "highway_classification";
}
if (!subtype)
return [];
var messageID = subtype === "highway_classification" ? "unknown_road" : "missing_tag." + subtype;
var referenceID = subtype === "highway_classification" ? "unknown_road" : "missing_tag";
var canDelete = entity.version === void 0 || entity.v !== void 0;
var severity = canDelete && subtype !== "highway_classification" ? "error" : "warning";
return [new validationIssue({
type: type3,
subtype,
severity,
message: function(context2) {
var entity2 = context2.hasEntity(this.entityIds[0]);
return entity2 ? _t.html("issues." + messageID + ".message", {
feature: utilDisplayLabel(entity2, context2.graph())
}) : "";
},
reference: showReference,
entityIds: [entity.id],
dynamicFixes: function(context2) {
var fixes = [];
var selectFixType = subtype === "highway_classification" ? "select_road_type" : "select_preset";
fixes.push(new validationIssueFix({
icon: "iD-icon-search",
title: _t.html("issues.fix." + selectFixType + ".title"),
onClick: function(context3) {
context3.ui().sidebar.showPresetList();
}
}));
var deleteOnClick;
var id2 = this.entityIds[0];
var operation = operationDelete(context2, [id2]);
var disabledReasonID = operation.disabled();
if (!disabledReasonID) {
deleteOnClick = function(context3) {
var id3 = this.issue.entityIds[0];
var operation2 = operationDelete(context3, [id3]);
if (!operation2.disabled()) {
operation2();
}
};
}
fixes.push(new validationIssueFix({
icon: "iD-operation-delete",
title: _t.html("issues.fix.delete_feature.title"),
disabledReason: disabledReasonID ? _t("operations.delete." + disabledReasonID + ".single") : void 0,
onClick: deleteOnClick
}));
return fixes;
}
})];
function showReference(selection2) {
selection2.selectAll(".issue-reference").data([0]).enter().append("div").attr("class", "issue-reference").call(_t.append("issues." + referenceID + ".reference"));
}
};
validation.type = type3;
return validation;
}
// modules/validations/outdated_tags.js
function validationOutdatedTags() {
const type3 = "outdated_tags";
let _waitingForDeprecated = true;
let _dataDeprecated;
_mainFileFetcher.get("deprecated").then((d) => _dataDeprecated = d).catch(() => {
}).finally(() => _waitingForDeprecated = false);
function oldTagIssues(entity, graph) {
const oldTags = Object.assign({}, entity.tags);
let preset = _mainPresetIndex.match(entity, graph);
let subtype = "deprecated_tags";
if (!preset)
return [];
if (!entity.hasInterestingTags())
return [];
if (preset.replacement) {
const newPreset = _mainPresetIndex.item(preset.replacement);
graph = actionChangePreset(entity.id, preset, newPreset, true)(graph);
entity = graph.entity(entity.id);
preset = newPreset;
}
if (_dataDeprecated) {
const deprecatedTags = entity.deprecatedTags(_dataDeprecated);
if (deprecatedTags.length) {
deprecatedTags.forEach((tag) => {
graph = actionUpgradeTags(entity.id, tag.old, tag.replace)(graph);
});
entity = graph.entity(entity.id);
}
}
let newTags = Object.assign({}, entity.tags);
if (preset.tags !== preset.addTags) {
Object.keys(preset.addTags).forEach((k) => {
if (!newTags[k]) {
if (preset.addTags[k] === "*") {
newTags[k] = "yes";
} else {
newTags[k] = preset.addTags[k];
}
}
});
}
const nsi = services.nsi;
let waitingForNsi = false;
let nsiResult;
if (nsi) {
waitingForNsi = nsi.status() === "loading";
if (!waitingForNsi) {
const loc = entity.extent(graph).center();
nsiResult = nsi.upgradeTags(newTags, loc);
if (nsiResult) {
newTags = nsiResult.newTags;
subtype = "noncanonical_brand";
}
}
}
let issues = [];
issues.provisional = _waitingForDeprecated || waitingForNsi;
const tagDiff = utilTagDiff(oldTags, newTags);
if (!tagDiff.length)
return issues;
const isOnlyAddingTags = tagDiff.every((d) => d.type === "+");
let prefix = "";
if (nsiResult) {
prefix = "noncanonical_brand.";
} else if (subtype === "deprecated_tags" && isOnlyAddingTags) {
subtype = "incomplete_tags";
prefix = "incomplete.";
}
let autoArgs = subtype !== "noncanonical_brand" ? [doUpgrade, _t("issues.fix.upgrade_tags.annotation")] : null;
issues.push(new validationIssue({
type: type3,
subtype,
severity: "warning",
message: showMessage,
reference: showReference,
entityIds: [entity.id],
hash: utilHashcode(JSON.stringify(tagDiff)),
dynamicFixes: () => {
let fixes = [
new validationIssueFix({
autoArgs,
title: _t.html("issues.fix.upgrade_tags.title"),
onClick: (context) => {
context.perform(doUpgrade, _t("issues.fix.upgrade_tags.annotation"));
}
})
];
const item = nsiResult && nsiResult.matched;
if (item) {
fixes.push(new validationIssueFix({
title: _t.html("issues.fix.tag_as_not.title", { name: item.displayName }),
onClick: (context) => {
context.perform(addNotTag, _t("issues.fix.tag_as_not.annotation"));
}
}));
}
return fixes;
}
}));
return issues;
function doUpgrade(graph2) {
const currEntity = graph2.hasEntity(entity.id);
if (!currEntity)
return graph2;
let newTags2 = Object.assign({}, currEntity.tags);
tagDiff.forEach((diff) => {
if (diff.type === "-") {
delete newTags2[diff.key];
} else if (diff.type === "+") {
newTags2[diff.key] = diff.newVal;
}
});
return actionChangeTags(currEntity.id, newTags2)(graph2);
}
function addNotTag(graph2) {
const currEntity = graph2.hasEntity(entity.id);
if (!currEntity)
return graph2;
const item = nsiResult && nsiResult.matched;
if (!item)
return graph2;
let newTags2 = Object.assign({}, currEntity.tags);
const wd = item.mainTag;
const notwd = `not:${wd}`;
const qid = item.tags[wd];
newTags2[notwd] = qid;
if (newTags2[wd] === qid) {
const wp = item.mainTag.replace("wikidata", "wikipedia");
delete newTags2[wd];
delete newTags2[wp];
}
return actionChangeTags(currEntity.id, newTags2)(graph2);
}
function showMessage(context) {
const currEntity = context.hasEntity(entity.id);
if (!currEntity)
return "";
let messageID = `issues.outdated_tags.${prefix}message`;
if (subtype === "noncanonical_brand" && isOnlyAddingTags) {
messageID += "_incomplete";
}
return _t.html(messageID, {
feature: utilDisplayLabel(currEntity, context.graph(), true)
});
}
function showReference(selection2) {
let enter = selection2.selectAll(".issue-reference").data([0]).enter();
enter.append("div").attr("class", "issue-reference").call(_t.append(`issues.outdated_tags.${prefix}reference`));
enter.append("strong").call(_t.append("issues.suggested"));
enter.append("table").attr("class", "tagDiff-table").selectAll(".tagDiff-row").data(tagDiff).enter().append("tr").attr("class", "tagDiff-row").append("td").attr("class", (d) => {
let klass = d.type === "+" ? "add" : "remove";
return `tagDiff-cell tagDiff-cell-${klass}`;
}).html((d) => d.display);
}
}
function oldMultipolygonIssues(entity, graph) {
let multipolygon, outerWay;
if (entity.type === "relation") {
outerWay = osmOldMultipolygonOuterMemberOfRelation(entity, graph);
multipolygon = entity;
} else if (entity.type === "way") {
multipolygon = osmIsOldMultipolygonOuterMember(entity, graph);
outerWay = entity;
} else {
return [];
}
if (!multipolygon || !outerWay)
return [];
return [new validationIssue({
type: type3,
subtype: "old_multipolygon",
severity: "warning",
message: showMessage,
reference: showReference,
entityIds: [outerWay.id, multipolygon.id],
dynamicFixes: () => {
return [
new validationIssueFix({
autoArgs: [doUpgrade, _t("issues.fix.move_tags.annotation")],
title: _t.html("issues.fix.move_tags.title"),
onClick: (context) => {
context.perform(doUpgrade, _t("issues.fix.move_tags.annotation"));
}
})
];
}
})];
function doUpgrade(graph2) {
let currMultipolygon = graph2.hasEntity(multipolygon.id);
let currOuterWay = graph2.hasEntity(outerWay.id);
if (!currMultipolygon || !currOuterWay)
return graph2;
currMultipolygon = currMultipolygon.mergeTags(currOuterWay.tags);
graph2 = graph2.replace(currMultipolygon);
return actionChangeTags(currOuterWay.id, {})(graph2);
}
function showMessage(context) {
let currMultipolygon = context.hasEntity(multipolygon.id);
if (!currMultipolygon)
return "";
return _t.html("issues.old_multipolygon.message", { multipolygon: utilDisplayLabel(currMultipolygon, context.graph(), true) });
}
function showReference(selection2) {
selection2.selectAll(".issue-reference").data([0]).enter().append("div").attr("class", "issue-reference").call(_t.append("issues.old_multipolygon.reference"));
}
}
let validation = function checkOutdatedTags(entity, graph) {
let issues = oldMultipolygonIssues(entity, graph);
if (!issues.length)
issues = oldTagIssues(entity, graph);
return issues;
};
validation.type = type3;
return validation;
}
// modules/validations/private_data.js
function validationPrivateData() {
var type3 = "private_data";
var privateBuildingValues = {
detached: true,
farm: true,
house: true,
houseboat: true,
residential: true,
semidetached_house: true,
static_caravan: true
};
var publicKeys = {
amenity: true,
craft: true,
historic: true,
leisure: true,
office: true,
shop: true,
tourism: true
};
var personalTags = {
"contact:email": true,
"contact:fax": true,
"contact:phone": true,
email: true,
fax: true,
phone: true
};
var validation = function checkPrivateData(entity) {
var tags = entity.tags;
if (!tags.building || !privateBuildingValues[tags.building])
return [];
var keepTags = {};
for (var k in tags) {
if (publicKeys[k])
return [];
if (!personalTags[k]) {
keepTags[k] = tags[k];
}
}
var tagDiff = utilTagDiff(tags, keepTags);
if (!tagDiff.length)
return [];
var fixID = tagDiff.length === 1 ? "remove_tag" : "remove_tags";
return [new validationIssue({
type: type3,
severity: "warning",
message: showMessage,
reference: showReference,
entityIds: [entity.id],
dynamicFixes: function() {
return [
new validationIssueFix({
icon: "iD-operation-delete",
title: _t.html("issues.fix." + fixID + ".title"),
onClick: function(context) {
context.perform(doUpgrade, _t("issues.fix.upgrade_tags.annotation"));
}
})
];
}
})];
function doUpgrade(graph) {
var currEntity = graph.hasEntity(entity.id);
if (!currEntity)
return graph;
var newTags = Object.assign({}, currEntity.tags);
tagDiff.forEach(function(diff) {
if (diff.type === "-") {
delete newTags[diff.key];
} else if (diff.type === "+") {
newTags[diff.key] = diff.newVal;
}
});
return actionChangeTags(currEntity.id, newTags)(graph);
}
function showMessage(context) {
var currEntity = context.hasEntity(this.entityIds[0]);
if (!currEntity)
return "";
return _t.html("issues.private_data.contact.message", { feature: utilDisplayLabel(currEntity, context.graph()) });
}
function showReference(selection2) {
var enter = selection2.selectAll(".issue-reference").data([0]).enter();
enter.append("div").attr("class", "issue-reference").call(_t.append("issues.private_data.reference"));
enter.append("strong").call(_t.append("issues.suggested"));
enter.append("table").attr("class", "tagDiff-table").selectAll(".tagDiff-row").data(tagDiff).enter().append("tr").attr("class", "tagDiff-row").append("td").attr("class", function(d) {
var klass = d.type === "+" ? "add" : "remove";
return "tagDiff-cell tagDiff-cell-" + klass;
}).html(function(d) {
return d.display;
});
}
};
validation.type = type3;
return validation;
}
// modules/validations/suspicious_name.js
function validationSuspiciousName() {
const type3 = "suspicious_name";
const keysToTestForGenericValues = [
"aerialway",
"aeroway",
"amenity",
"building",
"craft",
"highway",
"leisure",
"railway",
"man_made",
"office",
"shop",
"tourism",
"waterway"
];
let _waitingForNsi = false;
function isGenericMatchInNsi(tags) {
const nsi = services.nsi;
if (nsi) {
_waitingForNsi = nsi.status() === "loading";
if (!_waitingForNsi) {
return nsi.isGenericName(tags);
}
}
return false;
}
function nameMatchesRawTag(lowercaseName, tags) {
for (let i2 = 0; i2 < keysToTestForGenericValues.length; i2++) {
let key = keysToTestForGenericValues[i2];
let val = tags[key];
if (val) {
val = val.toLowerCase();
if (key === lowercaseName || val === lowercaseName || key.replace(/\_/g, " ") === lowercaseName || val.replace(/\_/g, " ") === lowercaseName) {
return true;
}
}
}
return false;
}
function isGenericName(name2, tags) {
name2 = name2.toLowerCase();
return nameMatchesRawTag(name2, tags) || isGenericMatchInNsi(tags);
}
function makeGenericNameIssue(entityId, nameKey, genericName, langCode) {
return new validationIssue({
type: type3,
subtype: "generic_name",
severity: "warning",
message: function(context) {
let entity = context.hasEntity(this.entityIds[0]);
if (!entity)
return "";
let preset = _mainPresetIndex.match(entity, context.graph());
let langName = langCode && _mainLocalizer.languageName(langCode);
return _t.html("issues.generic_name.message" + (langName ? "_language" : ""), { feature: preset.name(), name: genericName, language: langName });
},
reference: showReference,
entityIds: [entityId],
hash: `${nameKey}=${genericName}`,
dynamicFixes: function() {
return [
new validationIssueFix({
icon: "iD-operation-delete",
title: _t.html("issues.fix.remove_the_name.title"),
onClick: function(context) {
let entityId2 = this.issue.entityIds[0];
let entity = context.entity(entityId2);
let tags = Object.assign({}, entity.tags);
delete tags[nameKey];
context.perform(actionChangeTags(entityId2, tags), _t("issues.fix.remove_generic_name.annotation"));
}
})
];
}
});
function showReference(selection2) {
selection2.selectAll(".issue-reference").data([0]).enter().append("div").attr("class", "issue-reference").call(_t.append("issues.generic_name.reference"));
}
}
function makeIncorrectNameIssue(entityId, nameKey, incorrectName, langCode) {
return new validationIssue({
type: type3,
subtype: "not_name",
severity: "warning",
message: function(context) {
const entity = context.hasEntity(this.entityIds[0]);
if (!entity)
return "";
const preset = _mainPresetIndex.match(entity, context.graph());
const langName = langCode && _mainLocalizer.languageName(langCode);
return _t.html("issues.incorrect_name.message" + (langName ? "_language" : ""), { feature: preset.name(), name: incorrectName, language: langName });
},
reference: showReference,
entityIds: [entityId],
hash: `${nameKey}=${incorrectName}`,
dynamicFixes: function() {
return [
new validationIssueFix({
icon: "iD-operation-delete",
title: _t.html("issues.fix.remove_the_name.title"),
onClick: function(context) {
const entityId2 = this.issue.entityIds[0];
const entity = context.entity(entityId2);
let tags = Object.assign({}, entity.tags);
delete tags[nameKey];
context.perform(actionChangeTags(entityId2, tags), _t("issues.fix.remove_mistaken_name.annotation"));
}
})
];
}
});
function showReference(selection2) {
selection2.selectAll(".issue-reference").data([0]).enter().append("div").attr("class", "issue-reference").call(_t.append("issues.generic_name.reference"));
}
}
let validation = function checkGenericName(entity) {
const tags = entity.tags;
const hasWikidata = !!tags.wikidata || !!tags["brand:wikidata"] || !!tags["operator:wikidata"];
if (hasWikidata)
return [];
let issues = [];
const notNames2 = (tags["not:name"] || "").split(";");
for (let key in tags) {
const m = key.match(/^name(?:(?::)([a-zA-Z_-]+))?$/);
if (!m)
continue;
const langCode = m.length >= 2 ? m[1] : null;
const value = tags[key];
if (notNames2.length) {
for (let i2 in notNames2) {
const notName = notNames2[i2];
if (notName && value === notName) {
issues.push(makeIncorrectNameIssue(entity.id, key, value, langCode));
continue;
}
}
}
if (isGenericName(value, tags)) {
issues.provisional = _waitingForNsi;
issues.push(makeGenericNameIssue(entity.id, key, value, langCode));
}
}
return issues;
};
validation.type = type3;
return validation;
}
// modules/validations/unsquare_way.js
function validationUnsquareWay(context) {
var type3 = "unsquare_way";
var DEFAULT_DEG_THRESHOLD = 5;
var epsilon3 = 0.05;
var nodeThreshold = 10;
function isBuilding(entity, graph) {
if (entity.type !== "way" || entity.geometry(graph) !== "area")
return false;
return entity.tags.building && entity.tags.building !== "no";
}
var validation = function checkUnsquareWay(entity, graph) {
if (!isBuilding(entity, graph))
return [];
if (entity.tags.nonsquare === "yes")
return [];
var isClosed = entity.isClosed();
if (!isClosed)
return [];
var nodes = graph.childNodes(entity).slice();
if (nodes.length > nodeThreshold + 1)
return [];
var osm = services.osm;
if (!osm || nodes.some(function(node) {
return !osm.isDataLoaded(node.loc);
}))
return [];
var hasConnectedSquarableWays = nodes.some(function(node) {
return graph.parentWays(node).some(function(way) {
if (way.id === entity.id)
return false;
if (isBuilding(way, graph))
return true;
return graph.parentRelations(way).some(function(parentRelation) {
return parentRelation.isMultipolygon() && parentRelation.tags.building && parentRelation.tags.building !== "no";
});
});
});
if (hasConnectedSquarableWays)
return [];
var storedDegreeThreshold = corePreferences("validate-square-degrees");
var degreeThreshold = isNaN(storedDegreeThreshold) ? DEFAULT_DEG_THRESHOLD : parseFloat(storedDegreeThreshold);
var points = nodes.map(function(node) {
return context.projection(node.loc);
});
if (!geoOrthoCanOrthogonalize(points, isClosed, epsilon3, degreeThreshold, true))
return [];
var autoArgs;
if (!entity.tags.wikidata) {
var autoAction = actionOrthogonalize(entity.id, context.projection, void 0, degreeThreshold);
autoAction.transitionable = false;
autoArgs = [autoAction, _t("operations.orthogonalize.annotation.feature", { n: 1 })];
}
return [new validationIssue({
type: type3,
subtype: "building",
severity: "warning",
message: function(context2) {
var entity2 = context2.hasEntity(this.entityIds[0]);
return entity2 ? _t.html("issues.unsquare_way.message", {
feature: utilDisplayLabel(entity2, context2.graph())
}) : "";
},
reference: showReference,
entityIds: [entity.id],
hash: degreeThreshold,
dynamicFixes: function() {
return [
new validationIssueFix({
icon: "iD-operation-orthogonalize",
title: _t.html("issues.fix.square_feature.title"),
autoArgs,
onClick: function(context2, completionHandler) {
var entityId = this.issue.entityIds[0];
context2.perform(actionOrthogonalize(entityId, context2.projection, void 0, degreeThreshold), _t("operations.orthogonalize.annotation.feature", { n: 1 }));
window.setTimeout(function() {
completionHandler();
}, 175);
}
})
];
}
})];
function showReference(selection2) {
selection2.selectAll(".issue-reference").data([0]).enter().append("div").attr("class", "issue-reference").call(_t.append("issues.unsquare_way.buildings.reference"));
}
};
validation.type = type3;
return validation;
}
// modules/core/validator.js
function coreValidator(context) {
let dispatch10 = dispatch_default("validated", "focusedIssue");
let validator = utilRebind({}, dispatch10, "on");
let _rules = {};
let _disabledRules = {};
let _ignoredIssueIDs = /* @__PURE__ */ new Set();
let _resolvedIssueIDs = /* @__PURE__ */ new Set();
let _baseCache = validationCache("base");
let _headCache = validationCache("head");
let _completeDiff = {};
let _headIsCurrent = false;
let _deferredRIC = {};
let _deferredST = /* @__PURE__ */ new Set();
let _headPromise;
const RETRY = 5e3;
const _errorOverrides = parseHashParam(context.initialHashParams.validationError);
const _warningOverrides = parseHashParam(context.initialHashParams.validationWarning);
const _disableOverrides = parseHashParam(context.initialHashParams.validationDisable);
function parseHashParam(param) {
let result = [];
let rules = (param || "").split(",");
rules.forEach((rule) => {
rule = rule.trim();
const parts = rule.split("/", 2);
const type3 = parts[0];
const subtype = parts[1] || "*";
if (!type3 || !subtype)
return;
result.push({ type: makeRegExp(type3), subtype: makeRegExp(subtype) });
});
return result;
function makeRegExp(str2) {
const escaped = str2.replace(/[-\/\\^$+?.()|[\]{}]/g, "\\$&").replace(/\*/g, ".*");
return new RegExp("^" + escaped + "$");
}
}
validator.init = () => {
Object.values(validations_exports).forEach((validation) => {
if (typeof validation !== "function")
return;
const fn = validation(context);
const key = fn.type;
_rules[key] = fn;
});
let disabledRules = corePreferences("validate-disabledRules");
if (disabledRules) {
disabledRules.split(",").forEach((k) => _disabledRules[k] = true);
}
};
function reset(resetIgnored) {
_baseCache.queue = [];
_headCache.queue = [];
Object.keys(_deferredRIC).forEach((key) => {
window.cancelIdleCallback(key);
_deferredRIC[key]();
});
_deferredRIC = {};
_deferredST.forEach(window.clearTimeout);
_deferredST.clear();
if (resetIgnored)
_ignoredIssueIDs.clear();
_resolvedIssueIDs.clear();
_baseCache = validationCache("base");
_headCache = validationCache("head");
_completeDiff = {};
_headIsCurrent = false;
}
validator.reset = () => {
reset(true);
};
validator.resetIgnoredIssues = () => {
_ignoredIssueIDs.clear();
dispatch10.call("validated");
};
validator.revalidateUnsquare = () => {
revalidateUnsquare(_headCache);
revalidateUnsquare(_baseCache);
dispatch10.call("validated");
};
function revalidateUnsquare(cache) {
const checkUnsquareWay = _rules.unsquare_way;
if (!cache.graph || typeof checkUnsquareWay !== "function")
return;
cache.uncacheIssuesOfType("unsquare_way");
const buildings = context.history().tree().intersects(geoExtent([-180, -90], [180, 90]), cache.graph).filter((entity) => entity.type === "way" && entity.tags.building && entity.tags.building !== "no");
buildings.forEach((entity) => {
const detected = checkUnsquareWay(entity, cache.graph);
if (!detected.length)
return;
cache.cacheIssues(detected);
});
}
validator.getIssues = (options2) => {
const opts = Object.assign({ what: "all", where: "all", includeIgnored: false, includeDisabledRules: false }, options2);
const view = context.map().extent();
let seen = /* @__PURE__ */ new Set();
let results = [];
if (_headCache.graph && _headCache.graph !== _baseCache.graph) {
Object.values(_headCache.issuesByIssueID).forEach((issue) => {
const userModified = (issue.entityIds || []).some((id2) => _completeDiff.hasOwnProperty(id2));
if (opts.what === "edited" && !userModified)
return;
if (!filter2(issue))
return;
seen.add(issue.id);
results.push(issue);
});
}
if (opts.what === "all") {
Object.values(_baseCache.issuesByIssueID).forEach((issue) => {
if (!filter2(issue))
return;
seen.add(issue.id);
results.push(issue);
});
}
return results;
function filter2(issue) {
if (!issue)
return false;
if (seen.has(issue.id))
return false;
if (_resolvedIssueIDs.has(issue.id))
return false;
if (opts.includeDisabledRules === "only" && !_disabledRules[issue.type])
return false;
if (!opts.includeDisabledRules && _disabledRules[issue.type])
return false;
if (opts.includeIgnored === "only" && !_ignoredIssueIDs.has(issue.id))
return false;
if (!opts.includeIgnored && _ignoredIssueIDs.has(issue.id))
return false;
if ((issue.entityIds || []).some((id2) => !context.hasEntity(id2)))
return false;
if (opts.where === "visible") {
const extent = issue.extent(context.graph());
if (!view.intersects(extent))
return false;
}
return true;
}
};
validator.getResolvedIssues = () => {
return Array.from(_resolvedIssueIDs).map((issueID) => _baseCache.issuesByIssueID[issueID]).filter(Boolean);
};
validator.focusIssue = (issue) => {
const graph = context.graph();
let selectID;
let focusCenter;
const issueExtent = issue.extent(graph);
if (issueExtent) {
focusCenter = issueExtent.center();
}
if (issue.entityIds && issue.entityIds.length) {
selectID = issue.entityIds[0];
if (selectID && selectID.charAt(0) === "r") {
const ids = utilEntityAndDeepMemberIDs([selectID], graph);
let nodeID = ids.find((id2) => id2.charAt(0) === "n" && graph.hasEntity(id2));
if (!nodeID) {
const wayID = ids.find((id2) => id2.charAt(0) === "w" && graph.hasEntity(id2));
if (wayID) {
nodeID = graph.entity(wayID).first();
}
}
if (nodeID) {
focusCenter = graph.entity(nodeID).loc;
}
}
}
if (focusCenter) {
const setZoom = Math.max(context.map().zoom(), 19);
context.map().unobscuredCenterZoomEase(focusCenter, setZoom);
}
if (selectID) {
window.setTimeout(() => {
context.enter(modeSelect(context, [selectID]));
dispatch10.call("focusedIssue", this, issue);
}, 250);
}
};
validator.getIssuesBySeverity = (options2) => {
let groups = utilArrayGroupBy(validator.getIssues(options2), "severity");
groups.error = groups.error || [];
groups.warning = groups.warning || [];
return groups;
};
validator.getSharedEntityIssues = (entityIDs, options2) => {
const orderedIssueTypes = [
"missing_tag",
"missing_role",
"outdated_tags",
"mismatched_geometry",
"crossing_ways",
"almost_junction",
"disconnected_way",
"impossible_oneway"
];
const allIssues = validator.getIssues(options2);
const forEntityIDs = new Set(entityIDs);
return allIssues.filter((issue) => (issue.entityIds || []).some((entityID) => forEntityIDs.has(entityID))).sort((issue1, issue2) => {
if (issue1.type === issue2.type) {
return issue1.id < issue2.id ? -1 : 1;
}
const index1 = orderedIssueTypes.indexOf(issue1.type);
const index2 = orderedIssueTypes.indexOf(issue2.type);
if (index1 !== -1 && index2 !== -1) {
return index1 - index2;
} else if (index1 === -1 && index2 === -1) {
return issue1.type < issue2.type ? -1 : 1;
} else {
return index1 !== -1 ? -1 : 1;
}
});
};
validator.getEntityIssues = (entityID, options2) => {
return validator.getSharedEntityIssues([entityID], options2);
};
validator.getRuleKeys = () => {
return Object.keys(_rules);
};
validator.isRuleEnabled = (key) => {
return !_disabledRules[key];
};
validator.toggleRule = (key) => {
if (_disabledRules[key]) {
delete _disabledRules[key];
} else {
_disabledRules[key] = true;
}
corePreferences("validate-disabledRules", Object.keys(_disabledRules).join(","));
validator.validate();
};
validator.disableRules = (keys) => {
_disabledRules = {};
keys.forEach((k) => _disabledRules[k] = true);
corePreferences("validate-disabledRules", Object.keys(_disabledRules).join(","));
validator.validate();
};
validator.ignoreIssue = (issueID) => {
_ignoredIssueIDs.add(issueID);
};
validator.validate = () => {
const baseGraph = context.history().base();
if (!_headCache.graph)
_headCache.graph = baseGraph;
if (!_baseCache.graph)
_baseCache.graph = baseGraph;
const prevGraph = _headCache.graph;
const currGraph = context.graph();
if (currGraph === prevGraph) {
_headIsCurrent = true;
dispatch10.call("validated");
return Promise.resolve();
}
if (_headPromise) {
_headIsCurrent = false;
return _headPromise;
}
_headCache.graph = currGraph;
_completeDiff = context.history().difference().complete();
const incrementalDiff = coreDifference(prevGraph, currGraph);
let entityIDs = Object.keys(incrementalDiff.complete());
entityIDs = _headCache.withAllRelatedEntities(entityIDs);
if (!entityIDs.size) {
dispatch10.call("validated");
return Promise.resolve();
}
_headPromise = validateEntitiesAsync(entityIDs, _headCache).then(() => updateResolvedIssues(entityIDs)).then(() => dispatch10.call("validated")).catch(() => {
}).then(() => {
_headPromise = null;
if (!_headIsCurrent) {
validator.validate();
}
});
return _headPromise;
};
context.history().on("restore.validator", validator.validate).on("undone.validator", validator.validate).on("redone.validator", validator.validate).on("reset.validator", () => {
reset(false);
validator.validate();
});
context.on("exit.validator", validator.validate);
context.history().on("merge.validator", (entities) => {
if (!entities)
return;
const baseGraph = context.history().base();
if (!_headCache.graph)
_headCache.graph = baseGraph;
if (!_baseCache.graph)
_baseCache.graph = baseGraph;
let entityIDs = entities.map((entity) => entity.id);
entityIDs = _baseCache.withAllRelatedEntities(entityIDs);
validateEntitiesAsync(entityIDs, _baseCache);
});
function validateEntity(entity, graph) {
let result = { issues: [], provisional: false };
Object.keys(_rules).forEach(runValidation);
return result;
function runValidation(key) {
const fn = _rules[key];
if (typeof fn !== "function") {
console.error("no such validation rule = " + key);
return;
}
let detected = fn(entity, graph);
if (detected.provisional) {
result.provisional = true;
}
detected = detected.filter(applySeverityOverrides);
result.issues = result.issues.concat(detected);
function applySeverityOverrides(issue) {
const type3 = issue.type;
const subtype = issue.subtype || "";
let i2;
for (i2 = 0; i2 < _errorOverrides.length; i2++) {
if (_errorOverrides[i2].type.test(type3) && _errorOverrides[i2].subtype.test(subtype)) {
issue.severity = "error";
return true;
}
}
for (i2 = 0; i2 < _warningOverrides.length; i2++) {
if (_warningOverrides[i2].type.test(type3) && _warningOverrides[i2].subtype.test(subtype)) {
issue.severity = "warning";
return true;
}
}
for (i2 = 0; i2 < _disableOverrides.length; i2++) {
if (_disableOverrides[i2].type.test(type3) && _disableOverrides[i2].subtype.test(subtype)) {
return false;
}
}
return true;
}
}
}
function updateResolvedIssues(entityIDs) {
entityIDs.forEach((entityID) => {
const baseIssues = _baseCache.issuesByEntityID[entityID];
if (!baseIssues)
return;
baseIssues.forEach((issueID) => {
const issue = _baseCache.issuesByIssueID[issueID];
const userModified = (issue.entityIds || []).some((id2) => _completeDiff.hasOwnProperty(id2));
if (userModified && !_headCache.issuesByIssueID[issueID]) {
_resolvedIssueIDs.add(issueID);
} else {
_resolvedIssueIDs.delete(issueID);
}
});
});
}
function validateEntitiesAsync(entityIDs, cache) {
const jobs = Array.from(entityIDs).map((entityID) => {
if (cache.queuedEntityIDs.has(entityID))
return null;
cache.queuedEntityIDs.add(entityID);
cache.uncacheEntityID(entityID);
return () => {
cache.queuedEntityIDs.delete(entityID);
const graph = cache.graph;
if (!graph)
return;
const entity = graph.hasEntity(entityID);
if (!entity)
return;
const result = validateEntity(entity, graph);
if (result.provisional) {
cache.provisionalEntityIDs.add(entityID);
}
cache.cacheIssues(result.issues);
};
}).filter(Boolean);
cache.queue = cache.queue.concat(utilArrayChunk(jobs, 100));
if (cache.queuePromise)
return cache.queuePromise;
cache.queuePromise = processQueue(cache).then(() => revalidateProvisionalEntities(cache)).catch(() => {
}).finally(() => cache.queuePromise = null);
return cache.queuePromise;
}
function revalidateProvisionalEntities(cache) {
if (!cache.provisionalEntityIDs.size)
return;
const handle = window.setTimeout(() => {
_deferredST.delete(handle);
if (!cache.provisionalEntityIDs.size)
return;
validateEntitiesAsync(Array.from(cache.provisionalEntityIDs), cache);
}, RETRY);
_deferredST.add(handle);
}
function processQueue(cache) {
if (!cache.queue.length)
return Promise.resolve();
const chunk = cache.queue.pop();
return new Promise((resolvePromise, rejectPromise) => {
const handle = window.requestIdleCallback(() => {
delete _deferredRIC[handle];
chunk.forEach((job) => job());
resolvePromise();
});
_deferredRIC[handle] = rejectPromise;
}).then(() => {
if (cache.queue.length % 25 === 0)
dispatch10.call("validated");
}).then(() => processQueue(cache));
}
return validator;
}
function validationCache(which) {
let cache = {
which,
graph: null,
queue: [],
queuePromise: null,
queuedEntityIDs: /* @__PURE__ */ new Set(),
provisionalEntityIDs: /* @__PURE__ */ new Set(),
issuesByIssueID: {},
issuesByEntityID: {}
};
cache.cacheIssue = (issue) => {
(issue.entityIds || []).forEach((entityID) => {
if (!cache.issuesByEntityID[entityID]) {
cache.issuesByEntityID[entityID] = /* @__PURE__ */ new Set();
}
cache.issuesByEntityID[entityID].add(issue.id);
});
cache.issuesByIssueID[issue.id] = issue;
};
cache.uncacheIssue = (issue) => {
(issue.entityIds || []).forEach((entityID) => {
if (cache.issuesByEntityID[entityID]) {
cache.issuesByEntityID[entityID].delete(issue.id);
}
});
delete cache.issuesByIssueID[issue.id];
};
cache.cacheIssues = (issues) => {
issues.forEach(cache.cacheIssue);
};
cache.uncacheIssues = (issues) => {
issues.forEach(cache.uncacheIssue);
};
cache.uncacheIssuesOfType = (type3) => {
const issuesOfType = Object.values(cache.issuesByIssueID).filter((issue) => issue.type === type3);
cache.uncacheIssues(issuesOfType);
};
cache.uncacheEntityID = (entityID) => {
const entityIssueIDs = cache.issuesByEntityID[entityID];
if (entityIssueIDs) {
entityIssueIDs.forEach((issueID) => {
const issue = cache.issuesByIssueID[issueID];
if (issue) {
cache.uncacheIssue(issue);
} else {
delete cache.issuesByIssueID[issueID];
}
});
}
delete cache.issuesByEntityID[entityID];
cache.provisionalEntityIDs.delete(entityID);
};
cache.withAllRelatedEntities = (entityIDs) => {
let result = /* @__PURE__ */ new Set();
(entityIDs || []).forEach((entityID) => {
result.add(entityID);
const entityIssueIDs = cache.issuesByEntityID[entityID];
if (entityIssueIDs) {
entityIssueIDs.forEach((issueID) => {
const issue = cache.issuesByIssueID[issueID];
if (issue) {
(issue.entityIds || []).forEach((relatedID) => result.add(relatedID));
} else {
delete cache.issuesByIssueID[issueID];
}
});
}
});
return result;
};
return cache;
}
// modules/core/uploader.js
function coreUploader(context) {
var dispatch10 = dispatch_default("saveStarted", "saveEnded", "willAttemptUpload", "progressChanged", "resultNoChanges", "resultErrors", "resultConflicts", "resultSuccess");
var _isSaving = false;
var _conflicts = [];
var _errors = [];
var _origChanges;
var _discardTags = {};
_mainFileFetcher.get("discarded").then(function(d) {
_discardTags = d;
}).catch(function() {
});
var uploader = utilRebind({}, dispatch10, "on");
uploader.isSaving = function() {
return _isSaving;
};
uploader.save = function(changeset, tryAgain, checkConflicts) {
if (_isSaving && !tryAgain) {
return;
}
var osm = context.connection();
if (!osm)
return;
if (!osm.authenticated()) {
osm.authenticate(function(err) {
if (!err) {
uploader.save(changeset, tryAgain, checkConflicts);
}
});
return;
}
if (!_isSaving) {
_isSaving = true;
dispatch10.call("saveStarted", this);
}
var history = context.history();
_conflicts = [];
_errors = [];
_origChanges = history.changes(actionDiscardTags(history.difference(), _discardTags));
if (!tryAgain) {
history.perform(actionNoop());
}
if (!checkConflicts) {
upload(changeset);
} else {
performFullConflictCheck(changeset);
}
};
function performFullConflictCheck(changeset) {
var osm = context.connection();
if (!osm)
return;
var history = context.history();
var localGraph = context.graph();
var remoteGraph = coreGraph(history.base(), true);
var summary = history.difference().summary();
var _toCheck = [];
for (var i2 = 0; i2 < summary.length; i2++) {
var item = summary[i2];
if (item.changeType === "modified") {
_toCheck.push(item.entity.id);
}
}
var _toLoad = withChildNodes(_toCheck, localGraph);
var _loaded = {};
var _toLoadCount = 0;
var _toLoadTotal = _toLoad.length;
if (_toCheck.length) {
dispatch10.call("progressChanged", this, _toLoadCount, _toLoadTotal);
_toLoad.forEach(function(id2) {
_loaded[id2] = false;
});
osm.loadMultiple(_toLoad, loaded);
} else {
upload(changeset);
}
return;
function withChildNodes(ids, graph) {
var s = new Set(ids);
ids.forEach(function(id2) {
var entity = graph.entity(id2);
if (entity.type !== "way")
return;
graph.childNodes(entity).forEach(function(child) {
if (child.version !== void 0) {
s.add(child.id);
}
});
});
return Array.from(s);
}
function loaded(err, result) {
if (_errors.length)
return;
if (err) {
_errors.push({
msg: err.message || err.responseText,
details: [_t("save.status_code", { code: err.status })]
});
didResultInErrors();
} else {
var loadMore = [];
result.data.forEach(function(entity) {
remoteGraph.replace(entity);
_loaded[entity.id] = true;
_toLoad = _toLoad.filter(function(val) {
return val !== entity.id;
});
if (!entity.visible)
return;
var i3, id2;
if (entity.type === "way") {
for (i3 = 0; i3 < entity.nodes.length; i3++) {
id2 = entity.nodes[i3];
if (_loaded[id2] === void 0) {
_loaded[id2] = false;
loadMore.push(id2);
}
}
} else if (entity.type === "relation" && entity.isMultipolygon()) {
for (i3 = 0; i3 < entity.members.length; i3++) {
id2 = entity.members[i3].id;
if (_loaded[id2] === void 0) {
_loaded[id2] = false;
loadMore.push(id2);
}
}
}
});
_toLoadCount += result.data.length;
_toLoadTotal += loadMore.length;
dispatch10.call("progressChanged", this, _toLoadCount, _toLoadTotal);
if (loadMore.length) {
_toLoad.push.apply(_toLoad, loadMore);
osm.loadMultiple(loadMore, loaded);
}
if (!_toLoad.length) {
detectConflicts();
upload(changeset);
}
}
}
function detectConflicts() {
function choice(id2, text2, action) {
return {
id: id2,
text: text2,
action: function() {
history.replace(action);
}
};
}
function formatUser(d) {
return '' + escape_default(d) + "";
}
function entityName(entity) {
return utilDisplayName(entity) || utilDisplayType(entity.id) + " " + entity.id;
}
function sameVersions(local, remote) {
if (local.version !== remote.version)
return false;
if (local.type === "way") {
var children2 = utilArrayUnion(local.nodes, remote.nodes);
for (var i3 = 0; i3 < children2.length; i3++) {
var a = localGraph.hasEntity(children2[i3]);
var b = remoteGraph.hasEntity(children2[i3]);
if (a && b && a.version !== b.version)
return false;
}
}
return true;
}
_toCheck.forEach(function(id2) {
var local = localGraph.entity(id2);
var remote = remoteGraph.entity(id2);
if (sameVersions(local, remote))
return;
var merge3 = actionMergeRemoteChanges(id2, localGraph, remoteGraph, _discardTags, formatUser);
history.replace(merge3);
var mergeConflicts = merge3.conflicts();
if (!mergeConflicts.length)
return;
var forceLocal = actionMergeRemoteChanges(id2, localGraph, remoteGraph, _discardTags).withOption("force_local");
var forceRemote = actionMergeRemoteChanges(id2, localGraph, remoteGraph, _discardTags).withOption("force_remote");
var keepMine = _t("save.conflict." + (remote.visible ? "keep_local" : "restore"));
var keepTheirs = _t("save.conflict." + (remote.visible ? "keep_remote" : "delete"));
_conflicts.push({
id: id2,
name: entityName(local),
details: mergeConflicts,
chosen: 1,
choices: [
choice(id2, keepMine, forceLocal),
choice(id2, keepTheirs, forceRemote)
]
});
});
}
}
function upload(changeset) {
var osm = context.connection();
if (!osm) {
_errors.push({ msg: "No OSM Service" });
}
if (_conflicts.length) {
didResultInConflicts(changeset);
} else if (_errors.length) {
didResultInErrors();
} else {
var history = context.history();
var changes = history.changes(actionDiscardTags(history.difference(), _discardTags));
if (changes.modified.length || changes.created.length || changes.deleted.length) {
dispatch10.call("willAttemptUpload", this);
osm.putChangeset(changeset, changes, uploadCallback);
} else {
didResultInNoChanges();
}
}
}
function uploadCallback(err, changeset) {
if (err) {
if (err.status === 409) {
uploader.save(changeset, true, true);
} else {
_errors.push({
msg: err.message || err.responseText,
details: [_t("save.status_code", { code: err.status })]
});
didResultInErrors();
}
} else {
didResultInSuccess(changeset);
}
}
function didResultInNoChanges() {
dispatch10.call("resultNoChanges", this);
endSave();
context.flush();
}
function didResultInErrors() {
context.history().pop();
dispatch10.call("resultErrors", this, _errors);
endSave();
}
function didResultInConflicts(changeset) {
_conflicts.sort(function(a, b) {
return b.id.localeCompare(a.id);
});
dispatch10.call("resultConflicts", this, changeset, _conflicts, _origChanges);
endSave();
}
function didResultInSuccess(changeset) {
context.history().clearSaved();
dispatch10.call("resultSuccess", this, changeset);
window.setTimeout(function() {
endSave();
context.flush();
}, 2500);
}
function endSave() {
_isSaving = false;
dispatch10.call("saveEnded", this);
}
uploader.cancelConflictResolution = function() {
context.history().pop();
};
uploader.processResolvedConflicts = function(changeset) {
var history = context.history();
for (var i2 = 0; i2 < _conflicts.length; i2++) {
if (_conflicts[i2].chosen === 1) {
var entity = context.hasEntity(_conflicts[i2].id);
if (entity && entity.type === "way") {
var children2 = utilArrayUniq(entity.nodes);
for (var j2 = 0; j2 < children2.length; j2++) {
history.replace(actionRevert(children2[j2]));
}
}
history.replace(actionRevert(_conflicts[i2].id));
}
}
uploader.save(changeset, true, false);
};
uploader.reset = function() {
};
return uploader;
}
// modules/renderer/background_source.js
var import_lodash2 = __toESM(require_lodash());
// modules/util/IntervalTasksQueue.js
var IntervalTasksQueue = class {
constructor(intervalInMs) {
this.intervalInMs = intervalInMs;
this.pendingHandles = [];
this.time = 0;
}
enqueue(task) {
let taskTimeout = this.time;
this.time += this.intervalInMs;
this.pendingHandles.push(setTimeout(() => {
this.time -= this.intervalInMs;
task();
}, taskTimeout));
}
clear() {
this.pendingHandles.forEach((timeoutHandle) => {
clearTimeout(timeoutHandle);
});
this.pendingHandles = [];
this.time = 0;
}
};
// modules/renderer/background_source.js
var isRetina = window.devicePixelRatio && window.devicePixelRatio >= 2;
window.matchMedia(`
(-webkit-min-device-pixel-ratio: 2), /* Safari */
(min-resolution: 2dppx), /* standard */
(min-resolution: 192dpi) /* fallback */
`).addListener(function() {
isRetina = window.devicePixelRatio && window.devicePixelRatio >= 2;
});
function localeDateString(s) {
if (!s)
return null;
var options2 = { day: "numeric", month: "short", year: "numeric" };
var d = new Date(s);
if (isNaN(d.getTime()))
return null;
return d.toLocaleDateString(_mainLocalizer.localeCode(), options2);
}
function vintageRange(vintage) {
var s;
if (vintage.start || vintage.end) {
s = vintage.start || "?";
if (vintage.start !== vintage.end) {
s += " - " + (vintage.end || "?");
}
}
return s;
}
function rendererBackgroundSource(data) {
var source = Object.assign({}, data);
var _offset = [0, 0];
var _name = source.name;
var _description = source.description;
var _best = !!source.best;
var _template = source.encrypted ? utilAesDecrypt(source.template) : source.template;
source.tileSize = data.tileSize || 256;
source.zoomExtent = data.zoomExtent || [0, 22];
source.overzoom = data.overzoom !== false;
source.offset = function(val) {
if (!arguments.length)
return _offset;
_offset = val;
return source;
};
source.nudge = function(val, zoomlevel) {
_offset[0] += val[0] / Math.pow(2, zoomlevel);
_offset[1] += val[1] / Math.pow(2, zoomlevel);
return source;
};
source.name = function() {
var id_safe = source.id.replace(/\./g, "");
return _t("imagery." + id_safe + ".name", { default: (0, import_lodash2.escape)(_name) });
};
source.label = function() {
var id_safe = source.id.replace(/\./g, "");
return _t.html("imagery." + id_safe + ".name", { default: (0, import_lodash2.escape)(_name) });
};
source.description = function() {
var id_safe = source.id.replace(/\./g, "");
return _t.html("imagery." + id_safe + ".description", { default: (0, import_lodash2.escape)(_description) });
};
source.best = function() {
return _best;
};
source.area = function() {
if (!data.polygon)
return Number.MAX_VALUE;
var area = area_default({ type: "MultiPolygon", coordinates: [data.polygon] });
return isNaN(area) ? 0 : area;
};
source.imageryUsed = function() {
return _name || source.id;
};
source.template = function(val) {
if (!arguments.length)
return _template;
if (source.id === "custom" || source.id === "Bing") {
_template = val;
}
return source;
};
source.url = function(coord2) {
var result = _template.replace(/#.*/su, "");
if (result === "")
return result;
if (!source.type || source.id === "custom") {
if (/SERVICE=WMS|\{(proj|wkid|bbox)\}/.test(result)) {
source.type = "wms";
source.projection = "EPSG:3857";
} else if (/\{(x|y)\}/.test(result)) {
source.type = "tms";
} else if (/\{u\}/.test(result)) {
source.type = "bing";
}
}
if (source.type === "wms") {
var tileToProjectedCoords = function(x, y, z) {
var zoomSize = Math.pow(2, z);
var lon = x / zoomSize * Math.PI * 2 - Math.PI;
var lat = Math.atan(Math.sinh(Math.PI * (1 - 2 * y / zoomSize)));
switch (source.projection) {
case "EPSG:4326":
return {
x: lon * 180 / Math.PI,
y: lat * 180 / Math.PI
};
default:
var mercCoords = mercatorRaw(lon, lat);
return {
x: 2003750834e-2 / Math.PI * mercCoords[0],
y: 2003750834e-2 / Math.PI * mercCoords[1]
};
}
};
var tileSize = source.tileSize;
var projection2 = source.projection;
var minXmaxY = tileToProjectedCoords(coord2[0], coord2[1], coord2[2]);
var maxXminY = tileToProjectedCoords(coord2[0] + 1, coord2[1] + 1, coord2[2]);
result = result.replace(/\{(\w+)\}/g, function(token, key) {
switch (key) {
case "width":
case "height":
return tileSize;
case "proj":
return projection2;
case "wkid":
return projection2.replace(/^EPSG:/, "");
case "bbox":
if (projection2 === "EPSG:4326" && /VERSION=1.3|CRS={proj}/.test(source.template().toUpperCase())) {
return maxXminY.y + "," + minXmaxY.x + "," + minXmaxY.y + "," + maxXminY.x;
} else {
return minXmaxY.x + "," + maxXminY.y + "," + maxXminY.x + "," + minXmaxY.y;
}
case "w":
return minXmaxY.x;
case "s":
return maxXminY.y;
case "n":
return maxXminY.x;
case "e":
return minXmaxY.y;
default:
return token;
}
});
} else if (source.type === "tms") {
result = result.replace("{x}", coord2[0]).replace("{y}", coord2[1]).replace(/\{[t-]y\}/, Math.pow(2, coord2[2]) - coord2[1] - 1).replace(/\{z(oom)?\}/, coord2[2]).replace(/\{@2x\}|\{r\}/, isRetina ? "@2x" : "");
} else if (source.type === "bing") {
result = result.replace("{u}", function() {
var u = "";
for (var zoom = coord2[2]; zoom > 0; zoom--) {
var b = 0;
var mask = 1 << zoom - 1;
if ((coord2[0] & mask) !== 0)
b++;
if ((coord2[1] & mask) !== 0)
b += 2;
u += b.toString();
}
return u;
});
}
result = result.replace(/\{switch:([^}]+)\}/, function(s, r) {
var subdomains = r.split(",");
return subdomains[(coord2[0] + coord2[1]) % subdomains.length];
});
return result;
};
source.validZoom = function(z) {
return source.zoomExtent[0] <= z && (source.overzoom || source.zoomExtent[1] > z);
};
source.isLocatorOverlay = function() {
return source.id === "mapbox_locator_overlay";
};
source.isHidden = function() {
return source.id === "DigitalGlobe-Premium-vintage" || source.id === "DigitalGlobe-Standard-vintage";
};
source.copyrightNotices = function() {
};
source.getMetadata = function(center, tileCoord, callback) {
var vintage = {
start: localeDateString(source.startDate),
end: localeDateString(source.endDate)
};
vintage.range = vintageRange(vintage);
var metadata = { vintage };
callback(null, metadata);
};
return source;
}
rendererBackgroundSource.Bing = function(data, dispatch10) {
data.template = "https://ecn.t{switch:0,1,2,3}.tiles.virtualearth.net/tiles/a{u}.jpeg?g=1&pr=odbl&n=z";
var bing = rendererBackgroundSource(data);
var key = utilAesDecrypt("5c875730b09c6b422433e807e1ff060b6536c791dbfffcffc4c6b18a1bdba1f14593d151adb50e19e1be1ab19aef813bf135d0f103475e5c724dec94389e45d0");
const strictParam = "n";
var url = "https://dev.virtualearth.net/REST/v1/Imagery/Metadata/AerialOSM?include=ImageryProviders&uriScheme=https&key=" + key;
var cache = {};
var inflight = {};
var providers = [];
var taskQueue = new IntervalTasksQueue(250);
var metadataLastZoom = -1;
json_default(url).then(function(json) {
let imageryResource = json.resourceSets[0].resources[0];
let template = imageryResource.imageUrl;
let subDomains = imageryResource.imageUrlSubdomains;
let subDomainNumbers = subDomains.map((subDomain) => {
return subDomain.substring(1);
}).join(",");
template = template.replace("{subdomain}", `t{switch:${subDomainNumbers}}`).replace("{quadkey}", "{u}");
if (!new URLSearchParams(template).has(strictParam)) {
template += `&${strictParam}=z`;
}
bing.template(template);
providers = imageryResource.imageryProviders.map(function(provider) {
return {
attribution: provider.attribution,
areas: provider.coverageAreas.map(function(area) {
return {
zoom: [area.zoomMin, area.zoomMax],
extent: geoExtent([area.bbox[1], area.bbox[0]], [area.bbox[3], area.bbox[2]])
};
})
};
});
dispatch10.call("change");
}).catch(function() {
});
bing.copyrightNotices = function(zoom, extent) {
zoom = Math.min(zoom, 21);
return providers.filter(function(provider) {
return provider.areas.some(function(area) {
return extent.intersects(area.extent) && area.zoom[0] <= zoom && area.zoom[1] >= zoom;
});
}).map(function(provider) {
return provider.attribution;
}).join(", ");
};
bing.getMetadata = function(center, tileCoord, callback) {
var tileID = tileCoord.slice(0, 3).join("/");
var zoom = Math.min(tileCoord[2], 21);
var centerPoint = center[1] + "," + center[0];
var url2 = "https://dev.virtualearth.net/REST/v1/Imagery/BasicMetadata/AerialOSM/" + centerPoint + "?zl=" + zoom + "&key=" + key;
if (inflight[tileID])
return;
if (!cache[tileID]) {
cache[tileID] = {};
}
if (cache[tileID] && cache[tileID].metadata) {
return callback(null, cache[tileID].metadata);
}
inflight[tileID] = true;
if (metadataLastZoom !== tileCoord[2]) {
metadataLastZoom = tileCoord[2];
taskQueue.clear();
}
taskQueue.enqueue(() => {
json_default(url2).then(function(result) {
delete inflight[tileID];
if (!result) {
throw new Error("Unknown Error");
}
var vintage = {
start: localeDateString(result.resourceSets[0].resources[0].vintageStart),
end: localeDateString(result.resourceSets[0].resources[0].vintageEnd)
};
vintage.range = vintageRange(vintage);
var metadata = { vintage };
cache[tileID].metadata = metadata;
if (callback)
callback(null, metadata);
}).catch(function(err) {
delete inflight[tileID];
if (callback)
callback(err.message);
});
});
};
bing.terms_url = "https://blog.openstreetmap.org/2010/11/30/microsoft-imagery-details";
return bing;
};
rendererBackgroundSource.Esri = function(data) {
if (data.template.match(/blankTile/) === null) {
data.template = data.template + "?blankTile=false";
}
var esri = rendererBackgroundSource(data);
var cache = {};
var inflight = {};
var _prevCenter;
esri.fetchTilemap = function(center) {
if (_prevCenter && geoSphericalDistance(center, _prevCenter) < 5e3)
return;
_prevCenter = center;
var z = 20;
var dummyUrl = esri.url([1, 2, 3]);
var x = Math.floor((center[0] + 180) / 360 * Math.pow(2, z));
var y = Math.floor((1 - Math.log(Math.tan(center[1] * Math.PI / 180) + 1 / Math.cos(center[1] * Math.PI / 180)) / Math.PI) / 2 * Math.pow(2, z));
var tilemapUrl = dummyUrl.replace(/tile\/[0-9]+\/[0-9]+\/[0-9]+\?blankTile=false/, "tilemap") + "/" + z + "/" + y + "/" + x + "/8/8";
json_default(tilemapUrl).then(function(tilemap) {
if (!tilemap) {
throw new Error("Unknown Error");
}
var hasTiles = true;
for (var i2 = 0; i2 < tilemap.data.length; i2++) {
if (!tilemap.data[i2]) {
hasTiles = false;
break;
}
}
esri.zoomExtent[1] = hasTiles ? 22 : 19;
}).catch(function() {
});
};
esri.getMetadata = function(center, tileCoord, callback) {
if (esri.id !== "EsriWorldImagery") {
return callback(null, {});
}
var tileID = tileCoord.slice(0, 3).join("/");
var zoom = Math.min(tileCoord[2], esri.zoomExtent[1]);
var centerPoint = center[0] + "," + center[1];
var unknown = _t("info_panels.background.unknown");
var vintage = {};
var metadata = {};
if (inflight[tileID])
return;
var url = "https://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/4/query";
url += "?returnGeometry=false&geometry=" + centerPoint + "&inSR=4326&geometryType=esriGeometryPoint&outFields=*&f=json";
if (!cache[tileID]) {
cache[tileID] = {};
}
if (cache[tileID] && cache[tileID].metadata) {
return callback(null, cache[tileID].metadata);
}
inflight[tileID] = true;
json_default(url).then(function(result) {
delete inflight[tileID];
result = result.features.map((f2) => f2.attributes).filter((a) => a.MinMapLevel <= zoom && a.MaxMapLevel >= zoom)[0];
if (!result) {
throw new Error("Unknown Error");
} else if (result.features && result.features.length < 1) {
throw new Error("No Results");
} else if (result.error && result.error.message) {
throw new Error(result.error.message);
}
var captureDate = localeDateString(result.SRC_DATE2);
vintage = {
start: captureDate,
end: captureDate,
range: captureDate
};
metadata = {
vintage,
source: clean2(result.NICE_NAME),
description: clean2(result.NICE_DESC),
resolution: clean2(+parseFloat(result.SRC_RES).toFixed(4)),
accuracy: clean2(+parseFloat(result.SRC_ACC).toFixed(4))
};
if (isFinite(metadata.resolution)) {
metadata.resolution += " m";
}
if (isFinite(metadata.accuracy)) {
metadata.accuracy += " m";
}
cache[tileID].metadata = metadata;
if (callback)
callback(null, metadata);
}).catch(function(err) {
delete inflight[tileID];
if (callback)
callback(err.message);
});
function clean2(val) {
return String(val).trim() || unknown;
}
};
return esri;
};
rendererBackgroundSource.None = function() {
var source = rendererBackgroundSource({ id: "none", template: "" });
source.name = function() {
return _t("background.none");
};
source.label = function() {
return _t.html("background.none");
};
source.imageryUsed = function() {
return null;
};
source.area = function() {
return -1;
};
return source;
};
rendererBackgroundSource.Custom = function(template) {
var source = rendererBackgroundSource({ id: "custom", template });
source.name = function() {
return _t("background.custom");
};
source.label = function() {
return _t.html("background.custom");
};
source.imageryUsed = function() {
var cleaned = source.template();
if (cleaned.indexOf("?") !== -1) {
var parts = cleaned.split("?", 2);
var qs = utilStringQs(parts[1]);
["access_token", "connectId", "token"].forEach(function(param) {
if (qs[param]) {
qs[param] = "{apikey}";
}
});
cleaned = parts[0] + "?" + utilQsString(qs, true);
}
cleaned = cleaned.replace(/token\/(\w+)/, "token/{apikey}").replace(/key=(\w+)/, "key={apikey}");
return "Custom (" + cleaned + " )";
};
source.area = function() {
return -2;
};
return source;
};
// modules/renderer/background.js
var import_which_polygon4 = __toESM(require_which_polygon());
// modules/renderer/tile_layer.js
function rendererTileLayer(context) {
var transformProp = utilPrefixCSSProperty("Transform");
var tiler8 = utilTiler();
var _tileSize = 256;
var _projection;
var _cache4 = {};
var _tileOrigin;
var _zoom;
var _source;
function tileSizeAtZoom(d, z) {
var EPSILON = 2e-3;
return _tileSize * Math.pow(2, z - d[2]) / _tileSize + EPSILON;
}
function atZoom(t, distance) {
var power = Math.pow(2, distance);
return [
Math.floor(t[0] * power),
Math.floor(t[1] * power),
t[2] + distance
];
}
function lookUp(d) {
for (var up = -1; up > -d[2]; up--) {
var tile = atZoom(d, up);
if (_cache4[_source.url(tile)] !== false) {
return tile;
}
}
}
function uniqueBy(a, n2) {
var o = [];
var seen = {};
for (var i2 = 0; i2 < a.length; i2++) {
if (seen[a[i2][n2]] === void 0) {
o.push(a[i2]);
seen[a[i2][n2]] = true;
}
}
return o;
}
function addSource(d) {
d.push(_source.url(d));
return d;
}
function background(selection2) {
_zoom = geoScaleToZoom(_projection.scale(), _tileSize);
var pixelOffset;
if (_source) {
pixelOffset = [
_source.offset()[0] * Math.pow(2, _zoom),
_source.offset()[1] * Math.pow(2, _zoom)
];
} else {
pixelOffset = [0, 0];
}
var translate = [
_projection.translate()[0] + pixelOffset[0],
_projection.translate()[1] + pixelOffset[1]
];
tiler8.scale(_projection.scale() * 2 * Math.PI).translate(translate);
_tileOrigin = [
_projection.scale() * Math.PI - translate[0],
_projection.scale() * Math.PI - translate[1]
];
render(selection2);
}
function render(selection2) {
if (!_source)
return;
var requests = [];
var showDebug = context.getDebug("tile") && !_source.overlay;
if (_source.validZoom(_zoom)) {
tiler8.skipNullIsland(!!_source.overlay);
tiler8().forEach(function(d) {
addSource(d);
if (d[3] === "")
return;
if (typeof d[3] !== "string")
return;
requests.push(d);
if (_cache4[d[3]] === false && lookUp(d)) {
requests.push(addSource(lookUp(d)));
}
});
requests = uniqueBy(requests, 3).filter(function(r) {
return _cache4[r[3]] !== false;
});
}
function load(d3_event, d) {
_cache4[d[3]] = true;
select_default2(this).on("error", null).on("load", null).classed("tile-loaded", true);
render(selection2);
}
function error(d3_event, d) {
_cache4[d[3]] = false;
select_default2(this).on("error", null).on("load", null).remove();
render(selection2);
}
function imageTransform(d) {
var ts = _tileSize * Math.pow(2, _zoom - d[2]);
var scale = tileSizeAtZoom(d, _zoom);
return "translate(" + (d[0] * ts - _tileOrigin[0]) + "px," + (d[1] * ts - _tileOrigin[1]) + "px) scale(" + scale + "," + scale + ")";
}
function tileCenter(d) {
var ts = _tileSize * Math.pow(2, _zoom - d[2]);
return [
d[0] * ts - _tileOrigin[0] + ts / 2,
d[1] * ts - _tileOrigin[1] + ts / 2
];
}
function debugTransform(d) {
var coord2 = tileCenter(d);
return "translate(" + coord2[0] + "px," + coord2[1] + "px)";
}
var dims = tiler8.size();
var mapCenter = [dims[0] / 2, dims[1] / 2];
var minDist = Math.max(dims[0], dims[1]);
var nearCenter;
requests.forEach(function(d) {
var c = tileCenter(d);
var dist = geoVecLength(c, mapCenter);
if (dist < minDist) {
minDist = dist;
nearCenter = d;
}
});
var image = selection2.selectAll("img").data(requests, function(d) {
return d[3];
});
image.exit().style(transformProp, imageTransform).classed("tile-removing", true).classed("tile-center", false).each(function() {
var tile = select_default2(this);
window.setTimeout(function() {
if (tile.classed("tile-removing")) {
tile.remove();
}
}, 300);
});
image.enter().append("img").attr("class", "tile").attr("alt", "").attr("draggable", "false").style("width", _tileSize + "px").style("height", _tileSize + "px").attr("src", function(d) {
return d[3];
}).on("error", error).on("load", load).merge(image).style(transformProp, imageTransform).classed("tile-debug", showDebug).classed("tile-removing", false).classed("tile-center", function(d) {
return d === nearCenter;
});
var debug2 = selection2.selectAll(".tile-label-debug").data(showDebug ? requests : [], function(d) {
return d[3];
});
debug2.exit().remove();
if (showDebug) {
var debugEnter = debug2.enter().append("div").attr("class", "tile-label-debug");
debugEnter.append("div").attr("class", "tile-label-debug-coord");
debugEnter.append("div").attr("class", "tile-label-debug-vintage");
debug2 = debug2.merge(debugEnter);
debug2.style(transformProp, debugTransform);
debug2.selectAll(".tile-label-debug-coord").text(function(d) {
return d[2] + " / " + d[0] + " / " + d[1];
});
debug2.selectAll(".tile-label-debug-vintage").each(function(d) {
var span = select_default2(this);
var center = context.projection.invert(tileCenter(d));
_source.getMetadata(center, d, function(err, result) {
if (result && result.vintage && result.vintage.range) {
span.text(result.vintage.range);
} else {
span.html(_t.html("info_panels.background.vintage") + ": " + _t.html("info_panels.background.unknown"));
}
});
});
}
}
background.projection = function(val) {
if (!arguments.length)
return _projection;
_projection = val;
return background;
};
background.dimensions = function(val) {
if (!arguments.length)
return tiler8.size();
tiler8.size(val);
return background;
};
background.source = function(val) {
if (!arguments.length)
return _source;
_source = val;
_tileSize = _source.tileSize;
_cache4 = {};
tiler8.tileSize(_source.tileSize).zoomExtent(_source.zoomExtent);
return background;
};
return background;
}
// modules/renderer/background.js
var _imageryIndex = null;
function rendererBackground(context) {
const dispatch10 = dispatch_default("change");
const baseLayer = rendererTileLayer(context).projection(context.projection);
let _checkedBlocklists = [];
let _isValid = true;
let _overlayLayers = [];
let _brightness = 1;
let _contrast = 1;
let _saturation = 1;
let _sharpness = 1;
function ensureImageryIndex() {
return _mainFileFetcher.get("imagery").then((sources) => {
if (_imageryIndex)
return _imageryIndex;
_imageryIndex = {
imagery: sources,
features: {}
};
const features2 = sources.map((source) => {
if (!source.polygon)
return null;
const rings = source.polygon.map((ring) => [ring]);
const feature3 = {
type: "Feature",
properties: { id: source.id },
geometry: { type: "MultiPolygon", coordinates: rings }
};
_imageryIndex.features[source.id] = feature3;
return feature3;
}).filter(Boolean);
_imageryIndex.query = (0, import_which_polygon4.default)({ type: "FeatureCollection", features: features2 });
_imageryIndex.backgrounds = sources.map((source) => {
if (source.type === "bing") {
return rendererBackgroundSource.Bing(source, dispatch10);
} else if (/^EsriWorldImagery/.test(source.id)) {
return rendererBackgroundSource.Esri(source);
} else {
return rendererBackgroundSource(source);
}
});
_imageryIndex.backgrounds.unshift(rendererBackgroundSource.None());
let template = corePreferences("background-custom-template") || "";
const custom = rendererBackgroundSource.Custom(template);
_imageryIndex.backgrounds.unshift(custom);
return _imageryIndex;
});
}
function background(selection2) {
const currSource = baseLayer.source();
if (context.map().zoom() > 18) {
if (currSource && /^EsriWorldImagery/.test(currSource.id)) {
const center = context.map().center();
currSource.fetchTilemap(center);
}
}
const sources = background.sources(context.map().extent());
const wasValid = _isValid;
_isValid = !!sources.filter((d) => d === currSource).length;
if (wasValid !== _isValid) {
background.updateImagery();
}
let baseFilter = "";
if (_brightness !== 1) {
baseFilter += ` brightness(${_brightness})`;
}
if (_contrast !== 1) {
baseFilter += ` contrast(${_contrast})`;
}
if (_saturation !== 1) {
baseFilter += ` saturate(${_saturation})`;
}
if (_sharpness < 1) {
const blur = number_default(0.5, 5)(1 - _sharpness);
baseFilter += ` blur(${blur}px)`;
}
let base = selection2.selectAll(".layer-background").data([0]);
base = base.enter().insert("div", ".layer-data").attr("class", "layer layer-background").merge(base);
base.style("filter", baseFilter || null);
let imagery = base.selectAll(".layer-imagery").data([0]);
imagery.enter().append("div").attr("class", "layer layer-imagery").merge(imagery).call(baseLayer);
let maskFilter = "";
let mixBlendMode = "";
if (_sharpness > 1) {
mixBlendMode = "overlay";
maskFilter = "saturate(0) blur(3px) invert(1)";
let contrast = _sharpness - 1;
maskFilter += ` contrast(${contrast})`;
let brightness = number_default(1, 0.85)(_sharpness - 1);
maskFilter += ` brightness(${brightness})`;
}
let mask = base.selectAll(".layer-unsharp-mask").data(_sharpness > 1 ? [0] : []);
mask.exit().remove();
mask.enter().append("div").attr("class", "layer layer-mask layer-unsharp-mask").merge(mask).call(baseLayer).style("filter", maskFilter || null).style("mix-blend-mode", mixBlendMode || null);
let overlays = selection2.selectAll(".layer-overlay").data(_overlayLayers, (d) => d.source().name());
overlays.exit().remove();
overlays.enter().insert("div", ".layer-data").attr("class", "layer layer-overlay").merge(overlays).each((layer, i2, nodes) => select_default2(nodes[i2]).call(layer));
}
background.updateImagery = function() {
let currSource = baseLayer.source();
if (context.inIntro() || !currSource)
return;
let o = _overlayLayers.filter((d) => !d.source().isLocatorOverlay() && !d.source().isHidden()).map((d) => d.source().id).join(",");
const meters = geoOffsetToMeters(currSource.offset());
const EPSILON = 0.01;
const x = +meters[0].toFixed(2);
const y = +meters[1].toFixed(2);
let hash = utilStringQs(window.location.hash);
let id2 = currSource.id;
if (id2 === "custom") {
id2 = `custom:${currSource.template()}`;
}
if (id2) {
hash.background = id2;
} else {
delete hash.background;
}
if (o) {
hash.overlays = o;
} else {
delete hash.overlays;
}
if (Math.abs(x) > EPSILON || Math.abs(y) > EPSILON) {
hash.offset = `${x},${y}`;
} else {
delete hash.offset;
}
if (!window.mocha) {
window.location.replace("#" + utilQsString(hash, true));
}
let imageryUsed = [];
let photoOverlaysUsed = [];
const currUsed = currSource.imageryUsed();
if (currUsed && _isValid) {
imageryUsed.push(currUsed);
}
_overlayLayers.filter((d) => !d.source().isLocatorOverlay() && !d.source().isHidden()).forEach((d) => imageryUsed.push(d.source().imageryUsed()));
const dataLayer = context.layers().layer("data");
if (dataLayer && dataLayer.enabled() && dataLayer.hasData()) {
imageryUsed.push(dataLayer.getSrc());
}
const photoOverlayLayers = {
streetside: "Bing Streetside",
mapillary: "Mapillary Images",
"mapillary-map-features": "Mapillary Map Features",
"mapillary-signs": "Mapillary Signs",
kartaview: "KartaView Images"
};
for (let layerID in photoOverlayLayers) {
const layer = context.layers().layer(layerID);
if (layer && layer.enabled()) {
photoOverlaysUsed.push(layerID);
imageryUsed.push(photoOverlayLayers[layerID]);
}
}
context.history().imageryUsed(imageryUsed);
context.history().photoOverlaysUsed(photoOverlaysUsed);
};
background.sources = (extent, zoom, includeCurrent) => {
if (!_imageryIndex)
return [];
let visible = {};
(_imageryIndex.query.bbox(extent.rectangle(), true) || []).forEach((d) => visible[d.id] = true);
const currSource = baseLayer.source();
const osm = context.connection();
const blocklists = osm && osm.imageryBlocklists() || [];
const blocklistChanged = blocklists.length !== _checkedBlocklists.length || blocklists.some((regex, index) => String(regex) !== _checkedBlocklists[index]);
if (blocklistChanged) {
_imageryIndex.backgrounds.forEach((source) => {
source.isBlocked = blocklists.some((regex) => regex.test(source.template()));
});
_checkedBlocklists = blocklists.map((regex) => String(regex));
}
return _imageryIndex.backgrounds.filter((source) => {
if (includeCurrent && currSource === source)
return true;
if (source.isBlocked)
return false;
if (!source.polygon)
return true;
if (zoom && zoom < 6)
return false;
return visible[source.id];
});
};
background.dimensions = (val) => {
if (!val)
return;
baseLayer.dimensions(val);
_overlayLayers.forEach((layer) => layer.dimensions(val));
};
background.baseLayerSource = function(d) {
if (!arguments.length)
return baseLayer.source();
const osm = context.connection();
if (!osm)
return background;
const blocklists = osm.imageryBlocklists();
const template = d.template();
let fail = false;
let tested = 0;
let regex;
for (let i2 = 0; i2 < blocklists.length; i2++) {
regex = blocklists[i2];
fail = regex.test(template);
tested++;
if (fail)
break;
}
if (!tested) {
regex = /.*\.google(apis)?\..*\/(vt|kh)[\?\/].*([xyz]=.*){3}.*/;
fail = regex.test(template);
}
baseLayer.source(!fail ? d : background.findSource("none"));
dispatch10.call("change");
background.updateImagery();
return background;
};
background.findSource = (id2) => {
if (!id2 || !_imageryIndex)
return null;
return _imageryIndex.backgrounds.find((d) => d.id && d.id === id2);
};
background.bing = () => {
background.baseLayerSource(background.findSource("Bing"));
};
background.showsLayer = (d) => {
const currSource = baseLayer.source();
if (!d || !currSource)
return false;
return d.id === currSource.id || _overlayLayers.some((layer) => d.id === layer.source().id);
};
background.overlayLayerSources = () => {
return _overlayLayers.map((layer) => layer.source());
};
background.toggleOverlayLayer = (d) => {
let layer;
for (let i2 = 0; i2 < _overlayLayers.length; i2++) {
layer = _overlayLayers[i2];
if (layer.source() === d) {
_overlayLayers.splice(i2, 1);
dispatch10.call("change");
background.updateImagery();
return;
}
}
layer = rendererTileLayer(context).source(d).projection(context.projection).dimensions(baseLayer.dimensions());
_overlayLayers.push(layer);
dispatch10.call("change");
background.updateImagery();
};
background.nudge = (d, zoom) => {
const currSource = baseLayer.source();
if (currSource) {
currSource.nudge(d, zoom);
dispatch10.call("change");
background.updateImagery();
}
return background;
};
background.offset = function(d) {
const currSource = baseLayer.source();
if (!arguments.length) {
return currSource && currSource.offset() || [0, 0];
}
if (currSource) {
currSource.offset(d);
dispatch10.call("change");
background.updateImagery();
}
return background;
};
background.brightness = function(d) {
if (!arguments.length)
return _brightness;
_brightness = d;
if (context.mode())
dispatch10.call("change");
return background;
};
background.contrast = function(d) {
if (!arguments.length)
return _contrast;
_contrast = d;
if (context.mode())
dispatch10.call("change");
return background;
};
background.saturation = function(d) {
if (!arguments.length)
return _saturation;
_saturation = d;
if (context.mode())
dispatch10.call("change");
return background;
};
background.sharpness = function(d) {
if (!arguments.length)
return _sharpness;
_sharpness = d;
if (context.mode())
dispatch10.call("change");
return background;
};
let _loadPromise;
background.ensureLoaded = () => {
if (_loadPromise)
return _loadPromise;
function parseMapParams(qmap) {
if (!qmap)
return false;
const params = qmap.split("/").map(Number);
if (params.length < 3 || params.some(isNaN))
return false;
return geoExtent([params[2], params[1]]);
}
const hash = utilStringQs(window.location.hash);
const requested = hash.background || hash.layer;
let extent = parseMapParams(hash.map);
return _loadPromise = ensureImageryIndex().then((imageryIndex) => {
const first = imageryIndex.backgrounds.length && imageryIndex.backgrounds[0];
let best;
if (!requested && extent) {
best = background.sources(extent).find((s) => s.best());
}
if (requested && requested.indexOf("custom:") === 0) {
const template = requested.replace(/^custom:/, "");
const custom = background.findSource("custom");
background.baseLayerSource(custom.template(template));
corePreferences("background-custom-template", template);
} else {
background.baseLayerSource(background.findSource(requested) || best || background.findSource(corePreferences("background-last-used")) || background.findSource("Bing") || first || background.findSource("none"));
}
const locator = imageryIndex.backgrounds.find((d) => d.overlay && d.default);
if (locator) {
background.toggleOverlayLayer(locator);
}
const overlays = (hash.overlays || "").split(",");
overlays.forEach((overlay) => {
overlay = background.findSource(overlay);
if (overlay) {
background.toggleOverlayLayer(overlay);
}
});
if (hash.gpx) {
const gpx2 = context.layers().layer("data");
if (gpx2) {
gpx2.url(hash.gpx, ".gpx");
}
}
if (hash.offset) {
const offset = hash.offset.replace(/;/g, ",").split(",").map((n2) => !isNaN(n2) && n2);
if (offset.length === 2) {
background.offset(geoMetersToOffset(offset));
}
}
}).catch(() => {
});
};
return utilRebind(background, dispatch10, "on");
}
// modules/renderer/features.js
function rendererFeatures(context) {
var dispatch10 = dispatch_default("change", "redraw");
var features2 = utilRebind({}, dispatch10, "on");
var _deferred2 = /* @__PURE__ */ new Set();
var traffic_roads = {
"motorway": true,
"motorway_link": true,
"trunk": true,
"trunk_link": true,
"primary": true,
"primary_link": true,
"secondary": true,
"secondary_link": true,
"tertiary": true,
"tertiary_link": true,
"residential": true,
"unclassified": true,
"living_street": true
};
var service_roads = {
"service": true,
"road": true,
"track": true
};
var paths = {
"path": true,
"footway": true,
"cycleway": true,
"bridleway": true,
"steps": true,
"pedestrian": true
};
var past_futures = {
"proposed": true,
"construction": true,
"abandoned": true,
"dismantled": true,
"disused": true,
"razed": true,
"demolished": true,
"obliterated": true
};
var _cullFactor = 1;
var _cache4 = {};
var _rules = {};
var _stats = {};
var _keys = [];
var _hidden = [];
var _forceVisible = {};
function update() {
if (!window.mocha) {
var hash = utilStringQs(window.location.hash);
var disabled = features2.disabled();
if (disabled.length) {
hash.disable_features = disabled.join(",");
} else {
delete hash.disable_features;
}
window.location.replace("#" + utilQsString(hash, true));
corePreferences("disabled-features", disabled.join(","));
}
_hidden = features2.hidden();
dispatch10.call("change");
dispatch10.call("redraw");
}
function defineRule(k, filter2, max3) {
var isEnabled = true;
_keys.push(k);
_rules[k] = {
filter: filter2,
enabled: isEnabled,
count: 0,
currentMax: max3 || Infinity,
defaultMax: max3 || Infinity,
enable: function() {
this.enabled = true;
this.currentMax = this.defaultMax;
},
disable: function() {
this.enabled = false;
this.currentMax = 0;
},
hidden: function() {
return this.count === 0 && !this.enabled || this.count > this.currentMax * _cullFactor;
},
autoHidden: function() {
return this.hidden() && this.currentMax > 0;
}
};
}
defineRule("points", function isPoint(tags, geometry) {
return geometry === "point";
}, 200);
defineRule("traffic_roads", function isTrafficRoad(tags) {
return traffic_roads[tags.highway];
});
defineRule("service_roads", function isServiceRoad(tags) {
return service_roads[tags.highway];
});
defineRule("paths", function isPath(tags) {
return paths[tags.highway];
});
defineRule("buildings", function isBuilding(tags) {
return !!tags.building && tags.building !== "no" || tags.parking === "multi-storey" || tags.parking === "sheds" || tags.parking === "carports" || tags.parking === "garage_boxes";
}, 250);
defineRule("building_parts", function isBuildingPart(tags) {
return tags["building:part"];
});
defineRule("indoor", function isIndoor(tags) {
return tags.indoor;
});
defineRule("landuse", function isLanduse(tags, geometry) {
return geometry === "area" && !_rules.buildings.filter(tags) && !_rules.building_parts.filter(tags) && !_rules.indoor.filter(tags) && !_rules.water.filter(tags) && !_rules.pistes.filter(tags);
});
defineRule("boundaries", function isBoundary(tags) {
return !!tags.boundary && !(traffic_roads[tags.highway] || service_roads[tags.highway] || paths[tags.highway] || tags.waterway || tags.railway || tags.landuse || tags.natural || tags.building || tags.power);
});
defineRule("water", function isWater(tags) {
return !!tags.waterway || tags.natural === "water" || tags.natural === "coastline" || tags.natural === "bay" || tags.landuse === "pond" || tags.landuse === "basin" || tags.landuse === "reservoir" || tags.landuse === "salt_pond";
});
defineRule("rail", function isRail(tags) {
return (!!tags.railway || tags.landuse === "railway") && !(traffic_roads[tags.highway] || service_roads[tags.highway] || paths[tags.highway]);
});
defineRule("pistes", function isPiste(tags) {
return tags["piste:type"];
});
defineRule("aerialways", function isPiste(tags) {
return tags.aerialway && tags.aerialway !== "yes" && tags.aerialway !== "station";
});
defineRule("power", function isPower(tags) {
return !!tags.power;
});
defineRule("past_future", function isPastFuture(tags) {
if (traffic_roads[tags.highway] || service_roads[tags.highway] || paths[tags.highway]) {
return false;
}
var strings = Object.keys(tags);
for (var i2 = 0; i2 < strings.length; i2++) {
var s = strings[i2];
if (past_futures[s] || past_futures[tags[s]]) {
return true;
}
}
return false;
});
defineRule("others", function isOther(tags, geometry) {
return geometry === "line" || geometry === "area";
});
features2.features = function() {
return _rules;
};
features2.keys = function() {
return _keys;
};
features2.enabled = function(k) {
if (!arguments.length) {
return _keys.filter(function(k2) {
return _rules[k2].enabled;
});
}
return _rules[k] && _rules[k].enabled;
};
features2.disabled = function(k) {
if (!arguments.length) {
return _keys.filter(function(k2) {
return !_rules[k2].enabled;
});
}
return _rules[k] && !_rules[k].enabled;
};
features2.hidden = function(k) {
if (!arguments.length) {
return _keys.filter(function(k2) {
return _rules[k2].hidden();
});
}
return _rules[k] && _rules[k].hidden();
};
features2.autoHidden = function(k) {
if (!arguments.length) {
return _keys.filter(function(k2) {
return _rules[k2].autoHidden();
});
}
return _rules[k] && _rules[k].autoHidden();
};
features2.enable = function(k) {
if (_rules[k] && !_rules[k].enabled) {
_rules[k].enable();
update();
}
};
features2.enableAll = function() {
var didEnable = false;
for (var k in _rules) {
if (!_rules[k].enabled) {
didEnable = true;
_rules[k].enable();
}
}
if (didEnable)
update();
};
features2.disable = function(k) {
if (_rules[k] && _rules[k].enabled) {
_rules[k].disable();
update();
}
};
features2.disableAll = function() {
var didDisable = false;
for (var k in _rules) {
if (_rules[k].enabled) {
didDisable = true;
_rules[k].disable();
}
}
if (didDisable)
update();
};
features2.toggle = function(k) {
if (_rules[k]) {
(function(f2) {
return f2.enabled ? f2.disable() : f2.enable();
})(_rules[k]);
update();
}
};
features2.resetStats = function() {
for (var i2 = 0; i2 < _keys.length; i2++) {
_rules[_keys[i2]].count = 0;
}
dispatch10.call("change");
};
features2.gatherStats = function(d, resolver, dimensions) {
var needsRedraw = false;
var types = utilArrayGroupBy(d, "type");
var entities = [].concat(types.relation || [], types.way || [], types.node || []);
var currHidden, geometry, matches, i2, j2;
for (i2 = 0; i2 < _keys.length; i2++) {
_rules[_keys[i2]].count = 0;
}
_cullFactor = dimensions[0] * dimensions[1] / 1e6;
for (i2 = 0; i2 < entities.length; i2++) {
geometry = entities[i2].geometry(resolver);
matches = Object.keys(features2.getMatches(entities[i2], resolver, geometry));
for (j2 = 0; j2 < matches.length; j2++) {
_rules[matches[j2]].count++;
}
}
currHidden = features2.hidden();
if (currHidden !== _hidden) {
_hidden = currHidden;
needsRedraw = true;
dispatch10.call("change");
}
return needsRedraw;
};
features2.stats = function() {
for (var i2 = 0; i2 < _keys.length; i2++) {
_stats[_keys[i2]] = _rules[_keys[i2]].count;
}
return _stats;
};
features2.clear = function(d) {
for (var i2 = 0; i2 < d.length; i2++) {
features2.clearEntity(d[i2]);
}
};
features2.clearEntity = function(entity) {
delete _cache4[osmEntity.key(entity)];
};
features2.reset = function() {
Array.from(_deferred2).forEach(function(handle) {
window.cancelIdleCallback(handle);
_deferred2.delete(handle);
});
_cache4 = {};
};
function relationShouldBeChecked(relation) {
return relation.tags.type === "boundary";
}
features2.getMatches = function(entity, resolver, geometry) {
if (geometry === "vertex" || geometry === "relation" && !relationShouldBeChecked(entity))
return {};
var ent = osmEntity.key(entity);
if (!_cache4[ent]) {
_cache4[ent] = {};
}
if (!_cache4[ent].matches) {
var matches = {};
var hasMatch = false;
for (var i2 = 0; i2 < _keys.length; i2++) {
if (_keys[i2] === "others") {
if (hasMatch)
continue;
if (entity.type === "way") {
var parents = features2.getParents(entity, resolver, geometry);
if (parents.length === 1 && parents[0].isMultipolygon() || parents.length > 0 && parents.every(function(parent) {
return parent.tags.type === "boundary";
})) {
var pkey = osmEntity.key(parents[0]);
if (_cache4[pkey] && _cache4[pkey].matches) {
matches = Object.assign({}, _cache4[pkey].matches);
continue;
}
}
}
}
if (_rules[_keys[i2]].filter(entity.tags, geometry)) {
matches[_keys[i2]] = hasMatch = true;
}
}
_cache4[ent].matches = matches;
}
return _cache4[ent].matches;
};
features2.getParents = function(entity, resolver, geometry) {
if (geometry === "point")
return [];
var ent = osmEntity.key(entity);
if (!_cache4[ent]) {
_cache4[ent] = {};
}
if (!_cache4[ent].parents) {
var parents = [];
if (geometry === "vertex") {
parents = resolver.parentWays(entity);
} else {
parents = resolver.parentRelations(entity);
}
_cache4[ent].parents = parents;
}
return _cache4[ent].parents;
};
features2.isHiddenPreset = function(preset, geometry) {
if (!_hidden.length)
return false;
if (!preset.tags)
return false;
var test = preset.setTags({}, geometry);
for (var key in _rules) {
if (_rules[key].filter(test, geometry)) {
if (_hidden.indexOf(key) !== -1) {
return key;
}
return false;
}
}
return false;
};
features2.isHiddenFeature = function(entity, resolver, geometry) {
if (!_hidden.length)
return false;
if (!entity.version)
return false;
if (_forceVisible[entity.id])
return false;
var matches = Object.keys(features2.getMatches(entity, resolver, geometry));
return matches.length && matches.every(function(k) {
return features2.hidden(k);
});
};
features2.isHiddenChild = function(entity, resolver, geometry) {
if (!_hidden.length)
return false;
if (!entity.version || geometry === "point")
return false;
if (_forceVisible[entity.id])
return false;
var parents = features2.getParents(entity, resolver, geometry);
if (!parents.length)
return false;
for (var i2 = 0; i2 < parents.length; i2++) {
if (!features2.isHidden(parents[i2], resolver, parents[i2].geometry(resolver))) {
return false;
}
}
return true;
};
features2.hasHiddenConnections = function(entity, resolver) {
if (!_hidden.length)
return false;
var childNodes, connections;
if (entity.type === "midpoint") {
childNodes = [resolver.entity(entity.edge[0]), resolver.entity(entity.edge[1])];
connections = [];
} else {
childNodes = entity.nodes ? resolver.childNodes(entity) : [];
connections = features2.getParents(entity, resolver, entity.geometry(resolver));
}
connections = childNodes.reduce(function(result, e) {
return resolver.isShared(e) ? utilArrayUnion(result, resolver.parentWays(e)) : result;
}, connections);
return connections.some(function(e) {
return features2.isHidden(e, resolver, e.geometry(resolver));
});
};
features2.isHidden = function(entity, resolver, geometry) {
if (!_hidden.length)
return false;
if (!entity.version)
return false;
var fn = geometry === "vertex" ? features2.isHiddenChild : features2.isHiddenFeature;
return fn(entity, resolver, geometry);
};
features2.filter = function(d, resolver) {
if (!_hidden.length)
return d;
var result = [];
for (var i2 = 0; i2 < d.length; i2++) {
var entity = d[i2];
if (!features2.isHidden(entity, resolver, entity.geometry(resolver))) {
result.push(entity);
}
}
return result;
};
features2.forceVisible = function(entityIDs) {
if (!arguments.length)
return Object.keys(_forceVisible);
_forceVisible = {};
for (var i2 = 0; i2 < entityIDs.length; i2++) {
_forceVisible[entityIDs[i2]] = true;
var entity = context.hasEntity(entityIDs[i2]);
if (entity && entity.type === "relation") {
for (var j2 in entity.members) {
_forceVisible[entity.members[j2].id] = true;
}
}
}
return features2;
};
features2.init = function() {
var storage = corePreferences("disabled-features");
if (storage) {
var storageDisabled = storage.replace(/;/g, ",").split(",");
storageDisabled.forEach(features2.disable);
}
var hash = utilStringQs(window.location.hash);
if (hash.disable_features) {
var hashDisabled = hash.disable_features.replace(/;/g, ",").split(",");
hashDisabled.forEach(features2.disable);
}
};
context.history().on("merge.features", function(newEntities) {
if (!newEntities)
return;
var handle = window.requestIdleCallback(function() {
var graph = context.graph();
var types = utilArrayGroupBy(newEntities, "type");
var entities = [].concat(types.relation || [], types.way || [], types.node || []);
for (var i2 = 0; i2 < entities.length; i2++) {
var geometry = entities[i2].geometry(graph);
features2.getMatches(entities[i2], graph, geometry);
}
});
_deferred2.add(handle);
});
return features2;
}
// modules/svg/areas.js
var import_fast_deep_equal5 = __toESM(require_fast_deep_equal());
// modules/svg/helpers.js
function svgPassiveVertex(node, graph, activeID) {
if (!activeID)
return 1;
if (activeID === node.id)
return 0;
var parents = graph.parentWays(node);
var i2, j2, nodes, isClosed, ix1, ix2, ix3, ix4, max3;
for (i2 = 0; i2 < parents.length; i2++) {
nodes = parents[i2].nodes;
isClosed = parents[i2].isClosed();
for (j2 = 0; j2 < nodes.length; j2++) {
if (nodes[j2] === node.id) {
ix1 = j2 - 2;
ix2 = j2 - 1;
ix3 = j2 + 1;
ix4 = j2 + 2;
if (isClosed) {
max3 = nodes.length - 1;
if (ix1 < 0)
ix1 = max3 + ix1;
if (ix2 < 0)
ix2 = max3 + ix2;
if (ix3 > max3)
ix3 = ix3 - max3;
if (ix4 > max3)
ix4 = ix4 - max3;
}
if (nodes[ix1] === activeID)
return 0;
else if (nodes[ix2] === activeID)
return 2;
else if (nodes[ix3] === activeID)
return 2;
else if (nodes[ix4] === activeID)
return 0;
else if (isClosed && nodes.indexOf(activeID) !== -1)
return 0;
}
}
}
return 1;
}
function svgMarkerSegments(projection2, graph, dt, shouldReverse, bothDirections) {
return function(entity) {
var i2 = 0;
var offset = dt;
var segments = [];
var clip = identity_default2().clipExtent(projection2.clipExtent()).stream;
var coordinates = graph.childNodes(entity).map(function(n2) {
return n2.loc;
});
var a, b;
if (shouldReverse(entity)) {
coordinates.reverse();
}
stream_default({
type: "LineString",
coordinates
}, projection2.stream(clip({
lineStart: function() {
},
lineEnd: function() {
a = null;
},
point: function(x, y) {
b = [x, y];
if (a) {
var span = geoVecLength(a, b) - offset;
if (span >= 0) {
var heading = geoVecAngle(a, b);
var dx = dt * Math.cos(heading);
var dy = dt * Math.sin(heading);
var p = [
a[0] + offset * Math.cos(heading),
a[1] + offset * Math.sin(heading)
];
var coord2 = [a, p];
for (span -= dt; span >= 0; span -= dt) {
p = geoVecAdd(p, [dx, dy]);
coord2.push(p);
}
coord2.push(b);
var segment = "";
var j2;
for (j2 = 0; j2 < coord2.length; j2++) {
segment += (j2 === 0 ? "M" : "L") + coord2[j2][0] + "," + coord2[j2][1];
}
segments.push({ id: entity.id, index: i2++, d: segment });
if (bothDirections(entity)) {
segment = "";
for (j2 = coord2.length - 1; j2 >= 0; j2--) {
segment += (j2 === coord2.length - 1 ? "M" : "L") + coord2[j2][0] + "," + coord2[j2][1];
}
segments.push({ id: entity.id, index: i2++, d: segment });
}
}
offset = -span;
}
a = b;
}
})));
return segments;
};
}
function svgPath(projection2, graph, isArea) {
var cache = {};
var padding = isArea ? 65 : 5;
var viewport = projection2.clipExtent();
var paddedExtent = [
[viewport[0][0] - padding, viewport[0][1] - padding],
[viewport[1][0] + padding, viewport[1][1] + padding]
];
var clip = identity_default2().clipExtent(paddedExtent).stream;
var project = projection2.stream;
var path = path_default().projection({ stream: function(output) {
return project(clip(output));
} });
var svgpath = function(entity) {
if (entity.id in cache) {
return cache[entity.id];
} else {
return cache[entity.id] = path(entity.asGeoJSON(graph));
}
};
svgpath.geojson = function(d) {
if (d.__featurehash__ !== void 0) {
if (d.__featurehash__ in cache) {
return cache[d.__featurehash__];
} else {
return cache[d.__featurehash__] = path(d);
}
} else {
return path(d);
}
};
return svgpath;
}
function svgPointTransform(projection2) {
var svgpoint = function(entity) {
var pt = projection2(entity.loc);
return "translate(" + pt[0] + "," + pt[1] + ")";
};
svgpoint.geojson = function(d) {
return svgpoint(d.properties.entity);
};
return svgpoint;
}
function svgRelationMemberTags(graph) {
return function(entity) {
var tags = entity.tags;
var shouldCopyMultipolygonTags = !entity.hasInterestingTags();
graph.parentRelations(entity).forEach(function(relation) {
var type3 = relation.tags.type;
if (type3 === "multipolygon" && shouldCopyMultipolygonTags || type3 === "boundary") {
tags = Object.assign({}, relation.tags, tags);
}
});
return tags;
};
}
function svgSegmentWay(way, graph, activeID) {
if (activeID === void 0) {
return graph.transient(way, "waySegments", getWaySegments);
} else {
return getWaySegments();
}
function getWaySegments() {
var isActiveWay = way.nodes.indexOf(activeID) !== -1;
var features2 = { passive: [], active: [] };
var start2 = {};
var end = {};
var node, type3;
for (var i2 = 0; i2 < way.nodes.length; i2++) {
node = graph.entity(way.nodes[i2]);
type3 = svgPassiveVertex(node, graph, activeID);
end = { node, type: type3 };
if (start2.type !== void 0) {
if (start2.node.id === activeID || end.node.id === activeID) {
} else if (isActiveWay && (start2.type === 2 || end.type === 2)) {
pushActive(start2, end, i2);
} else if (start2.type === 0 && end.type === 0) {
pushActive(start2, end, i2);
} else {
pushPassive(start2, end, i2);
}
}
start2 = end;
}
return features2;
function pushActive(start3, end2, index) {
features2.active.push({
type: "Feature",
id: way.id + "-" + index + "-nope",
properties: {
nope: true,
target: true,
entity: way,
nodes: [start3.node, end2.node],
index
},
geometry: {
type: "LineString",
coordinates: [start3.node.loc, end2.node.loc]
}
});
}
function pushPassive(start3, end2, index) {
features2.passive.push({
type: "Feature",
id: way.id + "-" + index,
properties: {
target: true,
entity: way,
nodes: [start3.node, end2.node],
index
},
geometry: {
type: "LineString",
coordinates: [start3.node.loc, end2.node.loc]
}
});
}
}
}
// modules/svg/tag_classes.js
function svgTagClasses() {
var primaries = [
"building",
"highway",
"railway",
"waterway",
"aeroway",
"aerialway",
"piste:type",
"boundary",
"power",
"amenity",
"natural",
"landuse",
"leisure",
"military",
"place",
"man_made",
"route",
"attraction",
"building:part",
"indoor"
];
var statuses = [
"proposed",
"planned",
"construction",
"disused",
"abandoned",
"dismantled",
"razed",
"demolished",
"obliterated",
"intermittent"
];
var secondaries = [
"oneway",
"bridge",
"tunnel",
"embankment",
"cutting",
"barrier",
"surface",
"tracktype",
"footway",
"crossing",
"service",
"sport",
"public_transport",
"location",
"parking",
"golf",
"type",
"leisure",
"man_made",
"indoor",
"construction",
"proposed"
];
var _tags = function(entity) {
return entity.tags;
};
var tagClasses = function(selection2) {
selection2.each(function tagClassesEach(entity) {
var value = this.className;
if (value.baseVal !== void 0) {
value = value.baseVal;
}
var t = _tags(entity);
var computed = tagClasses.getClassesString(t, value);
if (computed !== value) {
select_default2(this).attr("class", computed);
}
});
};
tagClasses.getClassesString = function(t, value) {
var primary, status;
var i2, j2, k, v;
var overrideGeometry;
if (/\bstroke\b/.test(value)) {
if (!!t.barrier && t.barrier !== "no") {
overrideGeometry = "line";
}
}
var classes = value.trim().split(/\s+/).filter(function(klass) {
return klass.length && !/^tag-/.test(klass);
}).map(function(klass) {
return klass === "line" || klass === "area" ? overrideGeometry || klass : klass;
});
for (i2 = 0; i2 < primaries.length; i2++) {
k = primaries[i2];
v = t[k];
if (!v || v === "no")
continue;
if (k === "piste:type") {
k = "piste";
} else if (k === "building:part") {
k = "building_part";
}
primary = k;
if (statuses.indexOf(v) !== -1) {
status = v;
classes.push("tag-" + k);
} else {
classes.push("tag-" + k);
classes.push("tag-" + k + "-" + v);
}
break;
}
if (!primary) {
for (i2 = 0; i2 < statuses.length; i2++) {
for (j2 = 0; j2 < primaries.length; j2++) {
k = statuses[i2] + ":" + primaries[j2];
v = t[k];
if (!v || v === "no")
continue;
status = statuses[i2];
break;
}
}
}
if (!status) {
for (i2 = 0; i2 < statuses.length; i2++) {
k = statuses[i2];
v = t[k];
if (!v || v === "no")
continue;
if (v === "yes") {
status = k;
} else if (primary && primary === v) {
status = k;
} else if (!primary && primaries.indexOf(v) !== -1) {
status = k;
primary = v;
classes.push("tag-" + v);
}
if (status)
break;
}
}
if (status) {
classes.push("tag-status");
classes.push("tag-status-" + status);
}
for (i2 = 0; i2 < secondaries.length; i2++) {
k = secondaries[i2];
v = t[k];
if (!v || v === "no" || k === primary)
continue;
classes.push("tag-" + k);
classes.push("tag-" + k + "-" + v);
}
if (primary === "highway" && !osmPathHighwayTagValues[t.highway] || primary === "aeroway") {
var surface = t.highway === "track" ? "unpaved" : "paved";
for (k in t) {
v = t[k];
if (k in osmPavedTags) {
surface = osmPavedTags[k][v] ? "paved" : "unpaved";
}
if (k in osmSemipavedTags && !!osmSemipavedTags[k][v]) {
surface = "semipaved";
}
}
classes.push("tag-" + surface);
}
var qid = t.wikidata || t["flag:wikidata"] || t["brand:wikidata"] || t["network:wikidata"] || t["operator:wikidata"];
if (qid) {
classes.push("tag-wikidata");
}
return classes.join(" ").trim();
};
tagClasses.tags = function(val) {
if (!arguments.length)
return _tags;
_tags = val;
return tagClasses;
};
return tagClasses;
}
// modules/svg/tag_pattern.js
var patterns = {
amenity: {
grave_yard: "cemetery",
fountain: "water_standing"
},
landuse: {
cemetery: [
{ religion: "christian", pattern: "cemetery_christian" },
{ religion: "buddhist", pattern: "cemetery_buddhist" },
{ religion: "muslim", pattern: "cemetery_muslim" },
{ religion: "jewish", pattern: "cemetery_jewish" },
{ pattern: "cemetery" }
],
construction: "construction",
farmland: "farmland",
farmyard: "farmyard",
forest: [
{ leaf_type: "broadleaved", pattern: "forest_broadleaved" },
{ leaf_type: "needleleaved", pattern: "forest_needleleaved" },
{ leaf_type: "leafless", pattern: "forest_leafless" },
{ pattern: "forest" }
],
grave_yard: "cemetery",
grass: "grass",
landfill: "landfill",
meadow: "meadow",
military: "construction",
orchard: "orchard",
quarry: "quarry",
vineyard: "vineyard"
},
leisure: {
horse_riding: "farmyard"
},
natural: {
beach: "beach",
grassland: "grass",
sand: "beach",
scrub: "scrub",
water: [
{ water: "pond", pattern: "pond" },
{ water: "reservoir", pattern: "water_standing" },
{ pattern: "waves" }
],
wetland: [
{ wetland: "marsh", pattern: "wetland_marsh" },
{ wetland: "swamp", pattern: "wetland_swamp" },
{ wetland: "bog", pattern: "wetland_bog" },
{ wetland: "reedbed", pattern: "wetland_reedbed" },
{ pattern: "wetland" }
],
wood: [
{ leaf_type: "broadleaved", pattern: "forest_broadleaved" },
{ leaf_type: "needleleaved", pattern: "forest_needleleaved" },
{ leaf_type: "leafless", pattern: "forest_leafless" },
{ pattern: "forest" }
]
},
golf: {
green: "golf_green",
tee: "grass",
fairway: "grass",
rough: "scrub"
},
surface: {
grass: "grass",
sand: "beach"
}
};
function svgTagPattern(tags) {
if (tags.building && tags.building !== "no") {
return null;
}
for (var tag in patterns) {
var entityValue = tags[tag];
if (!entityValue)
continue;
if (typeof patterns[tag] === "string") {
return "pattern-" + patterns[tag];
} else {
var values = patterns[tag];
for (var value in values) {
if (entityValue !== value)
continue;
var rules = values[value];
if (typeof rules === "string") {
return "pattern-" + rules;
}
for (var ruleKey in rules) {
var rule = rules[ruleKey];
var pass = true;
for (var criterion in rule) {
if (criterion !== "pattern") {
var v = tags[criterion];
if (!v || v !== rule[criterion]) {
pass = false;
break;
}
}
}
if (pass) {
return "pattern-" + rule.pattern;
}
}
}
}
}
return null;
}
// modules/svg/areas.js
function svgAreas(projection2, context) {
function getPatternStyle(tags) {
var imageID = svgTagPattern(tags);
if (imageID) {
return 'url("#ideditor-' + imageID + '")';
}
return "";
}
function drawTargets(selection2, graph, entities, filter2) {
var targetClass = context.getDebug("target") ? "pink " : "nocolor ";
var nopeClass = context.getDebug("target") ? "red " : "nocolor ";
var getPath = svgPath(projection2).geojson;
var activeID = context.activeID();
var base = context.history().base();
var data = { targets: [], nopes: [] };
entities.forEach(function(way) {
var features2 = svgSegmentWay(way, graph, activeID);
data.targets.push.apply(data.targets, features2.passive);
data.nopes.push.apply(data.nopes, features2.active);
});
var targetData = data.targets.filter(getPath);
var targets = selection2.selectAll(".area.target-allowed").filter(function(d) {
return filter2(d.properties.entity);
}).data(targetData, function key(d) {
return d.id;
});
targets.exit().remove();
var segmentWasEdited = function(d) {
var wayID = d.properties.entity.id;
if (!base.entities[wayID] || !(0, import_fast_deep_equal5.default)(graph.entities[wayID].nodes, base.entities[wayID].nodes)) {
return false;
}
return d.properties.nodes.some(function(n2) {
return !base.entities[n2.id] || !(0, import_fast_deep_equal5.default)(graph.entities[n2.id].loc, base.entities[n2.id].loc);
});
};
targets.enter().append("path").merge(targets).attr("d", getPath).attr("class", function(d) {
return "way area target target-allowed " + targetClass + d.id;
}).classed("segment-edited", segmentWasEdited);
var nopeData = data.nopes.filter(getPath);
var nopes = selection2.selectAll(".area.target-nope").filter(function(d) {
return filter2(d.properties.entity);
}).data(nopeData, function key(d) {
return d.id;
});
nopes.exit().remove();
nopes.enter().append("path").merge(nopes).attr("d", getPath).attr("class", function(d) {
return "way area target target-nope " + nopeClass + d.id;
}).classed("segment-edited", segmentWasEdited);
}
function drawAreas(selection2, graph, entities, filter2) {
var path = svgPath(projection2, graph, true);
var areas = {};
var multipolygon;
var base = context.history().base();
for (var i2 = 0; i2 < entities.length; i2++) {
var entity = entities[i2];
if (entity.geometry(graph) !== "area")
continue;
multipolygon = osmIsOldMultipolygonOuterMember(entity, graph);
if (multipolygon) {
areas[multipolygon.id] = {
entity: multipolygon.mergeTags(entity.tags),
area: Math.abs(entity.area(graph))
};
} else if (!areas[entity.id]) {
areas[entity.id] = {
entity,
area: Math.abs(entity.area(graph))
};
}
}
var fills = Object.values(areas).filter(function hasPath(a) {
return path(a.entity);
});
fills.sort(function areaSort(a, b) {
return b.area - a.area;
});
fills = fills.map(function(a) {
return a.entity;
});
var strokes = fills.filter(function(area) {
return area.type === "way";
});
var data = {
clip: fills,
shadow: strokes,
stroke: strokes,
fill: fills
};
var clipPaths = context.surface().selectAll("defs").selectAll(".clipPath-osm").filter(filter2).data(data.clip, osmEntity.key);
clipPaths.exit().remove();
var clipPathsEnter = clipPaths.enter().append("clipPath").attr("class", "clipPath-osm").attr("id", function(entity2) {
return "ideditor-" + entity2.id + "-clippath";
});
clipPathsEnter.append("path");
clipPaths.merge(clipPathsEnter).selectAll("path").attr("d", path);
var drawLayer = selection2.selectAll(".layer-osm.areas");
var touchLayer = selection2.selectAll(".layer-touch.areas");
var areagroup = drawLayer.selectAll("g.areagroup").data(["fill", "shadow", "stroke"]);
areagroup = areagroup.enter().append("g").attr("class", function(d) {
return "areagroup area-" + d;
}).merge(areagroup);
var paths = areagroup.selectAll("path").filter(filter2).data(function(layer) {
return data[layer];
}, osmEntity.key);
paths.exit().remove();
var fillpaths = selection2.selectAll(".area-fill path.area").nodes();
var bisect = bisector(function(node) {
return -node.__data__.area(graph);
}).left;
function sortedByArea(entity2) {
if (this._parent.__data__ === "fill") {
return fillpaths[bisect(fillpaths, -entity2.area(graph))];
}
}
paths = paths.enter().insert("path", sortedByArea).merge(paths).each(function(entity2) {
var layer = this.parentNode.__data__;
this.setAttribute("class", entity2.type + " area " + layer + " " + entity2.id);
if (layer === "fill") {
this.setAttribute("clip-path", "url(#ideditor-" + entity2.id + "-clippath)");
this.style.fill = this.style.stroke = getPatternStyle(entity2.tags);
}
}).classed("added", function(d) {
return !base.entities[d.id];
}).classed("geometry-edited", function(d) {
return graph.entities[d.id] && base.entities[d.id] && !(0, import_fast_deep_equal5.default)(graph.entities[d.id].nodes, base.entities[d.id].nodes);
}).classed("retagged", function(d) {
return graph.entities[d.id] && base.entities[d.id] && !(0, import_fast_deep_equal5.default)(graph.entities[d.id].tags, base.entities[d.id].tags);
}).call(svgTagClasses()).attr("d", path);
touchLayer.call(drawTargets, graph, data.stroke, filter2);
}
return drawAreas;
}
// modules/svg/data.js
var import_fast_json_stable_stringify = __toESM(require_fast_json_stable_stringify());
// node_modules/@tmcw/togeojson/dist/togeojson.es.js
function nodeVal(x) {
if (x && x.normalize) {
x.normalize();
}
return x && x.textContent || "";
}
function get1(x, y) {
const n2 = x.getElementsByTagName(y);
return n2.length ? n2[0] : null;
}
function getLineStyle(extensions) {
const style = {};
if (extensions) {
const lineStyle = get1(extensions, "line");
if (lineStyle) {
const color2 = nodeVal(get1(lineStyle, "color")), opacity = parseFloat(nodeVal(get1(lineStyle, "opacity"))), width = parseFloat(nodeVal(get1(lineStyle, "width")));
if (color2)
style.stroke = color2;
if (!isNaN(opacity))
style["stroke-opacity"] = opacity;
if (!isNaN(width))
style["stroke-width"] = width * 96 / 25.4;
}
}
return style;
}
function getExtensions(node) {
let values = [];
if (node !== null) {
for (let i2 = 0; i2 < node.childNodes.length; i2++) {
const child = node.childNodes[i2];
if (child.nodeType !== 1)
continue;
const name2 = ["heart", "gpxtpx:hr", "hr"].includes(child.nodeName) ? "heart" : child.nodeName;
if (name2 === "gpxtpx:TrackPointExtension") {
values = values.concat(getExtensions(child));
} else {
const val = nodeVal(child);
values.push([name2, isNaN(val) ? val : parseFloat(val)]);
}
}
}
return values;
}
function getMulti(x, ys) {
const o = {};
let n2;
let k;
for (k = 0; k < ys.length; k++) {
n2 = get1(x, ys[k]);
if (n2)
o[ys[k]] = nodeVal(n2);
}
return o;
}
function getProperties$1(node) {
const prop = getMulti(node, [
"name",
"cmt",
"desc",
"type",
"time",
"keywords"
]);
const extensions = node.getElementsByTagNameNS("http://www.garmin.com/xmlschemas/GpxExtensions/v3", "*");
for (let i2 = 0; i2 < extensions.length; i2++) {
const extension = extensions[i2];
if (extension.parentNode.parentNode === node) {
prop[extension.tagName.replace(":", "_")] = nodeVal(extension);
}
}
const links = node.getElementsByTagName("link");
if (links.length)
prop.links = [];
for (let i2 = 0; i2 < links.length; i2++) {
prop.links.push(Object.assign({ href: links[i2].getAttribute("href") }, getMulti(links[i2], ["text", "type"])));
}
return prop;
}
function coordPair$1(x) {
const ll = [
parseFloat(x.getAttribute("lon")),
parseFloat(x.getAttribute("lat"))
];
const ele = get1(x, "ele");
const time = get1(x, "time");
if (ele) {
const e = parseFloat(nodeVal(ele));
if (!isNaN(e)) {
ll.push(e);
}
}
return {
coordinates: ll,
time: time ? nodeVal(time) : null,
extendedValues: getExtensions(get1(x, "extensions"))
};
}
function getRoute(node) {
const line = getPoints$1(node, "rtept");
if (!line)
return;
return {
type: "Feature",
properties: Object.assign(getProperties$1(node), getLineStyle(get1(node, "extensions")), { _gpxType: "rte" }),
geometry: {
type: "LineString",
coordinates: line.line
}
};
}
function getPoints$1(node, pointname) {
const pts = node.getElementsByTagName(pointname);
if (pts.length < 2)
return;
const line = [];
const times = [];
const extendedValues = {};
for (let i2 = 0; i2 < pts.length; i2++) {
const c = coordPair$1(pts[i2]);
line.push(c.coordinates);
if (c.time)
times.push(c.time);
for (let j2 = 0; j2 < c.extendedValues.length; j2++) {
const [name2, val] = c.extendedValues[j2];
const plural = name2 === "heart" ? name2 : name2.replace("gpxtpx:", "") + "s";
if (!extendedValues[plural]) {
extendedValues[plural] = Array(pts.length).fill(null);
}
extendedValues[plural][i2] = val;
}
}
return {
line,
times,
extendedValues
};
}
function getTrack(node) {
const segments = node.getElementsByTagName("trkseg");
const track = [];
const times = [];
const extractedLines = [];
for (let i2 = 0; i2 < segments.length; i2++) {
const line = getPoints$1(segments[i2], "trkpt");
if (line) {
extractedLines.push(line);
if (line.times && line.times.length)
times.push(line.times);
}
}
if (extractedLines.length === 0)
return;
const multi = extractedLines.length > 1;
const properties = Object.assign(getProperties$1(node), getLineStyle(get1(node, "extensions")), { _gpxType: "trk" }, times.length ? {
coordinateProperties: {
times: multi ? times : times[0]
}
} : {});
for (let i2 = 0; i2 < extractedLines.length; i2++) {
const line = extractedLines[i2];
track.push(line.line);
for (const [name2, val] of Object.entries(line.extendedValues)) {
if (!properties.coordinateProperties) {
properties.coordinateProperties = {};
}
const props = properties.coordinateProperties;
if (multi) {
if (!props[name2])
props[name2] = extractedLines.map((line2) => new Array(line2.line.length).fill(null));
props[name2][i2] = val;
} else {
props[name2] = val;
}
}
}
return {
type: "Feature",
properties,
geometry: multi ? {
type: "MultiLineString",
coordinates: track
} : {
type: "LineString",
coordinates: track[0]
}
};
}
function getPoint(node) {
return {
type: "Feature",
properties: Object.assign(getProperties$1(node), getMulti(node, ["sym"])),
geometry: {
type: "Point",
coordinates: coordPair$1(node).coordinates
}
};
}
function* gpxGen(doc) {
const tracks = doc.getElementsByTagName("trk");
const routes = doc.getElementsByTagName("rte");
const waypoints = doc.getElementsByTagName("wpt");
for (let i2 = 0; i2 < tracks.length; i2++) {
const feature3 = getTrack(tracks[i2]);
if (feature3)
yield feature3;
}
for (let i2 = 0; i2 < routes.length; i2++) {
const feature3 = getRoute(routes[i2]);
if (feature3)
yield feature3;
}
for (let i2 = 0; i2 < waypoints.length; i2++) {
yield getPoint(waypoints[i2]);
}
}
function gpx(doc) {
return {
type: "FeatureCollection",
features: Array.from(gpxGen(doc))
};
}
var removeSpace = /\s*/g;
var trimSpace = /^\s*|\s*$/g;
var splitSpace = /\s+/;
function okhash(x) {
if (!x || !x.length)
return 0;
let h = 0;
for (let i2 = 0; i2 < x.length; i2++) {
h = (h << 5) - h + x.charCodeAt(i2) | 0;
}
return h;
}
function coord1(v) {
return v.replace(removeSpace, "").split(",").map(parseFloat);
}
function coord(v) {
return v.replace(trimSpace, "").split(splitSpace).map(coord1);
}
function xml2str(node) {
if (node.xml !== void 0)
return node.xml;
if (node.tagName) {
let output = node.tagName;
for (let i2 = 0; i2 < node.attributes.length; i2++) {
output += node.attributes[i2].name + node.attributes[i2].value;
}
for (let i2 = 0; i2 < node.childNodes.length; i2++) {
output += xml2str(node.childNodes[i2]);
}
return output;
}
if (node.nodeName === "#text") {
return (node.nodeValue || node.value || "").trim();
}
if (node.nodeName === "#cdata-section") {
return node.nodeValue;
}
return "";
}
var geotypes = ["Polygon", "LineString", "Point", "Track", "gx:Track"];
function kmlColor(properties, elem, prefix) {
let v = nodeVal(get1(elem, "color")) || "";
const colorProp = prefix == "stroke" || prefix === "fill" ? prefix : prefix + "-color";
if (v.substr(0, 1) === "#") {
v = v.substr(1);
}
if (v.length === 6 || v.length === 3) {
properties[colorProp] = v;
} else if (v.length === 8) {
properties[prefix + "-opacity"] = parseInt(v.substr(0, 2), 16) / 255;
properties[colorProp] = "#" + v.substr(6, 2) + v.substr(4, 2) + v.substr(2, 2);
}
}
function numericProperty(properties, elem, source, target) {
const val = parseFloat(nodeVal(get1(elem, source)));
if (!isNaN(val))
properties[target] = val;
}
function gxCoords(root3) {
let elems = root3.getElementsByTagName("coord");
const coords = [];
const times = [];
if (elems.length === 0)
elems = root3.getElementsByTagName("gx:coord");
for (let i2 = 0; i2 < elems.length; i2++) {
coords.push(nodeVal(elems[i2]).split(" ").map(parseFloat));
}
const timeElems = root3.getElementsByTagName("when");
for (let j2 = 0; j2 < timeElems.length; j2++)
times.push(nodeVal(timeElems[j2]));
return {
coords,
times
};
}
function getGeometry(root3) {
let geomNode;
let geomNodes;
let i2;
let j2;
let k;
const geoms = [];
const coordTimes = [];
if (get1(root3, "MultiGeometry")) {
return getGeometry(get1(root3, "MultiGeometry"));
}
if (get1(root3, "MultiTrack")) {
return getGeometry(get1(root3, "MultiTrack"));
}
if (get1(root3, "gx:MultiTrack")) {
return getGeometry(get1(root3, "gx:MultiTrack"));
}
for (i2 = 0; i2 < geotypes.length; i2++) {
geomNodes = root3.getElementsByTagName(geotypes[i2]);
if (geomNodes) {
for (j2 = 0; j2 < geomNodes.length; j2++) {
geomNode = geomNodes[j2];
if (geotypes[i2] === "Point") {
geoms.push({
type: "Point",
coordinates: coord1(nodeVal(get1(geomNode, "coordinates")))
});
} else if (geotypes[i2] === "LineString") {
geoms.push({
type: "LineString",
coordinates: coord(nodeVal(get1(geomNode, "coordinates")))
});
} else if (geotypes[i2] === "Polygon") {
const rings = geomNode.getElementsByTagName("LinearRing"), coords = [];
for (k = 0; k < rings.length; k++) {
coords.push(coord(nodeVal(get1(rings[k], "coordinates"))));
}
geoms.push({
type: "Polygon",
coordinates: coords
});
} else if (geotypes[i2] === "Track" || geotypes[i2] === "gx:Track") {
const track = gxCoords(geomNode);
geoms.push({
type: "LineString",
coordinates: track.coords
});
if (track.times.length)
coordTimes.push(track.times);
}
}
}
}
return {
geoms,
coordTimes
};
}
function getPlacemark(root3, styleIndex, styleMapIndex, styleByHash) {
const geomsAndTimes = getGeometry(root3);
let i2;
const properties = {};
const name2 = nodeVal(get1(root3, "name"));
const address = nodeVal(get1(root3, "address"));
let styleUrl = nodeVal(get1(root3, "styleUrl"));
const description2 = nodeVal(get1(root3, "description"));
const timeSpan = get1(root3, "TimeSpan");
const timeStamp = get1(root3, "TimeStamp");
const extendedData = get1(root3, "ExtendedData");
let iconStyle = get1(root3, "IconStyle");
let labelStyle = get1(root3, "LabelStyle");
let lineStyle = get1(root3, "LineStyle");
let polyStyle = get1(root3, "PolyStyle");
const visibility = get1(root3, "visibility");
if (name2)
properties.name = name2;
if (address)
properties.address = address;
if (styleUrl) {
if (styleUrl[0] !== "#") {
styleUrl = "#" + styleUrl;
}
properties.styleUrl = styleUrl;
if (styleIndex[styleUrl]) {
properties.styleHash = styleIndex[styleUrl];
}
if (styleMapIndex[styleUrl]) {
properties.styleMapHash = styleMapIndex[styleUrl];
properties.styleHash = styleIndex[styleMapIndex[styleUrl].normal];
}
const style = styleByHash[properties.styleHash];
if (style) {
if (!iconStyle)
iconStyle = get1(style, "IconStyle");
if (!labelStyle)
labelStyle = get1(style, "LabelStyle");
if (!lineStyle)
lineStyle = get1(style, "LineStyle");
if (!polyStyle)
polyStyle = get1(style, "PolyStyle");
}
}
if (description2)
properties.description = description2;
if (timeSpan) {
const begin = nodeVal(get1(timeSpan, "begin"));
const end = nodeVal(get1(timeSpan, "end"));
properties.timespan = { begin, end };
}
if (timeStamp) {
properties.timestamp = nodeVal(get1(timeStamp, "when"));
}
if (iconStyle) {
kmlColor(properties, iconStyle, "icon");
numericProperty(properties, iconStyle, "scale", "icon-scale");
numericProperty(properties, iconStyle, "heading", "icon-heading");
const hotspot = get1(iconStyle, "hotSpot");
if (hotspot) {
const left = parseFloat(hotspot.getAttribute("x"));
const top = parseFloat(hotspot.getAttribute("y"));
if (!isNaN(left) && !isNaN(top))
properties["icon-offset"] = [left, top];
}
const icon2 = get1(iconStyle, "Icon");
if (icon2) {
const href = nodeVal(get1(icon2, "href"));
if (href)
properties.icon = href;
}
}
if (labelStyle) {
kmlColor(properties, labelStyle, "label");
numericProperty(properties, labelStyle, "scale", "label-scale");
}
if (lineStyle) {
kmlColor(properties, lineStyle, "stroke");
numericProperty(properties, lineStyle, "width", "stroke-width");
}
if (polyStyle) {
kmlColor(properties, polyStyle, "fill");
const fill = nodeVal(get1(polyStyle, "fill"));
const outline = nodeVal(get1(polyStyle, "outline"));
if (fill)
properties["fill-opacity"] = fill === "1" ? properties["fill-opacity"] || 1 : 0;
if (outline)
properties["stroke-opacity"] = outline === "1" ? properties["stroke-opacity"] || 1 : 0;
}
if (extendedData) {
const datas = extendedData.getElementsByTagName("Data"), simpleDatas = extendedData.getElementsByTagName("SimpleData");
for (i2 = 0; i2 < datas.length; i2++) {
properties[datas[i2].getAttribute("name")] = nodeVal(get1(datas[i2], "value"));
}
for (i2 = 0; i2 < simpleDatas.length; i2++) {
properties[simpleDatas[i2].getAttribute("name")] = nodeVal(simpleDatas[i2]);
}
}
if (visibility) {
properties.visibility = nodeVal(visibility);
}
if (geomsAndTimes.coordTimes.length) {
properties.coordinateProperties = {
times: geomsAndTimes.coordTimes.length === 1 ? geomsAndTimes.coordTimes[0] : geomsAndTimes.coordTimes
};
}
const feature3 = {
type: "Feature",
geometry: geomsAndTimes.geoms.length === 0 ? null : geomsAndTimes.geoms.length === 1 ? geomsAndTimes.geoms[0] : {
type: "GeometryCollection",
geometries: geomsAndTimes.geoms
},
properties
};
if (root3.getAttribute("id"))
feature3.id = root3.getAttribute("id");
return feature3;
}
function* kmlGen(doc) {
const styleIndex = {};
const styleByHash = {};
const styleMapIndex = {};
const placemarks = doc.getElementsByTagName("Placemark");
const styles = doc.getElementsByTagName("Style");
const styleMaps = doc.getElementsByTagName("StyleMap");
for (let k = 0; k < styles.length; k++) {
const style = styles[k];
const hash = okhash(xml2str(style)).toString(16);
let id2 = style.getAttribute("id");
if (!id2 && style.parentNode.tagName.replace("gx:", "") === "CascadingStyle") {
id2 = style.parentNode.getAttribute("kml:id") || style.parentNode.getAttribute("id");
}
styleIndex["#" + id2] = hash;
styleByHash[hash] = style;
}
for (let l = 0; l < styleMaps.length; l++) {
styleIndex["#" + styleMaps[l].getAttribute("id")] = okhash(xml2str(styleMaps[l])).toString(16);
const pairs = styleMaps[l].getElementsByTagName("Pair");
const pairsMap = {};
for (let m = 0; m < pairs.length; m++) {
pairsMap[nodeVal(get1(pairs[m], "key"))] = nodeVal(get1(pairs[m], "styleUrl"));
}
styleMapIndex["#" + styleMaps[l].getAttribute("id")] = pairsMap;
}
for (let j2 = 0; j2 < placemarks.length; j2++) {
const feature3 = getPlacemark(placemarks[j2], styleIndex, styleMapIndex, styleByHash);
if (feature3)
yield feature3;
}
}
function kml(doc) {
return {
type: "FeatureCollection",
features: Array.from(kmlGen(doc))
};
}
// modules/svg/data.js
var _initialized = false;
var _enabled = false;
var _geojson;
function svgData(projection2, context, dispatch10) {
var throttledRedraw = throttle_default(function() {
dispatch10.call("change");
}, 1e3);
var _showLabels = true;
var detected = utilDetect();
var layer = select_default2(null);
var _vtService;
var _fileList;
var _template;
var _src;
function init2() {
if (_initialized)
return;
_geojson = {};
_enabled = true;
function over(d3_event) {
d3_event.stopPropagation();
d3_event.preventDefault();
d3_event.dataTransfer.dropEffect = "copy";
}
context.container().attr("dropzone", "copy").on("drop.svgData", function(d3_event) {
d3_event.stopPropagation();
d3_event.preventDefault();
if (!detected.filedrop)
return;
drawData.fileList(d3_event.dataTransfer.files);
}).on("dragenter.svgData", over).on("dragexit.svgData", over).on("dragover.svgData", over);
_initialized = true;
}
function getService() {
if (services.vectorTile && !_vtService) {
_vtService = services.vectorTile;
_vtService.event.on("loadedData", throttledRedraw);
} else if (!services.vectorTile && _vtService) {
_vtService = null;
}
return _vtService;
}
function showLayer() {
layerOn();
layer.style("opacity", 0).transition().duration(250).style("opacity", 1).on("end", function() {
dispatch10.call("change");
});
}
function hideLayer() {
throttledRedraw.cancel();
layer.transition().duration(250).style("opacity", 0).on("end", layerOff);
}
function layerOn() {
layer.style("display", "block");
}
function layerOff() {
layer.selectAll(".viewfield-group").remove();
layer.style("display", "none");
}
function ensureIDs(gj) {
if (!gj)
return null;
if (gj.type === "FeatureCollection") {
for (var i2 = 0; i2 < gj.features.length; i2++) {
ensureFeatureID(gj.features[i2]);
}
} else {
ensureFeatureID(gj);
}
return gj;
}
function ensureFeatureID(feature3) {
if (!feature3)
return;
feature3.__featurehash__ = utilHashcode((0, import_fast_json_stable_stringify.default)(feature3));
return feature3;
}
function getFeatures(gj) {
if (!gj)
return [];
if (gj.type === "FeatureCollection") {
return gj.features;
} else {
return [gj];
}
}
function featureKey(d) {
return d.__featurehash__;
}
function isPolygon(d) {
return d.geometry.type === "Polygon" || d.geometry.type === "MultiPolygon";
}
function clipPathID(d) {
return "ideditor-data-" + d.__featurehash__ + "-clippath";
}
function featureClasses(d) {
return [
"data" + d.__featurehash__,
d.geometry.type,
isPolygon(d) ? "area" : "",
d.__layerID__ || ""
].filter(Boolean).join(" ");
}
function drawData(selection2) {
var vtService = getService();
var getPath = svgPath(projection2).geojson;
var getAreaPath = svgPath(projection2, null, true).geojson;
var hasData = drawData.hasData();
layer = selection2.selectAll(".layer-mapdata").data(_enabled && hasData ? [0] : []);
layer.exit().remove();
layer = layer.enter().append("g").attr("class", "layer-mapdata").merge(layer);
var surface = context.surface();
if (!surface || surface.empty())
return;
var geoData, polygonData;
if (_template && vtService) {
var sourceID = _template;
vtService.loadTiles(sourceID, _template, projection2);
geoData = vtService.data(sourceID, projection2);
} else {
geoData = getFeatures(_geojson);
}
geoData = geoData.filter(getPath);
polygonData = geoData.filter(isPolygon);
var clipPaths = surface.selectAll("defs").selectAll(".clipPath-data").data(polygonData, featureKey);
clipPaths.exit().remove();
var clipPathsEnter = clipPaths.enter().append("clipPath").attr("class", "clipPath-data").attr("id", clipPathID);
clipPathsEnter.append("path");
clipPaths.merge(clipPathsEnter).selectAll("path").attr("d", getAreaPath);
var datagroups = layer.selectAll("g.datagroup").data(["fill", "shadow", "stroke"]);
datagroups = datagroups.enter().append("g").attr("class", function(d) {
return "datagroup datagroup-" + d;
}).merge(datagroups);
var pathData = {
fill: polygonData,
shadow: geoData,
stroke: geoData
};
var paths = datagroups.selectAll("path").data(function(layer2) {
return pathData[layer2];
}, featureKey);
paths.exit().remove();
paths = paths.enter().append("path").attr("class", function(d) {
var datagroup = this.parentNode.__data__;
return "pathdata " + datagroup + " " + featureClasses(d);
}).attr("clip-path", function(d) {
var datagroup = this.parentNode.__data__;
return datagroup === "fill" ? "url(#" + clipPathID(d) + ")" : null;
}).merge(paths).attr("d", function(d) {
var datagroup = this.parentNode.__data__;
return datagroup === "fill" ? getAreaPath(d) : getPath(d);
});
layer.call(drawLabels, "label-halo", geoData).call(drawLabels, "label", geoData);
function drawLabels(selection3, textClass, data) {
var labelPath = path_default(projection2);
var labelData = data.filter(function(d) {
return _showLabels && d.properties && (d.properties.desc || d.properties.name);
});
var labels = selection3.selectAll("text." + textClass).data(labelData, featureKey);
labels.exit().remove();
labels = labels.enter().append("text").attr("class", function(d) {
return textClass + " " + featureClasses(d);
}).merge(labels).text(function(d) {
return d.properties.desc || d.properties.name;
}).attr("x", function(d) {
var centroid = labelPath.centroid(d);
return centroid[0] + 11;
}).attr("y", function(d) {
var centroid = labelPath.centroid(d);
return centroid[1];
});
}
}
function getExtension(fileName) {
if (!fileName)
return;
var re2 = /\.(gpx|kml|(geo)?json)$/i;
var match = fileName.toLowerCase().match(re2);
return match && match.length && match[0];
}
function xmlToDom(textdata) {
return new DOMParser().parseFromString(textdata, "text/xml");
}
function stringifyGeojsonProperties(feature3) {
const properties = feature3.properties;
for (const key in properties) {
const property = properties[key];
if (typeof property === "number" || typeof property === "boolean" || Array.isArray(property)) {
properties[key] = property.toString();
} else if (property === null) {
properties[key] = "null";
} else if (typeof property === "object") {
properties[key] = JSON.stringify(property);
}
}
}
drawData.setFile = function(extension, data) {
_template = null;
_fileList = null;
_geojson = null;
_src = null;
var gj;
switch (extension) {
case ".gpx":
gj = gpx(xmlToDom(data));
break;
case ".kml":
gj = kml(xmlToDom(data));
break;
case ".geojson":
case ".json":
gj = JSON.parse(data);
if (gj.type === "FeatureCollection") {
gj.features.forEach(stringifyGeojsonProperties);
} else if (gj.type === "Feature") {
stringifyGeojsonProperties(gj);
}
break;
}
gj = gj || {};
if (Object.keys(gj).length) {
_geojson = ensureIDs(gj);
_src = extension + " data file";
this.fitZoom();
}
dispatch10.call("change");
return this;
};
drawData.showLabels = function(val) {
if (!arguments.length)
return _showLabels;
_showLabels = val;
return this;
};
drawData.enabled = function(val) {
if (!arguments.length)
return _enabled;
_enabled = val;
if (_enabled) {
showLayer();
} else {
hideLayer();
}
dispatch10.call("change");
return this;
};
drawData.hasData = function() {
var gj = _geojson || {};
return !!(_template || Object.keys(gj).length);
};
drawData.template = function(val, src) {
if (!arguments.length)
return _template;
var osm = context.connection();
if (osm) {
var blocklists = osm.imageryBlocklists();
var fail = false;
var tested = 0;
var regex;
for (var i2 = 0; i2 < blocklists.length; i2++) {
regex = blocklists[i2];
fail = regex.test(val);
tested++;
if (fail)
break;
}
if (!tested) {
regex = /.*\.google(apis)?\..*\/(vt|kh)[\?\/].*([xyz]=.*){3}.*/;
fail = regex.test(val);
}
}
_template = val;
_fileList = null;
_geojson = null;
_src = src || "vectortile:" + val.split(/[?#]/)[0];
dispatch10.call("change");
return this;
};
drawData.geojson = function(gj, src) {
if (!arguments.length)
return _geojson;
_template = null;
_fileList = null;
_geojson = null;
_src = null;
gj = gj || {};
if (Object.keys(gj).length) {
_geojson = ensureIDs(gj);
_src = src || "unknown.geojson";
}
dispatch10.call("change");
return this;
};
drawData.fileList = function(fileList) {
if (!arguments.length)
return _fileList;
_template = null;
_fileList = fileList;
_geojson = null;
_src = null;
if (!fileList || !fileList.length)
return this;
var f2 = fileList[0];
var extension = getExtension(f2.name);
var reader = new FileReader();
reader.onload = function() {
return function(e) {
drawData.setFile(extension, e.target.result);
};
}(f2);
reader.readAsText(f2);
return this;
};
drawData.url = function(url, defaultExtension) {
_template = null;
_fileList = null;
_geojson = null;
_src = null;
var testUrl = url.split(/[?#]/)[0];
var extension = getExtension(testUrl) || defaultExtension;
if (extension) {
_template = null;
text_default3(url).then(function(data) {
drawData.setFile(extension, data);
}).catch(function() {
});
} else {
drawData.template(url);
}
return this;
};
drawData.getSrc = function() {
return _src || "";
};
drawData.fitZoom = function() {
var features2 = getFeatures(_geojson);
if (!features2.length)
return;
var map2 = context.map();
var viewport = map2.trimmedExtent().polygon();
var coords = features2.reduce(function(coords2, feature3) {
var geom = feature3.geometry;
if (!geom)
return coords2;
var c = geom.coordinates;
switch (geom.type) {
case "Point":
c = [c];
case "MultiPoint":
case "LineString":
break;
case "MultiPolygon":
c = utilArrayFlatten(c);
case "Polygon":
case "MultiLineString":
c = utilArrayFlatten(c);
break;
}
return utilArrayUnion(coords2, c);
}, []);
if (!geoPolygonIntersectsPolygon(viewport, coords, true)) {
var extent = geoExtent(bounds_default({ type: "LineString", coordinates: coords }));
map2.centerZoom(extent.center(), map2.trimmedExtentZoom(extent));
}
return this;
};
init2();
return drawData;
}
// modules/svg/debug.js
function svgDebug(projection2, context) {
function drawDebug(selection2) {
const showTile = context.getDebug("tile");
const showCollision = context.getDebug("collision");
const showImagery = context.getDebug("imagery");
const showTouchTargets = context.getDebug("target");
const showDownloaded = context.getDebug("downloaded");
let debugData = [];
if (showTile) {
debugData.push({ class: "red", label: "tile" });
}
if (showCollision) {
debugData.push({ class: "yellow", label: "collision" });
}
if (showImagery) {
debugData.push({ class: "orange", label: "imagery" });
}
if (showTouchTargets) {
debugData.push({ class: "pink", label: "touchTargets" });
}
if (showDownloaded) {
debugData.push({ class: "purple", label: "downloaded" });
}
let legend = context.container().select(".main-content").selectAll(".debug-legend").data(debugData.length ? [0] : []);
legend.exit().remove();
legend = legend.enter().append("div").attr("class", "fillD debug-legend").merge(legend);
let legendItems = legend.selectAll(".debug-legend-item").data(debugData, (d) => d.label);
legendItems.exit().remove();
legendItems.enter().append("span").attr("class", (d) => `debug-legend-item ${d.class}`).text((d) => d.label);
let layer = selection2.selectAll(".layer-debug").data(showImagery || showDownloaded ? [0] : []);
layer.exit().remove();
layer = layer.enter().append("g").attr("class", "layer-debug").merge(layer);
const extent = context.map().extent();
_mainFileFetcher.get("imagery").then((d) => {
const hits = showImagery && d.query.bbox(extent.rectangle(), true) || [];
const features2 = hits.map((d2) => d2.features[d2.id]);
let imagery = layer.selectAll("path.debug-imagery").data(features2);
imagery.exit().remove();
imagery.enter().append("path").attr("class", "debug-imagery debug orange");
}).catch(() => {
});
const osm = context.connection();
let dataDownloaded = [];
if (osm && showDownloaded) {
const rtree = osm.caches("get").tile.rtree;
dataDownloaded = rtree.all().map((bbox) => {
return {
type: "Feature",
properties: { id: bbox.id },
geometry: {
type: "Polygon",
coordinates: [[
[bbox.minX, bbox.minY],
[bbox.minX, bbox.maxY],
[bbox.maxX, bbox.maxY],
[bbox.maxX, bbox.minY],
[bbox.minX, bbox.minY]
]]
}
};
});
}
let downloaded = layer.selectAll("path.debug-downloaded").data(showDownloaded ? dataDownloaded : []);
downloaded.exit().remove();
downloaded.enter().append("path").attr("class", "debug-downloaded debug purple");
layer.selectAll("path").attr("d", svgPath(projection2).geojson);
}
drawDebug.enabled = function() {
if (!arguments.length) {
return context.getDebug("tile") || context.getDebug("collision") || context.getDebug("imagery") || context.getDebug("target") || context.getDebug("downloaded");
} else {
return this;
}
};
return drawDebug;
}
// modules/svg/defs.js
function svgDefs(context) {
var _defsSelection = select_default2(null);
var _spritesheetIds = [
"iD-sprite",
"maki-sprite",
"temaki-sprite",
"fa-sprite",
"community-sprite"
];
function drawDefs(selection2) {
_defsSelection = selection2.append("defs");
_defsSelection.append("marker").attr("id", "ideditor-oneway-marker").attr("viewBox", "0 0 10 5").attr("refX", 2.5).attr("refY", 2.5).attr("markerWidth", 2).attr("markerHeight", 2).attr("markerUnits", "strokeWidth").attr("orient", "auto").append("path").attr("class", "oneway-marker-path").attr("d", "M 5,3 L 0,3 L 0,2 L 5,2 L 5,0 L 10,2.5 L 5,5 z").attr("stroke", "none").attr("fill", "#000").attr("opacity", "0.75");
function addSidedMarker(name2, color2, offset) {
_defsSelection.append("marker").attr("id", "ideditor-sided-marker-" + name2).attr("viewBox", "0 0 2 2").attr("refX", 1).attr("refY", -offset).attr("markerWidth", 1.5).attr("markerHeight", 1.5).attr("markerUnits", "strokeWidth").attr("orient", "auto").append("path").attr("class", "sided-marker-path sided-marker-" + name2 + "-path").attr("d", "M 0,0 L 1,1 L 2,0 z").attr("stroke", "none").attr("fill", color2);
}
addSidedMarker("natural", "rgb(170, 170, 170)", 0);
addSidedMarker("coastline", "#77dede", 1);
addSidedMarker("waterway", "#77dede", 1);
addSidedMarker("barrier", "#ddd", 1);
addSidedMarker("man_made", "#fff", 0);
_defsSelection.append("marker").attr("id", "ideditor-viewfield-marker").attr("viewBox", "0 0 16 16").attr("refX", 8).attr("refY", 16).attr("markerWidth", 4).attr("markerHeight", 4).attr("markerUnits", "strokeWidth").attr("orient", "auto").append("path").attr("class", "viewfield-marker-path").attr("d", "M 6,14 C 8,13.4 8,13.4 10,14 L 16,3 C 12,0 4,0 0,3 z").attr("fill", "#333").attr("fill-opacity", "0.75").attr("stroke", "#fff").attr("stroke-width", "0.5px").attr("stroke-opacity", "0.75");
_defsSelection.append("marker").attr("id", "ideditor-viewfield-marker-wireframe").attr("viewBox", "0 0 16 16").attr("refX", 8).attr("refY", 16).attr("markerWidth", 4).attr("markerHeight", 4).attr("markerUnits", "strokeWidth").attr("orient", "auto").append("path").attr("class", "viewfield-marker-path").attr("d", "M 6,14 C 8,13.4 8,13.4 10,14 L 16,3 C 12,0 4,0 0,3 z").attr("fill", "none").attr("stroke", "#fff").attr("stroke-width", "0.5px").attr("stroke-opacity", "0.75");
var patterns2 = _defsSelection.selectAll("pattern").data([
["beach", "dots"],
["construction", "construction"],
["cemetery", "cemetery"],
["cemetery_christian", "cemetery_christian"],
["cemetery_buddhist", "cemetery_buddhist"],
["cemetery_muslim", "cemetery_muslim"],
["cemetery_jewish", "cemetery_jewish"],
["farmland", "farmland"],
["farmyard", "farmyard"],
["forest", "forest"],
["forest_broadleaved", "forest_broadleaved"],
["forest_needleleaved", "forest_needleleaved"],
["forest_leafless", "forest_leafless"],
["golf_green", "grass"],
["grass", "grass"],
["landfill", "landfill"],
["meadow", "grass"],
["orchard", "orchard"],
["pond", "pond"],
["quarry", "quarry"],
["scrub", "bushes"],
["vineyard", "vineyard"],
["water_standing", "lines"],
["waves", "waves"],
["wetland", "wetland"],
["wetland_marsh", "wetland_marsh"],
["wetland_swamp", "wetland_swamp"],
["wetland_bog", "wetland_bog"],
["wetland_reedbed", "wetland_reedbed"]
]).enter().append("pattern").attr("id", function(d) {
return "ideditor-pattern-" + d[0];
}).attr("width", 32).attr("height", 32).attr("patternUnits", "userSpaceOnUse");
patterns2.append("rect").attr("x", 0).attr("y", 0).attr("width", 32).attr("height", 32).attr("class", function(d) {
return "pattern-color-" + d[0];
});
patterns2.append("image").attr("x", 0).attr("y", 0).attr("width", 32).attr("height", 32).attr("xlink:href", function(d) {
return context.imagePath("pattern/" + d[1] + ".png");
});
_defsSelection.selectAll("clipPath").data([12, 18, 20, 32, 45]).enter().append("clipPath").attr("id", function(d) {
return "ideditor-clip-square-" + d;
}).append("rect").attr("x", 0).attr("y", 0).attr("width", function(d) {
return d;
}).attr("height", function(d) {
return d;
});
addSprites(_spritesheetIds, true);
}
function addSprites(ids, overrideColors) {
_spritesheetIds = utilArrayUniq(_spritesheetIds.concat(ids));
var spritesheets = _defsSelection.selectAll(".spritesheet").data(_spritesheetIds);
spritesheets.enter().append("g").attr("class", function(d) {
return "spritesheet spritesheet-" + d;
}).each(function(d) {
var url = context.imagePath(d + ".svg");
var node = select_default2(this).node();
svg(url).then(function(svg2) {
node.appendChild(select_default2(svg2.documentElement).attr("id", "ideditor-" + d).node());
if (overrideColors && d !== "iD-sprite") {
select_default2(node).selectAll("path").attr("fill", "currentColor");
}
}).catch(function() {
});
});
spritesheets.exit().remove();
}
drawDefs.addSprites = addSprites;
return drawDefs;
}
// modules/svg/keepRight.js
var _layerEnabled = false;
var _qaService;
function svgKeepRight(projection2, context, dispatch10) {
const throttledRedraw = throttle_default(() => dispatch10.call("change"), 1e3);
const minZoom3 = 12;
let touchLayer = select_default2(null);
let drawLayer = select_default2(null);
let layerVisible = false;
function markerPath(selection2, klass) {
selection2.attr("class", klass).attr("transform", "translate(-4, -24)").attr("d", "M11.6,6.2H7.1l1.4-5.1C8.6,0.6,8.1,0,7.5,0H2.2C1.7,0,1.3,0.3,1.3,0.8L0,10.2c-0.1,0.6,0.4,1.1,0.9,1.1h4.6l-1.8,7.6C3.6,19.4,4.1,20,4.7,20c0.3,0,0.6-0.2,0.8-0.5l6.9-11.9C12.7,7,12.3,6.2,11.6,6.2z");
}
function getService() {
if (services.keepRight && !_qaService) {
_qaService = services.keepRight;
_qaService.on("loaded", throttledRedraw);
} else if (!services.keepRight && _qaService) {
_qaService = null;
}
return _qaService;
}
function editOn() {
if (!layerVisible) {
layerVisible = true;
drawLayer.style("display", "block");
}
}
function editOff() {
if (layerVisible) {
layerVisible = false;
drawLayer.style("display", "none");
drawLayer.selectAll(".qaItem.keepRight").remove();
touchLayer.selectAll(".qaItem.keepRight").remove();
}
}
function layerOn() {
editOn();
drawLayer.style("opacity", 0).transition().duration(250).style("opacity", 1).on("end interrupt", () => dispatch10.call("change"));
}
function layerOff() {
throttledRedraw.cancel();
drawLayer.interrupt();
touchLayer.selectAll(".qaItem.keepRight").remove();
drawLayer.transition().duration(250).style("opacity", 0).on("end interrupt", () => {
editOff();
dispatch10.call("change");
});
}
function updateMarkers() {
if (!layerVisible || !_layerEnabled)
return;
const service = getService();
const selectedID = context.selectedErrorID();
const data = service ? service.getItems(projection2) : [];
const getTransform = svgPointTransform(projection2);
const markers = drawLayer.selectAll(".qaItem.keepRight").data(data, (d) => d.id);
markers.exit().remove();
const markersEnter = markers.enter().append("g").attr("class", (d) => `qaItem ${d.service} itemId-${d.id} itemType-${d.parentIssueType}`);
markersEnter.append("ellipse").attr("cx", 0.5).attr("cy", 1).attr("rx", 6.5).attr("ry", 3).attr("class", "stroke");
markersEnter.append("path").call(markerPath, "shadow");
markersEnter.append("use").attr("class", "qaItem-fill").attr("width", "20px").attr("height", "20px").attr("x", "-8px").attr("y", "-22px").attr("xlink:href", "#iD-icon-bolt");
markers.merge(markersEnter).sort(sortY).classed("selected", (d) => d.id === selectedID).attr("transform", getTransform);
if (touchLayer.empty())
return;
const fillClass = context.getDebug("target") ? "pink " : "nocolor ";
const targets = touchLayer.selectAll(".qaItem.keepRight").data(data, (d) => d.id);
targets.exit().remove();
targets.enter().append("rect").attr("width", "20px").attr("height", "20px").attr("x", "-8px").attr("y", "-22px").merge(targets).sort(sortY).attr("class", (d) => `qaItem ${d.service} target ${fillClass} itemId-${d.id}`).attr("transform", getTransform);
function sortY(a, b) {
return a.id === selectedID ? 1 : b.id === selectedID ? -1 : a.severity === "error" && b.severity !== "error" ? 1 : b.severity === "error" && a.severity !== "error" ? -1 : b.loc[1] - a.loc[1];
}
}
function drawKeepRight(selection2) {
const service = getService();
const surface = context.surface();
if (surface && !surface.empty()) {
touchLayer = surface.selectAll(".data-layer.touch .layer-touch.markers");
}
drawLayer = selection2.selectAll(".layer-keepRight").data(service ? [0] : []);
drawLayer.exit().remove();
drawLayer = drawLayer.enter().append("g").attr("class", "layer-keepRight").style("display", _layerEnabled ? "block" : "none").merge(drawLayer);
if (_layerEnabled) {
if (service && ~~context.map().zoom() >= minZoom3) {
editOn();
service.loadIssues(projection2);
updateMarkers();
} else {
editOff();
}
}
}
drawKeepRight.enabled = function(val) {
if (!arguments.length)
return _layerEnabled;
_layerEnabled = val;
if (_layerEnabled) {
layerOn();
} else {
layerOff();
if (context.selectedErrorID()) {
context.enter(modeBrowse(context));
}
}
dispatch10.call("change");
return this;
};
drawKeepRight.supported = () => !!getService();
return drawKeepRight;
}
// modules/svg/geolocate.js
function svgGeolocate(projection2) {
var layer = select_default2(null);
var _position;
function init2() {
if (svgGeolocate.initialized)
return;
svgGeolocate.enabled = false;
svgGeolocate.initialized = true;
}
function showLayer() {
layer.style("display", "block");
}
function hideLayer() {
layer.transition().duration(250).style("opacity", 0);
}
function layerOn() {
layer.style("opacity", 0).transition().duration(250).style("opacity", 1);
}
function layerOff() {
layer.style("display", "none");
}
function transform2(d) {
return svgPointTransform(projection2)(d);
}
function accuracy(accuracy2, loc) {
var degreesRadius = geoMetersToLat(accuracy2), tangentLoc = [loc[0], loc[1] + degreesRadius], projectedTangent = projection2(tangentLoc), projectedLoc = projection2([loc[0], loc[1]]);
return Math.round(projectedLoc[1] - projectedTangent[1]).toString();
}
function update() {
var geolocation = { loc: [_position.coords.longitude, _position.coords.latitude] };
var groups = layer.selectAll(".geolocations").selectAll(".geolocation").data([geolocation]);
groups.exit().remove();
var pointsEnter = groups.enter().append("g").attr("class", "geolocation");
pointsEnter.append("circle").attr("class", "geolocate-radius").attr("dx", "0").attr("dy", "0").attr("fill", "rgb(15,128,225)").attr("fill-opacity", "0.3").attr("r", "0");
pointsEnter.append("circle").attr("dx", "0").attr("dy", "0").attr("fill", "rgb(15,128,225)").attr("stroke", "white").attr("stroke-width", "1.5").attr("r", "6");
groups.merge(pointsEnter).attr("transform", transform2);
layer.select(".geolocate-radius").attr("r", accuracy(_position.coords.accuracy, geolocation.loc));
}
function drawLocation(selection2) {
var enabled = svgGeolocate.enabled;
layer = selection2.selectAll(".layer-geolocate").data([0]);
layer.exit().remove();
var layerEnter = layer.enter().append("g").attr("class", "layer-geolocate").style("display", enabled ? "block" : "none");
layerEnter.append("g").attr("class", "geolocations");
layer = layerEnter.merge(layer);
if (enabled) {
update();
} else {
layerOff();
}
}
drawLocation.enabled = function(position, enabled) {
if (!arguments.length)
return svgGeolocate.enabled;
_position = position;
svgGeolocate.enabled = enabled;
if (svgGeolocate.enabled) {
showLayer();
layerOn();
} else {
hideLayer();
}
return this;
};
init2();
return drawLocation;
}
// modules/svg/labels.js
var import_rbush7 = __toESM(require_rbush_min());
function svgLabels(projection2, context) {
var path = path_default(projection2);
var detected = utilDetect();
var baselineHack = detected.ie || detected.browser.toLowerCase() === "edge" || detected.browser.toLowerCase() === "firefox" && detected.version >= 70;
var _rdrawn = new import_rbush7.default();
var _rskipped = new import_rbush7.default();
var _textWidthCache = {};
var _entitybboxes = {};
var labelStack = [
["line", "aeroway", "*", 12],
["line", "highway", "motorway", 12],
["line", "highway", "trunk", 12],
["line", "highway", "primary", 12],
["line", "highway", "secondary", 12],
["line", "highway", "tertiary", 12],
["line", "highway", "*", 12],
["line", "railway", "*", 12],
["line", "waterway", "*", 12],
["area", "aeroway", "*", 12],
["area", "amenity", "*", 12],
["area", "building", "*", 12],
["area", "historic", "*", 12],
["area", "leisure", "*", 12],
["area", "man_made", "*", 12],
["area", "natural", "*", 12],
["area", "shop", "*", 12],
["area", "tourism", "*", 12],
["area", "camp_site", "*", 12],
["point", "aeroway", "*", 10],
["point", "amenity", "*", 10],
["point", "building", "*", 10],
["point", "historic", "*", 10],
["point", "leisure", "*", 10],
["point", "man_made", "*", 10],
["point", "natural", "*", 10],
["point", "shop", "*", 10],
["point", "tourism", "*", 10],
["point", "camp_site", "*", 10],
["line", "name", "*", 12],
["area", "name", "*", 12],
["point", "name", "*", 10]
];
function shouldSkipIcon(preset) {
var noIcons = ["building", "landuse", "natural"];
return noIcons.some(function(s) {
return preset.id.indexOf(s) >= 0;
});
}
function get3(array2, prop) {
return function(d, i2) {
return array2[i2][prop];
};
}
function textWidth(text2, size, elem) {
var c = _textWidthCache[size];
if (!c)
c = _textWidthCache[size] = {};
if (c[text2]) {
return c[text2];
} else if (elem) {
c[text2] = elem.getComputedTextLength();
return c[text2];
} else {
var str2 = encodeURIComponent(text2).match(/%[CDEFcdef]/g);
if (str2 === null) {
return size / 3 * 2 * text2.length;
} else {
return size / 3 * (2 * text2.length + str2.length);
}
}
}
function drawLinePaths(selection2, entities, filter2, classes, labels) {
var paths = selection2.selectAll("path").filter(filter2).data(entities, osmEntity.key);
paths.exit().remove();
paths.enter().append("path").style("stroke-width", get3(labels, "font-size")).attr("id", function(d) {
return "ideditor-labelpath-" + d.id;
}).attr("class", classes).merge(paths).attr("d", get3(labels, "lineString"));
}
function drawLineLabels(selection2, entities, filter2, classes, labels) {
var texts = selection2.selectAll("text." + classes).filter(filter2).data(entities, osmEntity.key);
texts.exit().remove();
texts.enter().append("text").attr("class", function(d, i2) {
return classes + " " + labels[i2].classes + " " + d.id;
}).attr("dy", baselineHack ? "0.35em" : null).append("textPath").attr("class", "textpath");
selection2.selectAll("text." + classes).selectAll(".textpath").filter(filter2).data(entities, osmEntity.key).attr("startOffset", "50%").attr("xlink:href", function(d) {
return "#ideditor-labelpath-" + d.id;
}).text(utilDisplayNameForPath);
}
function drawPointLabels(selection2, entities, filter2, classes, labels) {
var texts = selection2.selectAll("text." + classes).filter(filter2).data(entities, osmEntity.key);
texts.exit().remove();
texts.enter().append("text").attr("class", function(d, i2) {
return classes + " " + labels[i2].classes + " " + d.id;
}).merge(texts).attr("x", get3(labels, "x")).attr("y", get3(labels, "y")).style("text-anchor", get3(labels, "textAnchor")).text(utilDisplayName).each(function(d, i2) {
textWidth(utilDisplayName(d), labels[i2].height, this);
});
}
function drawAreaLabels(selection2, entities, filter2, classes, labels) {
entities = entities.filter(hasText);
labels = labels.filter(hasText);
drawPointLabels(selection2, entities, filter2, classes, labels);
function hasText(d, i2) {
return labels[i2].hasOwnProperty("x") && labels[i2].hasOwnProperty("y");
}
}
function drawAreaIcons(selection2, entities, filter2, classes, labels) {
var icons = selection2.selectAll("use." + classes).filter(filter2).data(entities, osmEntity.key);
icons.exit().remove();
icons.enter().append("use").attr("class", "icon " + classes).attr("width", "17px").attr("height", "17px").merge(icons).attr("transform", get3(labels, "transform")).attr("xlink:href", function(d) {
var preset = _mainPresetIndex.match(d, context.graph());
var picon = preset && preset.icon;
return picon ? "#" + picon : "";
});
}
function drawCollisionBoxes(selection2, rtree, which) {
var classes = "debug " + which + " " + (which === "debug-skipped" ? "orange" : "yellow");
var gj = [];
if (context.getDebug("collision")) {
gj = rtree.all().map(function(d) {
return { type: "Polygon", coordinates: [[
[d.minX, d.minY],
[d.maxX, d.minY],
[d.maxX, d.maxY],
[d.minX, d.maxY],
[d.minX, d.minY]
]] };
});
}
var boxes = selection2.selectAll("." + which).data(gj);
boxes.exit().remove();
boxes.enter().append("path").attr("class", classes).merge(boxes).attr("d", path_default());
}
function drawLabels(selection2, graph, entities, filter2, dimensions, fullRedraw) {
var wireframe = context.surface().classed("fill-wireframe");
var zoom = geoScaleToZoom(projection2.scale());
var labelable = [];
var renderNodeAs = {};
var i2, j2, k, entity, geometry;
for (i2 = 0; i2 < labelStack.length; i2++) {
labelable.push([]);
}
if (fullRedraw) {
_rdrawn.clear();
_rskipped.clear();
_entitybboxes = {};
} else {
for (i2 = 0; i2 < entities.length; i2++) {
entity = entities[i2];
var toRemove = [].concat(_entitybboxes[entity.id] || []).concat(_entitybboxes[entity.id + "I"] || []);
for (j2 = 0; j2 < toRemove.length; j2++) {
_rdrawn.remove(toRemove[j2]);
_rskipped.remove(toRemove[j2]);
}
}
}
for (i2 = 0; i2 < entities.length; i2++) {
entity = entities[i2];
geometry = entity.geometry(graph);
if (geometry === "point" || geometry === "vertex" && isInterestingVertex(entity)) {
var hasDirections = entity.directions(graph, projection2).length;
var markerPadding;
if (!wireframe && geometry === "point" && !(zoom >= 18 && hasDirections)) {
renderNodeAs[entity.id] = "point";
markerPadding = 20;
} else {
renderNodeAs[entity.id] = "vertex";
markerPadding = 0;
}
var coord2 = projection2(entity.loc);
var nodePadding = 10;
var bbox = {
minX: coord2[0] - nodePadding,
minY: coord2[1] - nodePadding - markerPadding,
maxX: coord2[0] + nodePadding,
maxY: coord2[1] + nodePadding
};
doInsert(bbox, entity.id + "P");
}
if (geometry === "vertex") {
geometry = "point";
}
var preset = geometry === "area" && _mainPresetIndex.match(entity, graph);
var icon2 = preset && !shouldSkipIcon(preset) && preset.icon;
if (!icon2 && !utilDisplayName(entity))
continue;
for (k = 0; k < labelStack.length; k++) {
var matchGeom = labelStack[k][0];
var matchKey = labelStack[k][1];
var matchVal = labelStack[k][2];
var hasVal = entity.tags[matchKey];
if (geometry === matchGeom && hasVal && (matchVal === "*" || matchVal === hasVal)) {
labelable[k].push(entity);
break;
}
}
}
var positions = {
point: [],
line: [],
area: []
};
var labelled = {
point: [],
line: [],
area: []
};
for (k = 0; k < labelable.length; k++) {
var fontSize = labelStack[k][3];
for (i2 = 0; i2 < labelable[k].length; i2++) {
entity = labelable[k][i2];
geometry = entity.geometry(graph);
var getName = geometry === "line" ? utilDisplayNameForPath : utilDisplayName;
var name2 = getName(entity);
var width = name2 && textWidth(name2, fontSize);
var p = null;
if (geometry === "point" || geometry === "vertex") {
if (wireframe)
continue;
var renderAs = renderNodeAs[entity.id];
if (renderAs === "vertex" && zoom < 17)
continue;
p = getPointLabel(entity, width, fontSize, renderAs);
} else if (geometry === "line") {
p = getLineLabel(entity, width, fontSize);
} else if (geometry === "area") {
p = getAreaLabel(entity, width, fontSize);
}
if (p) {
if (geometry === "vertex") {
geometry = "point";
}
p.classes = geometry + " tag-" + labelStack[k][1];
positions[geometry].push(p);
labelled[geometry].push(entity);
}
}
}
function isInterestingVertex(entity2) {
var selectedIDs = context.selectedIDs();
return entity2.hasInterestingTags() || entity2.isEndpoint(graph) || entity2.isConnected(graph) || selectedIDs.indexOf(entity2.id) !== -1 || graph.parentWays(entity2).some(function(parent) {
return selectedIDs.indexOf(parent.id) !== -1;
});
}
function getPointLabel(entity2, width2, height, geometry2) {
var y = geometry2 === "point" ? -12 : 0;
var pointOffsets = {
ltr: [15, y, "start"],
rtl: [-15, y, "end"]
};
var textDirection = _mainLocalizer.textDirection();
var coord3 = projection2(entity2.loc);
var textPadding = 2;
var offset = pointOffsets[textDirection];
var p2 = {
height,
width: width2,
x: coord3[0] + offset[0],
y: coord3[1] + offset[1],
textAnchor: offset[2]
};
var bbox2;
if (textDirection === "rtl") {
bbox2 = {
minX: p2.x - width2 - textPadding,
minY: p2.y - height / 2 - textPadding,
maxX: p2.x + textPadding,
maxY: p2.y + height / 2 + textPadding
};
} else {
bbox2 = {
minX: p2.x - textPadding,
minY: p2.y - height / 2 - textPadding,
maxX: p2.x + width2 + textPadding,
maxY: p2.y + height / 2 + textPadding
};
}
if (tryInsert([bbox2], entity2.id, true)) {
return p2;
}
}
function getLineLabel(entity2, width2, height) {
var viewport = geoExtent(context.projection.clipExtent()).polygon();
var points = graph.childNodes(entity2).map(function(node) {
return projection2(node.loc);
});
var length = geoPathLength(points);
if (length < width2 + 20)
return;
var lineOffsets = [
50,
45,
55,
40,
60,
35,
65,
30,
70,
25,
75,
20,
80,
15,
95,
10,
90,
5,
95
];
var padding = 3;
for (var i3 = 0; i3 < lineOffsets.length; i3++) {
var offset = lineOffsets[i3];
var middle = offset / 100 * length;
var start2 = middle - width2 / 2;
if (start2 < 0 || start2 + width2 > length)
continue;
var sub = subpath(points, start2, start2 + width2);
if (!sub || !geoPolygonIntersectsPolygon(viewport, sub, true)) {
continue;
}
var isReverse = reverse(sub);
if (isReverse) {
sub = sub.reverse();
}
var bboxes = [];
var boxsize = (height + 2) / 2;
for (var j3 = 0; j3 < sub.length - 1; j3++) {
var a = sub[j3];
var b = sub[j3 + 1];
var num = Math.max(1, Math.floor(geoVecLength(a, b) / boxsize / 2));
for (var box = 0; box < num; box++) {
var p2 = geoVecInterp(a, b, box / num);
var x05 = p2[0] - boxsize - padding;
var y05 = p2[1] - boxsize - padding;
var x12 = p2[0] + boxsize + padding;
var y12 = p2[1] + boxsize + padding;
bboxes.push({
minX: Math.min(x05, x12),
minY: Math.min(y05, y12),
maxX: Math.max(x05, x12),
maxY: Math.max(y05, y12)
});
}
}
if (tryInsert(bboxes, entity2.id, false)) {
return {
"font-size": height + 2,
lineString: lineString2(sub),
startOffset: offset + "%"
};
}
}
function reverse(p3) {
var angle2 = Math.atan2(p3[1][1] - p3[0][1], p3[1][0] - p3[0][0]);
return !(p3[0][0] < p3[p3.length - 1][0] && angle2 < Math.PI / 2 && angle2 > -Math.PI / 2);
}
function lineString2(points2) {
return "M" + points2.join("L");
}
function subpath(points2, from, to) {
var sofar = 0;
var start3, end, i0, i1;
for (var i4 = 0; i4 < points2.length - 1; i4++) {
var a2 = points2[i4];
var b2 = points2[i4 + 1];
var current = geoVecLength(a2, b2);
var portion;
if (!start3 && sofar + current >= from) {
portion = (from - sofar) / current;
start3 = [
a2[0] + portion * (b2[0] - a2[0]),
a2[1] + portion * (b2[1] - a2[1])
];
i0 = i4 + 1;
}
if (!end && sofar + current >= to) {
portion = (to - sofar) / current;
end = [
a2[0] + portion * (b2[0] - a2[0]),
a2[1] + portion * (b2[1] - a2[1])
];
i1 = i4 + 1;
}
sofar += current;
}
var result = points2.slice(i0, i1);
result.unshift(start3);
result.push(end);
return result;
}
}
function getAreaLabel(entity2, width2, height) {
var centroid = path.centroid(entity2.asGeoJSON(graph));
var extent = entity2.extent(graph);
var areaWidth = projection2(extent[1])[0] - projection2(extent[0])[0];
if (isNaN(centroid[0]) || areaWidth < 20)
return;
var preset2 = _mainPresetIndex.match(entity2, context.graph());
var picon = preset2 && preset2.icon;
var iconSize = 17;
var padding = 2;
var p2 = {};
if (picon) {
if (addIcon()) {
addLabel(iconSize + padding);
return p2;
}
} else {
if (addLabel(0)) {
return p2;
}
}
function addIcon() {
var iconX = centroid[0] - iconSize / 2;
var iconY = centroid[1] - iconSize / 2;
var bbox2 = {
minX: iconX,
minY: iconY,
maxX: iconX + iconSize,
maxY: iconY + iconSize
};
if (tryInsert([bbox2], entity2.id + "I", true)) {
p2.transform = "translate(" + iconX + "," + iconY + ")";
return true;
}
return false;
}
function addLabel(yOffset) {
if (width2 && areaWidth >= width2 + 20) {
var labelX = centroid[0];
var labelY = centroid[1] + yOffset;
var bbox2 = {
minX: labelX - width2 / 2 - padding,
minY: labelY - height / 2 - padding,
maxX: labelX + width2 / 2 + padding,
maxY: labelY + height / 2 + padding
};
if (tryInsert([bbox2], entity2.id, true)) {
p2.x = labelX;
p2.y = labelY;
p2.textAnchor = "middle";
p2.height = height;
return true;
}
}
return false;
}
}
function doInsert(bbox2, id2) {
bbox2.id = id2;
var oldbox = _entitybboxes[id2];
if (oldbox) {
_rdrawn.remove(oldbox);
}
_entitybboxes[id2] = bbox2;
_rdrawn.insert(bbox2);
}
function tryInsert(bboxes, id2, saveSkipped) {
var skipped = false;
for (var i3 = 0; i3 < bboxes.length; i3++) {
var bbox2 = bboxes[i3];
bbox2.id = id2;
if (bbox2.minX < 0 || bbox2.minY < 0 || bbox2.maxX > dimensions[0] || bbox2.maxY > dimensions[1]) {
skipped = true;
break;
}
if (_rdrawn.collides(bbox2)) {
skipped = true;
break;
}
}
_entitybboxes[id2] = bboxes;
if (skipped) {
if (saveSkipped) {
_rskipped.load(bboxes);
}
} else {
_rdrawn.load(bboxes);
}
return !skipped;
}
var layer = selection2.selectAll(".layer-osm.labels");
layer.selectAll(".labels-group").data(["halo", "label", "debug"]).enter().append("g").attr("class", function(d) {
return "labels-group " + d;
});
var halo = layer.selectAll(".labels-group.halo");
var label = layer.selectAll(".labels-group.label");
var debug2 = layer.selectAll(".labels-group.debug");
drawPointLabels(label, labelled.point, filter2, "pointlabel", positions.point);
drawPointLabels(halo, labelled.point, filter2, "pointlabel-halo", positions.point);
drawLinePaths(layer, labelled.line, filter2, "", positions.line);
drawLineLabels(label, labelled.line, filter2, "linelabel", positions.line);
drawLineLabels(halo, labelled.line, filter2, "linelabel-halo", positions.line);
drawAreaLabels(label, labelled.area, filter2, "arealabel", positions.area);
drawAreaLabels(halo, labelled.area, filter2, "arealabel-halo", positions.area);
drawAreaIcons(label, labelled.area, filter2, "areaicon", positions.area);
drawAreaIcons(halo, labelled.area, filter2, "areaicon-halo", positions.area);
drawCollisionBoxes(debug2, _rskipped, "debug-skipped");
drawCollisionBoxes(debug2, _rdrawn, "debug-drawn");
layer.call(filterLabels);
}
function filterLabels(selection2) {
var drawLayer = selection2.selectAll(".layer-osm.labels");
var layers = drawLayer.selectAll(".labels-group.halo, .labels-group.label");
layers.selectAll(".nolabel").classed("nolabel", false);
var mouse = context.map().mouse();
var graph = context.graph();
var selectedIDs = context.selectedIDs();
var ids = [];
var pad2, bbox;
if (mouse) {
pad2 = 20;
bbox = { minX: mouse[0] - pad2, minY: mouse[1] - pad2, maxX: mouse[0] + pad2, maxY: mouse[1] + pad2 };
var nearMouse = _rdrawn.search(bbox).map(function(entity2) {
return entity2.id;
});
ids.push.apply(ids, nearMouse);
}
for (var i2 = 0; i2 < selectedIDs.length; i2++) {
var entity = graph.hasEntity(selectedIDs[i2]);
if (entity && entity.type === "node") {
ids.push(selectedIDs[i2]);
}
}
layers.selectAll(utilEntitySelector(ids)).classed("nolabel", true);
var debug2 = selection2.selectAll(".labels-group.debug");
var gj = [];
if (context.getDebug("collision")) {
gj = bbox ? [{
type: "Polygon",
coordinates: [[
[bbox.minX, bbox.minY],
[bbox.maxX, bbox.minY],
[bbox.maxX, bbox.maxY],
[bbox.minX, bbox.maxY],
[bbox.minX, bbox.minY]
]]
}] : [];
}
var box = debug2.selectAll(".debug-mouse").data(gj);
box.exit().remove();
box.enter().append("path").attr("class", "debug debug-mouse yellow").merge(box).attr("d", path_default());
}
var throttleFilterLabels = throttle_default(filterLabels, 100);
drawLabels.observe = function(selection2) {
var listener = function() {
throttleFilterLabels(selection2);
};
selection2.on("mousemove.hidelabels", listener);
context.on("enter.hidelabels", listener);
};
drawLabels.off = function(selection2) {
throttleFilterLabels.cancel();
selection2.on("mousemove.hidelabels", null);
context.on("enter.hidelabels", null);
};
return drawLabels;
}
// modules/svg/improveOSM.js
var _layerEnabled2 = false;
var _qaService2;
function svgImproveOSM(projection2, context, dispatch10) {
const throttledRedraw = throttle_default(() => dispatch10.call("change"), 1e3);
const minZoom3 = 12;
let touchLayer = select_default2(null);
let drawLayer = select_default2(null);
let layerVisible = false;
function markerPath(selection2, klass) {
selection2.attr("class", klass).attr("transform", "translate(-10, -28)").attr("points", "16,3 4,3 1,6 1,17 4,20 7,20 10,27 13,20 16,20 19,17.033 19,6");
}
function getService() {
if (services.improveOSM && !_qaService2) {
_qaService2 = services.improveOSM;
_qaService2.on("loaded", throttledRedraw);
} else if (!services.improveOSM && _qaService2) {
_qaService2 = null;
}
return _qaService2;
}
function editOn() {
if (!layerVisible) {
layerVisible = true;
drawLayer.style("display", "block");
}
}
function editOff() {
if (layerVisible) {
layerVisible = false;
drawLayer.style("display", "none");
drawLayer.selectAll(".qaItem.improveOSM").remove();
touchLayer.selectAll(".qaItem.improveOSM").remove();
}
}
function layerOn() {
editOn();
drawLayer.style("opacity", 0).transition().duration(250).style("opacity", 1).on("end interrupt", () => dispatch10.call("change"));
}
function layerOff() {
throttledRedraw.cancel();
drawLayer.interrupt();
touchLayer.selectAll(".qaItem.improveOSM").remove();
drawLayer.transition().duration(250).style("opacity", 0).on("end interrupt", () => {
editOff();
dispatch10.call("change");
});
}
function updateMarkers() {
if (!layerVisible || !_layerEnabled2)
return;
const service = getService();
const selectedID = context.selectedErrorID();
const data = service ? service.getItems(projection2) : [];
const getTransform = svgPointTransform(projection2);
const markers = drawLayer.selectAll(".qaItem.improveOSM").data(data, (d) => d.id);
markers.exit().remove();
const markersEnter = markers.enter().append("g").attr("class", (d) => `qaItem ${d.service} itemId-${d.id} itemType-${d.itemType}`);
markersEnter.append("polygon").call(markerPath, "shadow");
markersEnter.append("ellipse").attr("cx", 0).attr("cy", 0).attr("rx", 4.5).attr("ry", 2).attr("class", "stroke");
markersEnter.append("polygon").attr("fill", "currentColor").call(markerPath, "qaItem-fill");
markersEnter.append("use").attr("class", "icon-annotation").attr("transform", "translate(-6, -22)").attr("width", "12px").attr("height", "12px").attr("xlink:href", (d) => d.icon ? "#" + d.icon : "");
markers.merge(markersEnter).sort(sortY).classed("selected", (d) => d.id === selectedID).attr("transform", getTransform);
if (touchLayer.empty())
return;
const fillClass = context.getDebug("target") ? "pink " : "nocolor ";
const targets = touchLayer.selectAll(".qaItem.improveOSM").data(data, (d) => d.id);
targets.exit().remove();
targets.enter().append("rect").attr("width", "20px").attr("height", "30px").attr("x", "-10px").attr("y", "-28px").merge(targets).sort(sortY).attr("class", (d) => `qaItem ${d.service} target ${fillClass} itemId-${d.id}`).attr("transform", getTransform);
function sortY(a, b) {
return a.id === selectedID ? 1 : b.id === selectedID ? -1 : b.loc[1] - a.loc[1];
}
}
function drawImproveOSM(selection2) {
const service = getService();
const surface = context.surface();
if (surface && !surface.empty()) {
touchLayer = surface.selectAll(".data-layer.touch .layer-touch.markers");
}
drawLayer = selection2.selectAll(".layer-improveOSM").data(service ? [0] : []);
drawLayer.exit().remove();
drawLayer = drawLayer.enter().append("g").attr("class", "layer-improveOSM").style("display", _layerEnabled2 ? "block" : "none").merge(drawLayer);
if (_layerEnabled2) {
if (service && ~~context.map().zoom() >= minZoom3) {
editOn();
service.loadIssues(projection2);
updateMarkers();
} else {
editOff();
}
}
}
drawImproveOSM.enabled = function(val) {
if (!arguments.length)
return _layerEnabled2;
_layerEnabled2 = val;
if (_layerEnabled2) {
layerOn();
} else {
layerOff();
if (context.selectedErrorID()) {
context.enter(modeBrowse(context));
}
}
dispatch10.call("change");
return this;
};
drawImproveOSM.supported = () => !!getService();
return drawImproveOSM;
}
// modules/svg/osmose.js
var _layerEnabled3 = false;
var _qaService3;
function svgOsmose(projection2, context, dispatch10) {
const throttledRedraw = throttle_default(() => dispatch10.call("change"), 1e3);
const minZoom3 = 12;
let touchLayer = select_default2(null);
let drawLayer = select_default2(null);
let layerVisible = false;
function markerPath(selection2, klass) {
selection2.attr("class", klass).attr("transform", "translate(-10, -28)").attr("points", "16,3 4,3 1,6 1,17 4,20 7,20 10,27 13,20 16,20 19,17.033 19,6");
}
function getService() {
if (services.osmose && !_qaService3) {
_qaService3 = services.osmose;
_qaService3.on("loaded", throttledRedraw);
} else if (!services.osmose && _qaService3) {
_qaService3 = null;
}
return _qaService3;
}
function editOn() {
if (!layerVisible) {
layerVisible = true;
drawLayer.style("display", "block");
}
}
function editOff() {
if (layerVisible) {
layerVisible = false;
drawLayer.style("display", "none");
drawLayer.selectAll(".qaItem.osmose").remove();
touchLayer.selectAll(".qaItem.osmose").remove();
}
}
function layerOn() {
editOn();
drawLayer.style("opacity", 0).transition().duration(250).style("opacity", 1).on("end interrupt", () => dispatch10.call("change"));
}
function layerOff() {
throttledRedraw.cancel();
drawLayer.interrupt();
touchLayer.selectAll(".qaItem.osmose").remove();
drawLayer.transition().duration(250).style("opacity", 0).on("end interrupt", () => {
editOff();
dispatch10.call("change");
});
}
function updateMarkers() {
if (!layerVisible || !_layerEnabled3)
return;
const service = getService();
const selectedID = context.selectedErrorID();
const data = service ? service.getItems(projection2) : [];
const getTransform = svgPointTransform(projection2);
const markers = drawLayer.selectAll(".qaItem.osmose").data(data, (d) => d.id);
markers.exit().remove();
const markersEnter = markers.enter().append("g").attr("class", (d) => `qaItem ${d.service} itemId-${d.id} itemType-${d.itemType}`);
markersEnter.append("polygon").call(markerPath, "shadow");
markersEnter.append("ellipse").attr("cx", 0).attr("cy", 0).attr("rx", 4.5).attr("ry", 2).attr("class", "stroke");
markersEnter.append("polygon").attr("fill", (d) => service.getColor(d.item)).call(markerPath, "qaItem-fill");
markersEnter.append("use").attr("class", "icon-annotation").attr("transform", "translate(-6, -22)").attr("width", "12px").attr("height", "12px").attr("xlink:href", (d) => d.icon ? "#" + d.icon : "");
markers.merge(markersEnter).sort(sortY).classed("selected", (d) => d.id === selectedID).attr("transform", getTransform);
if (touchLayer.empty())
return;
const fillClass = context.getDebug("target") ? "pink" : "nocolor";
const targets = touchLayer.selectAll(".qaItem.osmose").data(data, (d) => d.id);
targets.exit().remove();
targets.enter().append("rect").attr("width", "20px").attr("height", "30px").attr("x", "-10px").attr("y", "-28px").merge(targets).sort(sortY).attr("class", (d) => `qaItem ${d.service} target ${fillClass} itemId-${d.id}`).attr("transform", getTransform);
function sortY(a, b) {
return a.id === selectedID ? 1 : b.id === selectedID ? -1 : b.loc[1] - a.loc[1];
}
}
function drawOsmose(selection2) {
const service = getService();
const surface = context.surface();
if (surface && !surface.empty()) {
touchLayer = surface.selectAll(".data-layer.touch .layer-touch.markers");
}
drawLayer = selection2.selectAll(".layer-osmose").data(service ? [0] : []);
drawLayer.exit().remove();
drawLayer = drawLayer.enter().append("g").attr("class", "layer-osmose").style("display", _layerEnabled3 ? "block" : "none").merge(drawLayer);
if (_layerEnabled3) {
if (service && ~~context.map().zoom() >= minZoom3) {
editOn();
service.loadIssues(projection2);
updateMarkers();
} else {
editOff();
}
}
}
drawOsmose.enabled = function(val) {
if (!arguments.length)
return _layerEnabled3;
_layerEnabled3 = val;
if (_layerEnabled3) {
getService().loadStrings().then(layerOn).catch((err) => {
console.log(err);
});
} else {
layerOff();
if (context.selectedErrorID()) {
context.enter(modeBrowse(context));
}
}
dispatch10.call("change");
return this;
};
drawOsmose.supported = () => !!getService();
return drawOsmose;
}
// modules/svg/streetside.js
function svgStreetside(projection2, context, dispatch10) {
var throttledRedraw = throttle_default(function() {
dispatch10.call("change");
}, 1e3);
var minZoom3 = 14;
var minMarkerZoom = 16;
var minViewfieldZoom = 18;
var layer = select_default2(null);
var _viewerYaw = 0;
var _selectedSequence = null;
var _streetside;
function init2() {
if (svgStreetside.initialized)
return;
svgStreetside.enabled = false;
svgStreetside.initialized = true;
}
function getService() {
if (services.streetside && !_streetside) {
_streetside = services.streetside;
_streetside.event.on("viewerChanged.svgStreetside", viewerChanged).on("loadedImages.svgStreetside", throttledRedraw);
} else if (!services.streetside && _streetside) {
_streetside = null;
}
return _streetside;
}
function showLayer() {
var service = getService();
if (!service)
return;
editOn();
layer.style("opacity", 0).transition().duration(250).style("opacity", 1).on("end", function() {
dispatch10.call("change");
});
}
function hideLayer() {
throttledRedraw.cancel();
layer.transition().duration(250).style("opacity", 0).on("end", editOff);
}
function editOn() {
layer.style("display", "block");
}
function editOff() {
layer.selectAll(".viewfield-group").remove();
layer.style("display", "none");
}
function click(d3_event, d) {
var service = getService();
if (!service)
return;
if (d.sequenceKey !== _selectedSequence) {
_viewerYaw = 0;
}
_selectedSequence = d.sequenceKey;
service.ensureViewerLoaded(context).then(function() {
service.selectImage(context, d.key).yaw(_viewerYaw).showViewer(context);
});
context.map().centerEase(d.loc);
}
function mouseover(d3_event, d) {
var service = getService();
if (service)
service.setStyles(context, d);
}
function mouseout() {
var service = getService();
if (service)
service.setStyles(context, null);
}
function transform2(d) {
var t = svgPointTransform(projection2)(d);
var rot = d.ca + _viewerYaw;
if (rot) {
t += " rotate(" + Math.floor(rot) + ",0,0)";
}
return t;
}
function viewerChanged() {
var service = getService();
if (!service)
return;
var viewer = service.viewer();
if (!viewer)
return;
_viewerYaw = viewer.getYaw();
if (context.map().isTransformed())
return;
layer.selectAll(".viewfield-group.currentView").attr("transform", transform2);
}
function filterBubbles(bubbles) {
var fromDate = context.photos().fromDate();
var toDate = context.photos().toDate();
var usernames = context.photos().usernames();
if (fromDate) {
var fromTimestamp = new Date(fromDate).getTime();
bubbles = bubbles.filter(function(bubble) {
return new Date(bubble.captured_at).getTime() >= fromTimestamp;
});
}
if (toDate) {
var toTimestamp = new Date(toDate).getTime();
bubbles = bubbles.filter(function(bubble) {
return new Date(bubble.captured_at).getTime() <= toTimestamp;
});
}
if (usernames) {
bubbles = bubbles.filter(function(bubble) {
return usernames.indexOf(bubble.captured_by) !== -1;
});
}
return bubbles;
}
function filterSequences(sequences) {
var fromDate = context.photos().fromDate();
var toDate = context.photos().toDate();
var usernames = context.photos().usernames();
if (fromDate) {
var fromTimestamp = new Date(fromDate).getTime();
sequences = sequences.filter(function(sequences2) {
return new Date(sequences2.properties.captured_at).getTime() >= fromTimestamp;
});
}
if (toDate) {
var toTimestamp = new Date(toDate).getTime();
sequences = sequences.filter(function(sequences2) {
return new Date(sequences2.properties.captured_at).getTime() <= toTimestamp;
});
}
if (usernames) {
sequences = sequences.filter(function(sequences2) {
return usernames.indexOf(sequences2.properties.captured_by) !== -1;
});
}
return sequences;
}
function update() {
var viewer = context.container().select(".photoviewer");
var selected = viewer.empty() ? void 0 : viewer.datum();
var z = ~~context.map().zoom();
var showMarkers = z >= minMarkerZoom;
var showViewfields = z >= minViewfieldZoom;
var service = getService();
var sequences = [];
var bubbles = [];
if (context.photos().showsPanoramic()) {
sequences = service ? service.sequences(projection2) : [];
bubbles = service && showMarkers ? service.bubbles(projection2) : [];
sequences = filterSequences(sequences);
bubbles = filterBubbles(bubbles);
}
var traces = layer.selectAll(".sequences").selectAll(".sequence").data(sequences, function(d) {
return d.properties.key;
});
traces.exit().remove();
traces = traces.enter().append("path").attr("class", "sequence").merge(traces).attr("d", svgPath(projection2).geojson);
var groups = layer.selectAll(".markers").selectAll(".viewfield-group").data(bubbles, function(d) {
return d.key + (d.sequenceKey ? "v1" : "v0");
});
groups.exit().remove();
var groupsEnter = groups.enter().append("g").attr("class", "viewfield-group").on("mouseenter", mouseover).on("mouseleave", mouseout).on("click", click);
groupsEnter.append("g").attr("class", "viewfield-scale");
var markers = groups.merge(groupsEnter).sort(function(a, b) {
return a === selected ? 1 : b === selected ? -1 : b.loc[1] - a.loc[1];
}).attr("transform", transform2).select(".viewfield-scale");
markers.selectAll("circle").data([0]).enter().append("circle").attr("dx", "0").attr("dy", "0").attr("r", "6");
var viewfields = markers.selectAll(".viewfield").data(showViewfields ? [0] : []);
viewfields.exit().remove();
viewfields.enter().insert("path", "circle").attr("class", "viewfield").attr("transform", "scale(1.5,1.5),translate(-8, -13)").attr("d", viewfieldPath);
function viewfieldPath() {
var d = this.parentNode.__data__;
if (d.pano) {
return "M 8,13 m -10,0 a 10,10 0 1,0 20,0 a 10,10 0 1,0 -20,0";
} else {
return "M 6,9 C 8,8.4 8,8.4 10,9 L 16,-2 C 12,-5 4,-5 0,-2 z";
}
}
}
function drawImages(selection2) {
var enabled = svgStreetside.enabled;
var service = getService();
layer = selection2.selectAll(".layer-streetside-images").data(service ? [0] : []);
layer.exit().remove();
var layerEnter = layer.enter().append("g").attr("class", "layer-streetside-images").style("display", enabled ? "block" : "none");
layerEnter.append("g").attr("class", "sequences");
layerEnter.append("g").attr("class", "markers");
layer = layerEnter.merge(layer);
if (enabled) {
if (service && ~~context.map().zoom() >= minZoom3) {
editOn();
update();
service.loadBubbles(projection2);
} else {
editOff();
}
}
}
drawImages.enabled = function(_) {
if (!arguments.length)
return svgStreetside.enabled;
svgStreetside.enabled = _;
if (svgStreetside.enabled) {
showLayer();
context.photos().on("change.streetside", update);
} else {
hideLayer();
context.photos().on("change.streetside", null);
}
dispatch10.call("change");
return this;
};
drawImages.supported = function() {
return !!getService();
};
init2();
return drawImages;
}
// modules/svg/mapillary_images.js
function svgMapillaryImages(projection2, context, dispatch10) {
const throttledRedraw = throttle_default(function() {
dispatch10.call("change");
}, 1e3);
const minZoom3 = 12;
const minMarkerZoom = 16;
const minViewfieldZoom = 18;
let layer = select_default2(null);
let _mapillary;
function init2() {
if (svgMapillaryImages.initialized)
return;
svgMapillaryImages.enabled = false;
svgMapillaryImages.initialized = true;
}
function getService() {
if (services.mapillary && !_mapillary) {
_mapillary = services.mapillary;
_mapillary.event.on("loadedImages", throttledRedraw);
} else if (!services.mapillary && _mapillary) {
_mapillary = null;
}
return _mapillary;
}
function showLayer() {
const service = getService();
if (!service)
return;
editOn();
layer.style("opacity", 0).transition().duration(250).style("opacity", 1).on("end", function() {
dispatch10.call("change");
});
}
function hideLayer() {
throttledRedraw.cancel();
layer.transition().duration(250).style("opacity", 0).on("end", editOff);
}
function editOn() {
layer.style("display", "block");
}
function editOff() {
layer.selectAll(".viewfield-group").remove();
layer.style("display", "none");
}
function click(d3_event, image) {
const service = getService();
if (!service)
return;
service.ensureViewerLoaded(context).then(function() {
service.selectImage(context, image.id).showViewer(context);
});
context.map().centerEase(image.loc);
}
function mouseover(d3_event, image) {
const service = getService();
if (service)
service.setStyles(context, image);
}
function mouseout() {
const service = getService();
if (service)
service.setStyles(context, null);
}
function transform2(d) {
let t = svgPointTransform(projection2)(d);
if (d.ca) {
t += " rotate(" + Math.floor(d.ca) + ",0,0)";
}
return t;
}
function filterImages(images) {
const showsPano = context.photos().showsPanoramic();
const showsFlat = context.photos().showsFlat();
const fromDate = context.photos().fromDate();
const toDate = context.photos().toDate();
if (!showsPano || !showsFlat) {
images = images.filter(function(image) {
if (image.is_pano)
return showsPano;
return showsFlat;
});
}
if (fromDate) {
images = images.filter(function(image) {
return new Date(image.captured_at).getTime() >= new Date(fromDate).getTime();
});
}
if (toDate) {
images = images.filter(function(image) {
return new Date(image.captured_at).getTime() <= new Date(toDate).getTime();
});
}
return images;
}
function filterSequences(sequences) {
const showsPano = context.photos().showsPanoramic();
const showsFlat = context.photos().showsFlat();
const fromDate = context.photos().fromDate();
const toDate = context.photos().toDate();
if (!showsPano || !showsFlat) {
sequences = sequences.filter(function(sequence) {
if (sequence.properties.hasOwnProperty("is_pano")) {
if (sequence.properties.is_pano)
return showsPano;
return showsFlat;
}
return false;
});
}
if (fromDate) {
sequences = sequences.filter(function(sequence) {
return new Date(sequence.properties.captured_at).getTime() >= new Date(fromDate).getTime().toString();
});
}
if (toDate) {
sequences = sequences.filter(function(sequence) {
return new Date(sequence.properties.captured_at).getTime() <= new Date(toDate).getTime().toString();
});
}
return sequences;
}
function update() {
const z = ~~context.map().zoom();
const showMarkers = z >= minMarkerZoom;
const showViewfields = z >= minViewfieldZoom;
const service = getService();
let sequences = service ? service.sequences(projection2) : [];
let images = service && showMarkers ? service.images(projection2) : [];
images = filterImages(images);
sequences = filterSequences(sequences, service);
service.filterViewer(context);
let traces = layer.selectAll(".sequences").selectAll(".sequence").data(sequences, function(d) {
return d.properties.id;
});
traces.exit().remove();
traces = traces.enter().append("path").attr("class", "sequence").merge(traces).attr("d", svgPath(projection2).geojson);
const groups = layer.selectAll(".markers").selectAll(".viewfield-group").data(images, function(d) {
return d.id;
});
groups.exit().remove();
const groupsEnter = groups.enter().append("g").attr("class", "viewfield-group").on("mouseenter", mouseover).on("mouseleave", mouseout).on("click", click);
groupsEnter.append("g").attr("class", "viewfield-scale");
const markers = groups.merge(groupsEnter).sort(function(a, b) {
return b.loc[1] - a.loc[1];
}).attr("transform", transform2).select(".viewfield-scale");
markers.selectAll("circle").data([0]).enter().append("circle").attr("dx", "0").attr("dy", "0").attr("r", "6");
const viewfields = markers.selectAll(".viewfield").data(showViewfields ? [0] : []);
viewfields.exit().remove();
viewfields.enter().insert("path", "circle").attr("class", "viewfield").classed("pano", function() {
return this.parentNode.__data__.is_pano;
}).attr("transform", "scale(1.5,1.5),translate(-8, -13)").attr("d", viewfieldPath);
function viewfieldPath() {
if (this.parentNode.__data__.is_pano) {
return "M 8,13 m -10,0 a 10,10 0 1,0 20,0 a 10,10 0 1,0 -20,0";
} else {
return "M 6,9 C 8,8.4 8,8.4 10,9 L 16,-2 C 12,-5 4,-5 0,-2 z";
}
}
}
function drawImages(selection2) {
const enabled = svgMapillaryImages.enabled;
const service = getService();
layer = selection2.selectAll(".layer-mapillary").data(service ? [0] : []);
layer.exit().remove();
const layerEnter = layer.enter().append("g").attr("class", "layer-mapillary").style("display", enabled ? "block" : "none");
layerEnter.append("g").attr("class", "sequences");
layerEnter.append("g").attr("class", "markers");
layer = layerEnter.merge(layer);
if (enabled) {
if (service && ~~context.map().zoom() >= minZoom3) {
editOn();
update();
service.loadImages(projection2);
} else {
editOff();
}
}
}
drawImages.enabled = function(_) {
if (!arguments.length)
return svgMapillaryImages.enabled;
svgMapillaryImages.enabled = _;
if (svgMapillaryImages.enabled) {
showLayer();
context.photos().on("change.mapillary_images", update);
} else {
hideLayer();
context.photos().on("change.mapillary_images", null);
}
dispatch10.call("change");
return this;
};
drawImages.supported = function() {
return !!getService();
};
init2();
return drawImages;
}
// modules/svg/mapillary_position.js
function svgMapillaryPosition(projection2, context) {
const throttledRedraw = throttle_default(function() {
update();
}, 1e3);
const minZoom3 = 12;
const minViewfieldZoom = 18;
let layer = select_default2(null);
let _mapillary;
let viewerCompassAngle;
function init2() {
if (svgMapillaryPosition.initialized)
return;
svgMapillaryPosition.initialized = true;
}
function getService() {
if (services.mapillary && !_mapillary) {
_mapillary = services.mapillary;
_mapillary.event.on("imageChanged", throttledRedraw);
_mapillary.event.on("bearingChanged", function(e) {
viewerCompassAngle = e.bearing;
if (context.map().isTransformed())
return;
layer.selectAll(".viewfield-group.currentView").filter(function(d) {
return d.is_pano;
}).attr("transform", transform2);
});
} else if (!services.mapillary && _mapillary) {
_mapillary = null;
}
return _mapillary;
}
function editOn() {
layer.style("display", "block");
}
function editOff() {
layer.selectAll(".viewfield-group").remove();
layer.style("display", "none");
}
function transform2(d) {
let t = svgPointTransform(projection2)(d);
if (d.is_pano && viewerCompassAngle !== null && isFinite(viewerCompassAngle)) {
t += " rotate(" + Math.floor(viewerCompassAngle) + ",0,0)";
} else if (d.ca) {
t += " rotate(" + Math.floor(d.ca) + ",0,0)";
}
return t;
}
function update() {
const z = ~~context.map().zoom();
const showViewfields = z >= minViewfieldZoom;
const service = getService();
const image = service && service.getActiveImage();
const groups = layer.selectAll(".markers").selectAll(".viewfield-group").data(image ? [image] : [], function(d) {
return d.id;
});
groups.exit().remove();
const groupsEnter = groups.enter().append("g").attr("class", "viewfield-group currentView highlighted");
groupsEnter.append("g").attr("class", "viewfield-scale");
const markers = groups.merge(groupsEnter).attr("transform", transform2).select(".viewfield-scale");
markers.selectAll("circle").data([0]).enter().append("circle").attr("dx", "0").attr("dy", "0").attr("r", "6");
const viewfields = markers.selectAll(".viewfield").data(showViewfields ? [0] : []);
viewfields.exit().remove();
viewfields.enter().insert("path", "circle").attr("class", "viewfield").attr("transform", "scale(1.5,1.5),translate(-8, -13)").attr("d", "M 6,9 C 8,8.4 8,8.4 10,9 L 16,-2 C 12,-5 4,-5 0,-2 z");
}
function drawImages(selection2) {
const service = getService();
layer = selection2.selectAll(".layer-mapillary-position").data(service ? [0] : []);
layer.exit().remove();
const layerEnter = layer.enter().append("g").attr("class", "layer-mapillary-position");
layerEnter.append("g").attr("class", "markers");
layer = layerEnter.merge(layer);
if (service && ~~context.map().zoom() >= minZoom3) {
editOn();
update();
} else {
editOff();
}
}
drawImages.enabled = function() {
update();
return this;
};
drawImages.supported = function() {
return !!getService();
};
init2();
return drawImages;
}
// modules/svg/mapillary_signs.js
function svgMapillarySigns(projection2, context, dispatch10) {
const throttledRedraw = throttle_default(function() {
dispatch10.call("change");
}, 1e3);
const minZoom3 = 12;
let layer = select_default2(null);
let _mapillary;
function init2() {
if (svgMapillarySigns.initialized)
return;
svgMapillarySigns.enabled = false;
svgMapillarySigns.initialized = true;
}
function getService() {
if (services.mapillary && !_mapillary) {
_mapillary = services.mapillary;
_mapillary.event.on("loadedSigns", throttledRedraw);
} else if (!services.mapillary && _mapillary) {
_mapillary = null;
}
return _mapillary;
}
function showLayer() {
const service = getService();
if (!service)
return;
service.loadSignResources(context);
editOn();
}
function hideLayer() {
throttledRedraw.cancel();
editOff();
}
function editOn() {
layer.style("display", "block");
}
function editOff() {
layer.selectAll(".icon-sign").remove();
layer.style("display", "none");
}
function click(d3_event, d) {
const service = getService();
if (!service)
return;
context.map().centerEase(d.loc);
const selectedImageId = service.getActiveImage() && service.getActiveImage().id;
service.getDetections(d.id).then((detections) => {
if (detections.length) {
const imageId = detections[0].image.id;
if (imageId === selectedImageId) {
service.highlightDetection(detections[0]).selectImage(context, imageId);
} else {
service.ensureViewerLoaded(context).then(function() {
service.highlightDetection(detections[0]).selectImage(context, imageId).showViewer(context);
});
}
}
});
}
function filterData(detectedFeatures) {
var fromDate = context.photos().fromDate();
var toDate = context.photos().toDate();
if (fromDate) {
var fromTimestamp = new Date(fromDate).getTime();
detectedFeatures = detectedFeatures.filter(function(feature3) {
return new Date(feature3.last_seen_at).getTime() >= fromTimestamp;
});
}
if (toDate) {
var toTimestamp = new Date(toDate).getTime();
detectedFeatures = detectedFeatures.filter(function(feature3) {
return new Date(feature3.first_seen_at).getTime() <= toTimestamp;
});
}
return detectedFeatures;
}
function update() {
const service = getService();
let data = service ? service.signs(projection2) : [];
data = filterData(data);
const transform2 = svgPointTransform(projection2);
const signs = layer.selectAll(".icon-sign").data(data, function(d) {
return d.id;
});
signs.exit().remove();
const enter = signs.enter().append("g").attr("class", "icon-sign icon-detected").on("click", click);
enter.append("use").attr("width", "24px").attr("height", "24px").attr("x", "-12px").attr("y", "-12px").attr("xlink:href", function(d) {
return "#" + d.value;
});
enter.append("rect").attr("width", "24px").attr("height", "24px").attr("x", "-12px").attr("y", "-12px");
signs.merge(enter).attr("transform", transform2);
}
function drawSigns(selection2) {
const enabled = svgMapillarySigns.enabled;
const service = getService();
layer = selection2.selectAll(".layer-mapillary-signs").data(service ? [0] : []);
layer.exit().remove();
layer = layer.enter().append("g").attr("class", "layer-mapillary-signs layer-mapillary-detections").style("display", enabled ? "block" : "none").merge(layer);
if (enabled) {
if (service && ~~context.map().zoom() >= minZoom3) {
editOn();
update();
service.loadSigns(projection2);
service.showSignDetections(true);
} else {
editOff();
}
} else if (service) {
service.showSignDetections(false);
}
}
drawSigns.enabled = function(_) {
if (!arguments.length)
return svgMapillarySigns.enabled;
svgMapillarySigns.enabled = _;
if (svgMapillarySigns.enabled) {
showLayer();
context.photos().on("change.mapillary_signs", update);
} else {
hideLayer();
context.photos().on("change.mapillary_signs", null);
}
dispatch10.call("change");
return this;
};
drawSigns.supported = function() {
return !!getService();
};
init2();
return drawSigns;
}
// modules/svg/mapillary_map_features.js
function svgMapillaryMapFeatures(projection2, context, dispatch10) {
const throttledRedraw = throttle_default(function() {
dispatch10.call("change");
}, 1e3);
const minZoom3 = 12;
let layer = select_default2(null);
let _mapillary;
function init2() {
if (svgMapillaryMapFeatures.initialized)
return;
svgMapillaryMapFeatures.enabled = false;
svgMapillaryMapFeatures.initialized = true;
}
function getService() {
if (services.mapillary && !_mapillary) {
_mapillary = services.mapillary;
_mapillary.event.on("loadedMapFeatures", throttledRedraw);
} else if (!services.mapillary && _mapillary) {
_mapillary = null;
}
return _mapillary;
}
function showLayer() {
const service = getService();
if (!service)
return;
service.loadObjectResources(context);
editOn();
}
function hideLayer() {
throttledRedraw.cancel();
editOff();
}
function editOn() {
layer.style("display", "block");
}
function editOff() {
layer.selectAll(".icon-map-feature").remove();
layer.style("display", "none");
}
function click(d3_event, d) {
const service = getService();
if (!service)
return;
context.map().centerEase(d.loc);
const selectedImageId = service.getActiveImage() && service.getActiveImage().id;
service.getDetections(d.id).then((detections) => {
if (detections.length) {
const imageId = detections[0].image.id;
if (imageId === selectedImageId) {
service.highlightDetection(detections[0]).selectImage(context, imageId);
} else {
service.ensureViewerLoaded(context).then(function() {
service.highlightDetection(detections[0]).selectImage(context, imageId).showViewer(context);
});
}
}
});
}
function filterData(detectedFeatures) {
const fromDate = context.photos().fromDate();
const toDate = context.photos().toDate();
if (fromDate) {
detectedFeatures = detectedFeatures.filter(function(feature3) {
return new Date(feature3.last_seen_at).getTime() >= new Date(fromDate).getTime();
});
}
if (toDate) {
detectedFeatures = detectedFeatures.filter(function(feature3) {
return new Date(feature3.first_seen_at).getTime() <= new Date(toDate).getTime();
});
}
return detectedFeatures;
}
function update() {
const service = getService();
let data = service ? service.mapFeatures(projection2) : [];
data = filterData(data);
const transform2 = svgPointTransform(projection2);
const mapFeatures = layer.selectAll(".icon-map-feature").data(data, function(d) {
return d.id;
});
mapFeatures.exit().remove();
const enter = mapFeatures.enter().append("g").attr("class", "icon-map-feature icon-detected").on("click", click);
enter.append("title").text(function(d) {
var id2 = d.value.replace(/--/g, ".").replace(/-/g, "_");
return _t("mapillary_map_features." + id2);
});
enter.append("use").attr("width", "24px").attr("height", "24px").attr("x", "-12px").attr("y", "-12px").attr("xlink:href", function(d) {
if (d.value === "object--billboard") {
return "#object--sign--advertisement";
}
return "#" + d.value;
});
enter.append("rect").attr("width", "24px").attr("height", "24px").attr("x", "-12px").attr("y", "-12px");
mapFeatures.merge(enter).attr("transform", transform2);
}
function drawMapFeatures(selection2) {
const enabled = svgMapillaryMapFeatures.enabled;
const service = getService();
layer = selection2.selectAll(".layer-mapillary-map-features").data(service ? [0] : []);
layer.exit().remove();
layer = layer.enter().append("g").attr("class", "layer-mapillary-map-features layer-mapillary-detections").style("display", enabled ? "block" : "none").merge(layer);
if (enabled) {
if (service && ~~context.map().zoom() >= minZoom3) {
editOn();
update();
service.loadMapFeatures(projection2);
service.showFeatureDetections(true);
} else {
editOff();
}
} else if (service) {
service.showFeatureDetections(false);
}
}
drawMapFeatures.enabled = function(_) {
if (!arguments.length)
return svgMapillaryMapFeatures.enabled;
svgMapillaryMapFeatures.enabled = _;
if (svgMapillaryMapFeatures.enabled) {
showLayer();
context.photos().on("change.mapillary_map_features", update);
} else {
hideLayer();
context.photos().on("change.mapillary_map_features", null);
}
dispatch10.call("change");
return this;
};
drawMapFeatures.supported = function() {
return !!getService();
};
init2();
return drawMapFeatures;
}
// modules/svg/kartaview_images.js
function svgKartaviewImages(projection2, context, dispatch10) {
var throttledRedraw = throttle_default(function() {
dispatch10.call("change");
}, 1e3);
var minZoom3 = 12;
var minMarkerZoom = 16;
var minViewfieldZoom = 18;
var layer = select_default2(null);
var _kartaview;
function init2() {
if (svgKartaviewImages.initialized)
return;
svgKartaviewImages.enabled = false;
svgKartaviewImages.initialized = true;
}
function getService() {
if (services.kartaview && !_kartaview) {
_kartaview = services.kartaview;
_kartaview.event.on("loadedImages", throttledRedraw);
} else if (!services.kartaview && _kartaview) {
_kartaview = null;
}
return _kartaview;
}
function showLayer() {
var service = getService();
if (!service)
return;
editOn();
layer.style("opacity", 0).transition().duration(250).style("opacity", 1).on("end", function() {
dispatch10.call("change");
});
}
function hideLayer() {
throttledRedraw.cancel();
layer.transition().duration(250).style("opacity", 0).on("end", editOff);
}
function editOn() {
layer.style("display", "block");
}
function editOff() {
layer.selectAll(".viewfield-group").remove();
layer.style("display", "none");
}
function click(d3_event, d) {
var service = getService();
if (!service)
return;
service.ensureViewerLoaded(context).then(function() {
service.selectImage(context, d.key).showViewer(context);
});
context.map().centerEase(d.loc);
}
function mouseover(d3_event, d) {
var service = getService();
if (service)
service.setStyles(context, d);
}
function mouseout() {
var service = getService();
if (service)
service.setStyles(context, null);
}
function transform2(d) {
var t = svgPointTransform(projection2)(d);
if (d.ca) {
t += " rotate(" + Math.floor(d.ca) + ",0,0)";
}
return t;
}
function filterImages(images) {
var fromDate = context.photos().fromDate();
var toDate = context.photos().toDate();
var usernames = context.photos().usernames();
if (fromDate) {
var fromTimestamp = new Date(fromDate).getTime();
images = images.filter(function(item) {
return new Date(item.captured_at).getTime() >= fromTimestamp;
});
}
if (toDate) {
var toTimestamp = new Date(toDate).getTime();
images = images.filter(function(item) {
return new Date(item.captured_at).getTime() <= toTimestamp;
});
}
if (usernames) {
images = images.filter(function(item) {
return usernames.indexOf(item.captured_by) !== -1;
});
}
return images;
}
function filterSequences(sequences) {
var fromDate = context.photos().fromDate();
var toDate = context.photos().toDate();
var usernames = context.photos().usernames();
if (fromDate) {
var fromTimestamp = new Date(fromDate).getTime();
sequences = sequences.filter(function(image) {
return new Date(image.properties.captured_at).getTime() >= fromTimestamp;
});
}
if (toDate) {
var toTimestamp = new Date(toDate).getTime();
sequences = sequences.filter(function(image) {
return new Date(image.properties.captured_at).getTime() <= toTimestamp;
});
}
if (usernames) {
sequences = sequences.filter(function(image) {
return usernames.indexOf(image.properties.captured_by) !== -1;
});
}
return sequences;
}
function update() {
var viewer = context.container().select(".photoviewer");
var selected = viewer.empty() ? void 0 : viewer.datum();
var z = ~~context.map().zoom();
var showMarkers = z >= minMarkerZoom;
var showViewfields = z >= minViewfieldZoom;
var service = getService();
var sequences = [];
var images = [];
if (context.photos().showsFlat()) {
sequences = service ? service.sequences(projection2) : [];
images = service && showMarkers ? service.images(projection2) : [];
sequences = filterSequences(sequences);
images = filterImages(images);
}
var traces = layer.selectAll(".sequences").selectAll(".sequence").data(sequences, function(d) {
return d.properties.key;
});
traces.exit().remove();
traces = traces.enter().append("path").attr("class", "sequence").merge(traces).attr("d", svgPath(projection2).geojson);
var groups = layer.selectAll(".markers").selectAll(".viewfield-group").data(images, function(d) {
return d.key;
});
groups.exit().remove();
var groupsEnter = groups.enter().append("g").attr("class", "viewfield-group").on("mouseenter", mouseover).on("mouseleave", mouseout).on("click", click);
groupsEnter.append("g").attr("class", "viewfield-scale");
var markers = groups.merge(groupsEnter).sort(function(a, b) {
return a === selected ? 1 : b === selected ? -1 : b.loc[1] - a.loc[1];
}).attr("transform", transform2).select(".viewfield-scale");
markers.selectAll("circle").data([0]).enter().append("circle").attr("dx", "0").attr("dy", "0").attr("r", "6");
var viewfields = markers.selectAll(".viewfield").data(showViewfields ? [0] : []);
viewfields.exit().remove();
viewfields.enter().insert("path", "circle").attr("class", "viewfield").attr("transform", "scale(1.5,1.5),translate(-8, -13)").attr("d", "M 6,9 C 8,8.4 8,8.4 10,9 L 16,-2 C 12,-5 4,-5 0,-2 z");
}
function drawImages(selection2) {
var enabled = svgKartaviewImages.enabled, service = getService();
layer = selection2.selectAll(".layer-kartaview").data(service ? [0] : []);
layer.exit().remove();
var layerEnter = layer.enter().append("g").attr("class", "layer-kartaview").style("display", enabled ? "block" : "none");
layerEnter.append("g").attr("class", "sequences");
layerEnter.append("g").attr("class", "markers");
layer = layerEnter.merge(layer);
if (enabled) {
if (service && ~~context.map().zoom() >= minZoom3) {
editOn();
update();
service.loadImages(projection2);
} else {
editOff();
}
}
}
drawImages.enabled = function(_) {
if (!arguments.length)
return svgKartaviewImages.enabled;
svgKartaviewImages.enabled = _;
if (svgKartaviewImages.enabled) {
showLayer();
context.photos().on("change.kartaview_images", update);
} else {
hideLayer();
context.photos().on("change.kartaview_images", null);
}
dispatch10.call("change");
return this;
};
drawImages.supported = function() {
return !!getService();
};
init2();
return drawImages;
}
// modules/svg/osm.js
function svgOsm(projection2, context, dispatch10) {
var enabled = true;
function drawOsm(selection2) {
selection2.selectAll(".layer-osm").data(["covered", "areas", "lines", "points", "labels"]).enter().append("g").attr("class", function(d) {
return "layer-osm " + d;
});
selection2.selectAll(".layer-osm.points").selectAll(".points-group").data(["points", "midpoints", "vertices", "turns"]).enter().append("g").attr("class", function(d) {
return "points-group " + d;
});
}
function showLayer() {
var layer = context.surface().selectAll(".data-layer.osm");
layer.interrupt();
layer.classed("disabled", false).style("opacity", 0).transition().duration(250).style("opacity", 1).on("end interrupt", function() {
dispatch10.call("change");
});
}
function hideLayer() {
var layer = context.surface().selectAll(".data-layer.osm");
layer.interrupt();
layer.transition().duration(250).style("opacity", 0).on("end interrupt", function() {
layer.classed("disabled", true);
dispatch10.call("change");
});
}
drawOsm.enabled = function(val) {
if (!arguments.length)
return enabled;
enabled = val;
if (enabled) {
showLayer();
} else {
hideLayer();
}
dispatch10.call("change");
return this;
};
return drawOsm;
}
// modules/svg/notes.js
var _notesEnabled = false;
var _osmService;
function svgNotes(projection2, context, dispatch10) {
if (!dispatch10) {
dispatch10 = dispatch_default("change");
}
var throttledRedraw = throttle_default(function() {
dispatch10.call("change");
}, 1e3);
var minZoom3 = 12;
var touchLayer = select_default2(null);
var drawLayer = select_default2(null);
var _notesVisible = false;
function markerPath(selection2, klass) {
selection2.attr("class", klass).attr("transform", "translate(-8, -22)").attr("d", "m17.5,0l-15,0c-1.37,0 -2.5,1.12 -2.5,2.5l0,11.25c0,1.37 1.12,2.5 2.5,2.5l3.75,0l0,3.28c0,0.38 0.43,0.6 0.75,0.37l4.87,-3.65l5.62,0c1.37,0 2.5,-1.12 2.5,-2.5l0,-11.25c0,-1.37 -1.12,-2.5 -2.5,-2.5z");
}
function getService() {
if (services.osm && !_osmService) {
_osmService = services.osm;
_osmService.on("loadedNotes", throttledRedraw);
} else if (!services.osm && _osmService) {
_osmService = null;
}
return _osmService;
}
function editOn() {
if (!_notesVisible) {
_notesVisible = true;
drawLayer.style("display", "block");
}
}
function editOff() {
if (_notesVisible) {
_notesVisible = false;
drawLayer.style("display", "none");
drawLayer.selectAll(".note").remove();
touchLayer.selectAll(".note").remove();
}
}
function layerOn() {
editOn();
drawLayer.style("opacity", 0).transition().duration(250).style("opacity", 1).on("end interrupt", function() {
dispatch10.call("change");
});
}
function layerOff() {
throttledRedraw.cancel();
drawLayer.interrupt();
touchLayer.selectAll(".note").remove();
drawLayer.transition().duration(250).style("opacity", 0).on("end interrupt", function() {
editOff();
dispatch10.call("change");
});
}
function updateMarkers() {
if (!_notesVisible || !_notesEnabled)
return;
var service = getService();
var selectedID = context.selectedNoteID();
var data = service ? service.notes(projection2) : [];
var getTransform = svgPointTransform(projection2);
var notes = drawLayer.selectAll(".note").data(data, function(d) {
return d.status + d.id;
});
notes.exit().remove();
var notesEnter = notes.enter().append("g").attr("class", function(d) {
return "note note-" + d.id + " " + d.status;
}).classed("new", function(d) {
return d.id < 0;
});
notesEnter.append("ellipse").attr("cx", 0.5).attr("cy", 1).attr("rx", 6.5).attr("ry", 3).attr("class", "stroke");
notesEnter.append("path").call(markerPath, "shadow");
notesEnter.append("use").attr("class", "note-fill").attr("width", "20px").attr("height", "20px").attr("x", "-8px").attr("y", "-22px").attr("xlink:href", "#iD-icon-note");
notesEnter.selectAll(".icon-annotation").data(function(d) {
return [d];
}).enter().append("use").attr("class", "icon-annotation").attr("width", "10px").attr("height", "10px").attr("x", "-3px").attr("y", "-19px").attr("xlink:href", function(d) {
if (d.id < 0)
return "#iD-icon-plus";
if (d.status === "open")
return "#iD-icon-close";
return "#iD-icon-apply";
});
notes.merge(notesEnter).sort(sortY).classed("selected", function(d) {
var mode = context.mode();
var isMoving = mode && mode.id === "drag-note";
return !isMoving && d.id === selectedID;
}).attr("transform", getTransform);
if (touchLayer.empty())
return;
var fillClass = context.getDebug("target") ? "pink " : "nocolor ";
var targets = touchLayer.selectAll(".note").data(data, function(d) {
return d.id;
});
targets.exit().remove();
targets.enter().append("rect").attr("width", "20px").attr("height", "20px").attr("x", "-8px").attr("y", "-22px").merge(targets).sort(sortY).attr("class", function(d) {
var newClass = d.id < 0 ? "new" : "";
return "note target note-" + d.id + " " + fillClass + newClass;
}).attr("transform", getTransform);
function sortY(a, b) {
if (a.id === selectedID)
return 1;
if (b.id === selectedID)
return -1;
return b.loc[1] - a.loc[1];
}
}
function drawNotes(selection2) {
var service = getService();
var surface = context.surface();
if (surface && !surface.empty()) {
touchLayer = surface.selectAll(".data-layer.touch .layer-touch.markers");
}
drawLayer = selection2.selectAll(".layer-notes").data(service ? [0] : []);
drawLayer.exit().remove();
drawLayer = drawLayer.enter().append("g").attr("class", "layer-notes").style("display", _notesEnabled ? "block" : "none").merge(drawLayer);
if (_notesEnabled) {
if (service && ~~context.map().zoom() >= minZoom3) {
editOn();
service.loadNotes(projection2);
updateMarkers();
} else {
editOff();
}
}
}
drawNotes.enabled = function(val) {
if (!arguments.length)
return _notesEnabled;
_notesEnabled = val;
if (_notesEnabled) {
layerOn();
} else {
layerOff();
if (context.selectedNoteID()) {
context.enter(modeBrowse(context));
}
}
dispatch10.call("change");
return this;
};
return drawNotes;
}
// modules/svg/touch.js
function svgTouch() {
function drawTouch(selection2) {
selection2.selectAll(".layer-touch").data(["areas", "lines", "points", "turns", "markers"]).enter().append("g").attr("class", function(d) {
return "layer-touch " + d;
});
}
return drawTouch;
}
// modules/util/dimensions.js
function refresh(selection2, node) {
var cr = node.getBoundingClientRect();
var prop = [cr.width, cr.height];
selection2.property("__dimensions__", prop);
return prop;
}
function utilGetDimensions(selection2, force) {
if (!selection2 || selection2.empty()) {
return [0, 0];
}
var node = selection2.node(), cached = selection2.property("__dimensions__");
return !cached || force ? refresh(selection2, node) : cached;
}
function utilSetDimensions(selection2, dimensions) {
if (!selection2 || selection2.empty()) {
return selection2;
}
var node = selection2.node();
if (dimensions === null) {
refresh(selection2, node);
return selection2;
}
return selection2.property("__dimensions__", [dimensions[0], dimensions[1]]).attr("width", dimensions[0]).attr("height", dimensions[1]);
}
// modules/svg/layers.js
function svgLayers(projection2, context) {
var dispatch10 = dispatch_default("change");
var svg2 = select_default2(null);
var _layers = [
{ id: "osm", layer: svgOsm(projection2, context, dispatch10) },
{ id: "notes", layer: svgNotes(projection2, context, dispatch10) },
{ id: "data", layer: svgData(projection2, context, dispatch10) },
{ id: "keepRight", layer: svgKeepRight(projection2, context, dispatch10) },
{ id: "improveOSM", layer: svgImproveOSM(projection2, context, dispatch10) },
{ id: "osmose", layer: svgOsmose(projection2, context, dispatch10) },
{ id: "streetside", layer: svgStreetside(projection2, context, dispatch10) },
{ id: "mapillary", layer: svgMapillaryImages(projection2, context, dispatch10) },
{ id: "mapillary-position", layer: svgMapillaryPosition(projection2, context, dispatch10) },
{ id: "mapillary-map-features", layer: svgMapillaryMapFeatures(projection2, context, dispatch10) },
{ id: "mapillary-signs", layer: svgMapillarySigns(projection2, context, dispatch10) },
{ id: "kartaview", layer: svgKartaviewImages(projection2, context, dispatch10) },
{ id: "debug", layer: svgDebug(projection2, context, dispatch10) },
{ id: "geolocate", layer: svgGeolocate(projection2, context, dispatch10) },
{ id: "touch", layer: svgTouch(projection2, context, dispatch10) }
];
function drawLayers(selection2) {
svg2 = selection2.selectAll(".surface").data([0]);
svg2 = svg2.enter().append("svg").attr("class", "surface").merge(svg2);
var defs = svg2.selectAll(".surface-defs").data([0]);
defs.enter().append("defs").attr("class", "surface-defs");
var groups = svg2.selectAll(".data-layer").data(_layers);
groups.exit().remove();
groups.enter().append("g").attr("class", function(d) {
return "data-layer " + d.id;
}).merge(groups).each(function(d) {
select_default2(this).call(d.layer);
});
}
drawLayers.all = function() {
return _layers;
};
drawLayers.layer = function(id2) {
var obj = _layers.find(function(o) {
return o.id === id2;
});
return obj && obj.layer;
};
drawLayers.only = function(what) {
var arr = [].concat(what);
var all = _layers.map(function(layer) {
return layer.id;
});
return drawLayers.remove(utilArrayDifference(all, arr));
};
drawLayers.remove = function(what) {
var arr = [].concat(what);
arr.forEach(function(id2) {
_layers = _layers.filter(function(o) {
return o.id !== id2;
});
});
dispatch10.call("change");
return this;
};
drawLayers.add = function(what) {
var arr = [].concat(what);
arr.forEach(function(obj) {
if ("id" in obj && "layer" in obj) {
_layers.push(obj);
}
});
dispatch10.call("change");
return this;
};
drawLayers.dimensions = function(val) {
if (!arguments.length)
return utilGetDimensions(svg2);
utilSetDimensions(svg2, val);
return this;
};
return utilRebind(drawLayers, dispatch10, "on");
}
// modules/svg/lines.js
var import_fast_deep_equal6 = __toESM(require_fast_deep_equal());
function svgLines(projection2, context) {
var detected = utilDetect();
var highway_stack = {
motorway: 0,
motorway_link: 1,
trunk: 2,
trunk_link: 3,
primary: 4,
primary_link: 5,
secondary: 6,
tertiary: 7,
unclassified: 8,
residential: 9,
service: 10,
footway: 11
};
function drawTargets(selection2, graph, entities, filter2) {
var targetClass = context.getDebug("target") ? "pink " : "nocolor ";
var nopeClass = context.getDebug("target") ? "red " : "nocolor ";
var getPath = svgPath(projection2).geojson;
var activeID = context.activeID();
var base = context.history().base();
var data = { targets: [], nopes: [] };
entities.forEach(function(way) {
var features2 = svgSegmentWay(way, graph, activeID);
data.targets.push.apply(data.targets, features2.passive);
data.nopes.push.apply(data.nopes, features2.active);
});
var targetData = data.targets.filter(getPath);
var targets = selection2.selectAll(".line.target-allowed").filter(function(d) {
return filter2(d.properties.entity);
}).data(targetData, function key(d) {
return d.id;
});
targets.exit().remove();
var segmentWasEdited = function(d) {
var wayID = d.properties.entity.id;
if (!base.entities[wayID] || !(0, import_fast_deep_equal6.default)(graph.entities[wayID].nodes, base.entities[wayID].nodes)) {
return false;
}
return d.properties.nodes.some(function(n2) {
return !base.entities[n2.id] || !(0, import_fast_deep_equal6.default)(graph.entities[n2.id].loc, base.entities[n2.id].loc);
});
};
targets.enter().append("path").merge(targets).attr("d", getPath).attr("class", function(d) {
return "way line target target-allowed " + targetClass + d.id;
}).classed("segment-edited", segmentWasEdited);
var nopeData = data.nopes.filter(getPath);
var nopes = selection2.selectAll(".line.target-nope").filter(function(d) {
return filter2(d.properties.entity);
}).data(nopeData, function key(d) {
return d.id;
});
nopes.exit().remove();
nopes.enter().append("path").merge(nopes).attr("d", getPath).attr("class", function(d) {
return "way line target target-nope " + nopeClass + d.id;
}).classed("segment-edited", segmentWasEdited);
}
function drawLines(selection2, graph, entities, filter2) {
var base = context.history().base();
function waystack(a, b) {
var selected = context.selectedIDs();
var scoreA = selected.indexOf(a.id) !== -1 ? 20 : 0;
var scoreB = selected.indexOf(b.id) !== -1 ? 20 : 0;
if (a.tags.highway) {
scoreA -= highway_stack[a.tags.highway];
}
if (b.tags.highway) {
scoreB -= highway_stack[b.tags.highway];
}
return scoreA - scoreB;
}
function drawLineGroup(selection3, klass, isSelected) {
var mode = context.mode();
var isDrawing = mode && /^draw/.test(mode.id);
var selectedClass = !isDrawing && isSelected ? "selected " : "";
var lines = selection3.selectAll("path").filter(filter2).data(getPathData(isSelected), osmEntity.key);
lines.exit().remove();
lines.enter().append("path").attr("class", function(d) {
var prefix = "way line";
if (!d.hasInterestingTags()) {
var parentRelations = graph.parentRelations(d);
var parentMultipolygons = parentRelations.filter(function(relation) {
return relation.isMultipolygon();
});
if (parentMultipolygons.length > 0 && parentRelations.length === parentMultipolygons.length) {
prefix = "relation area";
}
}
var oldMPClass = oldMultiPolygonOuters[d.id] ? "old-multipolygon " : "";
return prefix + " " + klass + " " + selectedClass + oldMPClass + d.id;
}).classed("added", function(d) {
return !base.entities[d.id];
}).classed("geometry-edited", function(d) {
return graph.entities[d.id] && base.entities[d.id] && !(0, import_fast_deep_equal6.default)(graph.entities[d.id].nodes, base.entities[d.id].nodes);
}).classed("retagged", function(d) {
return graph.entities[d.id] && base.entities[d.id] && !(0, import_fast_deep_equal6.default)(graph.entities[d.id].tags, base.entities[d.id].tags);
}).call(svgTagClasses()).merge(lines).sort(waystack).attr("d", getPath).call(svgTagClasses().tags(svgRelationMemberTags(graph)));
return selection3;
}
function getPathData(isSelected) {
return function() {
var layer = this.parentNode.__data__;
var data = pathdata[layer] || [];
return data.filter(function(d) {
if (isSelected) {
return context.selectedIDs().indexOf(d.id) !== -1;
} else {
return context.selectedIDs().indexOf(d.id) === -1;
}
});
};
}
function addMarkers(layergroup, pathclass, groupclass, groupdata, marker) {
var markergroup = layergroup.selectAll("g." + groupclass).data([pathclass]);
markergroup = markergroup.enter().append("g").attr("class", groupclass).merge(markergroup);
var markers = markergroup.selectAll("path").filter(filter2).data(function data() {
return groupdata[this.parentNode.__data__] || [];
}, function key(d) {
return [d.id, d.index];
});
markers.exit().remove();
markers = markers.enter().append("path").attr("class", pathclass).merge(markers).attr("marker-mid", marker).attr("d", function(d) {
return d.d;
});
if (detected.ie) {
markers.each(function() {
this.parentNode.insertBefore(this, this);
});
}
}
var getPath = svgPath(projection2, graph);
var ways = [];
var onewaydata = {};
var sideddata = {};
var oldMultiPolygonOuters = {};
for (var i2 = 0; i2 < entities.length; i2++) {
var entity = entities[i2];
var outer = osmOldMultipolygonOuterMember(entity, graph);
if (outer) {
ways.push(entity.mergeTags(outer.tags));
oldMultiPolygonOuters[outer.id] = true;
} else if (entity.geometry(graph) === "line") {
ways.push(entity);
}
}
ways = ways.filter(getPath);
var pathdata = utilArrayGroupBy(ways, function(way) {
return way.layer();
});
Object.keys(pathdata).forEach(function(k) {
var v = pathdata[k];
var onewayArr = v.filter(function(d) {
return d.isOneWay();
});
var onewaySegments = svgMarkerSegments(projection2, graph, 35, function shouldReverse(entity2) {
return entity2.tags.oneway === "-1";
}, function bothDirections(entity2) {
return entity2.tags.oneway === "reversible" || entity2.tags.oneway === "alternating";
});
onewaydata[k] = utilArrayFlatten(onewayArr.map(onewaySegments));
var sidedArr = v.filter(function(d) {
return d.isSided();
});
var sidedSegments = svgMarkerSegments(projection2, graph, 30, function shouldReverse() {
return false;
}, function bothDirections() {
return false;
});
sideddata[k] = utilArrayFlatten(sidedArr.map(sidedSegments));
});
var covered = selection2.selectAll(".layer-osm.covered");
var uncovered = selection2.selectAll(".layer-osm.lines");
var touchLayer = selection2.selectAll(".layer-touch.lines");
[covered, uncovered].forEach(function(selection3) {
var range3 = selection3 === covered ? range(-10, 0) : range(0, 11);
var layergroup = selection3.selectAll("g.layergroup").data(range3);
layergroup = layergroup.enter().append("g").attr("class", function(d) {
return "layergroup layer" + String(d);
}).merge(layergroup);
layergroup.selectAll("g.linegroup").data(["shadow", "casing", "stroke", "shadow-highlighted", "casing-highlighted", "stroke-highlighted"]).enter().append("g").attr("class", function(d) {
return "linegroup line-" + d;
});
layergroup.selectAll("g.line-shadow").call(drawLineGroup, "shadow", false);
layergroup.selectAll("g.line-casing").call(drawLineGroup, "casing", false);
layergroup.selectAll("g.line-stroke").call(drawLineGroup, "stroke", false);
layergroup.selectAll("g.line-shadow-highlighted").call(drawLineGroup, "shadow", true);
layergroup.selectAll("g.line-casing-highlighted").call(drawLineGroup, "casing", true);
layergroup.selectAll("g.line-stroke-highlighted").call(drawLineGroup, "stroke", true);
addMarkers(layergroup, "oneway", "onewaygroup", onewaydata, "url(#ideditor-oneway-marker)");
addMarkers(layergroup, "sided", "sidedgroup", sideddata, function marker(d) {
var category = graph.entity(d.id).sidednessIdentifier();
return "url(#ideditor-sided-marker-" + category + ")";
});
});
touchLayer.call(drawTargets, graph, ways, filter2);
}
return drawLines;
}
// modules/svg/midpoints.js
function svgMidpoints(projection2, context) {
var targetRadius = 8;
function drawTargets(selection2, graph, entities, filter2) {
var fillClass = context.getDebug("target") ? "pink " : "nocolor ";
var getTransform = svgPointTransform(projection2).geojson;
var data = entities.map(function(midpoint) {
return {
type: "Feature",
id: midpoint.id,
properties: {
target: true,
entity: midpoint
},
geometry: {
type: "Point",
coordinates: midpoint.loc
}
};
});
var targets = selection2.selectAll(".midpoint.target").filter(function(d) {
return filter2(d.properties.entity);
}).data(data, function key(d) {
return d.id;
});
targets.exit().remove();
targets.enter().append("circle").attr("r", targetRadius).merge(targets).attr("class", function(d) {
return "node midpoint target " + fillClass + d.id;
}).attr("transform", getTransform);
}
function drawMidpoints(selection2, graph, entities, filter2, extent) {
var drawLayer = selection2.selectAll(".layer-osm.points .points-group.midpoints");
var touchLayer = selection2.selectAll(".layer-touch.points");
var mode = context.mode();
if (mode && mode.id !== "select" || !context.map().withinEditableZoom()) {
drawLayer.selectAll(".midpoint").remove();
touchLayer.selectAll(".midpoint.target").remove();
return;
}
var poly = extent.polygon();
var midpoints = {};
for (var i2 = 0; i2 < entities.length; i2++) {
var entity = entities[i2];
if (entity.type !== "way")
continue;
if (!filter2(entity))
continue;
if (context.selectedIDs().indexOf(entity.id) < 0)
continue;
var nodes = graph.childNodes(entity);
for (var j2 = 0; j2 < nodes.length - 1; j2++) {
var a = nodes[j2];
var b = nodes[j2 + 1];
var id2 = [a.id, b.id].sort().join("-");
if (midpoints[id2]) {
midpoints[id2].parents.push(entity);
} else if (geoVecLength(projection2(a.loc), projection2(b.loc)) > 40) {
var point = geoVecInterp(a.loc, b.loc, 0.5);
var loc = null;
if (extent.intersects(point)) {
loc = point;
} else {
for (var k = 0; k < 4; k++) {
point = geoLineIntersection([a.loc, b.loc], [poly[k], poly[k + 1]]);
if (point && geoVecLength(projection2(a.loc), projection2(point)) > 20 && geoVecLength(projection2(b.loc), projection2(point)) > 20) {
loc = point;
break;
}
}
}
if (loc) {
midpoints[id2] = {
type: "midpoint",
id: id2,
loc,
edge: [a.id, b.id],
parents: [entity]
};
}
}
}
}
function midpointFilter(d) {
if (midpoints[d.id])
return true;
for (var i3 = 0; i3 < d.parents.length; i3++) {
if (filter2(d.parents[i3])) {
return true;
}
}
return false;
}
var groups = drawLayer.selectAll(".midpoint").filter(midpointFilter).data(Object.values(midpoints), function(d) {
return d.id;
});
groups.exit().remove();
var enter = groups.enter().insert("g", ":first-child").attr("class", "midpoint");
enter.append("polygon").attr("points", "-6,8 10,0 -6,-8").attr("class", "shadow");
enter.append("polygon").attr("points", "-3,4 5,0 -3,-4").attr("class", "fill");
groups = groups.merge(enter).attr("transform", function(d) {
var translate = svgPointTransform(projection2);
var a2 = graph.entity(d.edge[0]);
var b2 = graph.entity(d.edge[1]);
var angle2 = geoAngle(a2, b2, projection2) * (180 / Math.PI);
return translate(d) + " rotate(" + angle2 + ")";
}).call(svgTagClasses().tags(function(d) {
return d.parents[0].tags;
}));
groups.select("polygon.shadow");
groups.select("polygon.fill");
touchLayer.call(drawTargets, graph, Object.values(midpoints), midpointFilter);
}
return drawMidpoints;
}
// modules/svg/points.js
var import_fast_deep_equal7 = __toESM(require_fast_deep_equal());
function svgPoints(projection2, context) {
function markerPath(selection2, klass) {
selection2.attr("class", klass).attr("transform", "translate(-8, -23)").attr("d", "M 17,8 C 17,13 11,21 8.5,23.5 C 6,21 0,13 0,8 C 0,4 4,-0.5 8.5,-0.5 C 13,-0.5 17,4 17,8 z");
}
function sortY(a, b) {
return b.loc[1] - a.loc[1];
}
function fastEntityKey(d) {
var mode = context.mode();
var isMoving = mode && /^(add|draw|drag|move|rotate)/.test(mode.id);
return isMoving ? d.id : osmEntity.key(d);
}
function drawTargets(selection2, graph, entities, filter2) {
var fillClass = context.getDebug("target") ? "pink " : "nocolor ";
var getTransform = svgPointTransform(projection2).geojson;
var activeID = context.activeID();
var data = [];
entities.forEach(function(node) {
if (activeID === node.id)
return;
data.push({
type: "Feature",
id: node.id,
properties: {
target: true,
entity: node
},
geometry: node.asGeoJSON()
});
});
var targets = selection2.selectAll(".point.target").filter(function(d) {
return filter2(d.properties.entity);
}).data(data, function key(d) {
return d.id;
});
targets.exit().remove();
targets.enter().append("rect").attr("x", -10).attr("y", -26).attr("width", 20).attr("height", 30).merge(targets).attr("class", function(d) {
return "node point target " + fillClass + d.id;
}).attr("transform", getTransform);
}
function drawPoints(selection2, graph, entities, filter2) {
var wireframe = context.surface().classed("fill-wireframe");
var zoom = geoScaleToZoom(projection2.scale());
var base = context.history().base();
function renderAsPoint(entity) {
return entity.geometry(graph) === "point" && !(zoom >= 18 && entity.directions(graph, projection2).length);
}
var points = wireframe ? [] : entities.filter(renderAsPoint);
points.sort(sortY);
var drawLayer = selection2.selectAll(".layer-osm.points .points-group.points");
var touchLayer = selection2.selectAll(".layer-touch.points");
var groups = drawLayer.selectAll("g.point").filter(filter2).data(points, fastEntityKey);
groups.exit().remove();
var enter = groups.enter().append("g").attr("class", function(d) {
return "node point " + d.id;
}).order();
enter.append("path").call(markerPath, "shadow");
enter.append("ellipse").attr("cx", 0.5).attr("cy", 1).attr("rx", 6.5).attr("ry", 3).attr("class", "stroke");
enter.append("path").call(markerPath, "stroke");
enter.append("use").attr("transform", "translate(-5.5, -20)").attr("class", "icon").attr("width", "12px").attr("height", "12px");
groups = groups.merge(enter).attr("transform", svgPointTransform(projection2)).classed("added", function(d) {
return !base.entities[d.id];
}).classed("moved", function(d) {
return base.entities[d.id] && !(0, import_fast_deep_equal7.default)(graph.entities[d.id].loc, base.entities[d.id].loc);
}).classed("retagged", function(d) {
return base.entities[d.id] && !(0, import_fast_deep_equal7.default)(graph.entities[d.id].tags, base.entities[d.id].tags);
}).call(svgTagClasses());
groups.select(".shadow");
groups.select(".stroke");
groups.select(".icon").attr("xlink:href", function(entity) {
var preset = _mainPresetIndex.match(entity, graph);
var picon = preset && preset.icon;
return picon ? "#" + picon : "";
});
touchLayer.call(drawTargets, graph, points, filter2);
}
return drawPoints;
}
// modules/svg/turns.js
function svgTurns(projection2, context) {
function icon2(turn) {
var u = turn.u ? "-u" : "";
if (turn.no)
return "#iD-turn-no" + u;
if (turn.only)
return "#iD-turn-only" + u;
return "#iD-turn-yes" + u;
}
function drawTurns(selection2, graph, turns) {
function turnTransform(d) {
var pxRadius = 50;
var toWay = graph.entity(d.to.way);
var toPoints = graph.childNodes(toWay).map(function(n2) {
return n2.loc;
}).map(projection2);
var toLength = geoPathLength(toPoints);
var mid = toLength / 2;
var toNode = graph.entity(d.to.node);
var toVertex = graph.entity(d.to.vertex);
var a = geoAngle(toVertex, toNode, projection2);
var o = projection2(toVertex.loc);
var r = d.u ? 0 : !toWay.__via ? pxRadius : Math.min(mid, pxRadius);
return "translate(" + (r * Math.cos(a) + o[0]) + "," + (r * Math.sin(a) + o[1]) + ") rotate(" + a * 180 / Math.PI + ")";
}
var drawLayer = selection2.selectAll(".layer-osm.points .points-group.turns");
var touchLayer = selection2.selectAll(".layer-touch.turns");
var groups = drawLayer.selectAll("g.turn").data(turns, function(d) {
return d.key;
});
groups.exit().remove();
var groupsEnter = groups.enter().append("g").attr("class", function(d) {
return "turn " + d.key;
});
var turnsEnter = groupsEnter.filter(function(d) {
return !d.u;
});
turnsEnter.append("rect").attr("transform", "translate(-22, -12)").attr("width", "44").attr("height", "24");
turnsEnter.append("use").attr("transform", "translate(-22, -12)").attr("width", "44").attr("height", "24");
var uEnter = groupsEnter.filter(function(d) {
return d.u;
});
uEnter.append("circle").attr("r", "16");
uEnter.append("use").attr("transform", "translate(-16, -16)").attr("width", "32").attr("height", "32");
groups = groups.merge(groupsEnter).attr("opacity", function(d) {
return d.direct === false ? "0.7" : null;
}).attr("transform", turnTransform);
groups.select("use").attr("xlink:href", icon2);
groups.select("rect");
groups.select("circle");
var fillClass = context.getDebug("target") ? "pink " : "nocolor ";
groups = touchLayer.selectAll("g.turn").data(turns, function(d) {
return d.key;
});
groups.exit().remove();
groupsEnter = groups.enter().append("g").attr("class", function(d) {
return "turn " + d.key;
});
turnsEnter = groupsEnter.filter(function(d) {
return !d.u;
});
turnsEnter.append("rect").attr("class", "target " + fillClass).attr("transform", "translate(-22, -12)").attr("width", "44").attr("height", "24");
uEnter = groupsEnter.filter(function(d) {
return d.u;
});
uEnter.append("circle").attr("class", "target " + fillClass).attr("r", "16");
groups = groups.merge(groupsEnter).attr("transform", turnTransform);
groups.select("rect");
groups.select("circle");
return this;
}
return drawTurns;
}
// modules/svg/vertices.js
var import_fast_deep_equal8 = __toESM(require_fast_deep_equal());
function svgVertices(projection2, context) {
var radiuses = {
shadow: [6, 7.5, 7.5, 12],
stroke: [2.5, 3.5, 3.5, 8],
fill: [1, 1.5, 1.5, 1.5]
};
var _currHoverTarget;
var _currPersistent = {};
var _currHover = {};
var _prevHover = {};
var _currSelected = {};
var _prevSelected = {};
var _radii = {};
function sortY(a, b) {
return b.loc[1] - a.loc[1];
}
function fastEntityKey(d) {
var mode = context.mode();
var isMoving = mode && /^(add|draw|drag|move|rotate)/.test(mode.id);
return isMoving ? d.id : osmEntity.key(d);
}
function draw(selection2, graph, vertices, sets2, filter2) {
sets2 = sets2 || { selected: {}, important: {}, hovered: {} };
var icons = {};
var directions = {};
var wireframe = context.surface().classed("fill-wireframe");
var zoom = geoScaleToZoom(projection2.scale());
var z = zoom < 17 ? 0 : zoom < 18 ? 1 : 2;
var activeID = context.activeID();
var base = context.history().base();
function getIcon(d) {
var entity = graph.entity(d.id);
if (entity.id in icons)
return icons[entity.id];
icons[entity.id] = entity.hasInterestingTags() && _mainPresetIndex.match(entity, graph).icon;
return icons[entity.id];
}
function getDirections(entity) {
if (entity.id in directions)
return directions[entity.id];
var angles = entity.directions(graph, projection2);
directions[entity.id] = angles.length ? angles : false;
return angles;
}
function updateAttributes(selection3) {
["shadow", "stroke", "fill"].forEach(function(klass) {
var rads = radiuses[klass];
selection3.selectAll("." + klass).each(function(entity) {
var i2 = z && getIcon(entity);
var r = rads[i2 ? 3 : z];
if (entity.id !== activeID && entity.isEndpoint(graph) && !entity.isConnected(graph)) {
r += 1.5;
}
if (klass === "shadow") {
_radii[entity.id] = r;
}
select_default2(this).attr("r", r).attr("visibility", i2 && klass === "fill" ? "hidden" : null);
});
});
}
vertices.sort(sortY);
var groups = selection2.selectAll("g.vertex").filter(filter2).data(vertices, fastEntityKey);
groups.exit().remove();
var enter = groups.enter().append("g").attr("class", function(d) {
return "node vertex " + d.id;
}).order();
enter.append("circle").attr("class", "shadow");
enter.append("circle").attr("class", "stroke");
enter.filter(function(d) {
return d.hasInterestingTags();
}).append("circle").attr("class", "fill");
groups = groups.merge(enter).attr("transform", svgPointTransform(projection2)).classed("sibling", function(d) {
return d.id in sets2.selected;
}).classed("shared", function(d) {
return graph.isShared(d);
}).classed("endpoint", function(d) {
return d.isEndpoint(graph);
}).classed("added", function(d) {
return !base.entities[d.id];
}).classed("moved", function(d) {
return base.entities[d.id] && !(0, import_fast_deep_equal8.default)(graph.entities[d.id].loc, base.entities[d.id].loc);
}).classed("retagged", function(d) {
return base.entities[d.id] && !(0, import_fast_deep_equal8.default)(graph.entities[d.id].tags, base.entities[d.id].tags);
}).call(updateAttributes);
var iconUse = groups.selectAll(".icon").data(function data(d) {
return zoom >= 17 && getIcon(d) ? [d] : [];
}, fastEntityKey);
iconUse.exit().remove();
iconUse.enter().append("use").attr("class", "icon").attr("width", "12px").attr("height", "12px").attr("transform", "translate(-6, -6)").attr("xlink:href", function(d) {
var picon = getIcon(d);
return picon ? "#" + picon : "";
});
var dgroups = groups.selectAll(".viewfieldgroup").data(function data(d) {
return zoom >= 18 && getDirections(d) ? [d] : [];
}, fastEntityKey);
dgroups.exit().remove();
dgroups = dgroups.enter().insert("g", ".shadow").attr("class", "viewfieldgroup").merge(dgroups);
var viewfields = dgroups.selectAll(".viewfield").data(getDirections, function key(d) {
return osmEntity.key(d);
});
viewfields.exit().remove();
viewfields.enter().append("path").attr("class", "viewfield").attr("d", "M0,0H0").merge(viewfields).attr("marker-start", "url(#ideditor-viewfield-marker" + (wireframe ? "-wireframe" : "") + ")").attr("transform", function(d) {
return "rotate(" + d + ")";
});
}
function drawTargets(selection2, graph, entities, filter2) {
var targetClass = context.getDebug("target") ? "pink " : "nocolor ";
var nopeClass = context.getDebug("target") ? "red " : "nocolor ";
var getTransform = svgPointTransform(projection2).geojson;
var activeID = context.activeID();
var data = { targets: [], nopes: [] };
entities.forEach(function(node) {
if (activeID === node.id)
return;
var vertexType = svgPassiveVertex(node, graph, activeID);
if (vertexType !== 0) {
data.targets.push({
type: "Feature",
id: node.id,
properties: {
target: true,
entity: node
},
geometry: node.asGeoJSON()
});
} else {
data.nopes.push({
type: "Feature",
id: node.id + "-nope",
properties: {
nope: true,
target: true,
entity: node
},
geometry: node.asGeoJSON()
});
}
});
var targets = selection2.selectAll(".vertex.target-allowed").filter(function(d) {
return filter2(d.properties.entity);
}).data(data.targets, function key(d) {
return d.id;
});
targets.exit().remove();
targets.enter().append("circle").attr("r", function(d) {
return _radii[d.id] || radiuses.shadow[3];
}).merge(targets).attr("class", function(d) {
return "node vertex target target-allowed " + targetClass + d.id;
}).attr("transform", getTransform);
var nopes = selection2.selectAll(".vertex.target-nope").filter(function(d) {
return filter2(d.properties.entity);
}).data(data.nopes, function key(d) {
return d.id;
});
nopes.exit().remove();
nopes.enter().append("circle").attr("r", function(d) {
return _radii[d.properties.entity.id] || radiuses.shadow[3];
}).merge(nopes).attr("class", function(d) {
return "node vertex target target-nope " + nopeClass + d.id;
}).attr("transform", getTransform);
}
function renderAsVertex(entity, graph, wireframe, zoom) {
var geometry = entity.geometry(graph);
return geometry === "vertex" || geometry === "point" && (wireframe || zoom >= 18 && entity.directions(graph, projection2).length);
}
function isEditedNode(node, base, head) {
var baseNode = base.entities[node.id];
var headNode = head.entities[node.id];
return !headNode || !baseNode || !(0, import_fast_deep_equal8.default)(headNode.tags, baseNode.tags) || !(0, import_fast_deep_equal8.default)(headNode.loc, baseNode.loc);
}
function getSiblingAndChildVertices(ids, graph, wireframe, zoom) {
var results = {};
var seenIds = {};
function addChildVertices(entity) {
if (seenIds[entity.id])
return;
seenIds[entity.id] = true;
var geometry = entity.geometry(graph);
if (!context.features().isHiddenFeature(entity, graph, geometry)) {
var i2;
if (entity.type === "way") {
for (i2 = 0; i2 < entity.nodes.length; i2++) {
var child = graph.hasEntity(entity.nodes[i2]);
if (child) {
addChildVertices(child);
}
}
} else if (entity.type === "relation") {
for (i2 = 0; i2 < entity.members.length; i2++) {
var member = graph.hasEntity(entity.members[i2].id);
if (member) {
addChildVertices(member);
}
}
} else if (renderAsVertex(entity, graph, wireframe, zoom)) {
results[entity.id] = entity;
}
}
}
ids.forEach(function(id2) {
var entity = graph.hasEntity(id2);
if (!entity)
return;
if (entity.type === "node") {
if (renderAsVertex(entity, graph, wireframe, zoom)) {
results[entity.id] = entity;
graph.parentWays(entity).forEach(function(entity2) {
addChildVertices(entity2);
});
}
} else {
addChildVertices(entity);
}
});
return results;
}
function drawVertices(selection2, graph, entities, filter2, extent, fullRedraw) {
var wireframe = context.surface().classed("fill-wireframe");
var visualDiff = context.surface().classed("highlight-edited");
var zoom = geoScaleToZoom(projection2.scale());
var mode = context.mode();
var isMoving = mode && /^(add|draw|drag|move|rotate)/.test(mode.id);
var base = context.history().base();
var drawLayer = selection2.selectAll(".layer-osm.points .points-group.vertices");
var touchLayer = selection2.selectAll(".layer-touch.points");
if (fullRedraw) {
_currPersistent = {};
_radii = {};
}
for (var i2 = 0; i2 < entities.length; i2++) {
var entity = entities[i2];
var geometry = entity.geometry(graph);
var keep = false;
if (geometry === "point" && renderAsVertex(entity, graph, wireframe, zoom)) {
_currPersistent[entity.id] = entity;
keep = true;
} else if (geometry === "vertex" && (entity.hasInterestingTags() || entity.isEndpoint(graph) || entity.isConnected(graph) || visualDiff && isEditedNode(entity, base, graph))) {
_currPersistent[entity.id] = entity;
keep = true;
}
if (!keep && !fullRedraw) {
delete _currPersistent[entity.id];
}
}
var sets2 = {
persistent: _currPersistent,
selected: _currSelected,
hovered: _currHover
};
var all = Object.assign({}, isMoving ? _currHover : {}, _currSelected, _currPersistent);
var filterRendered = function(d) {
return d.id in _currPersistent || d.id in _currSelected || d.id in _currHover || filter2(d);
};
drawLayer.call(draw, graph, currentVisible(all), sets2, filterRendered);
var filterTouch = function(d) {
return isMoving ? true : filterRendered(d);
};
touchLayer.call(drawTargets, graph, currentVisible(all), filterTouch);
function currentVisible(which) {
return Object.keys(which).map(graph.hasEntity, graph).filter(function(entity2) {
return entity2 && entity2.intersects(extent, graph);
});
}
}
drawVertices.drawSelected = function(selection2, graph, extent) {
var wireframe = context.surface().classed("fill-wireframe");
var zoom = geoScaleToZoom(projection2.scale());
_prevSelected = _currSelected || {};
if (context.map().isInWideSelection()) {
_currSelected = {};
context.selectedIDs().forEach(function(id2) {
var entity = graph.hasEntity(id2);
if (!entity)
return;
if (entity.type === "node") {
if (renderAsVertex(entity, graph, wireframe, zoom)) {
_currSelected[entity.id] = entity;
}
}
});
} else {
_currSelected = getSiblingAndChildVertices(context.selectedIDs(), graph, wireframe, zoom);
}
var filter2 = function(d) {
return d.id in _prevSelected;
};
drawVertices(selection2, graph, Object.values(_prevSelected), filter2, extent, false);
};
drawVertices.drawHover = function(selection2, graph, target, extent) {
if (target === _currHoverTarget)
return;
var wireframe = context.surface().classed("fill-wireframe");
var zoom = geoScaleToZoom(projection2.scale());
_prevHover = _currHover || {};
_currHoverTarget = target;
var entity = target && target.properties && target.properties.entity;
if (entity) {
_currHover = getSiblingAndChildVertices([entity.id], graph, wireframe, zoom);
} else {
_currHover = {};
}
var filter2 = function(d) {
return d.id in _prevHover;
};
drawVertices(selection2, graph, Object.values(_prevHover), filter2, extent, false);
};
return drawVertices;
}
// modules/util/bind_once.js
function utilBindOnce(target, type3, listener, capture) {
var typeOnce = type3 + ".once";
function one2() {
target.on(typeOnce, null);
listener.apply(this, arguments);
}
target.on(typeOnce, one2, capture);
return this;
}
// modules/util/zoom_pan.js
function defaultFilter3(d3_event) {
return !d3_event.ctrlKey && !d3_event.button;
}
function defaultExtent2() {
var e = this;
if (e instanceof SVGElement) {
e = e.ownerSVGElement || e;
if (e.hasAttribute("viewBox")) {
e = e.viewBox.baseVal;
return [[e.x, e.y], [e.x + e.width, e.y + e.height]];
}
return [[0, 0], [e.width.baseVal.value, e.height.baseVal.value]];
}
return [[0, 0], [e.clientWidth, e.clientHeight]];
}
function defaultWheelDelta2(d3_event) {
return -d3_event.deltaY * (d3_event.deltaMode === 1 ? 0.05 : d3_event.deltaMode ? 1 : 2e-3);
}
function defaultConstrain2(transform2, extent, translateExtent) {
var dx0 = transform2.invertX(extent[0][0]) - translateExtent[0][0], dx1 = transform2.invertX(extent[1][0]) - translateExtent[1][0], dy0 = transform2.invertY(extent[0][1]) - translateExtent[0][1], dy1 = transform2.invertY(extent[1][1]) - translateExtent[1][1];
return transform2.translate(dx1 > dx0 ? (dx0 + dx1) / 2 : Math.min(0, dx0) || Math.max(0, dx1), dy1 > dy0 ? (dy0 + dy1) / 2 : Math.min(0, dy0) || Math.max(0, dy1));
}
function utilZoomPan() {
var filter2 = defaultFilter3, extent = defaultExtent2, constrain = defaultConstrain2, wheelDelta = defaultWheelDelta2, scaleExtent = [0, Infinity], translateExtent = [[-Infinity, -Infinity], [Infinity, Infinity]], interpolate = zoom_default, dispatch10 = dispatch_default("start", "zoom", "end"), _wheelDelay = 150, _transform = identity2, _activeGesture;
function zoom(selection2) {
selection2.on("pointerdown.zoom", pointerdown).on("wheel.zoom", wheeled).style("touch-action", "none").style("-webkit-tap-highlight-color", "rgba(0,0,0,0)");
select_default2(window).on("pointermove.zoompan", pointermove).on("pointerup.zoompan pointercancel.zoompan", pointerup);
}
zoom.transform = function(collection, transform2, point) {
var selection2 = collection.selection ? collection.selection() : collection;
if (collection !== selection2) {
schedule(collection, transform2, point);
} else {
selection2.interrupt().each(function() {
gesture(this, arguments).start(null).zoom(null, null, typeof transform2 === "function" ? transform2.apply(this, arguments) : transform2).end(null);
});
}
};
zoom.scaleBy = function(selection2, k, p) {
zoom.scaleTo(selection2, function() {
var k0 = _transform.k, k1 = typeof k === "function" ? k.apply(this, arguments) : k;
return k0 * k1;
}, p);
};
zoom.scaleTo = function(selection2, k, p) {
zoom.transform(selection2, function() {
var e = extent.apply(this, arguments), t0 = _transform, p02 = !p ? centroid(e) : typeof p === "function" ? p.apply(this, arguments) : p, p1 = t0.invert(p02), k1 = typeof k === "function" ? k.apply(this, arguments) : k;
return constrain(translate(scale(t0, k1), p02, p1), e, translateExtent);
}, p);
};
zoom.translateBy = function(selection2, x, y) {
zoom.transform(selection2, function() {
return constrain(_transform.translate(typeof x === "function" ? x.apply(this, arguments) : x, typeof y === "function" ? y.apply(this, arguments) : y), extent.apply(this, arguments), translateExtent);
});
};
zoom.translateTo = function(selection2, x, y, p) {
zoom.transform(selection2, function() {
var e = extent.apply(this, arguments), t = _transform, p02 = !p ? centroid(e) : typeof p === "function" ? p.apply(this, arguments) : p;
return constrain(identity2.translate(p02[0], p02[1]).scale(t.k).translate(typeof x === "function" ? -x.apply(this, arguments) : -x, typeof y === "function" ? -y.apply(this, arguments) : -y), e, translateExtent);
}, p);
};
function scale(transform2, k) {
k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], k));
return k === transform2.k ? transform2 : new Transform(k, transform2.x, transform2.y);
}
function translate(transform2, p02, p1) {
var x = p02[0] - p1[0] * transform2.k, y = p02[1] - p1[1] * transform2.k;
return x === transform2.x && y === transform2.y ? transform2 : new Transform(transform2.k, x, y);
}
function centroid(extent2) {
return [(+extent2[0][0] + +extent2[1][0]) / 2, (+extent2[0][1] + +extent2[1][1]) / 2];
}
function schedule(transition2, transform2, point) {
transition2.on("start.zoom", function() {
gesture(this, arguments).start(null);
}).on("interrupt.zoom end.zoom", function() {
gesture(this, arguments).end(null);
}).tween("zoom", function() {
var that = this, args = arguments, g = gesture(that, args), e = extent.apply(that, args), p = !point ? centroid(e) : typeof point === "function" ? point.apply(that, args) : point, w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]), a = _transform, b = typeof transform2 === "function" ? transform2.apply(that, args) : transform2, i2 = interpolate(a.invert(p).concat(w / a.k), b.invert(p).concat(w / b.k));
return function(t) {
if (t === 1) {
t = b;
} else {
var l = i2(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);
};
});
}
function gesture(that, args, clean2) {
return !clean2 && _activeGesture || new Gesture(that, args);
}
function Gesture(that, args) {
this.that = that;
this.args = args;
this.active = 0;
this.extent = extent.apply(that, args);
}
Gesture.prototype = {
start: function(d3_event) {
if (++this.active === 1) {
_activeGesture = this;
dispatch10.call("start", this, d3_event);
}
return this;
},
zoom: function(d3_event, key, transform2) {
if (this.mouse && key !== "mouse")
this.mouse[1] = transform2.invert(this.mouse[0]);
if (this.pointer0 && key !== "touch")
this.pointer0[1] = transform2.invert(this.pointer0[0]);
if (this.pointer1 && key !== "touch")
this.pointer1[1] = transform2.invert(this.pointer1[0]);
_transform = transform2;
dispatch10.call("zoom", this, d3_event, key, transform2);
return this;
},
end: function(d3_event) {
if (--this.active === 0) {
_activeGesture = null;
dispatch10.call("end", this, d3_event);
}
return this;
}
};
function wheeled(d3_event) {
if (!filter2.apply(this, arguments))
return;
var g = gesture(this, arguments), t = _transform, k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], t.k * Math.pow(2, wheelDelta.apply(this, arguments)))), p = utilFastMouse(this)(d3_event);
if (g.wheel) {
if (g.mouse[0][0] !== p[0] || g.mouse[0][1] !== p[1]) {
g.mouse[1] = t.invert(g.mouse[0] = p);
}
clearTimeout(g.wheel);
} else {
g.mouse = [p, t.invert(p)];
interrupt_default(this);
g.start(d3_event);
}
d3_event.preventDefault();
d3_event.stopImmediatePropagation();
g.wheel = setTimeout(wheelidled, _wheelDelay);
g.zoom(d3_event, "mouse", constrain(translate(scale(t, k), g.mouse[0], g.mouse[1]), g.extent, translateExtent));
function wheelidled() {
g.wheel = null;
g.end(d3_event);
}
}
var _downPointerIDs = /* @__PURE__ */ new Set();
var _pointerLocGetter;
function pointerdown(d3_event) {
_downPointerIDs.add(d3_event.pointerId);
if (!filter2.apply(this, arguments))
return;
var g = gesture(this, arguments, _downPointerIDs.size === 1);
var started;
d3_event.stopImmediatePropagation();
_pointerLocGetter = utilFastMouse(this);
var loc = _pointerLocGetter(d3_event);
var p = [loc, _transform.invert(loc), d3_event.pointerId];
if (!g.pointer0) {
g.pointer0 = p;
started = true;
} else if (!g.pointer1 && g.pointer0[2] !== p[2]) {
g.pointer1 = p;
}
if (started) {
interrupt_default(this);
g.start(d3_event);
}
}
function pointermove(d3_event) {
if (!_downPointerIDs.has(d3_event.pointerId))
return;
if (!_activeGesture || !_pointerLocGetter)
return;
var g = gesture(this, arguments);
var isPointer0 = g.pointer0 && g.pointer0[2] === d3_event.pointerId;
var isPointer1 = !isPointer0 && g.pointer1 && g.pointer1[2] === d3_event.pointerId;
if ((isPointer0 || isPointer1) && "buttons" in d3_event && !d3_event.buttons) {
if (g.pointer0)
_downPointerIDs.delete(g.pointer0[2]);
if (g.pointer1)
_downPointerIDs.delete(g.pointer1[2]);
g.end(d3_event);
return;
}
d3_event.preventDefault();
d3_event.stopImmediatePropagation();
var loc = _pointerLocGetter(d3_event);
var t, p, l;
if (isPointer0)
g.pointer0[0] = loc;
else if (isPointer1)
g.pointer1[0] = loc;
t = _transform;
if (g.pointer1) {
var p02 = g.pointer0[0], l0 = g.pointer0[1], p1 = g.pointer1[0], l1 = g.pointer1[1], dp = (dp = p1[0] - p02[0]) * dp + (dp = p1[1] - p02[1]) * dp, dl = (dl = l1[0] - l0[0]) * dl + (dl = l1[1] - l0[1]) * dl;
t = scale(t, Math.sqrt(dp / dl));
p = [(p02[0] + p1[0]) / 2, (p02[1] + p1[1]) / 2];
l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2];
} else if (g.pointer0) {
p = g.pointer0[0];
l = g.pointer0[1];
} else {
return;
}
g.zoom(d3_event, "touch", constrain(translate(t, p, l), g.extent, translateExtent));
}
function pointerup(d3_event) {
if (!_downPointerIDs.has(d3_event.pointerId))
return;
_downPointerIDs.delete(d3_event.pointerId);
if (!_activeGesture)
return;
var g = gesture(this, arguments);
d3_event.stopImmediatePropagation();
if (g.pointer0 && g.pointer0[2] === d3_event.pointerId)
delete g.pointer0;
else if (g.pointer1 && g.pointer1[2] === d3_event.pointerId)
delete g.pointer1;
if (g.pointer1 && !g.pointer0) {
g.pointer0 = g.pointer1;
delete g.pointer1;
}
if (g.pointer0) {
g.pointer0[1] = _transform.invert(g.pointer0[0]);
} else {
g.end(d3_event);
}
}
zoom.wheelDelta = function(_) {
return arguments.length ? (wheelDelta = utilFunctor(+_), zoom) : wheelDelta;
};
zoom.filter = function(_) {
return arguments.length ? (filter2 = utilFunctor(!!_), zoom) : filter2;
};
zoom.extent = function(_) {
return arguments.length ? (extent = utilFunctor([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), zoom) : extent;
};
zoom.scaleExtent = function(_) {
return arguments.length ? (scaleExtent[0] = +_[0], scaleExtent[1] = +_[1], zoom) : [scaleExtent[0], scaleExtent[1]];
};
zoom.translateExtent = function(_) {
return arguments.length ? (translateExtent[0][0] = +_[0][0], translateExtent[1][0] = +_[1][0], translateExtent[0][1] = +_[0][1], translateExtent[1][1] = +_[1][1], zoom) : [[translateExtent[0][0], translateExtent[0][1]], [translateExtent[1][0], translateExtent[1][1]]];
};
zoom.constrain = function(_) {
return arguments.length ? (constrain = _, zoom) : constrain;
};
zoom.interpolate = function(_) {
return arguments.length ? (interpolate = _, zoom) : interpolate;
};
zoom._transform = function(_) {
return arguments.length ? (_transform = _, zoom) : _transform;
};
return utilRebind(zoom, dispatch10, "on");
}
// modules/util/double_up.js
function utilDoubleUp() {
var dispatch10 = dispatch_default("doubleUp");
var _maxTimespan = 500;
var _maxDistance = 20;
var _pointer;
function pointerIsValidFor(loc) {
return new Date().getTime() - _pointer.startTime <= _maxTimespan && geoVecLength(_pointer.startLoc, loc) <= _maxDistance;
}
function pointerdown(d3_event) {
if (d3_event.ctrlKey || d3_event.button === 2)
return;
var loc = [d3_event.clientX, d3_event.clientY];
if (_pointer && !pointerIsValidFor(loc)) {
_pointer = void 0;
}
if (!_pointer) {
_pointer = {
startLoc: loc,
startTime: new Date().getTime(),
upCount: 0,
pointerId: d3_event.pointerId
};
} else {
_pointer.pointerId = d3_event.pointerId;
}
}
function pointerup(d3_event) {
if (d3_event.ctrlKey || d3_event.button === 2)
return;
if (!_pointer || _pointer.pointerId !== d3_event.pointerId)
return;
_pointer.upCount += 1;
if (_pointer.upCount === 2) {
var loc = [d3_event.clientX, d3_event.clientY];
if (pointerIsValidFor(loc)) {
var locInThis = utilFastMouse(this)(d3_event);
dispatch10.call("doubleUp", this, d3_event, locInThis);
}
_pointer = void 0;
}
}
function doubleUp(selection2) {
if ("PointerEvent" in window) {
selection2.on("pointerdown.doubleUp", pointerdown).on("pointerup.doubleUp", pointerup);
} else {
selection2.on("dblclick.doubleUp", function(d3_event) {
dispatch10.call("doubleUp", this, d3_event, utilFastMouse(this)(d3_event));
});
}
}
doubleUp.off = function(selection2) {
selection2.on("pointerdown.doubleUp", null).on("pointerup.doubleUp", null).on("dblclick.doubleUp", null);
};
return utilRebind(doubleUp, dispatch10, "on");
}
// modules/renderer/map.js
var TILESIZE = 256;
var minZoom2 = 2;
var maxZoom = 24;
var kMin = geoZoomToScale(minZoom2, TILESIZE);
var kMax = geoZoomToScale(maxZoom, TILESIZE);
function clamp(num, min3, max3) {
return Math.max(min3, Math.min(num, max3));
}
function rendererMap(context) {
var dispatch10 = dispatch_default("move", "drawn", "crossEditableZoom", "hitMinZoom", "changeHighlighting", "changeAreaFill");
var projection2 = context.projection;
var curtainProjection = context.curtainProjection;
var drawLayers;
var drawPoints;
var drawVertices;
var drawLines;
var drawAreas;
var drawMidpoints;
var drawLabels;
var _selection = select_default2(null);
var supersurface = select_default2(null);
var wrapper = select_default2(null);
var surface = select_default2(null);
var _dimensions = [1, 1];
var _dblClickZoomEnabled = true;
var _redrawEnabled = true;
var _gestureTransformStart;
var _transformStart = projection2.transform();
var _transformLast;
var _isTransformed = false;
var _minzoom = 0;
var _getMouseCoords;
var _lastPointerEvent;
var _lastWithinEditableZoom;
var _pointerDown = false;
var _pointerPrefix = "PointerEvent" in window ? "pointer" : "mouse";
var _zoomerPannerFunction = "PointerEvent" in window ? utilZoomPan : zoom_default2;
var _zoomerPanner = _zoomerPannerFunction().scaleExtent([kMin, kMax]).interpolate(value_default).filter(zoomEventFilter).on("zoom.map", zoomPan).on("start.map", function(d3_event) {
_pointerDown = d3_event && (d3_event.type === "pointerdown" || d3_event.sourceEvent && d3_event.sourceEvent.type === "pointerdown");
}).on("end.map", function() {
_pointerDown = false;
});
var _doubleUpHandler = utilDoubleUp();
var scheduleRedraw = throttle_default(redraw, 750);
function cancelPendingRedraw() {
scheduleRedraw.cancel();
}
function map2(selection2) {
_selection = selection2;
context.on("change.map", immediateRedraw);
var osm = context.connection();
if (osm) {
osm.on("change.map", immediateRedraw);
}
function didUndoOrRedo(targetTransform) {
var mode = context.mode().id;
if (mode !== "browse" && mode !== "select")
return;
if (targetTransform) {
map2.transformEase(targetTransform);
}
}
context.history().on("merge.map", function() {
scheduleRedraw();
}).on("change.map", immediateRedraw).on("undone.map", function(stack, fromStack) {
didUndoOrRedo(fromStack.transform);
}).on("redone.map", function(stack) {
didUndoOrRedo(stack.transform);
});
context.background().on("change.map", immediateRedraw);
context.features().on("redraw.map", immediateRedraw);
drawLayers.on("change.map", function() {
context.background().updateImagery();
immediateRedraw();
});
selection2.on("wheel.map mousewheel.map", function(d3_event) {
d3_event.preventDefault();
}).call(_zoomerPanner).call(_zoomerPanner.transform, projection2.transform()).on("dblclick.zoom", null);
map2.supersurface = supersurface = selection2.append("div").attr("class", "supersurface").call(utilSetTransform, 0, 0);
wrapper = supersurface.append("div").attr("class", "layer layer-data");
map2.surface = surface = wrapper.call(drawLayers).selectAll(".surface");
surface.call(drawLabels.observe).call(_doubleUpHandler).on(_pointerPrefix + "down.zoom", function(d3_event) {
_lastPointerEvent = d3_event;
if (d3_event.button === 2) {
d3_event.stopPropagation();
}
}, true).on(_pointerPrefix + "up.zoom", function(d3_event) {
_lastPointerEvent = d3_event;
if (resetTransform()) {
immediateRedraw();
}
}).on(_pointerPrefix + "move.map", function(d3_event) {
_lastPointerEvent = d3_event;
}).on(_pointerPrefix + "over.vertices", function(d3_event) {
if (map2.editableDataEnabled() && !_isTransformed) {
var hover = d3_event.target.__data__;
surface.call(drawVertices.drawHover, context.graph(), hover, map2.extent());
dispatch10.call("drawn", this, { full: false });
}
}).on(_pointerPrefix + "out.vertices", function(d3_event) {
if (map2.editableDataEnabled() && !_isTransformed) {
var hover = d3_event.relatedTarget && d3_event.relatedTarget.__data__;
surface.call(drawVertices.drawHover, context.graph(), hover, map2.extent());
dispatch10.call("drawn", this, { full: false });
}
});
var detected = utilDetect();
if ("GestureEvent" in window && !detected.isMobileWebKit) {
surface.on("gesturestart.surface", function(d3_event) {
d3_event.preventDefault();
_gestureTransformStart = projection2.transform();
}).on("gesturechange.surface", gestureChange);
}
updateAreaFill();
_doubleUpHandler.on("doubleUp.map", function(d3_event, p02) {
if (!_dblClickZoomEnabled)
return;
if (typeof d3_event.target.__data__ === "object" && !select_default2(d3_event.target).classed("fill"))
return;
var zoomOut2 = d3_event.shiftKey;
var t = projection2.transform();
var p1 = t.invert(p02);
t = t.scale(zoomOut2 ? 0.5 : 2);
t.x = p02[0] - p1[0] * t.k;
t.y = p02[1] - p1[1] * t.k;
map2.transformEase(t);
});
context.on("enter.map", function() {
if (!map2.editableDataEnabled(true))
return;
if (_isTransformed)
return;
var graph = context.graph();
var selectedAndParents = {};
context.selectedIDs().forEach(function(id2) {
var entity = graph.hasEntity(id2);
if (entity) {
selectedAndParents[entity.id] = entity;
if (entity.type === "node") {
graph.parentWays(entity).forEach(function(parent) {
selectedAndParents[parent.id] = parent;
});
}
}
});
var data = Object.values(selectedAndParents);
var filter2 = function(d) {
return d.id in selectedAndParents;
};
data = context.features().filter(data, graph);
surface.call(drawVertices.drawSelected, graph, map2.extent()).call(drawLines, graph, data, filter2).call(drawAreas, graph, data, filter2).call(drawMidpoints, graph, data, filter2, map2.trimmedExtent());
dispatch10.call("drawn", this, { full: false });
scheduleRedraw();
});
map2.dimensions(utilGetDimensions(selection2));
}
function zoomEventFilter(d3_event) {
if (d3_event.type === "mousedown") {
var hasOrphan = false;
var listeners = window.__on;
for (var i2 = 0; i2 < listeners.length; i2++) {
var listener = listeners[i2];
if (listener.name === "zoom" && listener.type === "mouseup") {
hasOrphan = true;
break;
}
}
if (hasOrphan) {
var event = window.CustomEvent;
if (event) {
event = new event("mouseup");
} else {
event = window.document.createEvent("Event");
event.initEvent("mouseup", false, false);
}
event.view = window;
window.dispatchEvent(event);
}
}
return d3_event.button !== 2;
}
function pxCenter() {
return [_dimensions[0] / 2, _dimensions[1] / 2];
}
function drawEditable(difference, extent) {
var mode = context.mode();
var graph = context.graph();
var features2 = context.features();
var all = context.history().intersects(map2.extent());
var fullRedraw = false;
var data;
var set3;
var filter2;
var applyFeatureLayerFilters = true;
if (map2.isInWideSelection()) {
data = [];
utilEntityAndDeepMemberIDs(mode.selectedIDs(), context.graph()).forEach(function(id2) {
var entity = context.hasEntity(id2);
if (entity)
data.push(entity);
});
fullRedraw = true;
filter2 = utilFunctor(true);
applyFeatureLayerFilters = false;
} else if (difference) {
var complete = difference.complete(map2.extent());
data = Object.values(complete).filter(Boolean);
set3 = new Set(Object.keys(complete));
filter2 = function(d) {
return set3.has(d.id);
};
features2.clear(data);
} else {
if (features2.gatherStats(all, graph, _dimensions)) {
extent = void 0;
}
if (extent) {
data = context.history().intersects(map2.extent().intersection(extent));
set3 = new Set(data.map(function(entity) {
return entity.id;
}));
filter2 = function(d) {
return set3.has(d.id);
};
} else {
data = all;
fullRedraw = true;
filter2 = utilFunctor(true);
}
}
if (applyFeatureLayerFilters) {
data = features2.filter(data, graph);
} else {
context.features().resetStats();
}
if (mode && mode.id === "select") {
surface.call(drawVertices.drawSelected, graph, map2.extent());
}
surface.call(drawVertices, graph, data, filter2, map2.extent(), fullRedraw).call(drawLines, graph, data, filter2).call(drawAreas, graph, data, filter2).call(drawMidpoints, graph, data, filter2, map2.trimmedExtent()).call(drawLabels, graph, data, filter2, _dimensions, fullRedraw).call(drawPoints, graph, data, filter2);
dispatch10.call("drawn", this, { full: true });
}
map2.init = function() {
drawLayers = svgLayers(projection2, context);
drawPoints = svgPoints(projection2, context);
drawVertices = svgVertices(projection2, context);
drawLines = svgLines(projection2, context);
drawAreas = svgAreas(projection2, context);
drawMidpoints = svgMidpoints(projection2, context);
drawLabels = svgLabels(projection2, context);
};
function editOff() {
context.features().resetStats();
surface.selectAll(".layer-osm *").remove();
surface.selectAll(".layer-touch:not(.markers) *").remove();
var allowed = {
"browse": true,
"save": true,
"select-note": true,
"select-data": true,
"select-error": true
};
var mode = context.mode();
if (mode && !allowed[mode.id]) {
context.enter(modeBrowse(context));
}
dispatch10.call("drawn", this, { full: true });
}
function gestureChange(d3_event) {
var e = d3_event;
e.preventDefault();
var props = {
deltaMode: 0,
deltaY: 1,
clientX: e.clientX,
clientY: e.clientY,
screenX: e.screenX,
screenY: e.screenY,
x: e.x,
y: e.y
};
var e22 = new WheelEvent("wheel", props);
e22._scale = e.scale;
e22._rotation = e.rotation;
_selection.node().dispatchEvent(e22);
}
function zoomPan(event, key, transform2) {
var source = event && event.sourceEvent || event;
var eventTransform = transform2 || event && event.transform;
var x = eventTransform.x;
var y = eventTransform.y;
var k = eventTransform.k;
if (source && source.type === "wheel") {
if (_pointerDown)
return;
var detected = utilDetect();
var dX = source.deltaX;
var dY = source.deltaY;
var x2 = x;
var y2 = y;
var k2 = k;
var t0, p02, p1;
if (source.deltaMode === 1) {
var lines = Math.abs(source.deltaY);
var sign2 = source.deltaY > 0 ? 1 : -1;
dY = sign2 * clamp(Math.exp((lines - 1) * 0.75) * 4.000244140625, 4.000244140625, 350.000244140625);
if (detected.os !== "mac") {
dY *= 5;
}
t0 = _isTransformed ? _transformLast : _transformStart;
p02 = _getMouseCoords(source);
p1 = t0.invert(p02);
k2 = t0.k * Math.pow(2, -dY / 500);
k2 = clamp(k2, kMin, kMax);
x2 = p02[0] - p1[0] * k2;
y2 = p02[1] - p1[1] * k2;
} else if (source._scale) {
t0 = _gestureTransformStart;
p02 = _getMouseCoords(source);
p1 = t0.invert(p02);
k2 = t0.k * source._scale;
k2 = clamp(k2, kMin, kMax);
x2 = p02[0] - p1[0] * k2;
y2 = p02[1] - p1[1] * k2;
} else if (source.ctrlKey && !isInteger(dY)) {
dY *= 6;
t0 = _isTransformed ? _transformLast : _transformStart;
p02 = _getMouseCoords(source);
p1 = t0.invert(p02);
k2 = t0.k * Math.pow(2, -dY / 500);
k2 = clamp(k2, kMin, kMax);
x2 = p02[0] - p1[0] * k2;
y2 = p02[1] - p1[1] * k2;
} else if ((source.altKey || source.shiftKey) && isInteger(dY)) {
t0 = _isTransformed ? _transformLast : _transformStart;
p02 = _getMouseCoords(source);
p1 = t0.invert(p02);
k2 = t0.k * Math.pow(2, -dY / 500);
k2 = clamp(k2, kMin, kMax);
x2 = p02[0] - p1[0] * k2;
y2 = p02[1] - p1[1] * k2;
} else if (detected.os === "mac" && detected.browser !== "Firefox" && !source.ctrlKey && isInteger(dX) && isInteger(dY)) {
p1 = projection2.translate();
x2 = p1[0] - dX;
y2 = p1[1] - dY;
k2 = projection2.scale();
k2 = clamp(k2, kMin, kMax);
}
if (x2 !== x || y2 !== y || k2 !== k) {
x = x2;
y = y2;
k = k2;
eventTransform = identity2.translate(x2, y2).scale(k2);
if (_zoomerPanner._transform) {
_zoomerPanner._transform(eventTransform);
} else {
_selection.node().__zoom = eventTransform;
}
}
}
if (_transformStart.x === x && _transformStart.y === y && _transformStart.k === k) {
return;
}
if (geoScaleToZoom(k, TILESIZE) < _minzoom) {
surface.interrupt();
dispatch10.call("hitMinZoom", this, map2);
setCenterZoom(map2.center(), context.minEditableZoom(), 0, true);
scheduleRedraw();
dispatch10.call("move", this, map2);
return;
}
projection2.transform(eventTransform);
var withinEditableZoom = map2.withinEditableZoom();
if (_lastWithinEditableZoom !== withinEditableZoom) {
if (_lastWithinEditableZoom !== void 0) {
dispatch10.call("crossEditableZoom", this, withinEditableZoom);
}
_lastWithinEditableZoom = withinEditableZoom;
}
var scale = k / _transformStart.k;
var tX = (x / scale - _transformStart.x) * scale;
var tY = (y / scale - _transformStart.y) * scale;
if (context.inIntro()) {
curtainProjection.transform({
x: x - tX,
y: y - tY,
k
});
}
if (source) {
_lastPointerEvent = event;
}
_isTransformed = true;
_transformLast = eventTransform;
utilSetTransform(supersurface, tX, tY, scale);
scheduleRedraw();
dispatch10.call("move", this, map2);
function isInteger(val) {
return typeof val === "number" && isFinite(val) && Math.floor(val) === val;
}
}
function resetTransform() {
if (!_isTransformed)
return false;
utilSetTransform(supersurface, 0, 0);
_isTransformed = false;
if (context.inIntro()) {
curtainProjection.transform(projection2.transform());
}
return true;
}
function redraw(difference, extent) {
if (surface.empty() || !_redrawEnabled)
return;
if (resetTransform()) {
difference = extent = void 0;
}
var zoom = map2.zoom();
var z = String(~~zoom);
if (surface.attr("data-zoom") !== z) {
surface.attr("data-zoom", z);
}
var lat = map2.center()[1];
var lowzoom = linear3().domain([-60, 0, 60]).range([17, 18.5, 17]).clamp(true);
surface.classed("low-zoom", zoom <= lowzoom(lat));
if (!difference) {
supersurface.call(context.background());
wrapper.call(drawLayers);
}
if (map2.editableDataEnabled() || map2.isInWideSelection()) {
context.loadTiles(projection2);
drawEditable(difference, extent);
} else {
editOff();
}
_transformStart = projection2.transform();
return map2;
}
var immediateRedraw = function(difference, extent) {
if (!difference && !extent)
cancelPendingRedraw();
redraw(difference, extent);
};
map2.lastPointerEvent = function() {
return _lastPointerEvent;
};
map2.mouse = function(d3_event) {
var event = d3_event || _lastPointerEvent;
if (event) {
var s;
while (s = event.sourceEvent) {
event = s;
}
return _getMouseCoords(event);
}
return null;
};
map2.mouseCoordinates = function() {
var coord2 = map2.mouse() || pxCenter();
return projection2.invert(coord2);
};
map2.dblclickZoomEnable = function(val) {
if (!arguments.length)
return _dblClickZoomEnabled;
_dblClickZoomEnabled = val;
return map2;
};
map2.redrawEnable = function(val) {
if (!arguments.length)
return _redrawEnabled;
_redrawEnabled = val;
return map2;
};
map2.isTransformed = function() {
return _isTransformed;
};
function setTransform(t2, duration, force) {
var t = projection2.transform();
if (!force && t2.k === t.k && t2.x === t.x && t2.y === t.y)
return false;
if (duration) {
_selection.transition().duration(duration).on("start", function() {
map2.startEase();
}).call(_zoomerPanner.transform, identity2.translate(t2.x, t2.y).scale(t2.k));
} else {
projection2.transform(t2);
_transformStart = t2;
_selection.call(_zoomerPanner.transform, _transformStart);
}
return true;
}
function setCenterZoom(loc2, z2, duration, force) {
var c = map2.center();
var z = map2.zoom();
if (loc2[0] === c[0] && loc2[1] === c[1] && z2 === z && !force)
return false;
var proj = geoRawMercator().transform(projection2.transform());
var k2 = clamp(geoZoomToScale(z2, TILESIZE), kMin, kMax);
proj.scale(k2);
var t = proj.translate();
var point = proj(loc2);
var center = pxCenter();
t[0] += center[0] - point[0];
t[1] += center[1] - point[1];
return setTransform(identity2.translate(t[0], t[1]).scale(k2), duration, force);
}
map2.pan = function(delta, duration) {
var t = projection2.translate();
var k = projection2.scale();
t[0] += delta[0];
t[1] += delta[1];
if (duration) {
_selection.transition().duration(duration).on("start", function() {
map2.startEase();
}).call(_zoomerPanner.transform, identity2.translate(t[0], t[1]).scale(k));
} else {
projection2.translate(t);
_transformStart = projection2.transform();
_selection.call(_zoomerPanner.transform, _transformStart);
dispatch10.call("move", this, map2);
immediateRedraw();
}
return map2;
};
map2.dimensions = function(val) {
if (!arguments.length)
return _dimensions;
_dimensions = val;
drawLayers.dimensions(_dimensions);
context.background().dimensions(_dimensions);
projection2.clipExtent([[0, 0], _dimensions]);
_getMouseCoords = utilFastMouse(supersurface.node());
scheduleRedraw();
return map2;
};
function zoomIn(delta) {
setCenterZoom(map2.center(), ~~map2.zoom() + delta, 250, true);
}
function zoomOut(delta) {
setCenterZoom(map2.center(), ~~map2.zoom() - delta, 250, true);
}
map2.zoomIn = function() {
zoomIn(1);
};
map2.zoomInFurther = function() {
zoomIn(4);
};
map2.canZoomIn = function() {
return map2.zoom() < maxZoom;
};
map2.zoomOut = function() {
zoomOut(1);
};
map2.zoomOutFurther = function() {
zoomOut(4);
};
map2.canZoomOut = function() {
return map2.zoom() > minZoom2;
};
map2.center = function(loc2) {
if (!arguments.length) {
return projection2.invert(pxCenter());
}
if (setCenterZoom(loc2, map2.zoom())) {
dispatch10.call("move", this, map2);
}
scheduleRedraw();
return map2;
};
map2.unobscuredCenterZoomEase = function(loc, zoom) {
var offset = map2.unobscuredOffsetPx();
var proj = geoRawMercator().transform(projection2.transform());
proj.scale(geoZoomToScale(zoom, TILESIZE));
var locPx = proj(loc);
var offsetLocPx = [locPx[0] + offset[0], locPx[1] + offset[1]];
var offsetLoc = proj.invert(offsetLocPx);
map2.centerZoomEase(offsetLoc, zoom);
};
map2.unobscuredOffsetPx = function() {
var openPane = context.container().select(".map-panes .map-pane.shown");
if (!openPane.empty()) {
return [openPane.node().offsetWidth / 2, 0];
}
return [0, 0];
};
map2.zoom = function(z2) {
if (!arguments.length) {
return Math.max(geoScaleToZoom(projection2.scale(), TILESIZE), 0);
}
if (z2 < _minzoom) {
surface.interrupt();
dispatch10.call("hitMinZoom", this, map2);
z2 = context.minEditableZoom();
}
if (setCenterZoom(map2.center(), z2)) {
dispatch10.call("move", this, map2);
}
scheduleRedraw();
return map2;
};
map2.centerZoom = function(loc2, z2) {
if (setCenterZoom(loc2, z2)) {
dispatch10.call("move", this, map2);
}
scheduleRedraw();
return map2;
};
map2.zoomTo = function(entity) {
var extent = entity.extent(context.graph());
if (!isFinite(extent.area()))
return map2;
var z2 = clamp(map2.trimmedExtentZoom(extent), 0, 20);
return map2.centerZoom(extent.center(), z2);
};
map2.centerEase = function(loc2, duration) {
duration = duration || 250;
setCenterZoom(loc2, map2.zoom(), duration);
return map2;
};
map2.zoomEase = function(z2, duration) {
duration = duration || 250;
setCenterZoom(map2.center(), z2, duration, false);
return map2;
};
map2.centerZoomEase = function(loc2, z2, duration) {
duration = duration || 250;
setCenterZoom(loc2, z2, duration, false);
return map2;
};
map2.transformEase = function(t2, duration) {
duration = duration || 250;
setTransform(t2, duration, false);
return map2;
};
map2.zoomToEase = function(obj, duration) {
var extent;
if (Array.isArray(obj)) {
obj.forEach(function(entity) {
var entityExtent = entity.extent(context.graph());
if (!extent) {
extent = entityExtent;
} else {
extent = extent.extend(entityExtent);
}
});
} else {
extent = obj.extent(context.graph());
}
if (!isFinite(extent.area()))
return map2;
var z2 = clamp(map2.trimmedExtentZoom(extent), 0, 20);
return map2.centerZoomEase(extent.center(), z2, duration);
};
map2.startEase = function() {
utilBindOnce(surface, _pointerPrefix + "down.ease", function() {
map2.cancelEase();
});
return map2;
};
map2.cancelEase = function() {
_selection.interrupt();
return map2;
};
map2.extent = function(val) {
if (!arguments.length) {
return new geoExtent(projection2.invert([0, _dimensions[1]]), projection2.invert([_dimensions[0], 0]));
} else {
var extent = geoExtent(val);
map2.centerZoom(extent.center(), map2.extentZoom(extent));
}
};
map2.trimmedExtent = function(val) {
if (!arguments.length) {
var headerY = 71;
var footerY = 30;
var pad2 = 10;
return new geoExtent(projection2.invert([pad2, _dimensions[1] - footerY - pad2]), projection2.invert([_dimensions[0] - pad2, headerY + pad2]));
} else {
var extent = geoExtent(val);
map2.centerZoom(extent.center(), map2.trimmedExtentZoom(extent));
}
};
function calcExtentZoom(extent, dim) {
var tl = projection2([extent[0][0], extent[1][1]]);
var br = projection2([extent[1][0], extent[0][1]]);
var hFactor = (br[0] - tl[0]) / dim[0];
var vFactor = (br[1] - tl[1]) / dim[1];
var hZoomDiff = Math.log(Math.abs(hFactor)) / Math.LN2;
var vZoomDiff = Math.log(Math.abs(vFactor)) / Math.LN2;
var newZoom = map2.zoom() - Math.max(hZoomDiff, vZoomDiff);
return newZoom;
}
map2.extentZoom = function(val) {
return calcExtentZoom(geoExtent(val), _dimensions);
};
map2.trimmedExtentZoom = function(val) {
var trimY = 120;
var trimX = 40;
var trimmed = [_dimensions[0] - trimX, _dimensions[1] - trimY];
return calcExtentZoom(geoExtent(val), trimmed);
};
map2.withinEditableZoom = function() {
return map2.zoom() >= context.minEditableZoom();
};
map2.isInWideSelection = function() {
return !map2.withinEditableZoom() && context.selectedIDs().length;
};
map2.editableDataEnabled = function(skipZoomCheck) {
var layer = context.layers().layer("osm");
if (!layer || !layer.enabled())
return false;
return skipZoomCheck || map2.withinEditableZoom();
};
map2.notesEditable = function() {
var layer = context.layers().layer("notes");
if (!layer || !layer.enabled())
return false;
return map2.withinEditableZoom();
};
map2.minzoom = function(val) {
if (!arguments.length)
return _minzoom;
_minzoom = val;
return map2;
};
map2.toggleHighlightEdited = function() {
surface.classed("highlight-edited", !surface.classed("highlight-edited"));
map2.pan([0, 0]);
dispatch10.call("changeHighlighting", this);
};
map2.areaFillOptions = ["wireframe", "partial", "full"];
map2.activeAreaFill = function(val) {
if (!arguments.length)
return corePreferences("area-fill") || "partial";
corePreferences("area-fill", val);
if (val !== "wireframe") {
corePreferences("area-fill-toggle", val);
}
updateAreaFill();
map2.pan([0, 0]);
dispatch10.call("changeAreaFill", this);
return map2;
};
map2.toggleWireframe = function() {
var activeFill = map2.activeAreaFill();
if (activeFill === "wireframe") {
activeFill = corePreferences("area-fill-toggle") || "partial";
} else {
activeFill = "wireframe";
}
map2.activeAreaFill(activeFill);
};
function updateAreaFill() {
var activeFill = map2.activeAreaFill();
map2.areaFillOptions.forEach(function(opt) {
surface.classed("fill-" + opt, Boolean(opt === activeFill));
});
}
map2.layers = () => drawLayers;
map2.doubleUpHandler = function() {
return _doubleUpHandler;
};
return utilRebind(map2, dispatch10, "on");
}
// modules/renderer/photos.js
function rendererPhotos(context) {
var dispatch10 = dispatch_default("change");
var _layerIDs = ["streetside", "mapillary", "mapillary-map-features", "mapillary-signs", "kartaview"];
var _allPhotoTypes = ["flat", "panoramic"];
var _shownPhotoTypes = _allPhotoTypes.slice();
var _dateFilters = ["fromDate", "toDate"];
var _fromDate;
var _toDate;
var _usernames;
function photos() {
}
function updateStorage() {
if (window.mocha)
return;
var hash = utilStringQs(window.location.hash);
var enabled = context.layers().all().filter(function(d) {
return _layerIDs.indexOf(d.id) !== -1 && d.layer && d.layer.supported() && d.layer.enabled();
}).map(function(d) {
return d.id;
});
if (enabled.length) {
hash.photo_overlay = enabled.join(",");
} else {
delete hash.photo_overlay;
}
window.location.replace("#" + utilQsString(hash, true));
}
photos.overlayLayerIDs = function() {
return _layerIDs;
};
photos.allPhotoTypes = function() {
return _allPhotoTypes;
};
photos.dateFilters = function() {
return _dateFilters;
};
photos.dateFilterValue = function(val) {
return val === _dateFilters[0] ? _fromDate : _toDate;
};
photos.setDateFilter = function(type3, val, updateUrl) {
var date = val && new Date(val);
if (date && !isNaN(date)) {
val = date.toISOString().substr(0, 10);
} else {
val = null;
}
if (type3 === _dateFilters[0]) {
_fromDate = val;
if (_fromDate && _toDate && new Date(_toDate) < new Date(_fromDate)) {
_toDate = _fromDate;
}
}
if (type3 === _dateFilters[1]) {
_toDate = val;
if (_fromDate && _toDate && new Date(_toDate) < new Date(_fromDate)) {
_fromDate = _toDate;
}
}
dispatch10.call("change", this);
if (updateUrl) {
var rangeString;
if (_fromDate || _toDate) {
rangeString = (_fromDate || "") + "_" + (_toDate || "");
}
setUrlFilterValue("photo_dates", rangeString);
}
};
photos.setUsernameFilter = function(val, updateUrl) {
if (val && typeof val === "string")
val = val.replace(/;/g, ",").split(",");
if (val) {
val = val.map((d) => d.trim()).filter(Boolean);
if (!val.length) {
val = null;
}
}
_usernames = val;
dispatch10.call("change", this);
if (updateUrl) {
var hashString;
if (_usernames) {
hashString = _usernames.join(",");
}
setUrlFilterValue("photo_username", hashString);
}
};
function setUrlFilterValue(property, val) {
if (!window.mocha) {
var hash = utilStringQs(window.location.hash);
if (val) {
if (hash[property] === val)
return;
hash[property] = val;
} else {
if (!(property in hash))
return;
delete hash[property];
}
window.location.replace("#" + utilQsString(hash, true));
}
}
function showsLayer(id2) {
var layer = context.layers().layer(id2);
return layer && layer.supported() && layer.enabled();
}
photos.shouldFilterByDate = function() {
return showsLayer("mapillary") || showsLayer("kartaview") || showsLayer("streetside");
};
photos.shouldFilterByPhotoType = function() {
return showsLayer("mapillary") || showsLayer("streetside") && showsLayer("kartaview");
};
photos.shouldFilterByUsername = function() {
return !showsLayer("mapillary") && showsLayer("kartaview") && !showsLayer("streetside");
};
photos.showsPhotoType = function(val) {
if (!photos.shouldFilterByPhotoType())
return true;
return _shownPhotoTypes.indexOf(val) !== -1;
};
photos.showsFlat = function() {
return photos.showsPhotoType("flat");
};
photos.showsPanoramic = function() {
return photos.showsPhotoType("panoramic");
};
photos.fromDate = function() {
return _fromDate;
};
photos.toDate = function() {
return _toDate;
};
photos.togglePhotoType = function(val) {
var index = _shownPhotoTypes.indexOf(val);
if (index !== -1) {
_shownPhotoTypes.splice(index, 1);
} else {
_shownPhotoTypes.push(val);
}
dispatch10.call("change", this);
return photos;
};
photos.usernames = function() {
return _usernames;
};
photos.init = function() {
var hash = utilStringQs(window.location.hash);
if (hash.photo_dates) {
var parts = /^(.*)[–_](.*)$/g.exec(hash.photo_dates.trim());
this.setDateFilter("fromDate", parts && parts.length >= 2 && parts[1], false);
this.setDateFilter("toDate", parts && parts.length >= 3 && parts[2], false);
}
if (hash.photo_username) {
this.setUsernameFilter(hash.photo_username, false);
}
if (hash.photo_overlay) {
var hashOverlayIDs = hash.photo_overlay.replace(/;/g, ",").split(",");
hashOverlayIDs.forEach(function(id2) {
if (id2 === "openstreetcam")
id2 = "kartaview";
var layer2 = _layerIDs.indexOf(id2) !== -1 && context.layers().layer(id2);
if (layer2 && !layer2.enabled())
layer2.enabled(true);
});
}
if (hash.photo) {
var photoIds = hash.photo.replace(/;/g, ",").split(",");
var photoId = photoIds.length && photoIds[0].trim();
var results = /(.*)\/(.*)/g.exec(photoId);
if (results && results.length >= 3) {
var serviceId = results[1];
if (serviceId === "openstreetcam")
serviceId = "kartaview";
var photoKey = results[2];
var service = services[serviceId];
if (service && service.ensureViewerLoaded) {
var layer = _layerIDs.indexOf(serviceId) !== -1 && context.layers().layer(serviceId);
if (layer && !layer.enabled())
layer.enabled(true);
var baselineTime = Date.now();
service.on("loadedImages.rendererPhotos", function() {
if (Date.now() - baselineTime > 45e3) {
service.on("loadedImages.rendererPhotos", null);
return;
}
if (!service.cachedImage(photoKey))
return;
service.on("loadedImages.rendererPhotos", null);
service.ensureViewerLoaded(context).then(function() {
service.selectImage(context, photoKey).showViewer(context);
});
});
}
}
}
context.layers().on("change.rendererPhotos", updateStorage);
};
return utilRebind(photos, dispatch10, "on");
}
// modules/ui/account.js
function uiAccount(context) {
const osm = context.connection();
function updateUserDetails(selection2) {
if (!osm)
return;
if (!osm.authenticated()) {
render(selection2, null);
} else {
osm.userDetails((err, user) => render(selection2, user));
}
}
function render(selection2, user) {
let userInfo = selection2.select(".userInfo");
let loginLogout = selection2.select(".loginLogout");
if (user) {
userInfo.html("").classed("hide", false);
let userLink = userInfo.append("a").attr("href", osm.userURL(user.display_name)).attr("target", "_blank");
if (user.image_url) {
userLink.append("img").attr("class", "icon pre-text user-icon").attr("src", user.image_url);
} else {
userLink.call(svgIcon("#iD-icon-avatar", "pre-text light"));
}
userLink.append("span").attr("class", "label").html(user.display_name);
loginLogout.classed("hide", false).select("a").text(_t("logout")).on("click", (e) => {
e.preventDefault();
osm.logout();
tryLogout();
});
} else {
userInfo.html("").classed("hide", true);
loginLogout.classed("hide", false).select("a").text(_t("login")).on("click", (e) => {
e.preventDefault();
osm.authenticate();
});
}
}
function tryLogout() {
if (!osm)
return;
const url = osm.getUrlRoot() + "/logout?referer=%2Flogin";
const w = 600;
const h = 550;
const settings = [
["width", w],
["height", h],
["left", window.screen.width / 2 - w / 2],
["top", window.screen.height / 2 - h / 2]
].map((x) => x.join("=")).join(",");
window.open(url, "_blank", settings);
}
return function(selection2) {
if (!osm)
return;
selection2.append("li").attr("class", "userInfo").classed("hide", true);
selection2.append("li").attr("class", "loginLogout").classed("hide", true).append("a").attr("href", "#");
osm.on("change.account", () => updateUserDetails(selection2));
updateUserDetails(selection2);
};
}
// modules/ui/attribution.js
function uiAttribution(context) {
let _selection = select_default2(null);
function render(selection2, data, klass) {
let div = selection2.selectAll(`.${klass}`).data([0]);
div = div.enter().append("div").attr("class", klass).merge(div);
let attributions = div.selectAll(".attribution").data(data, (d) => d.id);
attributions.exit().remove();
attributions = attributions.enter().append("span").attr("class", "attribution").each((d, i2, nodes) => {
let attribution = select_default2(nodes[i2]);
if (d.terms_html) {
attribution.html(d.terms_html);
return;
}
if (d.terms_url) {
attribution = attribution.append("a").attr("href", d.terms_url).attr("target", "_blank");
}
const sourceID = d.id.replace(/\./g, "");
const terms_text = _t(`imagery.${sourceID}.attribution.text`, { default: d.terms_text || d.id || d.name() });
if (d.icon && !d.overlay) {
attribution.append("img").attr("class", "source-image").attr("src", d.icon);
}
attribution.append("span").attr("class", "attribution-text").text(terms_text);
}).merge(attributions);
let copyright = attributions.selectAll(".copyright-notice").data((d) => {
let notice = d.copyrightNotices(context.map().zoom(), context.map().extent());
return notice ? [notice] : [];
});
copyright.exit().remove();
copyright = copyright.enter().append("span").attr("class", "copyright-notice").merge(copyright);
copyright.text(String);
}
function update() {
let baselayer = context.background().baseLayerSource();
_selection.call(render, baselayer ? [baselayer] : [], "base-layer-attribution");
const z = context.map().zoom();
let overlays = context.background().overlayLayerSources() || [];
_selection.call(render, overlays.filter((s) => s.validZoom(z)), "overlay-layer-attribution");
}
return function(selection2) {
_selection = selection2;
context.background().on("change.attribution", update);
context.map().on("move.attribution", throttle_default(update, 400, { leading: false }));
update();
};
}
// modules/ui/contributors.js
function uiContributors(context) {
var osm = context.connection(), debouncedUpdate = debounce_default(function() {
update();
}, 1e3), limit = 4, hidden = false, wrap2 = select_default2(null);
function update() {
if (!osm)
return;
var users = {}, entities = context.history().intersects(context.map().extent());
entities.forEach(function(entity) {
if (entity && entity.user)
users[entity.user] = true;
});
var u = Object.keys(users), subset = u.slice(0, u.length > limit ? limit - 1 : limit);
wrap2.html("").call(svgIcon("#iD-icon-nearby", "pre-text light"));
var userList = select_default2(document.createElement("span"));
userList.selectAll().data(subset).enter().append("a").attr("class", "user-link").attr("href", function(d) {
return osm.userURL(d);
}).attr("target", "_blank").text(String);
if (u.length > limit) {
var count = select_default2(document.createElement("span"));
var othersNum = u.length - limit + 1;
count.append("a").attr("target", "_blank").attr("href", function() {
return osm.changesetsURL(context.map().center(), context.map().zoom());
}).text(othersNum);
wrap2.append("span").html(_t.html("contributors.truncated_list", { n: othersNum, users: { html: userList.html() }, count: { html: count.html() } }));
} else {
wrap2.append("span").html(_t.html("contributors.list", { users: { html: userList.html() } }));
}
if (!u.length) {
hidden = true;
wrap2.transition().style("opacity", 0);
} else if (hidden) {
wrap2.transition().style("opacity", 1);
}
}
return function(selection2) {
if (!osm)
return;
wrap2 = selection2;
update();
osm.on("loaded.contributors", debouncedUpdate);
context.map().on("move.contributors", debouncedUpdate);
};
}
// modules/ui/popover.js
var _popoverID = 0;
function uiPopover(klass) {
var _id = _popoverID++;
var _anchorSelection = select_default2(null);
var popover = function(selection2) {
_anchorSelection = selection2;
selection2.each(setup);
};
var _animation = utilFunctor(false);
var _placement = utilFunctor("top");
var _alignment = utilFunctor("center");
var _scrollContainer = utilFunctor(select_default2(null));
var _content;
var _displayType = utilFunctor("");
var _hasArrow = utilFunctor(true);
var _pointerPrefix = "PointerEvent" in window ? "pointer" : "mouse";
popover.displayType = function(val) {
if (arguments.length) {
_displayType = utilFunctor(val);
return popover;
} else {
return _displayType;
}
};
popover.hasArrow = function(val) {
if (arguments.length) {
_hasArrow = utilFunctor(val);
return popover;
} else {
return _hasArrow;
}
};
popover.placement = function(val) {
if (arguments.length) {
_placement = utilFunctor(val);
return popover;
} else {
return _placement;
}
};
popover.alignment = function(val) {
if (arguments.length) {
_alignment = utilFunctor(val);
return popover;
} else {
return _alignment;
}
};
popover.scrollContainer = function(val) {
if (arguments.length) {
_scrollContainer = utilFunctor(val);
return popover;
} else {
return _scrollContainer;
}
};
popover.content = function(val) {
if (arguments.length) {
_content = val;
return popover;
} else {
return _content;
}
};
popover.isShown = function() {
var popoverSelection = _anchorSelection.select(".popover-" + _id);
return !popoverSelection.empty() && popoverSelection.classed("in");
};
popover.show = function() {
_anchorSelection.each(show);
};
popover.updateContent = function() {
_anchorSelection.each(updateContent);
};
popover.hide = function() {
_anchorSelection.each(hide);
};
popover.toggle = function() {
_anchorSelection.each(toggle);
};
popover.destroy = function(selection2, selector) {
selector = selector || ".popover-" + _id;
selection2.on(_pointerPrefix + "enter.popover", null).on(_pointerPrefix + "leave.popover", null).on(_pointerPrefix + "up.popover", null).on(_pointerPrefix + "down.popover", null).on("click.popover", null).attr("title", function() {
return this.getAttribute("data-original-title") || this.getAttribute("title");
}).attr("data-original-title", null).selectAll(selector).remove();
};
popover.destroyAny = function(selection2) {
selection2.call(popover.destroy, ".popover");
};
function setup() {
var anchor = select_default2(this);
var animate = _animation.apply(this, arguments);
var popoverSelection = anchor.selectAll(".popover-" + _id).data([0]);
var enter = popoverSelection.enter().append("div").attr("class", "popover popover-" + _id + " " + (klass ? klass : "")).classed("arrowed", _hasArrow.apply(this, arguments));
enter.append("div").attr("class", "popover-arrow");
enter.append("div").attr("class", "popover-inner");
popoverSelection = enter.merge(popoverSelection);
if (animate) {
popoverSelection.classed("fade", true);
}
var display = _displayType.apply(this, arguments);
if (display === "hover") {
var _lastNonMouseEnterTime;
anchor.on(_pointerPrefix + "enter.popover", function(d3_event) {
if (d3_event.pointerType) {
if (d3_event.pointerType !== "mouse") {
_lastNonMouseEnterTime = d3_event.timeStamp;
return;
} else if (_lastNonMouseEnterTime && d3_event.timeStamp - _lastNonMouseEnterTime < 1500) {
return;
}
}
if (d3_event.buttons !== 0)
return;
show.apply(this, arguments);
}).on(_pointerPrefix + "leave.popover", function() {
hide.apply(this, arguments);
}).on("focus.popover", function() {
show.apply(this, arguments);
}).on("blur.popover", function() {
hide.apply(this, arguments);
});
} else if (display === "clickFocus") {
anchor.on(_pointerPrefix + "down.popover", function(d3_event) {
d3_event.preventDefault();
d3_event.stopPropagation();
}).on(_pointerPrefix + "up.popover", function(d3_event) {
d3_event.preventDefault();
d3_event.stopPropagation();
}).on("click.popover", toggle);
popoverSelection.attr("tabindex", 0).on("blur.popover", function() {
anchor.each(function() {
hide.apply(this, arguments);
});
});
}
}
function show() {
var anchor = select_default2(this);
var popoverSelection = anchor.selectAll(".popover-" + _id);
if (popoverSelection.empty()) {
anchor.call(popover.destroy);
anchor.each(setup);
popoverSelection = anchor.selectAll(".popover-" + _id);
}
popoverSelection.classed("in", true);
var displayType = _displayType.apply(this, arguments);
if (displayType === "clickFocus") {
anchor.classed("active", true);
popoverSelection.node().focus();
}
anchor.each(updateContent);
}
function updateContent() {
var anchor = select_default2(this);
if (_content) {
anchor.selectAll(".popover-" + _id + " > .popover-inner").call(_content.apply(this, arguments));
}
updatePosition.apply(this, arguments);
updatePosition.apply(this, arguments);
updatePosition.apply(this, arguments);
}
function updatePosition() {
var anchor = select_default2(this);
var popoverSelection = anchor.selectAll(".popover-" + _id);
var scrollContainer = _scrollContainer && _scrollContainer.apply(this, arguments);
var scrollNode = scrollContainer && !scrollContainer.empty() && scrollContainer.node();
var scrollLeft = scrollNode ? scrollNode.scrollLeft : 0;
var scrollTop = scrollNode ? scrollNode.scrollTop : 0;
var placement = _placement.apply(this, arguments);
popoverSelection.classed("left", false).classed("right", false).classed("top", false).classed("bottom", false).classed(placement, true);
var alignment = _alignment.apply(this, arguments);
var alignFactor = 0.5;
if (alignment === "leading") {
alignFactor = 0;
} else if (alignment === "trailing") {
alignFactor = 1;
}
var anchorFrame = getFrame(anchor.node());
var popoverFrame = getFrame(popoverSelection.node());
var position;
switch (placement) {
case "top":
position = {
x: anchorFrame.x + (anchorFrame.w - popoverFrame.w) * alignFactor,
y: anchorFrame.y - popoverFrame.h
};
break;
case "bottom":
position = {
x: anchorFrame.x + (anchorFrame.w - popoverFrame.w) * alignFactor,
y: anchorFrame.y + anchorFrame.h
};
break;
case "left":
position = {
x: anchorFrame.x - popoverFrame.w,
y: anchorFrame.y + (anchorFrame.h - popoverFrame.h) * alignFactor
};
break;
case "right":
position = {
x: anchorFrame.x + anchorFrame.w,
y: anchorFrame.y + (anchorFrame.h - popoverFrame.h) * alignFactor
};
break;
}
if (position) {
if (scrollNode && (placement === "top" || placement === "bottom")) {
var initialPosX = position.x;
if (position.x + popoverFrame.w > scrollNode.offsetWidth - 10) {
position.x = scrollNode.offsetWidth - 10 - popoverFrame.w;
} else if (position.x < 10) {
position.x = 10;
}
var arrow = anchor.selectAll(".popover-" + _id + " > .popover-arrow");
var arrowPosX = Math.min(Math.max(popoverFrame.w / 2 - (position.x - initialPosX), 10), popoverFrame.w - 10);
arrow.style("left", ~~arrowPosX + "px");
}
popoverSelection.style("left", ~~position.x + "px").style("top", ~~position.y + "px");
} else {
popoverSelection.style("left", null).style("top", null);
}
function getFrame(node) {
var positionStyle = select_default2(node).style("position");
if (positionStyle === "absolute" || positionStyle === "static") {
return {
x: node.offsetLeft - scrollLeft,
y: node.offsetTop - scrollTop,
w: node.offsetWidth,
h: node.offsetHeight
};
} else {
return {
x: 0,
y: 0,
w: node.offsetWidth,
h: node.offsetHeight
};
}
}
}
function hide() {
var anchor = select_default2(this);
if (_displayType.apply(this, arguments) === "clickFocus") {
anchor.classed("active", false);
}
anchor.selectAll(".popover-" + _id).classed("in", false);
}
function toggle() {
if (select_default2(this).select(".popover-" + _id).classed("in")) {
hide.apply(this, arguments);
} else {
show.apply(this, arguments);
}
}
return popover;
}
// modules/ui/tooltip.js
function uiTooltip(klass) {
var tooltip = uiPopover((klass || "") + " tooltip").displayType("hover");
var _title = function() {
var title = this.getAttribute("data-original-title");
if (title) {
return title;
} else {
title = this.getAttribute("title");
this.removeAttribute("title");
this.setAttribute("data-original-title", title);
}
return title;
};
var _heading = utilFunctor(null);
var _keys = utilFunctor(null);
tooltip.title = function(val) {
if (!arguments.length)
return _title;
_title = utilFunctor(val);
return tooltip;
};
tooltip.heading = function(val) {
if (!arguments.length)
return _heading;
_heading = utilFunctor(val);
return tooltip;
};
tooltip.keys = function(val) {
if (!arguments.length)
return _keys;
_keys = utilFunctor(val);
return tooltip;
};
tooltip.content(function() {
var heading = _heading.apply(this, arguments);
var text2 = _title.apply(this, arguments);
var keys = _keys.apply(this, arguments);
return function(selection2) {
var headingSelect = selection2.selectAll(".tooltip-heading").data(heading ? [heading] : []);
headingSelect.exit().remove();
headingSelect.enter().append("div").attr("class", "tooltip-heading").merge(headingSelect).html(heading);
var textSelect = selection2.selectAll(".tooltip-text").data(text2 ? [text2] : []);
textSelect.exit().remove();
textSelect.enter().append("div").attr("class", "tooltip-text").merge(textSelect).html(text2);
var keyhintWrap = selection2.selectAll(".keyhint-wrap").data(keys && keys.length ? [0] : []);
keyhintWrap.exit().remove();
var keyhintWrapEnter = keyhintWrap.enter().append("div").attr("class", "keyhint-wrap");
keyhintWrapEnter.append("span").call(_t.append("tooltip_keyhint"));
keyhintWrap = keyhintWrapEnter.merge(keyhintWrap);
keyhintWrap.selectAll("kbd.shortcut").data(keys && keys.length ? keys : []).enter().append("kbd").attr("class", "shortcut").html(function(d) {
return d;
});
};
});
return tooltip;
}
// modules/ui/edit_menu.js
function uiEditMenu(context) {
var dispatch10 = dispatch_default("toggled");
var _menu = select_default2(null);
var _operations = [];
var _anchorLoc = [0, 0];
var _anchorLocLonLat = [0, 0];
var _triggerType = "";
var _vpTopMargin = 85;
var _vpBottomMargin = 45;
var _vpSideMargin = 35;
var _menuTop = false;
var _menuHeight;
var _menuWidth;
var _verticalPadding = 4;
var _tooltipWidth = 210;
var _menuSideMargin = 10;
var _tooltips = [];
var editMenu = function(selection2) {
var isTouchMenu = _triggerType.includes("touch") || _triggerType.includes("pen");
var ops = _operations.filter(function(op) {
return !isTouchMenu || !op.mouseOnly;
});
if (!ops.length)
return;
_tooltips = [];
_menuTop = isTouchMenu;
var showLabels = isTouchMenu;
var buttonHeight = showLabels ? 32 : 34;
if (showLabels) {
_menuWidth = 52 + Math.min(120, 6 * Math.max.apply(Math, ops.map(function(op) {
return op.title.length;
})));
} else {
_menuWidth = 44;
}
_menuHeight = _verticalPadding * 2 + ops.length * buttonHeight;
_menu = selection2.append("div").attr("class", "edit-menu").classed("touch-menu", isTouchMenu).style("padding", _verticalPadding + "px 0");
var buttons = _menu.selectAll(".edit-menu-item").data(ops);
var buttonsEnter = buttons.enter().append("button").attr("class", function(d) {
return "edit-menu-item edit-menu-item-" + d.id;
}).style("height", buttonHeight + "px").on("click", click).on("pointerup", pointerup).on("pointerdown mousedown", function pointerdown(d3_event) {
d3_event.stopPropagation();
}).on("mouseenter.highlight", function(d3_event, d) {
if (!d.relatedEntityIds || select_default2(this).classed("disabled"))
return;
utilHighlightEntities(d.relatedEntityIds(), true, context);
}).on("mouseleave.highlight", function(d3_event, d) {
if (!d.relatedEntityIds)
return;
utilHighlightEntities(d.relatedEntityIds(), false, context);
});
buttonsEnter.each(function(d) {
var tooltip = uiTooltip().heading(d.title).title(d.tooltip()).keys([d.keys[0]]);
_tooltips.push(tooltip);
select_default2(this).call(tooltip).append("div").attr("class", "icon-wrap").call(svgIcon(d.icon && d.icon() || "#iD-operation-" + d.id, "operation"));
});
if (showLabels) {
buttonsEnter.append("span").attr("class", "label").html(function(d) {
return d.title;
});
}
buttonsEnter.merge(buttons).classed("disabled", function(d) {
return d.disabled();
});
updatePosition();
var initialScale = context.projection.scale();
context.map().on("move.edit-menu", function() {
if (initialScale !== context.projection.scale()) {
editMenu.close();
}
}).on("drawn.edit-menu", function(info) {
if (info.full)
updatePosition();
});
var lastPointerUpType;
function pointerup(d3_event) {
lastPointerUpType = d3_event.pointerType;
}
function click(d3_event, operation) {
d3_event.stopPropagation();
if (operation.relatedEntityIds) {
utilHighlightEntities(operation.relatedEntityIds(), false, context);
}
if (operation.disabled()) {
if (lastPointerUpType === "touch" || lastPointerUpType === "pen") {
context.ui().flash.duration(4e3).iconName("#iD-operation-" + operation.id).iconClass("operation disabled").label(operation.tooltip)();
}
} else {
if (lastPointerUpType === "touch" || lastPointerUpType === "pen") {
context.ui().flash.duration(2e3).iconName("#iD-operation-" + operation.id).iconClass("operation").label(operation.annotation() || operation.title)();
}
operation();
editMenu.close();
}
lastPointerUpType = null;
}
dispatch10.call("toggled", this, true);
};
function updatePosition() {
if (!_menu || _menu.empty())
return;
var anchorLoc = context.projection(_anchorLocLonLat);
var viewport = context.surfaceRect();
if (anchorLoc[0] < 0 || anchorLoc[0] > viewport.width || anchorLoc[1] < 0 || anchorLoc[1] > viewport.height) {
editMenu.close();
return;
}
var menuLeft = displayOnLeft(viewport);
var offset = [0, 0];
offset[0] = menuLeft ? -1 * (_menuSideMargin + _menuWidth) : _menuSideMargin;
if (_menuTop) {
if (anchorLoc[1] - _menuHeight < _vpTopMargin) {
offset[1] = -anchorLoc[1] + _vpTopMargin;
} else {
offset[1] = -_menuHeight;
}
} else {
if (anchorLoc[1] + _menuHeight > viewport.height - _vpBottomMargin) {
offset[1] = -anchorLoc[1] - _menuHeight + viewport.height - _vpBottomMargin;
} else {
offset[1] = 0;
}
}
var origin = geoVecAdd(anchorLoc, offset);
_menu.style("left", origin[0] + "px").style("top", origin[1] + "px");
var tooltipSide = tooltipPosition(viewport, menuLeft);
_tooltips.forEach(function(tooltip) {
tooltip.placement(tooltipSide);
});
function displayOnLeft(viewport2) {
if (_mainLocalizer.textDirection() === "ltr") {
if (anchorLoc[0] + _menuSideMargin + _menuWidth > viewport2.width - _vpSideMargin) {
return true;
}
return false;
} else {
if (anchorLoc[0] - _menuSideMargin - _menuWidth < _vpSideMargin) {
return false;
}
return true;
}
}
function tooltipPosition(viewport2, menuLeft2) {
if (_mainLocalizer.textDirection() === "ltr") {
if (menuLeft2) {
return "left";
}
if (anchorLoc[0] + _menuSideMargin + _menuWidth + _tooltipWidth > viewport2.width - _vpSideMargin) {
return "left";
}
return "right";
} else {
if (!menuLeft2) {
return "right";
}
if (anchorLoc[0] - _menuSideMargin - _menuWidth - _tooltipWidth < _vpSideMargin) {
return "right";
}
return "left";
}
}
}
editMenu.close = function() {
context.map().on("move.edit-menu", null).on("drawn.edit-menu", null);
_menu.remove();
_tooltips = [];
dispatch10.call("toggled", this, false);
};
editMenu.anchorLoc = function(val) {
if (!arguments.length)
return _anchorLoc;
_anchorLoc = val;
_anchorLocLonLat = context.projection.invert(_anchorLoc);
return editMenu;
};
editMenu.triggerType = function(val) {
if (!arguments.length)
return _triggerType;
_triggerType = val;
return editMenu;
};
editMenu.operations = function(val) {
if (!arguments.length)
return _operations;
_operations = val;
return editMenu;
};
return utilRebind(editMenu, dispatch10, "on");
}
// modules/ui/feature_info.js
function uiFeatureInfo(context) {
function update(selection2) {
var features2 = context.features();
var stats = features2.stats();
var count = 0;
var hiddenList = features2.hidden().map(function(k) {
if (stats[k]) {
count += stats[k];
return _t.html("inspector.title_count", { title: { html: _t.html("feature." + k + ".description") }, count: stats[k] });
}
return null;
}).filter(Boolean);
selection2.html("");
if (hiddenList.length) {
var tooltipBehavior = uiTooltip().placement("top").title(function() {
return hiddenList.join("
");
});
selection2.append("a").attr("class", "chip").attr("href", "#").call(_t.append("feature_info.hidden_warning", { count })).call(tooltipBehavior).on("click", function(d3_event) {
tooltipBehavior.hide();
d3_event.preventDefault();
context.ui().togglePanes(context.container().select(".map-panes .map-data-pane"));
});
}
selection2.classed("hide", !hiddenList.length);
}
return function(selection2) {
update(selection2);
context.features().on("change.feature_info", function() {
update(selection2);
});
};
}
// modules/ui/flash.js
function uiFlash(context) {
var _flashTimer;
var _duration = 2e3;
var _iconName = "#iD-icon-no";
var _iconClass = "disabled";
var _label = "";
function flash() {
if (_flashTimer) {
_flashTimer.stop();
}
context.container().select(".main-footer-wrap").classed("footer-hide", true).classed("footer-show", false);
context.container().select(".flash-wrap").classed("footer-hide", false).classed("footer-show", true);
var content = context.container().select(".flash-wrap").selectAll(".flash-content").data([0]);
var contentEnter = content.enter().append("div").attr("class", "flash-content");
var iconEnter = contentEnter.append("svg").attr("class", "flash-icon icon").append("g").attr("transform", "translate(10,10)");
iconEnter.append("circle").attr("r", 9);
iconEnter.append("use").attr("transform", "translate(-7,-7)").attr("width", "14").attr("height", "14");
contentEnter.append("div").attr("class", "flash-text");
content = content.merge(contentEnter);
content.selectAll(".flash-icon").attr("class", "icon flash-icon " + (_iconClass || ""));
content.selectAll(".flash-icon use").attr("xlink:href", _iconName);
content.selectAll(".flash-text").attr("class", "flash-text").html(_label);
_flashTimer = timeout_default(function() {
_flashTimer = null;
context.container().select(".main-footer-wrap").classed("footer-hide", false).classed("footer-show", true);
context.container().select(".flash-wrap").classed("footer-hide", true).classed("footer-show", false);
}, _duration);
return content;
}
flash.duration = function(_) {
if (!arguments.length)
return _duration;
_duration = _;
return flash;
};
flash.label = function(_) {
if (!arguments.length)
return _label;
_label = _;
return flash;
};
flash.iconName = function(_) {
if (!arguments.length)
return _iconName;
_iconName = _;
return flash;
};
flash.iconClass = function(_) {
if (!arguments.length)
return _iconClass;
_iconClass = _;
return flash;
};
return flash;
}
// modules/ui/full_screen.js
function uiFullScreen(context) {
var element = context.container().node();
function getFullScreenFn() {
if (element.requestFullscreen) {
return element.requestFullscreen;
} else if (element.msRequestFullscreen) {
return element.msRequestFullscreen;
} else if (element.mozRequestFullScreen) {
return element.mozRequestFullScreen;
} else if (element.webkitRequestFullscreen) {
return element.webkitRequestFullscreen;
}
}
function getExitFullScreenFn() {
if (document.exitFullscreen) {
return document.exitFullscreen;
} else if (document.msExitFullscreen) {
return document.msExitFullscreen;
} else if (document.mozCancelFullScreen) {
return document.mozCancelFullScreen;
} else if (document.webkitExitFullscreen) {
return document.webkitExitFullscreen;
}
}
function isFullScreen() {
return document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement;
}
function isSupported() {
return !!getFullScreenFn();
}
function fullScreen(d3_event) {
d3_event.preventDefault();
if (!isFullScreen()) {
getFullScreenFn().apply(element);
} else {
getExitFullScreenFn().apply(document);
}
}
return function() {
if (!isSupported())
return;
var detected = utilDetect();
var keys = detected.os === "mac" ? [uiCmd("\u2303\u2318F"), "f11"] : ["f11"];
context.keybinding().on(keys, fullScreen);
};
}
// modules/ui/geolocate.js
function uiGeolocate(context) {
var _geolocationOptions = {
enableHighAccuracy: false,
timeout: 6e3
};
var _locating = uiLoading(context).message(_t.html("geolocate.locating")).blocking(true);
var _layer = context.layers().layer("geolocate");
var _position;
var _extent;
var _timeoutID;
var _button = select_default2(null);
function click() {
if (context.inIntro())
return;
if (!_layer.enabled() && !_locating.isShown()) {
_timeoutID = setTimeout(error, 1e4);
context.container().call(_locating);
navigator.geolocation.getCurrentPosition(success, error, _geolocationOptions);
} else {
_locating.close();
_layer.enabled(null, false);
updateButtonState();
}
}
function zoomTo() {
context.enter(modeBrowse(context));
var map2 = context.map();
_layer.enabled(_position, true);
updateButtonState();
map2.centerZoomEase(_extent.center(), Math.min(20, map2.extentZoom(_extent)));
}
function success(geolocation) {
_position = geolocation;
var coords = _position.coords;
_extent = geoExtent([coords.longitude, coords.latitude]).padByMeters(coords.accuracy);
zoomTo();
finish();
}
function error() {
if (_position) {
zoomTo();
} else {
context.ui().flash.label(_t.html("geolocate.location_unavailable")).iconName("#iD-icon-geolocate")();
}
finish();
}
function finish() {
_locating.close();
if (_timeoutID) {
clearTimeout(_timeoutID);
}
_timeoutID = void 0;
}
function updateButtonState() {
_button.classed("active", _layer.enabled());
_button.attr("aria-pressed", _layer.enabled());
}
return function(selection2) {
if (!navigator.geolocation || !navigator.geolocation.getCurrentPosition)
return;
_button = selection2.append("button").on("click", click).attr("aria-pressed", false).call(svgIcon("#iD-icon-geolocate", "light")).call(uiTooltip().placement(_mainLocalizer.textDirection() === "rtl" ? "right" : "left").title(_t.html("geolocate.title")).keys([_t("geolocate.key")]));
context.keybinding().on(_t("geolocate.key"), click);
};
}
// modules/ui/panels/background.js
function uiPanelBackground(context) {
var background = context.background();
var _currSourceName = null;
var _metadata = {};
var _metadataKeys = [
"zoom",
"vintage",
"source",
"description",
"resolution",
"accuracy"
];
var debouncedRedraw = debounce_default(redraw, 250);
function redraw(selection2) {
var source = background.baseLayerSource();
if (!source)
return;
var isDG = source.id.match(/^DigitalGlobe/i) !== null;
var sourceLabel = source.label();
if (_currSourceName !== sourceLabel) {
_currSourceName = sourceLabel;
_metadata = {};
}
selection2.html("");
var list = selection2.append("ul").attr("class", "background-info");
list.append("li").html(_currSourceName);
_metadataKeys.forEach(function(k) {
if (isDG && k === "vintage")
return;
list.append("li").attr("class", "background-info-list-" + k).classed("hide", !_metadata[k]).call(_t.append("info_panels.background." + k, { suffix: ":" })).append("span").attr("class", "background-info-span-" + k).text(_metadata[k]);
});
debouncedGetMetadata(selection2);
var toggleTiles = context.getDebug("tile") ? "hide_tiles" : "show_tiles";
selection2.append("a").call(_t.append("info_panels.background." + toggleTiles)).attr("href", "#").attr("class", "button button-toggle-tiles").on("click", function(d3_event) {
d3_event.preventDefault();
context.setDebug("tile", !context.getDebug("tile"));
selection2.call(redraw);
});
if (isDG) {
var key = source.id + "-vintage";
var sourceVintage = context.background().findSource(key);
var showsVintage = context.background().showsLayer(sourceVintage);
var toggleVintage = showsVintage ? "hide_vintage" : "show_vintage";
selection2.append("a").call(_t.append("info_panels.background." + toggleVintage)).attr("href", "#").attr("class", "button button-toggle-vintage").on("click", function(d3_event) {
d3_event.preventDefault();
context.background().toggleOverlayLayer(sourceVintage);
selection2.call(redraw);
});
}
["DigitalGlobe-Premium", "DigitalGlobe-Standard"].forEach(function(layerId) {
if (source.id !== layerId) {
var key2 = layerId + "-vintage";
var sourceVintage2 = context.background().findSource(key2);
if (context.background().showsLayer(sourceVintage2)) {
context.background().toggleOverlayLayer(sourceVintage2);
}
}
});
}
var debouncedGetMetadata = debounce_default(getMetadata, 250);
function getMetadata(selection2) {
var tile = context.container().select(".layer-background img.tile-center");
if (tile.empty())
return;
var sourceName = _currSourceName;
var d = tile.datum();
var zoom = d && d.length >= 3 && d[2] || Math.floor(context.map().zoom());
var center = context.map().center();
_metadata.zoom = String(zoom);
selection2.selectAll(".background-info-list-zoom").classed("hide", false).selectAll(".background-info-span-zoom").text(_metadata.zoom);
if (!d || !d.length >= 3)
return;
background.baseLayerSource().getMetadata(center, d, function(err, result) {
if (err || _currSourceName !== sourceName)
return;
var vintage = result.vintage;
_metadata.vintage = vintage && vintage.range || _t("info_panels.background.unknown");
selection2.selectAll(".background-info-list-vintage").classed("hide", false).selectAll(".background-info-span-vintage").text(_metadata.vintage);
_metadataKeys.forEach(function(k) {
if (k === "zoom" || k === "vintage")
return;
var val = result[k];
_metadata[k] = val;
selection2.selectAll(".background-info-list-" + k).classed("hide", !val).selectAll(".background-info-span-" + k).text(val);
});
});
}
var panel = function(selection2) {
selection2.call(redraw);
context.map().on("drawn.info-background", function() {
selection2.call(debouncedRedraw);
}).on("move.info-background", function() {
selection2.call(debouncedGetMetadata);
});
};
panel.off = function() {
context.map().on("drawn.info-background", null).on("move.info-background", null);
};
panel.id = "background";
panel.label = _t.html("info_panels.background.title");
panel.key = _t("info_panels.background.key");
return panel;
}
// modules/ui/panels/history.js
function uiPanelHistory(context) {
var osm;
function displayTimestamp(timestamp) {
if (!timestamp)
return _t("info_panels.history.unknown");
var options2 = {
day: "numeric",
month: "short",
year: "numeric",
hour: "numeric",
minute: "numeric",
second: "numeric"
};
var d = new Date(timestamp);
if (isNaN(d.getTime()))
return _t("info_panels.history.unknown");
return d.toLocaleString(_mainLocalizer.localeCode(), options2);
}
function displayUser(selection2, userName) {
if (!userName) {
selection2.append("span").call(_t.append("info_panels.history.unknown"));
return;
}
selection2.append("span").attr("class", "user-name").text(userName);
var links = selection2.append("div").attr("class", "links");
if (osm) {
links.append("a").attr("class", "user-osm-link").attr("href", osm.userURL(userName)).attr("target", "_blank").call(_t.append("info_panels.history.profile_link"));
}
links.append("a").attr("class", "user-hdyc-link").attr("href", "https://hdyc.neis-one.org/?" + userName).attr("target", "_blank").attr("tabindex", -1).text("HDYC");
}
function displayChangeset(selection2, changeset) {
if (!changeset) {
selection2.append("span").call(_t.append("info_panels.history.unknown"));
return;
}
selection2.append("span").attr("class", "changeset-id").text(changeset);
var links = selection2.append("div").attr("class", "links");
if (osm) {
links.append("a").attr("class", "changeset-osm-link").attr("href", osm.changesetURL(changeset)).attr("target", "_blank").call(_t.append("info_panels.history.changeset_link"));
}
links.append("a").attr("class", "changeset-osmcha-link").attr("href", "https://osmcha.org/changesets/" + changeset).attr("target", "_blank").text("OSMCha");
links.append("a").attr("class", "changeset-achavi-link").attr("href", "https://overpass-api.de/achavi/?changeset=" + changeset).attr("target", "_blank").text("Achavi");
}
function redraw(selection2) {
var selectedNoteID = context.selectedNoteID();
osm = context.connection();
var selected, note, entity;
if (selectedNoteID && osm) {
selected = [_t.html("note.note") + " " + selectedNoteID];
note = osm.getNote(selectedNoteID);
} else {
selected = context.selectedIDs().filter(function(e) {
return context.hasEntity(e);
});
if (selected.length) {
entity = context.entity(selected[0]);
}
}
var singular = selected.length === 1 ? selected[0] : null;
selection2.html("");
if (singular) {
selection2.append("h4").attr("class", "history-heading").html(singular);
} else {
selection2.append("h4").attr("class", "history-heading").call(_t.append("info_panels.selected", { n: selected.length }));
}
if (!singular)
return;
if (entity) {
selection2.call(redrawEntity, entity);
} else if (note) {
selection2.call(redrawNote, note);
}
}
function redrawNote(selection2, note) {
if (!note || note.isNew()) {
selection2.append("div").call(_t.append("info_panels.history.note_no_history"));
return;
}
var list = selection2.append("ul");
list.append("li").call(_t.append("info_panels.history.note_comments", { suffix: ":" })).append("span").text(note.comments.length);
if (note.comments.length) {
list.append("li").call(_t.append("info_panels.history.note_created_date", { suffix: ":" })).append("span").text(displayTimestamp(note.comments[0].date));
list.append("li").call(_t.append("info_panels.history.note_created_user", { suffix: ":" })).call(displayUser, note.comments[0].user);
}
if (osm) {
selection2.append("a").attr("class", "view-history-on-osm").attr("target", "_blank").attr("href", osm.noteURL(note)).call(svgIcon("#iD-icon-out-link", "inline")).append("span").call(_t.append("info_panels.history.note_link_text"));
}
}
function redrawEntity(selection2, entity) {
if (!entity || entity.isNew()) {
selection2.append("div").call(_t.append("info_panels.history.no_history"));
return;
}
var links = selection2.append("div").attr("class", "links");
if (osm) {
links.append("a").attr("class", "view-history-on-osm").attr("href", osm.historyURL(entity)).attr("target", "_blank").call(_t.append("info_panels.history.history_link"));
}
links.append("a").attr("class", "pewu-history-viewer-link").attr("href", "https://pewu.github.io/osm-history/#/" + entity.type + "/" + entity.osmId()).attr("target", "_blank").attr("tabindex", -1).text("PeWu");
var list = selection2.append("ul");
list.append("li").call(_t.append("info_panels.history.version", { suffix: ":" })).append("span").text(entity.version);
list.append("li").call(_t.append("info_panels.history.last_edit", { suffix: ":" })).append("span").text(displayTimestamp(entity.timestamp));
list.append("li").call(_t.append("info_panels.history.edited_by", { suffix: ":" })).call(displayUser, entity.user);
list.append("li").call(_t.append("info_panels.history.changeset", { suffix: ":" })).call(displayChangeset, entity.changeset);
}
var panel = function(selection2) {
selection2.call(redraw);
context.map().on("drawn.info-history", function() {
selection2.call(redraw);
});
context.on("enter.info-history", function() {
selection2.call(redraw);
});
};
panel.off = function() {
context.map().on("drawn.info-history", null);
context.on("enter.info-history", null);
};
panel.id = "history";
panel.label = _t.html("info_panels.history.title");
panel.key = _t("info_panels.history.key");
return panel;
}
// modules/util/units.js
var OSM_PRECISION = 7;
function displayLength(m, isImperial) {
var d = m * (isImperial ? 3.28084 : 1);
var unit2;
if (isImperial) {
if (d >= 5280) {
d /= 5280;
unit2 = "miles";
} else {
unit2 = "feet";
}
} else {
if (d >= 1e3) {
d /= 1e3;
unit2 = "kilometers";
} else {
unit2 = "meters";
}
}
return _t("units." + unit2, {
quantity: d.toLocaleString(_mainLocalizer.localeCode(), {
maximumSignificantDigits: 4
})
});
}
function displayArea(m2, isImperial) {
var locale2 = _mainLocalizer.localeCode();
var d = m2 * (isImperial ? 10.7639111056 : 1);
var d1, d2, area;
var unit1 = "";
var unit2 = "";
if (isImperial) {
if (d >= 6969600) {
d1 = d / 27878400;
unit1 = "square_miles";
} else {
d1 = d;
unit1 = "square_feet";
}
if (d > 4356 && d < 4356e4) {
d2 = d / 43560;
unit2 = "acres";
}
} else {
if (d >= 25e4) {
d1 = d / 1e6;
unit1 = "square_kilometers";
} else {
d1 = d;
unit1 = "square_meters";
}
if (d > 1e3 && d < 1e7) {
d2 = d / 1e4;
unit2 = "hectares";
}
}
area = _t("units." + unit1, {
quantity: d1.toLocaleString(locale2, {
maximumSignificantDigits: 4
})
});
if (d2) {
return _t("units.area_pair", {
area1: area,
area2: _t("units." + unit2, {
quantity: d2.toLocaleString(locale2, {
maximumSignificantDigits: 2
})
})
});
} else {
return area;
}
}
function wrap(x, min3, max3) {
var d = max3 - min3;
return ((x - min3) % d + d) % d + min3;
}
function clamp2(x, min3, max3) {
return Math.max(min3, Math.min(x, max3));
}
function displayCoordinate(deg, pos, neg) {
var locale2 = _mainLocalizer.localeCode();
var min3 = (Math.abs(deg) - Math.floor(Math.abs(deg))) * 60;
var sec = (min3 - Math.floor(min3)) * 60;
var displayDegrees = _t("units.arcdegrees", {
quantity: Math.floor(Math.abs(deg)).toLocaleString(locale2)
});
var displayCoordinate2;
if (Math.floor(sec) > 0) {
displayCoordinate2 = displayDegrees + _t("units.arcminutes", {
quantity: Math.floor(min3).toLocaleString(locale2)
}) + _t("units.arcseconds", {
quantity: Math.round(sec).toLocaleString(locale2)
});
} else if (Math.floor(min3) > 0) {
displayCoordinate2 = displayDegrees + _t("units.arcminutes", {
quantity: Math.round(min3).toLocaleString(locale2)
});
} else {
displayCoordinate2 = _t("units.arcdegrees", {
quantity: Math.round(Math.abs(deg)).toLocaleString(locale2)
});
}
if (deg === 0) {
return displayCoordinate2;
} else {
return _t("units.coordinate", {
coordinate: displayCoordinate2,
direction: _t("units." + (deg > 0 ? pos : neg))
});
}
}
function dmsCoordinatePair(coord2) {
return _t("units.coordinate_pair", {
latitude: displayCoordinate(clamp2(coord2[1], -90, 90), "north", "south"),
longitude: displayCoordinate(wrap(coord2[0], -180, 180), "east", "west")
});
}
function decimalCoordinatePair(coord2) {
return _t("units.coordinate_pair", {
latitude: clamp2(coord2[1], -90, 90).toFixed(OSM_PRECISION),
longitude: wrap(coord2[0], -180, 180).toFixed(OSM_PRECISION)
});
}
// modules/ui/panels/location.js
function uiPanelLocation(context) {
var currLocation = "";
function redraw(selection2) {
selection2.html("");
var list = selection2.append("ul");
var coord2 = context.map().mouseCoordinates();
if (coord2.some(isNaN)) {
coord2 = context.map().center();
}
list.append("li").text(dmsCoordinatePair(coord2)).append("li").text(decimalCoordinatePair(coord2));
selection2.append("div").attr("class", "location-info").text(currLocation || " ");
debouncedGetLocation(selection2, coord2);
}
var debouncedGetLocation = debounce_default(getLocation, 250);
function getLocation(selection2, coord2) {
if (!services.geocoder) {
currLocation = _t("info_panels.location.unknown_location");
selection2.selectAll(".location-info").text(currLocation);
} else {
services.geocoder.reverse(coord2, function(err, result) {
currLocation = result ? result.display_name : _t("info_panels.location.unknown_location");
selection2.selectAll(".location-info").text(currLocation);
});
}
}
var panel = function(selection2) {
selection2.call(redraw);
context.surface().on(("PointerEvent" in window ? "pointer" : "mouse") + "move.info-location", function() {
selection2.call(redraw);
});
};
panel.off = function() {
context.surface().on(".info-location", null);
};
panel.id = "location";
panel.label = _t.html("info_panels.location.title");
panel.key = _t("info_panels.location.key");
return panel;
}
// modules/ui/panels/measurement.js
function uiPanelMeasurement(context) {
function radiansToMeters(r) {
return r * 63710071809e-4;
}
function steradiansToSqmeters(r) {
return r / (4 * Math.PI) * 510065621724e3;
}
function toLineString(feature3) {
if (feature3.type === "LineString")
return feature3;
var result = { type: "LineString", coordinates: [] };
if (feature3.type === "Polygon") {
result.coordinates = feature3.coordinates[0];
} else if (feature3.type === "MultiPolygon") {
result.coordinates = feature3.coordinates[0][0];
}
return result;
}
var _isImperial = !_mainLocalizer.usesMetric();
function redraw(selection2) {
var graph = context.graph();
var selectedNoteID = context.selectedNoteID();
var osm = services.osm;
var localeCode = _mainLocalizer.localeCode();
var heading;
var center, location, centroid;
var closed, geometry;
var totalNodeCount, length = 0, area = 0, distance;
if (selectedNoteID && osm) {
var note = osm.getNote(selectedNoteID);
heading = _t.html("note.note") + " " + selectedNoteID;
location = note.loc;
geometry = "note";
} else {
var selectedIDs = context.selectedIDs().filter(function(id2) {
return context.hasEntity(id2);
});
var selected = selectedIDs.map(function(id2) {
return context.entity(id2);
});
heading = selected.length === 1 ? selected[0].id : _t.html("info_panels.selected", { n: selected.length });
if (selected.length) {
var extent = geoExtent();
for (var i2 in selected) {
var entity = selected[i2];
extent._extend(entity.extent(graph));
geometry = entity.geometry(graph);
if (geometry === "line" || geometry === "area") {
closed = entity.type === "relation" || entity.isClosed() && !entity.isDegenerate();
var feature3 = entity.asGeoJSON(graph);
length += radiansToMeters(length_default(toLineString(feature3)));
centroid = path_default(context.projection).centroid(entity.asGeoJSON(graph));
centroid = centroid && context.projection.invert(centroid);
if (!centroid || !isFinite(centroid[0]) || !isFinite(centroid[1])) {
centroid = entity.extent(graph).center();
}
if (closed) {
area += steradiansToSqmeters(entity.area(graph));
}
}
}
if (selected.length > 1) {
geometry = null;
closed = null;
centroid = null;
}
if (selected.length === 2 && selected[0].type === "node" && selected[1].type === "node") {
distance = geoSphericalDistance(selected[0].loc, selected[1].loc);
}
if (selected.length === 1 && selected[0].type === "node") {
location = selected[0].loc;
} else {
totalNodeCount = utilGetAllNodes(selectedIDs, context.graph()).length;
}
if (!location && !centroid) {
center = extent.center();
}
}
}
selection2.html("");
if (heading) {
selection2.append("h4").attr("class", "measurement-heading").html(heading);
}
var list = selection2.append("ul");
var coordItem;
if (geometry) {
list.append("li").call(_t.append("info_panels.measurement.geometry", { suffix: ":" })).append("span").html(closed ? _t.html("info_panels.measurement.closed_" + geometry) : _t.html("geometry." + geometry));
}
if (totalNodeCount) {
list.append("li").call(_t.append("info_panels.measurement.node_count", { suffix: ":" })).append("span").text(totalNodeCount.toLocaleString(localeCode));
}
if (area) {
list.append("li").call(_t.append("info_panels.measurement.area", { suffix: ":" })).append("span").text(displayArea(area, _isImperial));
}
if (length) {
list.append("li").call(_t.append("info_panels.measurement." + (closed ? "perimeter" : "length"), { suffix: ":" })).append("span").text(displayLength(length, _isImperial));
}
if (typeof distance === "number") {
list.append("li").call(_t.append("info_panels.measurement.distance", { suffix: ":" })).append("span").text(displayLength(distance, _isImperial));
}
if (location) {
coordItem = list.append("li").call(_t.append("info_panels.measurement.location", { suffix: ":" }));
coordItem.append("span").text(dmsCoordinatePair(location));
coordItem.append("span").text(decimalCoordinatePair(location));
}
if (centroid) {
coordItem = list.append("li").call(_t.append("info_panels.measurement.centroid", { suffix: ":" }));
coordItem.append("span").text(dmsCoordinatePair(centroid));
coordItem.append("span").text(decimalCoordinatePair(centroid));
}
if (center) {
coordItem = list.append("li").call(_t.append("info_panels.measurement.center", { suffix: ":" }));
coordItem.append("span").text(dmsCoordinatePair(center));
coordItem.append("span").text(decimalCoordinatePair(center));
}
if (length || area || typeof distance === "number") {
var toggle = _isImperial ? "imperial" : "metric";
selection2.append("a").call(_t.append("info_panels.measurement." + toggle)).attr("href", "#").attr("class", "button button-toggle-units").on("click", function(d3_event) {
d3_event.preventDefault();
_isImperial = !_isImperial;
selection2.call(redraw);
});
}
}
var panel = function(selection2) {
selection2.call(redraw);
context.map().on("drawn.info-measurement", function() {
selection2.call(redraw);
});
context.on("enter.info-measurement", function() {
selection2.call(redraw);
});
};
panel.off = function() {
context.map().on("drawn.info-measurement", null);
context.on("enter.info-measurement", null);
};
panel.id = "measurement";
panel.label = _t.html("info_panels.measurement.title");
panel.key = _t("info_panels.measurement.key");
return panel;
}
// modules/ui/panels/index.js
var uiInfoPanels = {
background: uiPanelBackground,
history: uiPanelHistory,
location: uiPanelLocation,
measurement: uiPanelMeasurement
};
// modules/ui/info.js
function uiInfo(context) {
var ids = Object.keys(uiInfoPanels);
var wasActive = ["measurement"];
var panels = {};
var active = {};
ids.forEach(function(k) {
if (!panels[k]) {
panels[k] = uiInfoPanels[k](context);
active[k] = false;
}
});
function info(selection2) {
function redraw() {
var activeids = ids.filter(function(k) {
return active[k];
}).sort();
var containers = infoPanels.selectAll(".panel-container").data(activeids, function(k) {
return k;
});
containers.exit().style("opacity", 1).transition().duration(200).style("opacity", 0).on("end", function(d) {
select_default2(this).call(panels[d].off).remove();
});
var enter = containers.enter().append("div").attr("class", function(d) {
return "fillD2 panel-container panel-container-" + d;
});
enter.style("opacity", 0).transition().duration(200).style("opacity", 1);
var title = enter.append("div").attr("class", "panel-title fillD2");
title.append("h3").html(function(d) {
return panels[d].label;
});
title.append("button").attr("class", "close").attr("title", _t("icons.close")).on("click", function(d3_event, d) {
d3_event.stopImmediatePropagation();
d3_event.preventDefault();
info.toggle(d);
}).call(svgIcon("#iD-icon-close"));
enter.append("div").attr("class", function(d) {
return "panel-content panel-content-" + d;
});
infoPanels.selectAll(".panel-content").each(function(d) {
select_default2(this).call(panels[d]);
});
}
info.toggle = function(which) {
var activeids = ids.filter(function(k) {
return active[k];
});
if (which) {
active[which] = !active[which];
if (activeids.length === 1 && activeids[0] === which) {
wasActive = [which];
}
context.container().select("." + which + "-panel-toggle-item").classed("active", active[which]).select("input").property("checked", active[which]);
} else {
if (activeids.length) {
wasActive = activeids;
activeids.forEach(function(k) {
active[k] = false;
});
} else {
wasActive.forEach(function(k) {
active[k] = true;
});
}
}
redraw();
};
var infoPanels = selection2.selectAll(".info-panels").data([0]);
infoPanels = infoPanels.enter().append("div").attr("class", "info-panels").merge(infoPanels);
redraw();
context.keybinding().on(uiCmd("\u2318" + _t("info_panels.key")), function(d3_event) {
d3_event.stopImmediatePropagation();
d3_event.preventDefault();
info.toggle();
});
ids.forEach(function(k) {
var key = _t("info_panels." + k + ".key", { default: null });
if (!key)
return;
context.keybinding().on(uiCmd("\u2318\u21E7" + key), function(d3_event) {
d3_event.stopImmediatePropagation();
d3_event.preventDefault();
info.toggle(k);
});
});
}
return info;
}
// modules/ui/intro/helper.js
function pointBox(loc, context) {
var rect = context.surfaceRect();
var point = context.curtainProjection(loc);
return {
left: point[0] + rect.left - 40,
top: point[1] + rect.top - 60,
width: 80,
height: 90
};
}
function pad(locOrBox, padding, context) {
var box;
if (locOrBox instanceof Array) {
var rect = context.surfaceRect();
var point = context.curtainProjection(locOrBox);
box = {
left: point[0] + rect.left,
top: point[1] + rect.top
};
} else {
box = locOrBox;
}
return {
left: box.left - padding,
top: box.top - padding,
width: (box.width || 0) + 2 * padding,
height: (box.width || 0) + 2 * padding
};
}
function icon(name2, svgklass, useklass) {
return '";
}
var helpStringReplacements;
function helpHtml(id2, replacements) {
if (!helpStringReplacements) {
helpStringReplacements = {
point_icon: icon("#iD-icon-point", "inline"),
line_icon: icon("#iD-icon-line", "inline"),
area_icon: icon("#iD-icon-area", "inline"),
note_icon: icon("#iD-icon-note", "inline add-note"),
plus: icon("#iD-icon-plus", "inline"),
minus: icon("#iD-icon-minus", "inline"),
layers_icon: icon("#iD-icon-layers", "inline"),
data_icon: icon("#iD-icon-data", "inline"),
inspect: icon("#iD-icon-inspect", "inline"),
help_icon: icon("#iD-icon-help", "inline"),
undo_icon: icon(_mainLocalizer.textDirection() === "rtl" ? "#iD-icon-redo" : "#iD-icon-undo", "inline"),
redo_icon: icon(_mainLocalizer.textDirection() === "rtl" ? "#iD-icon-undo" : "#iD-icon-redo", "inline"),
save_icon: icon("#iD-icon-save", "inline"),
circularize_icon: icon("#iD-operation-circularize", "inline operation"),
continue_icon: icon("#iD-operation-continue", "inline operation"),
copy_icon: icon("#iD-operation-copy", "inline operation"),
delete_icon: icon("#iD-operation-delete", "inline operation"),
disconnect_icon: icon("#iD-operation-disconnect", "inline operation"),
downgrade_icon: icon("#iD-operation-downgrade", "inline operation"),
extract_icon: icon("#iD-operation-extract", "inline operation"),
merge_icon: icon("#iD-operation-merge", "inline operation"),
move_icon: icon("#iD-operation-move", "inline operation"),
orthogonalize_icon: icon("#iD-operation-orthogonalize", "inline operation"),
paste_icon: icon("#iD-operation-paste", "inline operation"),
reflect_long_icon: icon("#iD-operation-reflect-long", "inline operation"),
reflect_short_icon: icon("#iD-operation-reflect-short", "inline operation"),
reverse_icon: icon("#iD-operation-reverse", "inline operation"),
rotate_icon: icon("#iD-operation-rotate", "inline operation"),
split_icon: icon("#iD-operation-split", "inline operation"),
straighten_icon: icon("#iD-operation-straighten", "inline operation"),
leftclick: icon("#iD-walkthrough-mouse-left", "inline operation"),
rightclick: icon("#iD-walkthrough-mouse-right", "inline operation"),
mousewheel_icon: icon("#iD-walkthrough-mousewheel", "inline operation"),
tap_icon: icon("#iD-walkthrough-tap", "inline operation"),
doubletap_icon: icon("#iD-walkthrough-doubletap", "inline operation"),
longpress_icon: icon("#iD-walkthrough-longpress", "inline operation"),
touchdrag_icon: icon("#iD-walkthrough-touchdrag", "inline operation"),
pinch_icon: icon("#iD-walkthrough-pinch-apart", "inline operation"),
shift: uiCmd.display("\u21E7"),
alt: uiCmd.display("\u2325"),
return: uiCmd.display("\u21B5"),
esc: _t.html("shortcuts.key.esc"),
space: _t.html("shortcuts.key.space"),
add_note_key: _t.html("modes.add_note.key"),
help_key: _t.html("help.key"),
shortcuts_key: _t.html("shortcuts.toggle.key"),
save: _t.html("save.title"),
undo: _t.html("undo.title"),
redo: _t.html("redo.title"),
upload: _t.html("commit.save"),
point: _t.html("modes.add_point.title"),
line: _t.html("modes.add_line.title"),
area: _t.html("modes.add_area.title"),
note: _t.html("modes.add_note.label"),
circularize: _t.html("operations.circularize.title"),
continue: _t.html("operations.continue.title"),
copy: _t.html("operations.copy.title"),
delete: _t.html("operations.delete.title"),
disconnect: _t.html("operations.disconnect.title"),
downgrade: _t.html("operations.downgrade.title"),
extract: _t.html("operations.extract.title"),
merge: _t.html("operations.merge.title"),
move: _t.html("operations.move.title"),
orthogonalize: _t.html("operations.orthogonalize.title"),
paste: _t.html("operations.paste.title"),
reflect_long: _t.html("operations.reflect.title.long"),
reflect_short: _t.html("operations.reflect.title.short"),
reverse: _t.html("operations.reverse.title"),
rotate: _t.html("operations.rotate.title"),
split: _t.html("operations.split.title"),
straighten: _t.html("operations.straighten.title"),
map_data: _t.html("map_data.title"),
osm_notes: _t.html("map_data.layers.notes.title"),
fields: _t.html("inspector.fields"),
tags: _t.html("inspector.tags"),
relations: _t.html("inspector.relations"),
new_relation: _t.html("inspector.new_relation"),
turn_restrictions: _t.html("_tagging.presets.fields.restrictions.label"),
background_settings: _t.html("background.description"),
imagery_offset: _t.html("background.fix_misalignment"),
start_the_walkthrough: _t.html("splash.walkthrough"),
help: _t.html("help.title"),
ok: _t.html("intro.ok")
};
for (var key in helpStringReplacements) {
helpStringReplacements[key] = { html: helpStringReplacements[key] };
}
}
var reps;
if (replacements) {
reps = Object.assign(replacements, helpStringReplacements);
} else {
reps = helpStringReplacements;
}
return _t.html(id2, reps).replace(/\`(.*?)\`/g, "$1");
}
function slugify(text2) {
return text2.toString().toLowerCase().replace(/\s+/g, "-").replace(/[^\w\-]+/g, "").replace(/\-\-+/g, "-").replace(/^-+/, "").replace(/-+$/, "");
}
var missingStrings = {};
function checkKey(key, text2) {
if (_t(key, { default: void 0 }) === void 0) {
if (missingStrings.hasOwnProperty(key))
return;
missingStrings[key] = text2;
var missing = key + ": " + text2;
if (typeof console !== "undefined")
console.log(missing);
}
}
function localize(obj) {
var key;
var name2 = obj.tags && obj.tags.name;
if (name2) {
key = "intro.graph.name." + slugify(name2);
obj.tags.name = _t(key, { default: name2 });
checkKey(key, name2);
}
var street = obj.tags && obj.tags["addr:street"];
if (street) {
key = "intro.graph.name." + slugify(street);
obj.tags["addr:street"] = _t(key, { default: street });
checkKey(key, street);
var addrTags = [
"block_number",
"city",
"county",
"district",
"hamlet",
"neighbourhood",
"postcode",
"province",
"quarter",
"state",
"subdistrict",
"suburb"
];
addrTags.forEach(function(k) {
var key2 = "intro.graph." + k;
var tag = "addr:" + k;
var val = obj.tags && obj.tags[tag];
var str2 = _t(key2, { default: val });
if (str2) {
if (str2.match(/^<.*>$/) !== null) {
delete obj.tags[tag];
} else {
obj.tags[tag] = str2;
}
}
});
}
return obj;
}
function isMostlySquare(points) {
var threshold = 15;
var lowerBound = Math.cos((90 - threshold) * Math.PI / 180);
var upperBound = Math.cos(threshold * Math.PI / 180);
for (var i2 = 0; i2 < points.length; i2++) {
var a = points[(i2 - 1 + points.length) % points.length];
var origin = points[i2];
var b = points[(i2 + 1) % points.length];
var dotp = geoVecNormalizedDot(a, b, origin);
var mag = Math.abs(dotp);
if (mag > lowerBound && mag < upperBound) {
return false;
}
}
return true;
}
function selectMenuItem(context, operation) {
return context.container().select(".edit-menu .edit-menu-item-" + operation);
}
function transitionTime(point1, point2) {
var distance = geoSphericalDistance(point1, point2);
if (distance === 0) {
return 0;
} else if (distance < 80) {
return 500;
} else {
return 1e3;
}
}
// modules/ui/toggle.js
function uiToggle(show, callback) {
return function(selection2) {
selection2.style("opacity", show ? 0 : 1).classed("hide", false).transition().style("opacity", show ? 1 : 0).on("end", function() {
select_default2(this).classed("hide", !show).style("opacity", null);
if (callback)
callback.apply(this);
});
};
}
// modules/ui/curtain.js
function uiCurtain(containerNode) {
var surface = select_default2(null), tooltip = select_default2(null), darkness = select_default2(null);
function curtain(selection2) {
surface = selection2.append("svg").attr("class", "curtain").style("top", 0).style("left", 0);
darkness = surface.append("path").attr("x", 0).attr("y", 0).attr("class", "curtain-darkness");
select_default2(window).on("resize.curtain", resize);
tooltip = selection2.append("div").attr("class", "tooltip");
tooltip.append("div").attr("class", "popover-arrow");
tooltip.append("div").attr("class", "popover-inner");
resize();
function resize() {
surface.attr("width", containerNode.clientWidth).attr("height", containerNode.clientHeight);
curtain.cut(darkness.datum());
}
}
curtain.reveal = function(box, html2, options2) {
options2 = options2 || {};
if (typeof box === "string") {
box = select_default2(box).node();
}
if (box && box.getBoundingClientRect) {
box = copyBox(box.getBoundingClientRect());
var containerRect = containerNode.getBoundingClientRect();
box.top -= containerRect.top;
box.left -= containerRect.left;
}
if (box && options2.padding) {
box.top -= options2.padding;
box.left -= options2.padding;
box.bottom += options2.padding;
box.right += options2.padding;
box.height += options2.padding * 2;
box.width += options2.padding * 2;
}
var tooltipBox;
if (options2.tooltipBox) {
tooltipBox = options2.tooltipBox;
if (typeof tooltipBox === "string") {
tooltipBox = select_default2(tooltipBox).node();
}
if (tooltipBox && tooltipBox.getBoundingClientRect) {
tooltipBox = copyBox(tooltipBox.getBoundingClientRect());
}
} else {
tooltipBox = box;
}
if (tooltipBox && html2) {
if (html2.indexOf("**") !== -1) {
if (html2.indexOf(")(.+?)(\*\*)/, "$1$2$3");
} else {
html2 = html2.replace(/^(.+?)(\*\*)/, "$1$2");
}
html2 = html2.replace(/\*\*(.*?)\*\*/g, '$1');
}
html2 = html2.replace(/\*(.*?)\*/g, "$1");
html2 = html2.replace(/\{br\}/g, "
");
if (options2.buttonText && options2.buttonCallback) {
html2 += '";
}
var classes = "curtain-tooltip popover tooltip arrowed in " + (options2.tooltipClass || "");
tooltip.classed(classes, true).selectAll(".popover-inner").html(html2);
if (options2.buttonText && options2.buttonCallback) {
var button = tooltip.selectAll(".button-section .button.action");
button.on("click", function(d3_event) {
d3_event.preventDefault();
options2.buttonCallback();
});
}
var tip = copyBox(tooltip.node().getBoundingClientRect()), w = containerNode.clientWidth, h = containerNode.clientHeight, tooltipWidth = 200, tooltipArrow = 5, side, pos;
if (options2.tooltipClass === "intro-mouse") {
tip.height += 80;
}
if (tooltipBox.top + tooltipBox.height > h) {
tooltipBox.height -= tooltipBox.top + tooltipBox.height - h;
}
if (tooltipBox.left + tooltipBox.width > w) {
tooltipBox.width -= tooltipBox.left + tooltipBox.width - w;
}
if (tooltipBox.top + tooltipBox.height < 100) {
side = "bottom";
pos = [
tooltipBox.left + tooltipBox.width / 2 - tip.width / 2,
tooltipBox.top + tooltipBox.height
];
} else if (tooltipBox.top > h - 140) {
side = "top";
pos = [
tooltipBox.left + tooltipBox.width / 2 - tip.width / 2,
tooltipBox.top - tip.height
];
} else {
var tipY = tooltipBox.top + tooltipBox.height / 2 - tip.height / 2;
if (_mainLocalizer.textDirection() === "rtl") {
if (tooltipBox.left - tooltipWidth - tooltipArrow < 70) {
side = "right";
pos = [tooltipBox.left + tooltipBox.width + tooltipArrow, tipY];
} else {
side = "left";
pos = [tooltipBox.left - tooltipWidth - tooltipArrow, tipY];
}
} else {
if (tooltipBox.left + tooltipBox.width + tooltipArrow + tooltipWidth > w - 70) {
side = "left";
pos = [tooltipBox.left - tooltipWidth - tooltipArrow, tipY];
} else {
side = "right";
pos = [tooltipBox.left + tooltipBox.width + tooltipArrow, tipY];
}
}
}
if (options2.duration !== 0 || !tooltip.classed(side)) {
tooltip.call(uiToggle(true));
}
tooltip.style("top", pos[1] + "px").style("left", pos[0] + "px").attr("class", classes + " " + side);
var shiftY = 0;
if (side === "left" || side === "right") {
if (pos[1] < 60) {
shiftY = 60 - pos[1];
} else if (pos[1] + tip.height > h - 100) {
shiftY = h - pos[1] - tip.height - 100;
}
}
tooltip.selectAll(".popover-inner").style("top", shiftY + "px");
} else {
tooltip.classed("in", false).call(uiToggle(false));
}
curtain.cut(box, options2.duration);
return tooltip;
};
curtain.cut = function(datum2, duration) {
darkness.datum(datum2).interrupt();
var selection2;
if (duration === 0) {
selection2 = darkness;
} else {
selection2 = darkness.transition().duration(duration || 600).ease(linear2);
}
selection2.attr("d", function(d) {
var containerWidth = containerNode.clientWidth;
var containerHeight = containerNode.clientHeight;
var string = "M 0,0 L 0," + containerHeight + " L " + containerWidth + "," + containerHeight + "L" + containerWidth + ",0 Z";
if (!d)
return string;
return string + "M" + d.left + "," + d.top + "L" + d.left + "," + (d.top + d.height) + "L" + (d.left + d.width) + "," + (d.top + d.height) + "L" + (d.left + d.width) + "," + d.top + "Z";
});
};
curtain.remove = function() {
surface.remove();
tooltip.remove();
select_default2(window).on("resize.curtain", null);
};
function copyBox(src) {
return {
top: src.top,
right: src.right,
bottom: src.bottom,
left: src.left,
width: src.width,
height: src.height
};
}
return curtain;
}
// modules/ui/intro/welcome.js
function uiIntroWelcome(context, reveal) {
var dispatch10 = dispatch_default("done");
var chapter = {
title: "intro.welcome.title"
};
function welcome() {
context.map().centerZoom([-85.63591, 41.94285], 19);
reveal(".intro-nav-wrap .chapter-welcome", helpHtml("intro.welcome.welcome"), { buttonText: _t.html("intro.ok"), buttonCallback: practice });
}
function practice() {
reveal(".intro-nav-wrap .chapter-welcome", helpHtml("intro.welcome.practice"), { buttonText: _t.html("intro.ok"), buttonCallback: words });
}
function words() {
reveal(".intro-nav-wrap .chapter-welcome", helpHtml("intro.welcome.words"), { buttonText: _t.html("intro.ok"), buttonCallback: chapters });
}
function chapters() {
dispatch10.call("done");
reveal(".intro-nav-wrap .chapter-navigation", helpHtml("intro.welcome.chapters", { next: _t("intro.navigation.title") }));
}
chapter.enter = function() {
welcome();
};
chapter.exit = function() {
context.container().select(".curtain-tooltip.intro-mouse").selectAll(".counter").remove();
};
chapter.restart = function() {
chapter.exit();
chapter.enter();
};
return utilRebind(chapter, dispatch10, "on");
}
// modules/ui/intro/navigation.js
function uiIntroNavigation(context, reveal) {
var dispatch10 = dispatch_default("done");
var timeouts = [];
var hallId = "n2061";
var townHall = [-85.63591, 41.94285];
var springStreetId = "w397";
var springStreetEndId = "n1834";
var springStreet = [-85.63582, 41.94255];
var onewayField = _mainPresetIndex.field("oneway");
var maxspeedField = _mainPresetIndex.field("maxspeed");
var chapter = {
title: "intro.navigation.title"
};
function timeout2(f2, t) {
timeouts.push(window.setTimeout(f2, t));
}
function eventCancel(d3_event) {
d3_event.stopPropagation();
d3_event.preventDefault();
}
function isTownHallSelected() {
var ids = context.selectedIDs();
return ids.length === 1 && ids[0] === hallId;
}
function dragMap() {
context.enter(modeBrowse(context));
context.history().reset("initial");
var msec = transitionTime(townHall, context.map().center());
if (msec) {
reveal(null, null, { duration: 0 });
}
context.map().centerZoomEase(townHall, 19, msec);
timeout2(function() {
var centerStart = context.map().center();
var textId = context.lastPointerType() === "mouse" ? "drag" : "drag_touch";
var dragString = helpHtml("intro.navigation.map_info") + "{br}" + helpHtml("intro.navigation." + textId);
reveal(".surface", dragString);
context.map().on("drawn.intro", function() {
reveal(".surface", dragString, { duration: 0 });
});
context.map().on("move.intro", function() {
var centerNow = context.map().center();
if (centerStart[0] !== centerNow[0] || centerStart[1] !== centerNow[1]) {
context.map().on("move.intro", null);
timeout2(function() {
continueTo(zoomMap);
}, 3e3);
}
});
}, msec + 100);
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
nextStep();
}
}
function zoomMap() {
var zoomStart = context.map().zoom();
var textId = context.lastPointerType() === "mouse" ? "zoom" : "zoom_touch";
var zoomString = helpHtml("intro.navigation." + textId);
reveal(".surface", zoomString);
context.map().on("drawn.intro", function() {
reveal(".surface", zoomString, { duration: 0 });
});
context.map().on("move.intro", function() {
if (context.map().zoom() !== zoomStart) {
context.map().on("move.intro", null);
timeout2(function() {
continueTo(features2);
}, 3e3);
}
});
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
nextStep();
}
}
function features2() {
var onClick = function() {
continueTo(pointsLinesAreas);
};
reveal(".surface", helpHtml("intro.navigation.features"), { buttonText: _t.html("intro.ok"), buttonCallback: onClick });
context.map().on("drawn.intro", function() {
reveal(".surface", helpHtml("intro.navigation.features"), { duration: 0, buttonText: _t.html("intro.ok"), buttonCallback: onClick });
});
function continueTo(nextStep) {
context.map().on("drawn.intro", null);
nextStep();
}
}
function pointsLinesAreas() {
var onClick = function() {
continueTo(nodesWays);
};
reveal(".surface", helpHtml("intro.navigation.points_lines_areas"), { buttonText: _t.html("intro.ok"), buttonCallback: onClick });
context.map().on("drawn.intro", function() {
reveal(".surface", helpHtml("intro.navigation.points_lines_areas"), { duration: 0, buttonText: _t.html("intro.ok"), buttonCallback: onClick });
});
function continueTo(nextStep) {
context.map().on("drawn.intro", null);
nextStep();
}
}
function nodesWays() {
var onClick = function() {
continueTo(clickTownHall);
};
reveal(".surface", helpHtml("intro.navigation.nodes_ways"), { buttonText: _t.html("intro.ok"), buttonCallback: onClick });
context.map().on("drawn.intro", function() {
reveal(".surface", helpHtml("intro.navigation.nodes_ways"), { duration: 0, buttonText: _t.html("intro.ok"), buttonCallback: onClick });
});
function continueTo(nextStep) {
context.map().on("drawn.intro", null);
nextStep();
}
}
function clickTownHall() {
context.enter(modeBrowse(context));
context.history().reset("initial");
var entity = context.hasEntity(hallId);
if (!entity)
return;
reveal(null, null, { duration: 0 });
context.map().centerZoomEase(entity.loc, 19, 500);
timeout2(function() {
var entity2 = context.hasEntity(hallId);
if (!entity2)
return;
var box = pointBox(entity2.loc, context);
var textId = context.lastPointerType() === "mouse" ? "click_townhall" : "tap_townhall";
reveal(box, helpHtml("intro.navigation." + textId));
context.map().on("move.intro drawn.intro", function() {
var entity3 = context.hasEntity(hallId);
if (!entity3)
return;
var box2 = pointBox(entity3.loc, context);
reveal(box2, helpHtml("intro.navigation." + textId), { duration: 0 });
});
context.on("enter.intro", function() {
if (isTownHallSelected())
continueTo(selectedTownHall);
});
}, 550);
context.history().on("change.intro", function() {
if (!context.hasEntity(hallId)) {
continueTo(clickTownHall);
}
});
function continueTo(nextStep) {
context.on("enter.intro", null);
context.map().on("move.intro drawn.intro", null);
context.history().on("change.intro", null);
nextStep();
}
}
function selectedTownHall() {
if (!isTownHallSelected())
return clickTownHall();
var entity = context.hasEntity(hallId);
if (!entity)
return clickTownHall();
var box = pointBox(entity.loc, context);
var onClick = function() {
continueTo(editorTownHall);
};
reveal(box, helpHtml("intro.navigation.selected_townhall"), { buttonText: _t.html("intro.ok"), buttonCallback: onClick });
context.map().on("move.intro drawn.intro", function() {
var entity2 = context.hasEntity(hallId);
if (!entity2)
return;
var box2 = pointBox(entity2.loc, context);
reveal(box2, helpHtml("intro.navigation.selected_townhall"), { duration: 0, buttonText: _t.html("intro.ok"), buttonCallback: onClick });
});
context.history().on("change.intro", function() {
if (!context.hasEntity(hallId)) {
continueTo(clickTownHall);
}
});
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
context.history().on("change.intro", null);
nextStep();
}
}
function editorTownHall() {
if (!isTownHallSelected())
return clickTownHall();
context.container().select(".inspector-wrap").on("wheel.intro", eventCancel);
var onClick = function() {
continueTo(presetTownHall);
};
reveal(".entity-editor-pane", helpHtml("intro.navigation.editor_townhall"), { buttonText: _t.html("intro.ok"), buttonCallback: onClick });
context.on("exit.intro", function() {
continueTo(clickTownHall);
});
context.history().on("change.intro", function() {
if (!context.hasEntity(hallId)) {
continueTo(clickTownHall);
}
});
function continueTo(nextStep) {
context.on("exit.intro", null);
context.history().on("change.intro", null);
context.container().select(".inspector-wrap").on("wheel.intro", null);
nextStep();
}
}
function presetTownHall() {
if (!isTownHallSelected())
return clickTownHall();
context.container().select(".inspector-wrap .panewrap").style("right", "0%");
context.container().select(".inspector-wrap").on("wheel.intro", eventCancel);
var entity = context.entity(context.selectedIDs()[0]);
var preset = _mainPresetIndex.match(entity, context.graph());
var onClick = function() {
continueTo(fieldsTownHall);
};
reveal(".entity-editor-pane .section-feature-type", helpHtml("intro.navigation.preset_townhall", { preset: preset.name() }), { buttonText: _t.html("intro.ok"), buttonCallback: onClick });
context.on("exit.intro", function() {
continueTo(clickTownHall);
});
context.history().on("change.intro", function() {
if (!context.hasEntity(hallId)) {
continueTo(clickTownHall);
}
});
function continueTo(nextStep) {
context.on("exit.intro", null);
context.history().on("change.intro", null);
context.container().select(".inspector-wrap").on("wheel.intro", null);
nextStep();
}
}
function fieldsTownHall() {
if (!isTownHallSelected())
return clickTownHall();
context.container().select(".inspector-wrap .panewrap").style("right", "0%");
context.container().select(".inspector-wrap").on("wheel.intro", eventCancel);
var onClick = function() {
continueTo(closeTownHall);
};
reveal(".entity-editor-pane .section-preset-fields", helpHtml("intro.navigation.fields_townhall"), { buttonText: _t.html("intro.ok"), buttonCallback: onClick });
context.on("exit.intro", function() {
continueTo(clickTownHall);
});
context.history().on("change.intro", function() {
if (!context.hasEntity(hallId)) {
continueTo(clickTownHall);
}
});
function continueTo(nextStep) {
context.on("exit.intro", null);
context.history().on("change.intro", null);
context.container().select(".inspector-wrap").on("wheel.intro", null);
nextStep();
}
}
function closeTownHall() {
if (!isTownHallSelected())
return clickTownHall();
var selector = ".entity-editor-pane button.close svg use";
var href = select_default2(selector).attr("href") || "#iD-icon-close";
reveal(".entity-editor-pane", helpHtml("intro.navigation.close_townhall", { button: { html: icon(href, "inline") } }));
context.on("exit.intro", function() {
continueTo(searchStreet);
});
context.history().on("change.intro", function() {
var selector2 = ".entity-editor-pane button.close svg use";
var href2 = select_default2(selector2).attr("href") || "#iD-icon-close";
reveal(".entity-editor-pane", helpHtml("intro.navigation.close_townhall", { button: { html: icon(href2, "inline") } }), { duration: 0 });
});
function continueTo(nextStep) {
context.on("exit.intro", null);
context.history().on("change.intro", null);
nextStep();
}
}
function searchStreet() {
context.enter(modeBrowse(context));
context.history().reset("initial");
var msec = transitionTime(springStreet, context.map().center());
if (msec) {
reveal(null, null, { duration: 0 });
}
context.map().centerZoomEase(springStreet, 19, msec);
timeout2(function() {
reveal(".search-header input", helpHtml("intro.navigation.search_street", { name: _t("intro.graph.name.spring-street") }));
context.container().select(".search-header input").on("keyup.intro", checkSearchResult);
}, msec + 100);
}
function checkSearchResult() {
var first = context.container().select(".feature-list-item:nth-child(0n+2)");
var firstName = first.select(".entity-name");
var name2 = _t("intro.graph.name.spring-street");
if (!firstName.empty() && firstName.html() === name2) {
reveal(first.node(), helpHtml("intro.navigation.choose_street", { name: name2 }), { duration: 300 });
context.on("exit.intro", function() {
continueTo(selectedStreet);
});
context.container().select(".search-header input").on("keydown.intro", eventCancel, true).on("keyup.intro", null);
}
function continueTo(nextStep) {
context.on("exit.intro", null);
context.container().select(".search-header input").on("keydown.intro", null).on("keyup.intro", null);
nextStep();
}
}
function selectedStreet() {
if (!context.hasEntity(springStreetEndId) || !context.hasEntity(springStreetId)) {
return searchStreet();
}
var onClick = function() {
continueTo(editorStreet);
};
var entity = context.entity(springStreetEndId);
var box = pointBox(entity.loc, context);
box.height = 500;
reveal(box, helpHtml("intro.navigation.selected_street", { name: _t("intro.graph.name.spring-street") }), { duration: 600, buttonText: _t.html("intro.ok"), buttonCallback: onClick });
timeout2(function() {
context.map().on("move.intro drawn.intro", function() {
var entity2 = context.hasEntity(springStreetEndId);
if (!entity2)
return;
var box2 = pointBox(entity2.loc, context);
box2.height = 500;
reveal(box2, helpHtml("intro.navigation.selected_street", { name: _t("intro.graph.name.spring-street") }), { duration: 0, buttonText: _t.html("intro.ok"), buttonCallback: onClick });
});
}, 600);
context.on("enter.intro", function(mode) {
if (!context.hasEntity(springStreetId)) {
return continueTo(searchStreet);
}
var ids = context.selectedIDs();
if (mode.id !== "select" || !ids.length || ids[0] !== springStreetId) {
context.enter(modeSelect(context, [springStreetId]));
}
});
context.history().on("change.intro", function() {
if (!context.hasEntity(springStreetEndId) || !context.hasEntity(springStreetId)) {
timeout2(function() {
continueTo(searchStreet);
}, 300);
}
});
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
context.on("enter.intro", null);
context.history().on("change.intro", null);
nextStep();
}
}
function editorStreet() {
var selector = ".entity-editor-pane button.close svg use";
var href = select_default2(selector).attr("href") || "#iD-icon-close";
reveal(".entity-editor-pane", helpHtml("intro.navigation.street_different_fields") + "{br}" + helpHtml("intro.navigation.editor_street", {
button: { html: icon(href, "inline") },
field1: { html: onewayField.label() },
field2: { html: maxspeedField.label() }
}));
context.on("exit.intro", function() {
continueTo(play);
});
context.history().on("change.intro", function() {
var selector2 = ".entity-editor-pane button.close svg use";
var href2 = select_default2(selector2).attr("href") || "#iD-icon-close";
reveal(".entity-editor-pane", helpHtml("intro.navigation.street_different_fields") + "{br}" + helpHtml("intro.navigation.editor_street", {
button: { html: icon(href2, "inline") },
field1: { html: onewayField.label() },
field2: { html: maxspeedField.label() }
}), { duration: 0 });
});
function continueTo(nextStep) {
context.on("exit.intro", null);
context.history().on("change.intro", null);
nextStep();
}
}
function play() {
dispatch10.call("done");
reveal(".ideditor", helpHtml("intro.navigation.play", { next: _t("intro.points.title") }), {
tooltipBox: ".intro-nav-wrap .chapter-point",
buttonText: _t.html("intro.ok"),
buttonCallback: function() {
reveal(".ideditor");
}
});
}
chapter.enter = function() {
dragMap();
};
chapter.exit = function() {
timeouts.forEach(window.clearTimeout);
context.on("enter.intro exit.intro", null);
context.map().on("move.intro drawn.intro", null);
context.history().on("change.intro", null);
context.container().select(".inspector-wrap").on("wheel.intro", null);
context.container().select(".search-header input").on("keydown.intro keyup.intro", null);
};
chapter.restart = function() {
chapter.exit();
chapter.enter();
};
return utilRebind(chapter, dispatch10, "on");
}
// modules/ui/intro/point.js
function uiIntroPoint(context, reveal) {
var dispatch10 = dispatch_default("done");
var timeouts = [];
var intersection = [-85.63279, 41.94394];
var building = [-85.632422, 41.944045];
var cafePreset = _mainPresetIndex.item("amenity/cafe");
var _pointID = null;
var chapter = {
title: "intro.points.title"
};
function timeout2(f2, t) {
timeouts.push(window.setTimeout(f2, t));
}
function eventCancel(d3_event) {
d3_event.stopPropagation();
d3_event.preventDefault();
}
function addPoint() {
context.enter(modeBrowse(context));
context.history().reset("initial");
var msec = transitionTime(intersection, context.map().center());
if (msec) {
reveal(null, null, { duration: 0 });
}
context.map().centerZoomEase(intersection, 19, msec);
timeout2(function() {
var tooltip = reveal("button.add-point", helpHtml("intro.points.points_info") + "{br}" + helpHtml("intro.points.add_point"));
_pointID = null;
tooltip.selectAll(".popover-inner").insert("svg", "span").attr("class", "tooltip-illustration").append("use").attr("xlink:href", "#iD-graphic-points");
context.on("enter.intro", function(mode) {
if (mode.id !== "add-point")
return;
continueTo(placePoint);
});
}, msec + 100);
function continueTo(nextStep) {
context.on("enter.intro", null);
nextStep();
}
}
function placePoint() {
if (context.mode().id !== "add-point") {
return chapter.restart();
}
var pointBox2 = pad(building, 150, context);
var textId = context.lastPointerType() === "mouse" ? "place_point" : "place_point_touch";
reveal(pointBox2, helpHtml("intro.points." + textId));
context.map().on("move.intro drawn.intro", function() {
pointBox2 = pad(building, 150, context);
reveal(pointBox2, helpHtml("intro.points." + textId), { duration: 0 });
});
context.on("enter.intro", function(mode) {
if (mode.id !== "select")
return chapter.restart();
_pointID = context.mode().selectedIDs()[0];
continueTo(searchPreset);
});
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
context.on("enter.intro", null);
nextStep();
}
}
function searchPreset() {
if (context.mode().id !== "select" || !_pointID || !context.hasEntity(_pointID)) {
return addPoint();
}
context.container().select(".inspector-wrap").on("wheel.intro", eventCancel);
context.container().select(".preset-search-input").on("keydown.intro", null).on("keyup.intro", checkPresetSearch);
reveal(".preset-search-input", helpHtml("intro.points.search_cafe", { preset: cafePreset.name() }));
context.on("enter.intro", function(mode) {
if (!_pointID || !context.hasEntity(_pointID)) {
return continueTo(addPoint);
}
var ids = context.selectedIDs();
if (mode.id !== "select" || !ids.length || ids[0] !== _pointID) {
context.enter(modeSelect(context, [_pointID]));
context.container().select(".inspector-wrap").on("wheel.intro", eventCancel);
context.container().select(".preset-search-input").on("keydown.intro", null).on("keyup.intro", checkPresetSearch);
reveal(".preset-search-input", helpHtml("intro.points.search_cafe", { preset: cafePreset.name() }));
context.history().on("change.intro", null);
}
});
function checkPresetSearch() {
var first = context.container().select(".preset-list-item:first-child");
if (first.classed("preset-amenity-cafe")) {
context.container().select(".preset-search-input").on("keydown.intro", eventCancel, true).on("keyup.intro", null);
reveal(first.select(".preset-list-button").node(), helpHtml("intro.points.choose_cafe", { preset: cafePreset.name() }), { duration: 300 });
context.history().on("change.intro", function() {
continueTo(aboutFeatureEditor);
});
}
}
function continueTo(nextStep) {
context.on("enter.intro", null);
context.history().on("change.intro", null);
context.container().select(".inspector-wrap").on("wheel.intro", null);
context.container().select(".preset-search-input").on("keydown.intro keyup.intro", null);
nextStep();
}
}
function aboutFeatureEditor() {
if (context.mode().id !== "select" || !_pointID || !context.hasEntity(_pointID)) {
return addPoint();
}
timeout2(function() {
reveal(".entity-editor-pane", helpHtml("intro.points.feature_editor"), {
tooltipClass: "intro-points-describe",
buttonText: _t.html("intro.ok"),
buttonCallback: function() {
continueTo(addName);
}
});
}, 400);
context.on("exit.intro", function() {
continueTo(reselectPoint);
});
function continueTo(nextStep) {
context.on("exit.intro", null);
nextStep();
}
}
function addName() {
if (context.mode().id !== "select" || !_pointID || !context.hasEntity(_pointID)) {
return addPoint();
}
context.container().select(".inspector-wrap .panewrap").style("right", "0%");
var addNameString = helpHtml("intro.points.fields_info") + "{br}" + helpHtml("intro.points.add_name");
timeout2(function() {
var entity = context.entity(_pointID);
if (entity.tags.name) {
var tooltip = reveal(".entity-editor-pane", addNameString, {
tooltipClass: "intro-points-describe",
buttonText: _t.html("intro.ok"),
buttonCallback: function() {
continueTo(addCloseEditor);
}
});
tooltip.select(".instruction").style("display", "none");
} else {
reveal(".entity-editor-pane", addNameString, { tooltipClass: "intro-points-describe" });
}
}, 400);
context.history().on("change.intro", function() {
continueTo(addCloseEditor);
});
context.on("exit.intro", function() {
continueTo(reselectPoint);
});
function continueTo(nextStep) {
context.on("exit.intro", null);
context.history().on("change.intro", null);
nextStep();
}
}
function addCloseEditor() {
context.container().select(".inspector-wrap .panewrap").style("right", "0%");
var selector = ".entity-editor-pane button.close svg use";
var href = select_default2(selector).attr("href") || "#iD-icon-close";
context.on("exit.intro", function() {
continueTo(reselectPoint);
});
reveal(".entity-editor-pane", helpHtml("intro.points.add_close", { button: { html: icon(href, "inline") } }));
function continueTo(nextStep) {
context.on("exit.intro", null);
nextStep();
}
}
function reselectPoint() {
if (!_pointID)
return chapter.restart();
var entity = context.hasEntity(_pointID);
if (!entity)
return chapter.restart();
var oldPreset = _mainPresetIndex.match(entity, context.graph());
context.replace(actionChangePreset(_pointID, oldPreset, cafePreset));
context.enter(modeBrowse(context));
var msec = transitionTime(entity.loc, context.map().center());
if (msec) {
reveal(null, null, { duration: 0 });
}
context.map().centerEase(entity.loc, msec);
timeout2(function() {
var box = pointBox(entity.loc, context);
reveal(box, helpHtml("intro.points.reselect"), { duration: 600 });
timeout2(function() {
context.map().on("move.intro drawn.intro", function() {
var entity2 = context.hasEntity(_pointID);
if (!entity2)
return chapter.restart();
var box2 = pointBox(entity2.loc, context);
reveal(box2, helpHtml("intro.points.reselect"), { duration: 0 });
});
}, 600);
context.on("enter.intro", function(mode) {
if (mode.id !== "select")
return;
continueTo(updatePoint);
});
}, msec + 100);
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
context.on("enter.intro", null);
nextStep();
}
}
function updatePoint() {
if (context.mode().id !== "select" || !_pointID || !context.hasEntity(_pointID)) {
return continueTo(reselectPoint);
}
context.container().select(".inspector-wrap .panewrap").style("right", "0%");
context.on("exit.intro", function() {
continueTo(reselectPoint);
});
context.history().on("change.intro", function() {
continueTo(updateCloseEditor);
});
timeout2(function() {
reveal(".entity-editor-pane", helpHtml("intro.points.update"), { tooltipClass: "intro-points-describe" });
}, 400);
function continueTo(nextStep) {
context.on("exit.intro", null);
context.history().on("change.intro", null);
nextStep();
}
}
function updateCloseEditor() {
if (context.mode().id !== "select" || !_pointID || !context.hasEntity(_pointID)) {
return continueTo(reselectPoint);
}
context.container().select(".inspector-wrap .panewrap").style("right", "0%");
context.on("exit.intro", function() {
continueTo(rightClickPoint);
});
timeout2(function() {
reveal(".entity-editor-pane", helpHtml("intro.points.update_close", { button: { html: icon("#iD-icon-close", "inline") } }));
}, 500);
function continueTo(nextStep) {
context.on("exit.intro", null);
nextStep();
}
}
function rightClickPoint() {
if (!_pointID)
return chapter.restart();
var entity = context.hasEntity(_pointID);
if (!entity)
return chapter.restart();
context.enter(modeBrowse(context));
var box = pointBox(entity.loc, context);
var textId = context.lastPointerType() === "mouse" ? "rightclick" : "edit_menu_touch";
reveal(box, helpHtml("intro.points." + textId), { duration: 600 });
timeout2(function() {
context.map().on("move.intro", function() {
var entity2 = context.hasEntity(_pointID);
if (!entity2)
return chapter.restart();
var box2 = pointBox(entity2.loc, context);
reveal(box2, helpHtml("intro.points." + textId), { duration: 0 });
});
}, 600);
context.on("enter.intro", function(mode) {
if (mode.id !== "select")
return;
var ids = context.selectedIDs();
if (ids.length !== 1 || ids[0] !== _pointID)
return;
timeout2(function() {
var node = selectMenuItem(context, "delete").node();
if (!node)
return;
continueTo(enterDelete);
}, 50);
});
function continueTo(nextStep) {
context.on("enter.intro", null);
context.map().on("move.intro", null);
nextStep();
}
}
function enterDelete() {
if (!_pointID)
return chapter.restart();
var entity = context.hasEntity(_pointID);
if (!entity)
return chapter.restart();
var node = selectMenuItem(context, "delete").node();
if (!node) {
return continueTo(rightClickPoint);
}
reveal(".edit-menu", helpHtml("intro.points.delete"), { padding: 50 });
timeout2(function() {
context.map().on("move.intro", function() {
reveal(".edit-menu", helpHtml("intro.points.delete"), { duration: 0, padding: 50 });
});
}, 300);
context.on("exit.intro", function() {
if (!_pointID)
return chapter.restart();
var entity2 = context.hasEntity(_pointID);
if (entity2)
return continueTo(rightClickPoint);
});
context.history().on("change.intro", function(changed) {
if (changed.deleted().length) {
continueTo(undo);
}
});
function continueTo(nextStep) {
context.map().on("move.intro", null);
context.history().on("change.intro", null);
context.on("exit.intro", null);
nextStep();
}
}
function undo() {
context.history().on("change.intro", function() {
continueTo(play);
});
reveal(".top-toolbar button.undo-button", helpHtml("intro.points.undo"));
function continueTo(nextStep) {
context.history().on("change.intro", null);
nextStep();
}
}
function play() {
dispatch10.call("done");
reveal(".ideditor", helpHtml("intro.points.play", { next: _t("intro.areas.title") }), {
tooltipBox: ".intro-nav-wrap .chapter-area",
buttonText: _t.html("intro.ok"),
buttonCallback: function() {
reveal(".ideditor");
}
});
}
chapter.enter = function() {
addPoint();
};
chapter.exit = function() {
timeouts.forEach(window.clearTimeout);
context.on("enter.intro exit.intro", null);
context.map().on("move.intro drawn.intro", null);
context.history().on("change.intro", null);
context.container().select(".inspector-wrap").on("wheel.intro", eventCancel);
context.container().select(".preset-search-input").on("keydown.intro keyup.intro", null);
};
chapter.restart = function() {
chapter.exit();
chapter.enter();
};
return utilRebind(chapter, dispatch10, "on");
}
// modules/ui/intro/area.js
function uiIntroArea(context, reveal) {
var dispatch10 = dispatch_default("done");
var playground = [-85.63552, 41.94159];
var playgroundPreset = _mainPresetIndex.item("leisure/playground");
var nameField = _mainPresetIndex.field("name");
var descriptionField = _mainPresetIndex.field("description");
var timeouts = [];
var _areaID;
var chapter = {
title: "intro.areas.title"
};
function timeout2(f2, t) {
timeouts.push(window.setTimeout(f2, t));
}
function eventCancel(d3_event) {
d3_event.stopPropagation();
d3_event.preventDefault();
}
function revealPlayground(center, text2, options2) {
var padding = 180 * Math.pow(2, context.map().zoom() - 19.5);
var box = pad(center, padding, context);
reveal(box, text2, options2);
}
function addArea() {
context.enter(modeBrowse(context));
context.history().reset("initial");
_areaID = null;
var msec = transitionTime(playground, context.map().center());
if (msec) {
reveal(null, null, { duration: 0 });
}
context.map().centerZoomEase(playground, 19, msec);
timeout2(function() {
var tooltip = reveal("button.add-area", helpHtml("intro.areas.add_playground"));
tooltip.selectAll(".popover-inner").insert("svg", "span").attr("class", "tooltip-illustration").append("use").attr("xlink:href", "#iD-graphic-areas");
context.on("enter.intro", function(mode) {
if (mode.id !== "add-area")
return;
continueTo(startPlayground);
});
}, msec + 100);
function continueTo(nextStep) {
context.on("enter.intro", null);
nextStep();
}
}
function startPlayground() {
if (context.mode().id !== "add-area") {
return chapter.restart();
}
_areaID = null;
context.map().zoomEase(19.5, 500);
timeout2(function() {
var textId = context.lastPointerType() === "mouse" ? "starting_node_click" : "starting_node_tap";
var startDrawString = helpHtml("intro.areas.start_playground") + helpHtml("intro.areas." + textId);
revealPlayground(playground, startDrawString, { duration: 250 });
timeout2(function() {
context.map().on("move.intro drawn.intro", function() {
revealPlayground(playground, startDrawString, { duration: 0 });
});
context.on("enter.intro", function(mode) {
if (mode.id !== "draw-area")
return chapter.restart();
continueTo(continuePlayground);
});
}, 250);
}, 550);
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
context.on("enter.intro", null);
nextStep();
}
}
function continuePlayground() {
if (context.mode().id !== "draw-area") {
return chapter.restart();
}
_areaID = null;
revealPlayground(playground, helpHtml("intro.areas.continue_playground"), { duration: 250 });
timeout2(function() {
context.map().on("move.intro drawn.intro", function() {
revealPlayground(playground, helpHtml("intro.areas.continue_playground"), { duration: 0 });
});
}, 250);
context.on("enter.intro", function(mode) {
if (mode.id === "draw-area") {
var entity = context.hasEntity(context.selectedIDs()[0]);
if (entity && entity.nodes.length >= 6) {
return continueTo(finishPlayground);
} else {
return;
}
} else if (mode.id === "select") {
_areaID = context.selectedIDs()[0];
return continueTo(searchPresets);
} else {
return chapter.restart();
}
});
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
context.on("enter.intro", null);
nextStep();
}
}
function finishPlayground() {
if (context.mode().id !== "draw-area") {
return chapter.restart();
}
_areaID = null;
var finishString = helpHtml("intro.areas.finish_area_" + (context.lastPointerType() === "mouse" ? "click" : "tap")) + helpHtml("intro.areas.finish_playground");
revealPlayground(playground, finishString, { duration: 250 });
timeout2(function() {
context.map().on("move.intro drawn.intro", function() {
revealPlayground(playground, finishString, { duration: 0 });
});
}, 250);
context.on("enter.intro", function(mode) {
if (mode.id === "draw-area") {
return;
} else if (mode.id === "select") {
_areaID = context.selectedIDs()[0];
return continueTo(searchPresets);
} else {
return chapter.restart();
}
});
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
context.on("enter.intro", null);
nextStep();
}
}
function searchPresets() {
if (!_areaID || !context.hasEntity(_areaID)) {
return addArea();
}
var ids = context.selectedIDs();
if (context.mode().id !== "select" || !ids.length || ids[0] !== _areaID) {
context.enter(modeSelect(context, [_areaID]));
}
context.container().select(".inspector-wrap").on("wheel.intro", eventCancel);
timeout2(function() {
context.container().select(".inspector-wrap .panewrap").style("right", "-100%");
context.container().select(".preset-search-input").on("keydown.intro", null).on("keyup.intro", checkPresetSearch);
reveal(".preset-search-input", helpHtml("intro.areas.search_playground", { preset: playgroundPreset.name() }));
}, 400);
context.on("enter.intro", function(mode) {
if (!_areaID || !context.hasEntity(_areaID)) {
return continueTo(addArea);
}
var ids2 = context.selectedIDs();
if (mode.id !== "select" || !ids2.length || ids2[0] !== _areaID) {
context.enter(modeSelect(context, [_areaID]));
context.container().select(".inspector-wrap .panewrap").style("right", "-100%");
context.container().select(".inspector-wrap").on("wheel.intro", eventCancel);
context.container().select(".preset-search-input").on("keydown.intro", null).on("keyup.intro", checkPresetSearch);
reveal(".preset-search-input", helpHtml("intro.areas.search_playground", { preset: playgroundPreset.name() }));
context.history().on("change.intro", null);
}
});
function checkPresetSearch() {
var first = context.container().select(".preset-list-item:first-child");
if (first.classed("preset-leisure-playground")) {
reveal(first.select(".preset-list-button").node(), helpHtml("intro.areas.choose_playground", { preset: playgroundPreset.name() }), { duration: 300 });
context.container().select(".preset-search-input").on("keydown.intro", eventCancel, true).on("keyup.intro", null);
context.history().on("change.intro", function() {
continueTo(clickAddField);
});
}
}
function continueTo(nextStep) {
context.container().select(".inspector-wrap").on("wheel.intro", null);
context.on("enter.intro", null);
context.history().on("change.intro", null);
context.container().select(".preset-search-input").on("keydown.intro keyup.intro", null);
nextStep();
}
}
function clickAddField() {
if (!_areaID || !context.hasEntity(_areaID)) {
return addArea();
}
var ids = context.selectedIDs();
if (context.mode().id !== "select" || !ids.length || ids[0] !== _areaID) {
return searchPresets();
}
if (!context.container().select(".form-field-description").empty()) {
return continueTo(describePlayground);
}
context.container().select(".inspector-wrap").on("wheel.intro", eventCancel);
timeout2(function() {
context.container().select(".inspector-wrap .panewrap").style("right", "0%");
var entity = context.entity(_areaID);
if (entity.tags.description) {
return continueTo(play);
}
var box = context.container().select(".more-fields").node().getBoundingClientRect();
if (box.top > 300) {
var pane = context.container().select(".entity-editor-pane .inspector-body");
var start2 = pane.node().scrollTop;
var end = start2 + (box.top - 300);
pane.transition().duration(250).tween("scroll.inspector", function() {
var node = this;
var i2 = number_default(start2, end);
return function(t) {
node.scrollTop = i2(t);
};
});
}
timeout2(function() {
reveal(".more-fields .combobox-input", helpHtml("intro.areas.add_field", {
name: { html: nameField.label() },
description: { html: descriptionField.label() }
}), { duration: 300 });
context.container().select(".more-fields .combobox-input").on("click.intro", function() {
var watcher;
watcher = window.setInterval(function() {
if (!context.container().select("div.combobox").empty()) {
window.clearInterval(watcher);
continueTo(chooseDescriptionField);
}
}, 300);
});
}, 300);
}, 400);
context.on("exit.intro", function() {
return continueTo(searchPresets);
});
function continueTo(nextStep) {
context.container().select(".inspector-wrap").on("wheel.intro", null);
context.container().select(".more-fields .combobox-input").on("click.intro", null);
context.on("exit.intro", null);
nextStep();
}
}
function chooseDescriptionField() {
if (!_areaID || !context.hasEntity(_areaID)) {
return addArea();
}
var ids = context.selectedIDs();
if (context.mode().id !== "select" || !ids.length || ids[0] !== _areaID) {
return searchPresets();
}
if (!context.container().select(".form-field-description").empty()) {
return continueTo(describePlayground);
}
if (context.container().select("div.combobox").empty()) {
return continueTo(clickAddField);
}
var watcher;
watcher = window.setInterval(function() {
if (context.container().select("div.combobox").empty()) {
window.clearInterval(watcher);
timeout2(function() {
if (context.container().select(".form-field-description").empty()) {
continueTo(retryChooseDescription);
} else {
continueTo(describePlayground);
}
}, 300);
}
}, 300);
reveal("div.combobox", helpHtml("intro.areas.choose_field", { field: { html: descriptionField.label() } }), { duration: 300 });
context.on("exit.intro", function() {
return continueTo(searchPresets);
});
function continueTo(nextStep) {
if (watcher)
window.clearInterval(watcher);
context.on("exit.intro", null);
nextStep();
}
}
function describePlayground() {
if (!_areaID || !context.hasEntity(_areaID)) {
return addArea();
}
var ids = context.selectedIDs();
if (context.mode().id !== "select" || !ids.length || ids[0] !== _areaID) {
return searchPresets();
}
context.container().select(".inspector-wrap .panewrap").style("right", "0%");
if (context.container().select(".form-field-description").empty()) {
return continueTo(retryChooseDescription);
}
context.on("exit.intro", function() {
continueTo(play);
});
reveal(".entity-editor-pane", helpHtml("intro.areas.describe_playground", { button: { html: icon("#iD-icon-close", "inline") } }), { duration: 300 });
function continueTo(nextStep) {
context.on("exit.intro", null);
nextStep();
}
}
function retryChooseDescription() {
if (!_areaID || !context.hasEntity(_areaID)) {
return addArea();
}
var ids = context.selectedIDs();
if (context.mode().id !== "select" || !ids.length || ids[0] !== _areaID) {
return searchPresets();
}
context.container().select(".inspector-wrap .panewrap").style("right", "0%");
reveal(".entity-editor-pane", helpHtml("intro.areas.retry_add_field", { field: { html: descriptionField.label() } }), {
buttonText: _t.html("intro.ok"),
buttonCallback: function() {
continueTo(clickAddField);
}
});
context.on("exit.intro", function() {
return continueTo(searchPresets);
});
function continueTo(nextStep) {
context.on("exit.intro", null);
nextStep();
}
}
function play() {
dispatch10.call("done");
reveal(".ideditor", helpHtml("intro.areas.play", { next: _t("intro.lines.title") }), {
tooltipBox: ".intro-nav-wrap .chapter-line",
buttonText: _t.html("intro.ok"),
buttonCallback: function() {
reveal(".ideditor");
}
});
}
chapter.enter = function() {
addArea();
};
chapter.exit = function() {
timeouts.forEach(window.clearTimeout);
context.on("enter.intro exit.intro", null);
context.map().on("move.intro drawn.intro", null);
context.history().on("change.intro", null);
context.container().select(".inspector-wrap").on("wheel.intro", null);
context.container().select(".preset-search-input").on("keydown.intro keyup.intro", null);
context.container().select(".more-fields .combobox-input").on("click.intro", null);
};
chapter.restart = function() {
chapter.exit();
chapter.enter();
};
return utilRebind(chapter, dispatch10, "on");
}
// modules/ui/intro/line.js
function uiIntroLine(context, reveal) {
var dispatch10 = dispatch_default("done");
var timeouts = [];
var _tulipRoadID = null;
var flowerRoadID = "w646";
var tulipRoadStart = [-85.6297754121684, 41.95805253325314];
var tulipRoadMidpoint = [-85.62975395449628, 41.95787501510204];
var tulipRoadIntersection = [-85.62974496187628, 41.95742515554585];
var roadCategory = _mainPresetIndex.item("category-road_minor");
var residentialPreset = _mainPresetIndex.item("highway/residential");
var woodRoadID = "w525";
var woodRoadEndID = "n2862";
var woodRoadAddNode = [-85.62390110349587, 41.95397111462291];
var woodRoadDragEndpoint = [-85.623867390213, 41.95466987786487];
var woodRoadDragMidpoint = [-85.62386254803509, 41.95430395953872];
var washingtonStreetID = "w522";
var twelfthAvenueID = "w1";
var eleventhAvenueEndID = "n3550";
var twelfthAvenueEndID = "n5";
var _washingtonSegmentID = null;
var eleventhAvenueEnd = context.entity(eleventhAvenueEndID).loc;
var twelfthAvenueEnd = context.entity(twelfthAvenueEndID).loc;
var deleteLinesLoc = [-85.6219395542764, 41.95228033922477];
var twelfthAvenue = [-85.62219310052491, 41.952505413152956];
var chapter = {
title: "intro.lines.title"
};
function timeout2(f2, t) {
timeouts.push(window.setTimeout(f2, t));
}
function eventCancel(d3_event) {
d3_event.stopPropagation();
d3_event.preventDefault();
}
function addLine() {
context.enter(modeBrowse(context));
context.history().reset("initial");
var msec = transitionTime(tulipRoadStart, context.map().center());
if (msec) {
reveal(null, null, { duration: 0 });
}
context.map().centerZoomEase(tulipRoadStart, 18.5, msec);
timeout2(function() {
var tooltip = reveal("button.add-line", helpHtml("intro.lines.add_line"));
tooltip.selectAll(".popover-inner").insert("svg", "span").attr("class", "tooltip-illustration").append("use").attr("xlink:href", "#iD-graphic-lines");
context.on("enter.intro", function(mode) {
if (mode.id !== "add-line")
return;
continueTo(startLine);
});
}, msec + 100);
function continueTo(nextStep) {
context.on("enter.intro", null);
nextStep();
}
}
function startLine() {
if (context.mode().id !== "add-line")
return chapter.restart();
_tulipRoadID = null;
var padding = 70 * Math.pow(2, context.map().zoom() - 18);
var box = pad(tulipRoadStart, padding, context);
box.height = box.height + 100;
var textId = context.lastPointerType() === "mouse" ? "start_line" : "start_line_tap";
var startLineString = helpHtml("intro.lines.missing_road") + "{br}" + helpHtml("intro.lines.line_draw_info") + helpHtml("intro.lines." + textId);
reveal(box, startLineString);
context.map().on("move.intro drawn.intro", function() {
padding = 70 * Math.pow(2, context.map().zoom() - 18);
box = pad(tulipRoadStart, padding, context);
box.height = box.height + 100;
reveal(box, startLineString, { duration: 0 });
});
context.on("enter.intro", function(mode) {
if (mode.id !== "draw-line")
return chapter.restart();
continueTo(drawLine);
});
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
context.on("enter.intro", null);
nextStep();
}
}
function drawLine() {
if (context.mode().id !== "draw-line")
return chapter.restart();
_tulipRoadID = context.mode().selectedIDs()[0];
context.map().centerEase(tulipRoadMidpoint, 500);
timeout2(function() {
var padding = 200 * Math.pow(2, context.map().zoom() - 18.5);
var box = pad(tulipRoadMidpoint, padding, context);
box.height = box.height * 2;
reveal(box, helpHtml("intro.lines.intersect", { name: _t("intro.graph.name.flower-street") }));
context.map().on("move.intro drawn.intro", function() {
padding = 200 * Math.pow(2, context.map().zoom() - 18.5);
box = pad(tulipRoadMidpoint, padding, context);
box.height = box.height * 2;
reveal(box, helpHtml("intro.lines.intersect", { name: _t("intro.graph.name.flower-street") }), { duration: 0 });
});
}, 550);
context.history().on("change.intro", function() {
if (isLineConnected()) {
continueTo(continueLine);
}
});
context.on("enter.intro", function(mode) {
if (mode.id === "draw-line") {
return;
} else if (mode.id === "select") {
continueTo(retryIntersect);
return;
} else {
return chapter.restart();
}
});
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
context.history().on("change.intro", null);
context.on("enter.intro", null);
nextStep();
}
}
function isLineConnected() {
var entity = _tulipRoadID && context.hasEntity(_tulipRoadID);
if (!entity)
return false;
var drawNodes = context.graph().childNodes(entity);
return drawNodes.some(function(node) {
return context.graph().parentWays(node).some(function(parent) {
return parent.id === flowerRoadID;
});
});
}
function retryIntersect() {
select_default2(window).on("pointerdown.intro mousedown.intro", eventCancel, true);
var box = pad(tulipRoadIntersection, 80, context);
reveal(box, helpHtml("intro.lines.retry_intersect", { name: _t("intro.graph.name.flower-street") }));
timeout2(chapter.restart, 3e3);
}
function continueLine() {
if (context.mode().id !== "draw-line")
return chapter.restart();
var entity = _tulipRoadID && context.hasEntity(_tulipRoadID);
if (!entity)
return chapter.restart();
context.map().centerEase(tulipRoadIntersection, 500);
var continueLineText = helpHtml("intro.lines.continue_line") + "{br}" + helpHtml("intro.lines.finish_line_" + (context.lastPointerType() === "mouse" ? "click" : "tap")) + helpHtml("intro.lines.finish_road");
reveal(".surface", continueLineText);
context.on("enter.intro", function(mode) {
if (mode.id === "draw-line") {
return;
} else if (mode.id === "select") {
return continueTo(chooseCategoryRoad);
} else {
return chapter.restart();
}
});
function continueTo(nextStep) {
context.on("enter.intro", null);
nextStep();
}
}
function chooseCategoryRoad() {
if (context.mode().id !== "select")
return chapter.restart();
context.on("exit.intro", function() {
return chapter.restart();
});
var button = context.container().select(".preset-category-road_minor .preset-list-button");
if (button.empty())
return chapter.restart();
context.container().select(".inspector-wrap").on("wheel.intro", eventCancel);
timeout2(function() {
context.container().select(".inspector-wrap .panewrap").style("right", "-100%");
reveal(button.node(), helpHtml("intro.lines.choose_category_road", { category: roadCategory.name() }));
button.on("click.intro", function() {
continueTo(choosePresetResidential);
});
}, 400);
function continueTo(nextStep) {
context.container().select(".inspector-wrap").on("wheel.intro", null);
context.container().select(".preset-list-button").on("click.intro", null);
context.on("exit.intro", null);
nextStep();
}
}
function choosePresetResidential() {
if (context.mode().id !== "select")
return chapter.restart();
context.on("exit.intro", function() {
return chapter.restart();
});
var subgrid = context.container().select(".preset-category-road_minor .subgrid");
if (subgrid.empty())
return chapter.restart();
subgrid.selectAll(":not(.preset-highway-residential) .preset-list-button").on("click.intro", function() {
continueTo(retryPresetResidential);
});
subgrid.selectAll(".preset-highway-residential .preset-list-button").on("click.intro", function() {
continueTo(nameRoad);
});
timeout2(function() {
reveal(subgrid.node(), helpHtml("intro.lines.choose_preset_residential", { preset: residentialPreset.name() }), { tooltipBox: ".preset-highway-residential .preset-list-button", duration: 300 });
}, 300);
function continueTo(nextStep) {
context.container().select(".preset-list-button").on("click.intro", null);
context.on("exit.intro", null);
nextStep();
}
}
function retryPresetResidential() {
if (context.mode().id !== "select")
return chapter.restart();
context.on("exit.intro", function() {
return chapter.restart();
});
context.container().select(".inspector-wrap").on("wheel.intro", eventCancel);
timeout2(function() {
var button = context.container().select(".entity-editor-pane .preset-list-button");
reveal(button.node(), helpHtml("intro.lines.retry_preset_residential", { preset: residentialPreset.name() }));
button.on("click.intro", function() {
continueTo(chooseCategoryRoad);
});
}, 500);
function continueTo(nextStep) {
context.container().select(".inspector-wrap").on("wheel.intro", null);
context.container().select(".preset-list-button").on("click.intro", null);
context.on("exit.intro", null);
nextStep();
}
}
function nameRoad() {
context.on("exit.intro", function() {
continueTo(didNameRoad);
});
timeout2(function() {
reveal(".entity-editor-pane", helpHtml("intro.lines.name_road", { button: { html: icon("#iD-icon-close", "inline") } }), { tooltipClass: "intro-lines-name_road" });
}, 500);
function continueTo(nextStep) {
context.on("exit.intro", null);
nextStep();
}
}
function didNameRoad() {
context.history().checkpoint("doneAddLine");
timeout2(function() {
reveal(".surface", helpHtml("intro.lines.did_name_road"), {
buttonText: _t.html("intro.ok"),
buttonCallback: function() {
continueTo(updateLine);
}
});
}, 500);
function continueTo(nextStep) {
nextStep();
}
}
function updateLine() {
context.history().reset("doneAddLine");
if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
return chapter.restart();
}
var msec = transitionTime(woodRoadDragMidpoint, context.map().center());
if (msec) {
reveal(null, null, { duration: 0 });
}
context.map().centerZoomEase(woodRoadDragMidpoint, 19, msec);
timeout2(function() {
var padding = 250 * Math.pow(2, context.map().zoom() - 19);
var box = pad(woodRoadDragMidpoint, padding, context);
var advance = function() {
continueTo(addNode);
};
reveal(box, helpHtml("intro.lines.update_line"), { buttonText: _t.html("intro.ok"), buttonCallback: advance });
context.map().on("move.intro drawn.intro", function() {
var padding2 = 250 * Math.pow(2, context.map().zoom() - 19);
var box2 = pad(woodRoadDragMidpoint, padding2, context);
reveal(box2, helpHtml("intro.lines.update_line"), { duration: 0, buttonText: _t.html("intro.ok"), buttonCallback: advance });
});
}, msec + 100);
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
nextStep();
}
}
function addNode() {
context.history().reset("doneAddLine");
if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
return chapter.restart();
}
var padding = 40 * Math.pow(2, context.map().zoom() - 19);
var box = pad(woodRoadAddNode, padding, context);
var addNodeString = helpHtml("intro.lines.add_node" + (context.lastPointerType() === "mouse" ? "" : "_touch"));
reveal(box, addNodeString);
context.map().on("move.intro drawn.intro", function() {
var padding2 = 40 * Math.pow(2, context.map().zoom() - 19);
var box2 = pad(woodRoadAddNode, padding2, context);
reveal(box2, addNodeString, { duration: 0 });
});
context.history().on("change.intro", function(changed) {
if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
return continueTo(updateLine);
}
if (changed.created().length === 1) {
timeout2(function() {
continueTo(startDragEndpoint);
}, 500);
}
});
context.on("enter.intro", function(mode) {
if (mode.id !== "select") {
continueTo(updateLine);
}
});
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
context.history().on("change.intro", null);
context.on("enter.intro", null);
nextStep();
}
}
function startDragEndpoint() {
if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
return continueTo(updateLine);
}
var padding = 100 * Math.pow(2, context.map().zoom() - 19);
var box = pad(woodRoadDragEndpoint, padding, context);
var startDragString = helpHtml("intro.lines.start_drag_endpoint" + (context.lastPointerType() === "mouse" ? "" : "_touch")) + helpHtml("intro.lines.drag_to_intersection");
reveal(box, startDragString);
context.map().on("move.intro drawn.intro", function() {
if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
return continueTo(updateLine);
}
var padding2 = 100 * Math.pow(2, context.map().zoom() - 19);
var box2 = pad(woodRoadDragEndpoint, padding2, context);
reveal(box2, startDragString, { duration: 0 });
var entity = context.entity(woodRoadEndID);
if (geoSphericalDistance(entity.loc, woodRoadDragEndpoint) <= 4) {
continueTo(finishDragEndpoint);
}
});
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
nextStep();
}
}
function finishDragEndpoint() {
if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
return continueTo(updateLine);
}
var padding = 100 * Math.pow(2, context.map().zoom() - 19);
var box = pad(woodRoadDragEndpoint, padding, context);
var finishDragString = helpHtml("intro.lines.spot_looks_good") + helpHtml("intro.lines.finish_drag_endpoint" + (context.lastPointerType() === "mouse" ? "" : "_touch"));
reveal(box, finishDragString);
context.map().on("move.intro drawn.intro", function() {
if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
return continueTo(updateLine);
}
var padding2 = 100 * Math.pow(2, context.map().zoom() - 19);
var box2 = pad(woodRoadDragEndpoint, padding2, context);
reveal(box2, finishDragString, { duration: 0 });
var entity = context.entity(woodRoadEndID);
if (geoSphericalDistance(entity.loc, woodRoadDragEndpoint) > 4) {
continueTo(startDragEndpoint);
}
});
context.on("enter.intro", function() {
continueTo(startDragMidpoint);
});
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
context.on("enter.intro", null);
nextStep();
}
}
function startDragMidpoint() {
if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
return continueTo(updateLine);
}
if (context.selectedIDs().indexOf(woodRoadID) === -1) {
context.enter(modeSelect(context, [woodRoadID]));
}
var padding = 80 * Math.pow(2, context.map().zoom() - 19);
var box = pad(woodRoadDragMidpoint, padding, context);
reveal(box, helpHtml("intro.lines.start_drag_midpoint"));
context.map().on("move.intro drawn.intro", function() {
if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
return continueTo(updateLine);
}
var padding2 = 80 * Math.pow(2, context.map().zoom() - 19);
var box2 = pad(woodRoadDragMidpoint, padding2, context);
reveal(box2, helpHtml("intro.lines.start_drag_midpoint"), { duration: 0 });
});
context.history().on("change.intro", function(changed) {
if (changed.created().length === 1) {
continueTo(continueDragMidpoint);
}
});
context.on("enter.intro", function(mode) {
if (mode.id !== "select") {
context.enter(modeSelect(context, [woodRoadID]));
}
});
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
context.history().on("change.intro", null);
context.on("enter.intro", null);
nextStep();
}
}
function continueDragMidpoint() {
if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
return continueTo(updateLine);
}
var padding = 100 * Math.pow(2, context.map().zoom() - 19);
var box = pad(woodRoadDragEndpoint, padding, context);
box.height += 400;
var advance = function() {
context.history().checkpoint("doneUpdateLine");
continueTo(deleteLines);
};
reveal(box, helpHtml("intro.lines.continue_drag_midpoint"), { buttonText: _t.html("intro.ok"), buttonCallback: advance });
context.map().on("move.intro drawn.intro", function() {
if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
return continueTo(updateLine);
}
var padding2 = 100 * Math.pow(2, context.map().zoom() - 19);
var box2 = pad(woodRoadDragEndpoint, padding2, context);
box2.height += 400;
reveal(box2, helpHtml("intro.lines.continue_drag_midpoint"), { duration: 0, buttonText: _t.html("intro.ok"), buttonCallback: advance });
});
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
nextStep();
}
}
function deleteLines() {
context.history().reset("doneUpdateLine");
context.enter(modeBrowse(context));
if (!context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
return chapter.restart();
}
var msec = transitionTime(deleteLinesLoc, context.map().center());
if (msec) {
reveal(null, null, { duration: 0 });
}
context.map().centerZoomEase(deleteLinesLoc, 18, msec);
timeout2(function() {
var padding = 200 * Math.pow(2, context.map().zoom() - 18);
var box = pad(deleteLinesLoc, padding, context);
box.top -= 200;
box.height += 400;
var advance = function() {
continueTo(rightClickIntersection);
};
reveal(box, helpHtml("intro.lines.delete_lines", { street: _t("intro.graph.name.12th-avenue") }), { buttonText: _t.html("intro.ok"), buttonCallback: advance });
context.map().on("move.intro drawn.intro", function() {
var padding2 = 200 * Math.pow(2, context.map().zoom() - 18);
var box2 = pad(deleteLinesLoc, padding2, context);
box2.top -= 200;
box2.height += 400;
reveal(box2, helpHtml("intro.lines.delete_lines", { street: _t("intro.graph.name.12th-avenue") }), { duration: 0, buttonText: _t.html("intro.ok"), buttonCallback: advance });
});
context.history().on("change.intro", function() {
timeout2(function() {
continueTo(deleteLines);
}, 500);
});
}, msec + 100);
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
context.history().on("change.intro", null);
nextStep();
}
}
function rightClickIntersection() {
context.history().reset("doneUpdateLine");
context.enter(modeBrowse(context));
context.map().centerZoomEase(eleventhAvenueEnd, 18, 500);
var rightClickString = helpHtml("intro.lines.split_street", {
street1: _t("intro.graph.name.11th-avenue"),
street2: _t("intro.graph.name.washington-street")
}) + helpHtml("intro.lines." + (context.lastPointerType() === "mouse" ? "rightclick_intersection" : "edit_menu_intersection_touch"));
timeout2(function() {
var padding = 60 * Math.pow(2, context.map().zoom() - 18);
var box = pad(eleventhAvenueEnd, padding, context);
reveal(box, rightClickString);
context.map().on("move.intro drawn.intro", function() {
var padding2 = 60 * Math.pow(2, context.map().zoom() - 18);
var box2 = pad(eleventhAvenueEnd, padding2, context);
reveal(box2, rightClickString, { duration: 0 });
});
context.on("enter.intro", function(mode) {
if (mode.id !== "select")
return;
var ids = context.selectedIDs();
if (ids.length !== 1 || ids[0] !== eleventhAvenueEndID)
return;
timeout2(function() {
var node = selectMenuItem(context, "split").node();
if (!node)
return;
continueTo(splitIntersection);
}, 50);
});
context.history().on("change.intro", function() {
timeout2(function() {
continueTo(deleteLines);
}, 300);
});
}, 600);
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
context.on("enter.intro", null);
context.history().on("change.intro", null);
nextStep();
}
}
function splitIntersection() {
if (!context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
return continueTo(deleteLines);
}
var node = selectMenuItem(context, "split").node();
if (!node) {
return continueTo(rightClickIntersection);
}
var wasChanged = false;
_washingtonSegmentID = null;
reveal(".edit-menu", helpHtml("intro.lines.split_intersection", { street: _t("intro.graph.name.washington-street") }), { padding: 50 });
context.map().on("move.intro drawn.intro", function() {
var node2 = selectMenuItem(context, "split").node();
if (!wasChanged && !node2) {
return continueTo(rightClickIntersection);
}
reveal(".edit-menu", helpHtml("intro.lines.split_intersection", { street: _t("intro.graph.name.washington-street") }), { duration: 0, padding: 50 });
});
context.history().on("change.intro", function(changed) {
wasChanged = true;
timeout2(function() {
if (context.history().undoAnnotation() === _t("operations.split.annotation.line", { n: 1 })) {
_washingtonSegmentID = changed.created()[0].id;
continueTo(didSplit);
} else {
_washingtonSegmentID = null;
continueTo(retrySplit);
}
}, 300);
});
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
context.history().on("change.intro", null);
nextStep();
}
}
function retrySplit() {
context.enter(modeBrowse(context));
context.map().centerZoomEase(eleventhAvenueEnd, 18, 500);
var advance = function() {
continueTo(rightClickIntersection);
};
var padding = 60 * Math.pow(2, context.map().zoom() - 18);
var box = pad(eleventhAvenueEnd, padding, context);
reveal(box, helpHtml("intro.lines.retry_split"), { buttonText: _t.html("intro.ok"), buttonCallback: advance });
context.map().on("move.intro drawn.intro", function() {
var padding2 = 60 * Math.pow(2, context.map().zoom() - 18);
var box2 = pad(eleventhAvenueEnd, padding2, context);
reveal(box2, helpHtml("intro.lines.retry_split"), { duration: 0, buttonText: _t.html("intro.ok"), buttonCallback: advance });
});
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
nextStep();
}
}
function didSplit() {
if (!_washingtonSegmentID || !context.hasEntity(_washingtonSegmentID) || !context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
return continueTo(rightClickIntersection);
}
var ids = context.selectedIDs();
var string = "intro.lines.did_split_" + (ids.length > 1 ? "multi" : "single");
var street = _t("intro.graph.name.washington-street");
var padding = 200 * Math.pow(2, context.map().zoom() - 18);
var box = pad(twelfthAvenue, padding, context);
box.width = box.width / 2;
reveal(box, helpHtml(string, { street1: street, street2: street }), { duration: 500 });
timeout2(function() {
context.map().centerZoomEase(twelfthAvenue, 18, 500);
context.map().on("move.intro drawn.intro", function() {
var padding2 = 200 * Math.pow(2, context.map().zoom() - 18);
var box2 = pad(twelfthAvenue, padding2, context);
box2.width = box2.width / 2;
reveal(box2, helpHtml(string, { street1: street, street2: street }), { duration: 0 });
});
}, 600);
context.on("enter.intro", function() {
var ids2 = context.selectedIDs();
if (ids2.length === 1 && ids2[0] === _washingtonSegmentID) {
continueTo(multiSelect);
}
});
context.history().on("change.intro", function() {
if (!_washingtonSegmentID || !context.hasEntity(_washingtonSegmentID) || !context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
return continueTo(rightClickIntersection);
}
});
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
context.on("enter.intro", null);
context.history().on("change.intro", null);
nextStep();
}
}
function multiSelect() {
if (!_washingtonSegmentID || !context.hasEntity(_washingtonSegmentID) || !context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
return continueTo(rightClickIntersection);
}
var ids = context.selectedIDs();
var hasWashington = ids.indexOf(_washingtonSegmentID) !== -1;
var hasTwelfth = ids.indexOf(twelfthAvenueID) !== -1;
if (hasWashington && hasTwelfth) {
return continueTo(multiRightClick);
} else if (!hasWashington && !hasTwelfth) {
return continueTo(didSplit);
}
context.map().centerZoomEase(twelfthAvenue, 18, 500);
timeout2(function() {
var selected, other, padding, box;
if (hasWashington) {
selected = _t("intro.graph.name.washington-street");
other = _t("intro.graph.name.12th-avenue");
padding = 60 * Math.pow(2, context.map().zoom() - 18);
box = pad(twelfthAvenueEnd, padding, context);
box.width *= 3;
} else {
selected = _t("intro.graph.name.12th-avenue");
other = _t("intro.graph.name.washington-street");
padding = 200 * Math.pow(2, context.map().zoom() - 18);
box = pad(twelfthAvenue, padding, context);
box.width /= 2;
}
reveal(box, helpHtml("intro.lines.multi_select", { selected, other1: other }) + " " + helpHtml("intro.lines.add_to_selection_" + (context.lastPointerType() === "mouse" ? "click" : "touch"), { selected, other2: other }));
context.map().on("move.intro drawn.intro", function() {
if (hasWashington) {
selected = _t("intro.graph.name.washington-street");
other = _t("intro.graph.name.12th-avenue");
padding = 60 * Math.pow(2, context.map().zoom() - 18);
box = pad(twelfthAvenueEnd, padding, context);
box.width *= 3;
} else {
selected = _t("intro.graph.name.12th-avenue");
other = _t("intro.graph.name.washington-street");
padding = 200 * Math.pow(2, context.map().zoom() - 18);
box = pad(twelfthAvenue, padding, context);
box.width /= 2;
}
reveal(box, helpHtml("intro.lines.multi_select", { selected, other1: other }) + " " + helpHtml("intro.lines.add_to_selection_" + (context.lastPointerType() === "mouse" ? "click" : "touch"), { selected, other2: other }), { duration: 0 });
});
context.on("enter.intro", function() {
continueTo(multiSelect);
});
context.history().on("change.intro", function() {
if (!_washingtonSegmentID || !context.hasEntity(_washingtonSegmentID) || !context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
return continueTo(rightClickIntersection);
}
});
}, 600);
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
context.on("enter.intro", null);
context.history().on("change.intro", null);
nextStep();
}
}
function multiRightClick() {
if (!_washingtonSegmentID || !context.hasEntity(_washingtonSegmentID) || !context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
return continueTo(rightClickIntersection);
}
var padding = 200 * Math.pow(2, context.map().zoom() - 18);
var box = pad(twelfthAvenue, padding, context);
var rightClickString = helpHtml("intro.lines.multi_select_success") + helpHtml("intro.lines.multi_" + (context.lastPointerType() === "mouse" ? "rightclick" : "edit_menu_touch"));
reveal(box, rightClickString);
context.map().on("move.intro drawn.intro", function() {
var padding2 = 200 * Math.pow(2, context.map().zoom() - 18);
var box2 = pad(twelfthAvenue, padding2, context);
reveal(box2, rightClickString, { duration: 0 });
});
context.ui().editMenu().on("toggled.intro", function(open) {
if (!open)
return;
timeout2(function() {
var ids = context.selectedIDs();
if (ids.length === 2 && ids.indexOf(twelfthAvenueID) !== -1 && ids.indexOf(_washingtonSegmentID) !== -1) {
var node = selectMenuItem(context, "delete").node();
if (!node)
return;
continueTo(multiDelete);
} else if (ids.length === 1 && ids.indexOf(_washingtonSegmentID) !== -1) {
return continueTo(multiSelect);
} else {
return continueTo(didSplit);
}
}, 300);
});
context.history().on("change.intro", function() {
if (!_washingtonSegmentID || !context.hasEntity(_washingtonSegmentID) || !context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
return continueTo(rightClickIntersection);
}
});
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
context.ui().editMenu().on("toggled.intro", null);
context.history().on("change.intro", null);
nextStep();
}
}
function multiDelete() {
if (!_washingtonSegmentID || !context.hasEntity(_washingtonSegmentID) || !context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
return continueTo(rightClickIntersection);
}
var node = selectMenuItem(context, "delete").node();
if (!node)
return continueTo(multiRightClick);
reveal(".edit-menu", helpHtml("intro.lines.multi_delete"), { padding: 50 });
context.map().on("move.intro drawn.intro", function() {
reveal(".edit-menu", helpHtml("intro.lines.multi_delete"), { duration: 0, padding: 50 });
});
context.on("exit.intro", function() {
if (context.hasEntity(_washingtonSegmentID) || context.hasEntity(twelfthAvenueID)) {
return continueTo(multiSelect);
}
});
context.history().on("change.intro", function() {
if (context.hasEntity(_washingtonSegmentID) || context.hasEntity(twelfthAvenueID)) {
continueTo(retryDelete);
} else {
continueTo(play);
}
});
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
context.on("exit.intro", null);
context.history().on("change.intro", null);
nextStep();
}
}
function retryDelete() {
context.enter(modeBrowse(context));
var padding = 200 * Math.pow(2, context.map().zoom() - 18);
var box = pad(twelfthAvenue, padding, context);
reveal(box, helpHtml("intro.lines.retry_delete"), {
buttonText: _t.html("intro.ok"),
buttonCallback: function() {
continueTo(multiSelect);
}
});
function continueTo(nextStep) {
nextStep();
}
}
function play() {
dispatch10.call("done");
reveal(".ideditor", helpHtml("intro.lines.play", { next: _t("intro.buildings.title") }), {
tooltipBox: ".intro-nav-wrap .chapter-building",
buttonText: _t.html("intro.ok"),
buttonCallback: function() {
reveal(".ideditor");
}
});
}
chapter.enter = function() {
addLine();
};
chapter.exit = function() {
timeouts.forEach(window.clearTimeout);
select_default2(window).on("pointerdown.intro mousedown.intro", null, true);
context.on("enter.intro exit.intro", null);
context.map().on("move.intro drawn.intro", null);
context.history().on("change.intro", null);
context.container().select(".inspector-wrap").on("wheel.intro", null);
context.container().select(".preset-list-button").on("click.intro", null);
};
chapter.restart = function() {
chapter.exit();
chapter.enter();
};
return utilRebind(chapter, dispatch10, "on");
}
// modules/ui/intro/building.js
function uiIntroBuilding(context, reveal) {
var dispatch10 = dispatch_default("done");
var house = [-85.62815, 41.95638];
var tank = [-85.62732, 41.95347];
var buildingCatetory = _mainPresetIndex.item("category-building");
var housePreset = _mainPresetIndex.item("building/house");
var tankPreset = _mainPresetIndex.item("man_made/storage_tank");
var timeouts = [];
var _houseID = null;
var _tankID = null;
var chapter = {
title: "intro.buildings.title"
};
function timeout2(f2, t) {
timeouts.push(window.setTimeout(f2, t));
}
function eventCancel(d3_event) {
d3_event.stopPropagation();
d3_event.preventDefault();
}
function revealHouse(center, text2, options2) {
var padding = 160 * Math.pow(2, context.map().zoom() - 20);
var box = pad(center, padding, context);
reveal(box, text2, options2);
}
function revealTank(center, text2, options2) {
var padding = 190 * Math.pow(2, context.map().zoom() - 19.5);
var box = pad(center, padding, context);
reveal(box, text2, options2);
}
function addHouse() {
context.enter(modeBrowse(context));
context.history().reset("initial");
_houseID = null;
var msec = transitionTime(house, context.map().center());
if (msec) {
reveal(null, null, { duration: 0 });
}
context.map().centerZoomEase(house, 19, msec);
timeout2(function() {
var tooltip = reveal("button.add-area", helpHtml("intro.buildings.add_building"));
tooltip.selectAll(".popover-inner").insert("svg", "span").attr("class", "tooltip-illustration").append("use").attr("xlink:href", "#iD-graphic-buildings");
context.on("enter.intro", function(mode) {
if (mode.id !== "add-area")
return;
continueTo(startHouse);
});
}, msec + 100);
function continueTo(nextStep) {
context.on("enter.intro", null);
nextStep();
}
}
function startHouse() {
if (context.mode().id !== "add-area") {
return continueTo(addHouse);
}
_houseID = null;
context.map().zoomEase(20, 500);
timeout2(function() {
var startString = helpHtml("intro.buildings.start_building") + helpHtml("intro.buildings.building_corner_" + (context.lastPointerType() === "mouse" ? "click" : "tap"));
revealHouse(house, startString);
context.map().on("move.intro drawn.intro", function() {
revealHouse(house, startString, { duration: 0 });
});
context.on("enter.intro", function(mode) {
if (mode.id !== "draw-area")
return chapter.restart();
continueTo(continueHouse);
});
}, 550);
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
context.on("enter.intro", null);
nextStep();
}
}
function continueHouse() {
if (context.mode().id !== "draw-area") {
return continueTo(addHouse);
}
_houseID = null;
var continueString = helpHtml("intro.buildings.continue_building") + "{br}" + helpHtml("intro.areas.finish_area_" + (context.lastPointerType() === "mouse" ? "click" : "tap")) + helpHtml("intro.buildings.finish_building");
revealHouse(house, continueString);
context.map().on("move.intro drawn.intro", function() {
revealHouse(house, continueString, { duration: 0 });
});
context.on("enter.intro", function(mode) {
if (mode.id === "draw-area") {
return;
} else if (mode.id === "select") {
var graph = context.graph();
var way = context.entity(context.selectedIDs()[0]);
var nodes = graph.childNodes(way);
var points = utilArrayUniq(nodes).map(function(n2) {
return context.projection(n2.loc);
});
if (isMostlySquare(points)) {
_houseID = way.id;
return continueTo(chooseCategoryBuilding);
} else {
return continueTo(retryHouse);
}
} else {
return chapter.restart();
}
});
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
context.on("enter.intro", null);
nextStep();
}
}
function retryHouse() {
var onClick = function() {
continueTo(addHouse);
};
revealHouse(house, helpHtml("intro.buildings.retry_building"), { buttonText: _t.html("intro.ok"), buttonCallback: onClick });
context.map().on("move.intro drawn.intro", function() {
revealHouse(house, helpHtml("intro.buildings.retry_building"), { duration: 0, buttonText: _t.html("intro.ok"), buttonCallback: onClick });
});
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
nextStep();
}
}
function chooseCategoryBuilding() {
if (!_houseID || !context.hasEntity(_houseID)) {
return addHouse();
}
var ids = context.selectedIDs();
if (context.mode().id !== "select" || !ids.length || ids[0] !== _houseID) {
context.enter(modeSelect(context, [_houseID]));
}
context.container().select(".inspector-wrap").on("wheel.intro", eventCancel);
timeout2(function() {
context.container().select(".inspector-wrap .panewrap").style("right", "-100%");
var button = context.container().select(".preset-category-building .preset-list-button");
reveal(button.node(), helpHtml("intro.buildings.choose_category_building", { category: buildingCatetory.name() }));
button.on("click.intro", function() {
button.on("click.intro", null);
continueTo(choosePresetHouse);
});
}, 400);
context.on("enter.intro", function(mode) {
if (!_houseID || !context.hasEntity(_houseID)) {
return continueTo(addHouse);
}
var ids2 = context.selectedIDs();
if (mode.id !== "select" || !ids2.length || ids2[0] !== _houseID) {
return continueTo(chooseCategoryBuilding);
}
});
function continueTo(nextStep) {
context.container().select(".inspector-wrap").on("wheel.intro", null);
context.container().select(".preset-list-button").on("click.intro", null);
context.on("enter.intro", null);
nextStep();
}
}
function choosePresetHouse() {
if (!_houseID || !context.hasEntity(_houseID)) {
return addHouse();
}
var ids = context.selectedIDs();
if (context.mode().id !== "select" || !ids.length || ids[0] !== _houseID) {
context.enter(modeSelect(context, [_houseID]));
}
context.container().select(".inspector-wrap").on("wheel.intro", eventCancel);
timeout2(function() {
context.container().select(".inspector-wrap .panewrap").style("right", "-100%");
var button = context.container().select(".preset-building-house .preset-list-button");
reveal(button.node(), helpHtml("intro.buildings.choose_preset_house", { preset: housePreset.name() }), { duration: 300 });
button.on("click.intro", function() {
button.on("click.intro", null);
continueTo(closeEditorHouse);
});
}, 400);
context.on("enter.intro", function(mode) {
if (!_houseID || !context.hasEntity(_houseID)) {
return continueTo(addHouse);
}
var ids2 = context.selectedIDs();
if (mode.id !== "select" || !ids2.length || ids2[0] !== _houseID) {
return continueTo(chooseCategoryBuilding);
}
});
function continueTo(nextStep) {
context.container().select(".inspector-wrap").on("wheel.intro", null);
context.container().select(".preset-list-button").on("click.intro", null);
context.on("enter.intro", null);
nextStep();
}
}
function closeEditorHouse() {
if (!_houseID || !context.hasEntity(_houseID)) {
return addHouse();
}
var ids = context.selectedIDs();
if (context.mode().id !== "select" || !ids.length || ids[0] !== _houseID) {
context.enter(modeSelect(context, [_houseID]));
}
context.history().checkpoint("hasHouse");
context.on("exit.intro", function() {
continueTo(rightClickHouse);
});
timeout2(function() {
reveal(".entity-editor-pane", helpHtml("intro.buildings.close", { button: { html: icon("#iD-icon-close", "inline") } }));
}, 500);
function continueTo(nextStep) {
context.on("exit.intro", null);
nextStep();
}
}
function rightClickHouse() {
if (!_houseID)
return chapter.restart();
context.enter(modeBrowse(context));
context.history().reset("hasHouse");
var zoom = context.map().zoom();
if (zoom < 20) {
zoom = 20;
}
context.map().centerZoomEase(house, zoom, 500);
context.on("enter.intro", function(mode) {
if (mode.id !== "select")
return;
var ids = context.selectedIDs();
if (ids.length !== 1 || ids[0] !== _houseID)
return;
timeout2(function() {
var node = selectMenuItem(context, "orthogonalize").node();
if (!node)
return;
continueTo(clickSquare);
}, 50);
});
context.map().on("move.intro drawn.intro", function() {
var rightclickString = helpHtml("intro.buildings." + (context.lastPointerType() === "mouse" ? "rightclick_building" : "edit_menu_building_touch"));
revealHouse(house, rightclickString, { duration: 0 });
});
context.history().on("change.intro", function() {
continueTo(rightClickHouse);
});
function continueTo(nextStep) {
context.on("enter.intro", null);
context.map().on("move.intro drawn.intro", null);
context.history().on("change.intro", null);
nextStep();
}
}
function clickSquare() {
if (!_houseID)
return chapter.restart();
var entity = context.hasEntity(_houseID);
if (!entity)
return continueTo(rightClickHouse);
var node = selectMenuItem(context, "orthogonalize").node();
if (!node) {
return continueTo(rightClickHouse);
}
var wasChanged = false;
reveal(".edit-menu", helpHtml("intro.buildings.square_building"), { padding: 50 });
context.on("enter.intro", function(mode) {
if (mode.id === "browse") {
continueTo(rightClickHouse);
} else if (mode.id === "move" || mode.id === "rotate") {
continueTo(retryClickSquare);
}
});
context.map().on("move.intro", function() {
var node2 = selectMenuItem(context, "orthogonalize").node();
if (!wasChanged && !node2) {
return continueTo(rightClickHouse);
}
reveal(".edit-menu", helpHtml("intro.buildings.square_building"), { duration: 0, padding: 50 });
});
context.history().on("change.intro", function() {
wasChanged = true;
context.history().on("change.intro", null);
timeout2(function() {
if (context.history().undoAnnotation() === _t("operations.orthogonalize.annotation.feature", { n: 1 })) {
continueTo(doneSquare);
} else {
continueTo(retryClickSquare);
}
}, 500);
});
function continueTo(nextStep) {
context.on("enter.intro", null);
context.map().on("move.intro", null);
context.history().on("change.intro", null);
nextStep();
}
}
function retryClickSquare() {
context.enter(modeBrowse(context));
revealHouse(house, helpHtml("intro.buildings.retry_square"), {
buttonText: _t.html("intro.ok"),
buttonCallback: function() {
continueTo(rightClickHouse);
}
});
function continueTo(nextStep) {
nextStep();
}
}
function doneSquare() {
context.history().checkpoint("doneSquare");
revealHouse(house, helpHtml("intro.buildings.done_square"), {
buttonText: _t.html("intro.ok"),
buttonCallback: function() {
continueTo(addTank);
}
});
function continueTo(nextStep) {
nextStep();
}
}
function addTank() {
context.enter(modeBrowse(context));
context.history().reset("doneSquare");
_tankID = null;
var msec = transitionTime(tank, context.map().center());
if (msec) {
reveal(null, null, { duration: 0 });
}
context.map().centerZoomEase(tank, 19.5, msec);
timeout2(function() {
reveal("button.add-area", helpHtml("intro.buildings.add_tank"));
context.on("enter.intro", function(mode) {
if (mode.id !== "add-area")
return;
continueTo(startTank);
});
}, msec + 100);
function continueTo(nextStep) {
context.on("enter.intro", null);
nextStep();
}
}
function startTank() {
if (context.mode().id !== "add-area") {
return continueTo(addTank);
}
_tankID = null;
timeout2(function() {
var startString = helpHtml("intro.buildings.start_tank") + helpHtml("intro.buildings.tank_edge_" + (context.lastPointerType() === "mouse" ? "click" : "tap"));
revealTank(tank, startString);
context.map().on("move.intro drawn.intro", function() {
revealTank(tank, startString, { duration: 0 });
});
context.on("enter.intro", function(mode) {
if (mode.id !== "draw-area")
return chapter.restart();
continueTo(continueTank);
});
}, 550);
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
context.on("enter.intro", null);
nextStep();
}
}
function continueTank() {
if (context.mode().id !== "draw-area") {
return continueTo(addTank);
}
_tankID = null;
var continueString = helpHtml("intro.buildings.continue_tank") + "{br}" + helpHtml("intro.areas.finish_area_" + (context.lastPointerType() === "mouse" ? "click" : "tap")) + helpHtml("intro.buildings.finish_tank");
revealTank(tank, continueString);
context.map().on("move.intro drawn.intro", function() {
revealTank(tank, continueString, { duration: 0 });
});
context.on("enter.intro", function(mode) {
if (mode.id === "draw-area") {
return;
} else if (mode.id === "select") {
_tankID = context.selectedIDs()[0];
return continueTo(searchPresetTank);
} else {
return continueTo(addTank);
}
});
function continueTo(nextStep) {
context.map().on("move.intro drawn.intro", null);
context.on("enter.intro", null);
nextStep();
}
}
function searchPresetTank() {
if (!_tankID || !context.hasEntity(_tankID)) {
return addTank();
}
var ids = context.selectedIDs();
if (context.mode().id !== "select" || !ids.length || ids[0] !== _tankID) {
context.enter(modeSelect(context, [_tankID]));
}
context.container().select(".inspector-wrap").on("wheel.intro", eventCancel);
timeout2(function() {
context.container().select(".inspector-wrap .panewrap").style("right", "-100%");
context.container().select(".preset-search-input").on("keydown.intro", null).on("keyup.intro", checkPresetSearch);
reveal(".preset-search-input", helpHtml("intro.buildings.search_tank", { preset: tankPreset.name() }));
}, 400);
context.on("enter.intro", function(mode) {
if (!_tankID || !context.hasEntity(_tankID)) {
return continueTo(addTank);
}
var ids2 = context.selectedIDs();
if (mode.id !== "select" || !ids2.length || ids2[0] !== _tankID) {
context.enter(modeSelect(context, [_tankID]));
context.container().select(".inspector-wrap .panewrap").style("right", "-100%");
context.container().select(".inspector-wrap").on("wheel.intro", eventCancel);
context.container().select(".preset-search-input").on("keydown.intro", null).on("keyup.intro", checkPresetSearch);
reveal(".preset-search-input", helpHtml("intro.buildings.search_tank", { preset: tankPreset.name() }));
context.history().on("change.intro", null);
}
});
function checkPresetSearch() {
var first = context.container().select(".preset-list-item:first-child");
if (first.classed("preset-man_made-storage_tank")) {
reveal(first.select(".preset-list-button").node(), helpHtml("intro.buildings.choose_tank", { preset: tankPreset.name() }), { duration: 300 });
context.container().select(".preset-search-input").on("keydown.intro", eventCancel, true).on("keyup.intro", null);
context.history().on("change.intro", function() {
continueTo(closeEditorTank);
});
}
}
function continueTo(nextStep) {
context.container().select(".inspector-wrap").on("wheel.intro", null);
context.on("enter.intro", null);
context.history().on("change.intro", null);
context.container().select(".preset-search-input").on("keydown.intro keyup.intro", null);
nextStep();
}
}
function closeEditorTank() {
if (!_tankID || !context.hasEntity(_tankID)) {
return addTank();
}
var ids = context.selectedIDs();
if (context.mode().id !== "select" || !ids.length || ids[0] !== _tankID) {
context.enter(modeSelect(context, [_tankID]));
}
context.history().checkpoint("hasTank");
context.on("exit.intro", function() {
continueTo(rightClickTank);
});
timeout2(function() {
reveal(".entity-editor-pane", helpHtml("intro.buildings.close", { button: { html: icon("#iD-icon-close", "inline") } }));
}, 500);
function continueTo(nextStep) {
context.on("exit.intro", null);
nextStep();
}
}
function rightClickTank() {
if (!_tankID)
return continueTo(addTank);
context.enter(modeBrowse(context));
context.history().reset("hasTank");
context.map().centerEase(tank, 500);
timeout2(function() {
context.on("enter.intro", function(mode) {
if (mode.id !== "select")
return;
var ids = context.selectedIDs();
if (ids.length !== 1 || ids[0] !== _tankID)
return;
timeout2(function() {
var node = selectMenuItem(context, "circularize").node();
if (!node)
return;
continueTo(clickCircle);
}, 50);
});
var rightclickString = helpHtml("intro.buildings." + (context.lastPointerType() === "mouse" ? "rightclick_tank" : "edit_menu_tank_touch"));
revealTank(tank, rightclickString);
context.map().on("move.intro drawn.intro", function() {
revealTank(tank, rightclickString, { duration: 0 });
});
context.history().on("change.intro", function() {
continueTo(rightClickTank);
});
}, 600);
function continueTo(nextStep) {
context.on("enter.intro", null);
context.map().on("move.intro drawn.intro", null);
context.history().on("change.intro", null);
nextStep();
}
}
function clickCircle() {
if (!_tankID)
return chapter.restart();
var entity = context.hasEntity(_tankID);
if (!entity)
return continueTo(rightClickTank);
var node = selectMenuItem(context, "circularize").node();
if (!node) {
return continueTo(rightClickTank);
}
var wasChanged = false;
reveal(".edit-menu", helpHtml("intro.buildings.circle_tank"), { padding: 50 });
context.on("enter.intro", function(mode) {
if (mode.id === "browse") {
continueTo(rightClickTank);
} else if (mode.id === "move" || mode.id === "rotate") {
continueTo(retryClickCircle);
}
});
context.map().on("move.intro", function() {
var node2 = selectMenuItem(context, "circularize").node();
if (!wasChanged && !node2) {
return continueTo(rightClickTank);
}
reveal(".edit-menu", helpHtml("intro.buildings.circle_tank"), { duration: 0, padding: 50 });
});
context.history().on("change.intro", function() {
wasChanged = true;
context.history().on("change.intro", null);
timeout2(function() {
if (context.history().undoAnnotation() === _t("operations.circularize.annotation.feature", { n: 1 })) {
continueTo(play);
} else {
continueTo(retryClickCircle);
}
}, 500);
});
function continueTo(nextStep) {
context.on("enter.intro", null);
context.map().on("move.intro", null);
context.history().on("change.intro", null);
nextStep();
}
}
function retryClickCircle() {
context.enter(modeBrowse(context));
revealTank(tank, helpHtml("intro.buildings.retry_circle"), {
buttonText: _t.html("intro.ok"),
buttonCallback: function() {
continueTo(rightClickTank);
}
});
function continueTo(nextStep) {
nextStep();
}
}
function play() {
dispatch10.call("done");
reveal(".ideditor", helpHtml("intro.buildings.play", { next: _t("intro.startediting.title") }), {
tooltipBox: ".intro-nav-wrap .chapter-startEditing",
buttonText: _t.html("intro.ok"),
buttonCallback: function() {
reveal(".ideditor");
}
});
}
chapter.enter = function() {
addHouse();
};
chapter.exit = function() {
timeouts.forEach(window.clearTimeout);
context.on("enter.intro exit.intro", null);
context.map().on("move.intro drawn.intro", null);
context.history().on("change.intro", null);
context.container().select(".inspector-wrap").on("wheel.intro", null);
context.container().select(".preset-search-input").on("keydown.intro keyup.intro", null);
context.container().select(".more-fields .combobox-input").on("click.intro", null);
};
chapter.restart = function() {
chapter.exit();
chapter.enter();
};
return utilRebind(chapter, dispatch10, "on");
}
// modules/ui/intro/start_editing.js
function uiIntroStartEditing(context, reveal) {
var dispatch10 = dispatch_default("done", "startEditing");
var modalSelection = select_default2(null);
var chapter = {
title: "intro.startediting.title"
};
function showHelp() {
reveal(".map-control.help-control", helpHtml("intro.startediting.help"), {
buttonText: _t.html("intro.ok"),
buttonCallback: function() {
shortcuts();
}
});
}
function shortcuts() {
reveal(".map-control.help-control", helpHtml("intro.startediting.shortcuts"), {
buttonText: _t.html("intro.ok"),
buttonCallback: function() {
showSave();
}
});
}
function showSave() {
context.container().selectAll(".shaded").remove();
reveal(".top-toolbar button.save", helpHtml("intro.startediting.save"), {
buttonText: _t.html("intro.ok"),
buttonCallback: function() {
showStart();
}
});
}
function showStart() {
context.container().selectAll(".shaded").remove();
modalSelection = uiModal(context.container());
modalSelection.select(".modal").attr("class", "modal-splash modal");
modalSelection.selectAll(".close").remove();
var startbutton = modalSelection.select(".content").attr("class", "fillL").append("button").attr("class", "modal-section huge-modal-button").on("click", function() {
modalSelection.remove();
});
startbutton.append("svg").attr("class", "illustration").append("use").attr("xlink:href", "#iD-logo-walkthrough");
startbutton.append("h2").call(_t.append("intro.startediting.start"));
dispatch10.call("startEditing");
}
chapter.enter = function() {
showHelp();
};
chapter.exit = function() {
modalSelection.remove();
context.container().selectAll(".shaded").remove();
};
return utilRebind(chapter, dispatch10, "on");
}
// modules/ui/intro/intro.js
var chapterUi = {
welcome: uiIntroWelcome,
navigation: uiIntroNavigation,
point: uiIntroPoint,
area: uiIntroArea,
line: uiIntroLine,
building: uiIntroBuilding,
startEditing: uiIntroStartEditing
};
var chapterFlow = [
"welcome",
"navigation",
"point",
"area",
"line",
"building",
"startEditing"
];
function uiIntro(context) {
const INTRO_IMAGERY = "EsriWorldImageryClarity";
let _introGraph = {};
let _currChapter;
function intro(selection2) {
_mainFileFetcher.get("intro_graph").then((dataIntroGraph) => {
for (let id2 in dataIntroGraph) {
if (!_introGraph[id2]) {
_introGraph[id2] = osmEntity(localize(dataIntroGraph[id2]));
}
}
selection2.call(startIntro);
}).catch(function() {
});
}
function startIntro(selection2) {
context.enter(modeBrowse(context));
let osm = context.connection();
let history = context.history().toJSON();
let hash = window.location.hash;
let center = context.map().center();
let zoom = context.map().zoom();
let background = context.background().baseLayerSource();
let overlays = context.background().overlayLayerSources();
let opacity = context.container().selectAll(".main-map .layer-background").style("opacity");
let caches = osm && osm.caches();
let baseEntities = context.history().graph().base().entities;
context.ui().sidebar.expand();
context.container().selectAll("button.sidebar-toggle").classed("disabled", true);
context.inIntro(true);
if (osm) {
osm.toggle(false).reset();
}
context.history().reset();
context.history().merge(Object.values(coreGraph().load(_introGraph).entities));
context.history().checkpoint("initial");
let imagery = context.background().findSource(INTRO_IMAGERY);
if (imagery) {
context.background().baseLayerSource(imagery);
} else {
context.background().bing();
}
overlays.forEach((d) => context.background().toggleOverlayLayer(d));
let layers = context.layers();
layers.all().forEach((item) => {
if (typeof item.layer.enabled === "function") {
item.layer.enabled(item.id === "osm");
}
});
context.container().selectAll(".main-map .layer-background").style("opacity", 1);
let curtain = uiCurtain(context.container().node());
selection2.call(curtain);
corePreferences("walkthrough_started", "yes");
let storedProgress = corePreferences("walkthrough_progress") || "";
let progress = storedProgress.split(";").filter(Boolean);
let chapters = chapterFlow.map((chapter, i2) => {
let s = chapterUi[chapter](context, curtain.reveal).on("done", () => {
buttons.filter((d) => d.title === s.title).classed("finished", true);
if (i2 < chapterFlow.length - 1) {
const next = chapterFlow[i2 + 1];
context.container().select(`button.chapter-${next}`).classed("next", true);
}
progress.push(chapter);
corePreferences("walkthrough_progress", utilArrayUniq(progress).join(";"));
});
return s;
});
chapters[chapters.length - 1].on("startEditing", () => {
progress.push("startEditing");
corePreferences("walkthrough_progress", utilArrayUniq(progress).join(";"));
let incomplete = utilArrayDifference(chapterFlow, progress);
if (!incomplete.length) {
corePreferences("walkthrough_completed", "yes");
}
curtain.remove();
navwrap.remove();
context.container().selectAll(".main-map .layer-background").style("opacity", opacity);
context.container().selectAll("button.sidebar-toggle").classed("disabled", false);
if (osm) {
osm.toggle(true).reset().caches(caches);
}
context.history().reset().merge(Object.values(baseEntities));
context.background().baseLayerSource(background);
overlays.forEach((d) => context.background().toggleOverlayLayer(d));
if (history) {
context.history().fromJSON(history, false);
}
context.map().centerZoom(center, zoom);
window.location.replace(hash);
context.inIntro(false);
});
let navwrap = selection2.append("div").attr("class", "intro-nav-wrap fillD");
navwrap.append("svg").attr("class", "intro-nav-wrap-logo").append("use").attr("xlink:href", "#iD-logo-walkthrough");
let buttonwrap = navwrap.append("div").attr("class", "joined").selectAll("button.chapter");
let buttons = buttonwrap.data(chapters).enter().append("button").attr("class", (d, i2) => `chapter chapter-${chapterFlow[i2]}`).on("click", enterChapter);
buttons.append("span").html((d) => _t.html(d.title));
buttons.append("span").attr("class", "status").call(svgIcon(_mainLocalizer.textDirection() === "rtl" ? "#iD-icon-backward" : "#iD-icon-forward", "inline"));
enterChapter(null, chapters[0]);
function enterChapter(d3_event, newChapter) {
if (_currChapter) {
_currChapter.exit();
}
context.enter(modeBrowse(context));
_currChapter = newChapter;
_currChapter.enter();
buttons.classed("next", false).classed("active", (d) => d.title === _currChapter.title);
}
}
return intro;
}
// modules/ui/issues_info.js
function uiIssuesInfo(context) {
var warningsItem = {
id: "warnings",
count: 0,
iconID: "iD-icon-alert",
descriptionID: "issues.warnings_and_errors"
};
var resolvedItem = {
id: "resolved",
count: 0,
iconID: "iD-icon-apply",
descriptionID: "issues.user_resolved_issues"
};
function update(selection2) {
var shownItems = [];
var liveIssues = context.validator().getIssues({
what: corePreferences("validate-what") || "edited",
where: corePreferences("validate-where") || "all"
});
if (liveIssues.length) {
warningsItem.count = liveIssues.length;
shownItems.push(warningsItem);
}
if (corePreferences("validate-what") === "all") {
var resolvedIssues = context.validator().getResolvedIssues();
if (resolvedIssues.length) {
resolvedItem.count = resolvedIssues.length;
shownItems.push(resolvedItem);
}
}
var chips = selection2.selectAll(".chip").data(shownItems, function(d) {
return d.id;
});
chips.exit().remove();
var enter = chips.enter().append("a").attr("class", function(d) {
return "chip " + d.id + "-count";
}).attr("href", "#").each(function(d) {
var chipSelection = select_default2(this);
var tooltipBehavior = uiTooltip().placement("top").title(_t.html(d.descriptionID));
chipSelection.call(tooltipBehavior).on("click", function(d3_event) {
d3_event.preventDefault();
tooltipBehavior.hide(select_default2(this));
context.ui().togglePanes(context.container().select(".map-panes .issues-pane"));
});
chipSelection.call(svgIcon("#" + d.iconID));
});
enter.append("span").attr("class", "count");
enter.merge(chips).selectAll("span.count").text(function(d) {
return d.count.toString();
});
}
return function(selection2) {
update(selection2);
context.validator().on("validated.infobox", function() {
update(selection2);
});
};
}
// modules/ui/map_in_map.js
function uiMapInMap(context) {
function mapInMap(selection2) {
var backgroundLayer = rendererTileLayer(context);
var overlayLayers = {};
var projection2 = geoRawMercator();
var dataLayer = svgData(projection2, context).showLabels(false);
var debugLayer = svgDebug(projection2, context);
var zoom = zoom_default2().scaleExtent([geoZoomToScale(0.5), geoZoomToScale(24)]).on("start", zoomStarted).on("zoom", zoomed).on("end", zoomEnded);
var wrap2 = select_default2(null);
var tiles = select_default2(null);
var viewport = select_default2(null);
var _isTransformed = false;
var _isHidden = true;
var _skipEvents = false;
var _gesture = null;
var _zDiff = 6;
var _dMini;
var _cMini;
var _tStart;
var _tCurr;
var _timeoutID;
function zoomStarted() {
if (_skipEvents)
return;
_tStart = _tCurr = projection2.transform();
_gesture = null;
}
function zoomed(d3_event) {
if (_skipEvents)
return;
var x = d3_event.transform.x;
var y = d3_event.transform.y;
var k = d3_event.transform.k;
var isZooming = k !== _tStart.k;
var isPanning = x !== _tStart.x || y !== _tStart.y;
if (!isZooming && !isPanning) {
return;
}
if (!_gesture) {
_gesture = isZooming ? "zoom" : "pan";
}
var tMini = projection2.transform();
var tX, tY, scale;
if (_gesture === "zoom") {
scale = k / tMini.k;
tX = (_cMini[0] / scale - _cMini[0]) * scale;
tY = (_cMini[1] / scale - _cMini[1]) * scale;
} else {
k = tMini.k;
scale = 1;
tX = x - tMini.x;
tY = y - tMini.y;
}
utilSetTransform(tiles, tX, tY, scale);
utilSetTransform(viewport, 0, 0, scale);
_isTransformed = true;
_tCurr = identity2.translate(x, y).scale(k);
var zMain = geoScaleToZoom(context.projection.scale());
var zMini = geoScaleToZoom(k);
_zDiff = zMain - zMini;
queueRedraw();
}
function zoomEnded() {
if (_skipEvents)
return;
if (_gesture !== "pan")
return;
updateProjection();
_gesture = null;
context.map().center(projection2.invert(_cMini));
}
function updateProjection() {
var loc = context.map().center();
var tMain = context.projection.transform();
var zMain = geoScaleToZoom(tMain.k);
var zMini = Math.max(zMain - _zDiff, 0.5);
var kMini = geoZoomToScale(zMini);
projection2.translate([tMain.x, tMain.y]).scale(kMini);
var point = projection2(loc);
var mouse = _gesture === "pan" ? geoVecSubtract([_tCurr.x, _tCurr.y], [_tStart.x, _tStart.y]) : [0, 0];
var xMini = _cMini[0] - point[0] + tMain.x + mouse[0];
var yMini = _cMini[1] - point[1] + tMain.y + mouse[1];
projection2.translate([xMini, yMini]).clipExtent([[0, 0], _dMini]);
_tCurr = projection2.transform();
if (_isTransformed) {
utilSetTransform(tiles, 0, 0);
utilSetTransform(viewport, 0, 0);
_isTransformed = false;
}
zoom.scaleExtent([geoZoomToScale(0.5), geoZoomToScale(zMain - 3)]);
_skipEvents = true;
wrap2.call(zoom.transform, _tCurr);
_skipEvents = false;
}
function redraw() {
clearTimeout(_timeoutID);
if (_isHidden)
return;
updateProjection();
var zMini = geoScaleToZoom(projection2.scale());
tiles = wrap2.selectAll(".map-in-map-tiles").data([0]);
tiles = tiles.enter().append("div").attr("class", "map-in-map-tiles").merge(tiles);
backgroundLayer.source(context.background().baseLayerSource()).projection(projection2).dimensions(_dMini);
var background = tiles.selectAll(".map-in-map-background").data([0]);
background.enter().append("div").attr("class", "map-in-map-background").merge(background).call(backgroundLayer);
var overlaySources = context.background().overlayLayerSources();
var activeOverlayLayers = [];
for (var i2 = 0; i2 < overlaySources.length; i2++) {
if (overlaySources[i2].validZoom(zMini)) {
if (!overlayLayers[i2])
overlayLayers[i2] = rendererTileLayer(context);
activeOverlayLayers.push(overlayLayers[i2].source(overlaySources[i2]).projection(projection2).dimensions(_dMini));
}
}
var overlay = tiles.selectAll(".map-in-map-overlay").data([0]);
overlay = overlay.enter().append("div").attr("class", "map-in-map-overlay").merge(overlay);
var overlays = overlay.selectAll("div").data(activeOverlayLayers, function(d) {
return d.source().name();
});
overlays.exit().remove();
overlays = overlays.enter().append("div").merge(overlays).each(function(layer) {
select_default2(this).call(layer);
});
var dataLayers = tiles.selectAll(".map-in-map-data").data([0]);
dataLayers.exit().remove();
dataLayers = dataLayers.enter().append("svg").attr("class", "map-in-map-data").merge(dataLayers).call(dataLayer).call(debugLayer);
if (_gesture !== "pan") {
var getPath = path_default(projection2);
var bbox = { type: "Polygon", coordinates: [context.map().extent().polygon()] };
viewport = wrap2.selectAll(".map-in-map-viewport").data([0]);
viewport = viewport.enter().append("svg").attr("class", "map-in-map-viewport").merge(viewport);
var path = viewport.selectAll(".map-in-map-bbox").data([bbox]);
path.enter().append("path").attr("class", "map-in-map-bbox").merge(path).attr("d", getPath).classed("thick", function(d) {
return getPath.area(d) < 30;
});
}
}
function queueRedraw() {
clearTimeout(_timeoutID);
_timeoutID = setTimeout(function() {
redraw();
}, 750);
}
function toggle(d3_event) {
if (d3_event)
d3_event.preventDefault();
_isHidden = !_isHidden;
context.container().select(".minimap-toggle-item").classed("active", !_isHidden).select("input").property("checked", !_isHidden);
if (_isHidden) {
wrap2.style("display", "block").style("opacity", "1").transition().duration(200).style("opacity", "0").on("end", function() {
selection2.selectAll(".map-in-map").style("display", "none");
});
} else {
wrap2.style("display", "block").style("opacity", "0").transition().duration(200).style("opacity", "1").on("end", function() {
redraw();
});
}
}
uiMapInMap.toggle = toggle;
wrap2 = selection2.selectAll(".map-in-map").data([0]);
wrap2 = wrap2.enter().append("div").attr("class", "map-in-map").style("display", _isHidden ? "none" : "block").call(zoom).on("dblclick.zoom", null).merge(wrap2);
_dMini = [200, 150];
_cMini = geoVecScale(_dMini, 0.5);
context.map().on("drawn.map-in-map", function(drawn) {
if (drawn.full === true) {
redraw();
}
});
redraw();
context.keybinding().on(_t("background.minimap.key"), toggle);
}
return mapInMap;
}
// modules/ui/notice.js
function uiNotice(context) {
return function(selection2) {
var div = selection2.append("div").attr("class", "notice");
var button = div.append("button").attr("class", "zoom-to notice fillD").on("click", function() {
context.map().zoomEase(context.minEditableZoom());
}).on("wheel", function(d3_event) {
var e22 = new WheelEvent(d3_event.type, d3_event);
context.surface().node().dispatchEvent(e22);
});
button.call(svgIcon("#iD-icon-plus", "pre-text")).append("span").attr("class", "label").call(_t.append("zoom_in_edit"));
function disableTooHigh() {
var canEdit = context.map().zoom() >= context.minEditableZoom();
div.style("display", canEdit ? "none" : "block");
}
context.map().on("move.notice", debounce_default(disableTooHigh, 500));
disableTooHigh();
};
}
// modules/ui/photoviewer.js
function uiPhotoviewer(context) {
var dispatch10 = dispatch_default("resize");
var _pointerPrefix = "PointerEvent" in window ? "pointer" : "mouse";
function photoviewer(selection2) {
selection2.append("button").attr("class", "thumb-hide").attr("title", _t("icons.close")).on("click", function() {
if (services.streetside) {
services.streetside.hideViewer(context);
}
if (services.mapillary) {
services.mapillary.hideViewer(context);
}
if (services.kartaview) {
services.kartaview.hideViewer(context);
}
}).append("div").call(svgIcon("#iD-icon-close"));
function preventDefault(d3_event) {
d3_event.preventDefault();
}
selection2.append("button").attr("class", "resize-handle-xy").on("touchstart touchdown touchend", preventDefault).on(_pointerPrefix + "down", buildResizeListener(selection2, "resize", dispatch10, { resizeOnX: true, resizeOnY: true }));
selection2.append("button").attr("class", "resize-handle-x").on("touchstart touchdown touchend", preventDefault).on(_pointerPrefix + "down", buildResizeListener(selection2, "resize", dispatch10, { resizeOnX: true }));
selection2.append("button").attr("class", "resize-handle-y").on("touchstart touchdown touchend", preventDefault).on(_pointerPrefix + "down", buildResizeListener(selection2, "resize", dispatch10, { resizeOnY: true }));
function buildResizeListener(target, eventName, dispatch11, options2) {
var resizeOnX = !!options2.resizeOnX;
var resizeOnY = !!options2.resizeOnY;
var minHeight = options2.minHeight || 240;
var minWidth = options2.minWidth || 320;
var pointerId;
var startX;
var startY;
var startWidth;
var startHeight;
function startResize(d3_event) {
if (pointerId !== (d3_event.pointerId || "mouse"))
return;
d3_event.preventDefault();
d3_event.stopPropagation();
var mapSize = context.map().dimensions();
if (resizeOnX) {
var maxWidth = mapSize[0];
var newWidth = clamp3(startWidth + d3_event.clientX - startX, minWidth, maxWidth);
target.style("width", newWidth + "px");
}
if (resizeOnY) {
var maxHeight = mapSize[1] - 90;
var newHeight = clamp3(startHeight + startY - d3_event.clientY, minHeight, maxHeight);
target.style("height", newHeight + "px");
}
dispatch11.call(eventName, target, utilGetDimensions(target, true));
}
function clamp3(num, min3, max3) {
return Math.max(min3, Math.min(num, max3));
}
function stopResize(d3_event) {
if (pointerId !== (d3_event.pointerId || "mouse"))
return;
d3_event.preventDefault();
d3_event.stopPropagation();
select_default2(window).on("." + eventName, null);
}
return function initResize(d3_event) {
d3_event.preventDefault();
d3_event.stopPropagation();
pointerId = d3_event.pointerId || "mouse";
startX = d3_event.clientX;
startY = d3_event.clientY;
var targetRect = target.node().getBoundingClientRect();
startWidth = targetRect.width;
startHeight = targetRect.height;
select_default2(window).on(_pointerPrefix + "move." + eventName, startResize, false).on(_pointerPrefix + "up." + eventName, stopResize, false);
if (_pointerPrefix === "pointer") {
select_default2(window).on("pointercancel." + eventName, stopResize, false);
}
};
}
}
photoviewer.onMapResize = function() {
var photoviewer2 = context.container().select(".photoviewer");
var content = context.container().select(".main-content");
var mapDimensions = utilGetDimensions(content, true);
var photoDimensions = utilGetDimensions(photoviewer2, true);
if (photoDimensions[0] > mapDimensions[0] || photoDimensions[1] > mapDimensions[1] - 90) {
var setPhotoDimensions = [
Math.min(photoDimensions[0], mapDimensions[0]),
Math.min(photoDimensions[1], mapDimensions[1] - 90)
];
photoviewer2.style("width", setPhotoDimensions[0] + "px").style("height", setPhotoDimensions[1] + "px");
dispatch10.call("resize", photoviewer2, setPhotoDimensions);
}
};
return utilRebind(photoviewer, dispatch10, "on");
}
// modules/ui/restore.js
function uiRestore(context) {
return function(selection2) {
if (!context.history().hasRestorableChanges())
return;
let modalSelection = uiModal(selection2, true);
modalSelection.select(".modal").attr("class", "modal fillL");
let introModal = modalSelection.select(".content");
introModal.append("div").attr("class", "modal-section").append("h3").call(_t.append("restore.heading"));
introModal.append("div").attr("class", "modal-section").append("p").call(_t.append("restore.description"));
let buttonWrap = introModal.append("div").attr("class", "modal-actions");
let restore = buttonWrap.append("button").attr("class", "restore").on("click", () => {
context.history().restore();
modalSelection.remove();
});
restore.append("svg").attr("class", "logo logo-restore").append("use").attr("xlink:href", "#iD-logo-restore");
restore.append("div").call(_t.append("restore.restore"));
let reset = buttonWrap.append("button").attr("class", "reset").on("click", () => {
context.history().clearSaved();
modalSelection.remove();
});
reset.append("svg").attr("class", "logo logo-reset").append("use").attr("xlink:href", "#iD-logo-reset");
reset.append("div").call(_t.append("restore.reset"));
restore.node().focus();
};
}
// modules/ui/scale.js
function uiScale(context) {
var projection2 = context.projection, isImperial = !_mainLocalizer.usesMetric(), maxLength = 180, tickHeight = 8;
function scaleDefs(loc1, loc2) {
var lat = (loc2[1] + loc1[1]) / 2, conversion = isImperial ? 3.28084 : 1, dist = geoLonToMeters(loc2[0] - loc1[0], lat) * conversion, scale = { dist: 0, px: 0, text: "" }, buckets, i2, val, dLon;
if (isImperial) {
buckets = [528e4, 528e3, 52800, 5280, 500, 50, 5, 1];
} else {
buckets = [5e6, 5e5, 5e4, 5e3, 500, 50, 5, 1];
}
for (i2 = 0; i2 < buckets.length; i2++) {
val = buckets[i2];
if (dist >= val) {
scale.dist = Math.floor(dist / val) * val;
break;
} else {
scale.dist = +dist.toFixed(2);
}
}
dLon = geoMetersToLon(scale.dist / conversion, lat);
scale.px = Math.round(projection2([loc1[0] + dLon, loc1[1]])[0]);
scale.text = displayLength(scale.dist / conversion, isImperial);
return scale;
}
function update(selection2) {
var dims = context.map().dimensions(), loc1 = projection2.invert([0, dims[1]]), loc2 = projection2.invert([maxLength, dims[1]]), scale = scaleDefs(loc1, loc2);
selection2.select(".scale-path").attr("d", "M0.5,0.5v" + tickHeight + "h" + scale.px + "v-" + tickHeight);
selection2.select(".scale-text").style(_mainLocalizer.textDirection() === "ltr" ? "left" : "right", scale.px + 16 + "px").text(scale.text);
}
return function(selection2) {
function switchUnits() {
isImperial = !isImperial;
selection2.call(update);
}
var scalegroup = selection2.append("svg").attr("class", "scale").on("click", switchUnits).append("g").attr("transform", "translate(10,11)");
scalegroup.append("path").attr("class", "scale-path");
selection2.append("div").attr("class", "scale-text");
selection2.call(update);
context.map().on("move.scale", function() {
update(selection2);
});
};
}
// modules/ui/shortcuts.js
function uiShortcuts(context) {
var detected = utilDetect();
var _activeTab = 0;
var _modalSelection;
var _selection = select_default2(null);
var _dataShortcuts;
function shortcutsModal(_modalSelection2) {
_modalSelection2.select(".modal").classed("modal-shortcuts", true);
var content = _modalSelection2.select(".content");
content.append("div").attr("class", "modal-section header").append("h2").call(_t.append("shortcuts.title"));
_mainFileFetcher.get("shortcuts").then(function(data) {
_dataShortcuts = data;
content.call(render);
}).catch(function() {
});
}
function render(selection2) {
if (!_dataShortcuts)
return;
var wrapper = selection2.selectAll(".wrapper").data([0]);
var wrapperEnter = wrapper.enter().append("div").attr("class", "wrapper modal-section");
var tabsBar = wrapperEnter.append("div").attr("class", "tabs-bar");
var shortcutsList = wrapperEnter.append("div").attr("class", "shortcuts-list");
wrapper = wrapper.merge(wrapperEnter);
var tabs = tabsBar.selectAll(".tab").data(_dataShortcuts);
var tabsEnter = tabs.enter().append("a").attr("class", "tab").attr("href", "#").on("click", function(d3_event, d) {
d3_event.preventDefault();
var i2 = _dataShortcuts.indexOf(d);
_activeTab = i2;
render(selection2);
});
tabsEnter.append("span").html(function(d) {
return _t.html(d.text);
});
wrapper.selectAll(".tab").classed("active", function(d, i2) {
return i2 === _activeTab;
});
var shortcuts = shortcutsList.selectAll(".shortcut-tab").data(_dataShortcuts);
var shortcutsEnter = shortcuts.enter().append("div").attr("class", function(d) {
return "shortcut-tab shortcut-tab-" + d.tab;
});
var columnsEnter = shortcutsEnter.selectAll(".shortcut-column").data(function(d) {
return d.columns;
}).enter().append("table").attr("class", "shortcut-column");
var rowsEnter = columnsEnter.selectAll(".shortcut-row").data(function(d) {
return d.rows;
}).enter().append("tr").attr("class", "shortcut-row");
var sectionRows = rowsEnter.filter(function(d) {
return !d.shortcuts;
});
sectionRows.append("td");
sectionRows.append("td").attr("class", "shortcut-section").append("h3").html(function(d) {
return _t.html(d.text);
});
var shortcutRows = rowsEnter.filter(function(d) {
return d.shortcuts;
});
var shortcutKeys = shortcutRows.append("td").attr("class", "shortcut-keys");
var modifierKeys = shortcutKeys.filter(function(d) {
return d.modifiers;
});
modifierKeys.selectAll("kbd.modifier").data(function(d) {
if (detected.os === "win" && d.text === "shortcuts.editing.commands.redo") {
return ["\u2318"];
} else if (detected.os !== "mac" && d.text === "shortcuts.browsing.display_options.fullscreen") {
return [];
} else {
return d.modifiers;
}
}).enter().each(function() {
var selection3 = select_default2(this);
selection3.append("kbd").attr("class", "modifier").text(function(d) {
return uiCmd.display(d);
});
selection3.append("span").text("+");
});
shortcutKeys.selectAll("kbd.shortcut").data(function(d) {
var arr = d.shortcuts;
if (detected.os === "win" && d.text === "shortcuts.editing.commands.redo") {
arr = ["Y"];
} else if (detected.os !== "mac" && d.text === "shortcuts.browsing.display_options.fullscreen") {
arr = ["F11"];
}
arr = arr.map(function(s) {
return uiCmd.display(s.indexOf(".") !== -1 ? _t(s) : s);
});
return utilArrayUniq(arr).map(function(s) {
return {
shortcut: s,
separator: d.separator,
suffix: d.suffix
};
});
}).enter().each(function(d, i2, nodes) {
var selection3 = select_default2(this);
var click = d.shortcut.toLowerCase().match(/(.*).click/);
if (click && click[1]) {
selection3.call(svgIcon("#iD-walkthrough-mouse-" + click[1], "operation"));
} else if (d.shortcut.toLowerCase() === "long-press") {
selection3.call(svgIcon("#iD-walkthrough-longpress", "longpress operation"));
} else if (d.shortcut.toLowerCase() === "tap") {
selection3.call(svgIcon("#iD-walkthrough-tap", "tap operation"));
} else {
selection3.append("kbd").attr("class", "shortcut").text(function(d2) {
return d2.shortcut;
});
}
if (i2 < nodes.length - 1) {
selection3.append("span").html(d.separator || "\xA0" + _t.html("shortcuts.or") + "\xA0");
} else if (i2 === nodes.length - 1 && d.suffix) {
selection3.append("span").text(d.suffix);
}
});
shortcutKeys.filter(function(d) {
return d.gesture;
}).each(function() {
var selection3 = select_default2(this);
selection3.append("span").text("+");
selection3.append("span").attr("class", "gesture").html(function(d) {
return _t.html(d.gesture);
});
});
shortcutRows.append("td").attr("class", "shortcut-desc").html(function(d) {
return d.text ? _t.html(d.text) : "\xA0";
});
wrapper.selectAll(".shortcut-tab").style("display", function(d, i2) {
return i2 === _activeTab ? "flex" : "none";
});
}
return function(selection2, show) {
_selection = selection2;
if (show) {
_modalSelection = uiModal(selection2);
_modalSelection.call(shortcutsModal);
} else {
context.keybinding().on([_t("shortcuts.toggle.key"), "?"], function() {
if (context.container().selectAll(".modal-shortcuts").size()) {
if (_modalSelection) {
_modalSelection.close();
_modalSelection = null;
}
} else {
_modalSelection = uiModal(_selection);
_modalSelection.call(shortcutsModal);
}
});
}
};
}
// modules/ui/data_header.js
function uiDataHeader() {
var _datum;
function dataHeader(selection2) {
var header = selection2.selectAll(".data-header").data(_datum ? [_datum] : [], function(d) {
return d.__featurehash__;
});
header.exit().remove();
var headerEnter = header.enter().append("div").attr("class", "data-header");
var iconEnter = headerEnter.append("div").attr("class", "data-header-icon");
iconEnter.append("div").attr("class", "preset-icon-28").call(svgIcon("#iD-icon-data", "note-fill"));
headerEnter.append("div").attr("class", "data-header-label").call(_t.append("map_data.layers.custom.title"));
}
dataHeader.datum = function(val) {
if (!arguments.length)
return _datum;
_datum = val;
return this;
};
return dataHeader;
}
// modules/ui/combobox.js
var _comboHideTimerID;
function uiCombobox(context, klass) {
var dispatch10 = dispatch_default("accept", "cancel");
var container = context.container();
var _suggestions = [];
var _data = [];
var _fetched = {};
var _selected = null;
var _canAutocomplete = true;
var _caseSensitive = false;
var _cancelFetch = false;
var _minItems = 2;
var _tDown = 0;
var _mouseEnterHandler, _mouseLeaveHandler;
var _fetcher = function(val, cb) {
cb(_data.filter(function(d) {
var terms = d.terms || [];
terms.push(d.value);
return terms.some(function(term) {
return term.toString().toLowerCase().indexOf(val.toLowerCase()) !== -1;
});
}));
};
var combobox = function(input, attachTo) {
if (!input || input.empty())
return;
input.classed("combobox-input", true).on("focus.combo-input", focus).on("blur.combo-input", blur).on("keydown.combo-input", keydown).on("keyup.combo-input", keyup).on("input.combo-input", change).on("mousedown.combo-input", mousedown).each(function() {
var parent = this.parentNode;
var sibling = this.nextSibling;
select_default2(parent).selectAll(".combobox-caret").filter(function(d) {
return d === input.node();
}).data([input.node()]).enter().insert("div", function() {
return sibling;
}).attr("class", "combobox-caret").on("mousedown.combo-caret", function(d3_event) {
d3_event.preventDefault();
input.node().focus();
mousedown(d3_event);
}).on("mouseup.combo-caret", function(d3_event) {
d3_event.preventDefault();
mouseup(d3_event);
});
});
function mousedown(d3_event) {
if (d3_event.button !== 0)
return;
if (input.classed("disabled"))
return;
_tDown = +new Date();
var start2 = input.property("selectionStart");
var end = input.property("selectionEnd");
if (start2 !== end) {
var val = utilGetSetValue(input);
input.node().setSelectionRange(val.length, val.length);
return;
}
input.on("mouseup.combo-input", mouseup);
}
function mouseup(d3_event) {
input.on("mouseup.combo-input", null);
if (d3_event.button !== 0)
return;
if (input.classed("disabled"))
return;
if (input.node() !== document.activeElement)
return;
var start2 = input.property("selectionStart");
var end = input.property("selectionEnd");
if (start2 !== end)
return;
var combo = container.selectAll(".combobox");
if (combo.empty() || combo.datum() !== input.node()) {
var tOrig = _tDown;
window.setTimeout(function() {
if (tOrig !== _tDown)
return;
fetchComboData("", function() {
show();
render();
});
}, 250);
} else {
hide();
}
}
function focus() {
fetchComboData("");
}
function blur() {
_comboHideTimerID = window.setTimeout(hide, 75);
}
function show() {
hide();
container.insert("div", ":first-child").datum(input.node()).attr("class", "combobox" + (klass ? " combobox-" + klass : "")).style("position", "absolute").style("display", "block").style("left", "0px").on("mousedown.combo-container", function(d3_event) {
d3_event.preventDefault();
});
container.on("scroll.combo-scroll", render, true);
}
function hide() {
if (_comboHideTimerID) {
window.clearTimeout(_comboHideTimerID);
_comboHideTimerID = void 0;
}
container.selectAll(".combobox").remove();
container.on("scroll.combo-scroll", null);
}
function keydown(d3_event) {
var shown = !container.selectAll(".combobox").empty();
var tagName = input.node() ? input.node().tagName.toLowerCase() : "";
switch (d3_event.keyCode) {
case 8:
case 46:
d3_event.stopPropagation();
_selected = null;
render();
input.on("input.combo-input", function() {
var start2 = input.property("selectionStart");
input.node().setSelectionRange(start2, start2);
input.on("input.combo-input", change);
});
break;
case 9:
accept(d3_event);
break;
case 13:
d3_event.preventDefault();
d3_event.stopPropagation();
break;
case 38:
if (tagName === "textarea" && !shown)
return;
d3_event.preventDefault();
if (tagName === "input" && !shown) {
show();
}
nav(-1);
break;
case 40:
if (tagName === "textarea" && !shown)
return;
d3_event.preventDefault();
if (tagName === "input" && !shown) {
show();
}
nav(1);
break;
}
}
function keyup(d3_event) {
switch (d3_event.keyCode) {
case 27:
cancel();
break;
case 13:
accept(d3_event);
break;
}
}
function change() {
fetchComboData(value(), function() {
_selected = null;
var val = input.property("value");
if (_suggestions.length) {
if (input.property("selectionEnd") === val.length) {
_selected = tryAutocomplete();
}
if (!_selected) {
_selected = val;
}
}
if (val.length) {
var combo = container.selectAll(".combobox");
if (combo.empty()) {
show();
}
} else {
hide();
}
render();
});
}
function nav(dir) {
if (_suggestions.length) {
var index = -1;
for (var i2 = 0; i2 < _suggestions.length; i2++) {
if (_selected && _suggestions[i2].value === _selected) {
index = i2;
break;
}
}
index = Math.max(Math.min(index + dir, _suggestions.length - 1), 0);
_selected = _suggestions[index].value;
input.property("value", _selected);
}
render();
ensureVisible();
}
function ensureVisible() {
var combo = container.selectAll(".combobox");
if (combo.empty())
return;
var containerRect = container.node().getBoundingClientRect();
var comboRect = combo.node().getBoundingClientRect();
if (comboRect.bottom > containerRect.bottom) {
var node = attachTo ? attachTo.node() : input.node();
node.scrollIntoView({ behavior: "instant", block: "center" });
render();
}
var selected = combo.selectAll(".combobox-option.selected").node();
if (selected) {
selected.scrollIntoView({ behavior: "smooth", block: "nearest" });
}
}
function value() {
var value2 = input.property("value");
var start2 = input.property("selectionStart");
var end = input.property("selectionEnd");
if (start2 && end) {
value2 = value2.substring(0, start2);
}
return value2;
}
function fetchComboData(v, cb) {
_cancelFetch = false;
_fetcher.call(input, v, function(results) {
if (_cancelFetch)
return;
_suggestions = results;
results.forEach(function(d) {
_fetched[d.value] = d;
});
if (cb) {
cb();
}
});
}
function tryAutocomplete() {
if (!_canAutocomplete)
return;
var val = _caseSensitive ? value() : value().toLowerCase();
if (!val)
return;
if (!isNaN(parseFloat(val)) && isFinite(val))
return;
var bestIndex = -1;
for (var i2 = 0; i2 < _suggestions.length; i2++) {
var suggestion = _suggestions[i2].value;
var compare = _caseSensitive ? suggestion : suggestion.toLowerCase();
if (compare === val) {
bestIndex = i2;
break;
} else if (bestIndex === -1 && compare.indexOf(val) === 0) {
bestIndex = i2;
}
}
if (bestIndex !== -1) {
var bestVal = _suggestions[bestIndex].value;
input.property("value", bestVal);
input.node().setSelectionRange(val.length, bestVal.length);
return bestVal;
}
}
function render() {
if (_suggestions.length < _minItems || document.activeElement !== input.node()) {
hide();
return;
}
var shown = !container.selectAll(".combobox").empty();
if (!shown)
return;
var combo = container.selectAll(".combobox");
var options2 = combo.selectAll(".combobox-option").data(_suggestions, function(d) {
return d.value;
});
options2.exit().remove();
options2.enter().append("a").attr("class", function(d) {
return "combobox-option " + (d.klass || "");
}).attr("title", function(d) {
return d.title;
}).html(function(d) {
return d.display || d.value;
}).on("mouseenter", _mouseEnterHandler).on("mouseleave", _mouseLeaveHandler).merge(options2).classed("selected", function(d) {
return d.value === _selected;
}).on("click.combo-option", accept).order();
var node = attachTo ? attachTo.node() : input.node();
var containerRect = container.node().getBoundingClientRect();
var rect = node.getBoundingClientRect();
combo.style("left", rect.left + 5 - containerRect.left + "px").style("width", rect.width - 10 + "px").style("top", rect.height + rect.top - containerRect.top + "px");
}
function accept(d3_event, d) {
_cancelFetch = true;
var thiz = input.node();
if (d) {
utilGetSetValue(input, d.value);
utilTriggerEvent(input, "change");
}
var val = utilGetSetValue(input);
thiz.setSelectionRange(val.length, val.length);
d = _fetched[val];
dispatch10.call("accept", thiz, d, val);
hide();
}
function cancel() {
_cancelFetch = true;
var thiz = input.node();
var val = utilGetSetValue(input);
var start2 = input.property("selectionStart");
var end = input.property("selectionEnd");
val = val.slice(0, start2) + val.slice(end);
utilGetSetValue(input, val);
thiz.setSelectionRange(val.length, val.length);
dispatch10.call("cancel", thiz);
hide();
}
};
combobox.canAutocomplete = function(val) {
if (!arguments.length)
return _canAutocomplete;
_canAutocomplete = val;
return combobox;
};
combobox.caseSensitive = function(val) {
if (!arguments.length)
return _caseSensitive;
_caseSensitive = val;
return combobox;
};
combobox.data = function(val) {
if (!arguments.length)
return _data;
_data = val;
return combobox;
};
combobox.fetcher = function(val) {
if (!arguments.length)
return _fetcher;
_fetcher = val;
return combobox;
};
combobox.minItems = function(val) {
if (!arguments.length)
return _minItems;
_minItems = val;
return combobox;
};
combobox.itemsMouseEnter = function(val) {
if (!arguments.length)
return _mouseEnterHandler;
_mouseEnterHandler = val;
return combobox;
};
combobox.itemsMouseLeave = function(val) {
if (!arguments.length)
return _mouseLeaveHandler;
_mouseLeaveHandler = val;
return combobox;
};
return utilRebind(combobox, dispatch10, "on");
}
uiCombobox.off = function(input, context) {
input.on("focus.combo-input", null).on("blur.combo-input", null).on("keydown.combo-input", null).on("keyup.combo-input", null).on("input.combo-input", null).on("mousedown.combo-input", null).on("mouseup.combo-input", null);
context.container().on("scroll.combo-scroll", null);
};
// modules/ui/disclosure.js
function uiDisclosure(context, key, expandedDefault) {
var dispatch10 = dispatch_default("toggled");
var _expanded;
var _label = utilFunctor("");
var _updatePreference = true;
var _content = function() {
};
var disclosure = function(selection2) {
if (_expanded === void 0 || _expanded === null) {
var preference = corePreferences("disclosure." + key + ".expanded");
_expanded = preference === null ? !!expandedDefault : preference === "true";
}
var hideToggle = selection2.selectAll(".hide-toggle-" + key).data([0]);
var hideToggleEnter = hideToggle.enter().append("h3").append("a").attr("role", "button").attr("href", "#").attr("class", "hide-toggle hide-toggle-" + key).call(svgIcon("", "pre-text", "hide-toggle-icon"));
hideToggleEnter.append("span").attr("class", "hide-toggle-text");
hideToggle = hideToggleEnter.merge(hideToggle);
hideToggle.on("click", toggle).attr("title", _t(`icons.${_expanded ? "collapse" : "expand"}`)).attr("aria-expanded", _expanded).classed("expanded", _expanded);
hideToggle.selectAll(".hide-toggle-text").html(_label());
hideToggle.selectAll(".hide-toggle-icon").attr("xlink:href", _expanded ? "#iD-icon-down" : _mainLocalizer.textDirection() === "rtl" ? "#iD-icon-backward" : "#iD-icon-forward");
var wrap2 = selection2.selectAll(".disclosure-wrap").data([0]);
wrap2 = wrap2.enter().append("div").attr("class", "disclosure-wrap disclosure-wrap-" + key).merge(wrap2).classed("hide", !_expanded);
if (_expanded) {
wrap2.call(_content);
}
function toggle(d3_event) {
d3_event.preventDefault();
_expanded = !_expanded;
if (_updatePreference) {
corePreferences("disclosure." + key + ".expanded", _expanded);
}
hideToggle.classed("expanded", _expanded).attr("aria-expanded", _expanded).attr("title", _t(`icons.${_expanded ? "collapse" : "expand"}`));
hideToggle.selectAll(".hide-toggle-icon").attr("xlink:href", _expanded ? "#iD-icon-down" : _mainLocalizer.textDirection() === "rtl" ? "#iD-icon-backward" : "#iD-icon-forward");
wrap2.call(uiToggle(_expanded));
if (_expanded) {
wrap2.call(_content);
}
dispatch10.call("toggled", this, _expanded);
}
};
disclosure.label = function(val) {
if (!arguments.length)
return _label;
_label = utilFunctor(val);
return disclosure;
};
disclosure.expanded = function(val) {
if (!arguments.length)
return _expanded;
_expanded = val;
return disclosure;
};
disclosure.updatePreference = function(val) {
if (!arguments.length)
return _updatePreference;
_updatePreference = val;
return disclosure;
};
disclosure.content = function(val) {
if (!arguments.length)
return _content;
_content = val;
return disclosure;
};
return utilRebind(disclosure, dispatch10, "on");
}
// modules/ui/section.js
function uiSection(id2, context) {
var _classes = utilFunctor("");
var _shouldDisplay;
var _content;
var _disclosure;
var _label;
var _expandedByDefault = utilFunctor(true);
var _disclosureContent;
var _disclosureExpanded;
var _containerSelection = select_default2(null);
var section = {
id: id2
};
section.classes = function(val) {
if (!arguments.length)
return _classes;
_classes = utilFunctor(val);
return section;
};
section.label = function(val) {
if (!arguments.length)
return _label;
_label = utilFunctor(val);
return section;
};
section.expandedByDefault = function(val) {
if (!arguments.length)
return _expandedByDefault;
_expandedByDefault = utilFunctor(val);
return section;
};
section.shouldDisplay = function(val) {
if (!arguments.length)
return _shouldDisplay;
_shouldDisplay = utilFunctor(val);
return section;
};
section.content = function(val) {
if (!arguments.length)
return _content;
_content = val;
return section;
};
section.disclosureContent = function(val) {
if (!arguments.length)
return _disclosureContent;
_disclosureContent = val;
return section;
};
section.disclosureExpanded = function(val) {
if (!arguments.length)
return _disclosureExpanded;
_disclosureExpanded = val;
return section;
};
section.render = function(selection2) {
_containerSelection = selection2.selectAll(".section-" + id2).data([0]);
var sectionEnter = _containerSelection.enter().append("div").attr("class", "section section-" + id2 + " " + (_classes && _classes() || ""));
_containerSelection = sectionEnter.merge(_containerSelection);
_containerSelection.call(renderContent);
};
section.reRender = function() {
_containerSelection.call(renderContent);
};
section.selection = function() {
return _containerSelection;
};
section.disclosure = function() {
return _disclosure;
};
function renderContent(selection2) {
if (_shouldDisplay) {
var shouldDisplay = _shouldDisplay();
selection2.classed("hide", !shouldDisplay);
if (!shouldDisplay) {
selection2.html("");
return;
}
}
if (_disclosureContent) {
if (!_disclosure) {
_disclosure = uiDisclosure(context, id2.replace(/-/g, "_"), _expandedByDefault()).label(_label || "").content(_disclosureContent);
}
if (_disclosureExpanded !== void 0) {
_disclosure.expanded(_disclosureExpanded);
_disclosureExpanded = void 0;
}
selection2.call(_disclosure);
return;
}
if (_content) {
selection2.call(_content);
}
}
return section;
}
// modules/ui/tag_reference.js
function uiTagReference(what) {
var wikibase = what.qid ? services.wikidata : services.osmWikibase;
var tagReference = {};
var _button = select_default2(null);
var _body = select_default2(null);
var _loaded;
var _showing;
function load() {
if (!wikibase)
return;
_button.classed("tag-reference-loading", true);
wikibase.getDocs(what, gotDocs);
}
function gotDocs(err, docs) {
_body.html("");
if (!docs || !docs.title) {
_body.append("p").attr("class", "tag-reference-description").call(_t.append("inspector.no_documentation_key"));
done();
return;
}
if (docs.imageURL) {
_body.append("img").attr("class", "tag-reference-wiki-image").attr("alt", docs.description).attr("src", docs.imageURL).on("load", function() {
done();
}).on("error", function() {
select_default2(this).remove();
done();
});
} else {
done();
}
var tagReferenceDescription = _body.append("p").attr("class", "tag-reference-description").append("span");
if (docs.description) {
tagReferenceDescription = tagReferenceDescription.attr("class", "localized-text").attr("lang", docs.descriptionLocaleCode || "und").text(docs.description);
} else {
tagReferenceDescription = tagReferenceDescription.call(_t.append("inspector.no_documentation_key"));
}
tagReferenceDescription.append("a").attr("class", "tag-reference-edit").attr("target", "_blank").attr("title", _t("inspector.edit_reference")).attr("href", docs.editURL).call(svgIcon("#iD-icon-edit", "inline"));
if (docs.wiki) {
_body.append("a").attr("class", "tag-reference-link").attr("target", "_blank").attr("href", docs.wiki.url).call(svgIcon("#iD-icon-out-link", "inline")).append("span").call(_t.append(docs.wiki.text));
}
if (what.key === "comment") {
_body.append("a").attr("class", "tag-reference-comment-link").attr("target", "_blank").call(svgIcon("#iD-icon-out-link", "inline")).attr("href", _t("commit.about_changeset_comments_link")).append("span").call(_t.append("commit.about_changeset_comments"));
}
}
function done() {
_loaded = true;
_button.classed("tag-reference-loading", false);
_body.classed("expanded", true).transition().duration(200).style("max-height", "200px").style("opacity", "1");
_showing = true;
_button.selectAll("svg.icon use").each(function() {
var iconUse = select_default2(this);
if (iconUse.attr("href") === "#iD-icon-info") {
iconUse.attr("href", "#iD-icon-info-filled");
}
});
}
function hide() {
_body.transition().duration(200).style("max-height", "0px").style("opacity", "0").on("end", function() {
_body.classed("expanded", false);
});
_showing = false;
_button.selectAll("svg.icon use").each(function() {
var iconUse = select_default2(this);
if (iconUse.attr("href") === "#iD-icon-info-filled") {
iconUse.attr("href", "#iD-icon-info");
}
});
}
tagReference.button = function(selection2, klass, iconName) {
_button = selection2.selectAll(".tag-reference-button").data([0]);
_button = _button.enter().append("button").attr("class", "tag-reference-button " + (klass || "")).attr("title", _t("icons.information")).call(svgIcon("#iD-icon-" + (iconName || "inspect"))).merge(_button);
_button.on("click", function(d3_event) {
d3_event.stopPropagation();
d3_event.preventDefault();
this.blur();
if (_showing) {
hide();
} else if (_loaded) {
done();
} else {
load();
}
});
};
tagReference.body = function(selection2) {
var itemID = what.qid || what.key + "-" + (what.value || "");
_body = selection2.selectAll(".tag-reference-body").data([itemID], function(d) {
return d;
});
_body.exit().remove();
_body = _body.enter().append("div").attr("class", "tag-reference-body").style("max-height", "0").style("opacity", "0").merge(_body);
if (_showing === false) {
hide();
}
};
tagReference.showing = function(val) {
if (!arguments.length)
return _showing;
_showing = val;
return tagReference;
};
return tagReference;
}
// modules/ui/field_help.js
function uiFieldHelp(context, fieldName) {
var fieldHelp = {};
var _inspector = select_default2(null);
var _wrap = select_default2(null);
var _body = select_default2(null);
var fieldHelpKeys = {
restrictions: [
["about", [
"about",
"from_via_to",
"maxdist",
"maxvia"
]],
["inspecting", [
"about",
"from_shadow",
"allow_shadow",
"restrict_shadow",
"only_shadow",
"restricted",
"only"
]],
["modifying", [
"about",
"indicators",
"allow_turn",
"restrict_turn",
"only_turn"
]],
["tips", [
"simple",
"simple_example",
"indirect",
"indirect_example",
"indirect_noedit"
]]
]
};
var fieldHelpHeadings = {};
var replacements = {
distField: { html: _t.html("restriction.controls.distance") },
viaField: { html: _t.html("restriction.controls.via") },
fromShadow: { html: icon("#iD-turn-shadow", "inline shadow from") },
allowShadow: { html: icon("#iD-turn-shadow", "inline shadow allow") },
restrictShadow: { html: icon("#iD-turn-shadow", "inline shadow restrict") },
onlyShadow: { html: icon("#iD-turn-shadow", "inline shadow only") },
allowTurn: { html: icon("#iD-turn-yes", "inline turn") },
restrictTurn: { html: icon("#iD-turn-no", "inline turn") },
onlyTurn: { html: icon("#iD-turn-only", "inline turn") }
};
var docs = fieldHelpKeys[fieldName].map(function(key) {
var helpkey = "help.field." + fieldName + "." + key[0];
var text2 = key[1].reduce(function(all, part) {
var subkey = helpkey + "." + part;
var depth = fieldHelpHeadings[subkey];
var hhh = depth ? Array(depth + 1).join("#") + " " : "";
return all + hhh + _t.html(subkey, replacements) + "\n\n";
}, "");
return {
key: helpkey,
title: _t.html(helpkey + ".title"),
html: marked(text2.trim())
};
});
function show() {
updatePosition();
_body.classed("hide", false).style("opacity", "0").transition().duration(200).style("opacity", "1");
}
function hide() {
_body.classed("hide", true).transition().duration(200).style("opacity", "0").on("end", function() {
_body.classed("hide", true);
});
}
function clickHelp(index) {
var d = docs[index];
var tkeys = fieldHelpKeys[fieldName][index][1];
_body.selectAll(".field-help-nav-item").classed("active", function(d2, i2) {
return i2 === index;
});
var content = _body.selectAll(".field-help-content").html(d.html);
content.selectAll("p").attr("class", function(d2, i2) {
return tkeys[i2];
});
if (d.key === "help.field.restrictions.inspecting") {
content.insert("img", "p.from_shadow").attr("class", "field-help-image cf").attr("src", context.imagePath("tr_inspect.gif"));
} else if (d.key === "help.field.restrictions.modifying") {
content.insert("img", "p.allow_turn").attr("class", "field-help-image cf").attr("src", context.imagePath("tr_modify.gif"));
}
}
fieldHelp.button = function(selection2) {
if (_body.empty())
return;
var button = selection2.selectAll(".field-help-button").data([0]);
button.enter().append("button").attr("class", "field-help-button").call(svgIcon("#iD-icon-help")).merge(button).on("click", function(d3_event) {
d3_event.stopPropagation();
d3_event.preventDefault();
if (_body.classed("hide")) {
show();
} else {
hide();
}
});
};
function updatePosition() {
var wrap2 = _wrap.node();
var inspector = _inspector.node();
var wRect = wrap2.getBoundingClientRect();
var iRect = inspector.getBoundingClientRect();
_body.style("top", wRect.top + inspector.scrollTop - iRect.top + "px");
}
fieldHelp.body = function(selection2) {
_wrap = selection2.selectAll(".form-field-input-wrap");
if (_wrap.empty())
return;
_inspector = context.container().select(".sidebar .entity-editor-pane .inspector-body");
if (_inspector.empty())
return;
_body = _inspector.selectAll(".field-help-body").data([0]);
var enter = _body.enter().append("div").attr("class", "field-help-body hide");
var titleEnter = enter.append("div").attr("class", "field-help-title cf");
titleEnter.append("h2").attr("class", _mainLocalizer.textDirection() === "rtl" ? "fr" : "fl").call(_t.append("help.field." + fieldName + ".title"));
titleEnter.append("button").attr("class", "fr close").attr("title", _t("icons.close")).on("click", function(d3_event) {
d3_event.stopPropagation();
d3_event.preventDefault();
hide();
}).call(svgIcon("#iD-icon-close"));
var navEnter = enter.append("div").attr("class", "field-help-nav cf");
var titles = docs.map(function(d) {
return d.title;
});
navEnter.selectAll(".field-help-nav-item").data(titles).enter().append("div").attr("class", "field-help-nav-item").html(function(d) {
return d;
}).on("click", function(d3_event, d) {
d3_event.stopPropagation();
d3_event.preventDefault();
clickHelp(titles.indexOf(d));
});
enter.append("div").attr("class", "field-help-content");
_body = _body.merge(enter);
clickHelp(0);
};
return fieldHelp;
}
// modules/ui/fields/check.js
function uiFieldCheck(field, context) {
var dispatch10 = dispatch_default("change");
var options2 = field.options;
var values = [];
var texts = [];
var _tags;
var input = select_default2(null);
var text2 = select_default2(null);
var label = select_default2(null);
var reverser = select_default2(null);
var _impliedYes;
var _entityIDs = [];
var _value;
if (options2) {
for (var i2 in options2) {
var v = options2[i2];
values.push(v === "undefined" ? void 0 : v);
texts.push(field.t.html("options." + v, { "default": v }));
}
} else {
values = [void 0, "yes"];
texts = [_t.html("inspector.unknown"), _t.html("inspector.check.yes")];
if (field.type !== "defaultCheck") {
values.push("no");
texts.push(_t.html("inspector.check.no"));
}
}
function checkImpliedYes() {
_impliedYes = field.id === "oneway_yes";
if (field.id === "oneway") {
var entity = context.entity(_entityIDs[0]);
for (var key in entity.tags) {
if (key in osmOneWayTags && entity.tags[key] in osmOneWayTags[key]) {
_impliedYes = true;
texts[0] = _t.html("_tagging.presets.fields.oneway_yes.options.undefined");
break;
}
}
}
}
function reverserHidden() {
if (!context.container().select("div.inspector-hover").empty())
return true;
return !(_value === "yes" || _impliedYes && !_value);
}
function reverserSetText(selection2) {
var entity = _entityIDs.length && context.hasEntity(_entityIDs[0]);
if (reverserHidden() || !entity)
return selection2;
var first = entity.first();
var last = entity.isClosed() ? entity.nodes[entity.nodes.length - 2] : entity.last();
var pseudoDirection = first < last;
var icon2 = pseudoDirection ? "#iD-icon-forward" : "#iD-icon-backward";
selection2.selectAll(".reverser-span").html("").call(_t.append("inspector.check.reverser")).call(svgIcon(icon2, "inline"));
return selection2;
}
var check = function(selection2) {
checkImpliedYes();
label = selection2.selectAll(".form-field-input-wrap").data([0]);
var enter = label.enter().append("label").attr("class", "form-field-input-wrap form-field-input-check");
enter.append("input").property("indeterminate", field.type !== "defaultCheck").attr("type", "checkbox").attr("id", field.domId);
enter.append("span").html(texts[0]).attr("class", "value");
if (field.type === "onewayCheck") {
enter.append("button").attr("class", "reverser" + (reverserHidden() ? " hide" : "")).append("span").attr("class", "reverser-span");
}
label = label.merge(enter);
input = label.selectAll("input");
text2 = label.selectAll("span.value");
input.on("click", function(d3_event) {
d3_event.stopPropagation();
var t = {};
if (Array.isArray(_tags[field.key])) {
if (values.indexOf("yes") !== -1) {
t[field.key] = "yes";
} else {
t[field.key] = values[0];
}
} else {
t[field.key] = values[(values.indexOf(_value) + 1) % values.length];
}
if (t[field.key] === "reversible" || t[field.key] === "alternating") {
t[field.key] = values[0];
}
dispatch10.call("change", this, t);
});
if (field.type === "onewayCheck") {
reverser = label.selectAll(".reverser");
reverser.call(reverserSetText).on("click", function(d3_event) {
d3_event.preventDefault();
d3_event.stopPropagation();
context.perform(function(graph) {
for (var i3 in _entityIDs) {
graph = actionReverse(_entityIDs[i3])(graph);
}
return graph;
}, _t("operations.reverse.annotation.line", { n: 1 }));
context.validator().validate();
select_default2(this).call(reverserSetText);
});
}
};
check.entityIDs = function(val) {
if (!arguments.length)
return _entityIDs;
_entityIDs = val;
return check;
};
check.tags = function(tags) {
_tags = tags;
function isChecked(val) {
return val !== "no" && val !== "" && val !== void 0 && val !== null;
}
function textFor(val) {
if (val === "")
val = void 0;
var index = values.indexOf(val);
return index !== -1 ? texts[index] : '"' + val + '"';
}
checkImpliedYes();
var isMixed = Array.isArray(tags[field.key]);
_value = !isMixed && tags[field.key] && tags[field.key].toLowerCase();
if (field.type === "onewayCheck" && (_value === "1" || _value === "-1")) {
_value = "yes";
}
input.property("indeterminate", isMixed || field.type !== "defaultCheck" && !_value).property("checked", isChecked(_value));
text2.html(isMixed ? _t.html("inspector.multiple_values") : textFor(_value)).classed("mixed", isMixed);
label.classed("set", !!_value);
if (field.type === "onewayCheck") {
reverser.classed("hide", reverserHidden()).call(reverserSetText);
}
};
check.focus = function() {
input.node().focus();
};
return utilRebind(check, dispatch10, "on");
}
// modules/ui/fields/combo.js
function uiFieldCombo(field, context) {
var dispatch10 = dispatch_default("change");
var _isMulti = field.type === "multiCombo" || field.type === "manyCombo";
var _isNetwork = field.type === "networkCombo";
var _isSemi = field.type === "semiCombo";
var _optarray = field.options;
var _showTagInfoSuggestions = field.type !== "manyCombo" && field.autoSuggestions !== false;
var _allowCustomValues = field.type !== "manyCombo" && field.customValues !== false;
var _snake_case = field.snake_case || field.snake_case === void 0;
var _combobox = uiCombobox(context, "combo-" + field.safeid).caseSensitive(field.caseSensitive).minItems(_isMulti || _isSemi ? 1 : 2);
var _container = select_default2(null);
var _inputWrap = select_default2(null);
var _input = select_default2(null);
var _comboData = [];
var _multiData = [];
var _entityIDs = [];
var _tags;
var _countryCode;
var _staticPlaceholder;
var _dataDeprecated = [];
_mainFileFetcher.get("deprecated").then(function(d) {
_dataDeprecated = d;
}).catch(function() {
});
if (_isMulti && field.key && /[^:]$/.test(field.key)) {
field.key += ":";
}
function snake(s) {
return s.replace(/\s+/g, "_").toLowerCase();
}
function clean2(s) {
return s.split(";").map(function(s2) {
return s2.trim();
}).join(";");
}
function tagValue(dval) {
dval = clean2(dval || "");
var found = _comboData.find(function(o) {
return o.key && clean2(o.value) === dval;
});
if (found)
return found.key;
if (field.type === "typeCombo" && !dval) {
return "yes";
}
return (_snake_case ? snake(dval) : dval) || void 0;
}
function displayValue(tval) {
tval = tval || "";
if (field.hasTextForStringId("options." + tval)) {
return field.t("options." + tval, { default: tval });
}
if (field.type === "typeCombo" && tval.toLowerCase() === "yes") {
return "";
}
return tval;
}
function objectDifference(a, b) {
return a.filter(function(d1) {
return !b.some(function(d2) {
return !d2.isMixed && d1.value === d2.value;
});
});
}
function initCombo(selection2, attachTo) {
if (!_allowCustomValues) {
selection2.attr("readonly", "readonly");
}
if (_showTagInfoSuggestions && services.taginfo) {
selection2.call(_combobox.fetcher(setTaginfoValues), attachTo);
setTaginfoValues("", setPlaceholder);
} else {
selection2.call(_combobox, attachTo);
setStaticValues(setPlaceholder);
}
}
function setStaticValues(callback) {
if (!_optarray)
return;
_comboData = _optarray.map(function(v) {
return {
key: v,
value: field.t("options." + v, { default: v }),
title: v,
display: field.t.html("options." + v, { default: v }),
klass: field.hasTextForStringId("options." + v) ? "" : "raw-option"
};
});
_combobox.data(objectDifference(_comboData, _multiData));
if (callback)
callback(_comboData);
}
function setTaginfoValues(q, callback) {
var fn = _isMulti ? "multikeys" : "values";
var query = (_isMulti ? field.key : "") + q;
var hasCountryPrefix = _isNetwork && _countryCode && _countryCode.indexOf(q.toLowerCase()) === 0;
if (hasCountryPrefix) {
query = _countryCode + ":";
}
var params = {
debounce: q !== "",
key: field.key,
query
};
if (_entityIDs.length) {
params.geometry = context.graph().geometry(_entityIDs[0]);
}
services.taginfo[fn](params, function(err, data) {
if (err)
return;
data = data.filter(function(d) {
if (field.type === "typeCombo" && d.value === "yes") {
return false;
}
return !d.count || d.count > 10;
});
var deprecatedValues = osmEntity.deprecatedTagValuesByKey(_dataDeprecated)[field.key];
if (deprecatedValues) {
data = data.filter(function(d) {
return deprecatedValues.indexOf(d.value) === -1;
});
}
if (hasCountryPrefix) {
data = data.filter(function(d) {
return d.value.toLowerCase().indexOf(_countryCode + ":") === 0;
});
}
_container.classed("empty-combobox", data.length === 0);
_comboData = data.map(function(d) {
var k = d.value;
if (_isMulti)
k = k.replace(field.key, "");
var label = field.t("options." + k, { default: k });
return {
key: k,
value: label,
display: field.t.html("options." + k, { default: k }),
title: d.title || label,
klass: field.hasTextForStringId("options." + k) ? "" : "raw-option"
};
});
_comboData = objectDifference(_comboData, _multiData);
if (callback)
callback(_comboData);
});
}
function setPlaceholder(values) {
if (_isMulti || _isSemi) {
_staticPlaceholder = field.placeholder() || _t("inspector.add");
} else {
var vals = values.map(function(d) {
return d.value;
}).filter(function(s) {
return s.length < 20;
});
var placeholders = vals.length > 1 ? vals : values.map(function(d) {
return d.key;
});
_staticPlaceholder = field.placeholder() || placeholders.slice(0, 3).join(", ");
}
if (!/(…|\.\.\.)$/.test(_staticPlaceholder)) {
_staticPlaceholder += "\u2026";
}
var ph;
if (!_isMulti && !_isSemi && _tags && Array.isArray(_tags[field.key])) {
ph = _t("inspector.multiple_values");
} else {
ph = _staticPlaceholder;
}
_container.selectAll("input").attr("placeholder", ph);
}
function change() {
var t = {};
var val;
if (_isMulti || _isSemi) {
val = tagValue(utilGetSetValue(_input).replace(/,/g, ";")) || "";
_container.classed("active", false);
utilGetSetValue(_input, "");
var vals = val.split(";").filter(Boolean);
if (!vals.length)
return;
if (_isMulti) {
utilArrayUniq(vals).forEach(function(v) {
var key = (field.key || "") + v;
if (_tags) {
var old = _tags[key];
if (typeof old === "string" && old.toLowerCase() !== "no")
return;
}
key = context.cleanTagKey(key);
field.keys.push(key);
t[key] = "yes";
});
} else if (_isSemi) {
var arr = _multiData.map(function(d) {
return d.key;
});
arr = arr.concat(vals);
t[field.key] = context.cleanTagValue(utilArrayUniq(arr).filter(Boolean).join(";"));
}
window.setTimeout(function() {
_input.node().focus();
}, 10);
} else {
var rawValue = utilGetSetValue(_input);
if (!rawValue && Array.isArray(_tags[field.key]))
return;
val = context.cleanTagValue(tagValue(rawValue));
t[field.key] = val || void 0;
}
dispatch10.call("change", this, t);
}
function removeMultikey(d3_event, d) {
d3_event.preventDefault();
d3_event.stopPropagation();
var t = {};
if (_isMulti) {
t[d.key] = void 0;
} else if (_isSemi) {
var arr = _multiData.map(function(md) {
return md.key === d.key ? null : md.key;
}).filter(Boolean);
arr = utilArrayUniq(arr);
t[field.key] = arr.length ? arr.join(";") : void 0;
}
dispatch10.call("change", this, t);
}
function combo(selection2) {
_container = selection2.selectAll(".form-field-input-wrap").data([0]);
var type3 = _isMulti || _isSemi ? "multicombo" : "combo";
_container = _container.enter().append("div").attr("class", "form-field-input-wrap form-field-input-" + type3).merge(_container);
if (_isMulti || _isSemi) {
_container = _container.selectAll(".chiplist").data([0]);
var listClass = "chiplist";
if (field.key === "destination" || field.key === "via") {
listClass += " full-line-chips";
}
_container = _container.enter().append("ul").attr("class", listClass).on("click", function() {
window.setTimeout(function() {
_input.node().focus();
}, 10);
}).merge(_container);
_inputWrap = _container.selectAll(".input-wrap").data([0]);
_inputWrap = _inputWrap.enter().append("li").attr("class", "input-wrap").merge(_inputWrap);
_input = _inputWrap.selectAll("input").data([0]);
} else {
_input = _container.selectAll("input").data([0]);
}
_input = _input.enter().append("input").attr("type", "text").attr("id", field.domId).call(utilNoAuto).call(initCombo, selection2).merge(_input);
if (_isNetwork) {
var extent = combinedEntityExtent();
var countryCode = extent && iso1A2Code(extent.center());
_countryCode = countryCode && countryCode.toLowerCase();
}
_input.on("change", change).on("blur", change);
_input.on("keydown.field", function(d3_event) {
switch (d3_event.keyCode) {
case 13:
_input.node().blur();
d3_event.stopPropagation();
break;
}
});
if (_isMulti || _isSemi) {
_combobox.on("accept", function() {
_input.node().blur();
_input.node().focus();
});
_input.on("focus", function() {
_container.classed("active", true);
});
}
}
combo.tags = function(tags) {
_tags = tags;
if (_isMulti || _isSemi) {
_multiData = [];
var maxLength;
if (_isMulti) {
for (var k in tags) {
if (field.key && k.indexOf(field.key) !== 0)
continue;
if (!field.key && field.keys.indexOf(k) === -1)
continue;
var v = tags[k];
if (!v || typeof v === "string" && v.toLowerCase() === "no")
continue;
var suffix = field.key ? k.substr(field.key.length) : k;
_multiData.push({
key: k,
value: displayValue(suffix),
isMixed: Array.isArray(v)
});
}
if (field.key) {
field.keys = _multiData.map(function(d) {
return d.key;
});
maxLength = context.maxCharsForTagKey() - utilUnicodeCharsCount(field.key);
} else {
maxLength = context.maxCharsForTagKey();
}
} else if (_isSemi) {
var allValues = [];
var commonValues;
if (Array.isArray(tags[field.key])) {
tags[field.key].forEach(function(tagVal) {
var thisVals = utilArrayUniq((tagVal || "").split(";")).filter(Boolean);
allValues = allValues.concat(thisVals);
if (!commonValues) {
commonValues = thisVals;
} else {
commonValues = commonValues.filter((value) => thisVals.includes(value));
}
});
allValues = utilArrayUniq(allValues).filter(Boolean);
} else {
allValues = utilArrayUniq((tags[field.key] || "").split(";")).filter(Boolean);
commonValues = allValues;
}
_multiData = allValues.map(function(v2) {
return {
key: v2,
value: displayValue(v2),
isMixed: !commonValues.includes(v2)
};
});
var currLength = utilUnicodeCharsCount(commonValues.join(";"));
maxLength = context.maxCharsForTagValue() - currLength;
if (currLength > 0) {
maxLength -= 1;
}
}
maxLength = Math.max(0, maxLength);
var allowDragAndDrop = _isSemi && !Array.isArray(tags[field.key]);
var available = objectDifference(_comboData, _multiData);
_combobox.data(available);
var hideAdd = !_allowCustomValues && !available.length || maxLength <= 0;
_container.selectAll(".chiplist .input-wrap").style("display", hideAdd ? "none" : null);
var chips = _container.selectAll(".chip").data(_multiData);
chips.exit().remove();
var enter = chips.enter().insert("li", ".input-wrap").attr("class", "chip");
enter.append("span");
enter.append("a");
chips = chips.merge(enter).order().classed("raw-value", function(d) {
var k2 = d.key;
if (_isMulti)
k2 = k2.replace(field.key, "");
return !field.hasTextForStringId("options." + k2);
}).classed("draggable", allowDragAndDrop).classed("mixed", function(d) {
return d.isMixed;
}).attr("title", function(d) {
return d.isMixed ? _t("inspector.unshared_value_tooltip") : null;
});
if (allowDragAndDrop) {
registerDragAndDrop(chips);
}
chips.select("span").text(function(d) {
return d.value;
});
chips.select("a").attr("href", "#").on("click", removeMultikey).attr("class", "remove").text("\xD7");
} else {
var isMixed = Array.isArray(tags[field.key]);
var mixedValues = isMixed && tags[field.key].map(function(val) {
return displayValue(val);
}).filter(Boolean);
var showsValue = !isMixed && tags[field.key] && !(field.type === "typeCombo" && tags[field.key] === "yes");
var isRawValue = showsValue && !field.hasTextForStringId("options." + tags[field.key]);
var isKnownValue = showsValue && !isRawValue;
var isReadOnly = !_allowCustomValues || isKnownValue;
utilGetSetValue(_input, !isMixed ? displayValue(tags[field.key]) : "").classed("raw-value", isRawValue).classed("known-value", isKnownValue).attr("readonly", isReadOnly ? "readonly" : void 0).attr("title", isMixed ? mixedValues.join("\n") : void 0).attr("placeholder", isMixed ? _t("inspector.multiple_values") : _staticPlaceholder || "").classed("mixed", isMixed).on("keydown.deleteCapture", function(d3_event) {
if (isReadOnly && isKnownValue && (d3_event.keyCode === utilKeybinding.keyCodes["\u232B"] || d3_event.keyCode === utilKeybinding.keyCodes["\u2326"])) {
d3_event.preventDefault();
d3_event.stopPropagation();
var t = {};
t[field.key] = void 0;
dispatch10.call("change", this, t);
}
});
}
};
function registerDragAndDrop(selection2) {
var dragOrigin, targetIndex;
selection2.call(drag_default().on("start", function(d3_event) {
dragOrigin = {
x: d3_event.x,
y: d3_event.y
};
targetIndex = null;
}).on("drag", function(d3_event) {
var x = d3_event.x - dragOrigin.x, y = d3_event.y - dragOrigin.y;
if (!select_default2(this).classed("dragging") && Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)) <= 5)
return;
var index = selection2.nodes().indexOf(this);
select_default2(this).classed("dragging", true);
targetIndex = null;
var targetIndexOffsetTop = null;
var draggedTagWidth = select_default2(this).node().offsetWidth;
if (field.key === "destination" || field.key === "via") {
_container.selectAll(".chip").style("transform", function(d2, index2) {
var node = select_default2(this).node();
if (index === index2) {
return "translate(" + x + "px, " + y + "px)";
} else if (index2 > index && d3_event.y > node.offsetTop) {
if (targetIndex === null || index2 > targetIndex) {
targetIndex = index2;
}
return "translateY(-100%)";
} else if (index2 < index && d3_event.y < node.offsetTop + node.offsetHeight) {
if (targetIndex === null || index2 < targetIndex) {
targetIndex = index2;
}
return "translateY(100%)";
}
return null;
});
} else {
_container.selectAll(".chip").each(function(d2, index2) {
var node = select_default2(this).node();
if (index !== index2 && d3_event.x < node.offsetLeft + node.offsetWidth + 5 && d3_event.x > node.offsetLeft && d3_event.y < node.offsetTop + node.offsetHeight && d3_event.y > node.offsetTop) {
targetIndex = index2;
targetIndexOffsetTop = node.offsetTop;
}
}).style("transform", function(d2, index2) {
var node = select_default2(this).node();
if (index === index2) {
return "translate(" + x + "px, " + y + "px)";
}
if (node.offsetTop === targetIndexOffsetTop) {
if (index2 < index && index2 >= targetIndex) {
return "translateX(" + draggedTagWidth + "px)";
} else if (index2 > index && index2 <= targetIndex) {
return "translateX(-" + draggedTagWidth + "px)";
}
}
return null;
});
}
}).on("end", function() {
if (!select_default2(this).classed("dragging")) {
return;
}
var index = selection2.nodes().indexOf(this);
select_default2(this).classed("dragging", false);
_container.selectAll(".chip").style("transform", null);
if (typeof targetIndex === "number") {
var element = _multiData[index];
_multiData.splice(index, 1);
_multiData.splice(targetIndex, 0, element);
var t = {};
if (_multiData.length) {
t[field.key] = _multiData.map(function(element2) {
return element2.key;
}).join(";");
} else {
t[field.key] = void 0;
}
dispatch10.call("change", this, t);
}
dragOrigin = void 0;
targetIndex = void 0;
}));
}
combo.focus = function() {
_input.node().focus();
};
combo.entityIDs = function(val) {
if (!arguments.length)
return _entityIDs;
_entityIDs = val;
return combo;
};
function combinedEntityExtent() {
return _entityIDs && _entityIDs.length && utilTotalExtent(_entityIDs, context.graph());
}
return utilRebind(combo, dispatch10, "on");
}
// modules/ui/fields/input.js
function uiFieldText(field, context) {
var dispatch10 = dispatch_default("change");
var input = select_default2(null);
var outlinkButton = select_default2(null);
var wrap2 = select_default2(null);
var _entityIDs = [];
var _tags;
var _phoneFormats = {};
if (field.type === "tel") {
_mainFileFetcher.get("phone_formats").then(function(d) {
_phoneFormats = d;
updatePhonePlaceholder();
}).catch(function() {
});
}
function calcLocked() {
var isLocked = (field.id === "brand" || field.id === "network" || field.id === "operator" || field.id === "flag") && _entityIDs.length && _entityIDs.some(function(entityID) {
var entity = context.graph().hasEntity(entityID);
if (!entity)
return false;
if (entity.tags.wikidata)
return true;
var preset = _mainPresetIndex.match(entity, context.graph());
var isSuggestion = preset && preset.suggestion;
var which = field.id;
return isSuggestion && !!entity.tags[which] && !!entity.tags[which + ":wikidata"];
});
field.locked(isLocked);
}
function i2(selection2) {
calcLocked();
var isLocked = field.locked();
wrap2 = selection2.selectAll(".form-field-input-wrap").data([0]);
wrap2 = wrap2.enter().append("div").attr("class", "form-field-input-wrap form-field-input-" + field.type).merge(wrap2);
input = wrap2.selectAll("input").data([0]);
input = input.enter().append("input").attr("type", field.type === "identifier" ? "text" : field.type).attr("id", field.domId).classed(field.type, true).call(utilNoAuto).merge(input);
input.classed("disabled", !!isLocked).attr("readonly", isLocked || null).on("input", change(true)).on("blur", change()).on("change", change());
if (field.type === "tel") {
updatePhonePlaceholder();
} else if (field.type === "number") {
var rtl = _mainLocalizer.textDirection() === "rtl";
input.attr("type", "text");
var inc = field.increment;
var buttons = wrap2.selectAll(".increment, .decrement").data(rtl ? [inc, -inc] : [-inc, inc]);
buttons.enter().append("button").attr("class", function(d) {
var which = d > 0 ? "increment" : "decrement";
return "form-field-button " + which;
}).attr("title", function(d) {
var which = d > 0 ? "increment" : "decrement";
return _t(`inspector.${which}`);
}).merge(buttons).on("click", function(d3_event, d) {
d3_event.preventDefault();
var raw_vals = input.node().value || "0";
var vals = raw_vals.split(";");
vals = vals.map(function(v) {
var num = parseFloat(v.trim(), 10);
return isFinite(num) ? clamped(num + d) : v.trim();
});
input.node().value = vals.join(";");
change()();
});
} else if (field.type === "identifier" && field.urlFormat && field.pattern) {
input.attr("type", "text");
outlinkButton = wrap2.selectAll(".foreign-id-permalink").data([0]);
outlinkButton.enter().append("button").call(svgIcon("#iD-icon-out-link")).attr("class", "form-field-button foreign-id-permalink").attr("title", function() {
var domainResults = /^https?:\/\/(.{1,}?)\//.exec(field.urlFormat);
if (domainResults.length >= 2 && domainResults[1]) {
var domain2 = domainResults[1];
return _t("icons.view_on", { domain: domain2 });
}
return "";
}).on("click", function(d3_event) {
d3_event.preventDefault();
var value = validIdentifierValueForLink();
if (value) {
var url = field.urlFormat.replace(/{value}/, encodeURIComponent(value));
window.open(url, "_blank");
}
}).merge(outlinkButton);
} else if (field.type === "url") {
input.attr("type", "text");
outlinkButton = wrap2.selectAll(".foreign-id-permalink").data([0]);
outlinkButton.enter().append("button").call(svgIcon("#iD-icon-out-link")).attr("class", "form-field-button foreign-id-permalink").attr("title", () => _t("icons.visit_website")).on("click", function(d3_event) {
d3_event.preventDefault();
const value = validIdentifierValueForLink();
if (value)
window.open(value, "_blank");
}).merge(outlinkButton);
} else if (field.key.split(":").includes("colour")) {
input.attr("type", "text");
updateColourPreview();
}
}
function isColourValid(colour) {
if (!colour.match(/^(#([0-9a-fA-F]{3}){1,2}|\w+)$/)) {
return false;
} else if (!CSS.supports("color", colour) || ["unset", "inherit", "initial", "revert"].includes(colour)) {
return false;
}
return true;
}
function updateColourPreview() {
wrap2.selectAll(".colour-preview").remove();
const colour = utilGetSetValue(input);
if (!isColourValid(colour) && colour !== "")
return;
var colourSelector = wrap2.selectAll(".colour-selector").data([0]);
outlinkButton = wrap2.selectAll(".colour-preview").data([colour]);
colourSelector.enter().append("input").attr("type", "color").attr("class", "form-field-button colour-selector").attr("value", colour).on("input", debounce_default(function(d3_event) {
d3_event.preventDefault();
var colour2 = this.value;
if (!isColourValid(colour2))
return;
utilGetSetValue(input, this.value);
change()();
updateColourPreview();
}, 100));
outlinkButton = outlinkButton.enter().append("div").attr("class", "form-field-button colour-preview").append("div").style("background-color", (d) => d).attr("class", "colour-box");
if (colour === "") {
outlinkButton = outlinkButton.call(svgIcon("#iD-icon-edit"));
}
outlinkButton.on("click", () => wrap2.select(".colour-selector").node().click()).merge(outlinkButton);
}
function updatePhonePlaceholder() {
if (input.empty() || !Object.keys(_phoneFormats).length)
return;
var extent = combinedEntityExtent();
var countryCode = extent && iso1A2Code(extent.center());
var format2 = countryCode && _phoneFormats[countryCode.toLowerCase()];
if (format2)
input.attr("placeholder", format2);
}
function validIdentifierValueForLink() {
const value = utilGetSetValue(input).trim();
if (field.type === "url" && value) {
try {
return new URL(value).href;
} catch (e) {
return null;
}
}
if (field.type === "identifier" && field.pattern) {
return value && value.match(new RegExp(field.pattern))[0];
}
return null;
}
function clamped(num) {
if (field.minValue !== void 0) {
num = Math.max(num, field.minValue);
}
if (field.maxValue !== void 0) {
num = Math.min(num, field.maxValue);
}
return num;
}
function change(onInput) {
return function() {
var t = {};
var val = utilGetSetValue(input);
if (!onInput)
val = context.cleanTagValue(val);
if (!val && Array.isArray(_tags[field.key]))
return;
if (!onInput) {
if (field.type === "number" && val) {
var vals = val.split(";");
vals = vals.map(function(v) {
var num = parseFloat(v.trim(), 10);
return isFinite(num) ? clamped(num) : v.trim();
});
val = vals.join(";");
}
utilGetSetValue(input, val);
}
t[field.key] = val || void 0;
dispatch10.call("change", this, t, onInput);
};
}
i2.entityIDs = function(val) {
if (!arguments.length)
return _entityIDs;
_entityIDs = val;
return i2;
};
i2.tags = function(tags) {
_tags = tags;
var isMixed = Array.isArray(tags[field.key]);
utilGetSetValue(input, !isMixed && tags[field.key] ? tags[field.key] : "").attr("title", isMixed ? tags[field.key].filter(Boolean).join("\n") : void 0).attr("placeholder", isMixed ? _t("inspector.multiple_values") : field.placeholder() || _t("inspector.unknown")).classed("mixed", isMixed);
if (field.key.split(":").includes("colour"))
updateColourPreview();
if (outlinkButton && !outlinkButton.empty()) {
var disabled = !validIdentifierValueForLink();
outlinkButton.classed("disabled", disabled);
}
};
i2.focus = function() {
var node = input.node();
if (node)
node.focus();
};
function combinedEntityExtent() {
return _entityIDs && _entityIDs.length && utilTotalExtent(_entityIDs, context.graph());
}
return utilRebind(i2, dispatch10, "on");
}
// modules/ui/fields/access.js
function uiFieldAccess(field, context) {
var dispatch10 = dispatch_default("change");
var items = select_default2(null);
var _tags;
function access(selection2) {
var wrap2 = selection2.selectAll(".form-field-input-wrap").data([0]);
wrap2 = wrap2.enter().append("div").attr("class", "form-field-input-wrap form-field-input-" + field.type).merge(wrap2);
var list = wrap2.selectAll("ul").data([0]);
list = list.enter().append("ul").attr("class", "rows").merge(list);
items = list.selectAll("li").data(field.keys);
var enter = items.enter().append("li").attr("class", function(d) {
return "labeled-input preset-access-" + d;
});
enter.append("span").attr("class", "label preset-label-access").attr("for", function(d) {
return "preset-input-access-" + d;
}).html(function(d) {
return field.t.html("types." + d);
});
enter.append("div").attr("class", "preset-input-access-wrap").append("input").attr("type", "text").attr("class", function(d) {
return "preset-input-access preset-input-access-" + d;
}).call(utilNoAuto).each(function(d) {
select_default2(this).call(uiCombobox(context, "access-" + d).data(access.options(d)));
});
items = items.merge(enter);
wrap2.selectAll(".preset-input-access").on("change", change).on("blur", change);
}
function change(d3_event, d) {
var tag = {};
var value = context.cleanTagValue(utilGetSetValue(select_default2(this)));
if (!value && typeof _tags[d] !== "string")
return;
tag[d] = value || void 0;
dispatch10.call("change", this, tag);
}
access.options = function(type3) {
var options2 = [
"yes",
"no",
"designated",
"permissive",
"destination",
"customers",
"private",
"permit",
"unknown"
];
if (type3 === "access") {
options2 = options2.filter((v) => v !== "yes" && v !== "designated");
}
if (type3 === "bicycle") {
options2.splice(options2.length - 4, 0, "dismount");
}
return options2.map(function(option) {
return {
title: field.t("options." + option + ".description"),
value: option
};
});
};
var placeholdersByHighway = {
footway: {
foot: "designated",
motor_vehicle: "no"
},
steps: {
foot: "yes",
motor_vehicle: "no",
bicycle: "no",
horse: "no"
},
pedestrian: {
foot: "yes",
motor_vehicle: "no"
},
cycleway: {
motor_vehicle: "no",
bicycle: "designated"
},
bridleway: {
motor_vehicle: "no",
horse: "designated"
},
path: {
foot: "yes",
motor_vehicle: "no",
bicycle: "yes",
horse: "yes"
},
motorway: {
foot: "no",
motor_vehicle: "yes",
bicycle: "no",
horse: "no"
},
trunk: {
motor_vehicle: "yes"
},
primary: {
foot: "yes",
motor_vehicle: "yes",
bicycle: "yes",
horse: "yes"
},
secondary: {
foot: "yes",
motor_vehicle: "yes",
bicycle: "yes",
horse: "yes"
},
tertiary: {
foot: "yes",
motor_vehicle: "yes",
bicycle: "yes",
horse: "yes"
},
residential: {
foot: "yes",
motor_vehicle: "yes",
bicycle: "yes",
horse: "yes"
},
unclassified: {
foot: "yes",
motor_vehicle: "yes",
bicycle: "yes",
horse: "yes"
},
service: {
foot: "yes",
motor_vehicle: "yes",
bicycle: "yes",
horse: "yes"
},
motorway_link: {
foot: "no",
motor_vehicle: "yes",
bicycle: "no",
horse: "no"
},
trunk_link: {
motor_vehicle: "yes"
},
primary_link: {
foot: "yes",
motor_vehicle: "yes",
bicycle: "yes",
horse: "yes"
},
secondary_link: {
foot: "yes",
motor_vehicle: "yes",
bicycle: "yes",
horse: "yes"
},
tertiary_link: {
foot: "yes",
motor_vehicle: "yes",
bicycle: "yes",
horse: "yes"
},
construction: {
access: "no"
}
};
access.tags = function(tags) {
_tags = tags;
utilGetSetValue(items.selectAll(".preset-input-access"), function(d) {
return typeof tags[d] === "string" ? tags[d] : "";
}).classed("mixed", function(d) {
return tags[d] && Array.isArray(tags[d]);
}).attr("title", function(d) {
return tags[d] && Array.isArray(tags[d]) && tags[d].filter(Boolean).join("\n");
}).attr("placeholder", function(d) {
if (tags[d] && Array.isArray(tags[d])) {
return _t("inspector.multiple_values");
}
if (d === "bicycle" || d === "motor_vehicle") {
if (tags.vehicle && typeof tags.vehicle === "string") {
return tags.vehicle;
}
}
if (tags.access && typeof tags.access === "string") {
return tags.access;
}
if (tags.highway) {
if (typeof tags.highway === "string") {
if (placeholdersByHighway[tags.highway] && placeholdersByHighway[tags.highway][d]) {
return placeholdersByHighway[tags.highway][d];
}
} else {
var impliedAccesses = tags.highway.filter(Boolean).map(function(highwayVal) {
return placeholdersByHighway[highwayVal] && placeholdersByHighway[highwayVal][d];
}).filter(Boolean);
if (impliedAccesses.length === tags.highway.length && new Set(impliedAccesses).size === 1) {
return impliedAccesses[0];
}
}
}
if (d === "access") {
return "yes";
}
return field.placeholder();
});
};
access.focus = function() {
items.selectAll(".preset-input-access").node().focus();
};
return utilRebind(access, dispatch10, "on");
}
// modules/ui/fields/address.js
function uiFieldAddress(field, context) {
var dispatch10 = dispatch_default("change");
var _selection = select_default2(null);
var _wrap = select_default2(null);
var addrField = _mainPresetIndex.field("address");
var _entityIDs = [];
var _tags;
var _countryCode;
var _addressFormats = [{
format: [
["housenumber", "street"],
["city", "postcode"]
]
}];
_mainFileFetcher.get("address_formats").then(function(d) {
_addressFormats = d;
if (!_selection.empty()) {
_selection.call(address);
}
}).catch(function() {
});
function getNearStreets() {
var extent = combinedEntityExtent();
var l = extent.center();
var box = geoExtent(l).padByMeters(200);
var streets = context.history().intersects(box).filter(isAddressable).map(function(d) {
var loc = context.projection([
(extent[0][0] + extent[1][0]) / 2,
(extent[0][1] + extent[1][1]) / 2
]);
var choice = geoChooseEdge(context.graph().childNodes(d), loc, context.projection);
return {
title: d.tags.name,
value: d.tags.name,
dist: choice.distance
};
}).sort(function(a, b) {
return a.dist - b.dist;
});
return utilArrayUniqBy(streets, "value");
function isAddressable(d) {
return d.tags.highway && d.tags.name && d.type === "way";
}
}
function getNearCities() {
var extent = combinedEntityExtent();
var l = extent.center();
var box = geoExtent(l).padByMeters(200);
var cities = context.history().intersects(box).filter(isAddressable).map(function(d) {
return {
title: d.tags["addr:city"] || d.tags.name,
value: d.tags["addr:city"] || d.tags.name,
dist: geoSphericalDistance(d.extent(context.graph()).center(), l)
};
}).sort(function(a, b) {
return a.dist - b.dist;
});
return utilArrayUniqBy(cities, "value");
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["addr:city"])
return true;
return false;
}
}
function getNearValues(key) {
var extent = combinedEntityExtent();
var l = extent.center();
var box = geoExtent(l).padByMeters(200);
var results = context.history().intersects(box).filter(function hasTag(d) {
return _entityIDs.indexOf(d.id) === -1 && d.tags[key];
}).map(function(d) {
return {
title: d.tags[key],
value: d.tags[key],
dist: geoSphericalDistance(d.extent(context.graph()).center(), l)
};
}).sort(function(a, b) {
return a.dist - b.dist;
});
return utilArrayUniqBy(results, "value");
}
function updateForCountryCode() {
if (!_countryCode)
return;
var addressFormat;
for (var i2 = 0; i2 < _addressFormats.length; i2++) {
var format2 = _addressFormats[i2];
if (!format2.countryCodes) {
addressFormat = format2;
} else if (format2.countryCodes.indexOf(_countryCode) !== -1) {
addressFormat = format2;
break;
}
}
var dropdowns = addressFormat.dropdowns || [
"city",
"county",
"country",
"district",
"hamlet",
"neighbourhood",
"place",
"postcode",
"province",
"quarter",
"state",
"street",
"subdistrict",
"suburb"
];
var widths = addressFormat.widths || {
housenumber: 1 / 3,
street: 2 / 3,
city: 2 / 3,
state: 1 / 4,
postcode: 1 / 3
};
function row(r) {
var total = r.reduce(function(sum, key) {
return sum + (widths[key] || 0.5);
}, 0);
return r.map(function(key) {
return {
id: key,
width: (widths[key] || 0.5) / total
};
});
}
var rows = _wrap.selectAll(".addr-row").data(addressFormat.format, function(d) {
return d.toString();
});
rows.exit().remove();
rows.enter().append("div").attr("class", "addr-row").selectAll("input").data(row).enter().append("input").property("type", "text").call(updatePlaceholder).attr("class", function(d) {
return "addr-" + d.id;
}).call(utilNoAuto).each(addDropdown).style("width", function(d) {
return d.width * 100 + "%";
});
function addDropdown(d) {
if (dropdowns.indexOf(d.id) === -1)
return;
var nearValues = d.id === "street" ? getNearStreets : d.id === "city" ? getNearCities : getNearValues;
select_default2(this).call(uiCombobox(context, "address-" + d.id).minItems(1).caseSensitive(true).fetcher(function(value, callback) {
callback(nearValues("addr:" + d.id));
}));
}
_wrap.selectAll("input").on("blur", change()).on("change", change());
_wrap.selectAll("input:not(.combobox-input)").on("input", change(true));
if (_tags)
updateTags(_tags);
}
function address(selection2) {
_selection = selection2;
_wrap = selection2.selectAll(".form-field-input-wrap").data([0]);
_wrap = _wrap.enter().append("div").attr("class", "form-field-input-wrap form-field-input-" + field.type).merge(_wrap);
var extent = combinedEntityExtent();
if (extent) {
var countryCode;
if (context.inIntro()) {
countryCode = _t("intro.graph.countrycode");
} else {
var center = extent.center();
countryCode = iso1A2Code(center);
}
if (countryCode) {
_countryCode = countryCode.toLowerCase();
updateForCountryCode();
}
}
}
function change(onInput) {
return function() {
var tags = {};
_wrap.selectAll("input").each(function(subfield) {
var key = field.key + ":" + subfield.id;
var value = this.value;
if (!onInput)
value = context.cleanTagValue(value);
if (Array.isArray(_tags[key]) && !value)
return;
tags[key] = value || void 0;
});
dispatch10.call("change", this, tags, onInput);
};
}
function updatePlaceholder(inputSelection) {
return inputSelection.attr("placeholder", function(subfield) {
if (_tags && Array.isArray(_tags[field.key + ":" + subfield.id])) {
return _t("inspector.multiple_values");
}
if (_countryCode) {
var localkey = subfield.id + "!" + _countryCode;
var tkey = addrField.hasTextForStringId("placeholders." + localkey) ? localkey : subfield.id;
return addrField.t("placeholders." + tkey);
}
});
}
function updateTags(tags) {
utilGetSetValue(_wrap.selectAll("input"), function(subfield) {
var val = tags[field.key + ":" + subfield.id];
return typeof val === "string" ? val : "";
}).attr("title", function(subfield) {
var val = tags[field.key + ":" + subfield.id];
return val && Array.isArray(val) ? val.filter(Boolean).join("\n") : void 0;
}).classed("mixed", function(subfield) {
return Array.isArray(tags[field.key + ":" + subfield.id]);
}).call(updatePlaceholder);
}
function combinedEntityExtent() {
return _entityIDs && _entityIDs.length && utilTotalExtent(_entityIDs, context.graph());
}
address.entityIDs = function(val) {
if (!arguments.length)
return _entityIDs;
_entityIDs = val;
return address;
};
address.tags = function(tags) {
_tags = tags;
updateTags(tags);
};
address.focus = function() {
var node = _wrap.selectAll("input").node();
if (node)
node.focus();
};
return utilRebind(address, dispatch10, "on");
}
// modules/ui/fields/cycleway.js
function uiFieldCycleway(field, context) {
var dispatch10 = dispatch_default("change");
var items = select_default2(null);
var wrap2 = select_default2(null);
var _tags;
function cycleway(selection2) {
function stripcolon(s) {
return s.replace(":", "");
}
wrap2 = selection2.selectAll(".form-field-input-wrap").data([0]);
wrap2 = wrap2.enter().append("div").attr("class", "form-field-input-wrap form-field-input-" + field.type).merge(wrap2);
var div = wrap2.selectAll("ul").data([0]);
div = div.enter().append("ul").attr("class", "rows").merge(div);
var keys = ["cycleway:left", "cycleway:right"];
items = div.selectAll("li").data(keys);
var enter = items.enter().append("li").attr("class", function(d) {
return "labeled-input preset-cycleway-" + stripcolon(d);
});
enter.append("span").attr("class", "label preset-label-cycleway").attr("for", function(d) {
return "preset-input-cycleway-" + stripcolon(d);
}).html(function(d) {
return field.t.html("types." + d);
});
enter.append("div").attr("class", "preset-input-cycleway-wrap").append("input").attr("type", "text").attr("class", function(d) {
return "preset-input-cycleway preset-input-" + stripcolon(d);
}).call(utilNoAuto).each(function(d) {
select_default2(this).call(uiCombobox(context, "cycleway-" + stripcolon(d)).data(cycleway.options(d)));
});
items = items.merge(enter);
wrap2.selectAll(".preset-input-cycleway").on("change", change).on("blur", change);
}
function change(d3_event, key) {
var newValue = context.cleanTagValue(utilGetSetValue(select_default2(this)));
if (!newValue && (Array.isArray(_tags.cycleway) || Array.isArray(_tags[key])))
return;
if (newValue === "none" || newValue === "") {
newValue = void 0;
}
var otherKey = key === "cycleway:left" ? "cycleway:right" : "cycleway:left";
var otherValue = typeof _tags.cycleway === "string" ? _tags.cycleway : _tags[otherKey];
if (otherValue && Array.isArray(otherValue)) {
otherValue = otherValue[0];
}
if (otherValue === "none" || otherValue === "") {
otherValue = void 0;
}
var tag = {};
if (newValue === otherValue) {
tag = {
cycleway: newValue,
"cycleway:left": void 0,
"cycleway:right": void 0
};
} else {
tag = {
cycleway: void 0
};
tag[key] = newValue;
tag[otherKey] = otherValue;
}
dispatch10.call("change", this, tag);
}
cycleway.options = function() {
return field.options.map(function(option) {
return {
title: field.t("options." + option + ".description"),
value: option
};
});
};
cycleway.tags = function(tags) {
_tags = tags;
var commonValue = typeof tags.cycleway === "string" && tags.cycleway;
utilGetSetValue(items.selectAll(".preset-input-cycleway"), function(d) {
if (commonValue)
return commonValue;
return !tags.cycleway && typeof tags[d] === "string" ? tags[d] : "";
}).attr("title", function(d) {
if (Array.isArray(tags.cycleway) || Array.isArray(tags[d])) {
var vals = [];
if (Array.isArray(tags.cycleway)) {
vals = vals.concat(tags.cycleway);
}
if (Array.isArray(tags[d])) {
vals = vals.concat(tags[d]);
}
return vals.filter(Boolean).join("\n");
}
return null;
}).attr("placeholder", function(d) {
if (Array.isArray(tags.cycleway) || Array.isArray(tags[d])) {
return _t("inspector.multiple_values");
}
return field.placeholder();
}).classed("mixed", function(d) {
return Array.isArray(tags.cycleway) || Array.isArray(tags[d]);
});
};
cycleway.focus = function() {
var node = wrap2.selectAll("input").node();
if (node)
node.focus();
};
return utilRebind(cycleway, dispatch10, "on");
}
// modules/ui/fields/lanes.js
function uiFieldLanes(field, context) {
var dispatch10 = dispatch_default("change");
var LANE_WIDTH = 40;
var LANE_HEIGHT = 200;
var _entityIDs = [];
function lanes(selection2) {
var lanesData = context.entity(_entityIDs[0]).lanes();
if (!context.container().select(".inspector-wrap.inspector-hidden").empty() || !selection2.node().parentNode) {
selection2.call(lanes.off);
return;
}
var wrap2 = selection2.selectAll(".form-field-input-wrap").data([0]);
wrap2 = wrap2.enter().append("div").attr("class", "form-field-input-wrap form-field-input-" + field.type).merge(wrap2);
var surface = wrap2.selectAll(".surface").data([0]);
var d = utilGetDimensions(wrap2);
var freeSpace = d[0] - lanesData.lanes.length * LANE_WIDTH * 1.5 + LANE_WIDTH * 0.5;
surface = surface.enter().append("svg").attr("width", d[0]).attr("height", 300).attr("class", "surface").merge(surface);
var lanesSelection = surface.selectAll(".lanes").data([0]);
lanesSelection = lanesSelection.enter().append("g").attr("class", "lanes").merge(lanesSelection);
lanesSelection.attr("transform", function() {
return "translate(" + freeSpace / 2 + ", 0)";
});
var lane = lanesSelection.selectAll(".lane").data(lanesData.lanes);
lane.exit().remove();
var enter = lane.enter().append("g").attr("class", "lane");
enter.append("g").append("rect").attr("y", 50).attr("width", LANE_WIDTH).attr("height", LANE_HEIGHT);
enter.append("g").attr("class", "forward").append("text").attr("y", 40).attr("x", 14).text("\u25B2");
enter.append("g").attr("class", "bothways").append("text").attr("y", 40).attr("x", 14).text("\u25B2\u25BC");
enter.append("g").attr("class", "backward").append("text").attr("y", 40).attr("x", 14).text("\u25BC");
lane = lane.merge(enter);
lane.attr("transform", function(d2) {
return "translate(" + LANE_WIDTH * d2.index * 1.5 + ", 0)";
});
lane.select(".forward").style("visibility", function(d2) {
return d2.direction === "forward" ? "visible" : "hidden";
});
lane.select(".bothways").style("visibility", function(d2) {
return d2.direction === "bothways" ? "visible" : "hidden";
});
lane.select(".backward").style("visibility", function(d2) {
return d2.direction === "backward" ? "visible" : "hidden";
});
}
lanes.entityIDs = function(val) {
_entityIDs = val;
};
lanes.tags = function() {
};
lanes.focus = function() {
};
lanes.off = function() {
};
return utilRebind(lanes, dispatch10, "on");
}
uiFieldLanes.supportsMultiselection = false;
// modules/ui/fields/localized.js
var _languagesArray = [];
function uiFieldLocalized(field, context) {
var dispatch10 = dispatch_default("change", "input");
var wikipedia = services.wikipedia;
var input = select_default2(null);
var localizedInputs = select_default2(null);
var _countryCode;
var _tags;
_mainFileFetcher.get("languages").then(loadLanguagesArray).catch(function() {
});
var _territoryLanguages = {};
_mainFileFetcher.get("territory_languages").then(function(d) {
_territoryLanguages = d;
}).catch(function() {
});
var langCombo = uiCombobox(context, "localized-lang").fetcher(fetchLanguages).minItems(0);
var _selection = select_default2(null);
var _multilingual = [];
var _buttonTip = uiTooltip().title(_t.html("translate.translate")).placement("left");
var _wikiTitles;
var _entityIDs = [];
function loadLanguagesArray(dataLanguages) {
if (_languagesArray.length !== 0)
return;
var replacements = {
sr: "sr-Cyrl",
"sr-Cyrl": false
};
for (var code in dataLanguages) {
if (replacements[code] === false)
continue;
var metaCode = code;
if (replacements[code])
metaCode = replacements[code];
_languagesArray.push({
localName: _mainLocalizer.languageName(metaCode, { localOnly: true }),
nativeName: dataLanguages[metaCode].nativeName,
code,
label: _mainLocalizer.languageName(metaCode)
});
}
}
function calcLocked() {
var isLocked = field.id === "name" && _entityIDs.length && _entityIDs.some(function(entityID) {
var entity = context.graph().hasEntity(entityID);
if (!entity)
return false;
if (entity.tags.wikidata)
return true;
if (entity.tags["name:etymology:wikidata"])
return true;
var preset = _mainPresetIndex.match(entity, context.graph());
if (preset) {
var isSuggestion = preset.suggestion;
var fields = preset.fields();
var showsBrandField = fields.some(function(d) {
return d.id === "brand";
});
var showsOperatorField = fields.some(function(d) {
return d.id === "operator";
});
var setsName = preset.addTags.name;
var setsBrandWikidata = preset.addTags["brand:wikidata"];
var setsOperatorWikidata = preset.addTags["operator:wikidata"];
return isSuggestion && setsName && (setsBrandWikidata && !showsBrandField || setsOperatorWikidata && !showsOperatorField);
}
return false;
});
field.locked(isLocked);
}
function calcMultilingual(tags) {
var existingLangsOrdered = _multilingual.map(function(item2) {
return item2.lang;
});
var existingLangs = new Set(existingLangsOrdered.filter(Boolean));
for (var k in tags) {
var m = k.match(/^(.*):([a-z]{2,3}(?:-[A-Z][a-z]{3})?(?:-[A-Z]{2})?)$/);
if (m && m[1] === field.key && m[2]) {
var item = { lang: m[2], value: tags[k] };
if (existingLangs.has(item.lang)) {
_multilingual[existingLangsOrdered.indexOf(item.lang)].value = item.value;
existingLangs.delete(item.lang);
} else {
_multilingual.push(item);
}
}
}
_multilingual.forEach(function(item2) {
if (item2.lang && existingLangs.has(item2.lang)) {
item2.value = "";
}
});
}
function localized(selection2) {
_selection = selection2;
calcLocked();
var isLocked = field.locked();
var wrap2 = selection2.selectAll(".form-field-input-wrap").data([0]);
wrap2 = wrap2.enter().append("div").attr("class", "form-field-input-wrap form-field-input-" + field.type).merge(wrap2);
input = wrap2.selectAll(".localized-main").data([0]);
input = input.enter().append("input").attr("type", "text").attr("id", field.domId).attr("class", "localized-main").call(utilNoAuto).merge(input);
input.classed("disabled", !!isLocked).attr("readonly", isLocked || null).on("input", change(true)).on("blur", change()).on("change", change());
var translateButton = wrap2.selectAll(".localized-add").data([0]);
translateButton = translateButton.enter().append("button").attr("class", "localized-add form-field-button").attr("aria-label", _t("icons.plus")).call(svgIcon("#iD-icon-plus")).merge(translateButton);
translateButton.classed("disabled", !!isLocked).call(isLocked ? _buttonTip.destroy : _buttonTip).on("click", addNew);
if (_tags && !_multilingual.length) {
calcMultilingual(_tags);
}
localizedInputs = selection2.selectAll(".localized-multilingual").data([0]);
localizedInputs = localizedInputs.enter().append("div").attr("class", "localized-multilingual").merge(localizedInputs);
localizedInputs.call(renderMultilingual);
localizedInputs.selectAll("button, input").classed("disabled", !!isLocked).attr("readonly", isLocked || null);
selection2.selectAll(".combobox-caret").classed("nope", true);
function addNew(d3_event) {
d3_event.preventDefault();
if (field.locked())
return;
var defaultLang = _mainLocalizer.languageCode().toLowerCase();
var langExists = _multilingual.find(function(datum2) {
return datum2.lang === defaultLang;
});
var isLangEn = defaultLang.indexOf("en") > -1;
if (isLangEn || langExists) {
defaultLang = "";
langExists = _multilingual.find(function(datum2) {
return datum2.lang === defaultLang;
});
}
if (!langExists) {
_multilingual.unshift({ lang: defaultLang, value: "" });
localizedInputs.call(renderMultilingual);
}
}
function change(onInput) {
return function(d3_event) {
if (field.locked()) {
d3_event.preventDefault();
return;
}
var val = utilGetSetValue(select_default2(this));
if (!onInput)
val = context.cleanTagValue(val);
if (!val && Array.isArray(_tags[field.key]))
return;
var t = {};
t[field.key] = val || void 0;
dispatch10.call("change", this, t, onInput);
};
}
}
function key(lang) {
return field.key + ":" + lang;
}
function changeLang(d3_event, d) {
var tags = {};
var lang = utilGetSetValue(select_default2(this)).toLowerCase();
var language = _languagesArray.find(function(d2) {
return d2.label.toLowerCase() === lang || d2.localName && d2.localName.toLowerCase() === lang || d2.nativeName && d2.nativeName.toLowerCase() === lang;
});
if (language)
lang = language.code;
if (d.lang && d.lang !== lang) {
tags[key(d.lang)] = void 0;
}
var newKey = lang && context.cleanTagKey(key(lang));
var value = utilGetSetValue(select_default2(this.parentNode).selectAll(".localized-value"));
if (newKey && value) {
tags[newKey] = value;
} else if (newKey && _wikiTitles && _wikiTitles[d.lang]) {
tags[newKey] = _wikiTitles[d.lang];
}
d.lang = lang;
dispatch10.call("change", this, tags);
}
function changeValue(d3_event, d) {
if (!d.lang)
return;
var value = context.cleanTagValue(utilGetSetValue(select_default2(this))) || void 0;
if (!value && Array.isArray(d.value))
return;
var t = {};
t[key(d.lang)] = value;
d.value = value;
dispatch10.call("change", this, t);
}
function fetchLanguages(value, cb) {
var v = value.toLowerCase();
var langCodes = [_mainLocalizer.localeCode(), _mainLocalizer.languageCode()];
if (_countryCode && _territoryLanguages[_countryCode]) {
langCodes = langCodes.concat(_territoryLanguages[_countryCode]);
}
var langItems = [];
langCodes.forEach(function(code) {
var langItem = _languagesArray.find(function(item) {
return item.code === code;
});
if (langItem)
langItems.push(langItem);
});
langItems = utilArrayUniq(langItems.concat(_languagesArray));
cb(langItems.filter(function(d) {
return d.label.toLowerCase().indexOf(v) >= 0 || d.localName && d.localName.toLowerCase().indexOf(v) >= 0 || d.nativeName && d.nativeName.toLowerCase().indexOf(v) >= 0 || d.code.toLowerCase().indexOf(v) >= 0;
}).map(function(d) {
return { value: d.label };
}));
}
function renderMultilingual(selection2) {
var entries = selection2.selectAll("div.entry").data(_multilingual, function(d) {
return d.lang;
});
entries.exit().style("top", "0").style("max-height", "240px").transition().duration(200).style("opacity", "0").style("max-height", "0px").remove();
var entriesEnter = entries.enter().append("div").attr("class", "entry").each(function(_, index) {
var wrap2 = select_default2(this);
var domId = utilUniqueDomId(index);
var label = wrap2.append("label").attr("class", "field-label").attr("for", domId);
var text2 = label.append("span").attr("class", "label-text");
text2.append("span").attr("class", "label-textvalue").call(_t.append("translate.localized_translation_label"));
text2.append("span").attr("class", "label-textannotation");
label.append("button").attr("class", "remove-icon-multilingual").attr("title", _t("icons.remove")).on("click", function(d3_event, d) {
if (field.locked())
return;
d3_event.preventDefault();
_multilingual.splice(_multilingual.indexOf(d), 1);
var langKey = d.lang && key(d.lang);
if (langKey && langKey in _tags) {
delete _tags[langKey];
var t = {};
t[langKey] = void 0;
dispatch10.call("change", this, t);
return;
}
renderMultilingual(selection2);
}).call(svgIcon("#iD-operation-delete"));
wrap2.append("input").attr("class", "localized-lang").attr("id", domId).attr("type", "text").attr("placeholder", _t("translate.localized_translation_language")).on("blur", changeLang).on("change", changeLang).call(langCombo);
wrap2.append("input").attr("type", "text").attr("class", "localized-value").on("blur", changeValue).on("change", changeValue);
});
entriesEnter.style("margin-top", "0px").style("max-height", "0px").style("opacity", "0").transition().duration(200).style("margin-top", "10px").style("max-height", "240px").style("opacity", "1").on("end", function() {
select_default2(this).style("max-height", "").style("overflow", "visible");
});
entries = entries.merge(entriesEnter);
entries.order();
entries.classed("present", true);
utilGetSetValue(entries.select(".localized-lang"), function(d) {
var langItem = _languagesArray.find(function(item) {
return item.code === d.lang;
});
if (langItem)
return langItem.label;
return d.lang;
});
utilGetSetValue(entries.select(".localized-value"), function(d) {
return typeof d.value === "string" ? d.value : "";
}).attr("title", function(d) {
return Array.isArray(d.value) ? d.value.filter(Boolean).join("\n") : null;
}).attr("placeholder", function(d) {
return Array.isArray(d.value) ? _t("inspector.multiple_values") : _t("translate.localized_translation_name");
}).classed("mixed", function(d) {
return Array.isArray(d.value);
});
}
localized.tags = function(tags) {
_tags = tags;
if (typeof tags.wikipedia === "string" && !_wikiTitles) {
_wikiTitles = {};
var wm = tags.wikipedia.match(/([^:]+):(.+)/);
if (wm && wm[0] && wm[1]) {
wikipedia.translations(wm[1], wm[2], function(err, d) {
if (err || !d)
return;
_wikiTitles = d;
});
}
}
var isMixed = Array.isArray(tags[field.key]);
utilGetSetValue(input, typeof tags[field.key] === "string" ? tags[field.key] : "").attr("title", isMixed ? tags[field.key].filter(Boolean).join("\n") : void 0).attr("placeholder", isMixed ? _t("inspector.multiple_values") : field.placeholder()).classed("mixed", isMixed);
calcMultilingual(tags);
_selection.call(localized);
};
localized.focus = function() {
input.node().focus();
};
localized.entityIDs = function(val) {
if (!arguments.length)
return _entityIDs;
_entityIDs = val;
_multilingual = [];
loadCountryCode();
return localized;
};
function loadCountryCode() {
var extent = combinedEntityExtent();
var countryCode = extent && iso1A2Code(extent.center());
_countryCode = countryCode && countryCode.toLowerCase();
}
function combinedEntityExtent() {
return _entityIDs && _entityIDs.length && utilTotalExtent(_entityIDs, context.graph());
}
return utilRebind(localized, dispatch10, "on");
}
// modules/ui/fields/roadheight.js
function uiFieldRoadheight(field, context) {
var dispatch10 = dispatch_default("change");
var primaryUnitInput = select_default2(null);
var primaryInput = select_default2(null);
var secondaryInput = select_default2(null);
var secondaryUnitInput = select_default2(null);
var _entityIDs = [];
var _tags;
var _isImperial;
var primaryUnits = [
{
value: "m",
title: _t("inspector.roadheight.meter")
},
{
value: "ft",
title: _t("inspector.roadheight.foot")
}
];
var unitCombo = uiCombobox(context, "roadheight-unit").data(primaryUnits);
function roadheight(selection2) {
var wrap2 = selection2.selectAll(".form-field-input-wrap").data([0]);
wrap2 = wrap2.enter().append("div").attr("class", "form-field-input-wrap form-field-input-" + field.type).merge(wrap2);
primaryInput = wrap2.selectAll("input.roadheight-number").data([0]);
primaryInput = primaryInput.enter().append("input").attr("type", "text").attr("class", "roadheight-number").attr("id", field.domId).call(utilNoAuto).merge(primaryInput);
primaryInput.on("change", change).on("blur", change);
var loc = combinedEntityExtent().center();
_isImperial = roadHeightUnit(loc) === "ft";
primaryUnitInput = wrap2.selectAll("input.roadheight-unit").data([0]);
primaryUnitInput = primaryUnitInput.enter().append("input").attr("type", "text").attr("class", "roadheight-unit").call(unitCombo).merge(primaryUnitInput);
primaryUnitInput.on("blur", changeUnits).on("change", changeUnits);
secondaryInput = wrap2.selectAll("input.roadheight-secondary-number").data([0]);
secondaryInput = secondaryInput.enter().append("input").attr("type", "text").attr("class", "roadheight-secondary-number").call(utilNoAuto).merge(secondaryInput);
secondaryInput.on("change", change).on("blur", change);
secondaryUnitInput = wrap2.selectAll("input.roadheight-secondary-unit").data([0]);
secondaryUnitInput = secondaryUnitInput.enter().append("input").attr("type", "text").call(utilNoAuto).classed("disabled", true).classed("roadheight-secondary-unit", true).attr("readonly", "readonly").merge(secondaryUnitInput);
function changeUnits() {
_isImperial = utilGetSetValue(primaryUnitInput) === "ft";
utilGetSetValue(primaryUnitInput, _isImperial ? "ft" : "m");
setUnitSuggestions();
change();
}
}
function setUnitSuggestions() {
utilGetSetValue(primaryUnitInput, _isImperial ? "ft" : "m");
}
function change() {
var tag = {};
var primaryValue = utilGetSetValue(primaryInput).trim();
var secondaryValue = utilGetSetValue(secondaryInput).trim();
if (!primaryValue && !secondaryValue && Array.isArray(_tags[field.key]))
return;
if (!primaryValue && !secondaryValue) {
tag[field.key] = void 0;
} else if (isNaN(primaryValue) || isNaN(secondaryValue) || !_isImperial) {
tag[field.key] = context.cleanTagValue(primaryValue);
} else {
if (primaryValue !== "") {
primaryValue = context.cleanTagValue(primaryValue + "'");
}
if (secondaryValue !== "") {
secondaryValue = context.cleanTagValue(secondaryValue + '"');
}
tag[field.key] = primaryValue + secondaryValue;
}
dispatch10.call("change", this, tag);
}
roadheight.tags = function(tags) {
_tags = tags;
var primaryValue = tags[field.key];
var secondaryValue;
var isMixed = Array.isArray(primaryValue);
if (!isMixed) {
if (primaryValue && (primaryValue.indexOf("'") >= 0 || primaryValue.indexOf('"') >= 0)) {
secondaryValue = primaryValue.match(/(-?[\d.]+)"/);
if (secondaryValue !== null) {
secondaryValue = secondaryValue[1];
}
primaryValue = primaryValue.match(/(-?[\d.]+)'/);
if (primaryValue !== null) {
primaryValue = primaryValue[1];
}
_isImperial = true;
} else if (primaryValue) {
_isImperial = false;
}
}
setUnitSuggestions();
utilGetSetValue(primaryInput, typeof primaryValue === "string" ? primaryValue : "").attr("title", isMixed ? primaryValue.filter(Boolean).join("\n") : null).attr("placeholder", isMixed ? _t("inspector.multiple_values") : _t("inspector.unknown")).classed("mixed", isMixed);
utilGetSetValue(secondaryInput, typeof secondaryValue === "string" ? secondaryValue : "").attr("placeholder", isMixed ? _t("inspector.multiple_values") : _isImperial ? "0" : null).classed("mixed", isMixed).classed("disabled", !_isImperial).attr("readonly", _isImperial ? null : "readonly");
secondaryUnitInput.attr("value", _isImperial ? _t("inspector.roadheight.inch") : null);
};
roadheight.focus = function() {
primaryInput.node().focus();
};
roadheight.entityIDs = function(val) {
_entityIDs = val;
};
function combinedEntityExtent() {
return _entityIDs && _entityIDs.length && utilTotalExtent(_entityIDs, context.graph());
}
return utilRebind(roadheight, dispatch10, "on");
}
// modules/ui/fields/roadspeed.js
function uiFieldRoadspeed(field, context) {
var dispatch10 = dispatch_default("change");
var unitInput = select_default2(null);
var input = select_default2(null);
var _entityIDs = [];
var _tags;
var _isImperial;
var speedCombo = uiCombobox(context, "roadspeed");
var unitCombo = uiCombobox(context, "roadspeed-unit").data(["km/h", "mph"].map(comboValues));
var metricValues = [20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120];
var imperialValues = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80];
function roadspeed(selection2) {
var wrap2 = selection2.selectAll(".form-field-input-wrap").data([0]);
wrap2 = wrap2.enter().append("div").attr("class", "form-field-input-wrap form-field-input-" + field.type).merge(wrap2);
input = wrap2.selectAll("input.roadspeed-number").data([0]);
input = input.enter().append("input").attr("type", "text").attr("class", "roadspeed-number").attr("id", field.domId).call(utilNoAuto).call(speedCombo).merge(input);
input.on("change", change).on("blur", change);
var loc = combinedEntityExtent().center();
_isImperial = roadSpeedUnit(loc) === "mph";
unitInput = wrap2.selectAll("input.roadspeed-unit").data([0]);
unitInput = unitInput.enter().append("input").attr("type", "text").attr("class", "roadspeed-unit").attr("aria-label", _t("inspector.speed_unit")).call(unitCombo).merge(unitInput);
unitInput.on("blur", changeUnits).on("change", changeUnits);
function changeUnits() {
_isImperial = utilGetSetValue(unitInput) === "mph";
utilGetSetValue(unitInput, _isImperial ? "mph" : "km/h");
setUnitSuggestions();
change();
}
}
function setUnitSuggestions() {
speedCombo.data((_isImperial ? imperialValues : metricValues).map(comboValues));
utilGetSetValue(unitInput, _isImperial ? "mph" : "km/h");
}
function comboValues(d) {
return {
value: d.toString(),
title: d.toString()
};
}
function change() {
var tag = {};
var value = utilGetSetValue(input).trim();
if (!value && Array.isArray(_tags[field.key]))
return;
if (!value) {
tag[field.key] = void 0;
} else if (isNaN(value) || !_isImperial) {
tag[field.key] = context.cleanTagValue(value);
} else {
tag[field.key] = context.cleanTagValue(value + " mph");
}
dispatch10.call("change", this, tag);
}
roadspeed.tags = function(tags) {
_tags = tags;
var value = tags[field.key];
var isMixed = Array.isArray(value);
if (!isMixed) {
if (value && value.indexOf("mph") >= 0) {
value = parseInt(value, 10).toString();
_isImperial = true;
} else if (value) {
_isImperial = false;
}
}
setUnitSuggestions();
utilGetSetValue(input, typeof value === "string" ? value : "").attr("title", isMixed ? value.filter(Boolean).join("\n") : null).attr("placeholder", isMixed ? _t("inspector.multiple_values") : field.placeholder()).classed("mixed", isMixed);
};
roadspeed.focus = function() {
input.node().focus();
};
roadspeed.entityIDs = function(val) {
_entityIDs = val;
};
function combinedEntityExtent() {
return _entityIDs && _entityIDs.length && utilTotalExtent(_entityIDs, context.graph());
}
return utilRebind(roadspeed, dispatch10, "on");
}
// modules/ui/fields/radio.js
function uiFieldRadio(field, context) {
var dispatch10 = dispatch_default("change");
var placeholder = select_default2(null);
var wrap2 = select_default2(null);
var labels = select_default2(null);
var radios = select_default2(null);
var radioData = (field.options || field.keys).slice();
var typeField;
var layerField;
var _oldType = {};
var _entityIDs = [];
function selectedKey() {
var node = wrap2.selectAll(".form-field-input-radio label.active input");
return !node.empty() && node.datum();
}
function radio(selection2) {
selection2.classed("preset-radio", true);
wrap2 = selection2.selectAll(".form-field-input-wrap").data([0]);
var enter = wrap2.enter().append("div").attr("class", "form-field-input-wrap form-field-input-radio");
enter.append("span").attr("class", "placeholder");
wrap2 = wrap2.merge(enter);
placeholder = wrap2.selectAll(".placeholder");
labels = wrap2.selectAll("label").data(radioData);
enter = labels.enter().append("label");
enter.append("input").attr("type", "radio").attr("name", field.id).attr("value", function(d) {
return field.t("options." + d, { "default": d });
}).attr("checked", false);
enter.append("span").html(function(d) {
return field.t.html("options." + d, { "default": d });
});
labels = labels.merge(enter);
radios = labels.selectAll("input").on("change", changeRadio);
}
function structureExtras(selection2, tags) {
var selected = selectedKey() || tags.layer !== void 0;
var type3 = _mainPresetIndex.field(selected);
var layer = _mainPresetIndex.field("layer");
var showLayer = selected === "bridge" || selected === "tunnel" || tags.layer !== void 0;
var extrasWrap = selection2.selectAll(".structure-extras-wrap").data(selected ? [0] : []);
extrasWrap.exit().remove();
extrasWrap = extrasWrap.enter().append("div").attr("class", "structure-extras-wrap").merge(extrasWrap);
var list = extrasWrap.selectAll("ul").data([0]);
list = list.enter().append("ul").attr("class", "rows").merge(list);
if (type3) {
if (!typeField || typeField.id !== selected) {
typeField = uiField(context, type3, _entityIDs, { wrap: false }).on("change", changeType);
}
typeField.tags(tags);
} else {
typeField = null;
}
var typeItem = list.selectAll(".structure-type-item").data(typeField ? [typeField] : [], function(d) {
return d.id;
});
typeItem.exit().remove();
var typeEnter = typeItem.enter().insert("li", ":first-child").attr("class", "labeled-input structure-type-item");
typeEnter.append("span").attr("class", "label structure-label-type").attr("for", "preset-input-" + selected).call(_t.append("inspector.radio.structure.type"));
typeEnter.append("div").attr("class", "structure-input-type-wrap");
typeItem = typeItem.merge(typeEnter);
if (typeField) {
typeItem.selectAll(".structure-input-type-wrap").call(typeField.render);
}
if (layer && showLayer) {
if (!layerField) {
layerField = uiField(context, layer, _entityIDs, { wrap: false }).on("change", changeLayer);
}
layerField.tags(tags);
field.keys = utilArrayUnion(field.keys, ["layer"]);
} else {
layerField = null;
field.keys = field.keys.filter(function(k) {
return k !== "layer";
});
}
var layerItem = list.selectAll(".structure-layer-item").data(layerField ? [layerField] : []);
layerItem.exit().remove();
var layerEnter = layerItem.enter().append("li").attr("class", "labeled-input structure-layer-item");
layerEnter.append("span").attr("class", "label structure-label-layer").attr("for", "preset-input-layer").call(_t.append("inspector.radio.structure.layer"));
layerEnter.append("div").attr("class", "structure-input-layer-wrap");
layerItem = layerItem.merge(layerEnter);
if (layerField) {
layerItem.selectAll(".structure-input-layer-wrap").call(layerField.render);
}
}
function changeType(t, onInput) {
var key = selectedKey();
if (!key)
return;
var val = t[key];
if (val !== "no") {
_oldType[key] = val;
}
if (field.type === "structureRadio") {
if (val === "no" || key !== "bridge" && key !== "tunnel" || key === "tunnel" && val === "building_passage") {
t.layer = void 0;
}
if (t.layer === void 0) {
if (key === "bridge" && val !== "no") {
t.layer = "1";
}
if (key === "tunnel" && val !== "no" && val !== "building_passage") {
t.layer = "-1";
}
}
}
dispatch10.call("change", this, t, onInput);
}
function changeLayer(t, onInput) {
if (t.layer === "0") {
t.layer = void 0;
}
dispatch10.call("change", this, t, onInput);
}
function changeRadio() {
var t = {};
var activeKey;
if (field.key) {
t[field.key] = void 0;
}
radios.each(function(d) {
var active = select_default2(this).property("checked");
if (active)
activeKey = d;
if (field.key) {
if (active)
t[field.key] = d;
} else {
var val = _oldType[activeKey] || "yes";
t[d] = active ? val : void 0;
}
});
if (field.type === "structureRadio") {
if (activeKey === "bridge") {
t.layer = "1";
} else if (activeKey === "tunnel" && t.tunnel !== "building_passage") {
t.layer = "-1";
} else {
t.layer = void 0;
}
}
dispatch10.call("change", this, t);
}
radio.tags = function(tags) {
function isOptionChecked(d) {
if (field.key) {
return tags[field.key] === d;
}
return !!(typeof tags[d] === "string" && tags[d].toLowerCase() !== "no");
}
function isMixed(d) {
if (field.key) {
return Array.isArray(tags[field.key]) && tags[field.key].includes(d);
}
return Array.isArray(tags[d]);
}
radios.property("checked", function(d) {
return isOptionChecked(d) && (field.key || field.options.filter(isOptionChecked).length === 1);
});
labels.classed("active", function(d) {
if (field.key) {
return Array.isArray(tags[field.key]) && tags[field.key].includes(d) || tags[field.key] === d;
}
return Array.isArray(tags[d]) && tags[d].some((v) => typeof v === "string" && v.toLowerCase() !== "no") || !!(typeof tags[d] === "string" && tags[d].toLowerCase() !== "no");
}).classed("mixed", isMixed).attr("title", function(d) {
return isMixed(d) ? _t("inspector.unshared_value_tooltip") : null;
});
var selection2 = radios.filter(function() {
return this.checked;
});
if (selection2.empty()) {
placeholder.text("");
placeholder.call(_t.append("inspector.none"));
} else {
placeholder.text(selection2.attr("value"));
_oldType[selection2.datum()] = tags[selection2.datum()];
}
if (field.type === "structureRadio") {
if (!!tags.waterway && !_oldType.tunnel) {
_oldType.tunnel = "culvert";
}
wrap2.call(structureExtras, tags);
}
};
radio.focus = function() {
radios.node().focus();
};
radio.entityIDs = function(val) {
if (!arguments.length)
return _entityIDs;
_entityIDs = val;
_oldType = {};
return radio;
};
radio.isAllowed = function() {
return _entityIDs.length === 1;
};
return utilRebind(radio, dispatch10, "on");
}
// modules/ui/fields/restrictions.js
function uiFieldRestrictions(field, context) {
var dispatch10 = dispatch_default("change");
var breathe = behaviorBreathe(context);
corePreferences("turn-restriction-via-way", null);
var storedViaWay = corePreferences("turn-restriction-via-way0");
var storedDistance = corePreferences("turn-restriction-distance");
var _maxViaWay = storedViaWay !== null ? +storedViaWay : 0;
var _maxDistance = storedDistance ? +storedDistance : 30;
var _initialized2 = false;
var _parent = select_default2(null);
var _container = select_default2(null);
var _oldTurns;
var _graph;
var _vertexID;
var _intersection;
var _fromWayID;
var _lastXPos;
function restrictions(selection2) {
_parent = selection2;
if (_vertexID && (context.graph() !== _graph || !_intersection)) {
_graph = context.graph();
_intersection = osmIntersection(_graph, _vertexID, _maxDistance);
}
var isOK = _intersection && _intersection.vertices.length && _intersection.vertices.filter(function(vertex) {
return vertex.id === _vertexID;
}).length && _intersection.ways.length > 2 && _intersection.ways.filter(function(way) {
return way.__to;
}).length > 1;
select_default2(selection2.node().parentNode).classed("hide", !isOK);
if (!isOK || !context.container().select(".inspector-wrap.inspector-hidden").empty() || !selection2.node().parentNode || !selection2.node().parentNode.parentNode) {
selection2.call(restrictions.off);
return;
}
var wrap2 = selection2.selectAll(".form-field-input-wrap").data([0]);
wrap2 = wrap2.enter().append("div").attr("class", "form-field-input-wrap form-field-input-" + field.type).merge(wrap2);
var container = wrap2.selectAll(".restriction-container").data([0]);
var containerEnter = container.enter().append("div").attr("class", "restriction-container");
containerEnter.append("div").attr("class", "restriction-help");
_container = containerEnter.merge(container).call(renderViewer);
var controls = wrap2.selectAll(".restriction-controls").data([0]);
controls.enter().append("div").attr("class", "restriction-controls-container").append("div").attr("class", "restriction-controls").merge(controls).call(renderControls);
}
function renderControls(selection2) {
var distControl = selection2.selectAll(".restriction-distance").data([0]);
distControl.exit().remove();
var distControlEnter = distControl.enter().append("div").attr("class", "restriction-control restriction-distance");
distControlEnter.append("span").attr("class", "restriction-control-label restriction-distance-label").call(_t.append("restriction.controls.distance", { suffix: ":" }));
distControlEnter.append("input").attr("class", "restriction-distance-input").attr("type", "range").attr("min", "20").attr("max", "50").attr("step", "5");
distControlEnter.append("span").attr("class", "restriction-distance-text");
selection2.selectAll(".restriction-distance-input").property("value", _maxDistance).on("input", function() {
var val = select_default2(this).property("value");
_maxDistance = +val;
_intersection = null;
_container.selectAll(".layer-osm .layer-turns *").remove();
corePreferences("turn-restriction-distance", _maxDistance);
_parent.call(restrictions);
});
selection2.selectAll(".restriction-distance-text").call(displayMaxDistance(_maxDistance));
var viaControl = selection2.selectAll(".restriction-via-way").data([0]);
viaControl.exit().remove();
var viaControlEnter = viaControl.enter().append("div").attr("class", "restriction-control restriction-via-way");
viaControlEnter.append("span").attr("class", "restriction-control-label restriction-via-way-label").call(_t.append("restriction.controls.via", { suffix: ":" }));
viaControlEnter.append("input").attr("class", "restriction-via-way-input").attr("type", "range").attr("min", "0").attr("max", "2").attr("step", "1");
viaControlEnter.append("span").attr("class", "restriction-via-way-text");
selection2.selectAll(".restriction-via-way-input").property("value", _maxViaWay).on("input", function() {
var val = select_default2(this).property("value");
_maxViaWay = +val;
_container.selectAll(".layer-osm .layer-turns *").remove();
corePreferences("turn-restriction-via-way0", _maxViaWay);
_parent.call(restrictions);
});
selection2.selectAll(".restriction-via-way-text").call(displayMaxVia(_maxViaWay));
}
function renderViewer(selection2) {
if (!_intersection)
return;
var vgraph = _intersection.graph;
var filter2 = utilFunctor(true);
var projection2 = geoRawMercator();
var sdims = utilGetDimensions(context.container().select(".sidebar"));
var d = [sdims[0] - 50, 370];
var c = geoVecScale(d, 0.5);
var z = 22;
projection2.scale(geoZoomToScale(z));
var extent = geoExtent();
for (var i2 = 0; i2 < _intersection.vertices.length; i2++) {
extent._extend(_intersection.vertices[i2].extent());
}
var padTop = 35;
if (_intersection.vertices.length > 1) {
var hPadding = Math.min(160, Math.max(110, d[0] * 0.4));
var vPadding = 160;
var tl = projection2([extent[0][0], extent[1][1]]);
var br = projection2([extent[1][0], extent[0][1]]);
var hFactor = (br[0] - tl[0]) / (d[0] - hPadding);
var vFactor = (br[1] - tl[1]) / (d[1] - vPadding - padTop);
var hZoomDiff = Math.log(Math.abs(hFactor)) / Math.LN2;
var vZoomDiff = Math.log(Math.abs(vFactor)) / Math.LN2;
z = z - Math.max(hZoomDiff, vZoomDiff);
projection2.scale(geoZoomToScale(z));
}
var extentCenter = projection2(extent.center());
extentCenter[1] = extentCenter[1] - padTop / 2;
projection2.translate(geoVecSubtract(c, extentCenter)).clipExtent([[0, 0], d]);
var drawLayers = svgLayers(projection2, context).only(["osm", "touch"]).dimensions(d);
var drawVertices = svgVertices(projection2, context);
var drawLines = svgLines(projection2, context);
var drawTurns = svgTurns(projection2, context);
var firstTime = selection2.selectAll(".surface").empty();
selection2.call(drawLayers);
var surface = selection2.selectAll(".surface").classed("tr", true);
if (firstTime) {
_initialized2 = true;
surface.call(breathe);
}
if (_fromWayID && !vgraph.hasEntity(_fromWayID)) {
_fromWayID = null;
_oldTurns = null;
}
surface.call(utilSetDimensions, d).call(drawVertices, vgraph, _intersection.vertices, filter2, extent, z).call(drawLines, vgraph, _intersection.ways, filter2).call(drawTurns, vgraph, _intersection.turns(_fromWayID, _maxViaWay));
surface.on("click.restrictions", click).on("mouseover.restrictions", mouseover);
surface.selectAll(".selected").classed("selected", false);
surface.selectAll(".related").classed("related", false);
var way;
if (_fromWayID) {
way = vgraph.entity(_fromWayID);
surface.selectAll("." + _fromWayID).classed("selected", true).classed("related", true);
}
document.addEventListener("resizeWindow", function() {
utilSetDimensions(_container, null);
redraw(1);
}, false);
updateHints(null);
function click(d3_event) {
surface.call(breathe.off).call(breathe);
var datum2 = d3_event.target.__data__;
var entity = datum2 && datum2.properties && datum2.properties.entity;
if (entity) {
datum2 = entity;
}
if (datum2 instanceof osmWay && (datum2.__from || datum2.__via)) {
_fromWayID = datum2.id;
_oldTurns = null;
redraw();
} else if (datum2 instanceof osmTurn) {
var actions, extraActions, turns, i3;
var restrictionType = osmInferRestriction(vgraph, datum2, projection2);
if (datum2.restrictionID && !datum2.direct) {
return;
} else if (datum2.restrictionID && !datum2.only) {
var seen = {};
var datumOnly = JSON.parse(JSON.stringify(datum2));
datumOnly.only = true;
restrictionType = restrictionType.replace(/^no/, "only");
turns = _intersection.turns(_fromWayID, 2);
extraActions = [];
_oldTurns = [];
for (i3 = 0; i3 < turns.length; i3++) {
var turn = turns[i3];
if (seen[turn.restrictionID])
continue;
if (turn.direct && turn.path[1] === datum2.path[1]) {
seen[turns[i3].restrictionID] = true;
turn.restrictionType = osmInferRestriction(vgraph, turn, projection2);
_oldTurns.push(turn);
extraActions.push(actionUnrestrictTurn(turn));
}
}
actions = _intersection.actions.concat(extraActions, [
actionRestrictTurn(datumOnly, restrictionType),
_t("operations.restriction.annotation.create")
]);
} else if (datum2.restrictionID) {
turns = _oldTurns || [];
extraActions = [];
for (i3 = 0; i3 < turns.length; i3++) {
if (turns[i3].key !== datum2.key) {
extraActions.push(actionRestrictTurn(turns[i3], turns[i3].restrictionType));
}
}
_oldTurns = null;
actions = _intersection.actions.concat(extraActions, [
actionUnrestrictTurn(datum2),
_t("operations.restriction.annotation.delete")
]);
} else {
actions = _intersection.actions.concat([
actionRestrictTurn(datum2, restrictionType),
_t("operations.restriction.annotation.create")
]);
}
context.perform.apply(context, actions);
var s = surface.selectAll("." + datum2.key);
datum2 = s.empty() ? null : s.datum();
updateHints(datum2);
} else {
_fromWayID = null;
_oldTurns = null;
redraw();
}
}
function mouseover(d3_event) {
var datum2 = d3_event.target.__data__;
updateHints(datum2);
}
_lastXPos = _lastXPos || sdims[0];
function redraw(minChange) {
var xPos = -1;
if (minChange) {
xPos = utilGetDimensions(context.container().select(".sidebar"))[0];
}
if (!minChange || minChange && Math.abs(xPos - _lastXPos) >= minChange) {
if (context.hasEntity(_vertexID)) {
_lastXPos = xPos;
_container.call(renderViewer);
}
}
}
function highlightPathsFrom(wayID) {
surface.selectAll(".related").classed("related", false).classed("allow", false).classed("restrict", false).classed("only", false);
surface.selectAll("." + wayID).classed("related", true);
if (wayID) {
var turns = _intersection.turns(wayID, _maxViaWay);
for (var i3 = 0; i3 < turns.length; i3++) {
var turn = turns[i3];
var ids = [turn.to.way];
var klass = turn.no ? "restrict" : turn.only ? "only" : "allow";
if (turn.only || turns.length === 1) {
if (turn.via.ways) {
ids = ids.concat(turn.via.ways);
}
} else if (turn.to.way === wayID) {
continue;
}
surface.selectAll(utilEntitySelector(ids)).classed("related", true).classed("allow", klass === "allow").classed("restrict", klass === "restrict").classed("only", klass === "only");
}
}
}
function updateHints(datum2) {
var help = _container.selectAll(".restriction-help").html("");
var placeholders = {};
["from", "via", "to"].forEach(function(k) {
placeholders[k] = { html: '' + _t("restriction.help." + k) + "" };
});
var entity = datum2 && datum2.properties && datum2.properties.entity;
if (entity) {
datum2 = entity;
}
if (_fromWayID) {
way = vgraph.entity(_fromWayID);
surface.selectAll("." + _fromWayID).classed("selected", true).classed("related", true);
}
if (datum2 instanceof osmWay && datum2.__from) {
way = datum2;
highlightPathsFrom(_fromWayID ? null : way.id);
surface.selectAll("." + way.id).classed("related", true);
var clickSelect = !_fromWayID || _fromWayID !== way.id;
help.append("div").html(_t.html("restriction.help." + (clickSelect ? "select_from_name" : "from_name"), {
from: placeholders.from,
fromName: displayName(way.id, vgraph)
}));
} else if (datum2 instanceof osmTurn) {
var restrictionType = osmInferRestriction(vgraph, datum2, projection2);
var turnType = restrictionType.replace(/^(only|no)\_/, "");
var indirect = datum2.direct === false ? _t.html("restriction.help.indirect") : "";
var klass, turnText, nextText;
if (datum2.no) {
klass = "restrict";
turnText = _t.html("restriction.help.turn.no_" + turnType, { indirect: { html: indirect } });
nextText = _t.html("restriction.help.turn.only_" + turnType, { indirect: "" });
} else if (datum2.only) {
klass = "only";
turnText = _t.html("restriction.help.turn.only_" + turnType, { indirect: { html: indirect } });
nextText = _t.html("restriction.help.turn.allowed_" + turnType, { indirect: "" });
} else {
klass = "allow";
turnText = _t.html("restriction.help.turn.allowed_" + turnType, { indirect: { html: indirect } });
nextText = _t.html("restriction.help.turn.no_" + turnType, { indirect: "" });
}
help.append("div").attr("class", "qualifier " + klass).html(turnText);
help.append("div").html(_t.html("restriction.help.from_name_to_name", {
from: placeholders.from,
fromName: displayName(datum2.from.way, vgraph),
to: placeholders.to,
toName: displayName(datum2.to.way, vgraph)
}));
if (datum2.via.ways && datum2.via.ways.length) {
var names = [];
for (var i3 = 0; i3 < datum2.via.ways.length; i3++) {
var prev = names[names.length - 1];
var curr = displayName(datum2.via.ways[i3], vgraph);
if (!prev || curr !== prev) {
names.push(curr);
}
}
help.append("div").html(_t.html("restriction.help.via_names", {
via: placeholders.via,
viaNames: names.join(", ")
}));
}
if (!indirect) {
help.append("div").html(_t.html("restriction.help.toggle", { turn: { html: nextText.trim() } }));
}
highlightPathsFrom(null);
var alongIDs = datum2.path.slice();
surface.selectAll(utilEntitySelector(alongIDs)).classed("related", true).classed("allow", klass === "allow").classed("restrict", klass === "restrict").classed("only", klass === "only");
} else {
highlightPathsFrom(null);
if (_fromWayID) {
help.append("div").html(_t.html("restriction.help.from_name", {
from: placeholders.from,
fromName: displayName(_fromWayID, vgraph)
}));
} else {
help.append("div").html(_t.html("restriction.help.select_from", {
from: placeholders.from
}));
}
}
}
}
function displayMaxDistance(maxDist) {
return (selection2) => {
var isImperial = !_mainLocalizer.usesMetric();
var opts;
if (isImperial) {
var distToFeet = {
20: 70,
25: 85,
30: 100,
35: 115,
40: 130,
45: 145,
50: 160
}[maxDist];
opts = { distance: _t("units.feet", { quantity: distToFeet }) };
} else {
opts = { distance: _t("units.meters", { quantity: maxDist }) };
}
return selection2.html("").call(_t.append("restriction.controls.distance_up_to", opts));
};
}
function displayMaxVia(maxVia) {
return (selection2) => {
selection2 = selection2.html("");
return maxVia === 0 ? selection2.call(_t.append("restriction.controls.via_node_only")) : maxVia === 1 ? selection2.call(_t.append("restriction.controls.via_up_to_one")) : selection2.call(_t.append("restriction.controls.via_up_to_two"));
};
}
function displayName(entityID, graph) {
var entity = graph.entity(entityID);
var name2 = utilDisplayName(entity) || "";
var matched = _mainPresetIndex.match(entity, graph);
var type3 = matched && matched.name() || utilDisplayType(entity.id);
return name2 || type3;
}
restrictions.entityIDs = function(val) {
_intersection = null;
_fromWayID = null;
_oldTurns = null;
_vertexID = val[0];
};
restrictions.tags = function() {
};
restrictions.focus = function() {
};
restrictions.off = function(selection2) {
if (!_initialized2)
return;
selection2.selectAll(".surface").call(breathe.off).on("click.restrictions", null).on("mouseover.restrictions", null);
select_default2(window).on("resize.restrictions", null);
};
return utilRebind(restrictions, dispatch10, "on");
}
uiFieldRestrictions.supportsMultiselection = false;
// modules/ui/fields/textarea.js
function uiFieldTextarea(field, context) {
var dispatch10 = dispatch_default("change");
var input = select_default2(null);
var _tags;
function textarea(selection2) {
var wrap2 = selection2.selectAll(".form-field-input-wrap").data([0]);
wrap2 = wrap2.enter().append("div").attr("class", "form-field-input-wrap form-field-input-" + field.type).merge(wrap2);
input = wrap2.selectAll("textarea").data([0]);
input = input.enter().append("textarea").attr("id", field.domId).call(utilNoAuto).on("input", change(true)).on("blur", change()).on("change", change()).merge(input);
}
function change(onInput) {
return function() {
var val = utilGetSetValue(input);
if (!onInput)
val = context.cleanTagValue(val);
if (!val && Array.isArray(_tags[field.key]))
return;
var t = {};
t[field.key] = val || void 0;
dispatch10.call("change", this, t, onInput);
};
}
textarea.tags = function(tags) {
_tags = tags;
var isMixed = Array.isArray(tags[field.key]);
utilGetSetValue(input, !isMixed && tags[field.key] ? tags[field.key] : "").attr("title", isMixed ? tags[field.key].filter(Boolean).join("\n") : void 0).attr("placeholder", isMixed ? _t("inspector.multiple_values") : field.placeholder() || _t("inspector.unknown")).classed("mixed", isMixed);
};
textarea.focus = function() {
input.node().focus();
};
return utilRebind(textarea, dispatch10, "on");
}
// modules/ui/fields/wikidata.js
function uiFieldWikidata(field, context) {
var wikidata = services.wikidata;
var dispatch10 = dispatch_default("change");
var _selection = select_default2(null);
var _searchInput = select_default2(null);
var _qid = null;
var _wikidataEntity = null;
var _wikiURL = "";
var _entityIDs = [];
var _wikipediaKey = field.keys && field.keys.find(function(key) {
return key.includes("wikipedia");
}), _hintKey = field.key === "wikidata" ? "name" : field.key.split(":")[0];
var combobox = uiCombobox(context, "combo-" + field.safeid).caseSensitive(true).minItems(1);
function wiki(selection2) {
_selection = selection2;
var wrap2 = selection2.selectAll(".form-field-input-wrap").data([0]);
wrap2 = wrap2.enter().append("div").attr("class", "form-field-input-wrap form-field-input-" + field.type).merge(wrap2);
var list = wrap2.selectAll("ul").data([0]);
list = list.enter().append("ul").attr("class", "rows").merge(list);
var searchRow = list.selectAll("li.wikidata-search").data([0]);
var searchRowEnter = searchRow.enter().append("li").attr("class", "wikidata-search");
searchRowEnter.append("input").attr("type", "text").attr("id", field.domId).style("flex", "1").call(utilNoAuto).on("focus", function() {
var node = select_default2(this).node();
node.setSelectionRange(0, node.value.length);
}).on("blur", function() {
setLabelForEntity();
}).call(combobox.fetcher(fetchWikidataItems));
combobox.on("accept", function(d) {
if (d) {
_qid = d.id;
change();
}
}).on("cancel", function() {
setLabelForEntity();
});
searchRowEnter.append("button").attr("class", "form-field-button wiki-link").attr("title", _t("icons.view_on", { domain: "wikidata.org" })).call(svgIcon("#iD-icon-out-link")).on("click", function(d3_event) {
d3_event.preventDefault();
if (_wikiURL)
window.open(_wikiURL, "_blank");
});
searchRow = searchRow.merge(searchRowEnter);
_searchInput = searchRow.select("input");
var wikidataProperties = ["description", "identifier"];
var items = list.selectAll("li.labeled-input").data(wikidataProperties);
var enter = items.enter().append("li").attr("class", function(d) {
return "labeled-input preset-wikidata-" + d;
});
enter.append("span").attr("class", "label").html(function(d) {
return _t.html("wikidata." + d);
});
enter.append("input").attr("type", "text").call(utilNoAuto).classed("disabled", "true").attr("readonly", "true");
enter.append("button").attr("class", "form-field-button").attr("title", _t("icons.copy")).call(svgIcon("#iD-operation-copy")).on("click", function(d3_event) {
d3_event.preventDefault();
select_default2(this.parentNode).select("input").node().select();
document.execCommand("copy");
});
}
function fetchWikidataItems(q, callback) {
if (!q && _hintKey) {
for (var i2 in _entityIDs) {
var entity = context.hasEntity(_entityIDs[i2]);
if (entity.tags[_hintKey]) {
q = entity.tags[_hintKey];
break;
}
}
}
wikidata.itemsForSearchQuery(q, function(err, data) {
if (err)
return;
for (var i3 in data) {
data[i3].value = data[i3].label + " (" + data[i3].id + ")";
data[i3].title = data[i3].description;
}
if (callback)
callback(data);
});
}
function change() {
var syncTags = {};
syncTags[field.key] = _qid;
dispatch10.call("change", this, syncTags);
var initGraph = context.graph();
var initEntityIDs = _entityIDs;
wikidata.entityByQID(_qid, function(err, entity) {
if (err)
return;
if (context.graph() !== initGraph)
return;
if (!entity.sitelinks)
return;
var langs = wikidata.languagesToQuery();
["labels", "descriptions"].forEach(function(key) {
if (!entity[key])
return;
var valueLangs = Object.keys(entity[key]);
if (valueLangs.length === 0)
return;
var valueLang = valueLangs[0];
if (langs.indexOf(valueLang) === -1) {
langs.push(valueLang);
}
});
var newWikipediaValue;
if (_wikipediaKey) {
var foundPreferred;
for (var i2 in langs) {
var lang = langs[i2];
var siteID = lang.replace("-", "_") + "wiki";
if (entity.sitelinks[siteID]) {
foundPreferred = true;
newWikipediaValue = lang + ":" + entity.sitelinks[siteID].title;
break;
}
}
if (!foundPreferred) {
var wikiSiteKeys = Object.keys(entity.sitelinks).filter(function(site) {
return site.endsWith("wiki");
});
if (wikiSiteKeys.length === 0) {
newWikipediaValue = null;
} else {
var wikiLang = wikiSiteKeys[0].slice(0, -4).replace("_", "-");
var wikiTitle = entity.sitelinks[wikiSiteKeys[0]].title;
newWikipediaValue = wikiLang + ":" + wikiTitle;
}
}
}
if (newWikipediaValue) {
newWikipediaValue = context.cleanTagValue(newWikipediaValue);
}
if (typeof newWikipediaValue === "undefined")
return;
var actions = initEntityIDs.map(function(entityID) {
var entity2 = context.hasEntity(entityID);
if (!entity2)
return null;
var currTags = Object.assign({}, entity2.tags);
if (newWikipediaValue === null) {
if (!currTags[_wikipediaKey])
return null;
delete currTags[_wikipediaKey];
} else {
currTags[_wikipediaKey] = newWikipediaValue;
}
return actionChangeTags(entityID, currTags);
}).filter(Boolean);
if (!actions.length)
return;
context.overwrite(function actionUpdateWikipediaTags(graph) {
actions.forEach(function(action) {
graph = action(graph);
});
return graph;
}, context.history().undoAnnotation());
});
}
function setLabelForEntity() {
var label = "";
if (_wikidataEntity) {
label = entityPropertyForDisplay(_wikidataEntity, "labels");
if (label.length === 0) {
label = _wikidataEntity.id.toString();
}
}
utilGetSetValue(_searchInput, label);
}
wiki.tags = function(tags) {
var isMixed = Array.isArray(tags[field.key]);
_searchInput.attr("title", isMixed ? tags[field.key].filter(Boolean).join("\n") : null).attr("placeholder", isMixed ? _t("inspector.multiple_values") : "").classed("mixed", isMixed);
_qid = typeof tags[field.key] === "string" && tags[field.key] || "";
if (!/^Q[0-9]*$/.test(_qid)) {
unrecognized();
return;
}
_wikiURL = "https://wikidata.org/wiki/" + _qid;
wikidata.entityByQID(_qid, function(err, entity) {
if (err) {
unrecognized();
return;
}
_wikidataEntity = entity;
setLabelForEntity();
var description2 = entityPropertyForDisplay(entity, "descriptions");
_selection.select("button.wiki-link").classed("disabled", false);
_selection.select(".preset-wikidata-description").style("display", function() {
return description2.length > 0 ? "flex" : "none";
}).select("input").attr("value", description2);
_selection.select(".preset-wikidata-identifier").style("display", function() {
return entity.id ? "flex" : "none";
}).select("input").attr("value", entity.id);
});
function unrecognized() {
_wikidataEntity = null;
setLabelForEntity();
_selection.select(".preset-wikidata-description").style("display", "none");
_selection.select(".preset-wikidata-identifier").style("display", "none");
_selection.select("button.wiki-link").classed("disabled", true);
if (_qid && _qid !== "") {
_wikiURL = "https://wikidata.org/wiki/Special:Search?search=" + _qid;
} else {
_wikiURL = "";
}
}
};
function entityPropertyForDisplay(wikidataEntity, propKey) {
if (!wikidataEntity[propKey])
return "";
var propObj = wikidataEntity[propKey];
var langKeys = Object.keys(propObj);
if (langKeys.length === 0)
return "";
var langs = wikidata.languagesToQuery();
for (var i2 in langs) {
var lang = langs[i2];
var valueObj = propObj[lang];
if (valueObj && valueObj.value && valueObj.value.length > 0)
return valueObj.value;
}
return propObj[langKeys[0]].value;
}
wiki.entityIDs = function(val) {
if (!arguments.length)
return _entityIDs;
_entityIDs = val;
return wiki;
};
wiki.focus = function() {
_searchInput.node().focus();
};
return utilRebind(wiki, dispatch10, "on");
}
// modules/ui/fields/wikipedia.js
function uiFieldWikipedia(field, context) {
const dispatch10 = dispatch_default("change");
const wikipedia = services.wikipedia;
const wikidata = services.wikidata;
let _langInput = select_default2(null);
let _titleInput = select_default2(null);
let _wikiURL = "";
let _entityIDs;
let _tags;
let _dataWikipedia = [];
_mainFileFetcher.get("wmf_sitematrix").then((d) => {
_dataWikipedia = d;
if (_tags)
updateForTags(_tags);
}).catch(() => {
});
const langCombo = uiCombobox(context, "wikipedia-lang").fetcher((value, callback) => {
const v = value.toLowerCase();
callback(_dataWikipedia.filter((d) => {
return d[0].toLowerCase().indexOf(v) >= 0 || d[1].toLowerCase().indexOf(v) >= 0 || d[2].toLowerCase().indexOf(v) >= 0;
}).map((d) => ({ value: d[1] })));
});
const titleCombo = uiCombobox(context, "wikipedia-title").fetcher((value, callback) => {
if (!value) {
value = "";
for (let i2 in _entityIDs) {
let entity = context.hasEntity(_entityIDs[i2]);
if (entity.tags.name) {
value = entity.tags.name;
break;
}
}
}
const searchfn = value.length > 7 ? wikipedia.search : wikipedia.suggestions;
searchfn(language()[2], value, (query, data) => {
callback(data.map((d) => ({ value: d })));
});
});
function wiki(selection2) {
let wrap2 = selection2.selectAll(".form-field-input-wrap").data([0]);
wrap2 = wrap2.enter().append("div").attr("class", `form-field-input-wrap form-field-input-${field.type}`).merge(wrap2);
let langContainer = wrap2.selectAll(".wiki-lang-container").data([0]);
langContainer = langContainer.enter().append("div").attr("class", "wiki-lang-container").merge(langContainer);
_langInput = langContainer.selectAll("input.wiki-lang").data([0]);
_langInput = _langInput.enter().append("input").attr("type", "text").attr("class", "wiki-lang").attr("placeholder", _t("translate.localized_translation_language")).call(utilNoAuto).call(langCombo).merge(_langInput);
_langInput.on("blur", changeLang).on("change", changeLang);
let titleContainer = wrap2.selectAll(".wiki-title-container").data([0]);
titleContainer = titleContainer.enter().append("div").attr("class", "wiki-title-container").merge(titleContainer);
_titleInput = titleContainer.selectAll("input.wiki-title").data([0]);
_titleInput = _titleInput.enter().append("input").attr("type", "text").attr("class", "wiki-title").attr("id", field.domId).call(utilNoAuto).call(titleCombo).merge(_titleInput);
_titleInput.on("blur", function() {
change(true);
}).on("change", function() {
change(false);
});
let link2 = titleContainer.selectAll(".wiki-link").data([0]);
link2 = link2.enter().append("button").attr("class", "form-field-button wiki-link").attr("title", _t("icons.view_on", { domain: "wikipedia.org" })).call(svgIcon("#iD-icon-out-link")).merge(link2);
link2.on("click", (d3_event) => {
d3_event.preventDefault();
if (_wikiURL)
window.open(_wikiURL, "_blank");
});
}
function defaultLanguageInfo(skipEnglishFallback) {
const langCode = _mainLocalizer.languageCode().toLowerCase();
for (let i2 in _dataWikipedia) {
let d = _dataWikipedia[i2];
if (d[2] === langCode)
return d;
}
return skipEnglishFallback ? ["", "", ""] : ["English", "English", "en"];
}
function language(skipEnglishFallback) {
const value = utilGetSetValue(_langInput).toLowerCase();
for (let i2 in _dataWikipedia) {
let d = _dataWikipedia[i2];
if (d[0].toLowerCase() === value || d[1].toLowerCase() === value || d[2] === value)
return d;
}
return defaultLanguageInfo(skipEnglishFallback);
}
function changeLang() {
utilGetSetValue(_langInput, language()[1]);
change(true);
}
function change(skipWikidata) {
let value = utilGetSetValue(_titleInput);
const m = value.match(/https?:\/\/([-a-z]+)\.wikipedia\.org\/(?:wiki|\1-[-a-z]+)\/([^#]+)(?:#(.+))?/);
const langInfo = m && _dataWikipedia.find((d) => m[1] === d[2]);
let syncTags = {};
if (langInfo) {
const nativeLangName = langInfo[1];
value = decodeURIComponent(m[2]).replace(/_/g, " ");
if (m[3]) {
let anchor;
anchor = decodeURIComponent(m[3]);
value += "#" + anchor.replace(/_/g, " ");
}
value = value.slice(0, 1).toUpperCase() + value.slice(1);
utilGetSetValue(_langInput, nativeLangName);
utilGetSetValue(_titleInput, value);
}
if (value) {
syncTags.wikipedia = context.cleanTagValue(language()[2] + ":" + value);
} else {
syncTags.wikipedia = void 0;
}
dispatch10.call("change", this, syncTags);
if (skipWikidata || !value || !language()[2])
return;
const initGraph = context.graph();
const initEntityIDs = _entityIDs;
wikidata.itemsByTitle(language()[2], value, (err, data) => {
if (err || !data || !Object.keys(data).length)
return;
if (context.graph() !== initGraph)
return;
const qids = Object.keys(data);
const value2 = qids && qids.find((id2) => id2.match(/^Q\d+$/));
let actions = initEntityIDs.map((entityID) => {
let entity = context.entity(entityID).tags;
let currTags = Object.assign({}, entity);
if (currTags.wikidata !== value2) {
currTags.wikidata = value2;
return actionChangeTags(entityID, currTags);
}
return null;
}).filter(Boolean);
if (!actions.length)
return;
context.overwrite(function actionUpdateWikidataTags(graph) {
actions.forEach(function(action) {
graph = action(graph);
});
return graph;
}, context.history().undoAnnotation());
});
}
wiki.tags = (tags) => {
_tags = tags;
updateForTags(tags);
};
function updateForTags(tags) {
const value = typeof tags[field.key] === "string" ? tags[field.key] : "";
const m = value.match(/([^:]+):([^#]+)(?:#(.+))?/);
const tagLang = m && m[1];
const tagArticleTitle = m && m[2];
let anchor = m && m[3];
const tagLangInfo = tagLang && _dataWikipedia.find((d) => tagLang === d[2]);
if (tagLangInfo) {
const nativeLangName = tagLangInfo[1];
utilGetSetValue(_langInput, nativeLangName);
utilGetSetValue(_titleInput, tagArticleTitle + (anchor ? "#" + anchor : ""));
if (anchor) {
try {
anchor = encodeURIComponent(anchor.replace(/ /g, "_")).replace(/%/g, ".");
} catch (e) {
anchor = anchor.replace(/ /g, "_");
}
}
_wikiURL = "https://" + tagLang + ".wikipedia.org/wiki/" + tagArticleTitle.replace(/ /g, "_") + (anchor ? "#" + anchor : "");
} else {
utilGetSetValue(_titleInput, value);
if (value && value !== "") {
utilGetSetValue(_langInput, "");
const defaultLangInfo = defaultLanguageInfo();
_wikiURL = `https://${defaultLangInfo[2]}.wikipedia.org/w/index.php?fulltext=1&search=${value}`;
} else {
const shownOrDefaultLangInfo = language(true);
utilGetSetValue(_langInput, shownOrDefaultLangInfo[1]);
_wikiURL = "";
}
}
}
wiki.entityIDs = (val) => {
if (!arguments.length)
return _entityIDs;
_entityIDs = val;
return wiki;
};
wiki.focus = () => {
_titleInput.node().focus();
};
return utilRebind(wiki, dispatch10, "on");
}
uiFieldWikipedia.supportsMultiselection = false;
// modules/ui/fields/index.js
var uiFields = {
access: uiFieldAccess,
address: uiFieldAddress,
check: uiFieldCheck,
combo: uiFieldCombo,
cycleway: uiFieldCycleway,
defaultCheck: uiFieldCheck,
email: uiFieldText,
identifier: uiFieldText,
lanes: uiFieldLanes,
localized: uiFieldLocalized,
roadheight: uiFieldRoadheight,
roadspeed: uiFieldRoadspeed,
manyCombo: uiFieldCombo,
multiCombo: uiFieldCombo,
networkCombo: uiFieldCombo,
number: uiFieldText,
onewayCheck: uiFieldCheck,
radio: uiFieldRadio,
restrictions: uiFieldRestrictions,
semiCombo: uiFieldCombo,
structureRadio: uiFieldRadio,
tel: uiFieldText,
text: uiFieldText,
textarea: uiFieldTextarea,
typeCombo: uiFieldCombo,
url: uiFieldText,
wikidata: uiFieldWikidata,
wikipedia: uiFieldWikipedia
};
// modules/ui/field.js
function uiField(context, presetField2, entityIDs, options2) {
options2 = Object.assign({
show: true,
wrap: true,
remove: true,
revert: true,
info: true
}, options2);
var dispatch10 = dispatch_default("change", "revert");
var field = Object.assign({}, presetField2);
field.domId = utilUniqueDomId("form-field-" + field.safeid);
var _show = options2.show;
var _state = "";
var _tags = {};
var _entityExtent;
if (entityIDs && entityIDs.length) {
_entityExtent = entityIDs.reduce(function(extent, entityID) {
var entity = context.graph().entity(entityID);
return extent.extend(entity.extent(context.graph()));
}, geoExtent());
}
var _locked = false;
var _lockedTip = uiTooltip().title(_t.html("inspector.lock.suggestion", { label: field.label })).placement("bottom");
field.keys = field.keys || [field.key];
if (_show && !field.impl) {
createField();
}
function createField() {
field.impl = uiFields[field.type](field, context).on("change", function(t, onInput) {
dispatch10.call("change", field, t, onInput);
});
if (entityIDs) {
field.entityIDs = entityIDs;
if (field.impl.entityIDs) {
field.impl.entityIDs(entityIDs);
}
}
}
function isModified() {
if (!entityIDs || !entityIDs.length)
return false;
return entityIDs.some(function(entityID) {
var original = context.graph().base().entities[entityID];
var latest = context.graph().entity(entityID);
return field.keys.some(function(key) {
return original ? latest.tags[key] !== original.tags[key] : latest.tags[key];
});
});
}
function tagsContainFieldKey() {
return field.keys.some(function(key) {
if (field.type === "multiCombo") {
for (var tagKey in _tags) {
if (tagKey.indexOf(key) === 0) {
return true;
}
}
return false;
}
return _tags[key] !== void 0;
});
}
function revert(d3_event, d) {
d3_event.stopPropagation();
d3_event.preventDefault();
if (!entityIDs || _locked)
return;
dispatch10.call("revert", d, d.keys);
}
function remove2(d3_event, d) {
d3_event.stopPropagation();
d3_event.preventDefault();
if (_locked)
return;
var t = {};
d.keys.forEach(function(key) {
t[key] = void 0;
});
dispatch10.call("change", d, t);
}
field.render = function(selection2) {
var container = selection2.selectAll(".form-field").data([field]);
var enter = container.enter().append("div").attr("class", function(d) {
return "form-field form-field-" + d.safeid;
}).classed("nowrap", !options2.wrap);
if (options2.wrap) {
var labelEnter = enter.append("label").attr("class", "field-label").attr("for", function(d) {
return d.domId;
});
var textEnter = labelEnter.append("span").attr("class", "label-text");
textEnter.append("span").attr("class", "label-textvalue").html(function(d) {
return d.label();
});
textEnter.append("span").attr("class", "label-textannotation");
if (options2.remove) {
labelEnter.append("button").attr("class", "remove-icon").attr("title", _t("icons.remove")).call(svgIcon("#iD-operation-delete"));
}
if (options2.revert) {
labelEnter.append("button").attr("class", "modified-icon").attr("title", _t("icons.undo")).call(svgIcon(_mainLocalizer.textDirection() === "rtl" ? "#iD-icon-redo" : "#iD-icon-undo"));
}
}
container = container.merge(enter);
container.select(".field-label > .remove-icon").on("click", remove2);
container.select(".field-label > .modified-icon").on("click", revert);
container.each(function(d) {
var selection3 = select_default2(this);
if (!d.impl) {
createField();
}
var reference, help;
if (options2.wrap && field.type === "restrictions") {
help = uiFieldHelp(context, "restrictions");
}
if (options2.wrap && options2.info) {
var referenceKey = d.key || "";
if (d.type === "multiCombo") {
referenceKey = referenceKey.replace(/:$/, "");
}
reference = uiTagReference(d.reference || { key: referenceKey }, context);
if (_state === "hover") {
reference.showing(false);
}
}
selection3.call(d.impl);
if (help) {
selection3.call(help.body).select(".field-label").call(help.button);
}
if (reference) {
selection3.call(reference.body).select(".field-label").call(reference.button);
}
d.impl.tags(_tags);
});
container.classed("locked", _locked).classed("modified", isModified()).classed("present", tagsContainFieldKey());
var annotation = container.selectAll(".field-label .label-textannotation");
var icon2 = annotation.selectAll(".icon").data(_locked ? [0] : []);
icon2.exit().remove();
icon2.enter().append("svg").attr("class", "icon").append("use").attr("xlink:href", "#fas-lock");
container.call(_locked ? _lockedTip : _lockedTip.destroy);
};
field.state = function(val) {
if (!arguments.length)
return _state;
_state = val;
return field;
};
field.tags = function(val) {
if (!arguments.length)
return _tags;
_tags = val;
if (tagsContainFieldKey() && !_show) {
_show = true;
if (!field.impl) {
createField();
}
}
return field;
};
field.locked = function(val) {
if (!arguments.length)
return _locked;
_locked = val;
return field;
};
field.show = function() {
_show = true;
if (!field.impl) {
createField();
}
if (field.default && field.key && _tags[field.key] !== field.default) {
var t = {};
t[field.key] = field.default;
dispatch10.call("change", this, t);
}
};
field.isShown = function() {
return _show;
};
field.isAllowed = function() {
if (entityIDs && entityIDs.length > 1 && uiFields[field.type].supportsMultiselection === false)
return false;
if (field.geometry && !entityIDs.every(function(entityID) {
return field.matchGeometry(context.graph().geometry(entityID));
}))
return false;
if (entityIDs && _entityExtent && field.locationSetID) {
var validLocations = _mainLocations.locationsAt(_entityExtent.center());
if (!validLocations[field.locationSetID])
return false;
}
var prerequisiteTag = field.prerequisiteTag;
if (entityIDs && !tagsContainFieldKey() && prerequisiteTag) {
if (!entityIDs.every(function(entityID) {
var entity = context.graph().entity(entityID);
if (prerequisiteTag.key) {
var value = entity.tags[prerequisiteTag.key];
if (!value)
return false;
if (prerequisiteTag.valueNot) {
return prerequisiteTag.valueNot !== value;
}
if (prerequisiteTag.value) {
return prerequisiteTag.value === value;
}
} else if (prerequisiteTag.keyNot) {
if (entity.tags[prerequisiteTag.keyNot])
return false;
}
return true;
}))
return false;
}
return true;
};
field.focus = function() {
if (field.impl) {
field.impl.focus();
}
};
return utilRebind(field, dispatch10, "on");
}
// modules/ui/form_fields.js
function uiFormFields(context) {
var moreCombo = uiCombobox(context, "more-fields").minItems(1);
var _fieldsArr = [];
var _lastPlaceholder = "";
var _state = "";
var _klass = "";
function formFields(selection2) {
var allowedFields = _fieldsArr.filter(function(field) {
return field.isAllowed();
});
var shown = allowedFields.filter(function(field) {
return field.isShown();
});
var notShown = allowedFields.filter(function(field) {
return !field.isShown();
});
var container = selection2.selectAll(".form-fields-container").data([0]);
container = container.enter().append("div").attr("class", "form-fields-container " + (_klass || "")).merge(container);
var fields = container.selectAll(".wrap-form-field").data(shown, function(d) {
return d.id + (d.entityIDs ? d.entityIDs.join() : "");
});
fields.exit().remove();
var enter = fields.enter().append("div").attr("class", function(d) {
return "wrap-form-field wrap-form-field-" + d.safeid;
});
fields = fields.merge(enter);
fields.order().each(function(d) {
select_default2(this).call(d.render);
});
var titles = [];
var moreFields = notShown.map(function(field) {
var title = field.title();
titles.push(title);
var terms = field.terms();
if (field.key)
terms.push(field.key);
if (field.keys)
terms = terms.concat(field.keys);
return {
display: field.label(),
value: title,
title,
field,
terms
};
});
var placeholder = titles.slice(0, 3).join(", ") + (titles.length > 3 ? "\u2026" : "");
var more = selection2.selectAll(".more-fields").data(_state === "hover" || moreFields.length === 0 ? [] : [0]);
more.exit().remove();
var moreEnter = more.enter().append("div").attr("class", "more-fields").append("label");
moreEnter.append("span").call(_t.append("inspector.add_fields"));
more = moreEnter.merge(more);
var input = more.selectAll(".value").data([0]);
input.exit().remove();
input = input.enter().append("input").attr("class", "value").attr("type", "text").attr("placeholder", placeholder).call(utilNoAuto).merge(input);
input.call(utilGetSetValue, "").call(moreCombo.data(moreFields).on("accept", function(d) {
if (!d)
return;
var field = d.field;
field.show();
selection2.call(formFields);
field.focus();
}));
if (_lastPlaceholder !== placeholder) {
input.attr("placeholder", placeholder);
_lastPlaceholder = placeholder;
}
}
formFields.fieldsArr = function(val) {
if (!arguments.length)
return _fieldsArr;
_fieldsArr = val || [];
return formFields;
};
formFields.state = function(val) {
if (!arguments.length)
return _state;
_state = val;
return formFields;
};
formFields.klass = function(val) {
if (!arguments.length)
return _klass;
_klass = val;
return formFields;
};
return formFields;
}
// modules/ui/changeset_editor.js
function uiChangesetEditor(context) {
var dispatch10 = dispatch_default("change");
var formFields = uiFormFields(context);
var commentCombo = uiCombobox(context, "comment").caseSensitive(true);
var _fieldsArr;
var _tags;
var _changesetID;
function changesetEditor(selection2) {
render(selection2);
}
function render(selection2) {
var initial = false;
if (!_fieldsArr) {
initial = true;
var presets = _mainPresetIndex;
_fieldsArr = [
uiField(context, presets.field("comment"), null, { show: true, revert: false }),
uiField(context, presets.field("source"), null, { show: false, revert: false }),
uiField(context, presets.field("hashtags"), null, { show: false, revert: false })
];
_fieldsArr.forEach(function(field) {
field.on("change", function(t, onInput) {
dispatch10.call("change", field, void 0, t, onInput);
});
});
}
_fieldsArr.forEach(function(field) {
field.tags(_tags);
});
selection2.call(formFields.fieldsArr(_fieldsArr));
if (initial) {
var commentField = selection2.select(".form-field-comment textarea");
var commentNode = commentField.node();
if (commentNode) {
commentNode.focus();
commentNode.select();
}
utilTriggerEvent(commentField, "blur");
var osm = context.connection();
if (osm) {
osm.userChangesets(function(err, changesets) {
if (err)
return;
var comments = changesets.map(function(changeset) {
var comment = changeset.tags.comment;
return comment ? { title: comment, value: comment } : null;
}).filter(Boolean);
commentField.call(commentCombo.data(utilArrayUniqBy(comments, "title")));
});
}
}
var hasGoogle = _tags.comment.match(/google/i);
var commentWarning = selection2.select(".form-field-comment").selectAll(".comment-warning").data(hasGoogle ? [0] : []);
commentWarning.exit().transition().duration(200).style("opacity", 0).remove();
var commentEnter = commentWarning.enter().insert("div", ".tag-reference-body").attr("class", "field-warning comment-warning").style("opacity", 0);
commentEnter.append("a").attr("target", "_blank").call(svgIcon("#iD-icon-alert", "inline")).attr("href", _t("commit.google_warning_link")).append("span").call(_t.append("commit.google_warning"));
commentEnter.transition().duration(200).style("opacity", 1);
}
changesetEditor.tags = function(_) {
if (!arguments.length)
return _tags;
_tags = _;
return changesetEditor;
};
changesetEditor.changesetID = function(_) {
if (!arguments.length)
return _changesetID;
if (_changesetID === _)
return changesetEditor;
_changesetID = _;
_fieldsArr = null;
return changesetEditor;
};
return utilRebind(changesetEditor, dispatch10, "on");
}
// modules/ui/commit.js
var import_fast_deep_equal9 = __toESM(require_fast_deep_equal());
// modules/util/jxon.js
var JXON = new function() {
var sValueProp = "keyValue", sAttributesProp = "keyAttributes", sAttrPref = "@", aCache = [], rIsNull = /^\s*$/, rIsBool = /^(?:true|false)$/i;
function parseText(sValue) {
if (rIsNull.test(sValue)) {
return null;
}
if (rIsBool.test(sValue)) {
return sValue.toLowerCase() === "true";
}
if (isFinite(sValue)) {
return parseFloat(sValue);
}
if (isFinite(Date.parse(sValue))) {
return new Date(sValue);
}
return sValue;
}
function EmptyTree() {
}
EmptyTree.prototype.toString = function() {
return "null";
};
EmptyTree.prototype.valueOf = function() {
return null;
};
function objectify(vValue) {
return vValue === null ? new EmptyTree() : vValue instanceof Object ? vValue : new vValue.constructor(vValue);
}
function createObjTree(oParentNode, nVerb, bFreeze, bNesteAttr) {
var nLevelStart = aCache.length, bChildren = oParentNode.hasChildNodes(), bAttributes = oParentNode.hasAttributes(), bHighVerb = Boolean(nVerb & 2);
var sProp, vContent, nLength = 0, sCollectedTxt = "", vResult = bHighVerb ? {} : true;
if (bChildren) {
for (var oNode, nItem = 0; nItem < oParentNode.childNodes.length; nItem++) {
oNode = oParentNode.childNodes.item(nItem);
if (oNode.nodeType === 4) {
sCollectedTxt += oNode.nodeValue;
} else if (oNode.nodeType === 3) {
sCollectedTxt += oNode.nodeValue.trim();
} else if (oNode.nodeType === 1 && !oNode.prefix) {
aCache.push(oNode);
}
}
}
var nLevelEnd = aCache.length, vBuiltVal = parseText(sCollectedTxt);
if (!bHighVerb && (bChildren || bAttributes)) {
vResult = nVerb === 0 ? objectify(vBuiltVal) : {};
}
for (var nElId = nLevelStart; nElId < nLevelEnd; nElId++) {
sProp = aCache[nElId].nodeName.toLowerCase();
vContent = createObjTree(aCache[nElId], nVerb, bFreeze, bNesteAttr);
if (vResult.hasOwnProperty(sProp)) {
if (vResult[sProp].constructor !== Array) {
vResult[sProp] = [vResult[sProp]];
}
vResult[sProp].push(vContent);
} else {
vResult[sProp] = vContent;
nLength++;
}
}
if (bAttributes) {
var nAttrLen = oParentNode.attributes.length, sAPrefix = bNesteAttr ? "" : sAttrPref, oAttrParent = bNesteAttr ? {} : vResult;
for (var oAttrib, nAttrib = 0; nAttrib < nAttrLen; nLength++, nAttrib++) {
oAttrib = oParentNode.attributes.item(nAttrib);
oAttrParent[sAPrefix + oAttrib.name.toLowerCase()] = parseText(oAttrib.value.trim());
}
if (bNesteAttr) {
if (bFreeze) {
Object.freeze(oAttrParent);
}
vResult[sAttributesProp] = oAttrParent;
nLength -= nAttrLen - 1;
}
}
if (nVerb === 3 || (nVerb === 2 || nVerb === 1 && nLength > 0) && sCollectedTxt) {
vResult[sValueProp] = vBuiltVal;
} else if (!bHighVerb && nLength === 0 && sCollectedTxt) {
vResult = vBuiltVal;
}
if (bFreeze && (bHighVerb || nLength > 0)) {
Object.freeze(vResult);
}
aCache.length = nLevelStart;
return vResult;
}
function loadObjTree(oXMLDoc, oParentEl, oParentObj) {
var vValue, oChild;
if (oParentObj instanceof String || oParentObj instanceof Number || oParentObj instanceof Boolean) {
oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toString()));
} else if (oParentObj.constructor === Date) {
oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toGMTString()));
}
for (var sName in oParentObj) {
vValue = oParentObj[sName];
if (isFinite(sName) || vValue instanceof Function) {
continue;
}
if (sName === sValueProp) {
if (vValue !== null && vValue !== true) {
oParentEl.appendChild(oXMLDoc.createTextNode(vValue.constructor === Date ? vValue.toGMTString() : String(vValue)));
}
} else if (sName === sAttributesProp) {
for (var sAttrib in vValue) {
oParentEl.setAttribute(sAttrib, vValue[sAttrib]);
}
} else if (sName.charAt(0) === sAttrPref) {
oParentEl.setAttribute(sName.slice(1), vValue);
} else if (vValue.constructor === Array) {
for (var nItem = 0; nItem < vValue.length; nItem++) {
oChild = oXMLDoc.createElement(sName);
loadObjTree(oXMLDoc, oChild, vValue[nItem]);
oParentEl.appendChild(oChild);
}
} else {
oChild = oXMLDoc.createElement(sName);
if (vValue instanceof Object) {
loadObjTree(oXMLDoc, oChild, vValue);
} else if (vValue !== null && vValue !== true) {
oChild.appendChild(oXMLDoc.createTextNode(vValue.toString()));
}
oParentEl.appendChild(oChild);
}
}
}
this.build = function(oXMLParent, nVerbosity, bFreeze, bNesteAttributes) {
var _nVerb = arguments.length > 1 && typeof nVerbosity === "number" ? nVerbosity & 3 : 1;
return createObjTree(oXMLParent, _nVerb, bFreeze || false, arguments.length > 3 ? bNesteAttributes : _nVerb === 3);
};
this.unbuild = function(oObjTree) {
var oNewDoc = document.implementation.createDocument("", "", null);
loadObjTree(oNewDoc, oNewDoc, oObjTree);
return oNewDoc;
};
this.stringify = function(oObjTree) {
return new XMLSerializer().serializeToString(JXON.unbuild(oObjTree));
};
}();
// modules/ui/sections/changes.js
function uiSectionChanges(context) {
var _discardTags = {};
_mainFileFetcher.get("discarded").then(function(d) {
_discardTags = d;
}).catch(function() {
});
var section = uiSection("changes-list", context).label(function() {
var history = context.history();
var summary = history.difference().summary();
return _t.html("inspector.title_count", { title: { html: _t.html("commit.changes") }, count: summary.length });
}).disclosureContent(renderDisclosureContent);
function renderDisclosureContent(selection2) {
var history = context.history();
var summary = history.difference().summary();
var container = selection2.selectAll(".commit-section").data([0]);
var containerEnter = container.enter().append("div").attr("class", "commit-section");
containerEnter.append("ul").attr("class", "changeset-list");
container = containerEnter.merge(container);
var items = container.select("ul").selectAll("li").data(summary);
var itemsEnter = items.enter().append("li").attr("class", "change-item");
var buttons = itemsEnter.append("button").on("mouseover", mouseover).on("mouseout", mouseout).on("click", click);
buttons.each(function(d) {
select_default2(this).call(svgIcon("#iD-icon-" + d.entity.geometry(d.graph), "pre-text " + d.changeType));
});
buttons.append("span").attr("class", "change-type").html(function(d) {
return _t.html("commit." + d.changeType) + " ";
});
buttons.append("strong").attr("class", "entity-type").text(function(d) {
var matched = _mainPresetIndex.match(d.entity, d.graph);
return matched && matched.name() || utilDisplayType(d.entity.id);
});
buttons.append("span").attr("class", "entity-name").text(function(d) {
var name2 = utilDisplayName(d.entity) || "", string = "";
if (name2 !== "") {
string += ":";
}
return string += " " + name2;
});
items = itemsEnter.merge(items);
var changeset = new osmChangeset().update({ id: void 0 });
var changes = history.changes(actionDiscardTags(history.difference(), _discardTags));
delete changeset.id;
var data = JXON.stringify(changeset.osmChangeJXON(changes));
var blob = new Blob([data], { type: "text/xml;charset=utf-8;" });
var fileName = "changes.osc";
var linkEnter = container.selectAll(".download-changes").data([0]).enter().append("a").attr("class", "download-changes");
linkEnter.attr("href", window.URL.createObjectURL(blob)).attr("download", fileName);
linkEnter.call(svgIcon("#iD-icon-load", "inline")).append("span").call(_t.append("commit.download_changes"));
function mouseover(d) {
if (d.entity) {
context.surface().selectAll(utilEntityOrMemberSelector([d.entity.id], context.graph())).classed("hover", true);
}
}
function mouseout() {
context.surface().selectAll(".hover").classed("hover", false);
}
function click(d3_event, change) {
if (change.changeType !== "deleted") {
var entity = change.entity;
context.map().zoomToEase(entity);
context.surface().selectAll(utilEntityOrMemberSelector([entity.id], context.graph())).classed("hover", true);
}
}
}
return section;
}
// modules/ui/commit_warnings.js
function uiCommitWarnings(context) {
function commitWarnings(selection2) {
var issuesBySeverity = context.validator().getIssuesBySeverity({ what: "edited", where: "all", includeDisabledRules: true });
for (var severity in issuesBySeverity) {
var issues = issuesBySeverity[severity];
if (severity !== "error") {
issues = issues.filter(function(issue) {
return issue.type !== "help_request";
});
}
var section = severity + "-section";
var issueItem = severity + "-item";
var container = selection2.selectAll("." + section).data(issues.length ? [0] : []);
container.exit().remove();
var containerEnter = container.enter().append("div").attr("class", "modal-section " + section + " fillL2");
containerEnter.append("h3").html(severity === "warning" ? _t.html("commit.warnings") : _t.html("commit.errors"));
containerEnter.append("ul").attr("class", "changeset-list");
container = containerEnter.merge(container);
var items = container.select("ul").selectAll("li").data(issues, function(d) {
return d.key;
});
items.exit().remove();
var itemsEnter = items.enter().append("li").attr("class", issueItem);
var buttons = itemsEnter.append("button").on("mouseover", function(d3_event, d) {
if (d.entityIds) {
context.surface().selectAll(utilEntityOrMemberSelector(d.entityIds, context.graph())).classed("hover", true);
}
}).on("mouseout", function() {
context.surface().selectAll(".hover").classed("hover", false);
}).on("click", function(d3_event, d) {
context.validator().focusIssue(d);
});
buttons.call(svgIcon("#iD-icon-alert", "pre-text"));
buttons.append("strong").attr("class", "issue-message");
buttons.filter(function(d) {
return d.tooltip;
}).call(uiTooltip().title(function(d) {
return d.tooltip;
}).placement("top"));
items = itemsEnter.merge(items);
items.selectAll(".issue-message").html(function(d) {
return d.message(context);
});
}
}
return commitWarnings;
}
// modules/ui/commit.js
var readOnlyTags = [
/^changesets_count$/,
/^created_by$/,
/^ideditor:/,
/^imagery_used$/,
/^host$/,
/^locale$/,
/^warnings:/,
/^resolved:/,
/^closed:note$/,
/^closed:keepright$/,
/^closed:improveosm:/,
/^closed:osmose:/
];
var hashtagRegex = /(#[^\u2000-\u206F\u2E00-\u2E7F\s\\'!"#$%()*,.\/:;<=>?@\[\]^`{|}~]+)/g;
function uiCommit(context) {
var dispatch10 = dispatch_default("cancel");
var _userDetails2;
var _selection;
var changesetEditor = uiChangesetEditor(context).on("change", changeTags);
var rawTagEditor = uiSectionRawTagEditor("changeset-tag-editor", context).on("change", changeTags).readOnlyTags(readOnlyTags);
var commitChanges = uiSectionChanges(context);
var commitWarnings = uiCommitWarnings(context);
function commit(selection2) {
_selection = selection2;
if (!context.changeset)
initChangeset();
loadDerivedChangesetTags();
selection2.call(render);
}
function initChangeset() {
var commentDate = +corePreferences("commentDate") || 0;
var currDate = Date.now();
var cutoff = 2 * 86400 * 1e3;
if (commentDate > currDate || currDate - commentDate > cutoff) {
corePreferences("comment", null);
corePreferences("hashtags", null);
corePreferences("source", null);
}
if (context.defaultChangesetComment()) {
corePreferences("comment", context.defaultChangesetComment());
corePreferences("commentDate", Date.now());
}
if (context.defaultChangesetSource()) {
corePreferences("source", context.defaultChangesetSource());
corePreferences("commentDate", Date.now());
}
if (context.defaultChangesetHashtags()) {
corePreferences("hashtags", context.defaultChangesetHashtags());
corePreferences("commentDate", Date.now());
}
var detected = utilDetect();
var tags = {
comment: corePreferences("comment") || "",
created_by: context.cleanTagValue("iD " + context.version),
host: context.cleanTagValue(detected.host),
locale: context.cleanTagValue(_mainLocalizer.localeCode())
};
findHashtags(tags, true);
var hashtags = corePreferences("hashtags");
if (hashtags) {
tags.hashtags = hashtags;
}
var source = corePreferences("source");
if (source) {
tags.source = source;
}
var photoOverlaysUsed = context.history().photoOverlaysUsed();
if (photoOverlaysUsed.length) {
var sources = (tags.source || "").split(";");
if (sources.indexOf("streetlevel imagery") === -1) {
sources.push("streetlevel imagery");
}
photoOverlaysUsed.forEach(function(photoOverlay) {
if (sources.indexOf(photoOverlay) === -1) {
sources.push(photoOverlay);
}
});
tags.source = context.cleanTagValue(sources.join(";"));
}
context.changeset = new osmChangeset({ tags });
}
function loadDerivedChangesetTags() {
var osm = context.connection();
if (!osm)
return;
var tags = Object.assign({}, context.changeset.tags);
var imageryUsed = context.cleanTagValue(context.history().imageryUsed().join(";"));
tags.imagery_used = imageryUsed || "None";
var osmClosed = osm.getClosedIDs();
var itemType;
if (osmClosed.length) {
tags["closed:note"] = context.cleanTagValue(osmClosed.join(";"));
}
if (services.keepRight) {
var krClosed = services.keepRight.getClosedIDs();
if (krClosed.length) {
tags["closed:keepright"] = context.cleanTagValue(krClosed.join(";"));
}
}
if (services.improveOSM) {
var iOsmClosed = services.improveOSM.getClosedCounts();
for (itemType in iOsmClosed) {
tags["closed:improveosm:" + itemType] = context.cleanTagValue(iOsmClosed[itemType].toString());
}
}
if (services.osmose) {
var osmoseClosed = services.osmose.getClosedCounts();
for (itemType in osmoseClosed) {
tags["closed:osmose:" + itemType] = context.cleanTagValue(osmoseClosed[itemType].toString());
}
}
for (var key in tags) {
if (key.match(/(^warnings:)|(^resolved:)/)) {
delete tags[key];
}
}
function addIssueCounts(issues, prefix) {
var issuesByType = utilArrayGroupBy(issues, "type");
for (var issueType in issuesByType) {
var issuesOfType = issuesByType[issueType];
if (issuesOfType[0].subtype) {
var issuesBySubtype = utilArrayGroupBy(issuesOfType, "subtype");
for (var issueSubtype in issuesBySubtype) {
var issuesOfSubtype = issuesBySubtype[issueSubtype];
tags[prefix + ":" + issueType + ":" + issueSubtype] = context.cleanTagValue(issuesOfSubtype.length.toString());
}
} else {
tags[prefix + ":" + issueType] = context.cleanTagValue(issuesOfType.length.toString());
}
}
}
var warnings = context.validator().getIssuesBySeverity({ what: "edited", where: "all", includeIgnored: true, includeDisabledRules: true }).warning.filter(function(issue) {
return issue.type !== "help_request";
});
addIssueCounts(warnings, "warnings");
var resolvedIssues = context.validator().getResolvedIssues();
addIssueCounts(resolvedIssues, "resolved");
context.changeset = context.changeset.update({ tags });
}
function render(selection2) {
var osm = context.connection();
if (!osm)
return;
var header = selection2.selectAll(".header").data([0]);
var headerTitle = header.enter().append("div").attr("class", "header fillL");
headerTitle.append("div").append("h2").call(_t.append("commit.title"));
headerTitle.append("button").attr("class", "close").attr("title", _t("icons.close")).on("click", function() {
dispatch10.call("cancel", this);
}).call(svgIcon("#iD-icon-close"));
var body = selection2.selectAll(".body").data([0]);
body = body.enter().append("div").attr("class", "body").merge(body);
var changesetSection = body.selectAll(".changeset-editor").data([0]);
changesetSection = changesetSection.enter().append("div").attr("class", "modal-section changeset-editor").merge(changesetSection);
changesetSection.call(changesetEditor.changesetID(context.changeset.id).tags(context.changeset.tags));
body.call(commitWarnings);
var saveSection = body.selectAll(".save-section").data([0]);
saveSection = saveSection.enter().append("div").attr("class", "modal-section save-section fillL").merge(saveSection);
var prose = saveSection.selectAll(".commit-info").data([0]);
if (prose.enter().size()) {
_userDetails2 = null;
}
prose = prose.enter().append("p").attr("class", "commit-info").call(_t.append("commit.upload_explanation")).merge(prose);
osm.userDetails(function(err, user) {
if (err)
return;
if (_userDetails2 === user)
return;
_userDetails2 = user;
var userLink = select_default2(document.createElement("div"));
if (user.image_url) {
userLink.append("img").attr("src", user.image_url).attr("class", "icon pre-text user-icon");
}
userLink.append("a").attr("class", "user-info").text(user.display_name).attr("href", osm.userURL(user.display_name)).attr("target", "_blank");
prose.html(_t.html("commit.upload_explanation_with_user", { user: { html: userLink.html() } }));
});
var requestReview = saveSection.selectAll(".request-review").data([0]);
var requestReviewEnter = requestReview.enter().append("div").attr("class", "request-review");
var requestReviewDomId = utilUniqueDomId("commit-input-request-review");
var labelEnter = requestReviewEnter.append("label").attr("for", requestReviewDomId);
if (!labelEnter.empty()) {
labelEnter.call(uiTooltip().title(_t.html("commit.request_review_info")).placement("top"));
}
labelEnter.append("input").attr("type", "checkbox").attr("id", requestReviewDomId);
labelEnter.append("span").call(_t.append("commit.request_review"));
requestReview = requestReview.merge(requestReviewEnter);
var requestReviewInput = requestReview.selectAll("input").property("checked", isReviewRequested(context.changeset.tags)).on("change", toggleRequestReview);
var buttonSection = saveSection.selectAll(".buttons").data([0]);
var buttonEnter = buttonSection.enter().append("div").attr("class", "buttons fillL");
buttonEnter.append("button").attr("class", "secondary-action button cancel-button").append("span").attr("class", "label").call(_t.append("commit.cancel"));
var uploadButton = buttonEnter.append("button").attr("class", "action button save-button");
uploadButton.append("span").attr("class", "label").call(_t.append("commit.save"));
var uploadBlockerTooltipText = getUploadBlockerMessage();
buttonSection = buttonSection.merge(buttonEnter);
buttonSection.selectAll(".cancel-button").on("click.cancel", function() {
dispatch10.call("cancel", this);
});
buttonSection.selectAll(".save-button").classed("disabled", uploadBlockerTooltipText !== null).on("click.save", function() {
if (!select_default2(this).classed("disabled")) {
this.blur();
for (var key in context.changeset.tags) {
if (!key)
delete context.changeset.tags[key];
}
context.uploader().save(context.changeset);
}
});
uiTooltip().destroyAny(buttonSection.selectAll(".save-button"));
if (uploadBlockerTooltipText) {
buttonSection.selectAll(".save-button").call(uiTooltip().title(uploadBlockerTooltipText).placement("top"));
}
var tagSection = body.selectAll(".tag-section.raw-tag-editor").data([0]);
tagSection = tagSection.enter().append("div").attr("class", "modal-section tag-section raw-tag-editor").merge(tagSection);
tagSection.call(rawTagEditor.tags(Object.assign({}, context.changeset.tags)).render);
var changesSection = body.selectAll(".commit-changes-section").data([0]);
changesSection = changesSection.enter().append("div").attr("class", "modal-section commit-changes-section").merge(changesSection);
changesSection.call(commitChanges.render);
function toggleRequestReview() {
var rr = requestReviewInput.property("checked");
updateChangeset({ review_requested: rr ? "yes" : void 0 });
tagSection.call(rawTagEditor.tags(Object.assign({}, context.changeset.tags)).render);
}
}
function getUploadBlockerMessage() {
var errors = context.validator().getIssuesBySeverity({ what: "edited", where: "all" }).error;
if (errors.length) {
return _t("commit.outstanding_errors_message", { count: errors.length });
} else {
var hasChangesetComment = context.changeset && context.changeset.tags.comment && context.changeset.tags.comment.trim().length;
if (!hasChangesetComment) {
return _t("commit.comment_needed_message");
}
}
return null;
}
function changeTags(_, changed, onInput) {
if (changed.hasOwnProperty("comment")) {
if (changed.comment === void 0) {
changed.comment = "";
}
if (!onInput) {
corePreferences("comment", changed.comment);
corePreferences("commentDate", Date.now());
}
}
if (changed.hasOwnProperty("source")) {
if (changed.source === void 0) {
corePreferences("source", null);
} else if (!onInput) {
corePreferences("source", changed.source);
corePreferences("commentDate", Date.now());
}
}
updateChangeset(changed, onInput);
if (_selection) {
_selection.call(render);
}
}
function findHashtags(tags, commentOnly) {
var detectedHashtags = commentHashtags();
if (detectedHashtags.length) {
corePreferences("hashtags", null);
}
if (!detectedHashtags.length || !commentOnly) {
detectedHashtags = detectedHashtags.concat(hashtagHashtags());
}
var allLowerCase = /* @__PURE__ */ new Set();
return detectedHashtags.filter(function(hashtag) {
var lowerCase = hashtag.toLowerCase();
if (!allLowerCase.has(lowerCase)) {
allLowerCase.add(lowerCase);
return true;
}
return false;
});
function commentHashtags() {
var matches = (tags.comment || "").replace(/http\S*/g, "").match(hashtagRegex);
return matches || [];
}
function hashtagHashtags() {
var matches = (tags.hashtags || "").split(/[,;\s]+/).map(function(s) {
if (s[0] !== "#") {
s = "#" + s;
}
var matched = s.match(hashtagRegex);
return matched && matched[0];
}).filter(Boolean);
return matches || [];
}
}
function isReviewRequested(tags) {
var rr = tags.review_requested;
if (rr === void 0)
return false;
rr = rr.trim().toLowerCase();
return !(rr === "" || rr === "no");
}
function updateChangeset(changed, onInput) {
var tags = Object.assign({}, context.changeset.tags);
Object.keys(changed).forEach(function(k) {
var v = changed[k];
k = context.cleanTagKey(k);
if (readOnlyTags.indexOf(k) !== -1)
return;
if (v === void 0) {
delete tags[k];
} else if (onInput) {
tags[k] = v;
} else {
tags[k] = context.cleanTagValue(v);
}
});
if (!onInput) {
var commentOnly = changed.hasOwnProperty("comment") && changed.comment !== "";
var arr = findHashtags(tags, commentOnly);
if (arr.length) {
tags.hashtags = context.cleanTagValue(arr.join(";"));
corePreferences("hashtags", tags.hashtags);
} else {
delete tags.hashtags;
corePreferences("hashtags", null);
}
}
if (_userDetails2 && _userDetails2.changesets_count !== void 0) {
var changesetsCount = parseInt(_userDetails2.changesets_count, 10) + 1;
tags.changesets_count = String(changesetsCount);
if (changesetsCount <= 100) {
var s;
s = corePreferences("walkthrough_completed");
if (s) {
tags["ideditor:walkthrough_completed"] = s;
}
s = corePreferences("walkthrough_progress");
if (s) {
tags["ideditor:walkthrough_progress"] = s;
}
s = corePreferences("walkthrough_started");
if (s) {
tags["ideditor:walkthrough_started"] = s;
}
}
} else {
delete tags.changesets_count;
}
if (!(0, import_fast_deep_equal9.default)(context.changeset.tags, tags)) {
context.changeset = context.changeset.update({ tags });
}
}
commit.reset = function() {
context.changeset = null;
};
return utilRebind(commit, dispatch10, "on");
}
// modules/ui/confirm.js
function uiConfirm(selection2) {
var modalSelection = uiModal(selection2);
modalSelection.select(".modal").classed("modal-alert", true);
var section = modalSelection.select(".content");
section.append("div").attr("class", "modal-section header");
section.append("div").attr("class", "modal-section message-text");
var buttons = section.append("div").attr("class", "modal-section buttons cf");
modalSelection.okButton = function() {
buttons.append("button").attr("class", "button ok-button action").on("click.confirm", function() {
modalSelection.remove();
}).call(_t.append("confirm.okay")).node().focus();
return modalSelection;
};
return modalSelection;
}
// modules/ui/conflicts.js
function uiConflicts(context) {
var dispatch10 = dispatch_default("cancel", "save");
var keybinding = utilKeybinding("conflicts");
var _origChanges;
var _conflictList;
var _shownConflictIndex;
function keybindingOn() {
select_default2(document).call(keybinding.on("\u238B", cancel, true));
}
function keybindingOff() {
select_default2(document).call(keybinding.unbind);
}
function tryAgain() {
keybindingOff();
dispatch10.call("save");
}
function cancel() {
keybindingOff();
dispatch10.call("cancel");
}
function conflicts(selection2) {
keybindingOn();
var headerEnter = selection2.selectAll(".header").data([0]).enter().append("div").attr("class", "header fillL");
headerEnter.append("button").attr("class", "fr").attr("title", _t("icons.close")).on("click", cancel).call(svgIcon("#iD-icon-close"));
headerEnter.append("h2").call(_t.append("save.conflict.header"));
var bodyEnter = selection2.selectAll(".body").data([0]).enter().append("div").attr("class", "body fillL");
var conflictsHelpEnter = bodyEnter.append("div").attr("class", "conflicts-help").call(_t.append("save.conflict.help"));
var changeset = new osmChangeset();
delete changeset.id;
var data = JXON.stringify(changeset.osmChangeJXON(_origChanges));
var blob = new Blob([data], { type: "text/xml;charset=utf-8;" });
var fileName = "changes.osc";
var linkEnter = conflictsHelpEnter.selectAll(".download-changes").append("a").attr("class", "download-changes");
linkEnter.attr("href", window.URL.createObjectURL(blob)).attr("download", fileName);
linkEnter.call(svgIcon("#iD-icon-load", "inline")).append("span").call(_t.append("save.conflict.download_changes"));
bodyEnter.append("div").attr("class", "conflict-container fillL3").call(showConflict, 0);
bodyEnter.append("div").attr("class", "conflicts-done").attr("opacity", 0).style("display", "none").call(_t.append("save.conflict.done"));
var buttonsEnter = bodyEnter.append("div").attr("class", "buttons col12 joined conflicts-buttons");
buttonsEnter.append("button").attr("disabled", _conflictList.length > 1).attr("class", "action conflicts-button col6").call(_t.append("save.title")).on("click.try_again", tryAgain);
buttonsEnter.append("button").attr("class", "secondary-action conflicts-button col6").call(_t.append("confirm.cancel")).on("click.cancel", cancel);
}
function showConflict(selection2, index) {
index = utilWrap(index, _conflictList.length);
_shownConflictIndex = index;
var parent = select_default2(selection2.node().parentNode);
if (index === _conflictList.length - 1) {
window.setTimeout(function() {
parent.select(".conflicts-button").attr("disabled", null);
parent.select(".conflicts-done").transition().attr("opacity", 1).style("display", "block");
}, 250);
}
var conflict = selection2.selectAll(".conflict").data([_conflictList[index]]);
conflict.exit().remove();
var conflictEnter = conflict.enter().append("div").attr("class", "conflict");
conflictEnter.append("h4").attr("class", "conflict-count").call(_t.append("save.conflict.count", { num: index + 1, total: _conflictList.length }));
conflictEnter.append("a").attr("class", "conflict-description").attr("href", "#").text(function(d) {
return d.name;
}).on("click", function(d3_event, d) {
d3_event.preventDefault();
zoomToEntity(d.id);
});
var details = conflictEnter.append("div").attr("class", "conflict-detail-container");
details.append("ul").attr("class", "conflict-detail-list").selectAll("li").data(function(d) {
return d.details || [];
}).enter().append("li").attr("class", "conflict-detail-item").html(function(d) {
return d;
});
details.append("div").attr("class", "conflict-choices").call(addChoices);
details.append("div").attr("class", "conflict-nav-buttons joined cf").selectAll("button").data(["previous", "next"]).enter().append("button").html(function(d) {
return _t.html("save.conflict." + d);
}).attr("class", "conflict-nav-button action col6").attr("disabled", function(d, i2) {
return i2 === 0 && index === 0 || i2 === 1 && index === _conflictList.length - 1 || null;
}).on("click", function(d3_event, d) {
d3_event.preventDefault();
var container = parent.selectAll(".conflict-container");
var sign2 = d === "previous" ? -1 : 1;
container.selectAll(".conflict").remove();
container.call(showConflict, index + sign2);
});
}
function addChoices(selection2) {
var choices = selection2.append("ul").attr("class", "layer-list").selectAll("li").data(function(d) {
return d.choices || [];
});
var choicesEnter = choices.enter().append("li").attr("class", "layer");
var labelEnter = choicesEnter.append("label");
labelEnter.append("input").attr("type", "radio").attr("name", function(d) {
return d.id;
}).on("change", function(d3_event, d) {
var ul = this.parentNode.parentNode.parentNode;
ul.__data__.chosen = d.id;
choose(d3_event, ul, d);
});
labelEnter.append("span").text(function(d) {
return d.text;
});
choicesEnter.merge(choices).each(function(d) {
var ul = this.parentNode;
if (ul.__data__.chosen === d.id) {
choose(null, ul, d);
}
});
}
function choose(d3_event, ul, datum2) {
if (d3_event)
d3_event.preventDefault();
select_default2(ul).selectAll("li").classed("active", function(d) {
return d === datum2;
}).selectAll("input").property("checked", function(d) {
return d === datum2;
});
var extent = geoExtent();
var entity;
entity = context.graph().hasEntity(datum2.id);
if (entity)
extent._extend(entity.extent(context.graph()));
datum2.action();
entity = context.graph().hasEntity(datum2.id);
if (entity)
extent._extend(entity.extent(context.graph()));
zoomToEntity(datum2.id, extent);
}
function zoomToEntity(id2, extent) {
context.surface().selectAll(".hover").classed("hover", false);
var entity = context.graph().hasEntity(id2);
if (entity) {
if (extent) {
context.map().trimmedExtent(extent);
} else {
context.map().zoomToEase(entity);
}
context.surface().selectAll(utilEntityOrMemberSelector([entity.id], context.graph())).classed("hover", true);
}
}
conflicts.conflictList = function(_) {
if (!arguments.length)
return _conflictList;
_conflictList = _;
return conflicts;
};
conflicts.origChanges = function(_) {
if (!arguments.length)
return _origChanges;
_origChanges = _;
return conflicts;
};
conflicts.shownEntityIds = function() {
if (_conflictList && typeof _shownConflictIndex === "number") {
return [_conflictList[_shownConflictIndex].id];
}
return [];
};
return utilRebind(conflicts, dispatch10, "on");
}
// modules/ui/entity_editor.js
var import_fast_deep_equal10 = __toESM(require_fast_deep_equal());
// modules/ui/sections/entity_issues.js
function uiSectionEntityIssues(context) {
var preference = corePreferences("entity-issues.reference.expanded");
var _expanded = preference === null ? true : preference === "true";
var _entityIDs = [];
var _issues = [];
var _activeIssueID;
var section = uiSection("entity-issues", context).shouldDisplay(function() {
return _issues.length > 0;
}).label(function() {
return _t.html("inspector.title_count", { title: { html: _t.html("issues.list_title") }, count: _issues.length });
}).disclosureContent(renderDisclosureContent);
context.validator().on("validated.entity_issues", function() {
reloadIssues();
section.reRender();
}).on("focusedIssue.entity_issues", function(issue) {
makeActiveIssue(issue.id);
});
function reloadIssues() {
_issues = context.validator().getSharedEntityIssues(_entityIDs, { includeDisabledRules: true });
}
function makeActiveIssue(issueID) {
_activeIssueID = issueID;
section.selection().selectAll(".issue-container").classed("active", function(d) {
return d.id === _activeIssueID;
});
}
function renderDisclosureContent(selection2) {
selection2.classed("grouped-items-area", true);
_activeIssueID = _issues.length > 0 ? _issues[0].id : null;
var containers = selection2.selectAll(".issue-container").data(_issues, function(d) {
return d.key;
});
containers.exit().remove();
var containersEnter = containers.enter().append("div").attr("class", "issue-container");
var itemsEnter = containersEnter.append("div").attr("class", function(d) {
return "issue severity-" + d.severity;
}).on("mouseover.highlight", function(d3_event, d) {
var ids = d.entityIds.filter(function(e) {
return _entityIDs.indexOf(e) === -1;
});
utilHighlightEntities(ids, true, context);
}).on("mouseout.highlight", function(d3_event, d) {
var ids = d.entityIds.filter(function(e) {
return _entityIDs.indexOf(e) === -1;
});
utilHighlightEntities(ids, false, context);
});
var labelsEnter = itemsEnter.append("div").attr("class", "issue-label");
var textEnter = labelsEnter.append("button").attr("class", "issue-text").on("click", function(d3_event, d) {
makeActiveIssue(d.id);
var extent = d.extent(context.graph());
if (extent) {
var setZoom = Math.max(context.map().zoom(), 19);
context.map().unobscuredCenterZoomEase(extent.center(), setZoom);
}
});
textEnter.each(function(d) {
var iconName = "#iD-icon-" + (d.severity === "warning" ? "alert" : "error");
select_default2(this).call(svgIcon(iconName, "issue-icon"));
});
textEnter.append("span").attr("class", "issue-message");
var infoButton = labelsEnter.append("button").attr("class", "issue-info-button").attr("title", _t("icons.information")).call(svgIcon("#iD-icon-inspect"));
infoButton.on("click", function(d3_event) {
d3_event.stopPropagation();
d3_event.preventDefault();
this.blur();
var container = select_default2(this.parentNode.parentNode.parentNode);
var info = container.selectAll(".issue-info");
var isExpanded = info.classed("expanded");
_expanded = !isExpanded;
corePreferences("entity-issues.reference.expanded", _expanded);
if (isExpanded) {
info.transition().duration(200).style("max-height", "0px").style("opacity", "0").on("end", function() {
info.classed("expanded", false);
});
} else {
info.classed("expanded", true).transition().duration(200).style("max-height", "200px").style("opacity", "1").on("end", function() {
info.style("max-height", null);
});
}
});
itemsEnter.append("ul").attr("class", "issue-fix-list");
containersEnter.append("div").attr("class", "issue-info" + (_expanded ? " expanded" : "")).style("max-height", _expanded ? null : "0").style("opacity", _expanded ? "1" : "0").each(function(d) {
if (typeof d.reference === "function") {
select_default2(this).call(d.reference);
} else {
select_default2(this).call(_t.append("inspector.no_documentation_key"));
}
});
containers = containers.merge(containersEnter).classed("active", function(d) {
return d.id === _activeIssueID;
});
containers.selectAll(".issue-message").html(function(d) {
return d.message(context);
});
var fixLists = containers.selectAll(".issue-fix-list");
var fixes = fixLists.selectAll(".issue-fix-item").data(function(d) {
return d.fixes ? d.fixes(context) : [];
}, function(fix) {
return fix.id;
});
fixes.exit().remove();
var fixesEnter = fixes.enter().append("li").attr("class", "issue-fix-item");
var buttons = fixesEnter.append("button").on("click", function(d3_event, d) {
if (select_default2(this).attr("disabled") || !d.onClick)
return;
if (d.issue.dateLastRanFix && new Date() - d.issue.dateLastRanFix < 1e3)
return;
d.issue.dateLastRanFix = new Date();
utilHighlightEntities(d.issue.entityIds.concat(d.entityIds), false, context);
new Promise(function(resolve, reject) {
d.onClick(context, resolve, reject);
if (d.onClick.length <= 1) {
resolve();
}
}).then(function() {
context.validator().validate();
});
}).on("mouseover.highlight", function(d3_event, d) {
utilHighlightEntities(d.entityIds, true, context);
}).on("mouseout.highlight", function(d3_event, d) {
utilHighlightEntities(d.entityIds, false, context);
});
buttons.each(function(d) {
var iconName = d.icon || "iD-icon-wrench";
if (iconName.startsWith("maki")) {
iconName += "-15";
}
select_default2(this).call(svgIcon("#" + iconName, "fix-icon"));
});
buttons.append("span").attr("class", "fix-message").html(function(d) {
return d.title;
});
fixesEnter.merge(fixes).selectAll("button").classed("actionable", function(d) {
return d.onClick;
}).attr("disabled", function(d) {
return d.onClick ? null : "true";
}).attr("title", function(d) {
if (d.disabledReason) {
return d.disabledReason;
}
return null;
});
}
section.entityIDs = function(val) {
if (!arguments.length)
return _entityIDs;
if (!_entityIDs || !val || !utilArrayIdentical(_entityIDs, val)) {
_entityIDs = val;
_activeIssueID = null;
reloadIssues();
}
return section;
};
return section;
}
// modules/ui/preset_icon.js
function uiPresetIcon() {
let _preset;
let _geometry;
function presetIcon(selection2) {
selection2.each(render);
}
function getIcon(p, geom) {
if (p.icon)
return p.icon;
if (geom === "line")
return "iD-other-line";
if (geom === "vertex")
return p.isFallback() ? "" : "temaki-vertex";
return "maki-marker-stroked";
}
function renderPointBorder(container, drawPoint) {
let pointBorder = container.selectAll(".preset-icon-point-border").data(drawPoint ? [0] : []);
pointBorder.exit().remove();
let pointBorderEnter = pointBorder.enter();
const w = 40;
const h = 40;
pointBorderEnter.append("svg").attr("class", "preset-icon-fill preset-icon-point-border").attr("width", w).attr("height", h).attr("viewBox", `0 0 ${w} ${h}`).append("path").attr("transform", "translate(11.5, 8)").attr("d", "M 17,8 C 17,13 11,21 8.5,23.5 C 6,21 0,13 0,8 C 0,4 4,-0.5 8.5,-0.5 C 13,-0.5 17,4 17,8 z");
pointBorder = pointBorderEnter.merge(pointBorder);
}
function renderCategoryBorder(container, category) {
let categoryBorder = container.selectAll(".preset-icon-category-border").data(category ? [0] : []);
categoryBorder.exit().remove();
let categoryBorderEnter = categoryBorder.enter();
const d = 60;
let svgEnter = categoryBorderEnter.append("svg").attr("class", "preset-icon-fill preset-icon-category-border").attr("width", d).attr("height", d).attr("viewBox", `0 0 ${d} ${d}`);
svgEnter.append("path").attr("class", "area").attr("d", "M9.5,7.5 L25.5,7.5 L28.5,12.5 L49.5,12.5 C51.709139,12.5 53.5,14.290861 53.5,16.5 L53.5,43.5 C53.5,45.709139 51.709139,47.5 49.5,47.5 L10.5,47.5 C8.290861,47.5 6.5,45.709139 6.5,43.5 L6.5,12.5 L9.5,7.5 Z");
categoryBorder = categoryBorderEnter.merge(categoryBorder);
if (category) {
categoryBorder.selectAll("path").attr("class", `area ${category.id}`);
}
}
function renderCircleFill(container, drawVertex) {
let vertexFill = container.selectAll(".preset-icon-fill-vertex").data(drawVertex ? [0] : []);
vertexFill.exit().remove();
let vertexFillEnter = vertexFill.enter();
const w = 60;
const h = 60;
const d = 40;
vertexFillEnter.append("svg").attr("class", "preset-icon-fill preset-icon-fill-vertex").attr("width", w).attr("height", h).attr("viewBox", `0 0 ${w} ${h}`).append("circle").attr("cx", w / 2).attr("cy", h / 2).attr("r", d / 2);
vertexFill = vertexFillEnter.merge(vertexFill);
}
function renderSquareFill(container, drawArea, tagClasses) {
let fill = container.selectAll(".preset-icon-fill-area").data(drawArea ? [0] : []);
fill.exit().remove();
let fillEnter = fill.enter();
const d = 60;
const w = d;
const h = d;
const l = d * 2 / 3;
const c1 = (w - l) / 2;
const c2 = c1 + l;
fillEnter = fillEnter.append("svg").attr("class", "preset-icon-fill preset-icon-fill-area").attr("width", w).attr("height", h).attr("viewBox", `0 0 ${w} ${h}`);
["fill", "stroke"].forEach((klass) => {
fillEnter.append("path").attr("d", `M${c1} ${c1} L${c1} ${c2} L${c2} ${c2} L${c2} ${c1} Z`).attr("class", `area ${klass}`);
});
const rVertex = 2.5;
[[c1, c1], [c1, c2], [c2, c2], [c2, c1]].forEach((point) => {
fillEnter.append("circle").attr("class", "vertex").attr("cx", point[0]).attr("cy", point[1]).attr("r", rVertex);
});
const rMidpoint = 1.25;
[[c1, w / 2], [c2, w / 2], [h / 2, c1], [h / 2, c2]].forEach((point) => {
fillEnter.append("circle").attr("class", "midpoint").attr("cx", point[0]).attr("cy", point[1]).attr("r", rMidpoint);
});
fill = fillEnter.merge(fill);
fill.selectAll("path.stroke").attr("class", `area stroke ${tagClasses}`);
fill.selectAll("path.fill").attr("class", `area fill ${tagClasses}`);
}
function renderLine(container, drawLine, tagClasses) {
let line = container.selectAll(".preset-icon-line").data(drawLine ? [0] : []);
line.exit().remove();
let lineEnter = line.enter();
const d = 60;
const w = d;
const h = d;
const y = Math.round(d * 0.72);
const l = Math.round(d * 0.6);
const r = 2.5;
const x12 = (w - l) / 2;
const x2 = x12 + l;
lineEnter = lineEnter.append("svg").attr("class", "preset-icon-line").attr("width", w).attr("height", h).attr("viewBox", `0 0 ${w} ${h}`);
["casing", "stroke"].forEach((klass) => {
lineEnter.append("path").attr("d", `M${x12} ${y} L${x2} ${y}`).attr("class", `line ${klass}`);
});
[[x12 - 1, y], [x2 + 1, y]].forEach((point) => {
lineEnter.append("circle").attr("class", "vertex").attr("cx", point[0]).attr("cy", point[1]).attr("r", r);
});
line = lineEnter.merge(line);
line.selectAll("path.stroke").attr("class", `line stroke ${tagClasses}`);
line.selectAll("path.casing").attr("class", `line casing ${tagClasses}`);
}
function renderRoute(container, drawRoute, p) {
let route = container.selectAll(".preset-icon-route").data(drawRoute ? [0] : []);
route.exit().remove();
let routeEnter = route.enter();
const d = 60;
const w = d;
const h = d;
const y12 = Math.round(d * 0.8);
const y2 = Math.round(d * 0.68);
const l = Math.round(d * 0.6);
const r = 2;
const x12 = (w - l) / 2;
const x2 = x12 + l / 3;
const x3 = x2 + l / 3;
const x4 = x3 + l / 3;
routeEnter = routeEnter.append("svg").attr("class", "preset-icon-route").attr("width", w).attr("height", h).attr("viewBox", `0 0 ${w} ${h}`);
["casing", "stroke"].forEach((klass) => {
routeEnter.append("path").attr("d", `M${x12} ${y12} L${x2} ${y2}`).attr("class", `segment0 line ${klass}`);
routeEnter.append("path").attr("d", `M${x2} ${y2} L${x3} ${y12}`).attr("class", `segment1 line ${klass}`);
routeEnter.append("path").attr("d", `M${x3} ${y12} L${x4} ${y2}`).attr("class", `segment2 line ${klass}`);
});
[[x12, y12], [x2, y2], [x3, y12], [x4, y2]].forEach((point) => {
routeEnter.append("circle").attr("class", "vertex").attr("cx", point[0]).attr("cy", point[1]).attr("r", r);
});
route = routeEnter.merge(route);
if (drawRoute) {
let routeType = p.tags.type === "waterway" ? "waterway" : p.tags.route;
const segmentPresetIDs = routeSegments[routeType];
for (let i2 in segmentPresetIDs) {
const segmentPreset = _mainPresetIndex.item(segmentPresetIDs[i2]);
const segmentTagClasses = svgTagClasses().getClassesString(segmentPreset.tags, "");
route.selectAll(`path.stroke.segment${i2}`).attr("class", `segment${i2} line stroke ${segmentTagClasses}`);
route.selectAll(`path.casing.segment${i2}`).attr("class", `segment${i2} line casing ${segmentTagClasses}`);
}
}
}
function renderSvgIcon(container, picon, geom, isFramed, category, tagClasses) {
const isMaki = picon && /^maki-/.test(picon);
const isTemaki = picon && /^temaki-/.test(picon);
const isFa = picon && /^fa[srb]-/.test(picon);
const isiDIcon = picon && !(isMaki || isTemaki || isFa);
let icon2 = container.selectAll(".preset-icon").data(picon ? [0] : []);
icon2.exit().remove();
icon2 = icon2.enter().append("div").attr("class", "preset-icon").call(svgIcon("")).merge(icon2);
icon2.attr("class", "preset-icon " + (geom ? geom + "-geom" : "")).classed("category", category).classed("framed", isFramed).classed("preset-icon-iD", isiDIcon);
icon2.selectAll("svg").attr("class", "icon " + picon + " " + (!isiDIcon && geom !== "line" ? "" : tagClasses));
icon2.selectAll("use").attr("href", "#" + picon);
}
function renderImageIcon(container, imageURL) {
let imageIcon = container.selectAll("img.image-icon").data(imageURL ? [0] : []);
imageIcon.exit().remove();
imageIcon = imageIcon.enter().append("img").attr("class", "image-icon").on("load", () => container.classed("showing-img", true)).on("error", () => container.classed("showing-img", false)).merge(imageIcon);
imageIcon.attr("src", imageURL);
}
const routeSegments = {
bicycle: ["highway/cycleway", "highway/cycleway", "highway/cycleway"],
bus: ["highway/unclassified", "highway/secondary", "highway/primary"],
trolleybus: ["highway/unclassified", "highway/secondary", "highway/primary"],
detour: ["highway/tertiary", "highway/residential", "highway/unclassified"],
ferry: ["route/ferry", "route/ferry", "route/ferry"],
foot: ["highway/footway", "highway/footway", "highway/footway"],
hiking: ["highway/path", "highway/path", "highway/path"],
horse: ["highway/bridleway", "highway/bridleway", "highway/bridleway"],
light_rail: ["railway/light_rail", "railway/light_rail", "railway/light_rail"],
monorail: ["railway/monorail", "railway/monorail", "railway/monorail"],
mtb: ["highway/path", "highway/track", "highway/bridleway"],
pipeline: ["man_made/pipeline", "man_made/pipeline", "man_made/pipeline"],
piste: ["piste/downhill", "piste/hike", "piste/nordic"],
power: ["power/line", "power/line", "power/line"],
road: ["highway/secondary", "highway/primary", "highway/trunk"],
subway: ["railway/subway", "railway/subway", "railway/subway"],
train: ["railway/rail", "railway/rail", "railway/rail"],
tram: ["railway/tram", "railway/tram", "railway/tram"],
waterway: ["waterway/stream", "waterway/stream", "waterway/stream"]
};
function render() {
let p = _preset.apply(this, arguments);
let geom = _geometry ? _geometry.apply(this, arguments) : null;
if (geom === "relation" && p.tags && (p.tags.type === "route" && p.tags.route && routeSegments[p.tags.route] || p.tags.type === "waterway")) {
geom = "route";
}
const showThirdPartyIcons = corePreferences("preferences.privacy.thirdpartyicons") || "true";
const isFallback = p.isFallback && p.isFallback();
const imageURL = showThirdPartyIcons === "true" && p.imageURL;
const picon = getIcon(p, geom);
const isCategory = !p.setTags;
const drawPoint = false;
const drawVertex = picon !== null && geom === "vertex" && !isFallback;
const drawLine = picon && geom === "line" && !isFallback && !isCategory;
const drawArea = picon && geom === "area" && !isFallback && !isCategory;
const drawRoute = picon && geom === "route";
const isFramed = drawVertex || drawArea || drawLine || drawRoute || isCategory;
let tags = !isCategory ? p.setTags({}, geom) : {};
for (let k in tags) {
if (tags[k] === "*") {
tags[k] = "yes";
}
}
let tagClasses = svgTagClasses().getClassesString(tags, "");
let selection2 = select_default2(this);
let container = selection2.selectAll(".preset-icon-container").data([0]);
container = container.enter().append("div").attr("class", "preset-icon-container").merge(container);
container.classed("showing-img", !!imageURL).classed("fallback", isFallback);
renderCategoryBorder(container, isCategory && p);
renderPointBorder(container, drawPoint);
renderCircleFill(container, drawVertex);
renderSquareFill(container, drawArea, tagClasses);
renderLine(container, drawLine, tagClasses);
renderRoute(container, drawRoute, p);
renderSvgIcon(container, picon, geom, isFramed, isCategory, tagClasses);
renderImageIcon(container, imageURL);
}
presetIcon.preset = function(val) {
if (!arguments.length)
return _preset;
_preset = utilFunctor(val);
return presetIcon;
};
presetIcon.geometry = function(val) {
if (!arguments.length)
return _geometry;
_geometry = utilFunctor(val);
return presetIcon;
};
return presetIcon;
}
// modules/ui/sections/feature_type.js
function uiSectionFeatureType(context) {
var dispatch10 = dispatch_default("choose");
var _entityIDs = [];
var _presets = [];
var _tagReference;
var section = uiSection("feature-type", context).label(_t.html("inspector.feature_type")).disclosureContent(renderDisclosureContent);
function renderDisclosureContent(selection2) {
selection2.classed("preset-list-item", true);
selection2.classed("mixed-types", _presets.length > 1);
var presetButtonWrap = selection2.selectAll(".preset-list-button-wrap").data([0]).enter().append("div").attr("class", "preset-list-button-wrap");
var presetButton = presetButtonWrap.append("button").attr("class", "preset-list-button preset-reset").call(uiTooltip().title(_t.html("inspector.back_tooltip")).placement("bottom"));
presetButton.append("div").attr("class", "preset-icon-container");
presetButton.append("div").attr("class", "label").append("div").attr("class", "label-inner");
presetButtonWrap.append("div").attr("class", "accessory-buttons");
var tagReferenceBodyWrap = selection2.selectAll(".tag-reference-body-wrap").data([0]);
tagReferenceBodyWrap = tagReferenceBodyWrap.enter().append("div").attr("class", "tag-reference-body-wrap").merge(tagReferenceBodyWrap);
if (_tagReference) {
selection2.selectAll(".preset-list-button-wrap .accessory-buttons").style("display", _presets.length === 1 ? null : "none").call(_tagReference.button);
tagReferenceBodyWrap.style("display", _presets.length === 1 ? null : "none").call(_tagReference.body);
}
selection2.selectAll(".preset-reset").on("click", function() {
dispatch10.call("choose", this, _presets);
}).on("pointerdown pointerup mousedown mouseup", function(d3_event) {
d3_event.preventDefault();
d3_event.stopPropagation();
});
var geometries = entityGeometries();
selection2.select(".preset-list-item button").call(uiPresetIcon().geometry(_presets.length === 1 ? geometries.length === 1 && geometries[0] : null).preset(_presets.length === 1 ? _presets[0] : _mainPresetIndex.item("point")));
var names = _presets.length === 1 ? [
_presets[0].nameLabel(),
_presets[0].subtitleLabel()
].filter(Boolean) : [_t("inspector.multiple_types")];
var label = selection2.select(".label-inner");
var nameparts = label.selectAll(".namepart").data(names, function(d) {
return d;
});
nameparts.exit().remove();
nameparts.enter().append("div").attr("class", "namepart").html(function(d) {
return d;
});
}
section.entityIDs = function(val) {
if (!arguments.length)
return _entityIDs;
_entityIDs = val;
return section;
};
section.presets = function(val) {
if (!arguments.length)
return _presets;
if (!utilArrayIdentical(val, _presets)) {
_presets = val;
if (_presets.length === 1) {
_tagReference = uiTagReference(_presets[0].reference(), context).showing(false);
}
}
return section;
};
function entityGeometries() {
var counts = {};
for (var i2 in _entityIDs) {
var geometry = context.graph().geometry(_entityIDs[i2]);
if (!counts[geometry])
counts[geometry] = 0;
counts[geometry] += 1;
}
return Object.keys(counts).sort(function(geom1, geom2) {
return counts[geom2] - counts[geom1];
});
}
return utilRebind(section, dispatch10, "on");
}
// modules/ui/sections/preset_fields.js
function uiSectionPresetFields(context) {
var section = uiSection("preset-fields", context).label(_t.html("inspector.fields")).disclosureContent(renderDisclosureContent);
var dispatch10 = dispatch_default("change", "revert");
var formFields = uiFormFields(context);
var _state;
var _fieldsArr;
var _presets = [];
var _tags;
var _entityIDs;
function renderDisclosureContent(selection2) {
if (!_fieldsArr) {
var graph = context.graph();
var geometries = Object.keys(_entityIDs.reduce(function(geoms, entityID) {
geoms[graph.entity(entityID).geometry(graph)] = true;
return geoms;
}, {}));
var presetsManager = _mainPresetIndex;
var allFields = [];
var allMoreFields = [];
var sharedTotalFields;
_presets.forEach(function(preset) {
var fields = preset.fields();
var moreFields = preset.moreFields();
allFields = utilArrayUnion(allFields, fields);
allMoreFields = utilArrayUnion(allMoreFields, moreFields);
if (!sharedTotalFields) {
sharedTotalFields = utilArrayUnion(fields, moreFields);
} else {
sharedTotalFields = sharedTotalFields.filter(function(field) {
return fields.indexOf(field) !== -1 || moreFields.indexOf(field) !== -1;
});
}
});
var sharedFields = allFields.filter(function(field) {
return sharedTotalFields.indexOf(field) !== -1;
});
var sharedMoreFields = allMoreFields.filter(function(field) {
return sharedTotalFields.indexOf(field) !== -1;
});
_fieldsArr = [];
sharedFields.forEach(function(field) {
if (field.matchAllGeometry(geometries)) {
_fieldsArr.push(uiField(context, field, _entityIDs));
}
});
var singularEntity = _entityIDs.length === 1 && graph.hasEntity(_entityIDs[0]);
if (singularEntity && singularEntity.isHighwayIntersection(graph) && presetsManager.field("restrictions")) {
_fieldsArr.push(uiField(context, presetsManager.field("restrictions"), _entityIDs));
}
var additionalFields = utilArrayUnion(sharedMoreFields, presetsManager.universal());
additionalFields.sort(function(field1, field2) {
return field1.label().localeCompare(field2.label(), _mainLocalizer.localeCode());
});
additionalFields.forEach(function(field) {
if (sharedFields.indexOf(field) === -1 && field.matchAllGeometry(geometries)) {
_fieldsArr.push(uiField(context, field, _entityIDs, { show: false }));
}
});
_fieldsArr.forEach(function(field) {
field.on("change", function(t, onInput) {
dispatch10.call("change", field, _entityIDs, t, onInput);
}).on("revert", function(keys) {
dispatch10.call("revert", field, keys);
});
});
}
_fieldsArr.forEach(function(field) {
field.state(_state).tags(_tags);
});
selection2.call(formFields.fieldsArr(_fieldsArr).state(_state).klass("grouped-items-area"));
selection2.selectAll(".wrap-form-field input").on("keydown", function(d3_event) {
if (d3_event.keyCode === 13 && context.container().select(".combobox").empty()) {
context.enter(modeBrowse(context));
}
});
}
section.presets = function(val) {
if (!arguments.length)
return _presets;
if (!_presets || !val || !utilArrayIdentical(_presets, val)) {
_presets = val;
_fieldsArr = null;
}
return section;
};
section.state = function(val) {
if (!arguments.length)
return _state;
_state = val;
return section;
};
section.tags = function(val) {
if (!arguments.length)
return _tags;
_tags = val;
return section;
};
section.entityIDs = function(val) {
if (!arguments.length)
return _entityIDs;
if (!val || !_entityIDs || !utilArrayIdentical(_entityIDs, val)) {
_entityIDs = val;
_fieldsArr = null;
}
return section;
};
return utilRebind(section, dispatch10, "on");
}
// modules/ui/sections/raw_member_editor.js
function uiSectionRawMemberEditor(context) {
var section = uiSection("raw-member-editor", context).shouldDisplay(function() {
if (!_entityIDs || _entityIDs.length !== 1)
return false;
var entity = context.hasEntity(_entityIDs[0]);
return entity && entity.type === "relation";
}).label(function() {
var entity = context.hasEntity(_entityIDs[0]);
if (!entity)
return "";
var gt = entity.members.length > _maxMembers ? ">" : "";
var count = gt + entity.members.slice(0, _maxMembers).length;
return _t.html("inspector.title_count", { title: { html: _t.html("inspector.members") }, count });
}).disclosureContent(renderDisclosureContent);
var taginfo = services.taginfo;
var _entityIDs;
var _maxMembers = 1e3;
function downloadMember(d3_event, d) {
d3_event.preventDefault();
select_default2(this.parentNode).classed("tag-reference-loading", true);
context.loadEntity(d.id, function() {
section.reRender();
});
}
function zoomToMember(d3_event, d) {
d3_event.preventDefault();
var entity = context.entity(d.id);
context.map().zoomToEase(entity);
utilHighlightEntities([d.id], true, context);
}
function selectMember(d3_event, d) {
d3_event.preventDefault();
utilHighlightEntities([d.id], false, context);
var entity = context.entity(d.id);
var mapExtent = context.map().extent();
if (!entity.intersects(mapExtent, context.graph())) {
context.map().zoomToEase(entity);
}
context.enter(modeSelect(context, [d.id]));
}
function changeRole(d3_event, d) {
var oldRole = d.role;
var newRole = context.cleanRelationRole(select_default2(this).property("value"));
if (oldRole !== newRole) {
var member = { id: d.id, type: d.type, role: newRole };
context.perform(actionChangeMember(d.relation.id, member, d.index), _t("operations.change_role.annotation", {
n: 1
}));
context.validator().validate();
}
}
function deleteMember(d3_event, d) {
utilHighlightEntities([d.id], false, context);
context.perform(actionDeleteMember(d.relation.id, d.index), _t("operations.delete_member.annotation", {
n: 1
}));
if (!context.hasEntity(d.relation.id)) {
context.enter(modeBrowse(context));
} else {
context.validator().validate();
}
}
function renderDisclosureContent(selection2) {
var entityID = _entityIDs[0];
var memberships = [];
var entity = context.entity(entityID);
entity.members.slice(0, _maxMembers).forEach(function(member, index) {
memberships.push({
index,
id: member.id,
type: member.type,
role: member.role,
relation: entity,
member: context.hasEntity(member.id),
domId: utilUniqueDomId(entityID + "-member-" + index)
});
});
var list = selection2.selectAll(".member-list").data([0]);
list = list.enter().append("ul").attr("class", "member-list").merge(list);
var items = list.selectAll("li").data(memberships, function(d) {
return osmEntity.key(d.relation) + "," + d.index + "," + (d.member ? osmEntity.key(d.member) : "incomplete");
});
items.exit().each(unbind).remove();
var itemsEnter = items.enter().append("li").attr("class", "member-row form-field").classed("member-incomplete", function(d) {
return !d.member;
});
itemsEnter.each(function(d) {
var item = select_default2(this);
var label = item.append("label").attr("class", "field-label").attr("for", d.domId);
if (d.member) {
item.on("mouseover", function() {
utilHighlightEntities([d.id], true, context);
}).on("mouseout", function() {
utilHighlightEntities([d.id], false, context);
});
var labelLink = label.append("span").attr("class", "label-text").append("a").attr("href", "#").on("click", selectMember);
labelLink.append("span").attr("class", "member-entity-type").text(function(d2) {
var matched = _mainPresetIndex.match(d2.member, context.graph());
return matched && matched.name() || utilDisplayType(d2.member.id);
});
labelLink.append("span").attr("class", "member-entity-name").text(function(d2) {
return utilDisplayName(d2.member);
});
label.append("button").attr("title", _t("icons.remove")).attr("class", "remove member-delete").call(svgIcon("#iD-operation-delete"));
label.append("button").attr("class", "member-zoom").attr("title", _t("icons.zoom_to")).call(svgIcon("#iD-icon-framed-dot", "monochrome")).on("click", zoomToMember);
} else {
var labelText = label.append("span").attr("class", "label-text");
labelText.append("span").attr("class", "member-entity-type").call(_t.append("inspector." + d.type, { id: d.id }));
labelText.append("span").attr("class", "member-entity-name").call(_t.append("inspector.incomplete", { id: d.id }));
label.append("button").attr("class", "member-download").attr("title", _t("icons.download")).call(svgIcon("#iD-icon-load")).on("click", downloadMember);
}
});
var wrapEnter = itemsEnter.append("div").attr("class", "form-field-input-wrap form-field-input-member");
wrapEnter.append("input").attr("class", "member-role").attr("id", function(d) {
return d.domId;
}).property("type", "text").attr("placeholder", _t("inspector.role")).call(utilNoAuto);
if (taginfo) {
wrapEnter.each(bindTypeahead);
}
items = items.merge(itemsEnter).order();
items.select("input.member-role").property("value", function(d) {
return d.role;
}).on("blur", changeRole).on("change", changeRole);
items.select("button.member-delete").on("click", deleteMember);
var dragOrigin, targetIndex;
items.call(drag_default().on("start", function(d3_event) {
dragOrigin = {
x: d3_event.x,
y: d3_event.y
};
targetIndex = null;
}).on("drag", function(d3_event) {
var x = d3_event.x - dragOrigin.x, y = d3_event.y - dragOrigin.y;
if (!select_default2(this).classed("dragging") && Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)) <= 5)
return;
var index = items.nodes().indexOf(this);
select_default2(this).classed("dragging", true);
targetIndex = null;
selection2.selectAll("li.member-row").style("transform", function(d2, index2) {
var node = select_default2(this).node();
if (index === index2) {
return "translate(" + x + "px, " + y + "px)";
} else if (index2 > index && d3_event.y > node.offsetTop) {
if (targetIndex === null || index2 > targetIndex) {
targetIndex = index2;
}
return "translateY(-100%)";
} else if (index2 < index && d3_event.y < node.offsetTop + node.offsetHeight) {
if (targetIndex === null || index2 < targetIndex) {
targetIndex = index2;
}
return "translateY(100%)";
}
return null;
});
}).on("end", function(d3_event, d) {
if (!select_default2(this).classed("dragging"))
return;
var index = items.nodes().indexOf(this);
select_default2(this).classed("dragging", false);
selection2.selectAll("li.member-row").style("transform", null);
if (targetIndex !== null) {
context.perform(actionMoveMember(d.relation.id, index, targetIndex), _t("operations.reorder_members.annotation"));
context.validator().validate();
}
}));
function bindTypeahead(d) {
var row = select_default2(this);
var role = row.selectAll("input.member-role");
var origValue = role.property("value");
function sort(value, data) {
var sameletter = [];
var other = [];
for (var i2 = 0; i2 < data.length; i2++) {
if (data[i2].value.substring(0, value.length) === value) {
sameletter.push(data[i2]);
} else {
other.push(data[i2]);
}
}
return sameletter.concat(other);
}
role.call(uiCombobox(context, "member-role").fetcher(function(role2, callback) {
var geometry;
if (d.member) {
geometry = context.graph().geometry(d.member.id);
} else if (d.type === "relation") {
geometry = "relation";
} else if (d.type === "way") {
geometry = "line";
} else {
geometry = "point";
}
var rtype = entity.tags.type;
taginfo.roles({
debounce: true,
rtype: rtype || "",
geometry,
query: role2
}, function(err, data) {
if (!err)
callback(sort(role2, data));
});
}).on("cancel", function() {
role.property("value", origValue);
}));
}
function unbind() {
var row = select_default2(this);
row.selectAll("input.member-role").call(uiCombobox.off, context);
}
}
section.entityIDs = function(val) {
if (!arguments.length)
return _entityIDs;
_entityIDs = val;
return section;
};
return section;
}
// modules/actions/delete_members.js
function actionDeleteMembers(relationId, memberIndexes) {
return function(graph) {
memberIndexes.sort((a, b) => b - a);
for (var i2 in memberIndexes) {
graph = actionDeleteMember(relationId, memberIndexes[i2])(graph);
}
return graph;
};
}
// modules/ui/sections/raw_membership_editor.js
function uiSectionRawMembershipEditor(context) {
var section = uiSection("raw-membership-editor", context).shouldDisplay(function() {
return _entityIDs && _entityIDs.length;
}).label(function() {
var parents = getSharedParentRelations();
var gt = parents.length > _maxMemberships ? ">" : "";
var count = gt + parents.slice(0, _maxMemberships).length;
return _t.html("inspector.title_count", { title: { html: _t.html("inspector.relations") }, count });
}).disclosureContent(renderDisclosureContent);
var taginfo = services.taginfo;
var nearbyCombo = uiCombobox(context, "parent-relation").minItems(1).fetcher(fetchNearbyRelations).itemsMouseEnter(function(d3_event, d) {
if (d.relation)
utilHighlightEntities([d.relation.id], true, context);
}).itemsMouseLeave(function(d3_event, d) {
if (d.relation)
utilHighlightEntities([d.relation.id], false, context);
});
var _inChange = false;
var _entityIDs = [];
var _showBlank;
var _maxMemberships = 1e3;
function getSharedParentRelations() {
var parents = [];
for (var i2 = 0; i2 < _entityIDs.length; i2++) {
var entity = context.graph().hasEntity(_entityIDs[i2]);
if (!entity)
continue;
if (i2 === 0) {
parents = context.graph().parentRelations(entity);
} else {
parents = utilArrayIntersection(parents, context.graph().parentRelations(entity));
}
if (!parents.length)
break;
}
return parents;
}
function getMemberships() {
var memberships = [];
var relations = getSharedParentRelations().slice(0, _maxMemberships);
var isMultiselect = _entityIDs.length > 1;
var i2, relation, membership, index, member, indexedMember;
for (i2 = 0; i2 < relations.length; i2++) {
relation = relations[i2];
membership = {
relation,
members: [],
hash: osmEntity.key(relation)
};
for (index = 0; index < relation.members.length; index++) {
member = relation.members[index];
if (_entityIDs.indexOf(member.id) !== -1) {
indexedMember = Object.assign({}, member, { index });
membership.members.push(indexedMember);
membership.hash += "," + index.toString();
if (!isMultiselect) {
memberships.push(membership);
membership = {
relation,
members: [],
hash: osmEntity.key(relation)
};
}
}
}
if (membership.members.length)
memberships.push(membership);
}
memberships.forEach(function(membership2) {
membership2.domId = utilUniqueDomId("membership-" + membership2.relation.id);
var roles = [];
membership2.members.forEach(function(member2) {
if (roles.indexOf(member2.role) === -1)
roles.push(member2.role);
});
membership2.role = roles.length === 1 ? roles[0] : roles;
});
return memberships;
}
function selectRelation(d3_event, d) {
d3_event.preventDefault();
utilHighlightEntities([d.relation.id], false, context);
context.enter(modeSelect(context, [d.relation.id]));
}
function zoomToRelation(d3_event, d) {
d3_event.preventDefault();
var entity = context.entity(d.relation.id);
context.map().zoomToEase(entity);
utilHighlightEntities([d.relation.id], true, context);
}
function changeRole(d3_event, d) {
if (d === 0)
return;
if (_inChange)
return;
var newRole = context.cleanRelationRole(select_default2(this).property("value"));
if (!newRole.trim() && typeof d.role !== "string")
return;
var membersToUpdate = d.members.filter(function(member) {
return member.role !== newRole;
});
if (membersToUpdate.length) {
_inChange = true;
context.perform(function actionChangeMemberRoles(graph) {
membersToUpdate.forEach(function(member) {
var newMember = Object.assign({}, member, { role: newRole });
delete newMember.index;
graph = actionChangeMember(d.relation.id, newMember, member.index)(graph);
});
return graph;
}, _t("operations.change_role.annotation", {
n: membersToUpdate.length
}));
context.validator().validate();
}
_inChange = false;
}
function addMembership(d, role) {
this.blur();
_showBlank = false;
function actionAddMembers(relationId, ids, role2) {
return function(graph) {
for (var i2 in ids) {
var member = { id: ids[i2], type: graph.entity(ids[i2]).type, role: role2 };
graph = actionAddMember(relationId, member)(graph);
}
return graph;
};
}
if (d.relation) {
context.perform(actionAddMembers(d.relation.id, _entityIDs, role), _t("operations.add_member.annotation", {
n: _entityIDs.length
}));
context.validator().validate();
} else {
var relation = osmRelation();
context.perform(actionAddEntity(relation), actionAddMembers(relation.id, _entityIDs, role), _t("operations.add.annotation.relation"));
context.enter(modeSelect(context, [relation.id]).newFeature(true));
}
}
function deleteMembership(d3_event, d) {
this.blur();
if (d === 0)
return;
utilHighlightEntities([d.relation.id], false, context);
var indexes = d.members.map(function(member) {
return member.index;
});
context.perform(actionDeleteMembers(d.relation.id, indexes), _t("operations.delete_member.annotation", {
n: _entityIDs.length
}));
context.validator().validate();
}
function fetchNearbyRelations(q, callback) {
var newRelation = {
relation: null,
value: _t("inspector.new_relation"),
display: _t.html("inspector.new_relation")
};
var entityID = _entityIDs[0];
var result = [];
var graph = context.graph();
function baseDisplayLabel(entity) {
var matched = _mainPresetIndex.match(entity, graph);
var presetName = matched && matched.name() || _t("inspector.relation");
var entityName = utilDisplayName(entity) || "";
return presetName + " " + entityName;
}
var explicitRelation = q && context.hasEntity(q.toLowerCase());
if (explicitRelation && explicitRelation.type === "relation" && explicitRelation.id !== entityID) {
result.push({
relation: explicitRelation,
value: baseDisplayLabel(explicitRelation) + " " + explicitRelation.id
});
} else {
context.history().intersects(context.map().extent()).forEach(function(entity) {
if (entity.type !== "relation" || entity.id === entityID)
return;
var value = baseDisplayLabel(entity);
if (q && (value + " " + entity.id).toLowerCase().indexOf(q.toLowerCase()) === -1)
return;
result.push({ relation: entity, value });
});
result.sort(function(a, b) {
return osmRelation.creationOrder(a.relation, b.relation);
});
var dupeGroups = Object.values(utilArrayGroupBy(result, "value")).filter(function(v) {
return v.length > 1;
});
dupeGroups.forEach(function(group) {
group.forEach(function(obj) {
obj.value += " " + obj.relation.id;
});
});
}
result.forEach(function(obj) {
obj.title = obj.value;
});
result.unshift(newRelation);
callback(result);
}
function renderDisclosureContent(selection2) {
var memberships = getMemberships();
var list = selection2.selectAll(".member-list").data([0]);
list = list.enter().append("ul").attr("class", "member-list").merge(list);
var items = list.selectAll("li.member-row-normal").data(memberships, function(d) {
return d.hash;
});
items.exit().each(unbind).remove();
var itemsEnter = items.enter().append("li").attr("class", "member-row member-row-normal form-field");
itemsEnter.on("mouseover", function(d3_event, d) {
utilHighlightEntities([d.relation.id], true, context);
}).on("mouseout", function(d3_event, d) {
utilHighlightEntities([d.relation.id], false, context);
});
var labelEnter = itemsEnter.append("label").attr("class", "field-label").attr("for", function(d) {
return d.domId;
});
var labelLink = labelEnter.append("span").attr("class", "label-text").append("a").attr("href", "#").on("click", selectRelation);
labelLink.append("span").attr("class", "member-entity-type").text(function(d) {
var matched = _mainPresetIndex.match(d.relation, context.graph());
return matched && matched.name() || _t.html("inspector.relation");
});
labelLink.append("span").attr("class", "member-entity-name").text(function(d) {
return utilDisplayName(d.relation);
});
labelEnter.append("button").attr("class", "remove member-delete").attr("title", _t("icons.remove")).call(svgIcon("#iD-operation-delete")).on("click", deleteMembership);
labelEnter.append("button").attr("class", "member-zoom").attr("title", _t("icons.zoom_to")).call(svgIcon("#iD-icon-framed-dot", "monochrome")).on("click", zoomToRelation);
var wrapEnter = itemsEnter.append("div").attr("class", "form-field-input-wrap form-field-input-member");
wrapEnter.append("input").attr("class", "member-role").attr("id", function(d) {
return d.domId;
}).property("type", "text").property("value", function(d) {
return typeof d.role === "string" ? d.role : "";
}).attr("title", function(d) {
return Array.isArray(d.role) ? d.role.filter(Boolean).join("\n") : d.role;
}).attr("placeholder", function(d) {
return Array.isArray(d.role) ? _t("inspector.multiple_roles") : _t("inspector.role");
}).classed("mixed", function(d) {
return Array.isArray(d.role);
}).call(utilNoAuto).on("blur", changeRole).on("change", changeRole);
if (taginfo) {
wrapEnter.each(bindTypeahead);
}
var newMembership = list.selectAll(".member-row-new").data(_showBlank ? [0] : []);
newMembership.exit().remove();
var newMembershipEnter = newMembership.enter().append("li").attr("class", "member-row member-row-new form-field");
var newLabelEnter = newMembershipEnter.append("label").attr("class", "field-label");
newLabelEnter.append("input").attr("placeholder", _t("inspector.choose_relation")).attr("type", "text").attr("class", "member-entity-input").call(utilNoAuto);
newLabelEnter.append("button").attr("class", "remove member-delete").attr("title", _t("icons.remove")).call(svgIcon("#iD-operation-delete")).on("click", function() {
list.selectAll(".member-row-new").remove();
});
var newWrapEnter = newMembershipEnter.append("div").attr("class", "form-field-input-wrap form-field-input-member");
newWrapEnter.append("input").attr("class", "member-role").property("type", "text").attr("placeholder", _t("inspector.role")).call(utilNoAuto);
newMembership = newMembership.merge(newMembershipEnter);
newMembership.selectAll(".member-entity-input").on("blur", cancelEntity).call(nearbyCombo.on("accept", acceptEntity).on("cancel", cancelEntity));
var addRow = selection2.selectAll(".add-row").data([0]);
var addRowEnter = addRow.enter().append("div").attr("class", "add-row");
var addRelationButton = addRowEnter.append("button").attr("class", "add-relation").attr("aria-label", _t("inspector.add_to_relation"));
addRelationButton.call(svgIcon("#iD-icon-plus", "light"));
addRelationButton.call(uiTooltip().title(_t.html("inspector.add_to_relation")).placement(_mainLocalizer.textDirection() === "ltr" ? "right" : "left"));
addRowEnter.append("div").attr("class", "space-value");
addRowEnter.append("div").attr("class", "space-buttons");
addRow = addRow.merge(addRowEnter);
addRow.select(".add-relation").on("click", function() {
_showBlank = true;
section.reRender();
list.selectAll(".member-entity-input").node().focus();
});
function acceptEntity(d) {
if (!d) {
cancelEntity();
return;
}
if (d.relation)
utilHighlightEntities([d.relation.id], false, context);
var role = context.cleanRelationRole(list.selectAll(".member-row-new .member-role").property("value"));
addMembership(d, role);
}
function cancelEntity() {
var input = newMembership.selectAll(".member-entity-input");
input.property("value", "");
context.surface().selectAll(".highlighted").classed("highlighted", false);
}
function bindTypeahead(d) {
var row = select_default2(this);
var role = row.selectAll("input.member-role");
var origValue = role.property("value");
function sort(value, data) {
var sameletter = [];
var other = [];
for (var i2 = 0; i2 < data.length; i2++) {
if (data[i2].value.substring(0, value.length) === value) {
sameletter.push(data[i2]);
} else {
other.push(data[i2]);
}
}
return sameletter.concat(other);
}
role.call(uiCombobox(context, "member-role").fetcher(function(role2, callback) {
var rtype = d.relation.tags.type;
taginfo.roles({
debounce: true,
rtype: rtype || "",
geometry: context.graph().geometry(_entityIDs[0]),
query: role2
}, function(err, data) {
if (!err)
callback(sort(role2, data));
});
}).on("cancel", function() {
role.property("value", origValue);
}));
}
function unbind() {
var row = select_default2(this);
row.selectAll("input.member-role").call(uiCombobox.off, context);
}
}
section.entityIDs = function(val) {
if (!arguments.length)
return _entityIDs;
_entityIDs = val;
_showBlank = false;
return section;
};
return section;
}
// modules/ui/sections/selection_list.js
function uiSectionSelectionList(context) {
var _selectedIDs = [];
var section = uiSection("selected-features", context).shouldDisplay(function() {
return _selectedIDs.length > 1;
}).label(function() {
return _t.html("inspector.title_count", { title: { html: _t.html("inspector.features") }, count: _selectedIDs.length });
}).disclosureContent(renderDisclosureContent);
context.history().on("change.selectionList", function(difference) {
if (difference) {
section.reRender();
}
});
section.entityIDs = function(val) {
if (!arguments.length)
return _selectedIDs;
_selectedIDs = val;
return section;
};
function selectEntity(d3_event, entity) {
context.enter(modeSelect(context, [entity.id]));
}
function deselectEntity(d3_event, entity) {
var selectedIDs = _selectedIDs.slice();
var index = selectedIDs.indexOf(entity.id);
if (index > -1) {
selectedIDs.splice(index, 1);
context.enter(modeSelect(context, selectedIDs));
}
}
function renderDisclosureContent(selection2) {
var list = selection2.selectAll(".feature-list").data([0]);
list = list.enter().append("ul").attr("class", "feature-list").merge(list);
var entities = _selectedIDs.map(function(id2) {
return context.hasEntity(id2);
}).filter(Boolean);
var items = list.selectAll(".feature-list-item").data(entities, osmEntity.key);
items.exit().remove();
var enter = items.enter().append("li").attr("class", "feature-list-item").each(function(d) {
select_default2(this).on("mouseover", function() {
utilHighlightEntities([d.id], true, context);
}).on("mouseout", function() {
utilHighlightEntities([d.id], false, context);
});
});
var label = enter.append("button").attr("class", "label").on("click", selectEntity);
label.append("span").attr("class", "entity-geom-icon").call(svgIcon("", "pre-text"));
label.append("span").attr("class", "entity-type");
label.append("span").attr("class", "entity-name");
enter.append("button").attr("class", "close").attr("title", _t("icons.deselect")).on("click", deselectEntity).call(svgIcon("#iD-icon-close"));
items = items.merge(enter);
items.selectAll(".entity-geom-icon use").attr("href", function() {
var entity = this.parentNode.parentNode.__data__;
return "#iD-icon-" + entity.geometry(context.graph());
});
items.selectAll(".entity-type").text(function(entity) {
return _mainPresetIndex.match(entity, context.graph()).name();
});
items.selectAll(".entity-name").text(function(d) {
var entity = context.entity(d.id);
return utilDisplayName(entity);
});
}
return section;
}
// modules/ui/entity_editor.js
function uiEntityEditor(context) {
var dispatch10 = dispatch_default("choose");
var _state = "select";
var _coalesceChanges = false;
var _modified = false;
var _base;
var _entityIDs;
var _activePresets = [];
var _newFeature;
var _sections;
function entityEditor(selection2) {
var combinedTags = utilCombinedTags(_entityIDs, context.graph());
var header = selection2.selectAll(".header").data([0]);
var headerEnter = header.enter().append("div").attr("class", "header fillL");
var direction = _mainLocalizer.textDirection() === "rtl" ? "forward" : "backward";
headerEnter.append("button").attr("class", "preset-reset preset-choose").attr("title", _t(`icons.${direction}`)).call(svgIcon(`#iD-icon-${direction}`));
headerEnter.append("button").attr("class", "close").attr("title", _t("icons.close")).on("click", function() {
context.enter(modeBrowse(context));
}).call(svgIcon(_modified ? "#iD-icon-apply" : "#iD-icon-close"));
headerEnter.append("h2");
header = header.merge(headerEnter);
header.selectAll("h2").html(_entityIDs.length === 1 ? _t.html("inspector.edit") : _t.html("inspector.edit_features"));
header.selectAll(".preset-reset").on("click", function() {
dispatch10.call("choose", this, _activePresets);
});
var body = selection2.selectAll(".inspector-body").data([0]);
var bodyEnter = body.enter().append("div").attr("class", "entity-editor inspector-body sep-top");
body = body.merge(bodyEnter);
if (!_sections) {
_sections = [
uiSectionSelectionList(context),
uiSectionFeatureType(context).on("choose", function(presets) {
dispatch10.call("choose", this, presets);
}),
uiSectionEntityIssues(context),
uiSectionPresetFields(context).on("change", changeTags).on("revert", revertTags),
uiSectionRawTagEditor("raw-tag-editor", context).on("change", changeTags),
uiSectionRawMemberEditor(context),
uiSectionRawMembershipEditor(context)
];
}
_sections.forEach(function(section) {
if (section.entityIDs) {
section.entityIDs(_entityIDs);
}
if (section.presets) {
section.presets(_activePresets);
}
if (section.tags) {
section.tags(combinedTags);
}
if (section.state) {
section.state(_state);
}
body.call(section.render);
});
context.history().on("change.entity-editor", historyChanged);
function historyChanged(difference) {
if (selection2.selectAll(".entity-editor").empty())
return;
if (_state === "hide")
return;
var significant = !difference || difference.didChange.properties || difference.didChange.addition || difference.didChange.deletion;
if (!significant)
return;
_entityIDs = _entityIDs.filter(context.hasEntity);
if (!_entityIDs.length)
return;
var priorActivePreset = _activePresets.length === 1 && _activePresets[0];
loadActivePresets();
var graph = context.graph();
entityEditor.modified(_base !== graph);
entityEditor(selection2);
if (priorActivePreset && _activePresets.length === 1 && priorActivePreset !== _activePresets[0]) {
context.container().selectAll(".entity-editor button.preset-reset .label").style("background-color", "#fff").transition().duration(750).style("background-color", null);
}
}
}
function changeTags(entityIDs, changed, onInput) {
var actions = [];
for (var i2 in entityIDs) {
var entityID = entityIDs[i2];
var entity = context.entity(entityID);
var tags = Object.assign({}, entity.tags);
for (var k in changed) {
if (!k)
continue;
var v = changed[k];
if (typeof v === "object") {
tags[k] = tags[v.oldKey];
} else if (v !== void 0 || tags.hasOwnProperty(k)) {
tags[k] = v;
}
}
if (!onInput) {
tags = utilCleanTags(tags);
}
if (!(0, import_fast_deep_equal10.default)(entity.tags, tags)) {
actions.push(actionChangeTags(entityID, tags));
}
}
if (actions.length) {
var combinedAction = function(graph) {
actions.forEach(function(action) {
graph = action(graph);
});
return graph;
};
var annotation = _t("operations.change_tags.annotation");
if (_coalesceChanges) {
context.overwrite(combinedAction, annotation);
} else {
context.perform(combinedAction, annotation);
_coalesceChanges = !!onInput;
}
}
if (!onInput) {
context.validator().validate();
}
}
function revertTags(keys) {
var actions = [];
for (var i2 in _entityIDs) {
var entityID = _entityIDs[i2];
var original = context.graph().base().entities[entityID];
var changed = {};
for (var j2 in keys) {
var key = keys[j2];
changed[key] = original ? original.tags[key] : void 0;
}
var entity = context.entity(entityID);
var tags = Object.assign({}, entity.tags);
for (var k in changed) {
if (!k)
continue;
var v = changed[k];
if (v !== void 0 || tags.hasOwnProperty(k)) {
tags[k] = v;
}
}
tags = utilCleanTags(tags);
if (!(0, import_fast_deep_equal10.default)(entity.tags, tags)) {
actions.push(actionChangeTags(entityID, tags));
}
}
if (actions.length) {
var combinedAction = function(graph) {
actions.forEach(function(action) {
graph = action(graph);
});
return graph;
};
var annotation = _t("operations.change_tags.annotation");
if (_coalesceChanges) {
context.overwrite(combinedAction, annotation);
} else {
context.perform(combinedAction, annotation);
_coalesceChanges = false;
}
}
context.validator().validate();
}
entityEditor.modified = function(val) {
if (!arguments.length)
return _modified;
_modified = val;
return entityEditor;
};
entityEditor.state = function(val) {
if (!arguments.length)
return _state;
_state = val;
return entityEditor;
};
entityEditor.entityIDs = function(val) {
if (!arguments.length)
return _entityIDs;
_base = context.graph();
_coalesceChanges = false;
if (val && _entityIDs && utilArrayIdentical(_entityIDs, val))
return entityEditor;
_entityIDs = val;
loadActivePresets(true);
return entityEditor.modified(false);
};
entityEditor.newFeature = function(val) {
if (!arguments.length)
return _newFeature;
_newFeature = val;
return entityEditor;
};
function loadActivePresets(isForNewSelection) {
var graph = context.graph();
var counts = {};
for (var i2 in _entityIDs) {
var entity = graph.hasEntity(_entityIDs[i2]);
if (!entity)
return;
var match = _mainPresetIndex.match(entity, graph);
if (!counts[match.id])
counts[match.id] = 0;
counts[match.id] += 1;
}
var matches = Object.keys(counts).sort(function(p1, p2) {
return counts[p2] - counts[p1];
}).map(function(pID) {
return _mainPresetIndex.item(pID);
});
if (!isForNewSelection) {
var weakPreset = _activePresets.length === 1 && !_activePresets[0].isFallback() && Object.keys(_activePresets[0].addTags || {}).length === 0;
if (weakPreset && matches.length === 1 && matches[0].isFallback())
return;
}
entityEditor.presets(matches);
}
entityEditor.presets = function(val) {
if (!arguments.length)
return _activePresets;
if (!utilArrayIdentical(val, _activePresets)) {
_activePresets = val;
}
return entityEditor;
};
return utilRebind(entityEditor, dispatch10, "on");
}
// modules/ui/feature_list.js
var sexagesimal = __toESM(require_sexagesimal());
function uiFeatureList(context) {
var _geocodeResults;
function featureList(selection2) {
var header = selection2.append("div").attr("class", "header fillL");
header.append("h2").call(_t.append("inspector.feature_list"));
var searchWrap = selection2.append("div").attr("class", "search-header");
searchWrap.call(svgIcon("#iD-icon-search", "pre-text"));
var search = searchWrap.append("input").attr("placeholder", _t("inspector.search")).attr("type", "search").call(utilNoAuto).on("keypress", keypress).on("keydown", keydown).on("input", inputevent);
var listWrap = selection2.append("div").attr("class", "inspector-body");
var list = listWrap.append("div").attr("class", "feature-list");
context.on("exit.feature-list", clearSearch);
context.map().on("drawn.feature-list", mapDrawn);
context.keybinding().on(uiCmd("\u2318F"), focusSearch);
function focusSearch(d3_event) {
var mode = context.mode() && context.mode().id;
if (mode !== "browse")
return;
d3_event.preventDefault();
search.node().focus();
}
function keydown(d3_event) {
if (d3_event.keyCode === 27) {
search.node().blur();
}
}
function keypress(d3_event) {
var q = search.property("value"), items = list.selectAll(".feature-list-item");
if (d3_event.keyCode === 13 && q.length && items.size()) {
click(d3_event, items.datum());
}
}
function inputevent() {
_geocodeResults = void 0;
drawList();
}
function clearSearch() {
search.property("value", "");
drawList();
}
function mapDrawn(e) {
if (e.full) {
drawList();
}
}
function features2() {
var result = [];
var graph = context.graph();
var visibleCenter = context.map().extent().center();
var q = search.property("value").toLowerCase();
if (!q)
return result;
var locationMatch = sexagesimal.pair(q.toUpperCase()) || q.match(/^(-?\d+\.?\d*)\s+(-?\d+\.?\d*)$/);
if (locationMatch) {
var loc = [parseFloat(locationMatch[0]), parseFloat(locationMatch[1])];
result.push({
id: -1,
geometry: "point",
type: _t("inspector.location"),
name: dmsCoordinatePair([loc[1], loc[0]]),
location: loc
});
}
var idMatch = !locationMatch && q.match(/(?:^|\W)(node|way|relation|[nwr])\W?0*([1-9]\d*)(?:\W|$)/i);
if (idMatch) {
var elemType = idMatch[1].charAt(0);
var elemId = idMatch[2];
result.push({
id: elemType + elemId,
geometry: elemType === "n" ? "point" : elemType === "w" ? "line" : "relation",
type: elemType === "n" ? _t("inspector.node") : elemType === "w" ? _t("inspector.way") : _t("inspector.relation"),
name: elemId
});
}
var allEntities = graph.entities;
var localResults = [];
for (var id2 in allEntities) {
var entity = allEntities[id2];
if (!entity)
continue;
var name2 = utilDisplayName(entity) || "";
if (name2.toLowerCase().indexOf(q) < 0)
continue;
var matched = _mainPresetIndex.match(entity, graph);
var type3 = matched && matched.name() || utilDisplayType(entity.id);
var extent = entity.extent(graph);
var distance = extent ? geoSphericalDistance(visibleCenter, extent.center()) : 0;
localResults.push({
id: entity.id,
entity,
geometry: entity.geometry(graph),
type: type3,
name: name2,
distance
});
if (localResults.length > 100)
break;
}
localResults = localResults.sort(function byDistance(a, b) {
return a.distance - b.distance;
});
result = result.concat(localResults);
(_geocodeResults || []).forEach(function(d) {
if (d.osm_type && d.osm_id) {
var id3 = osmEntity.id.fromOSM(d.osm_type, d.osm_id);
var tags = {};
tags[d.class] = d.type;
var attrs = { id: id3, type: d.osm_type, tags };
if (d.osm_type === "way") {
attrs.nodes = ["a", "a"];
}
var tempEntity = osmEntity(attrs);
var tempGraph = coreGraph([tempEntity]);
var matched2 = _mainPresetIndex.match(tempEntity, tempGraph);
var type4 = matched2 && matched2.name() || utilDisplayType(id3);
result.push({
id: tempEntity.id,
geometry: tempEntity.geometry(tempGraph),
type: type4,
name: d.display_name,
extent: new geoExtent([parseFloat(d.boundingbox[3]), parseFloat(d.boundingbox[0])], [parseFloat(d.boundingbox[2]), parseFloat(d.boundingbox[1])])
});
}
});
if (q.match(/^[0-9]+$/)) {
result.push({
id: "n" + q,
geometry: "point",
type: _t("inspector.node"),
name: q
});
result.push({
id: "w" + q,
geometry: "line",
type: _t("inspector.way"),
name: q
});
result.push({
id: "r" + q,
geometry: "relation",
type: _t("inspector.relation"),
name: q
});
}
return result;
}
function drawList() {
var value = search.property("value");
var results = features2();
list.classed("filtered", value.length);
var resultsIndicator = list.selectAll(".no-results-item").data([0]).enter().append("button").property("disabled", true).attr("class", "no-results-item").call(svgIcon("#iD-icon-alert", "pre-text"));
resultsIndicator.append("span").attr("class", "entity-name");
list.selectAll(".no-results-item .entity-name").html("").call(_t.append("geocoder.no_results_worldwide"));
if (services.geocoder) {
list.selectAll(".geocode-item").data([0]).enter().append("button").attr("class", "geocode-item secondary-action").on("click", geocoderSearch).append("div").attr("class", "label").append("span").attr("class", "entity-name").call(_t.append("geocoder.search"));
}
list.selectAll(".no-results-item").style("display", value.length && !results.length ? "block" : "none");
list.selectAll(".geocode-item").style("display", value && _geocodeResults === void 0 ? "block" : "none");
list.selectAll(".feature-list-item").data([-1]).remove();
var items = list.selectAll(".feature-list-item").data(results, function(d) {
return d.id;
});
var enter = items.enter().insert("button", ".geocode-item").attr("class", "feature-list-item").on("mouseover", mouseover).on("mouseout", mouseout).on("click", click);
var label = enter.append("div").attr("class", "label");
label.each(function(d) {
select_default2(this).call(svgIcon("#iD-icon-" + d.geometry, "pre-text"));
});
label.append("span").attr("class", "entity-type").text(function(d) {
return d.type;
});
label.append("span").attr("class", "entity-name").text(function(d) {
return d.name;
});
enter.style("opacity", 0).transition().style("opacity", 1);
items.order();
items.exit().remove();
}
function mouseover(d3_event, d) {
if (d.id === -1)
return;
utilHighlightEntities([d.id], true, context);
}
function mouseout(d3_event, d) {
if (d.id === -1)
return;
utilHighlightEntities([d.id], false, context);
}
function click(d3_event, d) {
d3_event.preventDefault();
if (d.location) {
context.map().centerZoomEase([d.location[1], d.location[0]], 19);
} else if (d.entity) {
utilHighlightEntities([d.id], false, context);
context.enter(modeSelect(context, [d.entity.id]));
context.map().zoomToEase(d.entity);
} else {
context.zoomToEntity(d.id);
}
}
function geocoderSearch() {
services.geocoder.search(search.property("value"), function(err, resp) {
_geocodeResults = resp || [];
drawList();
});
}
}
return featureList;
}
// modules/ui/improveOSM_comments.js
function uiImproveOsmComments() {
let _qaItem;
function issueComments(selection2) {
let comments = selection2.selectAll(".comments-container").data([0]);
comments = comments.enter().append("div").attr("class", "comments-container").merge(comments);
services.improveOSM.getComments(_qaItem).then((d) => {
if (!d.comments)
return;
const commentEnter = comments.selectAll(".comment").data(d.comments).enter().append("div").attr("class", "comment");
commentEnter.append("div").attr("class", "comment-avatar").call(svgIcon("#iD-icon-avatar", "comment-avatar-icon"));
const mainEnter = commentEnter.append("div").attr("class", "comment-main");
const metadataEnter = mainEnter.append("div").attr("class", "comment-metadata");
metadataEnter.append("div").attr("class", "comment-author").each(function(d2) {
const osm = services.osm;
let selection3 = select_default2(this);
if (osm && d2.username) {
selection3 = selection3.append("a").attr("class", "comment-author-link").attr("href", osm.userURL(d2.username)).attr("target", "_blank");
}
selection3.text((d4) => d4.username);
});
metadataEnter.append("div").attr("class", "comment-date").html((d2) => _t.html("note.status.commented", { when: localeDateString2(d2.timestamp) }));
mainEnter.append("div").attr("class", "comment-text").append("p").text((d2) => d2.text);
}).catch((err) => {
console.log(err);
});
}
function localeDateString2(s) {
if (!s)
return null;
const options2 = { day: "numeric", month: "short", year: "numeric" };
const d = new Date(s * 1e3);
if (isNaN(d.getTime()))
return null;
return d.toLocaleDateString(_mainLocalizer.localeCode(), options2);
}
issueComments.issue = function(val) {
if (!arguments.length)
return _qaItem;
_qaItem = val;
return issueComments;
};
return issueComments;
}
// modules/ui/improveOSM_details.js
function uiImproveOsmDetails(context) {
let _qaItem;
function issueDetail(d) {
if (d.desc)
return d.desc;
const issueKey = d.issueKey;
d.replacements = d.replacements || {};
d.replacements.default = { html: _t.html("inspector.unknown") };
return _t.html(`QA.improveOSM.error_types.${issueKey}.description`, d.replacements);
}
function improveOsmDetails(selection2) {
const details = selection2.selectAll(".error-details").data(_qaItem ? [_qaItem] : [], (d) => `${d.id}-${d.status || 0}`);
details.exit().remove();
const detailsEnter = details.enter().append("div").attr("class", "error-details qa-details-container");
const descriptionEnter = detailsEnter.append("div").attr("class", "qa-details-subsection");
descriptionEnter.append("h4").call(_t.append("QA.keepRight.detail_description"));
descriptionEnter.append("div").attr("class", "qa-details-description-text").html(issueDetail);
let relatedEntities = [];
descriptionEnter.selectAll(".error_entity_link, .error_object_link").attr("href", "#").each(function() {
const link2 = select_default2(this);
const isObjectLink = link2.classed("error_object_link");
const entityID = isObjectLink ? utilEntityRoot(_qaItem.objectType) + _qaItem.objectId : this.textContent;
const entity = context.hasEntity(entityID);
relatedEntities.push(entityID);
link2.on("mouseenter", () => {
utilHighlightEntities([entityID], true, context);
}).on("mouseleave", () => {
utilHighlightEntities([entityID], false, context);
}).on("click", (d3_event) => {
d3_event.preventDefault();
utilHighlightEntities([entityID], false, context);
const osmlayer = context.layers().layer("osm");
if (!osmlayer.enabled()) {
osmlayer.enabled(true);
}
context.map().centerZoom(_qaItem.loc, 20);
if (entity) {
context.enter(modeSelect(context, [entityID]));
} else {
context.loadEntity(entityID, (err, result) => {
if (err)
return;
const entity2 = result.data.find((e) => e.id === entityID);
if (entity2)
context.enter(modeSelect(context, [entityID]));
});
}
});
if (entity) {
let name2 = utilDisplayName(entity);
if (!name2 && !isObjectLink) {
const preset = _mainPresetIndex.match(entity, context.graph());
name2 = preset && !preset.isFallback() && preset.name();
}
if (name2) {
this.innerText = name2;
}
}
});
context.features().forceVisible(relatedEntities);
context.map().pan([0, 0]);
}
improveOsmDetails.issue = function(val) {
if (!arguments.length)
return _qaItem;
_qaItem = val;
return improveOsmDetails;
};
return improveOsmDetails;
}
// modules/ui/improveOSM_header.js
function uiImproveOsmHeader() {
let _qaItem;
function issueTitle(d) {
const issueKey = d.issueKey;
d.replacements = d.replacements || {};
d.replacements.default = { html: _t.html("inspector.unknown") };
return _t.html(`QA.improveOSM.error_types.${issueKey}.title`, d.replacements);
}
function improveOsmHeader(selection2) {
const header = selection2.selectAll(".qa-header").data(_qaItem ? [_qaItem] : [], (d) => `${d.id}-${d.status || 0}`);
header.exit().remove();
const headerEnter = header.enter().append("div").attr("class", "qa-header");
const svgEnter = headerEnter.append("div").attr("class", "qa-header-icon").classed("new", (d) => d.id < 0).append("svg").attr("width", "20px").attr("height", "30px").attr("viewbox", "0 0 20 30").attr("class", (d) => `preset-icon-28 qaItem ${d.service} itemId-${d.id} itemType-${d.itemType}`);
svgEnter.append("polygon").attr("fill", "currentColor").attr("class", "qaItem-fill").attr("points", "16,3 4,3 1,6 1,17 4,20 7,20 10,27 13,20 16,20 19,17.033 19,6");
svgEnter.append("use").attr("class", "icon-annotation").attr("width", "12px").attr("height", "12px").attr("transform", "translate(4, 5.5)").attr("xlink:href", (d) => d.icon ? "#" + d.icon : "");
headerEnter.append("div").attr("class", "qa-header-label").html(issueTitle);
}
improveOsmHeader.issue = function(val) {
if (!arguments.length)
return _qaItem;
_qaItem = val;
return improveOsmHeader;
};
return improveOsmHeader;
}
// modules/ui/improveOSM_editor.js
function uiImproveOsmEditor(context) {
const dispatch10 = dispatch_default("change");
const qaDetails = uiImproveOsmDetails(context);
const qaComments = uiImproveOsmComments(context);
const qaHeader = uiImproveOsmHeader(context);
let _qaItem;
function improveOsmEditor(selection2) {
const headerEnter = selection2.selectAll(".header").data([0]).enter().append("div").attr("class", "header fillL");
headerEnter.append("button").attr("class", "close").attr("title", _t("icons.close")).on("click", () => context.enter(modeBrowse(context))).call(svgIcon("#iD-icon-close"));
headerEnter.append("h2").call(_t.append("QA.improveOSM.title"));
let body = selection2.selectAll(".body").data([0]);
body = body.enter().append("div").attr("class", "body").merge(body);
const editor = body.selectAll(".qa-editor").data([0]);
editor.enter().append("div").attr("class", "modal-section qa-editor").merge(editor).call(qaHeader.issue(_qaItem)).call(qaDetails.issue(_qaItem)).call(qaComments.issue(_qaItem)).call(improveOsmSaveSection);
}
function improveOsmSaveSection(selection2) {
const isSelected = _qaItem && _qaItem.id === context.selectedErrorID();
const isShown = _qaItem && (isSelected || _qaItem.newComment || _qaItem.comment);
let saveSection = selection2.selectAll(".qa-save").data(isShown ? [_qaItem] : [], (d) => `${d.id}-${d.status || 0}`);
saveSection.exit().remove();
const saveSectionEnter = saveSection.enter().append("div").attr("class", "qa-save save-section cf");
saveSectionEnter.append("h4").attr("class", ".qa-save-header").call(_t.append("note.newComment"));
saveSectionEnter.append("textarea").attr("class", "new-comment-input").attr("placeholder", _t("QA.keepRight.comment_placeholder")).attr("maxlength", 1e3).property("value", (d) => d.newComment).call(utilNoAuto).on("input", changeInput).on("blur", changeInput);
saveSection = saveSectionEnter.merge(saveSection).call(qaSaveButtons);
function changeInput() {
const input = select_default2(this);
let val = input.property("value").trim();
if (val === "") {
val = void 0;
}
_qaItem = _qaItem.update({ newComment: val });
const qaService = services.improveOSM;
if (qaService) {
qaService.replaceItem(_qaItem);
}
saveSection.call(qaSaveButtons);
}
}
function qaSaveButtons(selection2) {
const isSelected = _qaItem && _qaItem.id === context.selectedErrorID();
let buttonSection = selection2.selectAll(".buttons").data(isSelected ? [_qaItem] : [], (d) => d.status + d.id);
buttonSection.exit().remove();
const buttonEnter = buttonSection.enter().append("div").attr("class", "buttons");
buttonEnter.append("button").attr("class", "button comment-button action").call(_t.append("QA.keepRight.save_comment"));
buttonEnter.append("button").attr("class", "button close-button action");
buttonEnter.append("button").attr("class", "button ignore-button action");
buttonSection = buttonSection.merge(buttonEnter);
buttonSection.select(".comment-button").attr("disabled", (d) => d.newComment ? null : true).on("click.comment", function(d3_event, d) {
this.blur();
const qaService = services.improveOSM;
if (qaService) {
qaService.postUpdate(d, (err, item) => dispatch10.call("change", item));
}
});
buttonSection.select(".close-button").html((d) => {
const andComment = d.newComment ? "_comment" : "";
return _t.html(`QA.keepRight.close${andComment}`);
}).on("click.close", function(d3_event, d) {
this.blur();
const qaService = services.improveOSM;
if (qaService) {
d.newStatus = "SOLVED";
qaService.postUpdate(d, (err, item) => dispatch10.call("change", item));
}
});
buttonSection.select(".ignore-button").html((d) => {
const andComment = d.newComment ? "_comment" : "";
return _t.html(`QA.keepRight.ignore${andComment}`);
}).on("click.ignore", function(d3_event, d) {
this.blur();
const qaService = services.improveOSM;
if (qaService) {
d.newStatus = "INVALID";
qaService.postUpdate(d, (err, item) => dispatch10.call("change", item));
}
});
}
improveOsmEditor.error = function(val) {
if (!arguments.length)
return _qaItem;
_qaItem = val;
return improveOsmEditor;
};
return utilRebind(improveOsmEditor, dispatch10, "on");
}
// modules/ui/preset_list.js
function uiPresetList(context) {
var dispatch10 = dispatch_default("cancel", "choose");
var _entityIDs;
var _currLoc;
var _currentPresets;
var _autofocus = false;
function presetList(selection2) {
if (!_entityIDs)
return;
var presets = _mainPresetIndex.matchAllGeometry(entityGeometries());
selection2.html("");
var messagewrap = selection2.append("div").attr("class", "header fillL");
var message = messagewrap.append("h2").call(_t.append("inspector.choose"));
var direction = _mainLocalizer.textDirection() === "rtl" ? "backward" : "forward";
messagewrap.append("button").attr("class", "preset-choose").attr("title", direction).on("click", function() {
dispatch10.call("cancel", this);
}).call(svgIcon(`#iD-icon-${direction}`));
function initialKeydown(d3_event) {
if (search.property("value").length === 0 && (d3_event.keyCode === utilKeybinding.keyCodes["\u232B"] || d3_event.keyCode === utilKeybinding.keyCodes["\u2326"])) {
d3_event.preventDefault();
d3_event.stopPropagation();
operationDelete(context, _entityIDs)();
} else if (search.property("value").length === 0 && (d3_event.ctrlKey || d3_event.metaKey) && d3_event.keyCode === utilKeybinding.keyCodes.z) {
d3_event.preventDefault();
d3_event.stopPropagation();
context.undo();
} else if (!d3_event.ctrlKey && !d3_event.metaKey) {
select_default2(this).on("keydown", keydown);
keydown.call(this, d3_event);
}
}
function keydown(d3_event) {
if (d3_event.keyCode === utilKeybinding.keyCodes["\u2193"] && search.node().selectionStart === search.property("value").length) {
d3_event.preventDefault();
d3_event.stopPropagation();
var buttons = list.selectAll(".preset-list-button");
if (!buttons.empty())
buttons.nodes()[0].focus();
}
}
function keypress(d3_event) {
var value = search.property("value");
if (d3_event.keyCode === 13 && value.length) {
list.selectAll(".preset-list-item:first-child").each(function(d) {
d.choose.call(this);
});
}
}
function inputevent() {
var value = search.property("value");
list.classed("filtered", value.length);
var results, messageText;
if (value.length) {
results = presets.search(value, entityGeometries()[0], _currLoc);
messageText = _t.html("inspector.results", {
n: results.collection.length,
search: value
});
} else {
results = _mainPresetIndex.defaults(entityGeometries()[0], 36, !context.inIntro(), _currLoc);
messageText = _t.html("inspector.choose");
}
list.call(drawList, results);
message.html(messageText);
}
var searchWrap = selection2.append("div").attr("class", "search-header");
searchWrap.call(svgIcon("#iD-icon-search", "pre-text"));
var search = searchWrap.append("input").attr("class", "preset-search-input").attr("placeholder", _t("inspector.search")).attr("type", "search").call(utilNoAuto).on("keydown", initialKeydown).on("keypress", keypress).on("input", debounce_default(inputevent));
if (_autofocus) {
search.node().focus();
setTimeout(function() {
search.node().focus();
}, 0);
}
var listWrap = selection2.append("div").attr("class", "inspector-body");
var list = listWrap.append("div").attr("class", "preset-list").call(drawList, _mainPresetIndex.defaults(entityGeometries()[0], 36, !context.inIntro(), _currLoc));
context.features().on("change.preset-list", updateForFeatureHiddenState);
}
function drawList(list, presets) {
presets = presets.matchAllGeometry(entityGeometries());
var collection = presets.collection.reduce(function(collection2, preset) {
if (!preset)
return collection2;
if (preset.members) {
if (preset.members.collection.filter(function(preset2) {
return preset2.addable();
}).length > 1) {
collection2.push(CategoryItem(preset));
}
} else if (preset.addable()) {
collection2.push(PresetItem(preset));
}
return collection2;
}, []);
var items = list.selectAll(".preset-list-item").data(collection, function(d) {
return d.preset.id;
});
items.order();
items.exit().remove();
items.enter().append("div").attr("class", function(item) {
return "preset-list-item preset-" + item.preset.id.replace("/", "-");
}).classed("current", function(item) {
return _currentPresets.indexOf(item.preset) !== -1;
}).each(function(item) {
select_default2(this).call(item);
}).style("opacity", 0).transition().style("opacity", 1);
updateForFeatureHiddenState();
}
function itemKeydown(d3_event) {
var item = select_default2(this.closest(".preset-list-item"));
var parentItem = select_default2(item.node().parentNode.closest(".preset-list-item"));
if (d3_event.keyCode === utilKeybinding.keyCodes["\u2193"]) {
d3_event.preventDefault();
d3_event.stopPropagation();
var nextItem = select_default2(item.node().nextElementSibling);
if (nextItem.empty()) {
if (!parentItem.empty()) {
nextItem = select_default2(parentItem.node().nextElementSibling);
}
} else if (select_default2(this).classed("expanded")) {
nextItem = item.select(".subgrid .preset-list-item:first-child");
}
if (!nextItem.empty()) {
nextItem.select(".preset-list-button").node().focus();
}
} else if (d3_event.keyCode === utilKeybinding.keyCodes["\u2191"]) {
d3_event.preventDefault();
d3_event.stopPropagation();
var previousItem = select_default2(item.node().previousElementSibling);
if (previousItem.empty()) {
if (!parentItem.empty()) {
previousItem = parentItem;
}
} else if (previousItem.select(".preset-list-button").classed("expanded")) {
previousItem = previousItem.select(".subgrid .preset-list-item:last-child");
}
if (!previousItem.empty()) {
previousItem.select(".preset-list-button").node().focus();
} else {
var search = select_default2(this.closest(".preset-list-pane")).select(".preset-search-input");
search.node().focus();
}
} else if (d3_event.keyCode === utilKeybinding.keyCodes[_mainLocalizer.textDirection() === "rtl" ? "\u2192" : "\u2190"]) {
d3_event.preventDefault();
d3_event.stopPropagation();
if (!parentItem.empty()) {
parentItem.select(".preset-list-button").node().focus();
}
} else if (d3_event.keyCode === utilKeybinding.keyCodes[_mainLocalizer.textDirection() === "rtl" ? "\u2190" : "\u2192"]) {
d3_event.preventDefault();
d3_event.stopPropagation();
item.datum().choose.call(select_default2(this).node());
}
}
function CategoryItem(preset) {
var box, sublist, shown = false;
function item(selection2) {
var wrap2 = selection2.append("div").attr("class", "preset-list-button-wrap category");
function click() {
var isExpanded = select_default2(this).classed("expanded");
var iconName = isExpanded ? _mainLocalizer.textDirection() === "rtl" ? "#iD-icon-backward" : "#iD-icon-forward" : "#iD-icon-down";
select_default2(this).classed("expanded", !isExpanded).attr("title", !isExpanded ? _t("icons.collapse") : _t("icons.expand"));
select_default2(this).selectAll("div.label-inner svg.icon use").attr("href", iconName);
item.choose();
}
var geometries = entityGeometries();
var button = wrap2.append("button").attr("class", "preset-list-button").attr("title", _t("icons.expand")).classed("expanded", false).call(uiPresetIcon().geometry(geometries.length === 1 && geometries[0]).preset(preset)).on("click", click).on("keydown", function(d3_event) {
if (d3_event.keyCode === utilKeybinding.keyCodes[_mainLocalizer.textDirection() === "rtl" ? "\u2190" : "\u2192"]) {
d3_event.preventDefault();
d3_event.stopPropagation();
if (!select_default2(this).classed("expanded")) {
click.call(this, d3_event);
}
} else if (d3_event.keyCode === utilKeybinding.keyCodes[_mainLocalizer.textDirection() === "rtl" ? "\u2192" : "\u2190"]) {
d3_event.preventDefault();
d3_event.stopPropagation();
if (select_default2(this).classed("expanded")) {
click.call(this, d3_event);
}
} else {
itemKeydown.call(this, d3_event);
}
});
var label = button.append("div").attr("class", "label").append("div").attr("class", "label-inner");
label.append("div").attr("class", "namepart").call(svgIcon(_mainLocalizer.textDirection() === "rtl" ? "#iD-icon-backward" : "#iD-icon-forward", "inline")).append("span").html(function() {
return preset.nameLabel() + "…";
});
box = selection2.append("div").attr("class", "subgrid").style("max-height", "0px").style("opacity", 0);
box.append("div").attr("class", "arrow");
sublist = box.append("div").attr("class", "preset-list fillL3");
}
item.choose = function() {
if (!box || !sublist)
return;
if (shown) {
shown = false;
box.transition().duration(200).style("opacity", "0").style("max-height", "0px").style("padding-bottom", "0px");
} else {
shown = true;
var members = preset.members.matchAllGeometry(entityGeometries());
sublist.call(drawList, members);
box.transition().duration(200).style("opacity", "1").style("max-height", 200 + members.collection.length * 190 + "px").style("padding-bottom", "10px");
}
};
item.preset = preset;
return item;
}
function PresetItem(preset) {
function item(selection2) {
var wrap2 = selection2.append("div").attr("class", "preset-list-button-wrap");
var geometries = entityGeometries();
var button = wrap2.append("button").attr("class", "preset-list-button").call(uiPresetIcon().geometry(geometries.length === 1 && geometries[0]).preset(preset)).on("click", item.choose).on("keydown", itemKeydown);
var label = button.append("div").attr("class", "label").append("div").attr("class", "label-inner");
var nameparts = [
preset.nameLabel(),
preset.subtitleLabel()
].filter(Boolean);
label.selectAll(".namepart").data(nameparts).enter().append("div").attr("class", "namepart").html(function(d) {
return d;
});
wrap2.call(item.reference.button);
selection2.call(item.reference.body);
}
item.choose = function() {
if (select_default2(this).classed("disabled"))
return;
if (!context.inIntro()) {
_mainPresetIndex.setMostRecent(preset, entityGeometries()[0]);
}
context.perform(function(graph) {
for (var i2 in _entityIDs) {
var entityID = _entityIDs[i2];
var oldPreset = _mainPresetIndex.match(graph.entity(entityID), graph);
graph = actionChangePreset(entityID, oldPreset, preset)(graph);
}
return graph;
}, _t("operations.change_tags.annotation"));
context.validator().validate();
dispatch10.call("choose", this, preset);
};
item.help = function(d3_event) {
d3_event.stopPropagation();
item.reference.toggle();
};
item.preset = preset;
item.reference = uiTagReference(preset.reference(), context);
return item;
}
function updateForFeatureHiddenState() {
if (!_entityIDs.every(context.hasEntity))
return;
var geometries = entityGeometries();
var button = context.container().selectAll(".preset-list .preset-list-button");
button.call(uiTooltip().destroyAny);
button.each(function(item, index) {
var hiddenPresetFeaturesId;
for (var i2 in geometries) {
hiddenPresetFeaturesId = context.features().isHiddenPreset(item.preset, geometries[i2]);
if (hiddenPresetFeaturesId)
break;
}
var isHiddenPreset = !context.inIntro() && !!hiddenPresetFeaturesId && (_currentPresets.length !== 1 || item.preset !== _currentPresets[0]);
select_default2(this).classed("disabled", isHiddenPreset);
if (isHiddenPreset) {
var isAutoHidden = context.features().autoHidden(hiddenPresetFeaturesId);
select_default2(this).call(uiTooltip().title(_t.html("inspector.hidden_preset." + (isAutoHidden ? "zoom" : "manual"), {
features: { html: _t.html("feature." + hiddenPresetFeaturesId + ".description") }
})).placement(index < 2 ? "bottom" : "top"));
}
});
}
presetList.autofocus = function(val) {
if (!arguments.length)
return _autofocus;
_autofocus = val;
return presetList;
};
presetList.entityIDs = function(val) {
if (!arguments.length)
return _entityIDs;
_entityIDs = val;
_currLoc = null;
if (_entityIDs && _entityIDs.length) {
const extent = _entityIDs.reduce(function(extent2, entityID) {
var entity = context.graph().entity(entityID);
return extent2.extend(entity.extent(context.graph()));
}, geoExtent());
_currLoc = extent.center();
var presets = _entityIDs.map(function(entityID) {
return _mainPresetIndex.match(context.entity(entityID), context.graph());
});
presetList.presets(presets);
}
return presetList;
};
presetList.presets = function(val) {
if (!arguments.length)
return _currentPresets;
_currentPresets = val;
return presetList;
};
function entityGeometries() {
var counts = {};
for (var i2 in _entityIDs) {
var entityID = _entityIDs[i2];
var entity = context.entity(entityID);
var geometry = entity.geometry(context.graph());
if (geometry === "vertex" && entity.isOnAddressLine(context.graph())) {
geometry = "point";
}
if (!counts[geometry])
counts[geometry] = 0;
counts[geometry] += 1;
}
return Object.keys(counts).sort(function(geom1, geom2) {
return counts[geom2] - counts[geom1];
});
}
return utilRebind(presetList, dispatch10, "on");
}
// modules/ui/view_on_osm.js
function uiViewOnOSM(context) {
var _what;
function viewOnOSM(selection2) {
var url;
if (_what instanceof osmEntity) {
url = context.connection().entityURL(_what);
} else if (_what instanceof osmNote) {
url = context.connection().noteURL(_what);
}
var data = !_what || _what.isNew() ? [] : [_what];
var link2 = selection2.selectAll(".view-on-osm").data(data, function(d) {
return d.id;
});
link2.exit().remove();
var linkEnter = link2.enter().append("a").attr("class", "view-on-osm").attr("target", "_blank").attr("href", url).call(svgIcon("#iD-icon-out-link", "inline"));
linkEnter.append("span").call(_t.append("inspector.view_on_osm"));
}
viewOnOSM.what = function(_) {
if (!arguments.length)
return _what;
_what = _;
return viewOnOSM;
};
return viewOnOSM;
}
// modules/ui/inspector.js
function uiInspector(context) {
var presetList = uiPresetList(context);
var entityEditor = uiEntityEditor(context);
var wrap2 = select_default2(null), presetPane = select_default2(null), editorPane = select_default2(null);
var _state = "select";
var _entityIDs;
var _newFeature = false;
function inspector(selection2) {
presetList.entityIDs(_entityIDs).autofocus(_newFeature).on("choose", inspector.setPreset).on("cancel", function() {
inspector.setPreset();
});
entityEditor.state(_state).entityIDs(_entityIDs).on("choose", inspector.showList);
wrap2 = selection2.selectAll(".panewrap").data([0]);
var enter = wrap2.enter().append("div").attr("class", "panewrap");
enter.append("div").attr("class", "preset-list-pane pane");
enter.append("div").attr("class", "entity-editor-pane pane");
wrap2 = wrap2.merge(enter);
presetPane = wrap2.selectAll(".preset-list-pane");
editorPane = wrap2.selectAll(".entity-editor-pane");
function shouldDefaultToPresetList() {
if (_state !== "select")
return false;
if (_entityIDs.length !== 1)
return false;
var entityID = _entityIDs[0];
var entity = context.hasEntity(entityID);
if (!entity)
return false;
if (entity.hasNonGeometryTags())
return false;
if (_newFeature)
return true;
if (entity.geometry(context.graph()) !== "vertex")
return false;
if (context.graph().parentRelations(entity).length)
return false;
if (context.validator().getEntityIssues(entityID).length)
return false;
if (entity.isHighwayIntersection(context.graph()))
return false;
return true;
}
if (shouldDefaultToPresetList()) {
wrap2.style("right", "-100%");
editorPane.classed("hide", true);
presetPane.classed("hide", false).call(presetList);
} else {
wrap2.style("right", "0%");
presetPane.classed("hide", true);
editorPane.classed("hide", false).call(entityEditor);
}
var footer = selection2.selectAll(".footer").data([0]);
footer = footer.enter().append("div").attr("class", "footer").merge(footer);
footer.call(uiViewOnOSM(context).what(context.hasEntity(_entityIDs.length === 1 && _entityIDs[0])));
}
inspector.showList = function(presets) {
presetPane.classed("hide", false);
wrap2.transition().styleTween("right", function() {
return value_default("0%", "-100%");
}).on("end", function() {
editorPane.classed("hide", true);
});
if (presets) {
presetList.presets(presets);
}
presetPane.call(presetList.autofocus(true));
};
inspector.setPreset = function(preset) {
if (preset && preset.id === "type/multipolygon") {
presetPane.call(presetList.autofocus(true));
} else {
editorPane.classed("hide", false);
wrap2.transition().styleTween("right", function() {
return value_default("-100%", "0%");
}).on("end", function() {
presetPane.classed("hide", true);
});
if (preset) {
entityEditor.presets([preset]);
}
editorPane.call(entityEditor);
}
};
inspector.state = function(val) {
if (!arguments.length)
return _state;
_state = val;
entityEditor.state(_state);
context.container().selectAll(".field-help-body").remove();
return inspector;
};
inspector.entityIDs = function(val) {
if (!arguments.length)
return _entityIDs;
_entityIDs = val;
return inspector;
};
inspector.newFeature = function(val) {
if (!arguments.length)
return _newFeature;
_newFeature = val;
return inspector;
};
return inspector;
}
// modules/ui/keepRight_details.js
function uiKeepRightDetails(context) {
let _qaItem;
function issueDetail(d) {
const { itemType, parentIssueType } = d;
const unknown = { html: _t.html("inspector.unknown") };
let replacements = d.replacements || {};
replacements.default = unknown;
if (_mainLocalizer.hasTextForStringId(`QA.keepRight.errorTypes.${itemType}.title`)) {
return _t.html(`QA.keepRight.errorTypes.${itemType}.description`, replacements);
} else {
return _t.html(`QA.keepRight.errorTypes.${parentIssueType}.description`, replacements);
}
}
function keepRightDetails(selection2) {
const details = selection2.selectAll(".error-details").data(_qaItem ? [_qaItem] : [], (d) => `${d.id}-${d.status || 0}`);
details.exit().remove();
const detailsEnter = details.enter().append("div").attr("class", "error-details qa-details-container");
const descriptionEnter = detailsEnter.append("div").attr("class", "qa-details-subsection");
descriptionEnter.append("h4").call(_t.append("QA.keepRight.detail_description"));
descriptionEnter.append("div").attr("class", "qa-details-description-text").html(issueDetail);
let relatedEntities = [];
descriptionEnter.selectAll(".error_entity_link, .error_object_link").attr("href", "#").each(function() {
const link2 = select_default2(this);
const isObjectLink = link2.classed("error_object_link");
const entityID = isObjectLink ? utilEntityRoot(_qaItem.objectType) + _qaItem.objectId : this.textContent;
const entity = context.hasEntity(entityID);
relatedEntities.push(entityID);
link2.on("mouseenter", () => {
utilHighlightEntities([entityID], true, context);
}).on("mouseleave", () => {
utilHighlightEntities([entityID], false, context);
}).on("click", (d3_event) => {
d3_event.preventDefault();
utilHighlightEntities([entityID], false, context);
const osmlayer = context.layers().layer("osm");
if (!osmlayer.enabled()) {
osmlayer.enabled(true);
}
context.map().centerZoomEase(_qaItem.loc, 20);
if (entity) {
context.enter(modeSelect(context, [entityID]));
} else {
context.loadEntity(entityID, (err, result) => {
if (err)
return;
const entity2 = result.data.find((e) => e.id === entityID);
if (entity2)
context.enter(modeSelect(context, [entityID]));
});
}
});
if (entity) {
let name2 = utilDisplayName(entity);
if (!name2 && !isObjectLink) {
const preset = _mainPresetIndex.match(entity, context.graph());
name2 = preset && !preset.isFallback() && preset.name();
}
if (name2) {
this.innerText = name2;
}
}
});
context.features().forceVisible(relatedEntities);
context.map().pan([0, 0]);
}
keepRightDetails.issue = function(val) {
if (!arguments.length)
return _qaItem;
_qaItem = val;
return keepRightDetails;
};
return keepRightDetails;
}
// modules/ui/keepRight_header.js
function uiKeepRightHeader() {
let _qaItem;
function issueTitle(d) {
const { itemType, parentIssueType } = d;
const unknown = _t.html("inspector.unknown");
let replacements = d.replacements || {};
replacements.default = { html: unknown };
if (_mainLocalizer.hasTextForStringId(`QA.keepRight.errorTypes.${itemType}.title`)) {
return _t.html(`QA.keepRight.errorTypes.${itemType}.title`, replacements);
} else {
return _t.html(`QA.keepRight.errorTypes.${parentIssueType}.title`, replacements);
}
}
function keepRightHeader(selection2) {
const header = selection2.selectAll(".qa-header").data(_qaItem ? [_qaItem] : [], (d) => `${d.id}-${d.status || 0}`);
header.exit().remove();
const headerEnter = header.enter().append("div").attr("class", "qa-header");
const iconEnter = headerEnter.append("div").attr("class", "qa-header-icon").classed("new", (d) => d.id < 0);
iconEnter.append("div").attr("class", (d) => `preset-icon-28 qaItem ${d.service} itemId-${d.id} itemType-${d.parentIssueType}`).call(svgIcon("#iD-icon-bolt", "qaItem-fill"));
headerEnter.append("div").attr("class", "qa-header-label").html(issueTitle);
}
keepRightHeader.issue = function(val) {
if (!arguments.length)
return _qaItem;
_qaItem = val;
return keepRightHeader;
};
return keepRightHeader;
}
// modules/ui/view_on_keepRight.js
function uiViewOnKeepRight() {
let _qaItem;
function viewOnKeepRight(selection2) {
let url;
if (services.keepRight && _qaItem instanceof QAItem) {
url = services.keepRight.issueURL(_qaItem);
}
const link2 = selection2.selectAll(".view-on-keepRight").data(url ? [url] : []);
link2.exit().remove();
const linkEnter = link2.enter().append("a").attr("class", "view-on-keepRight").attr("target", "_blank").attr("rel", "noopener").attr("href", (d) => d).call(svgIcon("#iD-icon-out-link", "inline"));
linkEnter.append("span").call(_t.append("inspector.view_on_keepRight"));
}
viewOnKeepRight.what = function(val) {
if (!arguments.length)
return _qaItem;
_qaItem = val;
return viewOnKeepRight;
};
return viewOnKeepRight;
}
// modules/ui/keepRight_editor.js
function uiKeepRightEditor(context) {
const dispatch10 = dispatch_default("change");
const qaDetails = uiKeepRightDetails(context);
const qaHeader = uiKeepRightHeader(context);
let _qaItem;
function keepRightEditor(selection2) {
const headerEnter = selection2.selectAll(".header").data([0]).enter().append("div").attr("class", "header fillL");
headerEnter.append("button").attr("class", "close").attr("title", _t("icons.close")).on("click", () => context.enter(modeBrowse(context))).call(svgIcon("#iD-icon-close"));
headerEnter.append("h2").call(_t.append("QA.keepRight.title"));
let body = selection2.selectAll(".body").data([0]);
body = body.enter().append("div").attr("class", "body").merge(body);
const editor = body.selectAll(".qa-editor").data([0]);
editor.enter().append("div").attr("class", "modal-section qa-editor").merge(editor).call(qaHeader.issue(_qaItem)).call(qaDetails.issue(_qaItem)).call(keepRightSaveSection);
const footer = selection2.selectAll(".footer").data([0]);
footer.enter().append("div").attr("class", "footer").merge(footer).call(uiViewOnKeepRight(context).what(_qaItem));
}
function keepRightSaveSection(selection2) {
const isSelected = _qaItem && _qaItem.id === context.selectedErrorID();
const isShown = _qaItem && (isSelected || _qaItem.newComment || _qaItem.comment);
let saveSection = selection2.selectAll(".qa-save").data(isShown ? [_qaItem] : [], (d) => `${d.id}-${d.status || 0}`);
saveSection.exit().remove();
const saveSectionEnter = saveSection.enter().append("div").attr("class", "qa-save save-section cf");
saveSectionEnter.append("h4").attr("class", ".qa-save-header").call(_t.append("QA.keepRight.comment"));
saveSectionEnter.append("textarea").attr("class", "new-comment-input").attr("placeholder", _t("QA.keepRight.comment_placeholder")).attr("maxlength", 1e3).property("value", (d) => d.newComment || d.comment).call(utilNoAuto).on("input", changeInput).on("blur", changeInput);
saveSection = saveSectionEnter.merge(saveSection).call(qaSaveButtons);
function changeInput() {
const input = select_default2(this);
let val = input.property("value").trim();
if (val === _qaItem.comment) {
val = void 0;
}
_qaItem = _qaItem.update({ newComment: val });
const qaService = services.keepRight;
if (qaService) {
qaService.replaceItem(_qaItem);
}
saveSection.call(qaSaveButtons);
}
}
function qaSaveButtons(selection2) {
const isSelected = _qaItem && _qaItem.id === context.selectedErrorID();
let buttonSection = selection2.selectAll(".buttons").data(isSelected ? [_qaItem] : [], (d) => d.status + d.id);
buttonSection.exit().remove();
const buttonEnter = buttonSection.enter().append("div").attr("class", "buttons");
buttonEnter.append("button").attr("class", "button comment-button action").call(_t.append("QA.keepRight.save_comment"));
buttonEnter.append("button").attr("class", "button close-button action");
buttonEnter.append("button").attr("class", "button ignore-button action");
buttonSection = buttonSection.merge(buttonEnter);
buttonSection.select(".comment-button").attr("disabled", (d) => d.newComment ? null : true).on("click.comment", function(d3_event, d) {
this.blur();
const qaService = services.keepRight;
if (qaService) {
qaService.postUpdate(d, (err, item) => dispatch10.call("change", item));
}
});
buttonSection.select(".close-button").html((d) => {
const andComment = d.newComment ? "_comment" : "";
return _t.html(`QA.keepRight.close${andComment}`);
}).on("click.close", function(d3_event, d) {
this.blur();
const qaService = services.keepRight;
if (qaService) {
d.newStatus = "ignore_t";
qaService.postUpdate(d, (err, item) => dispatch10.call("change", item));
}
});
buttonSection.select(".ignore-button").html((d) => {
const andComment = d.newComment ? "_comment" : "";
return _t.html(`QA.keepRight.ignore${andComment}`);
}).on("click.ignore", function(d3_event, d) {
this.blur();
const qaService = services.keepRight;
if (qaService) {
d.newStatus = "ignore";
qaService.postUpdate(d, (err, item) => dispatch10.call("change", item));
}
});
}
keepRightEditor.error = function(val) {
if (!arguments.length)
return _qaItem;
_qaItem = val;
return keepRightEditor;
};
return utilRebind(keepRightEditor, dispatch10, "on");
}
// modules/ui/lasso.js
function uiLasso(context) {
var group, polygon2;
lasso.coordinates = [];
function lasso(selection2) {
context.container().classed("lasso", true);
group = selection2.append("g").attr("class", "lasso hide");
polygon2 = group.append("path").attr("class", "lasso-path");
group.call(uiToggle(true));
}
function draw() {
if (polygon2) {
polygon2.data([lasso.coordinates]).attr("d", function(d) {
return "M" + d.join(" L") + " Z";
});
}
}
lasso.extent = function() {
return lasso.coordinates.reduce(function(extent, point) {
return extent.extend(geoExtent(point));
}, geoExtent());
};
lasso.p = function(_) {
if (!arguments.length)
return lasso;
lasso.coordinates.push(_);
draw();
return lasso;
};
lasso.close = function() {
if (group) {
group.call(uiToggle(false, function() {
select_default2(this).remove();
}));
}
context.container().classed("lasso", false);
};
return lasso;
}
// modules/ui/note_comments.js
function uiNoteComments() {
var _note;
function noteComments(selection2) {
if (_note.isNew())
return;
var comments = selection2.selectAll(".comments-container").data([0]);
comments = comments.enter().append("div").attr("class", "comments-container").merge(comments);
var commentEnter = comments.selectAll(".comment").data(_note.comments).enter().append("div").attr("class", "comment");
commentEnter.append("div").attr("class", function(d) {
return "comment-avatar user-" + d.uid;
}).call(svgIcon("#iD-icon-avatar", "comment-avatar-icon"));
var mainEnter = commentEnter.append("div").attr("class", "comment-main");
var metadataEnter = mainEnter.append("div").attr("class", "comment-metadata");
metadataEnter.append("div").attr("class", "comment-author").each(function(d) {
var selection3 = select_default2(this);
var osm = services.osm;
if (osm && d.user) {
selection3 = selection3.append("a").attr("class", "comment-author-link").attr("href", osm.userURL(d.user)).attr("target", "_blank");
}
if (d.user) {
selection3.text(d.user);
} else {
selection3.call(_t.append("note.anonymous"));
}
});
metadataEnter.append("div").attr("class", "comment-date").html(function(d) {
return _t.html("note.status." + d.action, { when: localeDateString2(d.date) });
});
mainEnter.append("div").attr("class", "comment-text").html(function(d) {
return d.html;
}).selectAll("a").attr("rel", "noopener nofollow").attr("target", "_blank");
comments.call(replaceAvatars);
}
function replaceAvatars(selection2) {
var showThirdPartyIcons = corePreferences("preferences.privacy.thirdpartyicons") || "true";
var osm = services.osm;
if (showThirdPartyIcons !== "true" || !osm)
return;
var uids = {};
_note.comments.forEach(function(d) {
if (d.uid)
uids[d.uid] = true;
});
Object.keys(uids).forEach(function(uid) {
osm.loadUser(uid, function(err, user) {
if (!user || !user.image_url)
return;
selection2.selectAll(".comment-avatar.user-" + uid).html("").append("img").attr("class", "icon comment-avatar-icon").attr("src", user.image_url).attr("alt", user.display_name);
});
});
}
function localeDateString2(s) {
if (!s)
return null;
var options2 = { day: "numeric", month: "short", year: "numeric" };
s = s.replace(/-/g, "/");
var d = new Date(s);
if (isNaN(d.getTime()))
return null;
return d.toLocaleDateString(_mainLocalizer.localeCode(), options2);
}
noteComments.note = function(val) {
if (!arguments.length)
return _note;
_note = val;
return noteComments;
};
return noteComments;
}
// modules/ui/note_header.js
function uiNoteHeader() {
var _note;
function noteHeader(selection2) {
var header = selection2.selectAll(".note-header").data(_note ? [_note] : [], function(d) {
return d.status + d.id;
});
header.exit().remove();
var headerEnter = header.enter().append("div").attr("class", "note-header");
var iconEnter = headerEnter.append("div").attr("class", function(d) {
return "note-header-icon " + d.status;
}).classed("new", function(d) {
return d.id < 0;
});
iconEnter.append("div").attr("class", "preset-icon-28").call(svgIcon("#iD-icon-note", "note-fill"));
iconEnter.each(function(d) {
var statusIcon;
if (d.id < 0) {
statusIcon = "#iD-icon-plus";
} else if (d.status === "open") {
statusIcon = "#iD-icon-close";
} else {
statusIcon = "#iD-icon-apply";
}
iconEnter.append("div").attr("class", "note-icon-annotation").attr("title", _t("icons.close")).call(svgIcon(statusIcon, "icon-annotation"));
});
headerEnter.append("div").attr("class", "note-header-label").html(function(d) {
if (_note.isNew()) {
return _t.html("note.new");
}
return _t.html("note.note") + " " + d.id + " " + (d.status === "closed" ? _t.html("note.closed") : "");
});
}
noteHeader.note = function(val) {
if (!arguments.length)
return _note;
_note = val;
return noteHeader;
};
return noteHeader;
}
// modules/ui/note_report.js
function uiNoteReport() {
var _note;
function noteReport(selection2) {
var url;
if (services.osm && _note instanceof osmNote && !_note.isNew()) {
url = services.osm.noteReportURL(_note);
}
var link2 = selection2.selectAll(".note-report").data(url ? [url] : []);
link2.exit().remove();
var linkEnter = link2.enter().append("a").attr("class", "note-report").attr("target", "_blank").attr("href", function(d) {
return d;
}).call(svgIcon("#iD-icon-out-link", "inline"));
linkEnter.append("span").call(_t.append("note.report"));
}
noteReport.note = function(val) {
if (!arguments.length)
return _note;
_note = val;
return noteReport;
};
return noteReport;
}
// modules/ui/note_editor.js
function uiNoteEditor(context) {
var dispatch10 = dispatch_default("change");
var noteComments = uiNoteComments(context);
var noteHeader = uiNoteHeader();
var _note;
var _newNote;
function noteEditor(selection2) {
var header = selection2.selectAll(".header").data([0]);
var headerEnter = header.enter().append("div").attr("class", "header fillL");
headerEnter.append("button").attr("class", "close").attr("title", _t("icons.close")).on("click", function() {
context.enter(modeBrowse(context));
}).call(svgIcon("#iD-icon-close"));
headerEnter.append("h2").call(_t.append("note.title"));
var body = selection2.selectAll(".body").data([0]);
body = body.enter().append("div").attr("class", "body").merge(body);
var editor = body.selectAll(".note-editor").data([0]);
editor.enter().append("div").attr("class", "modal-section note-editor").merge(editor).call(noteHeader.note(_note)).call(noteComments.note(_note)).call(noteSaveSection);
var footer = selection2.selectAll(".footer").data([0]);
footer.enter().append("div").attr("class", "footer").merge(footer).call(uiViewOnOSM(context).what(_note)).call(uiNoteReport(context).note(_note));
var osm = services.osm;
if (osm) {
osm.on("change.note-save", function() {
selection2.call(noteEditor);
});
}
}
function noteSaveSection(selection2) {
var isSelected = _note && _note.id === context.selectedNoteID();
var noteSave = selection2.selectAll(".note-save").data(isSelected ? [_note] : [], function(d) {
return d.status + d.id;
});
noteSave.exit().remove();
var noteSaveEnter = noteSave.enter().append("div").attr("class", "note-save save-section cf");
noteSaveEnter.append("h4").attr("class", ".note-save-header").html(function() {
return _note.isNew() ? _t.html("note.newDescription") : _t.html("note.newComment");
});
var commentTextarea = noteSaveEnter.append("textarea").attr("class", "new-comment-input").attr("placeholder", _t("note.inputPlaceholder")).attr("maxlength", 1e3).property("value", function(d) {
return d.newComment;
}).call(utilNoAuto).on("keydown.note-input", keydown).on("input.note-input", changeInput).on("blur.note-input", changeInput);
if (!commentTextarea.empty() && _newNote) {
commentTextarea.node().focus();
}
noteSave = noteSaveEnter.merge(noteSave).call(userDetails).call(noteSaveButtons);
function keydown(d3_event) {
if (!(d3_event.keyCode === 13 && d3_event.metaKey))
return;
var osm = services.osm;
if (!osm)
return;
var hasAuth = osm.authenticated();
if (!hasAuth)
return;
if (!_note.newComment)
return;
d3_event.preventDefault();
select_default2(this).on("keydown.note-input", null);
window.setTimeout(function() {
if (_note.isNew()) {
noteSave.selectAll(".save-button").node().focus();
clickSave(_note);
} else {
noteSave.selectAll(".comment-button").node().focus();
clickComment(_note);
}
}, 10);
}
function changeInput() {
var input = select_default2(this);
var val = input.property("value").trim() || void 0;
_note = _note.update({ newComment: val });
var osm = services.osm;
if (osm) {
osm.replaceNote(_note);
}
noteSave.call(noteSaveButtons);
}
}
function userDetails(selection2) {
var detailSection = selection2.selectAll(".detail-section").data([0]);
detailSection = detailSection.enter().append("div").attr("class", "detail-section").merge(detailSection);
var osm = services.osm;
if (!osm)
return;
var hasAuth = osm.authenticated();
var authWarning = detailSection.selectAll(".auth-warning").data(hasAuth ? [] : [0]);
authWarning.exit().transition().duration(200).style("opacity", 0).remove();
var authEnter = authWarning.enter().insert("div", ".tag-reference-body").attr("class", "field-warning auth-warning").style("opacity", 0);
authEnter.call(svgIcon("#iD-icon-alert", "inline"));
authEnter.append("span").call(_t.append("note.login"));
authEnter.append("a").attr("target", "_blank").call(svgIcon("#iD-icon-out-link", "inline")).append("span").call(_t.append("login")).on("click.note-login", function(d3_event) {
d3_event.preventDefault();
osm.authenticate();
});
authEnter.transition().duration(200).style("opacity", 1);
var prose = detailSection.selectAll(".note-save-prose").data(hasAuth ? [0] : []);
prose.exit().remove();
prose = prose.enter().append("p").attr("class", "note-save-prose").call(_t.append("note.upload_explanation")).merge(prose);
osm.userDetails(function(err, user) {
if (err)
return;
var userLink = select_default2(document.createElement("div"));
if (user.image_url) {
userLink.append("img").attr("src", user.image_url).attr("class", "icon pre-text user-icon");
}
userLink.append("a").attr("class", "user-info").text(user.display_name).attr("href", osm.userURL(user.display_name)).attr("target", "_blank");
prose.html(_t.html("note.upload_explanation_with_user", { user: { html: userLink.html() } }));
});
}
function noteSaveButtons(selection2) {
var osm = services.osm;
var hasAuth = osm && osm.authenticated();
var isSelected = _note && _note.id === context.selectedNoteID();
var buttonSection = selection2.selectAll(".buttons").data(isSelected ? [_note] : [], function(d) {
return d.status + d.id;
});
buttonSection.exit().remove();
var buttonEnter = buttonSection.enter().append("div").attr("class", "buttons");
if (_note.isNew()) {
buttonEnter.append("button").attr("class", "button cancel-button secondary-action").call(_t.append("confirm.cancel"));
buttonEnter.append("button").attr("class", "button save-button action").call(_t.append("note.save"));
} else {
buttonEnter.append("button").attr("class", "button status-button action");
buttonEnter.append("button").attr("class", "button comment-button action").call(_t.append("note.comment"));
}
buttonSection = buttonSection.merge(buttonEnter);
buttonSection.select(".cancel-button").on("click.cancel", clickCancel);
buttonSection.select(".save-button").attr("disabled", isSaveDisabled).on("click.save", clickSave);
buttonSection.select(".status-button").attr("disabled", hasAuth ? null : true).html(function(d) {
var action = d.status === "open" ? "close" : "open";
var andComment = d.newComment ? "_comment" : "";
return _t.html("note." + action + andComment);
}).on("click.status", clickStatus);
buttonSection.select(".comment-button").attr("disabled", isSaveDisabled).on("click.comment", clickComment);
function isSaveDisabled(d) {
return hasAuth && d.status === "open" && d.newComment ? null : true;
}
}
function clickCancel(d3_event, d) {
this.blur();
var osm = services.osm;
if (osm) {
osm.removeNote(d);
}
context.enter(modeBrowse(context));
dispatch10.call("change");
}
function clickSave(d3_event, d) {
this.blur();
var osm = services.osm;
if (osm) {
osm.postNoteCreate(d, function(err, note) {
dispatch10.call("change", note);
});
}
}
function clickStatus(d3_event, d) {
this.blur();
var osm = services.osm;
if (osm) {
var setStatus = d.status === "open" ? "closed" : "open";
osm.postNoteUpdate(d, setStatus, function(err, note) {
dispatch10.call("change", note);
});
}
}
function clickComment(d3_event, d) {
this.blur();
var osm = services.osm;
if (osm) {
osm.postNoteUpdate(d, d.status, function(err, note) {
dispatch10.call("change", note);
});
}
}
noteEditor.note = function(val) {
if (!arguments.length)
return _note;
_note = val;
return noteEditor;
};
noteEditor.newNote = function(val) {
if (!arguments.length)
return _newNote;
_newNote = val;
return noteEditor;
};
return utilRebind(noteEditor, dispatch10, "on");
}
// modules/ui/source_switch.js
function uiSourceSwitch(context) {
var keys;
function click(d3_event) {
d3_event.preventDefault();
var osm = context.connection();
if (!osm)
return;
if (context.inIntro())
return;
if (context.history().hasChanges() && !window.confirm(_t("source_switch.lose_changes")))
return;
var isLive = select_default2(this).classed("live");
isLive = !isLive;
context.enter(modeBrowse(context));
context.history().clearSaved();
context.flush();
select_default2(this).html(isLive ? _t.html("source_switch.live") : _t.html("source_switch.dev")).classed("live", isLive).classed("chip", isLive);
osm.switch(isLive ? keys[0] : keys[1]);
}
var sourceSwitch = function(selection2) {
selection2.append("a").attr("href", "#").call(_t.append("source_switch.live")).attr("class", "live chip").on("click", click);
};
sourceSwitch.keys = function(_) {
if (!arguments.length)
return keys;
keys = _;
return sourceSwitch;
};
return sourceSwitch;
}
// modules/ui/spinner.js
function uiSpinner(context) {
var osm = context.connection();
return function(selection2) {
var img = selection2.append("img").attr("src", context.imagePath("loader-black.gif")).style("opacity", 0);
if (osm) {
osm.on("loading.spinner", function() {
img.transition().style("opacity", 1);
}).on("loaded.spinner", function() {
img.transition().style("opacity", 0);
});
}
};
}
// modules/ui/sections/privacy.js
function uiSectionPrivacy(context) {
let section = uiSection("preferences-third-party", context).label(_t.html("preferences.privacy.title")).disclosureContent(renderDisclosureContent);
function renderDisclosureContent(selection2) {
selection2.selectAll(".privacy-options-list").data([0]).enter().append("ul").attr("class", "layer-list privacy-options-list");
let thirdPartyIconsEnter = selection2.select(".privacy-options-list").selectAll(".privacy-third-party-icons-item").data([corePreferences("preferences.privacy.thirdpartyicons") || "true"]).enter().append("li").attr("class", "privacy-third-party-icons-item").append("label").call(uiTooltip().title(_t.html("preferences.privacy.third_party_icons.tooltip")).placement("bottom"));
thirdPartyIconsEnter.append("input").attr("type", "checkbox").on("change", (d3_event, d) => {
d3_event.preventDefault();
corePreferences("preferences.privacy.thirdpartyicons", d === "true" ? "false" : "true");
});
thirdPartyIconsEnter.append("span").call(_t.append("preferences.privacy.third_party_icons.description"));
selection2.selectAll(".privacy-third-party-icons-item").classed("active", (d) => d === "true").select("input").property("checked", (d) => d === "true");
selection2.selectAll(".privacy-link").data([0]).enter().append("div").attr("class", "privacy-link").append("a").attr("target", "_blank").call(svgIcon("#iD-icon-out-link", "inline")).attr("href", "https://github.com/openstreetmap/iD/blob/release/PRIVACY.md").append("span").call(_t.append("preferences.privacy.privacy_link"));
}
corePreferences.onChange("preferences.privacy.thirdpartyicons", section.reRender);
return section;
}
// modules/ui/splash.js
function uiSplash(context) {
return (selection2) => {
if (context.history().hasRestorableChanges())
return;
let updateMessage = "";
const sawPrivacyVersion = corePreferences("sawPrivacyVersion");
let showSplash = !corePreferences("sawSplash");
if (sawPrivacyVersion !== context.privacyVersion) {
updateMessage = _t("splash.privacy_update");
showSplash = true;
}
if (!showSplash)
return;
corePreferences("sawSplash", true);
corePreferences("sawPrivacyVersion", context.privacyVersion);
_mainFileFetcher.get("intro_graph");
let modalSelection = uiModal(selection2);
modalSelection.select(".modal").attr("class", "modal-splash modal");
let introModal = modalSelection.select(".content").append("div").attr("class", "fillL");
introModal.append("div").attr("class", "modal-section").append("h3").call(_t.append("splash.welcome"));
let modalSection = introModal.append("div").attr("class", "modal-section");
modalSection.append("p").html(_t.html("splash.text", {
version: context.version,
website: { html: '' + _t.html("splash.changelog") + "" },
github: { html: 'github.com' }
}));
modalSection.append("p").html(_t.html("splash.privacy", {
updateMessage,
privacyLink: { html: '' + _t("splash.privacy_policy") + "" }
}));
uiSectionPrivacy(context).label(_t.html("splash.privacy_settings")).render(modalSection);
let buttonWrap = introModal.append("div").attr("class", "modal-actions");
let walkthrough = buttonWrap.append("button").attr("class", "walkthrough").on("click", () => {
context.container().call(uiIntro(context));
modalSelection.close();
});
walkthrough.append("svg").attr("class", "logo logo-walkthrough").append("use").attr("xlink:href", "#iD-logo-walkthrough");
walkthrough.append("div").call(_t.append("splash.walkthrough"));
let startEditing = buttonWrap.append("button").attr("class", "start-editing").on("click", modalSelection.close);
startEditing.append("svg").attr("class", "logo logo-features").append("use").attr("xlink:href", "#iD-logo-features");
startEditing.append("div").call(_t.append("splash.start"));
modalSelection.select("button.close").attr("class", "hide");
};
}
// modules/ui/status.js
function uiStatus(context) {
var osm = context.connection();
return function(selection2) {
if (!osm)
return;
function update(err, apiStatus) {
selection2.html("");
if (err) {
if (apiStatus === "connectionSwitched") {
return;
} else if (apiStatus === "rateLimited") {
selection2.call(_t.append("osm_api_status.message.rateLimit")).append("a").attr("href", "#").attr("class", "api-status-login").attr("target", "_blank").call(svgIcon("#iD-icon-out-link", "inline")).append("span").call(_t.append("login")).on("click.login", function(d3_event) {
d3_event.preventDefault();
osm.authenticate();
});
} else {
var throttledRetry = throttle_default(function() {
context.loadTiles(context.projection);
osm.reloadApiStatus();
}, 2e3);
selection2.call(_t.append("osm_api_status.message.error", { suffix: " " })).append("a").attr("href", "#").call(_t.append("osm_api_status.retry")).on("click.retry", function(d3_event) {
d3_event.preventDefault();
throttledRetry();
});
}
} else if (apiStatus === "readonly") {
selection2.call(_t.append("osm_api_status.message.readonly"));
} else if (apiStatus === "offline") {
selection2.call(_t.append("osm_api_status.message.offline"));
}
selection2.attr("class", "api-status " + (err ? "error" : apiStatus));
}
osm.on("apiStatusChange.uiStatus", update);
context.history().on("storage_error", () => {
selection2.selectAll("span.local-storage-full").remove();
selection2.append("span").attr("class", "local-storage-full").call(_t.append("osm_api_status.message.local_storage_full"));
selection2.classed("error", true);
});
window.setInterval(function() {
osm.reloadApiStatus();
}, 9e4);
osm.reloadApiStatus();
};
}
// node_modules/osm-community-index/lib/simplify.js
var import_diacritics3 = __toESM(require_diacritics(), 1);
function simplify2(str2) {
if (typeof str2 !== "string")
return "";
return import_diacritics3.default.remove(str2.replace(/&/g, "and").replace(/İ/ig, "i").replace(/[\s\-=_!"#%'*{},.\/:;?\(\)\[\]@\\$\^*+<>«»~`’\u00a1\u00a7\u00b6\u00b7\u00bf\u037e\u0387\u055a-\u055f\u0589\u05c0\u05c3\u05c6\u05f3\u05f4\u0609\u060a\u060c\u060d\u061b\u061e\u061f\u066a-\u066d\u06d4\u0700-\u070d\u07f7-\u07f9\u0830-\u083e\u085e\u0964\u0965\u0970\u0af0\u0df4\u0e4f\u0e5a\u0e5b\u0f04-\u0f12\u0f14\u0f85\u0fd0-\u0fd4\u0fd9\u0fda\u104a-\u104f\u10fb\u1360-\u1368\u166d\u166e\u16eb-\u16ed\u1735\u1736\u17d4-\u17d6\u17d8-\u17da\u1800-\u1805\u1807-\u180a\u1944\u1945\u1a1e\u1a1f\u1aa0-\u1aa6\u1aa8-\u1aad\u1b5a-\u1b60\u1bfc-\u1bff\u1c3b-\u1c3f\u1c7e\u1c7f\u1cc0-\u1cc7\u1cd3\u200b-\u200f\u2016\u2017\u2020-\u2027\u2030-\u2038\u203b-\u203e\u2041-\u2043\u2047-\u2051\u2053\u2055-\u205e\u2cf9-\u2cfc\u2cfe\u2cff\u2d70\u2e00\u2e01\u2e06-\u2e08\u2e0b\u2e0e-\u2e16\u2e18\u2e19\u2e1b\u2e1e\u2e1f\u2e2a-\u2e2e\u2e30-\u2e39\u3001-\u3003\u303d\u30fb\ua4fe\ua4ff\ua60d-\ua60f\ua673\ua67e\ua6f2-\ua6f7\ua874-\ua877\ua8ce\ua8cf\ua8f8-\ua8fa\ua92e\ua92f\ua95f\ua9c1-\ua9cd\ua9de\ua9df\uaa5c-\uaa5f\uaade\uaadf\uaaf0\uaaf1\uabeb\ufe10-\ufe16\ufe19\ufe30\ufe45\ufe46\ufe49-\ufe4c\ufe50-\ufe52\ufe54-\ufe57\ufe5f-\ufe61\ufe68\ufe6a\ufe6b\ufeff\uff01-\uff03\uff05-\uff07\uff0a\uff0c\uff0e\uff0f\uff1a\uff1b\uff1f\uff20\uff3c\uff61\uff64\uff65]+/g, "").toLowerCase());
}
// node_modules/osm-community-index/lib/resolve_strings.js
function resolveStrings(item, defaults2, localizerFn) {
let itemStrings = Object.assign({}, item.strings);
let defaultStrings = Object.assign({}, defaults2[item.type]);
const anyToken = new RegExp(/(\{\w+\})/, "gi");
if (localizerFn) {
if (itemStrings.community) {
const communityID = simplify2(itemStrings.community);
itemStrings.community = localizerFn(`_communities.${communityID}`);
}
["name", "description", "extendedDescription"].forEach((prop) => {
if (defaultStrings[prop])
defaultStrings[prop] = localizerFn(`_defaults.${item.type}.${prop}`);
if (itemStrings[prop])
itemStrings[prop] = localizerFn(`${item.id}.${prop}`);
});
}
let replacements = {
account: item.account,
community: itemStrings.community,
signupUrl: itemStrings.signupUrl,
url: itemStrings.url
};
if (!replacements.signupUrl) {
replacements.signupUrl = resolve(itemStrings.signupUrl || defaultStrings.signupUrl);
}
if (!replacements.url) {
replacements.url = resolve(itemStrings.url || defaultStrings.url);
}
let resolved = {
name: resolve(itemStrings.name || defaultStrings.name),
url: resolve(itemStrings.url || defaultStrings.url),
signupUrl: resolve(itemStrings.signupUrl || defaultStrings.signupUrl),
description: resolve(itemStrings.description || defaultStrings.description),
extendedDescription: resolve(itemStrings.extendedDescription || defaultStrings.extendedDescription)
};
resolved.nameHTML = linkify(resolved.url, resolved.name);
resolved.urlHTML = linkify(resolved.url);
resolved.signupUrlHTML = linkify(resolved.signupUrl);
resolved.descriptionHTML = resolve(itemStrings.description || defaultStrings.description, true);
resolved.extendedDescriptionHTML = resolve(itemStrings.extendedDescription || defaultStrings.extendedDescription, true);
return resolved;
function resolve(s, addLinks) {
if (!s)
return void 0;
let result = s;
for (let key in replacements) {
const token = `{${key}}`;
const regex = new RegExp(token, "g");
if (regex.test(result)) {
let replacement = replacements[key];
if (!replacement) {
throw new Error(`Cannot resolve token: ${token}`);
} else {
if (addLinks && (key === "signupUrl" || key === "url")) {
replacement = linkify(replacement);
}
result = result.replace(regex, replacement);
}
}
}
const leftovers = result.match(anyToken);
if (leftovers) {
throw new Error(`Cannot resolve tokens: ${leftovers}`);
}
if (addLinks && item.type === "reddit") {
result = result.replace(/(\/r\/\w+\/*)/i, (match) => linkify(resolved.url, match));
}
return result;
}
function linkify(url, text2) {
if (!url)
return void 0;
text2 = text2 || url;
return `${text2}`;
}
}
// modules/ui/success.js
var _oci = null;
function uiSuccess(context) {
const MAXEVENTS = 2;
const dispatch10 = dispatch_default("cancel");
let _changeset2;
let _location;
ensureOSMCommunityIndex();
function ensureOSMCommunityIndex() {
const data = _mainFileFetcher;
return Promise.all([
data.get("oci_features"),
data.get("oci_resources"),
data.get("oci_defaults")
]).then((vals) => {
if (_oci)
return _oci;
if (vals[0] && Array.isArray(vals[0].features)) {
_mainLocations.mergeCustomGeoJSON(vals[0]);
}
let ociResources = Object.values(vals[1].resources);
if (ociResources.length) {
return _mainLocations.mergeLocationSets(ociResources).then(() => {
_oci = {
resources: ociResources,
defaults: vals[2].defaults
};
return _oci;
});
} else {
_oci = {
resources: [],
defaults: vals[2].defaults
};
return _oci;
}
});
}
function parseEventDate(when) {
if (!when)
return;
let raw = when.trim();
if (!raw)
return;
if (!/Z$/.test(raw)) {
raw += "Z";
}
const parsed = new Date(raw);
return new Date(parsed.toUTCString().substr(0, 25));
}
function success(selection2) {
let header = selection2.append("div").attr("class", "header fillL");
header.append("h2").call(_t.append("success.just_edited"));
header.append("button").attr("class", "close").attr("title", _t("icons.close")).on("click", () => dispatch10.call("cancel")).call(svgIcon("#iD-icon-close"));
let body = selection2.append("div").attr("class", "body save-success fillL");
let summary = body.append("div").attr("class", "save-summary");
summary.append("h3").call(_t.append("success.thank_you" + (_location ? "_location" : ""), { where: _location }));
summary.append("p").call(_t.append("success.help_html")).append("a").attr("class", "link-out").attr("target", "_blank").attr("href", _t("success.help_link_url")).call(svgIcon("#iD-icon-out-link", "inline")).append("span").call(_t.append("success.help_link_text"));
let osm = context.connection();
if (!osm)
return;
let changesetURL = osm.changesetURL(_changeset2.id);
let table = summary.append("table").attr("class", "summary-table");
let row = table.append("tr").attr("class", "summary-row");
row.append("td").attr("class", "cell-icon summary-icon").append("a").attr("target", "_blank").attr("href", changesetURL).append("svg").attr("class", "logo-small").append("use").attr("xlink:href", "#iD-logo-osm");
let summaryDetail = row.append("td").attr("class", "cell-detail summary-detail");
summaryDetail.append("a").attr("class", "cell-detail summary-view-on-osm").attr("target", "_blank").attr("href", changesetURL).call(_t.append("success.view_on_osm"));
summaryDetail.append("div").html(_t.html("success.changeset_id", {
changeset_id: { html: `${_changeset2.id}` }
}));
ensureOSMCommunityIndex().then((oci) => {
const loc = context.map().center();
const validLocations = _mainLocations.locationsAt(loc);
let communities = [];
oci.resources.forEach((resource) => {
let area = validLocations[resource.locationSetID];
if (!area)
return;
const localizer = (stringID) => _t.html(`community.${stringID}`);
resource.resolved = resolveStrings(resource, oci.defaults, localizer);
communities.push({
area,
order: resource.order || 0,
resource
});
});
communities.sort((a, b) => a.area - b.area || b.order - a.order);
body.call(showCommunityLinks, communities.map((c) => c.resource));
});
}
function showCommunityLinks(selection2, resources) {
let communityLinks = selection2.append("div").attr("class", "save-communityLinks");
communityLinks.append("h3").call(_t.append("success.like_osm"));
let table = communityLinks.append("table").attr("class", "community-table");
let row = table.selectAll(".community-row").data(resources);
let rowEnter = row.enter().append("tr").attr("class", "community-row");
rowEnter.append("td").attr("class", "cell-icon community-icon").append("a").attr("target", "_blank").attr("href", (d) => d.resolved.url).append("svg").attr("class", "logo-small").append("use").attr("xlink:href", (d) => `#community-${d.type}`);
let communityDetail = rowEnter.append("td").attr("class", "cell-detail community-detail");
communityDetail.each(showCommunityDetails);
communityLinks.append("div").attr("class", "community-missing").call(_t.append("success.missing")).append("a").attr("class", "link-out").attr("target", "_blank").call(svgIcon("#iD-icon-out-link", "inline")).attr("href", "https://github.com/osmlab/osm-community-index/issues").append("span").call(_t.append("success.tell_us"));
}
function showCommunityDetails(d) {
let selection2 = select_default2(this);
let communityID = d.id;
selection2.append("div").attr("class", "community-name").html(d.resolved.nameHTML);
selection2.append("div").attr("class", "community-description").html(d.resolved.descriptionHTML);
if (d.resolved.extendedDescriptionHTML || d.languageCodes && d.languageCodes.length) {
selection2.append("div").call(uiDisclosure(context, `community-more-${d.id}`, false).expanded(false).updatePreference(false).label(_t.html("success.more")).content(showMore));
}
let nextEvents = (d.events || []).map((event) => {
event.date = parseEventDate(event.when);
return event;
}).filter((event) => {
const t = event.date.getTime();
const now3 = new Date().setHours(0, 0, 0, 0);
return !isNaN(t) && t >= now3;
}).sort((a, b) => {
return a.date < b.date ? -1 : a.date > b.date ? 1 : 0;
}).slice(0, MAXEVENTS);
if (nextEvents.length) {
selection2.append("div").call(uiDisclosure(context, `community-events-${d.id}`, false).expanded(false).updatePreference(false).label(_t.html("success.events")).content(showNextEvents)).select(".hide-toggle").append("span").attr("class", "badge-text").text(nextEvents.length);
}
function showMore(selection3) {
let more = selection3.selectAll(".community-more").data([0]);
let moreEnter = more.enter().append("div").attr("class", "community-more");
if (d.resolved.extendedDescriptionHTML) {
moreEnter.append("div").attr("class", "community-extended-description").html(d.resolved.extendedDescriptionHTML);
}
if (d.languageCodes && d.languageCodes.length) {
const languageList = d.languageCodes.map((code) => _mainLocalizer.languageName(code)).join(", ");
moreEnter.append("div").attr("class", "community-languages").call(_t.append("success.languages", { languages: languageList }));
}
}
function showNextEvents(selection3) {
let events = selection3.append("div").attr("class", "community-events");
let item = events.selectAll(".community-event").data(nextEvents);
let itemEnter = item.enter().append("div").attr("class", "community-event");
itemEnter.append("div").attr("class", "community-event-name").append("a").attr("target", "_blank").attr("href", (d2) => d2.url).text((d2) => {
let name2 = d2.name;
if (d2.i18n && d2.id) {
name2 = _t(`community.${communityID}.events.${d2.id}.name`, { default: name2 });
}
return name2;
});
itemEnter.append("div").attr("class", "community-event-when").text((d2) => {
let options2 = { weekday: "short", day: "numeric", month: "short", year: "numeric" };
if (d2.date.getHours() || d2.date.getMinutes()) {
options2.hour = "numeric";
options2.minute = "numeric";
}
return d2.date.toLocaleString(_mainLocalizer.localeCode(), options2);
});
itemEnter.append("div").attr("class", "community-event-where").text((d2) => {
let where = d2.where;
if (d2.i18n && d2.id) {
where = _t(`community.${communityID}.events.${d2.id}.where`, { default: where });
}
return where;
});
itemEnter.append("div").attr("class", "community-event-description").text((d2) => {
let description2 = d2.description;
if (d2.i18n && d2.id) {
description2 = _t(`community.${communityID}.events.${d2.id}.description`, { default: description2 });
}
return description2;
});
}
}
success.changeset = function(val) {
if (!arguments.length)
return _changeset2;
_changeset2 = val;
return success;
};
success.location = function(val) {
if (!arguments.length)
return _location;
_location = val;
return success;
};
return utilRebind(success, dispatch10, "on");
}
// modules/ui/version.js
var sawVersion = null;
var isNewVersion = false;
var isNewUser = false;
function uiVersion(context) {
var currVersion = context.version;
var matchedVersion = currVersion.match(/\d+\.\d+\.\d+.*/);
if (sawVersion === null && matchedVersion !== null) {
if (corePreferences("sawVersion")) {
isNewUser = false;
isNewVersion = corePreferences("sawVersion") !== currVersion && currVersion.indexOf("-") === -1;
} else {
isNewUser = true;
isNewVersion = true;
}
corePreferences("sawVersion", currVersion);
sawVersion = currVersion;
}
return function(selection2) {
selection2.append("a").attr("target", "_blank").attr("href", "https://github.com/openstreetmap/iD").text(currVersion);
if (isNewVersion && !isNewUser) {
selection2.append("a").attr("class", "badge").attr("target", "_blank").attr("href", "https://github.com/openstreetmap/iD/blob/release/CHANGELOG.md#whats-new").call(svgIcon("#maki-gift-11")).call(uiTooltip().title(_t.html("version.whats_new", { version: currVersion })).placement("top").scrollContainer(context.container().select(".main-footer-wrap")));
}
};
}
// modules/ui/zoom.js
function uiZoom(context) {
var zooms = [{
id: "zoom-in",
icon: "iD-icon-plus",
title: _t.html("zoom.in"),
action: zoomIn,
disabled: function() {
return !context.map().canZoomIn();
},
disabledTitle: _t.html("zoom.disabled.in"),
key: "+"
}, {
id: "zoom-out",
icon: "iD-icon-minus",
title: _t.html("zoom.out"),
action: zoomOut,
disabled: function() {
return !context.map().canZoomOut();
},
disabledTitle: _t.html("zoom.disabled.out"),
key: "-"
}];
function zoomIn(d3_event) {
if (d3_event.shiftKey)
return;
d3_event.preventDefault();
context.map().zoomIn();
}
function zoomOut(d3_event) {
if (d3_event.shiftKey)
return;
d3_event.preventDefault();
context.map().zoomOut();
}
function zoomInFurther(d3_event) {
if (d3_event.shiftKey)
return;
d3_event.preventDefault();
context.map().zoomInFurther();
}
function zoomOutFurther(d3_event) {
if (d3_event.shiftKey)
return;
d3_event.preventDefault();
context.map().zoomOutFurther();
}
return function(selection2) {
var tooltipBehavior = uiTooltip().placement(_mainLocalizer.textDirection() === "rtl" ? "right" : "left").title(function(d) {
if (d.disabled()) {
return d.disabledTitle;
}
return d.title;
}).keys(function(d) {
return [d.key];
});
var lastPointerUpType;
var buttons = selection2.selectAll("button").data(zooms).enter().append("button").attr("class", function(d) {
return d.id;
}).on("pointerup.editor", function(d3_event) {
lastPointerUpType = d3_event.pointerType;
}).on("click.editor", function(d3_event, d) {
if (!d.disabled()) {
d.action(d3_event);
} else if (lastPointerUpType === "touch" || lastPointerUpType === "pen") {
context.ui().flash.duration(2e3).iconName("#" + d.icon).iconClass("disabled").label(d.disabledTitle)();
}
lastPointerUpType = null;
}).call(tooltipBehavior);
buttons.each(function(d) {
select_default2(this).call(svgIcon("#" + d.icon, "light"));
});
utilKeybinding.plusKeys.forEach(function(key) {
context.keybinding().on([key], zoomIn);
context.keybinding().on([uiCmd("\u2325" + key)], zoomInFurther);
});
utilKeybinding.minusKeys.forEach(function(key) {
context.keybinding().on([key], zoomOut);
context.keybinding().on([uiCmd("\u2325" + key)], zoomOutFurther);
});
function updateButtonStates() {
buttons.classed("disabled", function(d) {
return d.disabled();
}).each(function() {
var selection3 = select_default2(this);
if (!selection3.select(".tooltip.in").empty()) {
selection3.call(tooltipBehavior.updateContent);
}
});
}
updateButtonStates();
context.map().on("move.uiZoom", updateButtonStates);
};
}
// modules/ui/sections/raw_tag_editor.js
function uiSectionRawTagEditor(id2, context) {
var section = uiSection(id2, context).classes("raw-tag-editor").label(function() {
var count = Object.keys(_tags).filter(function(d) {
return d;
}).length;
return _t.html("inspector.title_count", { title: { html: _t.html("inspector.tags") }, count });
}).expandedByDefault(false).disclosureContent(renderDisclosureContent);
var taginfo = services.taginfo;
var dispatch10 = dispatch_default("change");
var availableViews = [
{ id: "list", icon: "#fas-th-list" },
{ id: "text", icon: "#fas-i-cursor" }
];
var _tagView = corePreferences("raw-tag-editor-view") || "list";
var _readOnlyTags = [];
var _orderedKeys = [];
var _showBlank = false;
var _pendingChange = null;
var _state;
var _presets;
var _tags;
var _entityIDs;
var _didInteract = false;
function interacted() {
_didInteract = true;
}
function renderDisclosureContent(wrap2) {
_orderedKeys = _orderedKeys.filter(function(key) {
return _tags[key] !== void 0;
});
var all = Object.keys(_tags).sort();
var missingKeys = utilArrayDifference(all, _orderedKeys);
for (var i2 in missingKeys) {
_orderedKeys.push(missingKeys[i2]);
}
var rowData = _orderedKeys.map(function(key, i3) {
return { index: i3, key, value: _tags[key] };
});
if (!rowData.length || _showBlank) {
_showBlank = false;
rowData.push({ index: rowData.length, key: "", value: "" });
}
var options2 = wrap2.selectAll(".raw-tag-options").data([0]);
options2.exit().remove();
var optionsEnter = options2.enter().insert("div", ":first-child").attr("class", "raw-tag-options").attr("role", "tablist");
var optionEnter = optionsEnter.selectAll(".raw-tag-option").data(availableViews, function(d) {
return d.id;
}).enter();
optionEnter.append("button").attr("class", function(d) {
return "raw-tag-option raw-tag-option-" + d.id + (_tagView === d.id ? " selected" : "");
}).attr("aria-selected", function(d) {
return _tagView === d.id;
}).attr("role", "tab").attr("title", function(d) {
return _t("icons." + d.id);
}).on("click", function(d3_event, d) {
_tagView = d.id;
corePreferences("raw-tag-editor-view", d.id);
wrap2.selectAll(".raw-tag-option").classed("selected", function(datum2) {
return datum2 === d;
}).attr("aria-selected", function(datum2) {
return datum2 === d;
});
wrap2.selectAll(".tag-text").classed("hide", d.id !== "text").each(setTextareaHeight);
wrap2.selectAll(".tag-list, .add-row").classed("hide", d.id !== "list");
}).each(function(d) {
select_default2(this).call(svgIcon(d.icon));
});
var textData = rowsToText(rowData);
var textarea = wrap2.selectAll(".tag-text").data([0]);
textarea = textarea.enter().append("textarea").attr("class", "tag-text" + (_tagView !== "text" ? " hide" : "")).call(utilNoAuto).attr("placeholder", _t("inspector.key_value")).attr("spellcheck", "false").merge(textarea);
textarea.call(utilGetSetValue, textData).each(setTextareaHeight).on("input", setTextareaHeight).on("focus", interacted).on("blur", textChanged).on("change", textChanged);
var list = wrap2.selectAll(".tag-list").data([0]);
list = list.enter().append("ul").attr("class", "tag-list" + (_tagView !== "list" ? " hide" : "")).merge(list);
var addRowEnter = wrap2.selectAll(".add-row").data([0]).enter().append("div").attr("class", "add-row" + (_tagView !== "list" ? " hide" : ""));
addRowEnter.append("button").attr("class", "add-tag").attr("aria-label", _t("inspector.add_to_tag")).call(svgIcon("#iD-icon-plus", "light")).call(uiTooltip().title(_t.html("inspector.add_to_tag")).placement(_mainLocalizer.textDirection() === "ltr" ? "right" : "left")).on("click", addTag);
addRowEnter.append("div").attr("class", "space-value");
addRowEnter.append("div").attr("class", "space-buttons");
var items = list.selectAll(".tag-row").data(rowData, function(d) {
return d.key;
});
items.exit().each(unbind).remove();
var itemsEnter = items.enter().append("li").attr("class", "tag-row").classed("readonly", isReadOnly);
var innerWrap = itemsEnter.append("div").attr("class", "inner-wrap");
innerWrap.append("div").attr("class", "key-wrap").append("input").property("type", "text").attr("class", "key").call(utilNoAuto).on("focus", interacted).on("blur", keyChange).on("change", keyChange);
innerWrap.append("div").attr("class", "value-wrap").append("input").property("type", "text").attr("class", "value").call(utilNoAuto).on("focus", interacted).on("blur", valueChange).on("change", valueChange).on("keydown.push-more", pushMore);
innerWrap.append("button").attr("class", "form-field-button remove").attr("title", _t("icons.remove")).call(svgIcon("#iD-operation-delete"));
items = items.merge(itemsEnter).sort(function(a, b) {
return a.index - b.index;
});
items.each(function(d) {
var row = select_default2(this);
var key = row.select("input.key");
var value = row.select("input.value");
if (_entityIDs && taginfo && _state !== "hover") {
bindTypeahead(key, value);
}
var referenceOptions = { key: d.key };
if (typeof d.value === "string") {
referenceOptions.value = d.value;
}
var reference = uiTagReference(referenceOptions, context);
if (_state === "hover") {
reference.showing(false);
}
row.select(".inner-wrap").call(reference.button);
row.call(reference.body);
row.select("button.remove");
});
items.selectAll("input.key").attr("title", function(d) {
return d.key;
}).call(utilGetSetValue, function(d) {
return d.key;
}).attr("readonly", function(d) {
return isReadOnly(d) || null;
});
items.selectAll("input.value").attr("title", function(d) {
return Array.isArray(d.value) ? d.value.filter(Boolean).join("\n") : d.value;
}).classed("mixed", function(d) {
return Array.isArray(d.value);
}).attr("placeholder", function(d) {
return typeof d.value === "string" ? null : _t("inspector.multiple_values");
}).call(utilGetSetValue, function(d) {
return typeof d.value === "string" ? d.value : "";
}).attr("readonly", function(d) {
return isReadOnly(d) || null;
});
items.selectAll("button.remove").on(("PointerEvent" in window ? "pointer" : "mouse") + "down", removeTag);
}
function isReadOnly(d) {
for (var i2 = 0; i2 < _readOnlyTags.length; i2++) {
if (d.key.match(_readOnlyTags[i2]) !== null) {
return true;
}
}
return false;
}
function setTextareaHeight() {
if (_tagView !== "text")
return;
var selection2 = select_default2(this);
var matches = selection2.node().value.match(/\n/g);
var lineCount = 2 + Number(matches && matches.length);
var lineHeight = 20;
selection2.style("height", lineCount * lineHeight + "px");
}
function stringify3(s) {
return JSON.stringify(s).slice(1, -1);
}
function unstringify(s) {
var leading = "";
var trailing = "";
if (s.length < 1 || s.charAt(0) !== '"') {
leading = '"';
}
if (s.length < 2 || s.charAt(s.length - 1) !== '"' || s.charAt(s.length - 1) === '"' && s.charAt(s.length - 2) === "\\") {
trailing = '"';
}
return JSON.parse(leading + s + trailing);
}
function rowsToText(rows) {
var str2 = rows.filter(function(row) {
return row.key && row.key.trim() !== "";
}).map(function(row) {
var rawVal = row.value;
if (typeof rawVal !== "string")
rawVal = "*";
var val = rawVal ? stringify3(rawVal) : "";
return stringify3(row.key) + "=" + val;
}).join("\n");
if (_state !== "hover" && str2.length) {
return str2 + "\n";
}
return str2;
}
function textChanged() {
var newText = this.value.trim();
var newTags = {};
newText.split("\n").forEach(function(row) {
var m = row.match(/^\s*([^=]+)=(.*)$/);
if (m !== null) {
var k = context.cleanTagKey(unstringify(m[1].trim()));
var v = context.cleanTagValue(unstringify(m[2].trim()));
newTags[k] = v;
}
});
var tagDiff = utilTagDiff(_tags, newTags);
if (!tagDiff.length)
return;
_pendingChange = _pendingChange || {};
tagDiff.forEach(function(change) {
if (isReadOnly({ key: change.key }))
return;
if (change.newVal === "*" && typeof change.oldVal !== "string")
return;
if (change.type === "-") {
_pendingChange[change.key] = void 0;
} else if (change.type === "+") {
_pendingChange[change.key] = change.newVal || "";
}
});
if (Object.keys(_pendingChange).length === 0) {
_pendingChange = null;
return;
}
scheduleChange();
}
function pushMore(d3_event) {
if (d3_event.keyCode === 9 && !d3_event.shiftKey && section.selection().selectAll(".tag-list li:last-child input.value").node() === this && utilGetSetValue(select_default2(this))) {
addTag();
}
}
function bindTypeahead(key, value) {
if (isReadOnly(key.datum()))
return;
if (Array.isArray(value.datum().value)) {
value.call(uiCombobox(context, "tag-value").minItems(1).fetcher(function(value2, callback) {
var keyString = utilGetSetValue(key);
if (!_tags[keyString])
return;
var data = _tags[keyString].filter(Boolean).map(function(tagValue) {
return {
value: tagValue,
title: tagValue
};
});
callback(data);
}));
return;
}
var geometry = context.graph().geometry(_entityIDs[0]);
key.call(uiCombobox(context, "tag-key").fetcher(function(value2, callback) {
taginfo.keys({
debounce: true,
geometry,
query: value2
}, function(err, data) {
if (!err) {
var filtered = data.filter(function(d) {
return _tags[d.value] === void 0;
});
callback(sort(value2, filtered));
}
});
}));
value.call(uiCombobox(context, "tag-value").fetcher(function(value2, callback) {
taginfo.values({
debounce: true,
key: utilGetSetValue(key),
geometry,
query: value2
}, function(err, data) {
if (!err)
callback(sort(value2, data));
});
}));
function sort(value2, data) {
var sameletter = [];
var other = [];
for (var i2 = 0; i2 < data.length; i2++) {
if (data[i2].value.substring(0, value2.length) === value2) {
sameletter.push(data[i2]);
} else {
other.push(data[i2]);
}
}
return sameletter.concat(other);
}
}
function unbind() {
var row = select_default2(this);
row.selectAll("input.key").call(uiCombobox.off, context);
row.selectAll("input.value").call(uiCombobox.off, context);
}
function keyChange(d3_event, d) {
if (select_default2(this).attr("readonly"))
return;
var kOld = d.key;
if (_pendingChange && _pendingChange.hasOwnProperty(kOld) && _pendingChange[kOld] === void 0)
return;
var kNew = context.cleanTagKey(this.value.trim());
if (isReadOnly({ key: kNew })) {
this.value = kOld;
return;
}
if (kNew && kNew !== kOld && _tags[kNew] !== void 0) {
this.value = kOld;
section.selection().selectAll(".tag-list input.value").each(function(d2) {
if (d2.key === kNew) {
var input = select_default2(this).node();
input.focus();
input.select();
}
});
return;
}
_pendingChange = _pendingChange || {};
if (kOld) {
if (kOld === kNew)
return;
_pendingChange[kNew] = _pendingChange[kOld] || { oldKey: kOld };
_pendingChange[kOld] = void 0;
} else {
let row = this.parentNode.parentNode;
let inputVal = select_default2(row).selectAll("input.value");
let vNew = context.cleanTagValue(utilGetSetValue(inputVal));
_pendingChange[kNew] = vNew;
utilGetSetValue(inputVal, vNew);
}
var existingKeyIndex = _orderedKeys.indexOf(kOld);
if (existingKeyIndex !== -1)
_orderedKeys[existingKeyIndex] = kNew;
d.key = kNew;
this.value = kNew;
scheduleChange();
}
function valueChange(d3_event, d) {
if (isReadOnly(d))
return;
if (typeof d.value !== "string" && !this.value)
return;
if (_pendingChange && _pendingChange.hasOwnProperty(d.key) && _pendingChange[d.key] === void 0)
return;
_pendingChange = _pendingChange || {};
_pendingChange[d.key] = context.cleanTagValue(this.value);
scheduleChange();
}
function removeTag(d3_event, d) {
if (isReadOnly(d))
return;
if (d.key === "") {
_showBlank = false;
section.reRender();
} else {
_orderedKeys = _orderedKeys.filter(function(key) {
return key !== d.key;
});
_pendingChange = _pendingChange || {};
_pendingChange[d.key] = void 0;
scheduleChange();
}
}
function addTag() {
window.setTimeout(function() {
_showBlank = true;
section.reRender();
section.selection().selectAll(".tag-list li:last-child input.key").node().focus();
}, 20);
}
function scheduleChange() {
var entityIDs = _entityIDs;
window.setTimeout(function() {
if (!_pendingChange)
return;
dispatch10.call("change", this, entityIDs, _pendingChange);
_pendingChange = null;
}, 10);
}
section.state = function(val) {
if (!arguments.length)
return _state;
if (_state !== val) {
_orderedKeys = [];
_state = val;
}
return section;
};
section.presets = function(val) {
if (!arguments.length)
return _presets;
_presets = val;
if (_presets && _presets.length && _presets[0].isFallback()) {
section.disclosureExpanded(true);
} else if (!_didInteract) {
section.disclosureExpanded(null);
}
return section;
};
section.tags = function(val) {
if (!arguments.length)
return _tags;
_tags = val;
return section;
};
section.entityIDs = function(val) {
if (!arguments.length)
return _entityIDs;
if (!_entityIDs || !val || !utilArrayIdentical(_entityIDs, val)) {
_entityIDs = val;
_orderedKeys = [];
}
return section;
};
section.readOnlyTags = function(val) {
if (!arguments.length)
return _readOnlyTags;
_readOnlyTags = val;
return section;
};
return utilRebind(section, dispatch10, "on");
}
// modules/ui/data_editor.js
function uiDataEditor(context) {
var dataHeader = uiDataHeader();
var rawTagEditor = uiSectionRawTagEditor("custom-data-tag-editor", context).expandedByDefault(true).readOnlyTags([/./]);
var _datum;
function dataEditor(selection2) {
var header = selection2.selectAll(".header").data([0]);
var headerEnter = header.enter().append("div").attr("class", "header fillL");
headerEnter.append("button").attr("class", "close").attr("title", _t("icons.close")).on("click", function() {
context.enter(modeBrowse(context));
}).call(svgIcon("#iD-icon-close"));
headerEnter.append("h2").call(_t.append("map_data.title"));
var body = selection2.selectAll(".body").data([0]);
body = body.enter().append("div").attr("class", "body").merge(body);
var editor = body.selectAll(".data-editor").data([0]);
editor.enter().append("div").attr("class", "modal-section data-editor").merge(editor).call(dataHeader.datum(_datum));
var rte = body.selectAll(".raw-tag-editor").data([0]);
rte.enter().append("div").attr("class", "raw-tag-editor data-editor").merge(rte).call(rawTagEditor.tags(_datum && _datum.properties || {}).state("hover").render).selectAll("textarea.tag-text").attr("readonly", true).classed("readonly", true);
}
dataEditor.datum = function(val) {
if (!arguments.length)
return _datum;
_datum = val;
return this;
};
return dataEditor;
}
// modules/ui/osmose_details.js
function uiOsmoseDetails(context) {
let _qaItem;
function issueString(d, type3) {
if (!d)
return "";
const s = services.osmose.getStrings(d.itemType);
return type3 in s ? s[type3] : "";
}
function osmoseDetails(selection2) {
const details = selection2.selectAll(".error-details").data(_qaItem ? [_qaItem] : [], (d) => `${d.id}-${d.status || 0}`);
details.exit().remove();
const detailsEnter = details.enter().append("div").attr("class", "error-details qa-details-container");
if (issueString(_qaItem, "detail")) {
const div = detailsEnter.append("div").attr("class", "qa-details-subsection");
div.append("h4").call(_t.append("QA.keepRight.detail_description"));
div.append("p").attr("class", "qa-details-description-text").html((d) => issueString(d, "detail")).selectAll("a").attr("rel", "noopener").attr("target", "_blank");
}
const detailsDiv = detailsEnter.append("div").attr("class", "qa-details-subsection");
const elemsDiv = detailsEnter.append("div").attr("class", "qa-details-subsection");
if (issueString(_qaItem, "fix")) {
const div = detailsEnter.append("div").attr("class", "qa-details-subsection");
div.append("h4").call(_t.append("QA.osmose.fix_title"));
div.append("p").html((d) => issueString(d, "fix")).selectAll("a").attr("rel", "noopener").attr("target", "_blank");
}
if (issueString(_qaItem, "trap")) {
const div = detailsEnter.append("div").attr("class", "qa-details-subsection");
div.append("h4").call(_t.append("QA.osmose.trap_title"));
div.append("p").html((d) => issueString(d, "trap")).selectAll("a").attr("rel", "noopener").attr("target", "_blank");
}
const thisItem = _qaItem;
services.osmose.loadIssueDetail(_qaItem).then((d) => {
if (!d.elems || d.elems.length === 0)
return;
if (context.selectedErrorID() !== thisItem.id && context.container().selectAll(`.qaItem.osmose.hover.itemId-${thisItem.id}`).empty())
return;
if (d.detail) {
detailsDiv.append("h4").call(_t.append("QA.osmose.detail_title"));
detailsDiv.append("p").html((d2) => d2.detail).selectAll("a").attr("rel", "noopener").attr("target", "_blank");
}
elemsDiv.append("h4").call(_t.append("QA.osmose.elems_title"));
elemsDiv.append("ul").selectAll("li").data(d.elems).enter().append("li").append("a").attr("href", "#").attr("class", "error_entity_link").text((d2) => d2).each(function() {
const link2 = select_default2(this);
const entityID = this.textContent;
const entity = context.hasEntity(entityID);
link2.on("mouseenter", () => {
utilHighlightEntities([entityID], true, context);
}).on("mouseleave", () => {
utilHighlightEntities([entityID], false, context);
}).on("click", (d3_event) => {
d3_event.preventDefault();
utilHighlightEntities([entityID], false, context);
const osmlayer = context.layers().layer("osm");
if (!osmlayer.enabled()) {
osmlayer.enabled(true);
}
context.map().centerZoom(d.loc, 20);
if (entity) {
context.enter(modeSelect(context, [entityID]));
} else {
context.loadEntity(entityID, (err, result) => {
if (err)
return;
const entity2 = result.data.find((e) => e.id === entityID);
if (entity2)
context.enter(modeSelect(context, [entityID]));
});
}
});
if (entity) {
let name2 = utilDisplayName(entity);
if (!name2) {
const preset = _mainPresetIndex.match(entity, context.graph());
name2 = preset && !preset.isFallback() && preset.name();
}
if (name2) {
this.innerText = name2;
}
}
});
context.features().forceVisible(d.elems);
context.map().pan([0, 0]);
}).catch((err) => {
console.log(err);
});
}
osmoseDetails.issue = function(val) {
if (!arguments.length)
return _qaItem;
_qaItem = val;
return osmoseDetails;
};
return osmoseDetails;
}
// modules/ui/osmose_header.js
function uiOsmoseHeader() {
let _qaItem;
function issueTitle(d) {
const unknown = _t("inspector.unknown");
if (!d)
return unknown;
const s = services.osmose.getStrings(d.itemType);
return "title" in s ? s.title : unknown;
}
function osmoseHeader(selection2) {
const header = selection2.selectAll(".qa-header").data(_qaItem ? [_qaItem] : [], (d) => `${d.id}-${d.status || 0}`);
header.exit().remove();
const headerEnter = header.enter().append("div").attr("class", "qa-header");
const svgEnter = headerEnter.append("div").attr("class", "qa-header-icon").classed("new", (d) => d.id < 0).append("svg").attr("width", "20px").attr("height", "30px").attr("viewbox", "0 0 20 30").attr("class", (d) => `preset-icon-28 qaItem ${d.service} itemId-${d.id} itemType-${d.itemType}`);
svgEnter.append("polygon").attr("fill", (d) => services.osmose.getColor(d.item)).attr("class", "qaItem-fill").attr("points", "16,3 4,3 1,6 1,17 4,20 7,20 10,27 13,20 16,20 19,17.033 19,6");
svgEnter.append("use").attr("class", "icon-annotation").attr("width", "12px").attr("height", "12px").attr("transform", "translate(4, 5.5)").attr("xlink:href", (d) => d.icon ? "#" + d.icon : "");
headerEnter.append("div").attr("class", "qa-header-label").text(issueTitle);
}
osmoseHeader.issue = function(val) {
if (!arguments.length)
return _qaItem;
_qaItem = val;
return osmoseHeader;
};
return osmoseHeader;
}
// modules/ui/view_on_osmose.js
function uiViewOnOsmose() {
let _qaItem;
function viewOnOsmose(selection2) {
let url;
if (services.osmose && _qaItem instanceof QAItem) {
url = services.osmose.itemURL(_qaItem);
}
const link2 = selection2.selectAll(".view-on-osmose").data(url ? [url] : []);
link2.exit().remove();
const linkEnter = link2.enter().append("a").attr("class", "view-on-osmose").attr("target", "_blank").attr("rel", "noopener").attr("href", (d) => d).call(svgIcon("#iD-icon-out-link", "inline"));
linkEnter.append("span").call(_t.append("inspector.view_on_osmose"));
}
viewOnOsmose.what = function(val) {
if (!arguments.length)
return _qaItem;
_qaItem = val;
return viewOnOsmose;
};
return viewOnOsmose;
}
// modules/ui/osmose_editor.js
function uiOsmoseEditor(context) {
const dispatch10 = dispatch_default("change");
const qaDetails = uiOsmoseDetails(context);
const qaHeader = uiOsmoseHeader(context);
let _qaItem;
function osmoseEditor(selection2) {
const header = selection2.selectAll(".header").data([0]);
const headerEnter = header.enter().append("div").attr("class", "header fillL");
headerEnter.append("button").attr("class", "close").attr("title", _t("icons.close")).on("click", () => context.enter(modeBrowse(context))).call(svgIcon("#iD-icon-close"));
headerEnter.append("h2").call(_t.append("QA.osmose.title"));
let body = selection2.selectAll(".body").data([0]);
body = body.enter().append("div").attr("class", "body").merge(body);
let editor = body.selectAll(".qa-editor").data([0]);
editor.enter().append("div").attr("class", "modal-section qa-editor").merge(editor).call(qaHeader.issue(_qaItem)).call(qaDetails.issue(_qaItem)).call(osmoseSaveSection);
const footer = selection2.selectAll(".footer").data([0]);
footer.enter().append("div").attr("class", "footer").merge(footer).call(uiViewOnOsmose(context).what(_qaItem));
}
function osmoseSaveSection(selection2) {
const isSelected = _qaItem && _qaItem.id === context.selectedErrorID();
const isShown = _qaItem && isSelected;
let saveSection = selection2.selectAll(".qa-save").data(isShown ? [_qaItem] : [], (d) => `${d.id}-${d.status || 0}`);
saveSection.exit().remove();
const saveSectionEnter = saveSection.enter().append("div").attr("class", "qa-save save-section cf");
saveSection = saveSectionEnter.merge(saveSection).call(qaSaveButtons);
}
function qaSaveButtons(selection2) {
const isSelected = _qaItem && _qaItem.id === context.selectedErrorID();
let buttonSection = selection2.selectAll(".buttons").data(isSelected ? [_qaItem] : [], (d) => d.status + d.id);
buttonSection.exit().remove();
const buttonEnter = buttonSection.enter().append("div").attr("class", "buttons");
buttonEnter.append("button").attr("class", "button close-button action");
buttonEnter.append("button").attr("class", "button ignore-button action");
buttonSection = buttonSection.merge(buttonEnter);
buttonSection.select(".close-button").call(_t.append("QA.keepRight.close")).on("click.close", function(d3_event, d) {
this.blur();
const qaService = services.osmose;
if (qaService) {
d.newStatus = "done";
qaService.postUpdate(d, (err, item) => dispatch10.call("change", item));
}
});
buttonSection.select(".ignore-button").call(_t.append("QA.keepRight.ignore")).on("click.ignore", function(d3_event, d) {
this.blur();
const qaService = services.osmose;
if (qaService) {
d.newStatus = "false";
qaService.postUpdate(d, (err, item) => dispatch10.call("change", item));
}
});
}
osmoseEditor.error = function(val) {
if (!arguments.length)
return _qaItem;
_qaItem = val;
return osmoseEditor;
};
return utilRebind(osmoseEditor, dispatch10, "on");
}
// modules/ui/sidebar.js
function uiSidebar(context) {
var inspector = uiInspector(context);
var dataEditor = uiDataEditor(context);
var noteEditor = uiNoteEditor(context);
var improveOsmEditor = uiImproveOsmEditor(context);
var keepRightEditor = uiKeepRightEditor(context);
var osmoseEditor = uiOsmoseEditor(context);
var _current;
var _wasData = false;
var _wasNote = false;
var _wasQaItem = false;
var _pointerPrefix = "PointerEvent" in window ? "pointer" : "mouse";
function sidebar(selection2) {
var container = context.container();
var minWidth = 240;
var sidebarWidth;
var containerWidth;
var dragOffset;
selection2.style("min-width", minWidth + "px").style("max-width", "400px").style("width", "33.3333%");
var resizer = selection2.append("div").attr("class", "sidebar-resizer").on(_pointerPrefix + "down.sidebar-resizer", pointerdown);
var downPointerId, lastClientX, containerLocGetter;
function pointerdown(d3_event) {
if (downPointerId)
return;
if ("button" in d3_event && d3_event.button !== 0)
return;
downPointerId = d3_event.pointerId || "mouse";
lastClientX = d3_event.clientX;
containerLocGetter = utilFastMouse(container.node());
dragOffset = utilFastMouse(resizer.node())(d3_event)[0] - 1;
sidebarWidth = selection2.node().getBoundingClientRect().width;
containerWidth = container.node().getBoundingClientRect().width;
var widthPct = sidebarWidth / containerWidth * 100;
selection2.style("width", widthPct + "%").style("max-width", "85%");
resizer.classed("dragging", true);
select_default2(window).on("touchmove.sidebar-resizer", function(d3_event2) {
d3_event2.preventDefault();
}, { passive: false }).on(_pointerPrefix + "move.sidebar-resizer", pointermove).on(_pointerPrefix + "up.sidebar-resizer pointercancel.sidebar-resizer", pointerup);
}
function pointermove(d3_event) {
if (downPointerId !== (d3_event.pointerId || "mouse"))
return;
d3_event.preventDefault();
var dx = d3_event.clientX - lastClientX;
lastClientX = d3_event.clientX;
var isRTL = _mainLocalizer.textDirection() === "rtl";
var scaleX = isRTL ? 0 : 1;
var xMarginProperty = isRTL ? "margin-right" : "margin-left";
var x = containerLocGetter(d3_event)[0] - dragOffset;
sidebarWidth = isRTL ? containerWidth - x : x;
var isCollapsed = selection2.classed("collapsed");
var shouldCollapse = sidebarWidth < minWidth;
selection2.classed("collapsed", shouldCollapse);
if (shouldCollapse) {
if (!isCollapsed) {
selection2.style(xMarginProperty, "-400px").style("width", "400px");
context.ui().onResize([(sidebarWidth - dx) * scaleX, 0]);
}
} else {
var widthPct = sidebarWidth / containerWidth * 100;
selection2.style(xMarginProperty, null).style("width", widthPct + "%");
if (isCollapsed) {
context.ui().onResize([-sidebarWidth * scaleX, 0]);
} else {
context.ui().onResize([-dx * scaleX, 0]);
}
}
}
function pointerup(d3_event) {
if (downPointerId !== (d3_event.pointerId || "mouse"))
return;
downPointerId = null;
resizer.classed("dragging", false);
select_default2(window).on("touchmove.sidebar-resizer", null).on(_pointerPrefix + "move.sidebar-resizer", null).on(_pointerPrefix + "up.sidebar-resizer pointercancel.sidebar-resizer", null);
}
var featureListWrap = selection2.append("div").attr("class", "feature-list-pane").call(uiFeatureList(context));
var inspectorWrap = selection2.append("div").attr("class", "inspector-hidden inspector-wrap");
var hoverModeSelect = function(targets) {
context.container().selectAll(".feature-list-item button").classed("hover", false);
if (context.selectedIDs().length > 1 && targets && targets.length) {
var elements = context.container().selectAll(".feature-list-item button").filter(function(node) {
return targets.indexOf(node) !== -1;
});
if (!elements.empty()) {
elements.classed("hover", true);
}
}
};
sidebar.hoverModeSelect = throttle_default(hoverModeSelect, 200);
function hover(targets) {
var datum2 = targets && targets.length && targets[0];
if (datum2 && datum2.__featurehash__) {
_wasData = true;
sidebar.show(dataEditor.datum(datum2));
selection2.selectAll(".sidebar-component").classed("inspector-hover", true);
} else if (datum2 instanceof osmNote) {
if (context.mode().id === "drag-note")
return;
_wasNote = true;
var osm = services.osm;
if (osm) {
datum2 = osm.getNote(datum2.id);
}
sidebar.show(noteEditor.note(datum2));
selection2.selectAll(".sidebar-component").classed("inspector-hover", true);
} else if (datum2 instanceof QAItem) {
_wasQaItem = true;
var errService = services[datum2.service];
if (errService) {
datum2 = errService.getError(datum2.id);
}
var errEditor;
if (datum2.service === "keepRight") {
errEditor = keepRightEditor;
} else if (datum2.service === "osmose") {
errEditor = osmoseEditor;
} else {
errEditor = improveOsmEditor;
}
context.container().selectAll(".qaItem." + datum2.service).classed("hover", function(d) {
return d.id === datum2.id;
});
sidebar.show(errEditor.error(datum2));
selection2.selectAll(".sidebar-component").classed("inspector-hover", true);
} else if (!_current && datum2 instanceof osmEntity) {
featureListWrap.classed("inspector-hidden", true);
inspectorWrap.classed("inspector-hidden", false).classed("inspector-hover", true);
if (!inspector.entityIDs() || !utilArrayIdentical(inspector.entityIDs(), [datum2.id]) || inspector.state() !== "hover") {
inspector.state("hover").entityIDs([datum2.id]).newFeature(false);
inspectorWrap.call(inspector);
}
} else if (!_current) {
featureListWrap.classed("inspector-hidden", false);
inspectorWrap.classed("inspector-hidden", true);
inspector.state("hide");
} else if (_wasData || _wasNote || _wasQaItem) {
_wasNote = false;
_wasData = false;
_wasQaItem = false;
context.container().selectAll(".note").classed("hover", false);
context.container().selectAll(".qaItem").classed("hover", false);
sidebar.hide();
}
}
sidebar.hover = throttle_default(hover, 200);
sidebar.intersects = function(extent) {
var rect = selection2.node().getBoundingClientRect();
return extent.intersects([
context.projection.invert([0, rect.height]),
context.projection.invert([rect.width, 0])
]);
};
sidebar.select = function(ids, newFeature) {
sidebar.hide();
if (ids && ids.length) {
var entity = ids.length === 1 && context.entity(ids[0]);
if (entity && newFeature && selection2.classed("collapsed")) {
var extent = entity.extent(context.graph());
sidebar.expand(sidebar.intersects(extent));
}
featureListWrap.classed("inspector-hidden", true);
inspectorWrap.classed("inspector-hidden", false).classed("inspector-hover", false);
inspector.state("select").entityIDs(ids).newFeature(newFeature);
inspectorWrap.call(inspector);
} else {
inspector.state("hide");
}
};
sidebar.showPresetList = function() {
inspector.showList();
};
sidebar.show = function(component, element) {
featureListWrap.classed("inspector-hidden", true);
inspectorWrap.classed("inspector-hidden", true);
if (_current)
_current.remove();
_current = selection2.append("div").attr("class", "sidebar-component").call(component, element);
};
sidebar.hide = function() {
featureListWrap.classed("inspector-hidden", false);
inspectorWrap.classed("inspector-hidden", true);
if (_current)
_current.remove();
_current = null;
};
sidebar.expand = function(moveMap) {
if (selection2.classed("collapsed")) {
sidebar.toggle(moveMap);
}
};
sidebar.collapse = function(moveMap) {
if (!selection2.classed("collapsed")) {
sidebar.toggle(moveMap);
}
};
sidebar.toggle = function(moveMap) {
if (context.inIntro())
return;
var isCollapsed = selection2.classed("collapsed");
var isCollapsing = !isCollapsed;
var isRTL = _mainLocalizer.textDirection() === "rtl";
var scaleX = isRTL ? 0 : 1;
var xMarginProperty = isRTL ? "margin-right" : "margin-left";
sidebarWidth = selection2.node().getBoundingClientRect().width;
selection2.style("width", sidebarWidth + "px");
var startMargin, endMargin, lastMargin;
if (isCollapsing) {
startMargin = lastMargin = 0;
endMargin = -sidebarWidth;
} else {
startMargin = lastMargin = -sidebarWidth;
endMargin = 0;
}
if (!isCollapsing) {
selection2.classed("collapsed", isCollapsing);
}
selection2.transition().style(xMarginProperty, endMargin + "px").tween("panner", function() {
var i2 = number_default(startMargin, endMargin);
return function(t) {
var dx = lastMargin - Math.round(i2(t));
lastMargin = lastMargin - dx;
context.ui().onResize(moveMap ? void 0 : [dx * scaleX, 0]);
};
}).on("end", function() {
if (isCollapsing) {
selection2.classed("collapsed", isCollapsing);
}
if (!isCollapsing) {
var containerWidth2 = container.node().getBoundingClientRect().width;
var widthPct = sidebarWidth / containerWidth2 * 100;
selection2.style(xMarginProperty, null).style("width", widthPct + "%");
}
});
};
resizer.on("dblclick", function(d3_event) {
d3_event.preventDefault();
if (d3_event.sourceEvent) {
d3_event.sourceEvent.preventDefault();
}
sidebar.toggle();
});
context.map().on("crossEditableZoom.sidebar", function(within) {
if (!within && !selection2.select(".inspector-hover").empty()) {
hover([]);
}
});
}
sidebar.showPresetList = function() {
};
sidebar.hover = function() {
};
sidebar.hover.cancel = function() {
};
sidebar.intersects = function() {
};
sidebar.select = function() {
};
sidebar.show = function() {
};
sidebar.hide = function() {
};
sidebar.expand = function() {
};
sidebar.collapse = function() {
};
sidebar.toggle = function() {
};
return sidebar;
}
// modules/modes/draw_area.js
function modeDrawArea(context, wayID, startGraph, button) {
var mode = {
button,
id: "draw-area"
};
var behavior = behaviorDrawWay(context, wayID, mode, startGraph).on("rejectedSelfIntersection.modeDrawArea", function() {
context.ui().flash.iconName("#iD-icon-no").label(_t.html("self_intersection.error.areas"))();
});
mode.wayID = wayID;
mode.enter = function() {
context.install(behavior);
};
mode.exit = function() {
context.uninstall(behavior);
};
mode.selectedIDs = function() {
return [wayID];
};
mode.activeID = function() {
return behavior && behavior.activeID() || [];
};
return mode;
}
// modules/modes/add_area.js
function modeAddArea(context, mode) {
mode.id = "add-area";
var behavior = behaviorAddWay(context).on("start", start2).on("startFromWay", startFromWay).on("startFromNode", startFromNode);
var defaultTags = { area: "yes" };
if (mode.preset)
defaultTags = mode.preset.setTags(defaultTags, "area");
function actionClose(wayId) {
return function(graph) {
return graph.replace(graph.entity(wayId).close());
};
}
function start2(loc) {
var startGraph = context.graph();
var node = osmNode({ loc });
var way = osmWay({ tags: defaultTags });
context.perform(actionAddEntity(node), actionAddEntity(way), actionAddVertex(way.id, node.id), actionClose(way.id));
context.enter(modeDrawArea(context, way.id, startGraph, mode.button));
}
function startFromWay(loc, edge) {
var startGraph = context.graph();
var node = osmNode({ loc });
var way = osmWay({ tags: defaultTags });
context.perform(actionAddEntity(node), actionAddEntity(way), actionAddVertex(way.id, node.id), actionClose(way.id), actionAddMidpoint({ loc, edge }, node));
context.enter(modeDrawArea(context, way.id, startGraph, mode.button));
}
function startFromNode(node) {
var startGraph = context.graph();
var way = osmWay({ tags: defaultTags });
context.perform(actionAddEntity(way), actionAddVertex(way.id, node.id), actionClose(way.id));
context.enter(modeDrawArea(context, way.id, startGraph, mode.button));
}
mode.enter = function() {
context.install(behavior);
};
mode.exit = function() {
context.uninstall(behavior);
};
return mode;
}
// modules/modes/add_line.js
function modeAddLine(context, mode) {
mode.id = "add-line";
var behavior = behaviorAddWay(context).on("start", start2).on("startFromWay", startFromWay).on("startFromNode", startFromNode);
var defaultTags = {};
if (mode.preset)
defaultTags = mode.preset.setTags(defaultTags, "line");
function start2(loc) {
var startGraph = context.graph();
var node = osmNode({ loc });
var way = osmWay({ tags: defaultTags });
context.perform(actionAddEntity(node), actionAddEntity(way), actionAddVertex(way.id, node.id));
context.enter(modeDrawLine(context, way.id, startGraph, mode.button));
}
function startFromWay(loc, edge) {
var startGraph = context.graph();
var node = osmNode({ loc });
var way = osmWay({ tags: defaultTags });
context.perform(actionAddEntity(node), actionAddEntity(way), actionAddVertex(way.id, node.id), actionAddMidpoint({ loc, edge }, node));
context.enter(modeDrawLine(context, way.id, startGraph, mode.button));
}
function startFromNode(node) {
var startGraph = context.graph();
var way = osmWay({ tags: defaultTags });
context.perform(actionAddEntity(way), actionAddVertex(way.id, node.id));
context.enter(modeDrawLine(context, way.id, startGraph, mode.button));
}
mode.enter = function() {
context.install(behavior);
};
mode.exit = function() {
context.uninstall(behavior);
};
return mode;
}
// modules/modes/add_point.js
function modeAddPoint(context, mode) {
mode.id = "add-point";
var behavior = behaviorDraw(context).on("click", add).on("clickWay", addWay).on("clickNode", addNode).on("cancel", cancel).on("finish", cancel);
var defaultTags = {};
if (mode.preset)
defaultTags = mode.preset.setTags(defaultTags, "point");
function add(loc) {
var node = osmNode({ loc, tags: defaultTags });
context.perform(actionAddEntity(node), _t("operations.add.annotation.point"));
enterSelectMode(node);
}
function addWay(loc, edge) {
var node = osmNode({ tags: defaultTags });
context.perform(actionAddMidpoint({ loc, edge }, node), _t("operations.add.annotation.vertex"));
enterSelectMode(node);
}
function enterSelectMode(node) {
context.enter(modeSelect(context, [node.id]).newFeature(true));
}
function addNode(node) {
if (Object.keys(defaultTags).length === 0) {
enterSelectMode(node);
return;
}
var tags = Object.assign({}, node.tags);
for (var key in defaultTags) {
tags[key] = defaultTags[key];
}
context.perform(actionChangeTags(node.id, tags), _t("operations.add.annotation.point"));
enterSelectMode(node);
}
function cancel() {
context.enter(modeBrowse(context));
}
mode.enter = function() {
context.install(behavior);
};
mode.exit = function() {
context.uninstall(behavior);
};
return mode;
}
// modules/modes/select_note.js
function modeSelectNote(context, selectedNoteID) {
var mode = {
id: "select-note",
button: "browse"
};
var _keybinding = utilKeybinding("select-note");
var _noteEditor = uiNoteEditor(context).on("change", function() {
context.map().pan([0, 0]);
var note = checkSelectedID();
if (!note)
return;
context.ui().sidebar.show(_noteEditor.note(note));
});
var _behaviors = [
behaviorBreathe(context),
behaviorHover(context),
behaviorSelect(context),
behaviorLasso(context),
modeDragNode(context).behavior,
modeDragNote(context).behavior
];
var _newFeature = false;
function checkSelectedID() {
if (!services.osm)
return;
var note = services.osm.getNote(selectedNoteID);
if (!note) {
context.enter(modeBrowse(context));
}
return note;
}
function selectNote(d3_event, drawn) {
if (!checkSelectedID())
return;
var selection2 = context.surface().selectAll(".layer-notes .note-" + selectedNoteID);
if (selection2.empty()) {
var source = d3_event && d3_event.type === "zoom" && d3_event.sourceEvent;
if (drawn && source && (source.type === "pointermove" || source.type === "mousemove" || source.type === "touchmove")) {
context.enter(modeBrowse(context));
}
} else {
selection2.classed("selected", true);
context.selectedNoteID(selectedNoteID);
}
}
function esc() {
if (context.container().select(".combobox").size())
return;
context.enter(modeBrowse(context));
}
mode.zoomToSelected = function() {
if (!services.osm)
return;
var note = services.osm.getNote(selectedNoteID);
if (note) {
context.map().centerZoomEase(note.loc, 20);
}
};
mode.newFeature = function(val) {
if (!arguments.length)
return _newFeature;
_newFeature = val;
return mode;
};
mode.enter = function() {
var note = checkSelectedID();
if (!note)
return;
_behaviors.forEach(context.install);
_keybinding.on(_t("inspector.zoom_to.key"), mode.zoomToSelected).on("\u238B", esc, true);
select_default2(document).call(_keybinding);
selectNote();
var sidebar = context.ui().sidebar;
sidebar.show(_noteEditor.note(note).newNote(_newFeature));
sidebar.expand(sidebar.intersects(note.extent()));
context.map().on("drawn.select", selectNote);
};
mode.exit = function() {
_behaviors.forEach(context.uninstall);
select_default2(document).call(_keybinding.unbind);
context.surface().selectAll(".layer-notes .selected").classed("selected hover", false);
context.map().on("drawn.select", null);
context.ui().sidebar.hide();
context.selectedNoteID(null);
};
return mode;
}
// modules/modes/add_note.js
function modeAddNote(context) {
var mode = {
id: "add-note",
button: "note",
description: _t.html("modes.add_note.description"),
key: _t("modes.add_note.key")
};
var behavior = behaviorDraw(context).on("click", add).on("cancel", cancel).on("finish", cancel);
function add(loc) {
var osm = services.osm;
if (!osm)
return;
var note = osmNote({ loc, status: "open", comments: [] });
osm.replaceNote(note);
context.map().pan([0, 0]);
context.selectedNoteID(note.id).enter(modeSelectNote(context, note.id).newFeature(true));
}
function cancel() {
context.enter(modeBrowse(context));
}
mode.enter = function() {
context.install(behavior);
};
mode.exit = function() {
context.uninstall(behavior);
};
return mode;
}
// modules/modes/save.js
function modeSave(context) {
var mode = { id: "save" };
var keybinding = utilKeybinding("modeSave");
var commit = uiCommit(context).on("cancel", cancel);
var _conflictsUi;
var _location;
var _success;
var uploader = context.uploader().on("saveStarted.modeSave", function() {
keybindingOff();
}).on("willAttemptUpload.modeSave", prepareForSuccess).on("progressChanged.modeSave", showProgress).on("resultNoChanges.modeSave", function() {
cancel();
}).on("resultErrors.modeSave", showErrors).on("resultConflicts.modeSave", showConflicts).on("resultSuccess.modeSave", showSuccess);
function cancel() {
context.enter(modeBrowse(context));
}
function showProgress(num, total) {
var modal = context.container().select(".loading-modal .modal-section");
var progress = modal.selectAll(".progress").data([0]);
progress.enter().append("div").attr("class", "progress").merge(progress).text(_t("save.conflict_progress", { num, total }));
}
function showConflicts(changeset, conflicts, origChanges) {
var selection2 = context.container().select(".sidebar").append("div").attr("class", "sidebar-component");
context.container().selectAll(".main-content").classed("active", true).classed("inactive", false);
_conflictsUi = uiConflicts(context).conflictList(conflicts).origChanges(origChanges).on("cancel", function() {
context.container().selectAll(".main-content").classed("active", false).classed("inactive", true);
selection2.remove();
keybindingOn();
uploader.cancelConflictResolution();
}).on("save", function() {
context.container().selectAll(".main-content").classed("active", false).classed("inactive", true);
selection2.remove();
uploader.processResolvedConflicts(changeset);
});
selection2.call(_conflictsUi);
}
function showErrors(errors) {
keybindingOn();
var selection2 = uiConfirm(context.container());
selection2.select(".modal-section.header").append("h3").text(_t("save.error"));
addErrors(selection2, errors);
selection2.okButton();
}
function addErrors(selection2, data) {
var message = selection2.select(".modal-section.message-text");
var items = message.selectAll(".error-container").data(data);
var enter = items.enter().append("div").attr("class", "error-container");
enter.append("a").attr("class", "error-description").attr("href", "#").classed("hide-toggle", true).text(function(d) {
return d.msg || _t("save.unknown_error_details");
}).on("click", function(d3_event) {
d3_event.preventDefault();
var error = select_default2(this);
var detail = select_default2(this.nextElementSibling);
var exp2 = error.classed("expanded");
detail.style("display", exp2 ? "none" : "block");
error.classed("expanded", !exp2);
});
var details = enter.append("div").attr("class", "error-detail-container").style("display", "none");
details.append("ul").attr("class", "error-detail-list").selectAll("li").data(function(d) {
return d.details || [];
}).enter().append("li").attr("class", "error-detail-item").text(function(d) {
return d;
});
items.exit().remove();
}
function showSuccess(changeset) {
commit.reset();
var ui = _success.changeset(changeset).location(_location).on("cancel", function() {
context.ui().sidebar.hide();
});
context.enter(modeBrowse(context).sidebar(ui));
}
function keybindingOn() {
select_default2(document).call(keybinding.on("\u238B", cancel, true));
}
function keybindingOff() {
select_default2(document).call(keybinding.unbind);
}
function prepareForSuccess() {
_success = uiSuccess(context);
_location = null;
if (!services.geocoder)
return;
services.geocoder.reverse(context.map().center(), function(err, result) {
if (err || !result || !result.address)
return;
var addr = result.address;
var place = addr && (addr.town || addr.city || addr.county) || "";
var region = addr && (addr.state || addr.country) || "";
var separator = place && region ? _t("success.thank_you_where.separator") : "";
_location = _t("success.thank_you_where.format", { place, separator, region });
});
}
mode.selectedIDs = function() {
return _conflictsUi ? _conflictsUi.shownEntityIds() : [];
};
mode.enter = function() {
context.ui().sidebar.expand();
function done() {
context.ui().sidebar.show(commit);
}
keybindingOn();
context.container().selectAll(".main-content").classed("active", false).classed("inactive", true);
var osm = context.connection();
if (!osm) {
cancel();
return;
}
if (osm.authenticated()) {
done();
} else {
osm.authenticate(function(err) {
if (err) {
cancel();
} else {
done();
}
});
}
};
mode.exit = function() {
keybindingOff();
context.container().selectAll(".main-content").classed("active", true).classed("inactive", false);
context.ui().sidebar.hide();
};
return mode;
}
// modules/modes/select_error.js
function modeSelectError(context, selectedErrorID, selectedErrorService) {
var mode = {
id: "select-error",
button: "browse"
};
var keybinding = utilKeybinding("select-error");
var errorService = services[selectedErrorService];
var errorEditor;
switch (selectedErrorService) {
case "improveOSM":
errorEditor = uiImproveOsmEditor(context).on("change", function() {
context.map().pan([0, 0]);
var error = checkSelectedID();
if (!error)
return;
context.ui().sidebar.show(errorEditor.error(error));
});
break;
case "keepRight":
errorEditor = uiKeepRightEditor(context).on("change", function() {
context.map().pan([0, 0]);
var error = checkSelectedID();
if (!error)
return;
context.ui().sidebar.show(errorEditor.error(error));
});
break;
case "osmose":
errorEditor = uiOsmoseEditor(context).on("change", function() {
context.map().pan([0, 0]);
var error = checkSelectedID();
if (!error)
return;
context.ui().sidebar.show(errorEditor.error(error));
});
break;
}
var behaviors = [
behaviorBreathe(context),
behaviorHover(context),
behaviorSelect(context),
behaviorLasso(context),
modeDragNode(context).behavior,
modeDragNote(context).behavior
];
function checkSelectedID() {
if (!errorService)
return;
var error = errorService.getError(selectedErrorID);
if (!error) {
context.enter(modeBrowse(context));
}
return error;
}
mode.zoomToSelected = function() {
if (!errorService)
return;
var error = errorService.getError(selectedErrorID);
if (error) {
context.map().centerZoomEase(error.loc, 20);
}
};
mode.enter = function() {
var error = checkSelectedID();
if (!error)
return;
behaviors.forEach(context.install);
keybinding.on(_t("inspector.zoom_to.key"), mode.zoomToSelected).on("\u238B", esc, true);
select_default2(document).call(keybinding);
selectError();
var sidebar = context.ui().sidebar;
sidebar.show(errorEditor.error(error));
context.map().on("drawn.select-error", selectError);
function selectError(d3_event, drawn) {
if (!checkSelectedID())
return;
var selection2 = context.surface().selectAll(".itemId-" + selectedErrorID + "." + selectedErrorService);
if (selection2.empty()) {
var source = d3_event && d3_event.type === "zoom" && d3_event.sourceEvent;
if (drawn && source && (source.type === "pointermove" || source.type === "mousemove" || source.type === "touchmove")) {
context.enter(modeBrowse(context));
}
} else {
selection2.classed("selected", true);
context.selectedErrorID(selectedErrorID);
}
}
function esc() {
if (context.container().select(".combobox").size())
return;
context.enter(modeBrowse(context));
}
};
mode.exit = function() {
behaviors.forEach(context.uninstall);
select_default2(document).call(keybinding.unbind);
context.surface().selectAll(".qaItem.selected").classed("selected hover", false);
context.map().on("drawn.select-error", null);
context.ui().sidebar.hide();
context.selectedErrorID(null);
context.features().forceVisible([]);
};
return mode;
}
// modules/ui/tools/modes.js
function uiToolDrawModes(context) {
var tool = {
id: "old_modes",
label: _t.html("toolbar.add_feature")
};
var modes = [
modeAddPoint(context, {
title: _t.html("modes.add_point.title"),
button: "point",
description: _t.html("modes.add_point.description"),
preset: _mainPresetIndex.item("point"),
key: "1"
}),
modeAddLine(context, {
title: _t.html("modes.add_line.title"),
button: "line",
description: _t.html("modes.add_line.description"),
preset: _mainPresetIndex.item("line"),
key: "2"
}),
modeAddArea(context, {
title: _t.html("modes.add_area.title"),
button: "area",
description: _t.html("modes.add_area.description"),
preset: _mainPresetIndex.item("area"),
key: "3"
})
];
function enabled(_mode) {
return osmEditable();
}
function osmEditable() {
return context.editable();
}
modes.forEach(function(mode) {
context.keybinding().on(mode.key, function() {
if (!enabled(mode))
return;
if (mode.id === context.mode().id) {
context.enter(modeBrowse(context));
} else {
context.enter(mode);
}
});
});
tool.render = function(selection2) {
var wrap2 = selection2.append("div").attr("class", "joined").style("display", "flex");
var debouncedUpdate = debounce_default(update, 500, { leading: true, trailing: true });
context.map().on("move.modes", debouncedUpdate).on("drawn.modes", debouncedUpdate);
context.on("enter.modes", update);
update();
function update() {
var buttons = wrap2.selectAll("button.add-button").data(modes, function(d) {
return d.id;
});
buttons.exit().remove();
var buttonsEnter = buttons.enter().append("button").attr("class", function(d) {
return d.id + " add-button bar-button";
}).on("click.mode-buttons", function(d3_event, d) {
if (!enabled(d))
return;
var currMode = context.mode().id;
if (/^draw/.test(currMode))
return;
if (d.id === currMode) {
context.enter(modeBrowse(context));
} else {
context.enter(d);
}
}).call(uiTooltip().placement("bottom").title(function(d) {
return d.description;
}).keys(function(d) {
return [d.key];
}).scrollContainer(context.container().select(".top-toolbar")));
buttonsEnter.each(function(d) {
select_default2(this).call(svgIcon("#iD-icon-" + d.button));
});
buttonsEnter.append("span").attr("class", "label").html(function(mode) {
return mode.title;
});
if (buttons.enter().size() || buttons.exit().size()) {
context.ui().checkOverflow(".top-toolbar", true);
}
buttons = buttons.merge(buttonsEnter).attr("aria-disabled", function(d) {
return !enabled(d);
}).classed("disabled", function(d) {
return !enabled(d);
}).attr("aria-pressed", function(d) {
return context.mode() && context.mode().button === d.button;
}).classed("active", function(d) {
return context.mode() && context.mode().button === d.button;
});
}
};
return tool;
}
// modules/ui/tools/notes.js
function uiToolNotes(context) {
var tool = {
id: "notes",
label: _t.html("modes.add_note.label")
};
var mode = modeAddNote(context);
function enabled() {
return notesEnabled() && notesEditable();
}
function notesEnabled() {
var noteLayer = context.layers().layer("notes");
return noteLayer && noteLayer.enabled();
}
function notesEditable() {
var mode2 = context.mode();
return context.map().notesEditable() && mode2 && mode2.id !== "save";
}
context.keybinding().on(mode.key, function() {
if (!enabled())
return;
if (mode.id === context.mode().id) {
context.enter(modeBrowse(context));
} else {
context.enter(mode);
}
});
tool.render = function(selection2) {
var debouncedUpdate = debounce_default(update, 500, { leading: true, trailing: true });
context.map().on("move.notes", debouncedUpdate).on("drawn.notes", debouncedUpdate);
context.on("enter.notes", update);
update();
function update() {
var showNotes = notesEnabled();
var data = showNotes ? [mode] : [];
var buttons = selection2.selectAll("button.add-button").data(data, function(d) {
return d.id;
});
buttons.exit().remove();
var buttonsEnter = buttons.enter().append("button").attr("class", function(d) {
return d.id + " add-button bar-button";
}).on("click.notes", function(d3_event, d) {
if (!enabled())
return;
var currMode = context.mode().id;
if (/^draw/.test(currMode))
return;
if (d.id === currMode) {
context.enter(modeBrowse(context));
} else {
context.enter(d);
}
}).call(uiTooltip().placement("bottom").title(function(d) {
return d.description;
}).keys(function(d) {
return [d.key];
}).scrollContainer(context.container().select(".top-toolbar")));
buttonsEnter.each(function(d) {
select_default2(this).call(svgIcon(d.icon || "#iD-icon-" + d.button));
});
if (buttons.enter().size() || buttons.exit().size()) {
context.ui().checkOverflow(".top-toolbar", true);
}
buttons = buttons.merge(buttonsEnter).classed("disabled", function() {
return !enabled();
}).attr("aria-disabled", function() {
return !enabled();
}).classed("active", function(d) {
return context.mode() && context.mode().button === d.button;
}).attr("aria-pressed", function(d) {
return context.mode() && context.mode().button === d.button;
});
}
};
tool.uninstall = function() {
context.on("enter.editor.notes", null).on("exit.editor.notes", null).on("enter.notes", null);
context.map().on("move.notes", null).on("drawn.notes", null);
};
return tool;
}
// modules/ui/tools/save.js
function uiToolSave(context) {
var tool = {
id: "save",
label: _t.html("save.title")
};
var button = null;
var tooltipBehavior = null;
var history = context.history();
var key = uiCmd("\u2318S");
var _numChanges = 0;
function isSaving() {
var mode = context.mode();
return mode && mode.id === "save";
}
function isDisabled() {
return _numChanges === 0 || isSaving();
}
function save(d3_event) {
d3_event.preventDefault();
if (!context.inIntro() && !isSaving() && history.hasChanges()) {
context.enter(modeSave(context));
}
}
function bgColor(numChanges) {
var step;
if (numChanges === 0) {
return null;
} else if (numChanges <= 50) {
step = numChanges / 50;
return rgb_default("#fff", "#ff8")(step);
} else {
step = Math.min((numChanges - 50) / 50, 1);
return rgb_default("#ff8", "#f88")(step);
}
}
function updateCount() {
var val = history.difference().summary().length;
if (val === _numChanges)
return;
_numChanges = val;
if (tooltipBehavior) {
tooltipBehavior.title(_t.html(_numChanges > 0 ? "save.help" : "save.no_changes")).keys([key]);
}
if (button) {
button.classed("disabled", isDisabled()).style("background", bgColor(_numChanges));
button.select("span.count").text(_numChanges);
}
}
tool.render = function(selection2) {
tooltipBehavior = uiTooltip().placement("bottom").title(_t.html("save.no_changes")).keys([key]).scrollContainer(context.container().select(".top-toolbar"));
var lastPointerUpType;
button = selection2.append("button").attr("class", "save disabled bar-button").on("pointerup", function(d3_event) {
lastPointerUpType = d3_event.pointerType;
}).on("click", function(d3_event) {
save(d3_event);
if (_numChanges === 0 && (lastPointerUpType === "touch" || lastPointerUpType === "pen")) {
context.ui().flash.duration(2e3).iconName("#iD-icon-save").iconClass("disabled").label(_t.html("save.no_changes"))();
}
lastPointerUpType = null;
}).call(tooltipBehavior);
button.call(svgIcon("#iD-icon-save"));
button.append("span").attr("class", "count").attr("aria-hidden", "true").text("0");
updateCount();
context.keybinding().on(key, save, true);
context.history().on("change.save", updateCount);
context.on("enter.save", function() {
if (button) {
button.classed("disabled", isDisabled());
if (isSaving()) {
button.call(tooltipBehavior.hide);
}
}
});
};
tool.uninstall = function() {
context.keybinding().off(key, true);
context.history().on("change.save", null);
context.on("enter.save", null);
button = null;
tooltipBehavior = null;
};
return tool;
}
// modules/ui/tools/sidebar_toggle.js
function uiToolSidebarToggle(context) {
var tool = {
id: "sidebar_toggle",
label: _t.html("toolbar.inspect")
};
tool.render = function(selection2) {
selection2.append("button").attr("class", "bar-button").attr("aria-label", _t("sidebar.tooltip")).on("click", function() {
context.ui().sidebar.toggle();
}).call(uiTooltip().placement("bottom").title(_t.html("sidebar.tooltip")).keys([_t("sidebar.key")]).scrollContainer(context.container().select(".top-toolbar"))).call(svgIcon("#iD-icon-sidebar-" + (_mainLocalizer.textDirection() === "rtl" ? "right" : "left")));
};
return tool;
}
// modules/ui/tools/undo_redo.js
function uiToolUndoRedo(context) {
var tool = {
id: "undo_redo",
label: _t.html("toolbar.undo_redo")
};
var commands = [{
id: "undo",
cmd: uiCmd("\u2318Z"),
action: function() {
context.undo();
},
annotation: function() {
return context.history().undoAnnotation();
},
icon: "iD-icon-" + (_mainLocalizer.textDirection() === "rtl" ? "redo" : "undo")
}, {
id: "redo",
cmd: uiCmd("\u2318\u21E7Z"),
action: function() {
context.redo();
},
annotation: function() {
return context.history().redoAnnotation();
},
icon: "iD-icon-" + (_mainLocalizer.textDirection() === "rtl" ? "undo" : "redo")
}];
function editable() {
return context.mode() && context.mode().id !== "save" && context.map().editableDataEnabled(true);
}
tool.render = function(selection2) {
var tooltipBehavior = uiTooltip().placement("bottom").title(function(d) {
return d.annotation() ? _t.html(d.id + ".tooltip", { action: d.annotation() }) : _t.html(d.id + ".nothing");
}).keys(function(d) {
return [d.cmd];
}).scrollContainer(context.container().select(".top-toolbar"));
var lastPointerUpType;
var buttons = selection2.selectAll("button").data(commands).enter().append("button").attr("class", function(d) {
return "disabled " + d.id + "-button bar-button";
}).on("pointerup", function(d3_event) {
lastPointerUpType = d3_event.pointerType;
}).on("click", function(d3_event, d) {
d3_event.preventDefault();
var annotation = d.annotation();
if (editable() && annotation) {
d.action();
}
if (editable() && (lastPointerUpType === "touch" || lastPointerUpType === "pen")) {
var text2 = annotation ? _t.html(d.id + ".tooltip", { action: annotation }) : _t.html(d.id + ".nothing");
context.ui().flash.duration(2e3).iconName("#" + d.icon).iconClass(annotation ? "" : "disabled").label(text2)();
}
lastPointerUpType = null;
}).call(tooltipBehavior);
buttons.each(function(d) {
select_default2(this).call(svgIcon("#" + d.icon));
});
context.keybinding().on(commands[0].cmd, function(d3_event) {
d3_event.preventDefault();
if (editable())
commands[0].action();
}).on(commands[1].cmd, function(d3_event) {
d3_event.preventDefault();
if (editable())
commands[1].action();
});
var debouncedUpdate = debounce_default(update, 500, { leading: true, trailing: true });
context.map().on("move.undo_redo", debouncedUpdate).on("drawn.undo_redo", debouncedUpdate);
context.history().on("change.undo_redo", function(difference) {
if (difference)
update();
});
context.on("enter.undo_redo", update);
function update() {
buttons.classed("disabled", function(d) {
return !editable() || !d.annotation();
}).each(function() {
var selection3 = select_default2(this);
if (!selection3.select(".tooltip.in").empty()) {
selection3.call(tooltipBehavior.updateContent);
}
});
}
};
tool.uninstall = function() {
context.keybinding().off(commands[0].cmd).off(commands[1].cmd);
context.map().on("move.undo_redo", null).on("drawn.undo_redo", null);
context.history().on("change.undo_redo", null);
context.on("enter.undo_redo", null);
};
return tool;
}
// modules/ui/top_toolbar.js
function uiTopToolbar(context) {
var sidebarToggle = uiToolSidebarToggle(context), modes = uiToolDrawModes(context), notes = uiToolNotes(context), undoRedo = uiToolUndoRedo(context), save = uiToolSave(context);
function notesEnabled() {
var noteLayer = context.layers().layer("notes");
return noteLayer && noteLayer.enabled();
}
function topToolbar(bar) {
bar.on("wheel.topToolbar", function(d3_event) {
if (!d3_event.deltaX) {
bar.node().scrollLeft += d3_event.deltaY;
}
});
var debouncedUpdate = debounce_default(update, 500, { leading: true, trailing: true });
context.layers().on("change.topToolbar", debouncedUpdate);
update();
function update() {
var tools = [
sidebarToggle,
"spacer",
modes
];
tools.push("spacer");
if (notesEnabled()) {
tools = tools.concat([notes, "spacer"]);
}
tools = tools.concat([undoRedo, save]);
var toolbarItems = bar.selectAll(".toolbar-item").data(tools, function(d) {
return d.id || d;
});
toolbarItems.exit().each(function(d) {
if (d.uninstall) {
d.uninstall();
}
}).remove();
var itemsEnter = toolbarItems.enter().append("div").attr("class", function(d) {
var classes = "toolbar-item " + (d.id || d).replace("_", "-");
if (d.klass)
classes += " " + d.klass;
return classes;
});
var actionableItems = itemsEnter.filter(function(d) {
return d !== "spacer";
});
actionableItems.append("div").attr("class", "item-content").each(function(d) {
select_default2(this).call(d.render, bar);
});
actionableItems.append("div").attr("class", "item-label").html(function(d) {
return d.label;
});
}
}
return topToolbar;
}
// modules/ui/zoom_to_selection.js
function uiZoomToSelection(context) {
function isDisabled() {
var mode = context.mode();
return !mode || !mode.zoomToSelected;
}
var _lastPointerUpType;
function pointerup(d3_event) {
_lastPointerUpType = d3_event.pointerType;
}
function click(d3_event) {
d3_event.preventDefault();
if (isDisabled()) {
if (_lastPointerUpType === "touch" || _lastPointerUpType === "pen") {
context.ui().flash.duration(2e3).iconName("#iD-icon-framed-dot").iconClass("disabled").label(_t.html("inspector.zoom_to.no_selection"))();
}
} else {
var mode = context.mode();
if (mode && mode.zoomToSelected) {
mode.zoomToSelected();
}
}
_lastPointerUpType = null;
}
return function(selection2) {
var tooltipBehavior = uiTooltip().placement(_mainLocalizer.textDirection() === "rtl" ? "right" : "left").title(function() {
if (isDisabled()) {
return _t.html("inspector.zoom_to.no_selection");
}
return _t.html("inspector.zoom_to.title");
}).keys([_t("inspector.zoom_to.key")]);
var button = selection2.append("button").on("pointerup", pointerup).on("click", click).call(svgIcon("#iD-icon-framed-dot", "light")).call(tooltipBehavior);
function setEnabledState() {
button.classed("disabled", isDisabled());
if (!button.select(".tooltip.in").empty()) {
button.call(tooltipBehavior.updateContent);
}
}
context.on("enter.uiZoomToSelection", setEnabledState);
setEnabledState();
};
}
// modules/ui/pane.js
function uiPane(id2, context) {
var _key;
var _label = "";
var _description = "";
var _iconName = "";
var _sections;
var _paneSelection = select_default2(null);
var _paneTooltip;
var pane = {
id: id2
};
pane.label = function(val) {
if (!arguments.length)
return _label;
_label = val;
return pane;
};
pane.key = function(val) {
if (!arguments.length)
return _key;
_key = val;
return pane;
};
pane.description = function(val) {
if (!arguments.length)
return _description;
_description = val;
return pane;
};
pane.iconName = function(val) {
if (!arguments.length)
return _iconName;
_iconName = val;
return pane;
};
pane.sections = function(val) {
if (!arguments.length)
return _sections;
_sections = val;
return pane;
};
pane.selection = function() {
return _paneSelection;
};
function hidePane() {
context.ui().togglePanes();
}
pane.togglePane = function(d3_event) {
if (d3_event)
d3_event.preventDefault();
_paneTooltip.hide();
context.ui().togglePanes(!_paneSelection.classed("shown") ? _paneSelection : void 0);
};
pane.renderToggleButton = function(selection2) {
if (!_paneTooltip) {
_paneTooltip = uiTooltip().placement(_mainLocalizer.textDirection() === "rtl" ? "right" : "left").title(_description).keys([_key]);
}
selection2.append("button").on("click", pane.togglePane).call(svgIcon("#" + _iconName, "light")).call(_paneTooltip);
};
pane.renderContent = function(selection2) {
if (_sections) {
_sections.forEach(function(section) {
selection2.call(section.render);
});
}
};
pane.renderPane = function(selection2) {
_paneSelection = selection2.append("div").attr("class", "fillL map-pane hide " + id2 + "-pane").attr("pane", id2);
var heading = _paneSelection.append("div").attr("class", "pane-heading");
heading.append("h2").html(_label);
heading.append("button").attr("title", _t("icons.close")).on("click", hidePane).call(svgIcon("#iD-icon-close"));
_paneSelection.append("div").attr("class", "pane-content").call(pane.renderContent);
if (_key) {
context.keybinding().on(_key, pane.togglePane);
}
};
return pane;
}
// modules/ui/sections/background_display_options.js
function uiSectionBackgroundDisplayOptions(context) {
var section = uiSection("background-display-options", context).label(_t.html("background.display_options")).disclosureContent(renderDisclosureContent);
var _storedOpacity = corePreferences("background-opacity");
var _minVal = 0;
var _maxVal = 3;
var _sliders = ["brightness", "contrast", "saturation", "sharpness"];
var _options = {
brightness: _storedOpacity !== null ? +_storedOpacity : 1,
contrast: 1,
saturation: 1,
sharpness: 1
};
function clamp3(x, min3, max3) {
return Math.max(min3, Math.min(x, max3));
}
function updateValue(d, val) {
val = clamp3(val, _minVal, _maxVal);
_options[d] = val;
context.background()[d](val);
if (d === "brightness") {
corePreferences("background-opacity", val);
}
section.reRender();
}
function renderDisclosureContent(selection2) {
var container = selection2.selectAll(".display-options-container").data([0]);
var containerEnter = container.enter().append("div").attr("class", "display-options-container controls-list");
var slidersEnter = containerEnter.selectAll(".display-control").data(_sliders).enter().append("label").attr("class", function(d) {
return "display-control display-control-" + d;
});
slidersEnter.html(function(d) {
return _t.html("background." + d);
}).append("span").attr("class", function(d) {
return "display-option-value display-option-value-" + d;
});
var sildersControlEnter = slidersEnter.append("div").attr("class", "control-wrap");
sildersControlEnter.append("input").attr("class", function(d) {
return "display-option-input display-option-input-" + d;
}).attr("type", "range").attr("min", _minVal).attr("max", _maxVal).attr("step", "0.05").on("input", function(d3_event, d) {
var val = select_default2(this).property("value");
if (!val && d3_event && d3_event.target) {
val = d3_event.target.value;
}
updateValue(d, val);
});
sildersControlEnter.append("button").attr("title", function(d) {
return `${_t("background.reset")} ${_t("background." + d)}`;
}).attr("class", function(d) {
return "display-option-reset display-option-reset-" + d;
}).on("click", function(d3_event, d) {
if (d3_event.button !== 0)
return;
updateValue(d, 1);
}).call(svgIcon("#iD-icon-" + (_mainLocalizer.textDirection() === "rtl" ? "redo" : "undo")));
containerEnter.append("a").attr("class", "display-option-resetlink").attr("role", "button").attr("href", "#").call(_t.append("background.reset_all")).on("click", function(d3_event) {
d3_event.preventDefault();
for (var i2 = 0; i2 < _sliders.length; i2++) {
updateValue(_sliders[i2], 1);
}
});
container = containerEnter.merge(container);
container.selectAll(".display-option-input").property("value", function(d) {
return _options[d];
});
container.selectAll(".display-option-value").text(function(d) {
return Math.floor(_options[d] * 100) + "%";
});
container.selectAll(".display-option-reset").classed("disabled", function(d) {
return _options[d] === 1;
});
if (containerEnter.size() && _options.brightness !== 1) {
context.background().brightness(_options.brightness);
}
}
return section;
}
// modules/ui/settings/custom_background.js
function uiSettingsCustomBackground() {
var dispatch10 = dispatch_default("change");
function render(selection2) {
var _origSettings = {
template: corePreferences("background-custom-template")
};
var _currSettings = {
template: corePreferences("background-custom-template")
};
var example = "https://{switch:a,b,c}.tile.openstreetmap.org/{zoom}/{x}/{y}.png";
var modal = uiConfirm(selection2).okButton();
modal.classed("settings-modal settings-custom-background", true);
modal.select(".modal-section.header").append("h3").call(_t.append("settings.custom_background.header"));
var textSection = modal.select(".modal-section.message-text");
var instructions = `${_t.html("settings.custom_background.instructions.info")}
#### ${_t.html("settings.custom_background.instructions.wms.tokens_label")}
* ${_t.html("settings.custom_background.instructions.wms.tokens.proj")}
* ${_t.html("settings.custom_background.instructions.wms.tokens.wkid")}
* ${_t.html("settings.custom_background.instructions.wms.tokens.dimensions")}
* ${_t.html("settings.custom_background.instructions.wms.tokens.bbox")}
#### ${_t.html("settings.custom_background.instructions.tms.tokens_label")}
* ${_t.html("settings.custom_background.instructions.tms.tokens.xyz")}
* ${_t.html("settings.custom_background.instructions.tms.tokens.flipped_y")}
* ${_t.html("settings.custom_background.instructions.tms.tokens.switch")}
* ${_t.html("settings.custom_background.instructions.tms.tokens.quadtile")}
* ${_t.html("settings.custom_background.instructions.tms.tokens.scale_factor")}
#### ${_t.html("settings.custom_background.instructions.example")}
\`${example}\``;
textSection.append("div").attr("class", "instructions-template").html(marked(instructions));
textSection.append("textarea").attr("class", "field-template").attr("placeholder", _t("settings.custom_background.template.placeholder")).call(utilNoAuto).property("value", _currSettings.template);
var buttonSection = modal.select(".modal-section.buttons");
buttonSection.insert("button", ".ok-button").attr("class", "button cancel-button secondary-action").call(_t.append("confirm.cancel"));
buttonSection.select(".cancel-button").on("click.cancel", clickCancel);
buttonSection.select(".ok-button").attr("disabled", isSaveDisabled).on("click.save", clickSave);
function isSaveDisabled() {
return null;
}
function clickCancel() {
textSection.select(".field-template").property("value", _origSettings.template);
corePreferences("background-custom-template", _origSettings.template);
this.blur();
modal.close();
}
function clickSave() {
_currSettings.template = textSection.select(".field-template").property("value");
corePreferences("background-custom-template", _currSettings.template);
this.blur();
modal.close();
dispatch10.call("change", this, _currSettings);
}
}
return utilRebind(render, dispatch10, "on");
}
// modules/ui/sections/background_list.js
function uiSectionBackgroundList(context) {
var _backgroundList = select_default2(null);
var _customSource = context.background().findSource("custom");
var _settingsCustomBackground = uiSettingsCustomBackground(context).on("change", customChanged);
var section = uiSection("background-list", context).label(_t.html("background.backgrounds")).disclosureContent(renderDisclosureContent);
function previousBackgroundID() {
return corePreferences("background-last-used-toggle");
}
function renderDisclosureContent(selection2) {
var container = selection2.selectAll(".layer-background-list").data([0]);
_backgroundList = container.enter().append("ul").attr("class", "layer-list layer-background-list").attr("dir", "auto").merge(container);
var bgExtrasListEnter = selection2.selectAll(".bg-extras-list").data([0]).enter().append("ul").attr("class", "layer-list bg-extras-list");
var minimapLabelEnter = bgExtrasListEnter.append("li").attr("class", "minimap-toggle-item").append("label").call(uiTooltip().title(_t.html("background.minimap.tooltip")).keys([_t("background.minimap.key")]).placement("top"));
minimapLabelEnter.append("input").attr("type", "checkbox").on("change", function(d3_event) {
d3_event.preventDefault();
uiMapInMap.toggle();
});
minimapLabelEnter.append("span").call(_t.append("background.minimap.description"));
var panelLabelEnter = bgExtrasListEnter.append("li").attr("class", "background-panel-toggle-item").append("label").call(uiTooltip().title(_t.html("background.panel.tooltip")).keys([uiCmd("\u2318\u21E7" + _t("info_panels.background.key"))]).placement("top"));
panelLabelEnter.append("input").attr("type", "checkbox").on("change", function(d3_event) {
d3_event.preventDefault();
context.ui().info.toggle("background");
});
panelLabelEnter.append("span").call(_t.append("background.panel.description"));
var locPanelLabelEnter = bgExtrasListEnter.append("li").attr("class", "location-panel-toggle-item").append("label").call(uiTooltip().title(_t.html("background.location_panel.tooltip")).keys([uiCmd("\u2318\u21E7" + _t("info_panels.location.key"))]).placement("top"));
locPanelLabelEnter.append("input").attr("type", "checkbox").on("change", function(d3_event) {
d3_event.preventDefault();
context.ui().info.toggle("location");
});
locPanelLabelEnter.append("span").call(_t.append("background.location_panel.description"));
selection2.selectAll(".imagery-faq").data([0]).enter().append("div").attr("class", "imagery-faq").append("a").attr("target", "_blank").call(svgIcon("#iD-icon-out-link", "inline")).attr("href", "https://github.com/openstreetmap/iD/blob/develop/FAQ.md#how-can-i-report-an-issue-with-background-imagery").append("span").call(_t.append("background.imagery_problem_faq"));
_backgroundList.call(drawListItems, "radio", function(d3_event, d) {
chooseBackground(d);
}, function(d) {
return !d.isHidden() && !d.overlay;
});
}
function setTooltips(selection2) {
selection2.each(function(d, i2, nodes) {
var item = select_default2(this).select("label");
var span = item.select("span");
var placement = i2 < nodes.length / 2 ? "bottom" : "top";
var description2 = d.description();
var isOverflowing = span.property("clientWidth") !== span.property("scrollWidth");
item.call(uiTooltip().destroyAny);
if (d.id === previousBackgroundID()) {
item.call(uiTooltip().placement(placement).title("" + _t.html("background.switch") + "
").keys([uiCmd("\u2318" + _t("background.key"))]));
} else if (description2 || isOverflowing) {
item.call(uiTooltip().placement(placement).title(description2 || d.label()));
}
});
}
function drawListItems(layerList, type3, change, filter2) {
var sources = context.background().sources(context.map().extent(), context.map().zoom(), true).filter(filter2).sort(function(a, b) {
return a.best() && !b.best() ? -1 : b.best() && !a.best() ? 1 : descending(a.area(), b.area()) || ascending(a.name(), b.name()) || 0;
});
var layerLinks = layerList.selectAll("li").data(sources, function(d, i2) {
return d.id + "---" + i2;
});
layerLinks.exit().remove();
var enter = layerLinks.enter().append("li").classed("layer-custom", function(d) {
return d.id === "custom";
}).classed("best", function(d) {
return d.best();
});
var label = enter.append("label");
label.append("input").attr("type", type3).attr("name", "background-layer").attr("value", function(d) {
return d.id;
}).on("change", change);
label.append("span").html(function(d) {
return d.label();
});
enter.filter(function(d) {
return d.id === "custom";
}).append("button").attr("class", "layer-browse").call(uiTooltip().title(_t.html("settings.custom_background.tooltip")).placement(_mainLocalizer.textDirection() === "rtl" ? "right" : "left")).on("click", function(d3_event) {
d3_event.preventDefault();
editCustom();
}).call(svgIcon("#iD-icon-more"));
enter.filter(function(d) {
return d.best();
}).append("div").attr("class", "best").call(uiTooltip().title(_t.html("background.best_imagery")).placement(_mainLocalizer.textDirection() === "rtl" ? "right" : "left")).append("span").html("★");
layerList.call(updateLayerSelections);
}
function updateLayerSelections(selection2) {
function active(d) {
return context.background().showsLayer(d);
}
selection2.selectAll("li").classed("active", active).classed("switch", function(d) {
return d.id === previousBackgroundID();
}).call(setTooltips).selectAll("input").property("checked", active);
}
function chooseBackground(d) {
if (d.id === "custom" && !d.template()) {
return editCustom();
}
var previousBackground = context.background().baseLayerSource();
corePreferences("background-last-used-toggle", previousBackground.id);
corePreferences("background-last-used", d.id);
context.background().baseLayerSource(d);
}
function customChanged(d) {
if (d && d.template) {
_customSource.template(d.template);
chooseBackground(_customSource);
} else {
_customSource.template("");
chooseBackground(context.background().findSource("none"));
}
}
function editCustom() {
context.container().call(_settingsCustomBackground);
}
context.background().on("change.background_list", function() {
_backgroundList.call(updateLayerSelections);
});
context.map().on("move.background_list", debounce_default(function() {
window.requestIdleCallback(section.reRender);
}, 1e3));
return section;
}
// modules/ui/sections/background_offset.js
function uiSectionBackgroundOffset(context) {
var section = uiSection("background-offset", context).label(_t.html("background.fix_misalignment")).disclosureContent(renderDisclosureContent).expandedByDefault(false);
var _pointerPrefix = "PointerEvent" in window ? "pointer" : "mouse";
var _directions = [
["top", [0, -0.5]],
["left", [-0.5, 0]],
["right", [0.5, 0]],
["bottom", [0, 0.5]]
];
function updateValue() {
var meters = geoOffsetToMeters(context.background().offset());
var x = +meters[0].toFixed(2);
var y = +meters[1].toFixed(2);
context.container().selectAll(".nudge-inner-rect").select("input").classed("error", false).property("value", x + ", " + y);
context.container().selectAll(".nudge-reset").classed("disabled", function() {
return x === 0 && y === 0;
});
}
function resetOffset() {
context.background().offset([0, 0]);
updateValue();
}
function nudge(d) {
context.background().nudge(d, context.map().zoom());
updateValue();
}
function inputOffset() {
var input = select_default2(this);
var d = input.node().value;
if (d === "")
return resetOffset();
d = d.replace(/;/g, ",").split(",").map(function(n2) {
return !isNaN(n2) && n2;
});
if (d.length !== 2 || !d[0] || !d[1]) {
input.classed("error", true);
return;
}
context.background().offset(geoMetersToOffset(d));
updateValue();
}
function dragOffset(d3_event) {
if (d3_event.button !== 0)
return;
var origin = [d3_event.clientX, d3_event.clientY];
var pointerId = d3_event.pointerId || "mouse";
context.container().append("div").attr("class", "nudge-surface");
select_default2(window).on(_pointerPrefix + "move.drag-bg-offset", pointermove).on(_pointerPrefix + "up.drag-bg-offset", pointerup);
if (_pointerPrefix === "pointer") {
select_default2(window).on("pointercancel.drag-bg-offset", pointerup);
}
function pointermove(d3_event2) {
if (pointerId !== (d3_event2.pointerId || "mouse"))
return;
var latest = [d3_event2.clientX, d3_event2.clientY];
var d = [
-(origin[0] - latest[0]) / 4,
-(origin[1] - latest[1]) / 4
];
origin = latest;
nudge(d);
}
function pointerup(d3_event2) {
if (pointerId !== (d3_event2.pointerId || "mouse"))
return;
if (d3_event2.button !== 0)
return;
context.container().selectAll(".nudge-surface").remove();
select_default2(window).on(".drag-bg-offset", null);
}
}
function renderDisclosureContent(selection2) {
var container = selection2.selectAll(".nudge-container").data([0]);
var containerEnter = container.enter().append("div").attr("class", "nudge-container");
containerEnter.append("div").attr("class", "nudge-instructions").call(_t.append("background.offset"));
var nudgeWrapEnter = containerEnter.append("div").attr("class", "nudge-controls-wrap");
var nudgeEnter = nudgeWrapEnter.append("div").attr("class", "nudge-outer-rect").on(_pointerPrefix + "down", dragOffset);
nudgeEnter.append("div").attr("class", "nudge-inner-rect").append("input").attr("type", "text").attr("aria-label", _t("background.offset_label")).on("change", inputOffset);
nudgeWrapEnter.append("div").selectAll("button").data(_directions).enter().append("button").attr("title", function(d) {
return _t(`background.nudge.${d[0]}`);
}).attr("class", function(d) {
return d[0] + " nudge";
}).on("click", function(d3_event, d) {
nudge(d[1]);
});
nudgeWrapEnter.append("button").attr("title", _t("background.reset")).attr("class", "nudge-reset disabled").on("click", function(d3_event) {
d3_event.preventDefault();
resetOffset();
}).call(svgIcon("#iD-icon-" + (_mainLocalizer.textDirection() === "rtl" ? "redo" : "undo")));
updateValue();
}
context.background().on("change.backgroundOffset-update", updateValue);
return section;
}
// modules/ui/sections/overlay_list.js
function uiSectionOverlayList(context) {
var section = uiSection("overlay-list", context).label(_t.html("background.overlays")).disclosureContent(renderDisclosureContent);
var _overlayList = select_default2(null);
function setTooltips(selection2) {
selection2.each(function(d, i2, nodes) {
var item = select_default2(this).select("label");
var span = item.select("span");
var placement = i2 < nodes.length / 2 ? "bottom" : "top";
var description2 = d.description();
var isOverflowing = span.property("clientWidth") !== span.property("scrollWidth");
item.call(uiTooltip().destroyAny);
if (description2 || isOverflowing) {
item.call(uiTooltip().placement(placement).title(description2 || d.name()));
}
});
}
function updateLayerSelections(selection2) {
function active(d) {
return context.background().showsLayer(d);
}
selection2.selectAll("li").classed("active", active).call(setTooltips).selectAll("input").property("checked", active);
}
function chooseOverlay(d3_event, d) {
d3_event.preventDefault();
context.background().toggleOverlayLayer(d);
_overlayList.call(updateLayerSelections);
document.activeElement.blur();
}
function drawListItems(layerList, type3, change, filter2) {
var sources = context.background().sources(context.map().extent(), context.map().zoom(), true).filter(filter2);
var layerLinks = layerList.selectAll("li").data(sources, function(d) {
return d.name();
});
layerLinks.exit().remove();
var enter = layerLinks.enter().append("li");
var label = enter.append("label");
label.append("input").attr("type", type3).attr("name", "layers").on("change", change);
label.append("span").html(function(d) {
return d.label();
});
layerList.selectAll("li").sort(sortSources);
layerList.call(updateLayerSelections);
function sortSources(a, b) {
return a.best() && !b.best() ? -1 : b.best() && !a.best() ? 1 : descending(a.area(), b.area()) || ascending(a.name(), b.name()) || 0;
}
}
function renderDisclosureContent(selection2) {
var container = selection2.selectAll(".layer-overlay-list").data([0]);
_overlayList = container.enter().append("ul").attr("class", "layer-list layer-overlay-list").attr("dir", "auto").merge(container);
_overlayList.call(drawListItems, "checkbox", chooseOverlay, function(d) {
return !d.isHidden() && d.overlay;
});
}
context.map().on("move.overlay_list", debounce_default(function() {
window.requestIdleCallback(section.reRender);
}, 1e3));
return section;
}
// modules/ui/panes/background.js
function uiPaneBackground(context) {
var backgroundPane = uiPane("background", context).key(_t("background.key")).label(_t.html("background.title")).description(_t.html("background.description")).iconName("iD-icon-layers").sections([
uiSectionBackgroundList(context),
uiSectionOverlayList(context),
uiSectionBackgroundDisplayOptions(context),
uiSectionBackgroundOffset(context)
]);
return backgroundPane;
}
// modules/ui/panes/help.js
function uiPaneHelp(context) {
var docKeys = [
["help", [
"welcome",
"open_data_h",
"open_data",
"before_start_h",
"before_start",
"open_source_h",
"open_source",
"open_source_help"
]],
["overview", [
"navigation_h",
"navigation_drag",
"navigation_zoom",
"features_h",
"features",
"nodes_ways"
]],
["editing", [
"select_h",
"select_left_click",
"select_right_click",
"select_space",
"multiselect_h",
"multiselect",
"multiselect_shift_click",
"multiselect_lasso",
"undo_redo_h",
"undo_redo",
"save_h",
"save",
"save_validation",
"upload_h",
"upload",
"backups_h",
"backups",
"keyboard_h",
"keyboard"
]],
["feature_editor", [
"intro",
"definitions",
"type_h",
"type",
"type_picker",
"fields_h",
"fields_all_fields",
"fields_example",
"fields_add_field",
"tags_h",
"tags_all_tags",
"tags_resources"
]],
["points", [
"intro",
"add_point_h",
"add_point",
"add_point_finish",
"move_point_h",
"move_point",
"delete_point_h",
"delete_point",
"delete_point_command"
]],
["lines", [
"intro",
"add_line_h",
"add_line",
"add_line_draw",
"add_line_continue",
"add_line_finish",
"modify_line_h",
"modify_line_dragnode",
"modify_line_addnode",
"connect_line_h",
"connect_line",
"connect_line_display",
"connect_line_drag",
"connect_line_tag",
"disconnect_line_h",
"disconnect_line_command",
"move_line_h",
"move_line_command",
"move_line_connected",
"delete_line_h",
"delete_line",
"delete_line_command"
]],
["areas", [
"intro",
"point_or_area_h",
"point_or_area",
"add_area_h",
"add_area_command",
"add_area_draw",
"add_area_continue",
"add_area_finish",
"square_area_h",
"square_area_command",
"modify_area_h",
"modify_area_dragnode",
"modify_area_addnode",
"delete_area_h",
"delete_area",
"delete_area_command"
]],
["relations", [
"intro",
"edit_relation_h",
"edit_relation",
"edit_relation_add",
"edit_relation_delete",
"maintain_relation_h",
"maintain_relation",
"relation_types_h",
"multipolygon_h",
"multipolygon",
"multipolygon_create",
"multipolygon_merge",
"turn_restriction_h",
"turn_restriction",
"turn_restriction_field",
"turn_restriction_editing",
"route_h",
"route",
"route_add",
"boundary_h",
"boundary",
"boundary_add"
]],
["operations", [
"intro",
"intro_2",
"straighten",
"orthogonalize",
"circularize",
"move",
"rotate",
"reflect",
"continue",
"reverse",
"disconnect",
"split",
"extract",
"merge",
"delete",
"downgrade",
"copy_paste"
]],
["notes", [
"intro",
"add_note_h",
"add_note",
"place_note",
"move_note",
"update_note_h",
"update_note",
"save_note_h",
"save_note"
]],
["imagery", [
"intro",
"sources_h",
"choosing",
"sources",
"offsets_h",
"offset",
"offset_change"
]],
["streetlevel", [
"intro",
"using_h",
"using",
"photos",
"viewer"
]],
["gps", [
"intro",
"survey",
"using_h",
"using",
"tracing",
"upload"
]],
["qa", [
"intro",
"tools_h",
"tools",
"issues_h",
"issues"
]]
];
var headings = {
"help.help.open_data_h": 3,
"help.help.before_start_h": 3,
"help.help.open_source_h": 3,
"help.overview.navigation_h": 3,
"help.overview.features_h": 3,
"help.editing.select_h": 3,
"help.editing.multiselect_h": 3,
"help.editing.undo_redo_h": 3,
"help.editing.save_h": 3,
"help.editing.upload_h": 3,
"help.editing.backups_h": 3,
"help.editing.keyboard_h": 3,
"help.feature_editor.type_h": 3,
"help.feature_editor.fields_h": 3,
"help.feature_editor.tags_h": 3,
"help.points.add_point_h": 3,
"help.points.move_point_h": 3,
"help.points.delete_point_h": 3,
"help.lines.add_line_h": 3,
"help.lines.modify_line_h": 3,
"help.lines.connect_line_h": 3,
"help.lines.disconnect_line_h": 3,
"help.lines.move_line_h": 3,
"help.lines.delete_line_h": 3,
"help.areas.point_or_area_h": 3,
"help.areas.add_area_h": 3,
"help.areas.square_area_h": 3,
"help.areas.modify_area_h": 3,
"help.areas.delete_area_h": 3,
"help.relations.edit_relation_h": 3,
"help.relations.maintain_relation_h": 3,
"help.relations.relation_types_h": 2,
"help.relations.multipolygon_h": 3,
"help.relations.turn_restriction_h": 3,
"help.relations.route_h": 3,
"help.relations.boundary_h": 3,
"help.notes.add_note_h": 3,
"help.notes.update_note_h": 3,
"help.notes.save_note_h": 3,
"help.imagery.sources_h": 3,
"help.imagery.offsets_h": 3,
"help.streetlevel.using_h": 3,
"help.gps.using_h": 3,
"help.qa.tools_h": 3,
"help.qa.issues_h": 3
};
var docs = docKeys.map(function(key) {
var helpkey = "help." + key[0];
var helpPaneReplacements = { version: context.version };
var text2 = key[1].reduce(function(all, part) {
var subkey = helpkey + "." + part;
var depth = headings[subkey];
var hhh = depth ? Array(depth + 1).join("#") + " " : "";
return all + hhh + helpHtml(subkey, helpPaneReplacements) + "\n\n";
}, "");
return {
title: _t.html(helpkey + ".title"),
content: marked(text2.trim()).replace(//g, "").replace(/<\/code>/g, "")
};
});
var helpPane = uiPane("help", context).key(_t("help.key")).label(_t.html("help.title")).description(_t.html("help.title")).iconName("iD-icon-help");
helpPane.renderContent = function(content) {
function clickHelp(d, i2) {
var rtl = _mainLocalizer.textDirection() === "rtl";
content.property("scrollTop", 0);
helpPane.selection().select(".pane-heading h2").html(d.title);
body.html(d.content);
body.selectAll("a").attr("target", "_blank");
menuItems.classed("selected", function(m) {
return m.title === d.title;
});
nav.html("");
if (rtl) {
nav.call(drawNext).call(drawPrevious);
} else {
nav.call(drawPrevious).call(drawNext);
}
function drawNext(selection2) {
if (i2 < docs.length - 1) {
var nextLink = selection2.append("a").attr("href", "#").attr("class", "next").on("click", function(d3_event) {
d3_event.preventDefault();
clickHelp(docs[i2 + 1], i2 + 1);
});
nextLink.append("span").html(docs[i2 + 1].title).call(svgIcon(rtl ? "#iD-icon-backward" : "#iD-icon-forward", "inline"));
}
}
function drawPrevious(selection2) {
if (i2 > 0) {
var prevLink = selection2.append("a").attr("href", "#").attr("class", "previous").on("click", function(d3_event) {
d3_event.preventDefault();
clickHelp(docs[i2 - 1], i2 - 1);
});
prevLink.call(svgIcon(rtl ? "#iD-icon-forward" : "#iD-icon-backward", "inline")).append("span").html(docs[i2 - 1].title);
}
}
}
function clickWalkthrough(d3_event) {
d3_event.preventDefault();
if (context.inIntro())
return;
context.container().call(uiIntro(context));
context.ui().togglePanes();
}
function clickShortcuts(d3_event) {
d3_event.preventDefault();
context.container().call(context.ui().shortcuts, true);
}
var toc = content.append("ul").attr("class", "toc");
var menuItems = toc.selectAll("li").data(docs).enter().append("li").append("a").attr("role", "button").attr("href", "#").html(function(d) {
return d.title;
}).on("click", function(d3_event, d) {
d3_event.preventDefault();
clickHelp(d, docs.indexOf(d));
});
var shortcuts = toc.append("li").attr("class", "shortcuts").call(uiTooltip().title(_t.html("shortcuts.tooltip")).keys(["?"]).placement("top")).append("a").attr("href", "#").on("click", clickShortcuts);
shortcuts.append("div").call(_t.append("shortcuts.title"));
var walkthrough = toc.append("li").attr("class", "walkthrough").append("a").attr("href", "#").on("click", clickWalkthrough);
walkthrough.append("svg").attr("class", "logo logo-walkthrough").append("use").attr("xlink:href", "#iD-logo-walkthrough");
walkthrough.append("div").call(_t.append("splash.walkthrough"));
var helpContent = content.append("div").attr("class", "left-content");
var body = helpContent.append("div").attr("class", "body");
var nav = helpContent.append("div").attr("class", "nav");
clickHelp(docs[0], 0);
};
return helpPane;
}
// modules/ui/sections/validation_issues.js
function uiSectionValidationIssues(id2, severity, context) {
var _issues = [];
var section = uiSection(id2, context).label(function() {
if (!_issues)
return "";
var issueCountText = _issues.length > 1e3 ? "1000+" : String(_issues.length);
return _t.html("inspector.title_count", { title: { html: _t.html("issues." + severity + "s.list_title") }, count: issueCountText });
}).disclosureContent(renderDisclosureContent).shouldDisplay(function() {
return _issues && _issues.length;
});
function getOptions() {
return {
what: corePreferences("validate-what") || "edited",
where: corePreferences("validate-where") || "all"
};
}
function reloadIssues() {
_issues = context.validator().getIssuesBySeverity(getOptions())[severity];
}
function renderDisclosureContent(selection2) {
var center = context.map().center();
var graph = context.graph();
var issues = _issues.map(function withDistance(issue) {
var extent = issue.extent(graph);
var dist = extent ? geoSphericalDistance(center, extent.center()) : 0;
return Object.assign(issue, { dist });
}).sort(function byDistance(a, b) {
return a.dist - b.dist;
});
issues = issues.slice(0, 1e3);
selection2.call(drawIssuesList, issues);
}
function drawIssuesList(selection2, issues) {
var list = selection2.selectAll(".issues-list").data([0]);
list = list.enter().append("ul").attr("class", "layer-list issues-list " + severity + "s-list").merge(list);
var items = list.selectAll("li").data(issues, function(d) {
return d.key;
});
items.exit().remove();
var itemsEnter = items.enter().append("li").attr("class", function(d) {
return "issue severity-" + d.severity;
});
var labelsEnter = itemsEnter.append("button").attr("class", "issue-label").on("click", function(d3_event, d) {
context.validator().focusIssue(d);
}).on("mouseover", function(d3_event, d) {
utilHighlightEntities(d.entityIds, true, context);
}).on("mouseout", function(d3_event, d) {
utilHighlightEntities(d.entityIds, false, context);
});
var textEnter = labelsEnter.append("span").attr("class", "issue-text");
textEnter.append("span").attr("class", "issue-icon").each(function(d) {
var iconName = "#iD-icon-" + (d.severity === "warning" ? "alert" : "error");
select_default2(this).call(svgIcon(iconName));
});
textEnter.append("span").attr("class", "issue-message");
items = items.merge(itemsEnter).order();
items.selectAll(".issue-message").html(function(d) {
return d.message(context);
});
}
context.validator().on("validated.uiSectionValidationIssues" + id2, function() {
window.requestIdleCallback(function() {
reloadIssues();
section.reRender();
});
});
context.map().on("move.uiSectionValidationIssues" + id2, debounce_default(function() {
window.requestIdleCallback(function() {
if (getOptions().where === "visible") {
reloadIssues();
}
section.reRender();
});
}, 1e3));
return section;
}
// modules/ui/sections/validation_options.js
function uiSectionValidationOptions(context) {
var section = uiSection("issues-options", context).content(renderContent);
function renderContent(selection2) {
var container = selection2.selectAll(".issues-options-container").data([0]);
container = container.enter().append("div").attr("class", "issues-options-container").merge(container);
var data = [
{ key: "what", values: ["edited", "all"] },
{ key: "where", values: ["visible", "all"] }
];
var options2 = container.selectAll(".issues-option").data(data, function(d) {
return d.key;
});
var optionsEnter = options2.enter().append("div").attr("class", function(d) {
return "issues-option issues-option-" + d.key;
});
optionsEnter.append("div").attr("class", "issues-option-title").html(function(d) {
return _t.html("issues.options." + d.key + ".title");
});
var valuesEnter = optionsEnter.selectAll("label").data(function(d) {
return d.values.map(function(val) {
return { value: val, key: d.key };
});
}).enter().append("label");
valuesEnter.append("input").attr("type", "radio").attr("name", function(d) {
return "issues-option-" + d.key;
}).attr("value", function(d) {
return d.value;
}).property("checked", function(d) {
return getOptions()[d.key] === d.value;
}).on("change", function(d3_event, d) {
updateOptionValue(d3_event, d.key, d.value);
});
valuesEnter.append("span").html(function(d) {
return _t.html("issues.options." + d.key + "." + d.value);
});
}
function getOptions() {
return {
what: corePreferences("validate-what") || "edited",
where: corePreferences("validate-where") || "all"
};
}
function updateOptionValue(d3_event, d, val) {
if (!val && d3_event && d3_event.target) {
val = d3_event.target.value;
}
corePreferences("validate-" + d, val);
context.validator().validate();
}
return section;
}
// modules/ui/sections/validation_rules.js
function uiSectionValidationRules(context) {
var MINSQUARE = 0;
var MAXSQUARE = 20;
var DEFAULTSQUARE = 5;
var section = uiSection("issues-rules", context).disclosureContent(renderDisclosureContent).label(_t.html("issues.rules.title"));
var _ruleKeys = context.validator().getRuleKeys().filter(function(key) {
return key !== "maprules";
}).sort(function(key1, key2) {
return _t("issues." + key1 + ".title") < _t("issues." + key2 + ".title") ? -1 : 1;
});
function renderDisclosureContent(selection2) {
var container = selection2.selectAll(".issues-rulelist-container").data([0]);
var containerEnter = container.enter().append("div").attr("class", "issues-rulelist-container");
containerEnter.append("ul").attr("class", "layer-list issue-rules-list");
var ruleLinks = containerEnter.append("div").attr("class", "issue-rules-links section-footer");
ruleLinks.append("a").attr("class", "issue-rules-link").attr("role", "button").attr("href", "#").call(_t.append("issues.disable_all")).on("click", function(d3_event) {
d3_event.preventDefault();
context.validator().disableRules(_ruleKeys);
});
ruleLinks.append("a").attr("class", "issue-rules-link").attr("role", "button").attr("href", "#").call(_t.append("issues.enable_all")).on("click", function(d3_event) {
d3_event.preventDefault();
context.validator().disableRules([]);
});
container = container.merge(containerEnter);
container.selectAll(".issue-rules-list").call(drawListItems, _ruleKeys, "checkbox", "rule", toggleRule, isRuleEnabled);
}
function drawListItems(selection2, data, type3, name2, change, active) {
var items = selection2.selectAll("li").data(data);
items.exit().remove();
var enter = items.enter().append("li");
if (name2 === "rule") {
enter.call(uiTooltip().title(function(d) {
return _t.html("issues." + d + ".tip");
}).placement("top"));
}
var label = enter.append("label");
label.append("input").attr("type", type3).attr("name", name2).on("change", change);
label.append("span").html(function(d) {
var params = {};
if (d === "unsquare_way") {
params.val = { html: '' };
}
return _t.html("issues." + d + ".title", params);
});
items = items.merge(enter);
items.classed("active", active).selectAll("input").property("checked", active).property("indeterminate", false);
var degStr = corePreferences("validate-square-degrees");
if (degStr === null) {
degStr = DEFAULTSQUARE.toString();
}
var span = items.selectAll(".square-degrees");
var input = span.selectAll(".square-degrees-input").data([0]);
input.enter().append("input").attr("type", "number").attr("min", MINSQUARE.toString()).attr("max", MAXSQUARE.toString()).attr("step", "0.5").attr("class", "square-degrees-input").call(utilNoAuto).on("click", function(d3_event) {
d3_event.preventDefault();
d3_event.stopPropagation();
this.select();
}).on("keyup", function(d3_event) {
if (d3_event.keyCode === 13) {
this.blur();
this.select();
}
}).on("blur", changeSquare).merge(input).property("value", degStr);
}
function changeSquare() {
var input = select_default2(this);
var degStr = utilGetSetValue(input).trim();
var degNum = parseFloat(degStr, 10);
if (!isFinite(degNum)) {
degNum = DEFAULTSQUARE;
} else if (degNum > MAXSQUARE) {
degNum = MAXSQUARE;
} else if (degNum < MINSQUARE) {
degNum = MINSQUARE;
}
degNum = Math.round(degNum * 10) / 10;
degStr = degNum.toString();
input.property("value", degStr);
corePreferences("validate-square-degrees", degStr);
context.validator().revalidateUnsquare();
}
function isRuleEnabled(d) {
return context.validator().isRuleEnabled(d);
}
function toggleRule(d3_event, d) {
context.validator().toggleRule(d);
}
context.validator().on("validated.uiSectionValidationRules", function() {
window.requestIdleCallback(section.reRender);
});
return section;
}
// modules/ui/sections/validation_status.js
function uiSectionValidationStatus(context) {
var section = uiSection("issues-status", context).content(renderContent).shouldDisplay(function() {
var issues = context.validator().getIssues(getOptions());
return issues.length === 0;
});
function getOptions() {
return {
what: corePreferences("validate-what") || "edited",
where: corePreferences("validate-where") || "all"
};
}
function renderContent(selection2) {
var box = selection2.selectAll(".box").data([0]);
var boxEnter = box.enter().append("div").attr("class", "box");
boxEnter.append("div").call(svgIcon("#iD-icon-apply", "pre-text"));
var noIssuesMessage = boxEnter.append("span");
noIssuesMessage.append("strong").attr("class", "message");
noIssuesMessage.append("br");
noIssuesMessage.append("span").attr("class", "details");
renderIgnoredIssuesReset(selection2);
setNoIssuesText(selection2);
}
function renderIgnoredIssuesReset(selection2) {
var ignoredIssues = context.validator().getIssues({ what: "all", where: "all", includeDisabledRules: true, includeIgnored: "only" });
var resetIgnored = selection2.selectAll(".reset-ignored").data(ignoredIssues.length ? [0] : []);
resetIgnored.exit().remove();
var resetIgnoredEnter = resetIgnored.enter().append("div").attr("class", "reset-ignored section-footer");
resetIgnoredEnter.append("a").attr("href", "#");
resetIgnored = resetIgnored.merge(resetIgnoredEnter);
resetIgnored.select("a").html(_t.html("inspector.title_count", { title: { html: _t.html("issues.reset_ignored") }, count: ignoredIssues.length }));
resetIgnored.on("click", function(d3_event) {
d3_event.preventDefault();
context.validator().resetIgnoredIssues();
});
}
function setNoIssuesText(selection2) {
var opts = getOptions();
function checkForHiddenIssues(cases) {
for (var type3 in cases) {
var hiddenOpts = cases[type3];
var hiddenIssues = context.validator().getIssues(hiddenOpts);
if (hiddenIssues.length) {
selection2.select(".box .details").html("").call(_t.append("issues.no_issues.hidden_issues." + type3, { count: hiddenIssues.length.toString() }));
return;
}
}
selection2.select(".box .details").html("").call(_t.append("issues.no_issues.hidden_issues.none"));
}
var messageType;
if (opts.what === "edited" && opts.where === "visible") {
messageType = "edits_in_view";
checkForHiddenIssues({
elsewhere: { what: "edited", where: "all" },
everything_else: { what: "all", where: "visible" },
disabled_rules: { what: "edited", where: "visible", includeDisabledRules: "only" },
everything_else_elsewhere: { what: "all", where: "all" },
disabled_rules_elsewhere: { what: "edited", where: "all", includeDisabledRules: "only" },
ignored_issues: { what: "edited", where: "visible", includeIgnored: "only" },
ignored_issues_elsewhere: { what: "edited", where: "all", includeIgnored: "only" }
});
} else if (opts.what === "edited" && opts.where === "all") {
messageType = "edits";
checkForHiddenIssues({
everything_else: { what: "all", where: "all" },
disabled_rules: { what: "edited", where: "all", includeDisabledRules: "only" },
ignored_issues: { what: "edited", where: "all", includeIgnored: "only" }
});
} else if (opts.what === "all" && opts.where === "visible") {
messageType = "everything_in_view";
checkForHiddenIssues({
elsewhere: { what: "all", where: "all" },
disabled_rules: { what: "all", where: "visible", includeDisabledRules: "only" },
disabled_rules_elsewhere: { what: "all", where: "all", includeDisabledRules: "only" },
ignored_issues: { what: "all", where: "visible", includeIgnored: "only" },
ignored_issues_elsewhere: { what: "all", where: "all", includeIgnored: "only" }
});
} else if (opts.what === "all" && opts.where === "all") {
messageType = "everything";
checkForHiddenIssues({
disabled_rules: { what: "all", where: "all", includeDisabledRules: "only" },
ignored_issues: { what: "all", where: "all", includeIgnored: "only" }
});
}
if (opts.what === "edited" && context.history().difference().summary().length === 0) {
messageType = "no_edits";
}
selection2.select(".box .message").html("").call(_t.append("issues.no_issues.message." + messageType));
}
context.validator().on("validated.uiSectionValidationStatus", function() {
window.requestIdleCallback(section.reRender);
});
context.map().on("move.uiSectionValidationStatus", debounce_default(function() {
window.requestIdleCallback(section.reRender);
}, 1e3));
return section;
}
// modules/ui/panes/issues.js
function uiPaneIssues(context) {
var issuesPane = uiPane("issues", context).key(_t("issues.key")).label(_t.html("issues.title")).description(_t.html("issues.title")).iconName("iD-icon-alert").sections([
uiSectionValidationOptions(context),
uiSectionValidationStatus(context),
uiSectionValidationIssues("issues-errors", "error", context),
uiSectionValidationIssues("issues-warnings", "warning", context),
uiSectionValidationRules(context)
]);
return issuesPane;
}
// modules/ui/settings/custom_data.js
function uiSettingsCustomData(context) {
var dispatch10 = dispatch_default("change");
function render(selection2) {
var dataLayer = context.layers().layer("data");
var _origSettings = {
fileList: dataLayer && dataLayer.fileList() || null,
url: corePreferences("settings-custom-data-url")
};
var _currSettings = {
fileList: dataLayer && dataLayer.fileList() || null,
url: corePreferences("settings-custom-data-url")
};
var modal = uiConfirm(selection2).okButton();
modal.classed("settings-modal settings-custom-data", true);
modal.select(".modal-section.header").append("h3").call(_t.append("settings.custom_data.header"));
var textSection = modal.select(".modal-section.message-text");
textSection.append("pre").attr("class", "instructions-file").call(_t.append("settings.custom_data.file.instructions"));
textSection.append("input").attr("class", "field-file").attr("type", "file").attr("accept", ".gpx,.kml,.geojson,.json,application/gpx+xml,application/vnd.google-earth.kml+xml,application/geo+json,application/json").property("files", _currSettings.fileList).on("change", function(d3_event) {
var files = d3_event.target.files;
if (files && files.length) {
_currSettings.url = "";
textSection.select(".field-url").property("value", "");
_currSettings.fileList = files;
} else {
_currSettings.fileList = null;
}
});
textSection.append("h4").call(_t.append("settings.custom_data.or"));
textSection.append("pre").attr("class", "instructions-url").call(_t.append("settings.custom_data.url.instructions"));
textSection.append("textarea").attr("class", "field-url").attr("placeholder", _t("settings.custom_data.url.placeholder")).call(utilNoAuto).property("value", _currSettings.url);
var buttonSection = modal.select(".modal-section.buttons");
buttonSection.insert("button", ".ok-button").attr("class", "button cancel-button secondary-action").call(_t.append("confirm.cancel"));
buttonSection.select(".cancel-button").on("click.cancel", clickCancel);
buttonSection.select(".ok-button").attr("disabled", isSaveDisabled).on("click.save", clickSave);
function isSaveDisabled() {
return null;
}
function clickCancel() {
textSection.select(".field-url").property("value", _origSettings.url);
corePreferences("settings-custom-data-url", _origSettings.url);
this.blur();
modal.close();
}
function clickSave() {
_currSettings.url = textSection.select(".field-url").property("value").trim();
if (_currSettings.url) {
_currSettings.fileList = null;
}
if (_currSettings.fileList) {
_currSettings.url = "";
}
corePreferences("settings-custom-data-url", _currSettings.url);
this.blur();
modal.close();
dispatch10.call("change", this, _currSettings);
}
}
return utilRebind(render, dispatch10, "on");
}
// modules/ui/sections/data_layers.js
function uiSectionDataLayers(context) {
var settingsCustomData = uiSettingsCustomData(context).on("change", customChanged);
var layers = context.layers();
var section = uiSection("data-layers", context).label(_t.html("map_data.data_layers")).disclosureContent(renderDisclosureContent);
function renderDisclosureContent(selection2) {
var container = selection2.selectAll(".data-layer-container").data([0]);
container.enter().append("div").attr("class", "data-layer-container").merge(container).call(drawOsmItems).call(drawQAItems).call(drawCustomDataItems).call(drawVectorItems).call(drawPanelItems);
}
function showsLayer(which) {
var layer = layers.layer(which);
if (layer) {
return layer.enabled();
}
return false;
}
function setLayer(which, enabled) {
var mode = context.mode();
if (mode && /^draw/.test(mode.id))
return;
var layer = layers.layer(which);
if (layer) {
layer.enabled(enabled);
if (!enabled && (which === "osm" || which === "notes")) {
context.enter(modeBrowse(context));
}
}
}
function toggleLayer(which) {
setLayer(which, !showsLayer(which));
}
function drawOsmItems(selection2) {
var osmKeys = ["osm", "notes"];
var osmLayers = layers.all().filter(function(obj) {
return osmKeys.indexOf(obj.id) !== -1;
});
var ul = selection2.selectAll(".layer-list-osm").data([0]);
ul = ul.enter().append("ul").attr("class", "layer-list layer-list-osm").merge(ul);
var li = ul.selectAll(".list-item").data(osmLayers);
li.exit().remove();
var liEnter = li.enter().append("li").attr("class", function(d) {
return "list-item list-item-" + d.id;
});
var labelEnter = liEnter.append("label").each(function(d) {
if (d.id === "osm") {
select_default2(this).call(uiTooltip().title(_t.html("map_data.layers." + d.id + ".tooltip")).keys([uiCmd("\u2325" + _t("area_fill.wireframe.key"))]).placement("bottom"));
} else {
select_default2(this).call(uiTooltip().title(_t.html("map_data.layers." + d.id + ".tooltip")).placement("bottom"));
}
});
labelEnter.append("input").attr("type", "checkbox").on("change", function(d3_event, d) {
toggleLayer(d.id);
});
labelEnter.append("span").html(function(d) {
return _t.html("map_data.layers." + d.id + ".title");
});
li.merge(liEnter).classed("active", function(d) {
return d.layer.enabled();
}).selectAll("input").property("checked", function(d) {
return d.layer.enabled();
});
}
function drawQAItems(selection2) {
var qaKeys = ["keepRight", "improveOSM", "osmose"];
var qaLayers = layers.all().filter(function(obj) {
return qaKeys.indexOf(obj.id) !== -1;
});
var ul = selection2.selectAll(".layer-list-qa").data([0]);
ul = ul.enter().append("ul").attr("class", "layer-list layer-list-qa").merge(ul);
var li = ul.selectAll(".list-item").data(qaLayers);
li.exit().remove();
var liEnter = li.enter().append("li").attr("class", function(d) {
return "list-item list-item-" + d.id;
});
var labelEnter = liEnter.append("label").each(function(d) {
select_default2(this).call(uiTooltip().title(_t.html("map_data.layers." + d.id + ".tooltip")).placement("bottom"));
});
labelEnter.append("input").attr("type", "checkbox").on("change", function(d3_event, d) {
toggleLayer(d.id);
});
labelEnter.append("span").html(function(d) {
return _t.html("map_data.layers." + d.id + ".title");
});
li.merge(liEnter).classed("active", function(d) {
return d.layer.enabled();
}).selectAll("input").property("checked", function(d) {
return d.layer.enabled();
});
}
function drawVectorItems(selection2) {
var dataLayer = layers.layer("data");
var vtData = [
{
name: "Detroit Neighborhoods/Parks",
src: "neighborhoods-parks",
tooltip: "Neighborhood boundaries and parks as compiled by City of Detroit in concert with community groups.",
template: "https://{switch:a,b,c,d}.tiles.mapbox.com/v4/jonahadkins.cjksmur6x34562qp9iv1u3ksf-54hev,jonahadkins.cjksmqxdx33jj2wp90xd9x2md-4e5y2/{z}/{x}/{y}.vector.pbf?access_token=pk.eyJ1Ijoiam9uYWhhZGtpbnMiLCJhIjoiRlVVVkx3VSJ9.9sdVEK_B_VkEXPjssU5MqA"
},
{
name: "Detroit Composite POIs",
src: "composite-poi",
tooltip: "Fire Inspections, Business Licenses, and other public location data collated from the City of Detroit.",
template: "https://{switch:a,b,c,d}.tiles.mapbox.com/v4/jonahadkins.cjksmm6a02sli31myxhsr7zf3-2sw8h/{z}/{x}/{y}.vector.pbf?access_token=pk.eyJ1Ijoiam9uYWhhZGtpbnMiLCJhIjoiRlVVVkx3VSJ9.9sdVEK_B_VkEXPjssU5MqA"
},
{
name: "Detroit All-The-Places POIs",
src: "alltheplaces-poi",
tooltip: "Public domain business location data created by web scrapers.",
template: "https://{switch:a,b,c,d}.tiles.mapbox.com/v4/jonahadkins.cjksmswgk340g2vo06p1w9w0j-8fjjc/{z}/{x}/{y}.vector.pbf?access_token=pk.eyJ1Ijoiam9uYWhhZGtpbnMiLCJhIjoiRlVVVkx3VSJ9.9sdVEK_B_VkEXPjssU5MqA"
}
];
var detroit = geoExtent([-83.5, 42.1], [-82.8, 42.5]);
var showVectorItems = context.map().zoom() > 9 && detroit.contains(context.map().center());
var container = selection2.selectAll(".vectortile-container").data(showVectorItems ? [0] : []);
container.exit().remove();
var containerEnter = container.enter().append("div").attr("class", "vectortile-container");
containerEnter.append("h4").attr("class", "vectortile-header").text("Detroit Vector Tiles (Beta)");
containerEnter.append("ul").attr("class", "layer-list layer-list-vectortile");
containerEnter.append("div").attr("class", "vectortile-footer").append("a").attr("target", "_blank").call(svgIcon("#iD-icon-out-link", "inline")).attr("href", "https://github.com/osmus/detroit-mapping-challenge").append("span").text("About these layers");
container = container.merge(containerEnter);
var ul = container.selectAll(".layer-list-vectortile");
var li = ul.selectAll(".list-item").data(vtData);
li.exit().remove();
var liEnter = li.enter().append("li").attr("class", function(d) {
return "list-item list-item-" + d.src;
});
var labelEnter = liEnter.append("label").each(function(d) {
select_default2(this).call(uiTooltip().title(d.tooltip).placement("top"));
});
labelEnter.append("input").attr("type", "radio").attr("name", "vectortile").on("change", selectVTLayer);
labelEnter.append("span").text(function(d) {
return d.name;
});
li.merge(liEnter).classed("active", isVTLayerSelected).selectAll("input").property("checked", isVTLayerSelected);
function isVTLayerSelected(d) {
return dataLayer && dataLayer.template() === d.template;
}
function selectVTLayer(d3_event, d) {
corePreferences("settings-custom-data-url", d.template);
if (dataLayer) {
dataLayer.template(d.template, d.src);
dataLayer.enabled(true);
}
}
}
function drawCustomDataItems(selection2) {
var dataLayer = layers.layer("data");
var hasData = dataLayer && dataLayer.hasData();
var showsData = hasData && dataLayer.enabled();
var ul = selection2.selectAll(".layer-list-data").data(dataLayer ? [0] : []);
ul.exit().remove();
var ulEnter = ul.enter().append("ul").attr("class", "layer-list layer-list-data");
var liEnter = ulEnter.append("li").attr("class", "list-item-data");
var labelEnter = liEnter.append("label").call(uiTooltip().title(_t.html("map_data.layers.custom.tooltip")).placement("top"));
labelEnter.append("input").attr("type", "checkbox").on("change", function() {
toggleLayer("data");
});
labelEnter.append("span").call(_t.append("map_data.layers.custom.title"));
liEnter.append("button").attr("class", "open-data-options").call(uiTooltip().title(_t.html("settings.custom_data.tooltip")).placement(_mainLocalizer.textDirection() === "rtl" ? "right" : "left")).on("click", function(d3_event) {
d3_event.preventDefault();
editCustom();
}).call(svgIcon("#iD-icon-more"));
liEnter.append("button").attr("class", "zoom-to-data").call(uiTooltip().title(_t.html("map_data.layers.custom.zoom")).placement(_mainLocalizer.textDirection() === "rtl" ? "right" : "left")).on("click", function(d3_event) {
if (select_default2(this).classed("disabled"))
return;
d3_event.preventDefault();
d3_event.stopPropagation();
dataLayer.fitZoom();
}).call(svgIcon("#iD-icon-framed-dot", "monochrome"));
ul = ul.merge(ulEnter);
ul.selectAll(".list-item-data").classed("active", showsData).selectAll("label").classed("deemphasize", !hasData).selectAll("input").property("disabled", !hasData).property("checked", showsData);
ul.selectAll("button.zoom-to-data").classed("disabled", !hasData);
}
function editCustom() {
context.container().call(settingsCustomData);
}
function customChanged(d) {
var dataLayer = layers.layer("data");
if (d && d.url) {
dataLayer.url(d.url);
} else if (d && d.fileList) {
dataLayer.fileList(d.fileList);
}
}
function drawPanelItems(selection2) {
var panelsListEnter = selection2.selectAll(".md-extras-list").data([0]).enter().append("ul").attr("class", "layer-list md-extras-list");
var historyPanelLabelEnter = panelsListEnter.append("li").attr("class", "history-panel-toggle-item").append("label").call(uiTooltip().title(_t.html("map_data.history_panel.tooltip")).keys([uiCmd("\u2318\u21E7" + _t("info_panels.history.key"))]).placement("top"));
historyPanelLabelEnter.append("input").attr("type", "checkbox").on("change", function(d3_event) {
d3_event.preventDefault();
context.ui().info.toggle("history");
});
historyPanelLabelEnter.append("span").call(_t.append("map_data.history_panel.title"));
var measurementPanelLabelEnter = panelsListEnter.append("li").attr("class", "measurement-panel-toggle-item").append("label").call(uiTooltip().title(_t.html("map_data.measurement_panel.tooltip")).keys([uiCmd("\u2318\u21E7" + _t("info_panels.measurement.key"))]).placement("top"));
measurementPanelLabelEnter.append("input").attr("type", "checkbox").on("change", function(d3_event) {
d3_event.preventDefault();
context.ui().info.toggle("measurement");
});
measurementPanelLabelEnter.append("span").call(_t.append("map_data.measurement_panel.title"));
}
context.layers().on("change.uiSectionDataLayers", section.reRender);
context.map().on("move.uiSectionDataLayers", debounce_default(function() {
window.requestIdleCallback(section.reRender);
}, 1e3));
return section;
}
// modules/ui/sections/map_features.js
function uiSectionMapFeatures(context) {
var _features = context.features().keys();
var section = uiSection("map-features", context).label(_t.html("map_data.map_features")).disclosureContent(renderDisclosureContent).expandedByDefault(false);
function renderDisclosureContent(selection2) {
var container = selection2.selectAll(".layer-feature-list-container").data([0]);
var containerEnter = container.enter().append("div").attr("class", "layer-feature-list-container");
containerEnter.append("ul").attr("class", "layer-list layer-feature-list");
var footer = containerEnter.append("div").attr("class", "feature-list-links section-footer");
footer.append("a").attr("class", "feature-list-link").attr("role", "button").attr("href", "#").call(_t.append("issues.disable_all")).on("click", function(d3_event) {
d3_event.preventDefault();
context.features().disableAll();
});
footer.append("a").attr("class", "feature-list-link").attr("role", "button").attr("href", "#").call(_t.append("issues.enable_all")).on("click", function(d3_event) {
d3_event.preventDefault();
context.features().enableAll();
});
container = container.merge(containerEnter);
container.selectAll(".layer-feature-list").call(drawListItems, _features, "checkbox", "feature", clickFeature, showsFeature);
}
function drawListItems(selection2, data, type3, name2, change, active) {
var items = selection2.selectAll("li").data(data);
items.exit().remove();
var enter = items.enter().append("li").call(uiTooltip().title(function(d) {
var tip = _t.html(name2 + "." + d + ".tooltip");
if (autoHiddenFeature(d)) {
var msg = showsLayer("osm") ? _t.html("map_data.autohidden") : _t.html("map_data.osmhidden");
tip += "" + msg + "
";
}
return tip;
}).placement("top"));
var label = enter.append("label");
label.append("input").attr("type", type3).attr("name", name2).on("change", change);
label.append("span").html(function(d) {
return _t.html(name2 + "." + d + ".description");
});
items = items.merge(enter);
items.classed("active", active).selectAll("input").property("checked", active).property("indeterminate", autoHiddenFeature);
}
function autoHiddenFeature(d) {
return context.features().autoHidden(d);
}
function showsFeature(d) {
return context.features().enabled(d);
}
function clickFeature(d3_event, d) {
context.features().toggle(d);
}
function showsLayer(id2) {
var layer = context.layers().layer(id2);
return layer && layer.enabled();
}
context.features().on("change.map_features", section.reRender);
return section;
}
// modules/ui/sections/map_style_options.js
function uiSectionMapStyleOptions(context) {
var section = uiSection("fill-area", context).label(_t.html("map_data.style_options")).disclosureContent(renderDisclosureContent).expandedByDefault(false);
function renderDisclosureContent(selection2) {
var container = selection2.selectAll(".layer-fill-list").data([0]);
container.enter().append("ul").attr("class", "layer-list layer-fill-list").merge(container).call(drawListItems, context.map().areaFillOptions, "radio", "area_fill", setFill, isActiveFill);
var container2 = selection2.selectAll(".layer-visual-diff-list").data([0]);
container2.enter().append("ul").attr("class", "layer-list layer-visual-diff-list").merge(container2).call(drawListItems, ["highlight_edits"], "checkbox", "visual_diff", toggleHighlightEdited, function() {
return context.surface().classed("highlight-edited");
});
}
function drawListItems(selection2, data, type3, name2, change, active) {
var items = selection2.selectAll("li").data(data);
items.exit().remove();
var enter = items.enter().append("li").call(uiTooltip().title(function(d) {
return _t.html(name2 + "." + d + ".tooltip");
}).keys(function(d) {
var key = d === "wireframe" ? _t("area_fill.wireframe.key") : null;
if (d === "highlight_edits")
key = _t("map_data.highlight_edits.key");
return key ? [key] : null;
}).placement("top"));
var label = enter.append("label");
label.append("input").attr("type", type3).attr("name", name2).on("change", change);
label.append("span").html(function(d) {
return _t.html(name2 + "." + d + ".description");
});
items = items.merge(enter);
items.classed("active", active).selectAll("input").property("checked", active).property("indeterminate", false);
}
function isActiveFill(d) {
return context.map().activeAreaFill() === d;
}
function toggleHighlightEdited(d3_event) {
d3_event.preventDefault();
context.map().toggleHighlightEdited();
}
function setFill(d3_event, d) {
context.map().activeAreaFill(d);
}
context.map().on("changeHighlighting.ui_style, changeAreaFill.ui_style", section.reRender);
return section;
}
// modules/ui/sections/photo_overlays.js
function uiSectionPhotoOverlays(context) {
var layers = context.layers();
var section = uiSection("photo-overlays", context).label(_t.html("photo_overlays.title")).disclosureContent(renderDisclosureContent).expandedByDefault(false);
function renderDisclosureContent(selection2) {
var container = selection2.selectAll(".photo-overlay-container").data([0]);
container.enter().append("div").attr("class", "photo-overlay-container").merge(container).call(drawPhotoItems).call(drawPhotoTypeItems).call(drawDateFilter).call(drawUsernameFilter);
}
function drawPhotoItems(selection2) {
var photoKeys = context.photos().overlayLayerIDs();
var photoLayers = layers.all().filter(function(obj) {
return photoKeys.indexOf(obj.id) !== -1;
});
var data = photoLayers.filter(function(obj) {
return obj.layer.supported();
});
function layerSupported(d) {
return d.layer && d.layer.supported();
}
function layerEnabled(d) {
return layerSupported(d) && d.layer.enabled();
}
var ul = selection2.selectAll(".layer-list-photos").data([0]);
ul = ul.enter().append("ul").attr("class", "layer-list layer-list-photos").merge(ul);
var li = ul.selectAll(".list-item-photos").data(data);
li.exit().remove();
var liEnter = li.enter().append("li").attr("class", function(d) {
var classes = "list-item-photos list-item-" + d.id;
if (d.id === "mapillary-signs" || d.id === "mapillary-map-features") {
classes += " indented";
}
return classes;
});
var labelEnter = liEnter.append("label").each(function(d) {
var titleID;
if (d.id === "mapillary-signs")
titleID = "mapillary.signs.tooltip";
else if (d.id === "mapillary")
titleID = "mapillary_images.tooltip";
else if (d.id === "kartaview")
titleID = "kartaview_images.tooltip";
else
titleID = d.id.replace(/-/g, "_") + ".tooltip";
select_default2(this).call(uiTooltip().title(_t.html(titleID)).placement("top"));
});
labelEnter.append("input").attr("type", "checkbox").on("change", function(d3_event, d) {
toggleLayer(d.id);
});
labelEnter.append("span").html(function(d) {
var id2 = d.id;
if (id2 === "mapillary-signs")
id2 = "photo_overlays.traffic_signs";
return _t.html(id2.replace(/-/g, "_") + ".title");
});
li.merge(liEnter).classed("active", layerEnabled).selectAll("input").property("checked", layerEnabled);
}
function drawPhotoTypeItems(selection2) {
var data = context.photos().allPhotoTypes();
function typeEnabled(d) {
return context.photos().showsPhotoType(d);
}
var ul = selection2.selectAll(".layer-list-photo-types").data([0]);
ul.exit().remove();
ul = ul.enter().append("ul").attr("class", "layer-list layer-list-photo-types").merge(ul);
var li = ul.selectAll(".list-item-photo-types").data(context.photos().shouldFilterByPhotoType() ? data : []);
li.exit().remove();
var liEnter = li.enter().append("li").attr("class", function(d) {
return "list-item-photo-types list-item-" + d;
});
var labelEnter = liEnter.append("label").each(function(d) {
select_default2(this).call(uiTooltip().title(_t.html("photo_overlays.photo_type." + d + ".tooltip")).placement("top"));
});
labelEnter.append("input").attr("type", "checkbox").on("change", function(d3_event, d) {
context.photos().togglePhotoType(d);
});
labelEnter.append("span").html(function(d) {
return _t.html("photo_overlays.photo_type." + d + ".title");
});
li.merge(liEnter).classed("active", typeEnabled).selectAll("input").property("checked", typeEnabled);
}
function drawDateFilter(selection2) {
var data = context.photos().dateFilters();
function filterEnabled(d) {
return context.photos().dateFilterValue(d);
}
var ul = selection2.selectAll(".layer-list-date-filter").data([0]);
ul.exit().remove();
ul = ul.enter().append("ul").attr("class", "layer-list layer-list-date-filter").merge(ul);
var li = ul.selectAll(".list-item-date-filter").data(context.photos().shouldFilterByDate() ? data : []);
li.exit().remove();
var liEnter = li.enter().append("li").attr("class", "list-item-date-filter");
var labelEnter = liEnter.append("label").each(function(d) {
select_default2(this).call(uiTooltip().title(_t.html("photo_overlays.date_filter." + d + ".tooltip")).placement("top"));
});
labelEnter.append("span").html(function(d) {
return _t.html("photo_overlays.date_filter." + d + ".title");
});
labelEnter.append("input").attr("type", "date").attr("class", "list-item-input").attr("placeholder", _t("units.year_month_day")).call(utilNoAuto).each(function(d) {
utilGetSetValue(select_default2(this), context.photos().dateFilterValue(d) || "");
}).on("change", function(d3_event, d) {
var value = utilGetSetValue(select_default2(this)).trim();
context.photos().setDateFilter(d, value, true);
li.selectAll("input").each(function(d2) {
utilGetSetValue(select_default2(this), context.photos().dateFilterValue(d2) || "");
});
});
li = li.merge(liEnter).classed("active", filterEnabled);
}
function drawUsernameFilter(selection2) {
function filterEnabled() {
return context.photos().usernames();
}
var ul = selection2.selectAll(".layer-list-username-filter").data([0]);
ul.exit().remove();
ul = ul.enter().append("ul").attr("class", "layer-list layer-list-username-filter").merge(ul);
var li = ul.selectAll(".list-item-username-filter").data(context.photos().shouldFilterByUsername() ? ["username-filter"] : []);
li.exit().remove();
var liEnter = li.enter().append("li").attr("class", "list-item-username-filter");
var labelEnter = liEnter.append("label").each(function() {
select_default2(this).call(uiTooltip().title(_t.html("photo_overlays.username_filter.tooltip")).placement("top"));
});
labelEnter.append("span").call(_t.append("photo_overlays.username_filter.title"));
labelEnter.append("input").attr("type", "text").attr("class", "list-item-input").call(utilNoAuto).property("value", usernameValue).on("change", function() {
var value = select_default2(this).property("value");
context.photos().setUsernameFilter(value, true);
select_default2(this).property("value", usernameValue);
});
li.merge(liEnter).classed("active", filterEnabled);
function usernameValue() {
var usernames = context.photos().usernames();
if (usernames)
return usernames.join("; ");
return usernames;
}
}
function toggleLayer(which) {
setLayer(which, !showsLayer(which));
}
function showsLayer(which) {
var layer = layers.layer(which);
if (layer) {
return layer.enabled();
}
return false;
}
function setLayer(which, enabled) {
var layer = layers.layer(which);
if (layer) {
layer.enabled(enabled);
}
}
context.layers().on("change.uiSectionPhotoOverlays", section.reRender);
context.photos().on("change.uiSectionPhotoOverlays", section.reRender);
return section;
}
// modules/ui/panes/map_data.js
function uiPaneMapData(context) {
var mapDataPane = uiPane("map-data", context).key(_t("map_data.key")).label(_t.html("map_data.title")).description(_t.html("map_data.description")).iconName("iD-icon-data").sections([
uiSectionDataLayers(context),
uiSectionPhotoOverlays(context),
uiSectionMapStyleOptions(context),
uiSectionMapFeatures(context)
]);
return mapDataPane;
}
// modules/ui/panes/preferences.js
function uiPanePreferences(context) {
let preferencesPane = uiPane("preferences", context).key(_t("preferences.key")).label(_t.html("preferences.title")).description(_t.html("preferences.description")).iconName("fas-user-cog").sections([
uiSectionPrivacy(context)
]);
return preferencesPane;
}
// modules/ui/init.js
function uiInit(context) {
var _initCounter = 0;
var _needWidth = {};
var _lastPointerType;
function render(container) {
container.on("click.ui", function(d3_event) {
if (d3_event.button !== 0)
return;
if (!d3_event.composedPath)
return;
var isOkayTarget = d3_event.composedPath().some(function(node) {
return node.nodeType === 1 && (node.nodeName === "INPUT" || node.nodeName === "LABEL" || node.nodeName === "A");
});
if (isOkayTarget)
return;
d3_event.preventDefault();
});
var detected = utilDetect();
if ("GestureEvent" in window && !detected.isMobileWebKit) {
container.on("gesturestart.ui gesturechange.ui gestureend.ui", function(d3_event) {
d3_event.preventDefault();
});
}
if ("PointerEvent" in window) {
select_default2(window).on("pointerdown.ui pointerup.ui", function(d3_event) {
var pointerType = d3_event.pointerType || "mouse";
if (_lastPointerType !== pointerType) {
_lastPointerType = pointerType;
container.attr("pointer", pointerType);
}
}, true);
} else {
_lastPointerType = "mouse";
container.attr("pointer", "mouse");
}
container.attr("lang", _mainLocalizer.localeCode()).attr("dir", _mainLocalizer.textDirection());
container.call(uiFullScreen(context));
var map2 = context.map();
map2.redrawEnable(false);
map2.on("hitMinZoom.ui", function() {
ui.flash.iconName("#iD-icon-no").label(_t.html("cannot_zoom"))();
});
container.append("svg").attr("id", "ideditor-defs").call(ui.svgDefs);
container.append("div").attr("class", "sidebar").call(ui.sidebar);
var content = container.append("div").attr("class", "main-content active");
content.append("div").attr("class", "top-toolbar-wrap").append("div").attr("class", "top-toolbar fillD").call(uiTopToolbar(context));
content.append("div").attr("class", "main-map").attr("dir", "ltr").call(map2);
var overMap = content.append("div").attr("class", "over-map");
overMap.append("div").attr("class", "select-trap").text("t");
overMap.call(uiMapInMap(context)).call(uiNotice(context));
overMap.append("div").attr("class", "spinner").call(uiSpinner(context));
var controlsWrap = overMap.append("div").attr("class", "map-controls-wrap");
var controls = controlsWrap.append("div").attr("class", "map-controls");
controls.append("div").attr("class", "map-control zoombuttons").call(uiZoom(context));
controls.append("div").attr("class", "map-control zoom-to-selection-control").call(uiZoomToSelection(context));
controls.append("div").attr("class", "map-control geolocate-control").call(uiGeolocate(context));
controlsWrap.on("wheel.mapControls", function(d3_event) {
if (!d3_event.deltaX) {
controlsWrap.node().scrollTop += d3_event.deltaY;
}
});
var panes = overMap.append("div").attr("class", "map-panes");
var uiPanes = [
uiPaneBackground(context),
uiPaneMapData(context),
uiPaneIssues(context),
uiPanePreferences(context),
uiPaneHelp(context)
];
uiPanes.forEach(function(pane) {
controls.append("div").attr("class", "map-control map-pane-control " + pane.id + "-control").call(pane.renderToggleButton);
panes.call(pane.renderPane);
});
ui.info = uiInfo(context);
overMap.call(ui.info);
overMap.append("div").attr("class", "photoviewer").classed("al", true).classed("hide", true).call(ui.photoviewer);
overMap.append("div").attr("class", "attribution-wrap").attr("dir", "ltr").call(uiAttribution(context));
var about = content.append("div").attr("class", "map-footer");
about.append("div").attr("class", "api-status").call(uiStatus(context));
var footer = about.append("div").attr("class", "map-footer-bar fillD");
footer.append("div").attr("class", "flash-wrap footer-hide");
var footerWrap = footer.append("div").attr("class", "main-footer-wrap footer-show");
footerWrap.append("div").attr("class", "scale-block").call(uiScale(context));
var aboutList = footerWrap.append("div").attr("class", "info-block").append("ul").attr("class", "map-footer-list");
aboutList.append("li").attr("class", "user-list").call(uiContributors(context));
var apiConnections = context.apiConnections();
if (apiConnections && apiConnections.length > 1) {
aboutList.append("li").attr("class", "source-switch").call(uiSourceSwitch(context).keys(apiConnections));
}
aboutList.append("li").attr("class", "issues-info").call(uiIssuesInfo(context));
aboutList.append("li").attr("class", "feature-warning").call(uiFeatureInfo(context));
var issueLinks = aboutList.append("li");
issueLinks.append("a").attr("target", "_blank").attr("href", "https://github.com/openstreetmap/iD/issues").attr("aria-label", _t("report_a_bug")).call(svgIcon("#iD-icon-bug", "light")).call(uiTooltip().title(_t.html("report_a_bug")).placement("top"));
issueLinks.append("a").attr("target", "_blank").attr("href", "https://github.com/openstreetmap/iD/blob/develop/CONTRIBUTING.md#translating").attr("aria-label", _t("help_translate")).call(svgIcon("#iD-icon-translate", "light")).call(uiTooltip().title(_t.html("help_translate")).placement("top"));
aboutList.append("li").attr("class", "version").call(uiVersion(context));
if (!context.embed()) {
aboutList.call(uiAccount(context));
}
ui.onResize();
map2.redrawEnable(true);
ui.hash = behaviorHash(context);
ui.hash();
if (!ui.hash.hadHash) {
map2.centerZoom([0, 0], 2);
}
window.onbeforeunload = function() {
return context.save();
};
window.onunload = function() {
context.history().unlock();
};
select_default2(window).on("resize.editor", function() {
ui.onResize();
});
var panPixels = 80;
context.keybinding().on("\u232B", function(d3_event) {
d3_event.preventDefault();
}).on([_t("sidebar.key"), "`", "\xB2", "@"], ui.sidebar.toggle).on("\u2190", pan([panPixels, 0])).on("\u2191", pan([0, panPixels])).on("\u2192", pan([-panPixels, 0])).on("\u2193", pan([0, -panPixels])).on(uiCmd("\u2325\u2190"), pan([map2.dimensions()[0], 0])).on(uiCmd("\u2325\u2191"), pan([0, map2.dimensions()[1]])).on(uiCmd("\u2325\u2192"), pan([-map2.dimensions()[0], 0])).on(uiCmd("\u2325\u2193"), pan([0, -map2.dimensions()[1]])).on(uiCmd("\u2318" + _t("background.key")), function quickSwitch(d3_event) {
if (d3_event) {
d3_event.stopImmediatePropagation();
d3_event.preventDefault();
}
var previousBackground = context.background().findSource(corePreferences("background-last-used-toggle"));
if (previousBackground) {
var currentBackground = context.background().baseLayerSource();
corePreferences("background-last-used-toggle", currentBackground.id);
corePreferences("background-last-used", previousBackground.id);
context.background().baseLayerSource(previousBackground);
}
}).on(_t("area_fill.wireframe.key"), function toggleWireframe(d3_event) {
d3_event.preventDefault();
d3_event.stopPropagation();
context.map().toggleWireframe();
}).on(uiCmd("\u2325" + _t("area_fill.wireframe.key")), function toggleOsmData(d3_event) {
d3_event.preventDefault();
d3_event.stopPropagation();
var mode = context.mode();
if (mode && /^draw/.test(mode.id))
return;
var layer = context.layers().layer("osm");
if (layer) {
layer.enabled(!layer.enabled());
if (!layer.enabled()) {
context.enter(modeBrowse(context));
}
}
}).on(_t("map_data.highlight_edits.key"), function toggleHighlightEdited(d3_event) {
d3_event.preventDefault();
context.map().toggleHighlightEdited();
});
context.on("enter.editor", function(entered) {
container.classed("mode-" + entered.id, true);
}).on("exit.editor", function(exited) {
container.classed("mode-" + exited.id, false);
});
context.enter(modeBrowse(context));
if (!_initCounter++) {
if (!ui.hash.startWalkthrough) {
context.container().call(uiSplash(context)).call(uiRestore(context));
}
context.container().call(ui.shortcuts);
}
var osm = context.connection();
var auth = uiLoading(context).message(_t.html("loading_auth")).blocking(true);
if (osm && auth) {
osm.on("authLoading.ui", function() {
context.container().call(auth);
}).on("authDone.ui", function() {
auth.close();
});
}
_initCounter++;
if (ui.hash.startWalkthrough) {
ui.hash.startWalkthrough = false;
context.container().call(uiIntro(context));
}
function pan(d) {
return function(d3_event) {
if (d3_event.shiftKey)
return;
if (context.container().select(".combobox").size())
return;
d3_event.preventDefault();
context.map().pan(d, 100);
};
}
}
let ui = {};
let _loadPromise;
ui.ensureLoaded = () => {
if (_loadPromise)
return _loadPromise;
return _loadPromise = Promise.all([
_mainLocalizer.ensureLoaded(),
_mainPresetIndex.ensureLoaded()
]).then(() => {
if (!context.container().empty())
render(context.container());
}).catch((err) => console.error(err));
};
ui.restart = function() {
context.keybinding().clear();
_loadPromise = null;
context.container().selectAll("*").remove();
ui.ensureLoaded();
};
ui.lastPointerType = function() {
return _lastPointerType;
};
ui.svgDefs = svgDefs(context);
ui.flash = uiFlash(context);
ui.sidebar = uiSidebar(context);
ui.photoviewer = uiPhotoviewer(context);
ui.shortcuts = uiShortcuts(context);
ui.onResize = function(withPan) {
var map2 = context.map();
var mapDimensions = utilGetDimensions(context.container().select(".main-content"), true);
utilGetDimensions(context.container().select(".sidebar"), true);
if (withPan !== void 0) {
map2.redrawEnable(false);
map2.pan(withPan);
map2.redrawEnable(true);
}
map2.dimensions(mapDimensions);
ui.photoviewer.onMapResize();
ui.checkOverflow(".top-toolbar");
ui.checkOverflow(".map-footer-bar");
var resizeWindowEvent = document.createEvent("Event");
resizeWindowEvent.initEvent("resizeWindow", true, true);
document.dispatchEvent(resizeWindowEvent);
};
ui.checkOverflow = function(selector, reset) {
if (reset) {
delete _needWidth[selector];
}
var selection2 = context.container().select(selector);
if (selection2.empty())
return;
var scrollWidth = selection2.property("scrollWidth");
var clientWidth = selection2.property("clientWidth");
var needed = _needWidth[selector] || scrollWidth;
if (scrollWidth > clientWidth) {
selection2.classed("narrow", true);
if (!_needWidth[selector]) {
_needWidth[selector] = scrollWidth;
}
} else if (scrollWidth >= needed) {
selection2.classed("narrow", false);
}
};
ui.togglePanes = function(showPane) {
var hidePanes = context.container().selectAll(".map-pane.shown");
var side = _mainLocalizer.textDirection() === "ltr" ? "right" : "left";
hidePanes.classed("shown", false).classed("hide", true);
context.container().selectAll(".map-pane-control button").classed("active", false);
if (showPane) {
hidePanes.classed("shown", false).classed("hide", true).style(side, "-500px");
context.container().selectAll("." + showPane.attr("pane") + "-control button").classed("active", true);
showPane.classed("shown", true).classed("hide", false);
if (hidePanes.empty()) {
showPane.style(side, "-500px").transition().duration(200).style(side, "0px");
} else {
showPane.style(side, "0px");
}
} else {
hidePanes.classed("shown", true).classed("hide", false).style(side, "0px").transition().duration(200).style(side, "-500px").on("end", function() {
select_default2(this).classed("shown", false).classed("hide", true);
});
}
};
var _editMenu = uiEditMenu(context);
ui.editMenu = function() {
return _editMenu;
};
ui.showEditMenu = function(anchorPoint, triggerType, operations) {
ui.closeEditMenu();
if (!operations && context.mode().operations)
operations = context.mode().operations();
if (!operations || !operations.length)
return;
if (!context.map().editableDataEnabled())
return;
var surfaceNode = context.surface().node();
if (surfaceNode.focus) {
surfaceNode.focus();
}
operations.forEach(function(operation) {
if (operation.point)
operation.point(anchorPoint);
});
_editMenu.anchorLoc(anchorPoint).triggerType(triggerType).operations(operations);
context.map().supersurface.call(_editMenu);
};
ui.closeEditMenu = function() {
context.map().supersurface.select(".edit-menu").remove();
};
var _saveLoading = select_default2(null);
context.uploader().on("saveStarted.ui", function() {
_saveLoading = uiLoading(context).message(_t.html("save.uploading")).blocking(true);
context.container().call(_saveLoading);
}).on("saveEnded.ui", function() {
_saveLoading.close();
_saveLoading = select_default2(null);
});
return ui;
}
// modules/core/context.js
function coreContext() {
const dispatch10 = dispatch_default("enter", "exit", "change");
let context = utilRebind({}, dispatch10, "on");
let _deferred2 = /* @__PURE__ */ new Set();
context.version = "2.21.0";
context.privacyVersion = "20201202";
context.initialHashParams = window.location.hash ? utilStringQs(window.location.hash) : {};
context.changeset = null;
let _defaultChangesetComment = context.initialHashParams.comment;
let _defaultChangesetSource = context.initialHashParams.source;
let _defaultChangesetHashtags = context.initialHashParams.hashtags;
context.defaultChangesetComment = function(val) {
if (!arguments.length)
return _defaultChangesetComment;
_defaultChangesetComment = val;
return context;
};
context.defaultChangesetSource = function(val) {
if (!arguments.length)
return _defaultChangesetSource;
_defaultChangesetSource = val;
return context;
};
context.defaultChangesetHashtags = function(val) {
if (!arguments.length)
return _defaultChangesetHashtags;
_defaultChangesetHashtags = val;
return context;
};
let _setsDocumentTitle = true;
context.setsDocumentTitle = function(val) {
if (!arguments.length)
return _setsDocumentTitle;
_setsDocumentTitle = val;
return context;
};
let _documentTitleBase = document.title;
context.documentTitleBase = function(val) {
if (!arguments.length)
return _documentTitleBase;
_documentTitleBase = val;
return context;
};
let _ui;
context.ui = () => _ui;
context.lastPointerType = () => _ui.lastPointerType();
let _keybinding = utilKeybinding("context");
context.keybinding = () => _keybinding;
select_default2(document).call(_keybinding);
let _connection = services.osm;
let _history;
let _validator;
let _uploader;
context.connection = () => _connection;
context.history = () => _history;
context.validator = () => _validator;
context.uploader = () => _uploader;
context.preauth = (options2) => {
if (_connection) {
_connection.switch(options2);
}
return context;
};
let _apiConnections;
context.apiConnections = function(val) {
if (!arguments.length)
return _apiConnections;
_apiConnections = val;
return context;
};
context.locale = function(locale2) {
if (!arguments.length)
return _mainLocalizer.localeCode();
_mainLocalizer.preferredLocaleCodes(locale2);
return context;
};
function afterLoad(cid, callback) {
return (err, result) => {
if (err) {
if (err.status === 400 || err.status === 401 || err.status === 403) {
if (_connection) {
_connection.logout();
}
}
if (typeof callback === "function") {
callback(err);
}
return;
} else if (_connection && _connection.getConnectionId() !== cid) {
if (typeof callback === "function") {
callback({ message: "Connection Switched", status: -1 });
}
return;
} else {
_history.merge(result.data, result.extent);
if (typeof callback === "function") {
callback(err, result);
}
return;
}
};
}
context.loadTiles = (projection2, callback) => {
const handle = window.requestIdleCallback(() => {
_deferred2.delete(handle);
if (_connection && context.editableDataEnabled()) {
const cid = _connection.getConnectionId();
_connection.loadTiles(projection2, afterLoad(cid, callback));
}
});
_deferred2.add(handle);
};
context.loadTileAtLoc = (loc, callback) => {
const handle = window.requestIdleCallback(() => {
_deferred2.delete(handle);
if (_connection && context.editableDataEnabled()) {
const cid = _connection.getConnectionId();
_connection.loadTileAtLoc(loc, afterLoad(cid, callback));
}
});
_deferred2.add(handle);
};
context.loadEntity = (entityID, callback) => {
if (_connection) {
const cid = _connection.getConnectionId();
_connection.loadEntity(entityID, afterLoad(cid, callback));
_connection.loadEntityRelations(entityID, afterLoad(cid, callback));
}
};
context.zoomToEntity = (entityID, zoomTo) => {
context.loadEntity(entityID, (err, result) => {
if (err)
return;
if (zoomTo !== false) {
const entity = result.data.find((e) => e.id === entityID);
if (entity) {
_map.zoomTo(entity);
}
}
});
_map.on("drawn.zoomToEntity", () => {
if (!context.hasEntity(entityID))
return;
_map.on("drawn.zoomToEntity", null);
context.on("enter.zoomToEntity", null);
context.enter(modeSelect(context, [entityID]));
});
context.on("enter.zoomToEntity", () => {
if (_mode.id !== "browse") {
_map.on("drawn.zoomToEntity", null);
context.on("enter.zoomToEntity", null);
}
});
};
let _minEditableZoom = 16;
context.minEditableZoom = function(val) {
if (!arguments.length)
return _minEditableZoom;
_minEditableZoom = val;
if (_connection) {
_connection.tileZoom(val);
}
return context;
};
context.maxCharsForTagKey = () => 255;
context.maxCharsForTagValue = () => 255;
context.maxCharsForRelationRole = () => 255;
function cleanOsmString(val, maxChars) {
if (val === void 0 || val === null) {
val = "";
} else {
val = val.toString();
}
val = val.trim();
if (val.normalize)
val = val.normalize("NFC");
return utilUnicodeCharsTruncated(val, maxChars);
}
context.cleanTagKey = (val) => cleanOsmString(val, context.maxCharsForTagKey());
context.cleanTagValue = (val) => cleanOsmString(val, context.maxCharsForTagValue());
context.cleanRelationRole = (val) => cleanOsmString(val, context.maxCharsForRelationRole());
let _inIntro = false;
context.inIntro = function(val) {
if (!arguments.length)
return _inIntro;
_inIntro = val;
return context;
};
context.save = () => {
if (_inIntro || context.container().select(".modal").size())
return;
let canSave;
if (_mode && _mode.id === "save") {
canSave = false;
if (services.osm && services.osm.isChangesetInflight()) {
_history.clearSaved();
return;
}
} else {
canSave = context.selectedIDs().every((id2) => {
const entity = context.hasEntity(id2);
return entity && !entity.isDegenerate();
});
}
if (canSave) {
_history.save();
}
if (_history.hasChanges()) {
return _t("save.unsaved_changes");
}
};
context.debouncedSave = debounce_default(context.save, 350);
function withDebouncedSave(fn) {
return function() {
const result = fn.apply(_history, arguments);
context.debouncedSave();
return result;
};
}
context.hasEntity = (id2) => _history.graph().hasEntity(id2);
context.entity = (id2) => _history.graph().entity(id2);
let _mode;
context.mode = () => _mode;
context.enter = (newMode) => {
if (_mode) {
_mode.exit();
dispatch10.call("exit", this, _mode);
}
_mode = newMode;
_mode.enter();
dispatch10.call("enter", this, _mode);
};
context.selectedIDs = () => _mode && _mode.selectedIDs && _mode.selectedIDs() || [];
context.activeID = () => _mode && _mode.activeID && _mode.activeID();
let _selectedNoteID;
context.selectedNoteID = function(noteID) {
if (!arguments.length)
return _selectedNoteID;
_selectedNoteID = noteID;
return context;
};
let _selectedErrorID;
context.selectedErrorID = function(errorID) {
if (!arguments.length)
return _selectedErrorID;
_selectedErrorID = errorID;
return context;
};
context.install = (behavior) => context.surface().call(behavior);
context.uninstall = (behavior) => context.surface().call(behavior.off);
let _copyGraph;
context.copyGraph = () => _copyGraph;
let _copyIDs = [];
context.copyIDs = function(val) {
if (!arguments.length)
return _copyIDs;
_copyIDs = val;
_copyGraph = _history.graph();
return context;
};
let _copyLonLat;
context.copyLonLat = function(val) {
if (!arguments.length)
return _copyLonLat;
_copyLonLat = val;
return context;
};
let _background;
context.background = () => _background;
let _features;
context.features = () => _features;
context.hasHiddenConnections = (id2) => {
const graph = _history.graph();
const entity = graph.entity(id2);
return _features.hasHiddenConnections(entity, graph);
};
let _photos;
context.photos = () => _photos;
let _map;
context.map = () => _map;
context.layers = () => _map.layers();
context.surface = () => _map.surface;
context.editableDataEnabled = () => _map.editableDataEnabled();
context.surfaceRect = () => _map.surface.node().getBoundingClientRect();
context.editable = () => {
const mode = context.mode();
if (!mode || mode.id === "save")
return false;
return _map.editableDataEnabled();
};
let _debugFlags = {
tile: false,
collision: false,
imagery: false,
target: false,
downloaded: false
};
context.debugFlags = () => _debugFlags;
context.getDebug = (flag) => flag && _debugFlags[flag];
context.setDebug = function(flag, val) {
if (arguments.length === 1)
val = true;
_debugFlags[flag] = val;
dispatch10.call("change");
return context;
};
let _container = select_default2(null);
context.container = function(val) {
if (!arguments.length)
return _container;
_container = val;
_container.classed("ideditor", true);
return context;
};
context.containerNode = function(val) {
if (!arguments.length)
return context.container().node();
context.container(select_default2(val));
return context;
};
let _embed;
context.embed = function(val) {
if (!arguments.length)
return _embed;
_embed = val;
return context;
};
let _assetPath = "";
context.assetPath = function(val) {
if (!arguments.length)
return _assetPath;
_assetPath = val;
_mainFileFetcher.assetPath(val);
return context;
};
let _assetMap = {};
context.assetMap = function(val) {
if (!arguments.length)
return _assetMap;
_assetMap = val;
_mainFileFetcher.assetMap(val);
return context;
};
context.asset = (val) => {
if (/^http(s)?:\/\//i.test(val))
return val;
const filename = _assetPath + val;
return _assetMap[filename] || filename;
};
context.imagePath = (val) => context.asset(`img/${val}`);
context.reset = context.flush = () => {
context.debouncedSave.cancel();
Array.from(_deferred2).forEach((handle) => {
window.cancelIdleCallback(handle);
_deferred2.delete(handle);
});
Object.values(services).forEach((service) => {
if (service && typeof service.reset === "function") {
service.reset(context);
}
});
context.changeset = null;
_validator.reset();
_features.reset();
_history.reset();
_uploader.reset();
context.container().select(".inspector-wrap *").remove();
return context;
};
context.projection = geoRawMercator();
context.curtainProjection = geoRawMercator();
context.init = () => {
instantiateInternal();
initializeDependents();
return context;
function instantiateInternal() {
_history = coreHistory(context);
context.graph = _history.graph;
context.pauseChangeDispatch = _history.pauseChangeDispatch;
context.resumeChangeDispatch = _history.resumeChangeDispatch;
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);
_validator = coreValidator(context);
_uploader = coreUploader(context);
_background = rendererBackground(context);
_features = rendererFeatures(context);
_map = rendererMap(context);
_photos = rendererPhotos(context);
_ui = uiInit(context);
}
function initializeDependents() {
if (context.initialHashParams.presets) {
_mainPresetIndex.addablePresetIDs(new Set(context.initialHashParams.presets.split(",")));
}
if (context.initialHashParams.locale) {
_mainLocalizer.preferredLocaleCodes(context.initialHashParams.locale);
}
_mainLocalizer.ensureLoaded();
_background.ensureLoaded();
_mainPresetIndex.ensureLoaded();
Object.values(services).forEach((service) => {
if (service && typeof service.init === "function") {
service.init();
}
});
_map.init();
_validator.init();
_features.init();
if (services.maprules && context.initialHashParams.maprules) {
json_default(context.initialHashParams.maprules).then((mapcss) => {
services.maprules.init();
mapcss.forEach((mapcssSelector) => services.maprules.addRule(mapcssSelector));
}).catch(() => {
});
}
if (!context.container().empty()) {
_ui.ensureLoaded().then(() => {
_photos.init();
});
}
}
};
return context;
}
// modules/services/nsi.js
var _nsiStatus = "loading";
var _nsi = {};
var buildingPreset = {
"building/commercial": true,
"building/government": true,
"building/hotel": true,
"building/retail": true,
"building/office": true,
"building/supermarket": true,
"building/yes": true
};
var notNames = /:(colou?r|type|forward|backward|left|right|etymology|pronunciation|wikipedia)$/i;
var notBranches = /(coop|express|wireless|factory|outlet)/i;
function setNsiSources() {
const nsiVersion = package_default.dependencies["name-suggestion-index"] || package_default.devDependencies["name-suggestion-index"];
const v = (0, import_vparse2.default)(nsiVersion);
const vMinor = `${v.major}.${v.minor}`;
const sources = {
"nsi_data": `https://cdn.jsdelivr.net/npm/name-suggestion-index@${vMinor}/dist/nsi.min.json`,
"nsi_dissolved": `https://cdn.jsdelivr.net/npm/name-suggestion-index@${vMinor}/dist/dissolved.min.json`,
"nsi_features": `https://cdn.jsdelivr.net/npm/name-suggestion-index@${vMinor}/dist/featureCollection.min.json`,
"nsi_generics": `https://cdn.jsdelivr.net/npm/name-suggestion-index@${vMinor}/dist/genericWords.min.json`,
"nsi_presets": `https://cdn.jsdelivr.net/npm/name-suggestion-index@${vMinor}/dist/presets/nsi-id-presets.min.json`,
"nsi_replacements": `https://cdn.jsdelivr.net/npm/name-suggestion-index@${vMinor}/dist/replacements.min.json`,
"nsi_trees": `https://cdn.jsdelivr.net/npm/name-suggestion-index@${vMinor}/dist/trees.min.json`
};
let fileMap = _mainFileFetcher.fileMap();
for (const k in sources) {
if (!fileMap[k])
fileMap[k] = sources[k];
}
}
function loadNsiPresets() {
return Promise.all([
_mainFileFetcher.get("nsi_presets"),
_mainFileFetcher.get("nsi_features")
]).then((vals) => {
Object.values(vals[0].presets).forEach((preset) => preset.suggestion = true);
_mainPresetIndex.merge({
presets: vals[0].presets,
featureCollection: vals[1]
});
});
}
function loadNsiData() {
return Promise.all([
_mainFileFetcher.get("nsi_data"),
_mainFileFetcher.get("nsi_dissolved"),
_mainFileFetcher.get("nsi_replacements"),
_mainFileFetcher.get("nsi_trees")
]).then((vals) => {
_nsi = {
data: vals[0].nsi,
dissolved: vals[1].dissolved,
replacements: vals[2].replacements,
trees: vals[3].trees,
kvt: /* @__PURE__ */ new Map(),
qids: /* @__PURE__ */ new Map(),
ids: /* @__PURE__ */ new Map()
};
_nsi.matcher = new Matcher();
_nsi.matcher.buildMatchIndex(_nsi.data);
_nsi.matcher.buildLocationIndex(_nsi.data, _mainLocations.loco());
Object.keys(_nsi.data).forEach((tkv) => {
const category = _nsi.data[tkv];
const parts = tkv.split("/", 3);
const t = parts[0];
const k = parts[1];
const v = parts[2];
let vmap = _nsi.kvt.get(k);
if (!vmap) {
vmap = /* @__PURE__ */ new Map();
_nsi.kvt.set(k, vmap);
}
vmap.set(v, t);
const tree = _nsi.trees[t];
const mainTag = tree.mainTag;
const items = category.items || [];
items.forEach((item) => {
item.tkv = tkv;
item.mainTag = mainTag;
_nsi.ids.set(item.id, item);
const wd = item.tags[mainTag];
const wp = item.tags[mainTag.replace("wikidata", "wikipedia")];
if (wd)
_nsi.qids.set(wd, wd);
if (wp && wd)
_nsi.qids.set(wp, wd);
});
});
});
}
function gatherKVs(tags) {
let primary = /* @__PURE__ */ new Set();
let alternate = /* @__PURE__ */ new Set();
Object.keys(tags).forEach((osmkey) => {
const osmvalue = tags[osmkey];
if (!osmvalue)
return;
if (osmkey === "route_master")
osmkey = "route";
const vmap = _nsi.kvt.get(osmkey);
if (!vmap)
return;
if (vmap.get(osmvalue)) {
primary.add(`${osmkey}/${osmvalue}`);
} else if (osmvalue === "yes") {
alternate.add(`${osmkey}/${osmvalue}`);
}
});
const preset = _mainPresetIndex.matchTags(tags, "area");
if (buildingPreset[preset.id]) {
alternate.add("building/yes");
}
return { primary, alternate };
}
function identifyTree(tags) {
let unknown;
let t;
Object.keys(tags).forEach((osmkey) => {
if (t)
return;
const osmvalue = tags[osmkey];
if (!osmvalue)
return;
if (osmkey === "route_master")
osmkey = "route";
const vmap = _nsi.kvt.get(osmkey);
if (!vmap)
return;
if (osmvalue === "yes") {
unknown = "unknown";
} else {
t = vmap.get(osmvalue);
}
});
return t || unknown || null;
}
function gatherNames(tags) {
const empty2 = { primary: /* @__PURE__ */ new Set(), alternate: /* @__PURE__ */ new Set() };
let primary = /* @__PURE__ */ new Set();
let alternate = /* @__PURE__ */ new Set();
let foundSemi = false;
let testNameFragments = false;
let patterns2;
let t = identifyTree(tags);
if (!t)
return empty2;
if (t === "transit") {
patterns2 = {
primary: /^network$/i,
alternate: /^(operator|operator:\w+|network:\w+|\w+_name|\w+_name:\w+)$/i
};
} else if (t === "flags") {
patterns2 = {
primary: /^(flag:name|flag:name:\w+)$/i,
alternate: /^(flag|flag:\w+|subject|subject:\w+)$/i
};
} else if (t === "brands") {
testNameFragments = true;
patterns2 = {
primary: /^(name|name:\w+)$/i,
alternate: /^(brand|brand:\w+|operator|operator:\w+|\w+_name|\w+_name:\w+)/i
};
} else if (t === "operators") {
testNameFragments = true;
patterns2 = {
primary: /^(name|name:\w+|operator|operator:\w+)$/i,
alternate: /^(brand|brand:\w+|\w+_name|\w+_name:\w+)/i
};
} else {
testNameFragments = true;
patterns2 = {
primary: /^(name|name:\w+)$/i,
alternate: /^(brand|brand:\w+|network|network:\w+|operator|operator:\w+|\w+_name|\w+_name:\w+)/i
};
}
if (tags.name && testNameFragments) {
const nameParts = tags.name.split(/[\s\-\/,.]/);
for (let split = nameParts.length; split > 0; split--) {
const name2 = nameParts.slice(0, split).join(" ");
primary.add(name2);
}
}
Object.keys(tags).forEach((osmkey) => {
const osmvalue = tags[osmkey];
if (!osmvalue)
return;
if (isNamelike(osmkey, "primary")) {
if (/;/.test(osmvalue)) {
foundSemi = true;
} else {
primary.add(osmvalue);
alternate.delete(osmvalue);
}
} else if (!primary.has(osmvalue) && isNamelike(osmkey, "alternate")) {
if (/;/.test(osmvalue)) {
foundSemi = true;
} else {
alternate.add(osmvalue);
}
}
});
if (tags.man_made === "flagpole" && !primary.size && !alternate.size && !!tags.country) {
const osmvalue = tags.country;
if (/;/.test(osmvalue)) {
foundSemi = true;
} else {
alternate.add(osmvalue);
}
}
if (foundSemi) {
return empty2;
} else {
return { primary, alternate };
}
function isNamelike(osmkey, which) {
if (osmkey === "old_name")
return false;
return patterns2[which].test(osmkey) && !notNames.test(osmkey);
}
}
function gatherTuples(tryKVs, tryNames) {
let tuples = [];
["primary", "alternate"].forEach((whichName) => {
const arr = Array.from(tryNames[whichName]).sort((a, b) => b.length - a.length);
arr.forEach((n2) => {
["primary", "alternate"].forEach((whichKV) => {
tryKVs[whichKV].forEach((kv) => {
const parts = kv.split("/", 2);
const k = parts[0];
const v = parts[1];
tuples.push({ k, v, n: n2 });
});
});
});
});
return tuples;
}
function _upgradeTags(tags, loc) {
let newTags = Object.assign({}, tags);
let changed = false;
Object.keys(newTags).forEach((osmkey) => {
const matchTag = osmkey.match(/^(\w+:)?wikidata$/);
if (matchTag) {
const prefix = matchTag[1] || "";
const wd = newTags[osmkey];
const replace = _nsi.replacements[wd];
if (replace && replace.wikidata !== void 0) {
changed = true;
if (replace.wikidata) {
newTags[osmkey] = replace.wikidata;
} else {
delete newTags[osmkey];
}
}
if (replace && replace.wikipedia !== void 0) {
changed = true;
const wpkey = `${prefix}wikipedia`;
if (replace.wikipedia) {
newTags[wpkey] = replace.wikipedia;
} else {
delete newTags[wpkey];
}
}
}
});
const isRouteMaster = tags.type === "route_master";
const tryKVs = gatherKVs(tags);
if (!tryKVs.primary.size && !tryKVs.alternate.size) {
return changed ? { newTags, matched: null } : null;
}
const tryNames = gatherNames(tags);
const foundQID = _nsi.qids.get(tags.wikidata) || _nsi.qids.get(tags.wikipedia);
if (foundQID)
tryNames.primary.add(foundQID);
if (!tryNames.primary.size && !tryNames.alternate.size) {
return changed ? { newTags, matched: null } : null;
}
const tuples = gatherTuples(tryKVs, tryNames);
let foundPrimary = false;
let bestItem;
for (let i2 = 0; i2 < tuples.length && !foundPrimary; i2++) {
const tuple = tuples[i2];
const hits = _nsi.matcher.match(tuple.k, tuple.v, tuple.n, loc);
if (!hits || !hits.length)
continue;
if (hits[0].match !== "primary" && hits[0].match !== "alternate")
break;
for (let j2 = 0; j2 < hits.length; j2++) {
const hit = hits[j2];
const isPrimary = hits[j2].match === "primary";
const itemID = hit.itemID;
if (_nsi.dissolved[itemID])
continue;
const item = _nsi.ids.get(itemID);
if (!item)
continue;
const mainTag = item.mainTag;
const itemQID = item.tags[mainTag];
const notQID = newTags[`not:${mainTag}`];
if (!itemQID || itemQID === notQID || newTags.office && !item.tags.office) {
continue;
}
if (!bestItem || isPrimary) {
bestItem = item;
if (isPrimary) {
foundPrimary = true;
}
break;
}
}
}
if (bestItem) {
const itemID = bestItem.id;
const item = JSON.parse(JSON.stringify(bestItem));
const tkv = item.tkv;
const parts = tkv.split("/", 3);
const k = parts[1];
const v = parts[2];
const category = _nsi.data[tkv];
const properties = category.properties || {};
let preserveTags = item.preserveTags || properties.preserveTags || [];
["building", "emergency", "internet_access", "takeaway"].forEach((osmkey) => {
if (k !== osmkey)
preserveTags.push(`^${osmkey}$`);
});
const regexes = preserveTags.map((s) => new RegExp(s, "i"));
let keepTags = {};
Object.keys(newTags).forEach((osmkey) => {
if (regexes.some((regex) => regex.test(osmkey))) {
keepTags[osmkey] = newTags[osmkey];
}
});
_nsi.kvt.forEach((vmap, k2) => {
if (newTags[k2] === "yes")
delete newTags[k2];
});
if (foundQID) {
delete newTags.wikipedia;
delete newTags.wikidata;
}
Object.assign(newTags, item.tags, keepTags);
if (isRouteMaster) {
newTags.route_master = newTags.route;
delete newTags.route;
}
const origName = tags.name;
const newName = newTags.name;
if (newName && origName && newName !== origName && !newTags.branch) {
const newNames = gatherNames(newTags);
const newSet = /* @__PURE__ */ new Set([...newNames.primary, ...newNames.alternate]);
const isMoved = newSet.has(origName);
if (!isMoved) {
const nameParts = origName.split(/[\s\-\/,.]/);
for (let split = nameParts.length; split > 0; split--) {
const name2 = nameParts.slice(0, split).join(" ");
const branch = nameParts.slice(split).join(" ");
const nameHits = _nsi.matcher.match(k, v, name2, loc);
if (!nameHits || !nameHits.length)
continue;
if (nameHits.some((hit) => hit.itemID === itemID)) {
if (branch) {
if (notBranches.test(branch)) {
newTags.name = origName;
} else {
const branchHits = _nsi.matcher.match(k, v, branch, loc);
if (branchHits && branchHits.length) {
if (branchHits[0].match === "primary" || branchHits[0].match === "alternate") {
return null;
}
} else {
newTags.branch = branch;
}
}
}
break;
}
}
}
}
return { newTags, matched: item };
}
return changed ? { newTags, matched: null } : null;
}
function _isGenericName(tags) {
const n2 = tags.name;
if (!n2)
return false;
const tryNames = { primary: /* @__PURE__ */ new Set([n2]), alternate: /* @__PURE__ */ new Set() };
const tryKVs = gatherKVs(tags);
if (!tryKVs.primary.size && !tryKVs.alternate.size)
return false;
const tuples = gatherTuples(tryKVs, tryNames);
for (let i2 = 0; i2 < tuples.length; i2++) {
const tuple = tuples[i2];
const hits = _nsi.matcher.match(tuple.k, tuple.v, tuple.n);
if (hits && hits.length && hits[0].match === "excludeGeneric")
return true;
}
return false;
}
var nsi_default = {
init: () => {
setNsiSources();
_mainPresetIndex.ensureLoaded().then(() => loadNsiPresets()).then(() => delay(100)).then(() => _mainLocations.mergeLocationSets([])).then(() => loadNsiData()).then(() => _nsiStatus = "ok").catch(() => _nsiStatus = "failed");
function delay(msec) {
return new Promise((resolve) => {
window.setTimeout(resolve, msec);
});
}
},
reset: () => {
},
status: () => _nsiStatus,
isGenericName: (tags) => _isGenericName(tags),
upgradeTags: (tags, loc) => _upgradeTags(tags, loc),
cache: () => _nsi
};
// modules/services/kartaview.js
var import_rbush8 = __toESM(require_rbush_min());
var apibase2 = "https://kartaview.org";
var maxResults = 1e3;
var tileZoom = 14;
var tiler4 = utilTiler().zoomExtent([tileZoom, tileZoom]).skipNullIsland(true);
var dispatch6 = dispatch_default("loadedImages");
var imgZoom = zoom_default2().extent([[0, 0], [320, 240]]).translateExtent([[0, 0], [320, 240]]).scaleExtent([1, 15]);
var _oscCache;
var _oscSelectedImage;
var _loadViewerPromise2;
function abortRequest4(controller) {
controller.abort();
}
function maxPageAtZoom(z) {
if (z < 15)
return 2;
if (z === 15)
return 5;
if (z === 16)
return 10;
if (z === 17)
return 20;
if (z === 18)
return 40;
if (z > 18)
return 80;
}
function loadTiles2(which, url, projection2) {
var currZoom = Math.floor(geoScaleToZoom(projection2.scale()));
var tiles = tiler4.getTiles(projection2);
var cache = _oscCache[which];
Object.keys(cache.inflight).forEach(function(k) {
var wanted = tiles.find(function(tile) {
return k.indexOf(tile.id + ",") === 0;
});
if (!wanted) {
abortRequest4(cache.inflight[k]);
delete cache.inflight[k];
}
});
tiles.forEach(function(tile) {
loadNextTilePage(which, currZoom, url, tile);
});
}
function loadNextTilePage(which, currZoom, url, tile) {
var cache = _oscCache[which];
var bbox = tile.extent.bbox();
var maxPages = maxPageAtZoom(currZoom);
var nextPage = cache.nextPage[tile.id] || 1;
var params = utilQsString({
ipp: maxResults,
page: nextPage,
bbTopLeft: [bbox.maxY, bbox.minX].join(","),
bbBottomRight: [bbox.minY, bbox.maxX].join(",")
}, true);
if (nextPage > maxPages)
return;
var id2 = tile.id + "," + String(nextPage);
if (cache.loaded[id2] || cache.inflight[id2])
return;
var controller = new AbortController();
cache.inflight[id2] = controller;
var options2 = {
method: "POST",
signal: controller.signal,
body: params,
headers: { "Content-Type": "application/x-www-form-urlencoded" }
};
json_default(url, options2).then(function(data) {
cache.loaded[id2] = true;
delete cache.inflight[id2];
if (!data || !data.currentPageItems || !data.currentPageItems.length) {
throw new Error("No Data");
}
var features2 = data.currentPageItems.map(function(item) {
var loc = [+item.lng, +item.lat];
var d;
if (which === "images") {
d = {
loc,
key: item.id,
ca: +item.heading,
captured_at: item.shot_date || item.date_added,
captured_by: item.username,
imagePath: item.lth_name,
sequence_id: item.sequence_id,
sequence_index: +item.sequence_index
};
var seq = _oscCache.sequences[d.sequence_id];
if (!seq) {
seq = { rotation: 0, images: [] };
_oscCache.sequences[d.sequence_id] = seq;
}
seq.images[d.sequence_index] = d;
_oscCache.images.forImageKey[d.key] = d;
}
return {
minX: loc[0],
minY: loc[1],
maxX: loc[0],
maxY: loc[1],
data: d
};
});
cache.rtree.load(features2);
if (data.currentPageItems.length === maxResults) {
cache.nextPage[tile.id] = nextPage + 1;
loadNextTilePage(which, currZoom, url, tile);
} else {
cache.nextPage[tile.id] = Infinity;
}
if (which === "images") {
dispatch6.call("loadedImages");
}
}).catch(function() {
cache.loaded[id2] = true;
delete cache.inflight[id2];
});
}
function partitionViewport2(projection2) {
var z = geoScaleToZoom(projection2.scale());
var z2 = Math.ceil(z * 2) / 2 + 2.5;
var tiler8 = utilTiler().zoomExtent([z2, z2]);
return tiler8.getTiles(projection2).map(function(tile) {
return tile.extent;
});
}
function searchLimited2(limit, projection2, rtree) {
limit = limit || 5;
return partitionViewport2(projection2).reduce(function(result, extent) {
var found = rtree.search(extent.bbox()).slice(0, limit).map(function(d) {
return d.data;
});
return found.length ? result.concat(found) : result;
}, []);
}
var kartaview_default = {
init: function() {
if (!_oscCache) {
this.reset();
}
this.event = utilRebind(this, dispatch6, "on");
},
reset: function() {
if (_oscCache) {
Object.values(_oscCache.images.inflight).forEach(abortRequest4);
}
_oscCache = {
images: { inflight: {}, loaded: {}, nextPage: {}, rtree: new import_rbush8.default(), forImageKey: {} },
sequences: {}
};
_oscSelectedImage = null;
},
images: function(projection2) {
var limit = 5;
return searchLimited2(limit, projection2, _oscCache.images.rtree);
},
sequences: function(projection2) {
var viewport = projection2.clipExtent();
var min3 = [viewport[0][0], viewport[1][1]];
var max3 = [viewport[1][0], viewport[0][1]];
var bbox = geoExtent(projection2.invert(min3), projection2.invert(max3)).bbox();
var sequenceKeys = {};
_oscCache.images.rtree.search(bbox).forEach(function(d) {
sequenceKeys[d.data.sequence_id] = true;
});
var lineStrings = [];
Object.keys(sequenceKeys).forEach(function(sequenceKey) {
var seq = _oscCache.sequences[sequenceKey];
var images = seq && seq.images;
if (images) {
lineStrings.push({
type: "LineString",
coordinates: images.map(function(d) {
return d.loc;
}).filter(Boolean),
properties: {
captured_at: images[0] ? images[0].captured_at : null,
captured_by: images[0] ? images[0].captured_by : null,
key: sequenceKey
}
});
}
});
return lineStrings;
},
cachedImage: function(imageKey) {
return _oscCache.images.forImageKey[imageKey];
},
loadImages: function(projection2) {
var url = apibase2 + "/1.0/list/nearby-photos/";
loadTiles2("images", url, projection2);
},
ensureViewerLoaded: function(context) {
if (_loadViewerPromise2)
return _loadViewerPromise2;
var wrap2 = context.container().select(".photoviewer").selectAll(".kartaview-wrapper").data([0]);
var that = this;
var wrapEnter = wrap2.enter().append("div").attr("class", "photo-wrapper kartaview-wrapper").classed("hide", true).call(imgZoom.on("zoom", zoomPan)).on("dblclick.zoom", null);
wrapEnter.append("div").attr("class", "photo-attribution fillD");
var controlsEnter = wrapEnter.append("div").attr("class", "photo-controls-wrap").append("div").attr("class", "photo-controls");
controlsEnter.append("button").on("click.back", step(-1)).text("\u25C4");
controlsEnter.append("button").on("click.rotate-ccw", rotate(-90)).text("\u293F");
controlsEnter.append("button").on("click.rotate-cw", rotate(90)).text("\u293E");
controlsEnter.append("button").on("click.forward", step(1)).text("\u25BA");
wrapEnter.append("div").attr("class", "kartaview-image-wrap");
context.ui().photoviewer.on("resize.kartaview", function(dimensions) {
imgZoom = zoom_default2().extent([[0, 0], dimensions]).translateExtent([[0, 0], dimensions]).scaleExtent([1, 15]).on("zoom", zoomPan);
});
function zoomPan(d3_event) {
var t = d3_event.transform;
context.container().select(".photoviewer .kartaview-image-wrap").call(utilSetTransform, t.x, t.y, t.k);
}
function rotate(deg) {
return function() {
if (!_oscSelectedImage)
return;
var sequenceKey = _oscSelectedImage.sequence_id;
var sequence = _oscCache.sequences[sequenceKey];
if (!sequence)
return;
var r = sequence.rotation || 0;
r += deg;
if (r > 180)
r -= 360;
if (r < -180)
r += 360;
sequence.rotation = r;
var wrap3 = context.container().select(".photoviewer .kartaview-wrapper");
wrap3.transition().duration(100).call(imgZoom.transform, identity2);
wrap3.selectAll(".kartaview-image").transition().duration(100).style("transform", "rotate(" + r + "deg)");
};
}
function step(stepBy) {
return function() {
if (!_oscSelectedImage)
return;
var sequenceKey = _oscSelectedImage.sequence_id;
var sequence = _oscCache.sequences[sequenceKey];
if (!sequence)
return;
var nextIndex = _oscSelectedImage.sequence_index + stepBy;
var nextImage = sequence.images[nextIndex];
if (!nextImage)
return;
context.map().centerEase(nextImage.loc);
that.selectImage(context, nextImage.key);
};
}
_loadViewerPromise2 = Promise.resolve();
return _loadViewerPromise2;
},
showViewer: function(context) {
var viewer = context.container().select(".photoviewer").classed("hide", false);
var isHidden = viewer.selectAll(".photo-wrapper.kartaview-wrapper.hide").size();
if (isHidden) {
viewer.selectAll(".photo-wrapper:not(.kartaview-wrapper)").classed("hide", true);
viewer.selectAll(".photo-wrapper.kartaview-wrapper").classed("hide", false);
}
return this;
},
hideViewer: function(context) {
_oscSelectedImage = null;
this.updateUrlImage(null);
var viewer = context.container().select(".photoviewer");
if (!viewer.empty())
viewer.datum(null);
viewer.classed("hide", true).selectAll(".photo-wrapper").classed("hide", true);
context.container().selectAll(".viewfield-group, .sequence, .icon-sign").classed("currentView", false);
return this.setStyles(context, null, true);
},
selectImage: function(context, imageKey) {
var d = this.cachedImage(imageKey);
_oscSelectedImage = d;
this.updateUrlImage(imageKey);
var viewer = context.container().select(".photoviewer");
if (!viewer.empty())
viewer.datum(d);
this.setStyles(context, null, true);
context.container().selectAll(".icon-sign").classed("currentView", false);
if (!d)
return this;
var wrap2 = context.container().select(".photoviewer .kartaview-wrapper");
var imageWrap = wrap2.selectAll(".kartaview-image-wrap");
var attribution = wrap2.selectAll(".photo-attribution").text("");
wrap2.transition().duration(100).call(imgZoom.transform, identity2);
imageWrap.selectAll(".kartaview-image").remove();
if (d) {
var sequence = _oscCache.sequences[d.sequence_id];
var r = sequence && sequence.rotation || 0;
imageWrap.append("img").attr("class", "kartaview-image").attr("src", apibase2 + "/" + d.imagePath).style("transform", "rotate(" + r + "deg)");
if (d.captured_by) {
attribution.append("a").attr("class", "captured_by").attr("target", "_blank").attr("href", "https://kartaview.org/user/" + encodeURIComponent(d.captured_by)).text("@" + d.captured_by);
attribution.append("span").text("|");
}
if (d.captured_at) {
attribution.append("span").attr("class", "captured_at").text(localeDateString2(d.captured_at));
attribution.append("span").text("|");
}
attribution.append("a").attr("class", "image-link").attr("target", "_blank").attr("href", "https://kartaview.org/details/" + d.sequence_id + "/" + d.sequence_index).text("kartaview.org");
}
return this;
function localeDateString2(s) {
if (!s)
return null;
var options2 = { day: "numeric", month: "short", year: "numeric" };
var d2 = new Date(s);
if (isNaN(d2.getTime()))
return null;
return d2.toLocaleDateString(_mainLocalizer.localeCode(), options2);
}
},
getSelectedImage: function() {
return _oscSelectedImage;
},
getSequenceKeyForImage: function(d) {
return d && d.sequence_id;
},
setStyles: function(context, hovered, reset) {
if (reset) {
context.container().selectAll(".viewfield-group").classed("highlighted", false).classed("hovered", false).classed("currentView", false);
context.container().selectAll(".sequence").classed("highlighted", false).classed("currentView", false);
}
var hoveredImageKey = hovered && hovered.key;
var hoveredSequenceKey = this.getSequenceKeyForImage(hovered);
var hoveredSequence = hoveredSequenceKey && _oscCache.sequences[hoveredSequenceKey];
var hoveredImageKeys = hoveredSequence && hoveredSequence.images.map(function(d) {
return d.key;
}) || [];
var viewer = context.container().select(".photoviewer");
var selected = viewer.empty() ? void 0 : viewer.datum();
var selectedImageKey = selected && selected.key;
var selectedSequenceKey = this.getSequenceKeyForImage(selected);
var selectedSequence = selectedSequenceKey && _oscCache.sequences[selectedSequenceKey];
var selectedImageKeys = selectedSequence && selectedSequence.images.map(function(d) {
return d.key;
}) || [];
var highlightedImageKeys = utilArrayUnion(hoveredImageKeys, selectedImageKeys);
context.container().selectAll(".layer-kartaview .viewfield-group").classed("highlighted", function(d) {
return highlightedImageKeys.indexOf(d.key) !== -1;
}).classed("hovered", function(d) {
return d.key === hoveredImageKey;
}).classed("currentView", function(d) {
return d.key === selectedImageKey;
});
context.container().selectAll(".layer-kartaview .sequence").classed("highlighted", function(d) {
return d.properties.key === hoveredSequenceKey;
}).classed("currentView", function(d) {
return d.properties.key === selectedSequenceKey;
});
context.container().selectAll(".layer-kartaview .viewfield-group .viewfield").attr("d", viewfieldPath);
function viewfieldPath() {
var d = this.parentNode.__data__;
if (d.pano && d.key !== selectedImageKey) {
return "M 8,13 m -10,0 a 10,10 0 1,0 20,0 a 10,10 0 1,0 -20,0";
} else {
return "M 6,9 C 8,8.4 8,8.4 10,9 L 16,-2 C 12,-5 4,-5 0,-2 z";
}
}
return this;
},
updateUrlImage: function(imageKey) {
if (!window.mocha) {
var hash = utilStringQs(window.location.hash);
if (imageKey) {
hash.photo = "kartaview/" + imageKey;
} else {
delete hash.photo;
}
window.location.replace("#" + utilQsString(hash, true));
}
},
cache: function() {
return _oscCache;
}
};
// node_modules/osm-auth/src/osm-auth.mjs
var import_store = __toESM(require_store_legacy(), 1);
function osmAuth(o) {
var oauth2 = {};
oauth2.authenticated = function() {
return !!token("oauth2_access_token");
};
oauth2.logout = function() {
token("oauth2_access_token", "");
token("oauth_token", "");
token("oauth_token_secret", "");
token("oauth_request_token_secret", "");
return oauth2;
};
oauth2.authenticate = function(callback) {
if (oauth2.authenticated()) {
callback(null, oauth2);
return;
}
oauth2.logout();
var url = o.url + "/oauth2/authorize?" + utilQsString2({
client_id: o.client_id,
redirect_uri: o.redirect_uri,
response_type: "code",
scope: o.scope
});
if (!o.singlepage) {
var w = 600;
var h = 550;
var settings = [
["width", w],
["height", h],
["left", screen.width / 2 - w / 2],
["top", screen.height / 2 - h / 2]
].map(function(x) {
return x.join("=");
}).join(",");
var popup = window.open("about:blank", "oauth_window", settings);
oauth2.popupWindow = popup;
popup.location = url;
if (!popup) {
var error = new Error("Popup was blocked");
error.status = "popup-blocked";
throw error;
}
}
window.authComplete = function(url2) {
var params = utilStringQs2(url2.split("?")[1]);
getAccessToken(params.code);
delete window.authComplete;
};
function getAccessToken(auth_code) {
var url2 = o.url + "/oauth2/token?" + utilQsString2({
client_id: o.client_id,
grant_type: "authorization_code",
code: auth_code,
redirect_uri: o.redirect_uri,
client_secret: o.client_secret
});
oauth2.rawxhr("POST", url2, null, null, null, accessTokenDone);
o.loading();
}
function accessTokenDone(err, xhr) {
o.done();
if (err) {
callback(err);
return;
}
var access_token = JSON.parse(xhr.response);
token("oauth2_access_token", access_token.access_token);
callback(null, oauth2);
}
};
oauth2.bringPopupWindowToFront = function() {
var broughtPopupToFront = false;
try {
if (oauth2.popupWindow && !oauth2.popupWindow.closed) {
oauth2.popupWindow.focus();
broughtPopupToFront = true;
}
} catch (err) {
}
return broughtPopupToFront;
};
oauth2.bootstrapToken = function(auth_code, callback) {
function getAccessToken(auth_code2) {
var url = o.url + "/oauth2/token?" + utilQsString2({
client_id: o.client_id,
grant_type: "authorization_code",
code: auth_code2,
redirect_uri: o.redirect_uri,
client_secret: o.client_secret
});
oauth2.rawxhr("POST", url, null, null, null, accessTokenDone);
o.loading();
}
function accessTokenDone(err, xhr) {
o.done();
if (err) {
callback(err);
return;
}
var access_token = JSON.parse(xhr.response);
token("oauth2_access_token", access_token.access_token);
callback(null, oauth2);
}
getAccessToken(auth_code);
};
oauth2.xhr = function(options2, callback) {
if (oauth2.authenticated()) {
return run();
} else {
if (o.auto) {
oauth2.authenticate(run);
return;
} else {
callback("not authenticated", null);
return;
}
}
function run() {
var url = options2.prefix !== false ? o.url + options2.path : options2.path;
return oauth2.rawxhr(options2.method, url, token("oauth2_access_token"), options2.content, options2.headers, done);
}
function done(err, xhr) {
if (err) {
callback(err);
} else if (xhr.responseXML) {
callback(err, xhr.responseXML);
} else {
callback(err, xhr.response);
}
}
};
oauth2.rawxhr = function(method, url, access_token, data, headers, callback) {
headers = headers || { "Content-Type": "application/x-www-form-urlencoded" };
if (access_token) {
headers.Authorization = "Bearer " + access_token;
}
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status !== 0) {
if (/^20\d$/.test(xhr.status)) {
callback(null, xhr);
} else {
callback(xhr, null);
}
}
};
xhr.onerror = function(e) {
callback(e, null);
};
xhr.open(method, url, true);
for (var h in headers)
xhr.setRequestHeader(h, headers[h]);
xhr.send(data);
return xhr;
};
oauth2.preauth = function(val) {
if (val && val.access_token) {
token("oauth2_access_token", val.access_token);
}
return oauth2;
};
oauth2.options = function(val) {
if (!arguments.length)
return o;
o = val;
o.url = o.url || "https://www.openstreetmap.org";
o.auto = o.auto || false;
o.singlepage = o.singlepage || false;
o.loading = o.loading || function() {
};
o.done = o.done || function() {
};
return oauth2.preauth(o);
};
var token;
if (import_store.default.enabled) {
token = function(x, y) {
if (arguments.length === 1)
return import_store.default.get(o.url + x);
else if (arguments.length === 2)
return import_store.default.set(o.url + x, y);
};
} else {
var storage = {};
token = function(x, y) {
if (arguments.length === 1)
return storage[o.url + x];
else if (arguments.length === 2)
return storage[o.url + x] = y;
};
}
oauth2.options(o);
return oauth2;
}
function utilQsString2(obj) {
return Object.keys(obj).sort().map(function(key) {
return encodeURIComponent(key) + "=" + encodeURIComponent(obj[key]);
}).join("&");
}
function utilStringQs2(str2) {
var i2 = 0;
while (i2 < str2.length && (str2[i2] === "?" || str2[i2] === "#"))
i2++;
str2 = str2.slice(i2);
return str2.split("&").reduce(function(obj, pair2) {
var parts = pair2.split("=");
if (parts.length === 2) {
obj[parts[0]] = decodeURIComponent(parts[1]);
}
return obj;
}, {});
}
// modules/services/osm.js
var import_rbush9 = __toESM(require_rbush_min());
var tiler5 = utilTiler();
var dispatch7 = dispatch_default("apiStatusChange", "authLoading", "authDone", "change", "loading", "loaded", "loadedNotes");
var urlroot = "https://www.openstreetmap.org";
var redirectPath = window.location.origin + window.location.pathname;
var oauth = osmAuth({
url: urlroot,
client_id: "0tmNTmd0Jo1dQp4AUmMBLtGiD9YpMuXzHefitcuVStc",
client_secret: "BTlNrNxIPitHdL4sP2clHw5KLoee9aKkA7dQbc0Bj7Q",
scope: "read_prefs write_prefs write_api read_gpx write_notes",
redirect_uri: redirectPath + "land.html",
loading: authLoading,
done: authDone
});
var _imageryBlocklists = [/.*\.google(apis)?\..*\/(vt|kh)[\?\/].*([xyz]=.*){3}.*/];
var _tileCache = { toLoad: {}, loaded: {}, inflight: {}, seen: {}, rtree: new import_rbush9.default() };
var _noteCache = { toLoad: {}, loaded: {}, inflight: {}, inflightPost: {}, note: {}, closed: {}, rtree: new import_rbush9.default() };
var _userCache = { toLoad: {}, user: {} };
var _cachedApiStatus;
var _changeset = {};
var _deferred = /* @__PURE__ */ new Set();
var _connectionID = 1;
var _tileZoom4 = 16;
var _noteZoom = 12;
var _rateLimitError;
var _userChangesets;
var _userDetails;
var _off;
var _maxWayNodes = 2e3;
function authLoading() {
dispatch7.call("authLoading");
}
function authDone() {
dispatch7.call("authDone");
}
function abortRequest5(controllerOrXHR) {
if (controllerOrXHR) {
controllerOrXHR.abort();
}
}
function hasInflightRequests(cache) {
return Object.keys(cache.inflight).length;
}
function abortUnwantedRequests4(cache, visibleTiles) {
Object.keys(cache.inflight).forEach(function(k) {
if (cache.toLoad[k])
return;
if (visibleTiles.find(function(tile) {
return k === tile.id;
}))
return;
abortRequest5(cache.inflight[k]);
delete cache.inflight[k];
});
}
function getLoc(attrs) {
var lon = attrs.lon && attrs.lon.value;
var lat = attrs.lat && attrs.lat.value;
return [parseFloat(lon), parseFloat(lat)];
}
function getNodes(obj) {
var elems = obj.getElementsByTagName("nd");
var nodes = new Array(elems.length);
for (var i2 = 0, l = elems.length; i2 < l; i2++) {
nodes[i2] = "n" + elems[i2].attributes.ref.value;
}
return nodes;
}
function getNodesJSON(obj) {
var elems = obj.nodes;
var nodes = new Array(elems.length);
for (var i2 = 0, l = elems.length; i2 < l; i2++) {
nodes[i2] = "n" + elems[i2];
}
return nodes;
}
function getTags(obj) {
var elems = obj.getElementsByTagName("tag");
var tags = {};
for (var i2 = 0, l = elems.length; i2 < l; i2++) {
var attrs = elems[i2].attributes;
tags[attrs.k.value] = attrs.v.value;
}
return tags;
}
function getMembers(obj) {
var elems = obj.getElementsByTagName("member");
var members = new Array(elems.length);
for (var i2 = 0, l = elems.length; i2 < l; i2++) {
var attrs = elems[i2].attributes;
members[i2] = {
id: attrs.type.value[0] + attrs.ref.value,
type: attrs.type.value,
role: attrs.role.value
};
}
return members;
}
function getMembersJSON(obj) {
var elems = obj.members;
var members = new Array(elems.length);
for (var i2 = 0, l = elems.length; i2 < l; i2++) {
var attrs = elems[i2];
members[i2] = {
id: attrs.type[0] + attrs.ref,
type: attrs.type,
role: attrs.role
};
}
return members;
}
function getVisible(attrs) {
return !attrs.visible || attrs.visible.value !== "false";
}
function parseComments(comments) {
var parsedComments = [];
for (var i2 = 0; i2 < comments.length; i2++) {
var comment = comments[i2];
if (comment.nodeName === "comment") {
var childNodes = comment.childNodes;
var parsedComment = {};
for (var j2 = 0; j2 < childNodes.length; j2++) {
var node = childNodes[j2];
var nodeName = node.nodeName;
if (nodeName === "#text")
continue;
parsedComment[nodeName] = node.textContent;
if (nodeName === "uid") {
var uid = node.textContent;
if (uid && !_userCache.user[uid]) {
_userCache.toLoad[uid] = true;
}
}
}
if (parsedComment) {
parsedComments.push(parsedComment);
}
}
}
return parsedComments;
}
function encodeNoteRtree(note) {
return {
minX: note.loc[0],
minY: note.loc[1],
maxX: note.loc[0],
maxY: note.loc[1],
data: note
};
}
var jsonparsers = {
node: function nodeData(obj, uid) {
return new osmNode({
id: uid,
visible: typeof obj.visible === "boolean" ? obj.visible : true,
version: obj.version && obj.version.toString(),
changeset: obj.changeset && obj.changeset.toString(),
timestamp: obj.timestamp,
user: obj.user,
uid: obj.uid && obj.uid.toString(),
loc: [parseFloat(obj.lon), parseFloat(obj.lat)],
tags: obj.tags
});
},
way: function wayData(obj, uid) {
return new osmWay({
id: uid,
visible: typeof obj.visible === "boolean" ? obj.visible : true,
version: obj.version && obj.version.toString(),
changeset: obj.changeset && obj.changeset.toString(),
timestamp: obj.timestamp,
user: obj.user,
uid: obj.uid && obj.uid.toString(),
tags: obj.tags,
nodes: getNodesJSON(obj)
});
},
relation: function relationData(obj, uid) {
return new osmRelation({
id: uid,
visible: typeof obj.visible === "boolean" ? obj.visible : true,
version: obj.version && obj.version.toString(),
changeset: obj.changeset && obj.changeset.toString(),
timestamp: obj.timestamp,
user: obj.user,
uid: obj.uid && obj.uid.toString(),
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"
};
}
};
function parseJSON(payload, callback, options2) {
options2 = Object.assign({ skipSeen: true }, options2);
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 });
var children2 = json.elements;
var handle = window.requestIdleCallback(function() {
_deferred.delete(handle);
var results = [];
var result;
for (var i2 = 0; i2 < children2.length; i2++) {
result = parseChild(children2[i2]);
if (result)
results.push(result);
}
callback(null, results);
});
_deferred.add(handle);
function parseChild(child) {
var parser3 = jsonparsers[child.type];
if (!parser3)
return null;
var uid;
uid = osmEntity.id.fromOSM(child.type, child.id);
if (options2.skipSeen) {
if (_tileCache.seen[uid])
return null;
_tileCache.seen[uid] = true;
}
return parser3(child, uid);
}
}
function parseUserJSON(payload, callback, options2) {
options2 = Object.assign({ skipSeen: true }, options2);
if (!payload) {
return callback({ message: "No JSON", status: -1 });
}
var json = payload;
if (typeof json !== "object")
json = JSON.parse(payload);
if (!json.users && !json.user)
return callback({ message: "No JSON", status: -1 });
var objs = json.users || [json];
var handle = window.requestIdleCallback(function() {
_deferred.delete(handle);
var results = [];
var result;
for (var i2 = 0; i2 < objs.length; i2++) {
result = parseObj(objs[i2]);
if (result)
results.push(result);
}
callback(null, results);
});
_deferred.add(handle);
function parseObj(obj) {
var uid = obj.user.id && obj.user.id.toString();
if (options2.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 nodeData2(obj, uid) {
var attrs = obj.attributes;
return new osmNode({
id: uid,
visible: getVisible(attrs),
version: attrs.version.value,
changeset: attrs.changeset && attrs.changeset.value,
timestamp: attrs.timestamp && attrs.timestamp.value,
user: attrs.user && attrs.user.value,
uid: attrs.uid && attrs.uid.value,
loc: getLoc(attrs),
tags: getTags(obj)
});
},
way: function wayData2(obj, uid) {
var attrs = obj.attributes;
return new osmWay({
id: uid,
visible: getVisible(attrs),
version: attrs.version.value,
changeset: attrs.changeset && attrs.changeset.value,
timestamp: attrs.timestamp && attrs.timestamp.value,
user: attrs.user && attrs.user.value,
uid: attrs.uid && attrs.uid.value,
tags: getTags(obj),
nodes: getNodes(obj)
});
},
relation: function relationData2(obj, uid) {
var attrs = obj.attributes;
return new osmRelation({
id: uid,
visible: getVisible(attrs),
version: attrs.version.value,
changeset: attrs.changeset && attrs.changeset.value,
timestamp: attrs.timestamp && attrs.timestamp.value,
user: attrs.user && attrs.user.value,
uid: attrs.uid && attrs.uid.value,
tags: getTags(obj),
members: getMembers(obj)
});
},
note: function parseNote(obj, uid) {
var attrs = obj.attributes;
var childNodes = obj.childNodes;
var props = {};
props.id = uid;
props.loc = getLoc(attrs);
var coincident = false;
var epsilon3 = 1e-5;
do {
if (coincident) {
props.loc = geoVecAdd(props.loc, [epsilon3, epsilon3]);
}
var bbox = geoExtent(props.loc).bbox();
coincident = _noteCache.rtree.search(bbox).length;
} while (coincident);
for (var i2 = 0; i2 < childNodes.length; i2++) {
var node = childNodes[i2];
var nodeName = node.nodeName;
if (nodeName === "#text")
continue;
if (nodeName === "comments") {
props[nodeName] = parseComments(node.childNodes);
} else {
props[nodeName] = node.textContent;
}
}
var note = new osmNote(props);
var item = encodeNoteRtree(note);
_noteCache.note[note.id] = note;
_noteCache.rtree.insert(item);
return note;
},
user: function parseUser2(obj, uid) {
var attrs = obj.attributes;
var user = {
id: uid,
display_name: attrs.display_name && attrs.display_name.value,
account_created: attrs.account_created && attrs.account_created.value,
changesets_count: "0",
active_blocks: "0"
};
var img = obj.getElementsByTagName("img");
if (img && img[0] && img[0].getAttribute("href")) {
user.image_url = img[0].getAttribute("href");
}
var changesets = obj.getElementsByTagName("changesets");
if (changesets && changesets[0] && changesets[0].getAttribute("count")) {
user.changesets_count = changesets[0].getAttribute("count");
}
var blocks = obj.getElementsByTagName("blocks");
if (blocks && blocks[0]) {
var received = blocks[0].getElementsByTagName("received");
if (received && received[0] && received[0].getAttribute("active")) {
user.active_blocks = received[0].getAttribute("active");
}
}
_userCache.user[uid] = user;
delete _userCache.toLoad[uid];
return user;
}
};
function parseXML(xml, callback, options2) {
options2 = Object.assign({ skipSeen: true }, options2);
if (!xml || !xml.childNodes) {
return callback({ message: "No XML", status: -1 });
}
var root3 = xml.childNodes[0];
var children2 = root3.childNodes;
var handle = window.requestIdleCallback(function() {
_deferred.delete(handle);
var results = [];
var result;
for (var i2 = 0; i2 < children2.length; i2++) {
result = parseChild(children2[i2]);
if (result)
results.push(result);
}
callback(null, results);
});
_deferred.add(handle);
function parseChild(child) {
var parser3 = parsers[child.nodeName];
if (!parser3)
return null;
var uid;
if (child.nodeName === "user") {
uid = child.attributes.id.value;
if (options2.skipSeen && _userCache.user[uid]) {
delete _userCache.toLoad[uid];
return null;
}
} else if (child.nodeName === "note") {
uid = child.getElementsByTagName("id")[0].textContent;
} else {
uid = osmEntity.id.fromOSM(child.nodeName, child.attributes.id.value);
if (options2.skipSeen) {
if (_tileCache.seen[uid])
return null;
_tileCache.seen[uid] = true;
}
}
return parser3(child, uid);
}
}
function updateRtree4(item, replace) {
_noteCache.rtree.remove(item, function isEql(a, b) {
return a.data.id === b.data.id;
});
if (replace) {
_noteCache.rtree.insert(item);
}
}
function wrapcb(thisArg, callback, cid) {
return function(err, result) {
if (err) {
if (err.status === 400 || err.status === 401 || err.status === 403) {
thisArg.logout();
}
return callback.call(thisArg, err);
} else if (thisArg.getConnectionId() !== cid) {
return callback.call(thisArg, { message: "Connection Switched", status: -1 });
} else {
return callback.call(thisArg, err, result);
}
};
}
var osm_default = {
init: function() {
utilRebind(this, dispatch7, "on");
},
reset: function() {
Array.from(_deferred).forEach(function(handle) {
window.cancelIdleCallback(handle);
_deferred.delete(handle);
});
_connectionID++;
_userChangesets = void 0;
_userDetails = void 0;
_rateLimitError = void 0;
Object.values(_tileCache.inflight).forEach(abortRequest5);
Object.values(_noteCache.inflight).forEach(abortRequest5);
Object.values(_noteCache.inflightPost).forEach(abortRequest5);
if (_changeset.inflight)
abortRequest5(_changeset.inflight);
_tileCache = { toLoad: {}, loaded: {}, inflight: {}, seen: {}, rtree: new import_rbush9.default() };
_noteCache = { toLoad: {}, loaded: {}, inflight: {}, inflightPost: {}, note: {}, closed: {}, rtree: new import_rbush9.default() };
_userCache = { toLoad: {}, user: {} };
_cachedApiStatus = void 0;
_changeset = {};
return this;
},
getConnectionId: function() {
return _connectionID;
},
getUrlRoot: function() {
return urlroot;
},
changesetURL: function(changesetID) {
return urlroot + "/changeset/" + changesetID;
},
changesetsURL: function(center, zoom) {
var precision2 = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2));
return urlroot + "/history#map=" + Math.floor(zoom) + "/" + center[1].toFixed(precision2) + "/" + center[0].toFixed(precision2);
},
entityURL: function(entity) {
return urlroot + "/" + entity.type + "/" + entity.osmId();
},
historyURL: function(entity) {
return urlroot + "/" + entity.type + "/" + entity.osmId() + "/history";
},
userURL: function(username) {
return urlroot + "/user/" + encodeURIComponent(username);
},
noteURL: function(note) {
return urlroot + "/note/" + note.id;
},
noteReportURL: function(note) {
return urlroot + "/reports/new?reportable_type=Note&reportable_id=" + note.id;
},
loadFromAPI: function(path, callback, options2) {
options2 = Object.assign({ skipSeen: true }, options2);
var that = this;
var cid = _connectionID;
function done(err, payload) {
if (that.getConnectionId() !== cid) {
if (callback)
callback({ message: "Connection Switched", status: -1 });
return;
}
var isAuthenticated = that.authenticated();
if (isAuthenticated && err && err.status && (err.status === 400 || err.status === 401 || err.status === 403)) {
that.logout();
that.loadFromAPI(path, callback, options2);
} else {
if (!isAuthenticated && !_rateLimitError && err && err.status && (err.status === 509 || err.status === 429)) {
_rateLimitError = err;
dispatch7.call("change");
that.reloadApiStatus();
} else if (err && _cachedApiStatus === "online" || !err && _cachedApiStatus !== "online") {
that.reloadApiStatus();
}
if (callback) {
if (err) {
return callback(err);
} else {
if (path.indexOf(".json") !== -1) {
return parseJSON(payload, callback, options2);
} else {
return parseXML(payload, callback, options2);
}
}
}
}
}
if (this.authenticated()) {
return oauth.xhr({ method: "GET", path }, done);
} else {
var url = urlroot + path;
var controller = new AbortController();
var fn;
if (path.indexOf(".json") !== -1) {
fn = json_default;
} else {
fn = xml_default;
}
fn(url, { signal: controller.signal }).then(function(data) {
done(null, data);
}).catch(function(err) {
if (err.name === "AbortError")
return;
var match = err.message.match(/^\d{3}/);
if (match) {
done({ status: +match[0], statusText: err.message });
} else {
done(err.message);
}
});
return controller;
}
},
loadEntity: function(id2, callback) {
var type3 = osmEntity.id.type(id2);
var osmID = osmEntity.id.toOSM(id2);
var options2 = { skipSeen: false };
this.loadFromAPI("/api/0.6/" + type3 + "/" + osmID + (type3 !== "node" ? "/full" : "") + ".json", function(err, entities) {
if (callback)
callback(err, { data: entities });
}, options2);
},
loadEntityVersion: function(id2, version2, callback) {
var type3 = osmEntity.id.type(id2);
var osmID = osmEntity.id.toOSM(id2);
var options2 = { skipSeen: false };
this.loadFromAPI("/api/0.6/" + type3 + "/" + osmID + "/" + version2 + ".json", function(err, entities) {
if (callback)
callback(err, { data: entities });
}, options2);
},
loadEntityRelations: function(id2, callback) {
var type3 = osmEntity.id.type(id2);
var osmID = osmEntity.id.toOSM(id2);
var options2 = { skipSeen: false };
this.loadFromAPI("/api/0.6/" + type3 + "/" + osmID + "/relations.json", function(err, entities) {
if (callback)
callback(err, { data: entities });
}, options2);
},
loadMultiple: function(ids, callback) {
var that = this;
var groups = utilArrayGroupBy(utilArrayUniq(ids), osmEntity.id.type);
Object.keys(groups).forEach(function(k) {
var type3 = k + "s";
var osmIDs = groups[k].map(function(id2) {
return osmEntity.id.toOSM(id2);
});
var options2 = { skipSeen: false };
utilArrayChunk(osmIDs, 150).forEach(function(arr) {
that.loadFromAPI("/api/0.6/" + type3 + ".json?" + type3 + "=" + arr.join(), function(err, entities) {
if (callback)
callback(err, { data: entities });
}, options2);
});
});
},
putChangeset: function(changeset, changes, callback) {
var cid = _connectionID;
if (_changeset.inflight) {
return callback({ message: "Changeset already inflight", status: -2 }, changeset);
} else if (_changeset.open) {
return createdChangeset.call(this, null, _changeset.open);
} else {
var options2 = {
method: "PUT",
path: "/api/0.6/changeset/create",
headers: { "Content-Type": "text/xml" },
content: JXON.stringify(changeset.asJXON())
};
_changeset.inflight = oauth.xhr(options2, wrapcb(this, createdChangeset, cid));
}
function createdChangeset(err, changesetID) {
_changeset.inflight = null;
if (err) {
return callback(err, changeset);
}
_changeset.open = changesetID;
changeset = changeset.update({ id: changesetID });
var options3 = {
method: "POST",
path: "/api/0.6/changeset/" + changesetID + "/upload",
headers: { "Content-Type": "text/xml" },
content: JXON.stringify(changeset.osmChangeJXON(changes))
};
_changeset.inflight = oauth.xhr(options3, wrapcb(this, uploadedChangeset, cid));
}
function uploadedChangeset(err) {
_changeset.inflight = null;
if (err)
return callback(err, changeset);
window.setTimeout(function() {
callback(null, changeset);
}, 2500);
_changeset.open = null;
if (this.getConnectionId() === cid) {
oauth.xhr({
method: "PUT",
path: "/api/0.6/changeset/" + changeset.id + "/close",
headers: { "Content-Type": "text/xml" }
}, function() {
return true;
});
}
}
},
loadUsers: function(uids, callback) {
var toLoad = [];
var cached = [];
utilArrayUniq(uids).forEach(function(uid) {
if (_userCache.user[uid]) {
delete _userCache.toLoad[uid];
cached.push(_userCache.user[uid]);
} else {
toLoad.push(uid);
}
});
if (cached.length || !this.authenticated()) {
callback(void 0, cached);
if (!this.authenticated())
return;
}
utilArrayChunk(toLoad, 150).forEach(function(arr) {
oauth.xhr({ method: "GET", path: "/api/0.6/users.json?users=" + arr.join() }, wrapcb(this, done, _connectionID));
}.bind(this));
function done(err, payload) {
if (err)
return callback(err);
var options2 = { skipSeen: true };
return parseUserJSON(payload, function(err2, results) {
if (err2)
return callback(err2);
return callback(void 0, results);
}, options2);
}
},
loadUser: function(uid, callback) {
if (_userCache.user[uid] || !this.authenticated()) {
delete _userCache.toLoad[uid];
return callback(void 0, _userCache.user[uid]);
}
oauth.xhr({ method: "GET", path: "/api/0.6/user/" + uid + ".json" }, wrapcb(this, done, _connectionID));
function done(err, payload) {
if (err)
return callback(err);
var options2 = { skipSeen: true };
return parseUserJSON(payload, function(err2, results) {
if (err2)
return callback(err2);
return callback(void 0, results[0]);
}, options2);
}
},
userDetails: function(callback) {
if (_userDetails) {
return callback(void 0, _userDetails);
}
oauth.xhr({ method: "GET", path: "/api/0.6/user/details.json" }, wrapcb(this, done, _connectionID));
function done(err, payload) {
if (err)
return callback(err);
var options2 = { skipSeen: false };
return parseUserJSON(payload, function(err2, results) {
if (err2)
return callback(err2);
_userDetails = results[0];
return callback(void 0, _userDetails);
}, options2);
}
},
userChangesets: function(callback) {
if (_userChangesets) {
return callback(void 0, _userChangesets);
}
this.userDetails(wrapcb(this, gotDetails, _connectionID));
function gotDetails(err, user) {
if (err) {
return callback(err);
}
oauth.xhr({ method: "GET", path: "/api/0.6/changesets?user=" + user.id }, wrapcb(this, done, _connectionID));
}
function done(err, xml) {
if (err) {
return callback(err);
}
_userChangesets = Array.prototype.map.call(xml.getElementsByTagName("changeset"), function(changeset) {
return { tags: getTags(changeset) };
}).filter(function(changeset) {
var comment = changeset.tags.comment;
return comment && comment !== "";
});
return callback(void 0, _userChangesets);
}
},
status: function(callback) {
var url = urlroot + "/api/capabilities";
var errback = wrapcb(this, done, _connectionID);
xml_default(url).then(function(data) {
errback(null, data);
}).catch(function(err) {
errback(err.message);
});
function done(err, xml) {
if (err) {
return callback(err, null);
}
var elements = xml.getElementsByTagName("blacklist");
var regexes = [];
for (var i2 = 0; i2 < elements.length; i2++) {
var regexString = elements[i2].getAttribute("regex");
if (regexString) {
try {
var regex = new RegExp(regexString);
regexes.push(regex);
} catch (e) {
}
}
}
if (regexes.length) {
_imageryBlocklists = regexes;
}
if (_rateLimitError) {
return callback(_rateLimitError, "rateLimited");
} else {
var waynodes = xml.getElementsByTagName("waynodes");
var maxWayNodes = waynodes.length && parseInt(waynodes[0].getAttribute("maximum"), 10);
if (maxWayNodes && isFinite(maxWayNodes))
_maxWayNodes = maxWayNodes;
var apiStatus = xml.getElementsByTagName("status");
var val = apiStatus[0].getAttribute("api");
return callback(void 0, val);
}
}
},
reloadApiStatus: function() {
if (!this.throttledReloadApiStatus) {
var that = this;
this.throttledReloadApiStatus = throttle_default(function() {
that.status(function(err, status) {
if (status !== _cachedApiStatus) {
_cachedApiStatus = status;
dispatch7.call("apiStatusChange", that, err, status);
}
});
}, 500);
}
this.throttledReloadApiStatus();
},
maxWayNodes: function() {
return _maxWayNodes;
},
loadTiles: function(projection2, callback) {
if (_off)
return;
var tiles = tiler5.zoomExtent([_tileZoom4, _tileZoom4]).getTiles(projection2);
var hadRequests = hasInflightRequests(_tileCache);
abortUnwantedRequests4(_tileCache, tiles);
if (hadRequests && !hasInflightRequests(_tileCache)) {
dispatch7.call("loaded");
}
tiles.forEach(function(tile) {
this.loadTile(tile, callback);
}, this);
},
loadTile: function(tile, callback) {
if (_off)
return;
if (_tileCache.loaded[tile.id] || _tileCache.inflight[tile.id])
return;
if (!hasInflightRequests(_tileCache)) {
dispatch7.call("loading");
}
var path = "/api/0.6/map.json?bbox=";
var options2 = { skipSeen: true };
_tileCache.inflight[tile.id] = this.loadFromAPI(path + tile.extent.toParam(), tileCallback, options2);
function tileCallback(err, parsed) {
delete _tileCache.inflight[tile.id];
if (!err) {
delete _tileCache.toLoad[tile.id];
_tileCache.loaded[tile.id] = true;
var bbox = tile.extent.bbox();
bbox.id = tile.id;
_tileCache.rtree.insert(bbox);
}
if (callback) {
callback(err, Object.assign({ data: parsed }, tile));
}
if (!hasInflightRequests(_tileCache)) {
dispatch7.call("loaded");
}
}
},
isDataLoaded: function(loc) {
var bbox = { minX: loc[0], minY: loc[1], maxX: loc[0], maxY: loc[1] };
return _tileCache.rtree.collides(bbox);
},
loadTileAtLoc: function(loc, callback) {
if (Object.keys(_tileCache.toLoad).length > 50)
return;
var k = geoZoomToScale(_tileZoom4 + 1);
var offset = geoRawMercator().scale(k)(loc);
var projection2 = geoRawMercator().transform({ k, x: -offset[0], y: -offset[1] });
var tiles = tiler5.zoomExtent([_tileZoom4, _tileZoom4]).getTiles(projection2);
tiles.forEach(function(tile) {
if (_tileCache.toLoad[tile.id] || _tileCache.loaded[tile.id] || _tileCache.inflight[tile.id])
return;
_tileCache.toLoad[tile.id] = true;
this.loadTile(tile, callback);
}, this);
},
loadNotes: function(projection2, noteOptions) {
noteOptions = Object.assign({ limit: 1e4, closed: 7 }, noteOptions);
if (_off)
return;
var that = this;
var path = "/api/0.6/notes?limit=" + noteOptions.limit + "&closed=" + noteOptions.closed + "&bbox=";
var throttleLoadUsers = throttle_default(function() {
var uids = Object.keys(_userCache.toLoad);
if (!uids.length)
return;
that.loadUsers(uids, function() {
});
}, 750);
var tiles = tiler5.zoomExtent([_noteZoom, _noteZoom]).getTiles(projection2);
abortUnwantedRequests4(_noteCache, tiles);
tiles.forEach(function(tile) {
if (_noteCache.loaded[tile.id] || _noteCache.inflight[tile.id])
return;
var options2 = { skipSeen: false };
_noteCache.inflight[tile.id] = that.loadFromAPI(path + tile.extent.toParam(), function(err) {
delete _noteCache.inflight[tile.id];
if (!err) {
_noteCache.loaded[tile.id] = true;
}
throttleLoadUsers();
dispatch7.call("loadedNotes");
}, options2);
});
},
postNoteCreate: function(note, callback) {
if (!this.authenticated()) {
return callback({ message: "Not Authenticated", status: -3 }, note);
}
if (_noteCache.inflightPost[note.id]) {
return callback({ message: "Note update already inflight", status: -2 }, note);
}
if (!note.loc[0] || !note.loc[1] || !note.newComment)
return;
var comment = note.newComment;
if (note.newCategory && note.newCategory !== "None") {
comment += " #" + note.newCategory;
}
var path = "/api/0.6/notes?" + utilQsString({ lon: note.loc[0], lat: note.loc[1], text: comment });
_noteCache.inflightPost[note.id] = oauth.xhr({ method: "POST", path }, wrapcb(this, done, _connectionID));
function done(err, xml) {
delete _noteCache.inflightPost[note.id];
if (err) {
return callback(err);
}
this.removeNote(note);
var options2 = { skipSeen: false };
return parseXML(xml, function(err2, results) {
if (err2) {
return callback(err2);
} else {
return callback(void 0, results[0]);
}
}, options2);
}
},
postNoteUpdate: function(note, newStatus, callback) {
if (!this.authenticated()) {
return callback({ message: "Not Authenticated", status: -3 }, note);
}
if (_noteCache.inflightPost[note.id]) {
return callback({ message: "Note update already inflight", status: -2 }, note);
}
var action;
if (note.status !== "closed" && newStatus === "closed") {
action = "close";
} else if (note.status !== "open" && newStatus === "open") {
action = "reopen";
} else {
action = "comment";
if (!note.newComment)
return;
}
var path = "/api/0.6/notes/" + note.id + "/" + action;
if (note.newComment) {
path += "?" + utilQsString({ text: note.newComment });
}
_noteCache.inflightPost[note.id] = oauth.xhr({ method: "POST", path }, wrapcb(this, done, _connectionID));
function done(err, xml) {
delete _noteCache.inflightPost[note.id];
if (err) {
return callback(err);
}
this.removeNote(note);
if (action === "close") {
_noteCache.closed[note.id] = true;
} else if (action === "reopen") {
delete _noteCache.closed[note.id];
}
var options2 = { skipSeen: false };
return parseXML(xml, function(err2, results) {
if (err2) {
return callback(err2);
} else {
return callback(void 0, results[0]);
}
}, options2);
}
},
switch: function(newOptions) {
urlroot = newOptions.url;
var oldOptions = utilObjectOmit(oauth.options(), "access_token");
oauth.options(Object.assign(oldOptions, newOptions));
this.reset();
this.userChangesets(function() {
});
dispatch7.call("change");
return this;
},
toggle: function(val) {
_off = !val;
return this;
},
isChangesetInflight: function() {
return !!_changeset.inflight;
},
caches: function(obj) {
function cloneCache(source) {
var target = {};
Object.keys(source).forEach(function(k) {
if (k === "rtree") {
target.rtree = new import_rbush9.default().fromJSON(source.rtree.toJSON());
} else if (k === "note") {
target.note = {};
Object.keys(source.note).forEach(function(id2) {
target.note[id2] = osmNote(source.note[id2]);
});
} else {
target[k] = JSON.parse(JSON.stringify(source[k]));
}
});
return target;
}
if (!arguments.length) {
return {
tile: cloneCache(_tileCache),
note: cloneCache(_noteCache),
user: cloneCache(_userCache)
};
}
if (obj === "get") {
return {
tile: _tileCache,
note: _noteCache,
user: _userCache
};
}
if (obj.tile) {
_tileCache = obj.tile;
_tileCache.inflight = {};
}
if (obj.note) {
_noteCache = obj.note;
_noteCache.inflight = {};
_noteCache.inflightPost = {};
}
if (obj.user) {
_userCache = obj.user;
}
return this;
},
logout: function() {
_userChangesets = void 0;
_userDetails = void 0;
oauth.logout();
dispatch7.call("change");
return this;
},
authenticated: function() {
return oauth.authenticated();
},
authenticate: function(callback) {
var that = this;
var cid = _connectionID;
_userChangesets = void 0;
_userDetails = void 0;
function done(err, res) {
if (err) {
if (callback)
callback(err);
return;
}
if (that.getConnectionId() !== cid) {
if (callback)
callback({ message: "Connection Switched", status: -1 });
return;
}
_rateLimitError = void 0;
dispatch7.call("change");
if (callback)
callback(err, res);
that.userChangesets(function() {
});
}
oauth.authenticate(done);
},
imageryBlocklists: function() {
return _imageryBlocklists;
},
tileZoom: function(val) {
if (!arguments.length)
return _tileZoom4;
_tileZoom4 = val;
return this;
},
notes: function(projection2) {
var viewport = projection2.clipExtent();
var min3 = [viewport[0][0], viewport[1][1]];
var max3 = [viewport[1][0], viewport[0][1]];
var bbox = geoExtent(projection2.invert(min3), projection2.invert(max3)).bbox();
return _noteCache.rtree.search(bbox).map(function(d) {
return d.data;
});
},
getNote: function(id2) {
return _noteCache.note[id2];
},
removeNote: function(note) {
if (!(note instanceof osmNote) || !note.id)
return;
delete _noteCache.note[note.id];
updateRtree4(encodeNoteRtree(note), false);
},
replaceNote: function(note) {
if (!(note instanceof osmNote) || !note.id)
return;
_noteCache.note[note.id] = note;
updateRtree4(encodeNoteRtree(note), true);
return note;
},
getClosedIDs: function() {
return Object.keys(_noteCache.closed).sort();
}
};
// modules/services/osm_wikibase.js
var apibase3 = "https://wiki.openstreetmap.org/w/api.php";
var _inflight2 = {};
var _wikibaseCache = {};
var _localeIDs = { en: false };
var debouncedRequest = debounce_default(request, 500, { leading: false });
function request(url, callback) {
if (_inflight2[url])
return;
var controller = new AbortController();
_inflight2[url] = controller;
json_default(url, { signal: controller.signal }).then(function(result) {
delete _inflight2[url];
if (callback)
callback(null, result);
}).catch(function(err) {
delete _inflight2[url];
if (err.name === "AbortError")
return;
if (callback)
callback(err.message);
});
}
var osm_wikibase_default = {
init: function() {
_inflight2 = {};
_wikibaseCache = {};
_localeIDs = {};
},
reset: function() {
Object.values(_inflight2).forEach(function(controller) {
controller.abort();
});
_inflight2 = {};
},
claimToValue: function(entity, property, langCode) {
if (!entity.claims[property])
return void 0;
var locale2 = _localeIDs[langCode];
var preferredPick, localePick;
entity.claims[property].forEach(function(stmt) {
if (!preferredPick && stmt.rank === "preferred") {
preferredPick = stmt;
}
if (locale2 && stmt.qualifiers && stmt.qualifiers.P26 && stmt.qualifiers.P26[0].datavalue.value.id === locale2) {
localePick = stmt;
}
});
var result = localePick || preferredPick;
if (result) {
var datavalue = result.mainsnak.datavalue;
return datavalue.type === "wikibase-entityid" ? datavalue.value.id : datavalue.value;
} else {
return void 0;
}
},
monolingualClaimToValueObj: function(entity, property) {
if (!entity || !entity.claims[property])
return void 0;
return entity.claims[property].reduce(function(acc, obj) {
var value = obj.mainsnak.datavalue.value;
acc[value.language] = value.text;
return acc;
}, {});
},
toSitelink: function(key, value) {
var result = value ? "Tag:" + key + "=" + value : "Key:" + key;
return result.replace(/_/g, " ").trim();
},
getEntity: function(params, callback) {
var doRequest = params.debounce ? debouncedRequest : request;
var that = this;
var titles = [];
var result = {};
var rtypeSitelink = params.key === "type" && params.value ? ("Relation:" + params.value).replace(/_/g, " ").trim() : false;
var keySitelink = params.key ? this.toSitelink(params.key) : false;
var tagSitelink = params.key && params.value ? this.toSitelink(params.key, params.value) : false;
var localeSitelink;
if (params.langCodes) {
params.langCodes.forEach(function(langCode) {
if (_localeIDs[langCode] === void 0) {
localeSitelink = ("Locale:" + langCode).replace(/_/g, " ").trim();
titles.push(localeSitelink);
}
});
}
if (rtypeSitelink) {
if (_wikibaseCache[rtypeSitelink]) {
result.rtype = _wikibaseCache[rtypeSitelink];
} else {
titles.push(rtypeSitelink);
}
}
if (keySitelink) {
if (_wikibaseCache[keySitelink]) {
result.key = _wikibaseCache[keySitelink];
} else {
titles.push(keySitelink);
}
}
if (tagSitelink) {
if (_wikibaseCache[tagSitelink]) {
result.tag = _wikibaseCache[tagSitelink];
} else {
titles.push(tagSitelink);
}
}
if (!titles.length) {
return callback(null, result);
}
var obj = {
action: "wbgetentities",
sites: "wiki",
titles: titles.join("|"),
languages: params.langCodes.join("|"),
languagefallback: 1,
origin: "*",
format: "json"
};
var url = apibase3 + "?" + utilQsString(obj);
doRequest(url, function(err, d) {
if (err) {
callback(err);
} else if (!d.success || d.error) {
callback(d.error.messages.map(function(v) {
return v.html["*"];
}).join("
"));
} else {
var localeID = false;
Object.values(d.entities).forEach(function(res) {
if (res.missing !== "") {
var title = res.sitelinks.wiki.title;
if (title === rtypeSitelink) {
_wikibaseCache[rtypeSitelink] = res;
result.rtype = res;
} else if (title === keySitelink) {
_wikibaseCache[keySitelink] = res;
result.key = res;
} else if (title === tagSitelink) {
_wikibaseCache[tagSitelink] = res;
result.tag = res;
} else if (title === localeSitelink) {
localeID = res.id;
} else {
console.log("Unexpected title " + title);
}
}
});
if (localeSitelink) {
that.addLocale(params.langCodes[0], localeID);
}
callback(null, result);
}
});
},
getDocs: function(params, callback) {
var that = this;
var langCodes = _mainLocalizer.localeCodes().map(function(code) {
return code.toLowerCase();
});
params.langCodes = langCodes;
this.getEntity(params, function(err, data) {
if (err) {
callback(err);
return;
}
var entity = data.rtype || data.tag || data.key;
if (!entity) {
callback("No entity");
return;
}
var i2;
var description2;
for (i2 in langCodes) {
let code2 = langCodes[i2];
if (entity.descriptions[code2] && entity.descriptions[code2].language === code2) {
description2 = entity.descriptions[code2];
break;
}
}
if (!description2 && Object.values(entity.descriptions).length)
description2 = Object.values(entity.descriptions)[0];
var result = {
title: entity.title,
description: description2 ? description2.value : "",
descriptionLocaleCode: description2 ? description2.language : "",
editURL: "https://wiki.openstreetmap.org/wiki/" + entity.title
};
if (entity.claims) {
var imageroot;
var image = that.claimToValue(entity, "P4", langCodes[0]);
if (image) {
imageroot = "https://commons.wikimedia.org/w/index.php";
} else {
image = that.claimToValue(entity, "P28", langCodes[0]);
if (image) {
imageroot = "https://wiki.openstreetmap.org/w/index.php";
}
}
if (imageroot && image) {
result.imageURL = imageroot + "?" + utilQsString({
title: "Special:Redirect/file/" + image,
width: 400
});
}
}
var rtypeWiki = that.monolingualClaimToValueObj(data.rtype, "P31");
var tagWiki = that.monolingualClaimToValueObj(data.tag, "P31");
var keyWiki = that.monolingualClaimToValueObj(data.key, "P31");
var wikis = [rtypeWiki, tagWiki, keyWiki];
for (i2 in wikis) {
var wiki = wikis[i2];
for (var j2 in langCodes) {
var code = langCodes[j2];
var referenceId = langCodes[0].split("-")[0] !== "en" && code.split("-")[0] === "en" ? "inspector.wiki_en_reference" : "inspector.wiki_reference";
var info = getWikiInfo(wiki, code, referenceId);
if (info) {
result.wiki = info;
break;
}
}
if (result.wiki)
break;
}
callback(null, result);
function getWikiInfo(wiki2, langCode, tKey) {
if (wiki2 && wiki2[langCode]) {
return {
title: wiki2[langCode],
text: tKey,
url: "https://wiki.openstreetmap.org/wiki/" + wiki2[langCode]
};
}
}
});
},
addLocale: function(langCode, qid) {
_localeIDs[langCode] = qid;
},
apibase: function(val) {
if (!arguments.length)
return apibase3;
apibase3 = val;
return this;
}
};
// modules/services/streetside.js
var import_rbush10 = __toESM(require_rbush_min());
// modules/util/jsonp_request.js
var jsonpCache = {};
window.jsonpCache = jsonpCache;
function jsonpRequest(url, callback) {
var request3 = {
abort: function() {
}
};
if (window.JSONP_FIX) {
if (window.JSONP_DELAY === 0) {
callback(window.JSONP_FIX);
} else {
var t = window.setTimeout(function() {
callback(window.JSONP_FIX);
}, window.JSONP_DELAY || 0);
request3.abort = function() {
window.clearTimeout(t);
};
}
return request3;
}
function rand() {
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
var c = "";
var i2 = -1;
while (++i2 < 15)
c += chars.charAt(Math.floor(Math.random() * 52));
return c;
}
function create2(url2) {
var e = url2.match(/callback=(\w+)/);
var c = e ? e[1] : rand();
jsonpCache[c] = function(data) {
if (jsonpCache[c]) {
callback(data);
}
finalize();
};
function finalize() {
delete jsonpCache[c];
script.remove();
}
request3.abort = finalize;
return "jsonpCache." + c;
}
var cb = create2(url);
var script = select_default2("head").append("script").attr("type", "text/javascript").attr("src", url.replace(/(\{|%7B)callback(\}|%7D)/, cb));
return request3;
}
// modules/services/streetside.js
var bubbleApi = "https://dev.virtualearth.net/mapcontrol/HumanScaleServices/GetBubbles.ashx?";
var streetsideImagesApi = "https://t.ssl.ak.tiles.virtualearth.net/tiles/";
var bubbleAppKey = "AuftgJsO0Xs8Ts4M1xZUQJQXJNsvmh3IV8DkNieCiy3tCwCUMq76-WpkrBtNAuEm";
var pannellumViewerCSS = "pannellum-streetside/pannellum.css";
var pannellumViewerJS = "pannellum-streetside/pannellum.js";
var maxResults2 = 2e3;
var tileZoom2 = 16.5;
var tiler6 = utilTiler().zoomExtent([tileZoom2, tileZoom2]).skipNullIsland(true);
var dispatch8 = dispatch_default("loadedImages", "viewerChanged");
var minHfov = 10;
var maxHfov = 90;
var defaultHfov = 45;
var _hires = false;
var _resolution = 512;
var _currScene = 0;
var _ssCache;
var _pannellumViewer;
var _sceneOptions = {
showFullscreenCtrl: false,
autoLoad: true,
compass: true,
yaw: 0,
minHfov,
maxHfov,
hfov: defaultHfov,
type: "cubemap",
cubeMap: []
};
var _loadViewerPromise3;
function abortRequest6(i2) {
i2.abort();
}
function localeTimestamp(s) {
if (!s)
return null;
const options2 = { day: "numeric", month: "short", year: "numeric" };
const d = new Date(s);
if (isNaN(d.getTime()))
return null;
return d.toLocaleString(_mainLocalizer.localeCode(), options2);
}
function loadTiles3(which, url, projection2, margin) {
const tiles = tiler6.margin(margin).getTiles(projection2);
const cache = _ssCache[which];
Object.keys(cache.inflight).forEach((k) => {
const wanted = tiles.find((tile) => k.indexOf(tile.id + ",") === 0);
if (!wanted) {
abortRequest6(cache.inflight[k]);
delete cache.inflight[k];
}
});
tiles.forEach((tile) => loadNextTilePage2(which, url, tile));
}
function loadNextTilePage2(which, url, tile) {
const cache = _ssCache[which];
const nextPage = cache.nextPage[tile.id] || 0;
const id2 = tile.id + "," + String(nextPage);
if (cache.loaded[id2] || cache.inflight[id2])
return;
cache.inflight[id2] = getBubbles(url, tile, (bubbles) => {
cache.loaded[id2] = true;
delete cache.inflight[id2];
if (!bubbles)
return;
bubbles.shift();
const features2 = bubbles.map((bubble) => {
if (cache.points[bubble.id])
return null;
const loc = [bubble.lo, bubble.la];
const d = {
loc,
key: bubble.id,
ca: bubble.he,
captured_at: bubble.cd,
captured_by: "microsoft",
pr: bubble.pr,
ne: bubble.ne,
pano: true,
sequenceKey: null
};
cache.points[bubble.id] = d;
if (bubble.pr === void 0) {
cache.leaders.push(bubble.id);
}
return {
minX: loc[0],
minY: loc[1],
maxX: loc[0],
maxY: loc[1],
data: d
};
}).filter(Boolean);
cache.rtree.load(features2);
connectSequences();
if (which === "bubbles") {
dispatch8.call("loadedImages");
}
});
}
function connectSequences() {
let cache = _ssCache.bubbles;
let keepLeaders = [];
for (let i2 = 0; i2 < cache.leaders.length; i2++) {
let bubble = cache.points[cache.leaders[i2]];
let seen = {};
let sequence = { key: bubble.key, bubbles: [] };
let complete = false;
do {
sequence.bubbles.push(bubble);
seen[bubble.key] = true;
if (bubble.ne === void 0) {
complete = true;
} else {
bubble = cache.points[bubble.ne];
}
} while (bubble && !seen[bubble.key] && !complete);
if (complete) {
_ssCache.sequences[sequence.key] = sequence;
for (let j2 = 0; j2 < sequence.bubbles.length; j2++) {
sequence.bubbles[j2].sequenceKey = sequence.key;
}
sequence.geojson = {
type: "LineString",
properties: {
captured_at: sequence.bubbles[0] ? sequence.bubbles[0].captured_at : null,
captured_by: sequence.bubbles[0] ? sequence.bubbles[0].captured_by : null,
key: sequence.key
},
coordinates: sequence.bubbles.map((d) => d.loc)
};
} else {
keepLeaders.push(cache.leaders[i2]);
}
}
cache.leaders = keepLeaders;
}
function getBubbles(url, tile, callback) {
let rect = tile.extent.rectangle();
let urlForRequest = url + utilQsString({
n: rect[3],
s: rect[1],
e: rect[2],
w: rect[0],
c: maxResults2,
appkey: bubbleAppKey,
jsCallback: "{callback}"
});
return jsonpRequest(urlForRequest, (data) => {
if (!data || data.error) {
callback(null);
} else {
callback(data);
}
});
}
function partitionViewport3(projection2) {
let z = geoScaleToZoom(projection2.scale());
let z2 = Math.ceil(z * 2) / 2 + 2.5;
let tiler8 = utilTiler().zoomExtent([z2, z2]);
return tiler8.getTiles(projection2).map((tile) => tile.extent);
}
function searchLimited3(limit, projection2, rtree) {
limit = limit || 5;
return partitionViewport3(projection2).reduce((result, extent) => {
let found = rtree.search(extent.bbox()).slice(0, limit).map((d) => d.data);
return found.length ? result.concat(found) : result;
}, []);
}
function loadImage(imgInfo) {
return new Promise((resolve) => {
let img = new Image();
img.onload = () => {
let canvas = document.getElementById("ideditor-canvas" + imgInfo.face);
let ctx = canvas.getContext("2d");
ctx.drawImage(img, imgInfo.x, imgInfo.y);
resolve({ imgInfo, status: "ok" });
};
img.onerror = () => {
resolve({ data: imgInfo, status: "error" });
};
img.setAttribute("crossorigin", "");
img.src = imgInfo.url;
});
}
function loadCanvas(imageGroup) {
return Promise.all(imageGroup.map(loadImage)).then((data) => {
let canvas = document.getElementById("ideditor-canvas" + data[0].imgInfo.face);
const which = { "01": 0, "02": 1, "03": 2, "10": 3, "11": 4, "12": 5 };
let face = data[0].imgInfo.face;
_sceneOptions.cubeMap[which[face]] = canvas.toDataURL("image/jpeg", 1);
return { status: "loadCanvas for face " + data[0].imgInfo.face + "ok" };
});
}
function loadFaces(faceGroup) {
return Promise.all(faceGroup.map(loadCanvas)).then(() => {
return { status: "loadFaces done" };
});
}
function setupCanvas(selection2, reset) {
if (reset) {
selection2.selectAll("#ideditor-stitcher-canvases").remove();
}
selection2.selectAll("#ideditor-stitcher-canvases").data([0]).enter().append("div").attr("id", "ideditor-stitcher-canvases").attr("display", "none").selectAll("canvas").data(["canvas01", "canvas02", "canvas03", "canvas10", "canvas11", "canvas12"]).enter().append("canvas").attr("id", (d) => "ideditor-" + d).attr("width", _resolution).attr("height", _resolution);
}
function qkToXY(qk) {
let x = 0;
let y = 0;
let scale = 256;
for (let i2 = qk.length; i2 > 0; i2--) {
const key = qk[i2 - 1];
x += +(key === "1" || key === "3") * scale;
y += +(key === "2" || key === "3") * scale;
scale *= 2;
}
return [x, y];
}
function getQuadKeys() {
let dim = _resolution / 256;
let quadKeys;
if (dim === 16) {
quadKeys = [
"0000",
"0001",
"0010",
"0011",
"0100",
"0101",
"0110",
"0111",
"1000",
"1001",
"1010",
"1011",
"1100",
"1101",
"1110",
"1111",
"0002",
"0003",
"0012",
"0013",
"0102",
"0103",
"0112",
"0113",
"1002",
"1003",
"1012",
"1013",
"1102",
"1103",
"1112",
"1113",
"0020",
"0021",
"0030",
"0031",
"0120",
"0121",
"0130",
"0131",
"1020",
"1021",
"1030",
"1031",
"1120",
"1121",
"1130",
"1131",
"0022",
"0023",
"0032",
"0033",
"0122",
"0123",
"0132",
"0133",
"1022",
"1023",
"1032",
"1033",
"1122",
"1123",
"1132",
"1133",
"0200",
"0201",
"0210",
"0211",
"0300",
"0301",
"0310",
"0311",
"1200",
"1201",
"1210",
"1211",
"1300",
"1301",
"1310",
"1311",
"0202",
"0203",
"0212",
"0213",
"0302",
"0303",
"0312",
"0313",
"1202",
"1203",
"1212",
"1213",
"1302",
"1303",
"1312",
"1313",
"0220",
"0221",
"0230",
"0231",
"0320",
"0321",
"0330",
"0331",
"1220",
"1221",
"1230",
"1231",
"1320",
"1321",
"1330",
"1331",
"0222",
"0223",
"0232",
"0233",
"0322",
"0323",
"0332",
"0333",
"1222",
"1223",
"1232",
"1233",
"1322",
"1323",
"1332",
"1333",
"2000",
"2001",
"2010",
"2011",
"2100",
"2101",
"2110",
"2111",
"3000",
"3001",
"3010",
"3011",
"3100",
"3101",
"3110",
"3111",
"2002",
"2003",
"2012",
"2013",
"2102",
"2103",
"2112",
"2113",
"3002",
"3003",
"3012",
"3013",
"3102",
"3103",
"3112",
"3113",
"2020",
"2021",
"2030",
"2031",
"2120",
"2121",
"2130",
"2131",
"3020",
"3021",
"3030",
"3031",
"3120",
"3121",
"3130",
"3131",
"2022",
"2023",
"2032",
"2033",
"2122",
"2123",
"2132",
"2133",
"3022",
"3023",
"3032",
"3033",
"3122",
"3123",
"3132",
"3133",
"2200",
"2201",
"2210",
"2211",
"2300",
"2301",
"2310",
"2311",
"3200",
"3201",
"3210",
"3211",
"3300",
"3301",
"3310",
"3311",
"2202",
"2203",
"2212",
"2213",
"2302",
"2303",
"2312",
"2313",
"3202",
"3203",
"3212",
"3213",
"3302",
"3303",
"3312",
"3313",
"2220",
"2221",
"2230",
"2231",
"2320",
"2321",
"2330",
"2331",
"3220",
"3221",
"3230",
"3231",
"3320",
"3321",
"3330",
"3331",
"2222",
"2223",
"2232",
"2233",
"2322",
"2323",
"2332",
"2333",
"3222",
"3223",
"3232",
"3233",
"3322",
"3323",
"3332",
"3333"
];
} else if (dim === 8) {
quadKeys = [
"000",
"001",
"010",
"011",
"100",
"101",
"110",
"111",
"002",
"003",
"012",
"013",
"102",
"103",
"112",
"113",
"020",
"021",
"030",
"031",
"120",
"121",
"130",
"131",
"022",
"023",
"032",
"033",
"122",
"123",
"132",
"133",
"200",
"201",
"210",
"211",
"300",
"301",
"310",
"311",
"202",
"203",
"212",
"213",
"302",
"303",
"312",
"313",
"220",
"221",
"230",
"231",
"320",
"321",
"330",
"331",
"222",
"223",
"232",
"233",
"322",
"323",
"332",
"333"
];
} else if (dim === 4) {
quadKeys = [
"00",
"01",
"10",
"11",
"02",
"03",
"12",
"13",
"20",
"21",
"30",
"31",
"22",
"23",
"32",
"33"
];
} else {
quadKeys = [
"0",
"1",
"2",
"3"
];
}
return quadKeys;
}
var streetside_default = {
init: function() {
if (!_ssCache) {
this.reset();
}
this.event = utilRebind(this, dispatch8, "on");
},
reset: function() {
if (_ssCache) {
Object.values(_ssCache.bubbles.inflight).forEach(abortRequest6);
}
_ssCache = {
bubbles: { inflight: {}, loaded: {}, nextPage: {}, rtree: new import_rbush10.default(), points: {}, leaders: [] },
sequences: {}
};
},
bubbles: function(projection2) {
const limit = 5;
return searchLimited3(limit, projection2, _ssCache.bubbles.rtree);
},
cachedImage: function(imageKey) {
return _ssCache.bubbles.points[imageKey];
},
sequences: function(projection2) {
const viewport = projection2.clipExtent();
const min3 = [viewport[0][0], viewport[1][1]];
const max3 = [viewport[1][0], viewport[0][1]];
const bbox = geoExtent(projection2.invert(min3), projection2.invert(max3)).bbox();
let seen = {};
let results = [];
_ssCache.bubbles.rtree.search(bbox).forEach((d) => {
const key = d.data.sequenceKey;
if (key && !seen[key]) {
seen[key] = true;
results.push(_ssCache.sequences[key].geojson);
}
});
return results;
},
loadBubbles: function(projection2, margin) {
if (margin === void 0)
margin = 2;
loadTiles3("bubbles", bubbleApi, projection2, margin);
},
viewer: function() {
return _pannellumViewer;
},
initViewer: function() {
if (!window.pannellum)
return;
if (_pannellumViewer)
return;
_currScene += 1;
const sceneID = _currScene.toString();
const options2 = {
"default": { firstScene: sceneID },
scenes: {}
};
options2.scenes[sceneID] = _sceneOptions;
_pannellumViewer = window.pannellum.viewer("ideditor-viewer-streetside", options2);
},
ensureViewerLoaded: function(context) {
if (_loadViewerPromise3)
return _loadViewerPromise3;
let wrap2 = context.container().select(".photoviewer").selectAll(".ms-wrapper").data([0]);
let wrapEnter = wrap2.enter().append("div").attr("class", "photo-wrapper ms-wrapper").classed("hide", true);
let that = this;
let pointerPrefix = "PointerEvent" in window ? "pointer" : "mouse";
wrapEnter.append("div").attr("id", "ideditor-viewer-streetside").on(pointerPrefix + "down.streetside", () => {
select_default2(window).on(pointerPrefix + "move.streetside", () => {
dispatch8.call("viewerChanged");
}, true);
}).on(pointerPrefix + "up.streetside pointercancel.streetside", () => {
select_default2(window).on(pointerPrefix + "move.streetside", null);
let t = timer((elapsed) => {
dispatch8.call("viewerChanged");
if (elapsed > 2e3) {
t.stop();
}
});
}).append("div").attr("class", "photo-attribution fillD");
let controlsEnter = wrapEnter.append("div").attr("class", "photo-controls-wrap").append("div").attr("class", "photo-controls");
controlsEnter.append("button").on("click.back", step(-1)).text("\u25C4");
controlsEnter.append("button").on("click.forward", step(1)).text("\u25BA");
wrap2 = wrap2.merge(wrapEnter).call(setupCanvas, true);
context.ui().photoviewer.on("resize.streetside", () => {
if (_pannellumViewer) {
_pannellumViewer.resize();
}
});
_loadViewerPromise3 = new Promise((resolve, reject) => {
let loadedCount = 0;
function loaded() {
loadedCount += 1;
if (loadedCount === 2)
resolve();
}
const head = select_default2("head");
head.selectAll("#ideditor-streetside-viewercss").data([0]).enter().append("link").attr("id", "ideditor-streetside-viewercss").attr("rel", "stylesheet").attr("crossorigin", "anonymous").attr("href", context.asset(pannellumViewerCSS)).on("load.serviceStreetside", loaded).on("error.serviceStreetside", function() {
reject();
});
head.selectAll("#ideditor-streetside-viewerjs").data([0]).enter().append("script").attr("id", "ideditor-streetside-viewerjs").attr("crossorigin", "anonymous").attr("src", context.asset(pannellumViewerJS)).on("load.serviceStreetside", loaded).on("error.serviceStreetside", function() {
reject();
});
}).catch(function() {
_loadViewerPromise3 = null;
});
return _loadViewerPromise3;
function step(stepBy) {
return () => {
let viewer = context.container().select(".photoviewer");
let selected = viewer.empty() ? void 0 : viewer.datum();
if (!selected)
return;
let nextID = stepBy === 1 ? selected.ne : selected.pr;
let yaw = _pannellumViewer.getYaw();
let ca = selected.ca + yaw;
let origin = selected.loc;
const meters = 35;
let p1 = [
origin[0] + geoMetersToLon(meters / 5, origin[1]),
origin[1]
];
let p2 = [
origin[0] + geoMetersToLon(meters / 2, origin[1]),
origin[1] + geoMetersToLat(meters)
];
let p3 = [
origin[0] - geoMetersToLon(meters / 2, origin[1]),
origin[1] + geoMetersToLat(meters)
];
let p4 = [
origin[0] - geoMetersToLon(meters / 5, origin[1]),
origin[1]
];
let poly = [p1, p2, p3, p4, p1];
let angle2 = (stepBy === 1 ? ca : ca + 180) * (Math.PI / 180);
poly = geoRotate(poly, -angle2, origin);
let extent = poly.reduce((extent2, point) => {
return extent2.extend(geoExtent(point));
}, geoExtent());
let minDist = Infinity;
_ssCache.bubbles.rtree.search(extent.bbox()).forEach((d) => {
if (d.data.key === selected.key)
return;
if (!geoPointInPolygon(d.data.loc, poly))
return;
let dist = geoVecLength(d.data.loc, selected.loc);
let theta = selected.ca - d.data.ca;
let minTheta = Math.min(Math.abs(theta), 360 - Math.abs(theta));
if (minTheta > 20) {
dist += 5;
}
if (dist < minDist) {
nextID = d.data.key;
minDist = dist;
}
});
let nextBubble = nextID && that.cachedImage(nextID);
if (!nextBubble)
return;
context.map().centerEase(nextBubble.loc);
that.selectImage(context, nextBubble.key).yaw(yaw).showViewer(context);
};
}
},
yaw: function(yaw) {
if (typeof yaw !== "number")
return yaw;
_sceneOptions.yaw = yaw;
return this;
},
showViewer: function(context) {
let wrap2 = context.container().select(".photoviewer").classed("hide", false);
let isHidden = wrap2.selectAll(".photo-wrapper.ms-wrapper.hide").size();
if (isHidden) {
wrap2.selectAll(".photo-wrapper:not(.ms-wrapper)").classed("hide", true);
wrap2.selectAll(".photo-wrapper.ms-wrapper").classed("hide", false);
}
return this;
},
hideViewer: function(context) {
let viewer = context.container().select(".photoviewer");
if (!viewer.empty())
viewer.datum(null);
viewer.classed("hide", true).selectAll(".photo-wrapper").classed("hide", true);
context.container().selectAll(".viewfield-group, .sequence, .icon-sign").classed("currentView", false);
this.updateUrlImage(null);
return this.setStyles(context, null, true);
},
selectImage: function(context, key) {
let that = this;
let d = this.cachedImage(key);
let viewer = context.container().select(".photoviewer");
if (!viewer.empty())
viewer.datum(d);
this.setStyles(context, null, true);
let wrap2 = context.container().select(".photoviewer .ms-wrapper");
let attribution = wrap2.selectAll(".photo-attribution").html("");
wrap2.selectAll(".pnlm-load-box").style("display", "block");
if (!d)
return this;
this.updateUrlImage(key);
_sceneOptions.northOffset = d.ca;
let line1 = attribution.append("div").attr("class", "attribution-row");
const hiresDomId = utilUniqueDomId("streetside-hires");
let label = line1.append("label").attr("for", hiresDomId).attr("class", "streetside-hires");
label.append("input").attr("type", "checkbox").attr("id", hiresDomId).property("checked", _hires).on("click", (d3_event) => {
d3_event.stopPropagation();
_hires = !_hires;
_resolution = _hires ? 1024 : 512;
wrap2.call(setupCanvas, true);
let viewstate = {
yaw: _pannellumViewer.getYaw(),
pitch: _pannellumViewer.getPitch(),
hfov: _pannellumViewer.getHfov()
};
_sceneOptions = Object.assign(_sceneOptions, viewstate);
that.selectImage(context, d.key).showViewer(context);
});
label.append("span").call(_t.append("streetside.hires"));
let captureInfo = line1.append("div").attr("class", "attribution-capture-info");
if (d.captured_by) {
const yyyy = new Date().getFullYear();
captureInfo.append("a").attr("class", "captured_by").attr("target", "_blank").attr("href", "https://www.microsoft.com/en-us/maps/streetside").text("\xA9" + yyyy + " Microsoft");
captureInfo.append("span").text("|");
}
if (d.captured_at) {
captureInfo.append("span").attr("class", "captured_at").text(localeTimestamp(d.captured_at));
}
let line2 = attribution.append("div").attr("class", "attribution-row");
line2.append("a").attr("class", "image-view-link").attr("target", "_blank").attr("href", "https://www.bing.com/maps?cp=" + d.loc[1] + "~" + d.loc[0] + "&lvl=17&dir=" + d.ca + "&style=x&v=2&sV=1").call(_t.append("streetside.view_on_bing"));
line2.append("a").attr("class", "image-report-link").attr("target", "_blank").attr("href", "https://www.bing.com/maps/privacyreport/streetsideprivacyreport?bubbleid=" + encodeURIComponent(d.key) + "&focus=photo&lat=" + d.loc[1] + "&lng=" + d.loc[0] + "&z=17").call(_t.append("streetside.report"));
let bubbleIdQuadKey = d.key.toString(4);
const paddingNeeded = 16 - bubbleIdQuadKey.length;
for (let i2 = 0; i2 < paddingNeeded; i2++) {
bubbleIdQuadKey = "0" + bubbleIdQuadKey;
}
const imgUrlPrefix = streetsideImagesApi + "hs" + bubbleIdQuadKey;
const imgUrlSuffix = ".jpg?g=6338&n=z";
const faceKeys = ["01", "02", "03", "10", "11", "12"];
let quadKeys = getQuadKeys();
let faces = faceKeys.map((faceKey) => {
return quadKeys.map((quadKey) => {
const xy = qkToXY(quadKey);
return {
face: faceKey,
url: imgUrlPrefix + faceKey + quadKey + imgUrlSuffix,
x: xy[0],
y: xy[1]
};
});
});
loadFaces(faces).then(function() {
if (!_pannellumViewer) {
that.initViewer();
} else {
_currScene += 1;
let sceneID = _currScene.toString();
_pannellumViewer.addScene(sceneID, _sceneOptions).loadScene(sceneID);
if (_currScene > 2) {
sceneID = (_currScene - 1).toString();
_pannellumViewer.removeScene(sceneID);
}
}
});
return this;
},
getSequenceKeyForBubble: function(d) {
return d && d.sequenceKey;
},
setStyles: function(context, hovered, reset) {
if (reset) {
context.container().selectAll(".viewfield-group").classed("highlighted", false).classed("hovered", false).classed("currentView", false);
context.container().selectAll(".sequence").classed("highlighted", false).classed("currentView", false);
}
let hoveredBubbleKey = hovered && hovered.key;
let hoveredSequenceKey = this.getSequenceKeyForBubble(hovered);
let hoveredSequence = hoveredSequenceKey && _ssCache.sequences[hoveredSequenceKey];
let hoveredBubbleKeys = hoveredSequence && hoveredSequence.bubbles.map((d) => d.key) || [];
let viewer = context.container().select(".photoviewer");
let selected = viewer.empty() ? void 0 : viewer.datum();
let selectedBubbleKey = selected && selected.key;
let selectedSequenceKey = this.getSequenceKeyForBubble(selected);
let selectedSequence = selectedSequenceKey && _ssCache.sequences[selectedSequenceKey];
let selectedBubbleKeys = selectedSequence && selectedSequence.bubbles.map((d) => d.key) || [];
let highlightedBubbleKeys = utilArrayUnion(hoveredBubbleKeys, selectedBubbleKeys);
context.container().selectAll(".layer-streetside-images .viewfield-group").classed("highlighted", (d) => highlightedBubbleKeys.indexOf(d.key) !== -1).classed("hovered", (d) => d.key === hoveredBubbleKey).classed("currentView", (d) => d.key === selectedBubbleKey);
context.container().selectAll(".layer-streetside-images .sequence").classed("highlighted", (d) => d.properties.key === hoveredSequenceKey).classed("currentView", (d) => d.properties.key === selectedSequenceKey);
context.container().selectAll(".layer-streetside-images .viewfield-group .viewfield").attr("d", viewfieldPath);
function viewfieldPath() {
let d = this.parentNode.__data__;
if (d.pano && d.key !== selectedBubbleKey) {
return "M 8,13 m -10,0 a 10,10 0 1,0 20,0 a 10,10 0 1,0 -20,0";
} else {
return "M 6,9 C 8,8.4 8,8.4 10,9 L 16,-2 C 12,-5 4,-5 0,-2 z";
}
}
return this;
},
updateUrlImage: function(imageKey) {
if (!window.mocha) {
var hash = utilStringQs(window.location.hash);
if (imageKey) {
hash.photo = "streetside/" + imageKey;
} else {
delete hash.photo;
}
window.location.replace("#" + utilQsString(hash, true));
}
},
cache: function() {
return _ssCache;
}
};
// modules/services/taginfo.js
var apibase4 = "https://taginfo.openstreetmap.org/api/4/";
var _inflight3 = {};
var _popularKeys = {};
var _taginfoCache = {};
var tag_sorts = {
point: "count_nodes",
vertex: "count_nodes",
area: "count_ways",
line: "count_ways"
};
var tag_sort_members = {
point: "count_node_members",
vertex: "count_node_members",
area: "count_way_members",
line: "count_way_members",
relation: "count_relation_members"
};
var tag_filters = {
point: "nodes",
vertex: "nodes",
area: "ways",
line: "ways"
};
var tag_members_fractions = {
point: "count_node_members_fraction",
vertex: "count_node_members_fraction",
area: "count_way_members_fraction",
line: "count_way_members_fraction",
relation: "count_relation_members_fraction"
};
function sets(params, n2, o) {
if (params.geometry && o[params.geometry]) {
params[n2] = o[params.geometry];
}
return params;
}
function setFilter(params) {
return sets(params, "filter", tag_filters);
}
function setSort(params) {
return sets(params, "sortname", tag_sorts);
}
function setSortMembers(params) {
return sets(params, "sortname", tag_sort_members);
}
function clean(params) {
return utilObjectOmit(params, ["geometry", "debounce"]);
}
function filterKeys(type3) {
var count_type = type3 ? "count_" + type3 : "count_all";
return function(d) {
return parseFloat(d[count_type]) > 2500 || d.in_wiki;
};
}
function filterMultikeys(prefix) {
return function(d) {
var re2 = new RegExp("^" + prefix + "(.*)$");
var matches = d.key.match(re2) || [];
return matches.length === 2 && matches[1].indexOf(":") === -1;
};
}
function filterValues(allowUpperCase) {
return function(d) {
if (d.value.match(/[;,]/) !== null)
return false;
if (!allowUpperCase && d.value.match(/[A-Z*]/) !== null)
return false;
return parseFloat(d.fraction) > 0;
};
}
function filterRoles(geometry) {
return function(d) {
if (d.role === "")
return false;
if (d.role.match(/[A-Z*;,]/) !== null)
return false;
return parseFloat(d[tag_members_fractions[geometry]]) > 0;
};
}
function valKey(d) {
return {
value: d.key,
title: d.key
};
}
function valKeyDescription(d) {
var obj = {
value: d.value,
title: d.description || d.value
};
if (d.count) {
obj.count = d.count;
}
return obj;
}
function roleKey(d) {
return {
value: d.role,
title: d.role
};
}
function sortKeys(a, b) {
return a.key.indexOf(":") === -1 && b.key.indexOf(":") !== -1 ? -1 : a.key.indexOf(":") !== -1 && b.key.indexOf(":") === -1 ? 1 : 0;
}
var debouncedRequest2 = debounce_default(request2, 300, { leading: false });
function request2(url, params, exactMatch, callback, loaded) {
if (_inflight3[url])
return;
if (checkCache(url, params, exactMatch, callback))
return;
var controller = new AbortController();
_inflight3[url] = controller;
json_default(url, { signal: controller.signal }).then(function(result) {
delete _inflight3[url];
if (loaded)
loaded(null, result);
}).catch(function(err) {
delete _inflight3[url];
if (err.name === "AbortError")
return;
if (loaded)
loaded(err.message);
});
}
function checkCache(url, params, exactMatch, callback) {
var rp = params.rp || 25;
var testQuery = params.query || "";
var testUrl = url;
do {
var hit = _taginfoCache[testUrl];
if (hit && (url === testUrl || hit.length < rp)) {
callback(null, hit);
return true;
}
if (exactMatch || !testQuery.length)
return false;
testQuery = testQuery.slice(0, -1);
testUrl = url.replace(/&query=(.*?)&/, "&query=" + testQuery + "&");
} while (testQuery.length >= 0);
return false;
}
var taginfo_default = {
init: function() {
_inflight3 = {};
_taginfoCache = {};
_popularKeys = {
postal_code: true,
full_name: true,
loc_name: true,
reg_name: true,
short_name: true,
sorting_name: true,
artist_name: true,
nat_name: true,
long_name: true,
"bridge:name": true
};
var params = {
rp: 100,
sortname: "values_all",
sortorder: "desc",
page: 1,
debounce: false,
lang: _mainLocalizer.languageCode()
};
this.keys(params, function(err, data) {
if (err)
return;
data.forEach(function(d) {
if (d.value === "opening_hours")
return;
_popularKeys[d.value] = true;
});
});
},
reset: function() {
Object.values(_inflight3).forEach(function(controller) {
controller.abort();
});
_inflight3 = {};
},
keys: function(params, callback) {
var doRequest = params.debounce ? debouncedRequest2 : request2;
params = clean(setSort(params));
params = Object.assign({
rp: 10,
sortname: "count_all",
sortorder: "desc",
page: 1,
lang: _mainLocalizer.languageCode()
}, params);
var url = apibase4 + "keys/all?" + utilQsString(params);
doRequest(url, params, false, callback, function(err, d) {
if (err) {
callback(err);
} else {
var f2 = filterKeys(params.filter);
var result = d.data.filter(f2).sort(sortKeys).map(valKey);
_taginfoCache[url] = result;
callback(null, result);
}
});
},
multikeys: function(params, callback) {
var doRequest = params.debounce ? debouncedRequest2 : request2;
params = clean(setSort(params));
params = Object.assign({
rp: 25,
sortname: "count_all",
sortorder: "desc",
page: 1,
lang: _mainLocalizer.languageCode()
}, params);
var prefix = params.query;
var url = apibase4 + "keys/all?" + utilQsString(params);
doRequest(url, params, true, callback, function(err, d) {
if (err) {
callback(err);
} else {
var f2 = filterMultikeys(prefix);
var result = d.data.filter(f2).map(valKey);
_taginfoCache[url] = result;
callback(null, result);
}
});
},
values: function(params, callback) {
var key = params.key;
if (key && _popularKeys[key]) {
callback(null, []);
return;
}
var doRequest = params.debounce ? debouncedRequest2 : request2;
params = clean(setSort(setFilter(params)));
params = Object.assign({
rp: 25,
sortname: "count_all",
sortorder: "desc",
page: 1,
lang: _mainLocalizer.languageCode()
}, params);
var url = apibase4 + "key/values?" + utilQsString(params);
doRequest(url, params, false, callback, function(err, d) {
if (err) {
callback(err);
} else {
var re2 = /network|taxon|genus|species|brand|grape_variety|royal_cypher|listed_status|booth|rating|stars|:output|_hours|_times|_ref|manufacturer|country|target|brewery|cai_scale/;
var allowUpperCase = re2.test(params.key);
var f2 = filterValues(allowUpperCase);
var result = d.data.filter(f2).map(valKeyDescription);
_taginfoCache[url] = result;
callback(null, result);
}
});
},
roles: function(params, callback) {
var doRequest = params.debounce ? debouncedRequest2 : request2;
var geometry = params.geometry;
params = clean(setSortMembers(params));
params = Object.assign({
rp: 25,
sortname: "count_all_members",
sortorder: "desc",
page: 1,
lang: _mainLocalizer.languageCode()
}, params);
var url = apibase4 + "relation/roles?" + utilQsString(params);
doRequest(url, params, true, callback, function(err, d) {
if (err) {
callback(err);
} else {
var f2 = filterRoles(geometry);
var result = d.data.filter(f2).map(roleKey);
_taginfoCache[url] = result;
callback(null, result);
}
});
},
docs: function(params, callback) {
var doRequest = params.debounce ? debouncedRequest2 : request2;
params = clean(setSort(params));
var path = "key/wiki_pages?";
if (params.value) {
path = "tag/wiki_pages?";
} else if (params.rtype) {
path = "relation/wiki_pages?";
}
var url = apibase4 + path + utilQsString(params);
doRequest(url, params, true, callback, function(err, d) {
if (err) {
callback(err);
} else {
_taginfoCache[url] = d.data;
callback(null, d.data);
}
});
},
apibase: function(_) {
if (!arguments.length)
return apibase4;
apibase4 = _;
return this;
}
};
// modules/services/vector_tile.js
var import_fast_deep_equal11 = __toESM(require_fast_deep_equal());
// node_modules/@turf/helpers/dist/es/index.js
var earthRadius = 63710088e-1;
var factors = {
centimeters: earthRadius * 100,
centimetres: earthRadius * 100,
degrees: earthRadius / 111325,
feet: earthRadius * 3.28084,
inches: earthRadius * 39.37,
kilometers: earthRadius / 1e3,
kilometres: earthRadius / 1e3,
meters: earthRadius,
metres: earthRadius,
miles: earthRadius / 1609.344,
millimeters: earthRadius * 1e3,
millimetres: earthRadius * 1e3,
nauticalmiles: earthRadius / 1852,
radians: 1,
yards: earthRadius * 1.0936
};
var unitsFactors = {
centimeters: 100,
centimetres: 100,
degrees: 1 / 111325,
feet: 3.28084,
inches: 39.37,
kilometers: 1 / 1e3,
kilometres: 1 / 1e3,
meters: 1,
metres: 1,
miles: 1 / 1609.344,
millimeters: 1e3,
millimetres: 1e3,
nauticalmiles: 1 / 1852,
radians: 1 / earthRadius,
yards: 1.0936133
};
function feature2(geom, properties, options2) {
if (options2 === void 0) {
options2 = {};
}
var feat = { type: "Feature" };
if (options2.id === 0 || options2.id) {
feat.id = options2.id;
}
if (options2.bbox) {
feat.bbox = options2.bbox;
}
feat.properties = properties || {};
feat.geometry = geom;
return feat;
}
function polygon(coordinates, properties, options2) {
if (options2 === void 0) {
options2 = {};
}
for (var _i = 0, coordinates_1 = coordinates; _i < coordinates_1.length; _i++) {
var ring = coordinates_1[_i];
if (ring.length < 4) {
throw new Error("Each LinearRing of a Polygon must have 4 or more Positions.");
}
for (var j2 = 0; j2 < ring[ring.length - 1].length; j2++) {
if (ring[ring.length - 1][j2] !== ring[0][j2]) {
throw new Error("First and last Position are not equivalent.");
}
}
}
var geom = {
type: "Polygon",
coordinates
};
return feature2(geom, properties, options2);
}
function lineString(coordinates, properties, options2) {
if (options2 === void 0) {
options2 = {};
}
if (coordinates.length < 2) {
throw new Error("coordinates must be an array of two or more positions");
}
var geom = {
type: "LineString",
coordinates
};
return feature2(geom, properties, options2);
}
function multiLineString(coordinates, properties, options2) {
if (options2 === void 0) {
options2 = {};
}
var geom = {
type: "MultiLineString",
coordinates
};
return feature2(geom, properties, options2);
}
function multiPolygon(coordinates, properties, options2) {
if (options2 === void 0) {
options2 = {};
}
var geom = {
type: "MultiPolygon",
coordinates
};
return feature2(geom, properties, options2);
}
// node_modules/@turf/invariant/dist/es/index.js
function getGeom(geojson) {
if (geojson.type === "Feature") {
return geojson.geometry;
}
return geojson;
}
// node_modules/@turf/bbox-clip/dist/es/lib/lineclip.js
function lineclip(points, bbox, result) {
var len = points.length, codeA = bitCode(points[0], bbox), part = [], i2, codeB, lastCode;
var a;
var b;
if (!result)
result = [];
for (i2 = 1; i2 < len; i2++) {
a = points[i2 - 1];
b = points[i2];
codeB = lastCode = bitCode(b, bbox);
while (true) {
if (!(codeA | codeB)) {
part.push(a);
if (codeB !== lastCode) {
part.push(b);
if (i2 < len - 1) {
result.push(part);
part = [];
}
} else if (i2 === len - 1) {
part.push(b);
}
break;
} else if (codeA & codeB) {
break;
} else if (codeA) {
a = intersect(a, b, codeA, bbox);
codeA = bitCode(a, bbox);
} else {
b = intersect(a, b, codeB, bbox);
codeB = bitCode(b, bbox);
}
}
codeA = lastCode;
}
if (part.length)
result.push(part);
return result;
}
function polygonclip(points, bbox) {
var result, edge, prev, prevInside, i2, p, inside;
for (edge = 1; edge <= 8; edge *= 2) {
result = [];
prev = points[points.length - 1];
prevInside = !(bitCode(prev, bbox) & edge);
for (i2 = 0; i2 < points.length; i2++) {
p = points[i2];
inside = !(bitCode(p, bbox) & edge);
if (inside !== prevInside)
result.push(intersect(prev, p, edge, bbox));
if (inside)
result.push(p);
prev = p;
prevInside = inside;
}
points = result;
if (!points.length)
break;
}
return result;
}
function intersect(a, b, edge, bbox) {
return edge & 8 ? [a[0] + (b[0] - a[0]) * (bbox[3] - a[1]) / (b[1] - a[1]), bbox[3]] : edge & 4 ? [a[0] + (b[0] - a[0]) * (bbox[1] - a[1]) / (b[1] - a[1]), bbox[1]] : edge & 2 ? [bbox[2], a[1] + (b[1] - a[1]) * (bbox[2] - a[0]) / (b[0] - a[0])] : edge & 1 ? [bbox[0], a[1] + (b[1] - a[1]) * (bbox[0] - a[0]) / (b[0] - a[0])] : null;
}
function bitCode(p, bbox) {
var code = 0;
if (p[0] < bbox[0])
code |= 1;
else if (p[0] > bbox[2])
code |= 2;
if (p[1] < bbox[1])
code |= 4;
else if (p[1] > bbox[3])
code |= 8;
return code;
}
// node_modules/@turf/bbox-clip/dist/es/index.js
function bboxClip(feature3, bbox) {
var geom = getGeom(feature3);
var type3 = geom.type;
var properties = feature3.type === "Feature" ? feature3.properties : {};
var coords = geom.coordinates;
switch (type3) {
case "LineString":
case "MultiLineString": {
var lines_1 = [];
if (type3 === "LineString") {
coords = [coords];
}
coords.forEach(function(line) {
lineclip(line, bbox, lines_1);
});
if (lines_1.length === 1) {
return lineString(lines_1[0], properties);
}
return multiLineString(lines_1, properties);
}
case "Polygon":
return polygon(clipPolygon(coords, bbox), properties);
case "MultiPolygon":
return multiPolygon(coords.map(function(poly) {
return clipPolygon(poly, bbox);
}), properties);
default:
throw new Error("geometry " + type3 + " not supported");
}
}
function clipPolygon(rings, bbox) {
var outRings = [];
for (var _i = 0, rings_1 = rings; _i < rings_1.length; _i++) {
var ring = rings_1[_i];
var clipped = polygonclip(ring, bbox);
if (clipped.length > 0) {
if (clipped[0][0] !== clipped[clipped.length - 1][0] || clipped[0][1] !== clipped[clipped.length - 1][1]) {
clipped.push(clipped[0]);
}
if (clipped.length >= 4) {
outRings.push(clipped);
}
}
}
return outRings;
}
// modules/services/vector_tile.js
var import_fast_json_stable_stringify2 = __toESM(require_fast_json_stable_stringify());
var import_polygon_clipping2 = __toESM(require_polygon_clipping_umd());
var import_pbf2 = __toESM(require_pbf());
var import_vector_tile2 = __toESM(require_vector_tile());
var tiler7 = utilTiler().tileSize(512).margin(1);
var dispatch9 = dispatch_default("loadedData");
var _vtCache;
function abortRequest7(controller) {
controller.abort();
}
function vtToGeoJSON(data, tile, mergeCache) {
var vectorTile = new import_vector_tile2.default.VectorTile(new import_pbf2.default(data));
var layers = Object.keys(vectorTile.layers);
if (!Array.isArray(layers)) {
layers = [layers];
}
var features2 = [];
layers.forEach(function(layerID) {
var layer = vectorTile.layers[layerID];
if (layer) {
for (var i2 = 0; i2 < layer.length; i2++) {
var feature3 = layer.feature(i2).toGeoJSON(tile.xyz[0], tile.xyz[1], tile.xyz[2]);
var geometry = feature3.geometry;
if (geometry.type === "Polygon") {
geometry.type = "MultiPolygon";
geometry.coordinates = [geometry.coordinates];
}
var isClipped = false;
if (geometry.type === "MultiPolygon") {
var featureClip = bboxClip(feature3, tile.extent.rectangle());
if (!(0, import_fast_deep_equal11.default)(feature3.geometry, featureClip.geometry)) {
isClipped = true;
}
if (!feature3.geometry.coordinates.length)
continue;
if (!feature3.geometry.coordinates[0].length)
continue;
}
var featurehash = utilHashcode((0, import_fast_json_stable_stringify2.default)(feature3));
var propertyhash = utilHashcode((0, import_fast_json_stable_stringify2.default)(feature3.properties || {}));
feature3.__layerID__ = layerID.replace(/[^_a-zA-Z0-9\-]/g, "_");
feature3.__featurehash__ = featurehash;
feature3.__propertyhash__ = propertyhash;
features2.push(feature3);
if (isClipped && geometry.type === "MultiPolygon") {
var merged = mergeCache[propertyhash];
if (merged && merged.length) {
var other = merged[0];
var coords = import_polygon_clipping2.default.union(feature3.geometry.coordinates, other.geometry.coordinates);
if (!coords || !coords.length) {
continue;
}
merged.push(feature3);
for (var j2 = 0; j2 < merged.length; j2++) {
merged[j2].geometry.coordinates = coords;
merged[j2].__featurehash__ = featurehash;
}
} else {
mergeCache[propertyhash] = [feature3];
}
}
}
}
});
return features2;
}
function loadTile2(source, tile) {
if (source.loaded[tile.id] || source.inflight[tile.id])
return;
var url = source.template.replace("{x}", tile.xyz[0]).replace("{y}", tile.xyz[1]).replace(/\{[t-]y\}/, Math.pow(2, tile.xyz[2]) - tile.xyz[1] - 1).replace(/\{z(oom)?\}/, tile.xyz[2]).replace(/\{switch:([^}]+)\}/, function(s, r) {
var subdomains = r.split(",");
return subdomains[(tile.xyz[0] + tile.xyz[1]) % subdomains.length];
});
var controller = new AbortController();
source.inflight[tile.id] = controller;
fetch(url, { signal: controller.signal }).then(function(response) {
if (!response.ok) {
throw new Error(response.status + " " + response.statusText);
}
source.loaded[tile.id] = [];
delete source.inflight[tile.id];
return response.arrayBuffer();
}).then(function(data) {
if (!data) {
throw new Error("No Data");
}
var z = tile.xyz[2];
if (!source.canMerge[z]) {
source.canMerge[z] = {};
}
source.loaded[tile.id] = vtToGeoJSON(data, tile, source.canMerge[z]);
dispatch9.call("loadedData");
}).catch(function() {
source.loaded[tile.id] = [];
delete source.inflight[tile.id];
});
}
var vector_tile_default = {
init: function() {
if (!_vtCache) {
this.reset();
}
this.event = utilRebind(this, dispatch9, "on");
},
reset: function() {
for (var sourceID in _vtCache) {
var source = _vtCache[sourceID];
if (source && source.inflight) {
Object.values(source.inflight).forEach(abortRequest7);
}
}
_vtCache = {};
},
addSource: function(sourceID, template) {
_vtCache[sourceID] = { template, inflight: {}, loaded: {}, canMerge: {} };
return _vtCache[sourceID];
},
data: function(sourceID, projection2) {
var source = _vtCache[sourceID];
if (!source)
return [];
var tiles = tiler7.getTiles(projection2);
var seen = {};
var results = [];
for (var i2 = 0; i2 < tiles.length; i2++) {
var features2 = source.loaded[tiles[i2].id];
if (!features2 || !features2.length)
continue;
for (var j2 = 0; j2 < features2.length; j2++) {
var feature3 = features2[j2];
var hash = feature3.__featurehash__;
if (seen[hash])
continue;
seen[hash] = true;
results.push(Object.assign({}, feature3));
}
}
return results;
},
loadTiles: function(sourceID, template, projection2) {
var source = _vtCache[sourceID];
if (!source) {
source = this.addSource(sourceID, template);
}
var tiles = tiler7.getTiles(projection2);
Object.keys(source.inflight).forEach(function(k) {
var wanted = tiles.find(function(tile) {
return k === tile.id;
});
if (!wanted) {
abortRequest7(source.inflight[k]);
delete source.inflight[k];
}
});
tiles.forEach(function(tile) {
loadTile2(source, tile);
});
},
cache: function() {
return _vtCache;
}
};
// modules/services/wikidata.js
var apibase5 = "https://www.wikidata.org/w/api.php?";
var _wikidataCache = {};
var wikidata_default = {
init: function() {
},
reset: function() {
_wikidataCache = {};
},
itemsForSearchQuery: function(query, callback) {
if (!query) {
if (callback)
callback("No query", {});
return;
}
var lang = this.languagesToQuery()[0];
var url = apibase5 + utilQsString({
action: "wbsearchentities",
format: "json",
formatversion: 2,
search: query,
type: "item",
language: lang,
uselang: lang,
limit: 10,
origin: "*"
});
json_default(url).then(function(result) {
if (result && result.error) {
throw new Error(result.error);
}
if (callback)
callback(null, result.search || {});
}).catch(function(err) {
if (callback)
callback(err.message, {});
});
},
itemsByTitle: function(lang, title, callback) {
if (!title) {
if (callback)
callback("No title", {});
return;
}
lang = lang || "en";
var url = apibase5 + utilQsString({
action: "wbgetentities",
format: "json",
formatversion: 2,
sites: lang.replace(/-/g, "_") + "wiki",
titles: title,
languages: "en",
origin: "*"
});
json_default(url).then(function(result) {
if (result && result.error) {
throw new Error(result.error);
}
if (callback)
callback(null, result.entities || {});
}).catch(function(err) {
if (callback)
callback(err.message, {});
});
},
languagesToQuery: function() {
return _mainLocalizer.localeCodes().map(function(code) {
return code.toLowerCase();
}).filter(function(code) {
return code !== "en-us";
});
},
entityByQID: function(qid, callback) {
if (!qid) {
callback("No qid", {});
return;
}
if (_wikidataCache[qid]) {
if (callback)
callback(null, _wikidataCache[qid]);
return;
}
var langs = this.languagesToQuery();
var url = apibase5 + utilQsString({
action: "wbgetentities",
format: "json",
formatversion: 2,
ids: qid,
props: "labels|descriptions|claims|sitelinks",
sitefilter: langs.map(function(d) {
return d + "wiki";
}).join("|"),
languages: langs.join("|"),
languagefallback: 1,
origin: "*"
});
json_default(url).then(function(result) {
if (result && result.error) {
throw new Error(result.error);
}
if (callback)
callback(null, result.entities[qid] || {});
}).catch(function(err) {
if (callback)
callback(err.message, {});
});
},
getDocs: function(params, callback) {
var langs = this.languagesToQuery();
this.entityByQID(params.qid, function(err, entity) {
if (err || !entity) {
callback(err || "No entity");
return;
}
var i2;
var description2;
for (i2 in langs) {
let code = langs[i2];
if (entity.descriptions[code] && entity.descriptions[code].language === code) {
description2 = entity.descriptions[code];
break;
}
}
if (!description2 && Object.values(entity.descriptions).length)
description2 = Object.values(entity.descriptions)[0];
var result = {
title: entity.id,
description: description2 ? description2.value : "",
descriptionLocaleCode: description2 ? description2.language : "",
editURL: "https://www.wikidata.org/wiki/" + entity.id
};
if (entity.claims) {
var imageroot = "https://commons.wikimedia.org/w/index.php";
var props = ["P154", "P18"];
var prop, image;
for (i2 = 0; i2 < props.length; i2++) {
prop = entity.claims[props[i2]];
if (prop && Object.keys(prop).length > 0) {
image = prop[Object.keys(prop)[0]].mainsnak.datavalue.value;
if (image) {
result.imageURL = imageroot + "?" + utilQsString({
title: "Special:Redirect/file/" + image,
width: 400
});
break;
}
}
}
}
if (entity.sitelinks) {
var englishLocale = _mainLocalizer.languageCode().toLowerCase() === "en";
for (i2 = 0; i2 < langs.length; i2++) {
var w = langs[i2] + "wiki";
if (entity.sitelinks[w]) {
var title = entity.sitelinks[w].title;
var tKey = "inspector.wiki_reference";
if (!englishLocale && langs[i2] === "en") {
tKey = "inspector.wiki_en_reference";
}
result.wiki = {
title,
text: tKey,
url: "https://" + langs[i2] + ".wikipedia.org/wiki/" + title.replace(/ /g, "_")
};
break;
}
}
}
callback(null, result);
});
}
};
// modules/services/wikipedia.js
var endpoint = "https://en.wikipedia.org/w/api.php?";
var wikipedia_default = {
init: function() {
},
reset: function() {
},
search: function(lang, query, callback) {
if (!query) {
if (callback)
callback("No Query", []);
return;
}
lang = lang || "en";
var url = endpoint.replace("en", lang) + utilQsString({
action: "query",
list: "search",
srlimit: "10",
srinfo: "suggestion",
format: "json",
origin: "*",
srsearch: query
});
json_default(url).then(function(result) {
if (result && result.error) {
throw new Error(result.error);
} else if (!result || !result.query || !result.query.search) {
throw new Error("No Results");
}
if (callback) {
var titles = result.query.search.map(function(d) {
return d.title;
});
callback(null, titles);
}
}).catch(function(err) {
if (callback)
callback(err, []);
});
},
suggestions: function(lang, query, callback) {
if (!query) {
if (callback)
callback("", []);
return;
}
lang = lang || "en";
var url = endpoint.replace("en", lang) + utilQsString({
action: "opensearch",
namespace: 0,
suggest: "",
format: "json",
origin: "*",
search: query
});
json_default(url).then(function(result) {
if (result && result.error) {
throw new Error(result.error);
} else if (!result || result.length < 2) {
throw new Error("No Results");
}
if (callback)
callback(null, result[1] || []);
}).catch(function(err) {
if (callback)
callback(err.message, []);
});
},
translations: function(lang, title, callback) {
if (!title) {
if (callback)
callback("No Title");
return;
}
var url = endpoint.replace("en", lang) + utilQsString({
action: "query",
prop: "langlinks",
format: "json",
origin: "*",
lllimit: 500,
titles: title
});
json_default(url).then(function(result) {
if (result && result.error) {
throw new Error(result.error);
} else if (!result || !result.query || !result.query.pages) {
throw new Error("No Results");
}
if (callback) {
var list = result.query.pages[Object.keys(result.query.pages)[0]];
var translations = {};
if (list && list.langlinks) {
list.langlinks.forEach(function(d) {
translations[d.lang] = d["*"];
});
}
callback(null, translations);
}
}).catch(function(err) {
if (callback)
callback(err.message);
});
}
};
// modules/services/index.js
var services = {
geocoder: nominatim_default,
keepRight: keepRight_default,
improveOSM: improveOSM_default,
osmose: osmose_default,
mapillary: mapillary_default,
nsi: nsi_default,
kartaview: kartaview_default,
osm: osm_default,
osmWikibase: osm_wikibase_default,
maprules: maprules_default,
streetside: streetside_default,
taginfo: taginfo_default,
vectorTile: vector_tile_default,
wikidata: wikidata_default,
wikipedia: wikipedia_default
};
// modules/modes/drag_note.js
function modeDragNote(context) {
var mode = {
id: "drag-note",
button: "browse"
};
var edit2 = behaviorEdit(context);
var _nudgeInterval;
var _lastLoc;
var _note;
function startNudge(d3_event, nudge) {
if (_nudgeInterval)
window.clearInterval(_nudgeInterval);
_nudgeInterval = window.setInterval(function() {
context.map().pan(nudge);
doMove(d3_event, nudge);
}, 50);
}
function stopNudge() {
if (_nudgeInterval) {
window.clearInterval(_nudgeInterval);
_nudgeInterval = null;
}
}
function origin(note) {
return context.projection(note.loc);
}
function start2(d3_event, note) {
_note = note;
var osm = services.osm;
if (osm) {
_note = osm.getNote(_note.id);
}
context.surface().selectAll(".note-" + _note.id).classed("active", true);
context.perform(actionNoop());
context.enter(mode);
context.selectedNoteID(_note.id);
}
function move(d3_event, entity, point) {
d3_event.stopPropagation();
_lastLoc = context.projection.invert(point);
doMove(d3_event);
var nudge = geoViewportEdge(point, context.map().dimensions());
if (nudge) {
startNudge(d3_event, nudge);
} else {
stopNudge();
}
}
function doMove(d3_event, nudge) {
nudge = nudge || [0, 0];
var currPoint = d3_event && d3_event.point || context.projection(_lastLoc);
var currMouse = geoVecSubtract(currPoint, nudge);
var loc = context.projection.invert(currMouse);
_note = _note.move(loc);
var osm = services.osm;
if (osm) {
osm.replaceNote(_note);
}
context.replace(actionNoop());
}
function end() {
context.replace(actionNoop());
context.selectedNoteID(_note.id).enter(modeSelectNote(context, _note.id));
}
var drag = behaviorDrag().selector(".layer-touch.markers .target.note.new").surface(context.container().select(".main-map").node()).origin(origin).on("start", start2).on("move", move).on("end", end);
mode.enter = function() {
context.install(edit2);
};
mode.exit = function() {
context.ui().sidebar.hover.cancel();
context.uninstall(edit2);
context.surface().selectAll(".active").classed("active", false);
stopNudge();
};
mode.behavior = drag;
return mode;
}
// modules/modes/select_data.js
function modeSelectData(context, selectedDatum) {
var mode = {
id: "select-data",
button: "browse"
};
var keybinding = utilKeybinding("select-data");
var dataEditor = uiDataEditor(context);
var behaviors = [
behaviorBreathe(context),
behaviorHover(context),
behaviorSelect(context),
behaviorLasso(context),
modeDragNode(context).behavior,
modeDragNote(context).behavior
];
function selectData(d3_event, drawn) {
var selection2 = context.surface().selectAll(".layer-mapdata .data" + selectedDatum.__featurehash__);
if (selection2.empty()) {
var source = d3_event && d3_event.type === "zoom" && d3_event.sourceEvent;
if (drawn && source && (source.type === "pointermove" || source.type === "mousemove" || source.type === "touchmove")) {
context.enter(modeBrowse(context));
}
} else {
selection2.classed("selected", true);
}
}
function esc() {
if (context.container().select(".combobox").size())
return;
context.enter(modeBrowse(context));
}
mode.zoomToSelected = function() {
var extent = geoExtent(bounds_default(selectedDatum));
context.map().centerZoomEase(extent.center(), context.map().trimmedExtentZoom(extent));
};
mode.enter = function() {
behaviors.forEach(context.install);
keybinding.on(_t("inspector.zoom_to.key"), mode.zoomToSelected).on("\u238B", esc, true);
select_default2(document).call(keybinding);
selectData();
var sidebar = context.ui().sidebar;
sidebar.show(dataEditor.datum(selectedDatum));
var extent = geoExtent(bounds_default(selectedDatum));
sidebar.expand(sidebar.intersects(extent));
context.map().on("drawn.select-data", selectData);
};
mode.exit = function() {
behaviors.forEach(context.uninstall);
select_default2(document).call(keybinding.unbind);
context.surface().selectAll(".layer-mapdata .selected").classed("selected hover", false);
context.map().on("drawn.select-data", null);
context.ui().sidebar.hide();
};
return mode;
}
// modules/behavior/select.js
function behaviorSelect(context) {
var _tolerancePx = 4;
var _lastMouseEvent = null;
var _showMenu = false;
var _downPointers = {};
var _longPressTimeout = null;
var _lastInteractionType = null;
var _multiselectionPointerId = null;
var _pointerPrefix = "PointerEvent" in window ? "pointer" : "mouse";
function keydown(d3_event) {
if (d3_event.keyCode === 32) {
var activeNode = document.activeElement;
if (activeNode && (/* @__PURE__ */ new Set(["INPUT", "TEXTAREA"])).has(activeNode.nodeName))
return;
}
if (d3_event.keyCode === 93 || d3_event.keyCode === 32) {
d3_event.preventDefault();
}
if (d3_event.repeat)
return;
cancelLongPress();
if (d3_event.shiftKey) {
context.surface().classed("behavior-multiselect", true);
}
if (d3_event.keyCode === 32) {
if (!_downPointers.spacebar && _lastMouseEvent) {
cancelLongPress();
_longPressTimeout = window.setTimeout(didLongPress, 500, "spacebar", "spacebar");
_downPointers.spacebar = {
firstEvent: _lastMouseEvent,
lastEvent: _lastMouseEvent
};
}
}
}
function keyup(d3_event) {
cancelLongPress();
if (!d3_event.shiftKey) {
context.surface().classed("behavior-multiselect", false);
}
if (d3_event.keyCode === 93) {
d3_event.preventDefault();
_lastInteractionType = "menukey";
contextmenu(d3_event);
} else if (d3_event.keyCode === 32) {
var pointer = _downPointers.spacebar;
if (pointer) {
delete _downPointers.spacebar;
if (pointer.done)
return;
d3_event.preventDefault();
_lastInteractionType = "spacebar";
click(pointer.firstEvent, pointer.lastEvent, "spacebar");
}
}
}
function pointerdown(d3_event) {
var id2 = (d3_event.pointerId || "mouse").toString();
cancelLongPress();
if (d3_event.buttons && d3_event.buttons !== 1)
return;
context.ui().closeEditMenu();
_longPressTimeout = window.setTimeout(didLongPress, 500, id2, "longdown-" + (d3_event.pointerType || "mouse"));
_downPointers[id2] = {
firstEvent: d3_event,
lastEvent: d3_event
};
}
function didLongPress(id2, interactionType) {
var pointer = _downPointers[id2];
if (!pointer)
return;
for (var i2 in _downPointers) {
_downPointers[i2].done = true;
}
_longPressTimeout = null;
_lastInteractionType = interactionType;
_showMenu = true;
click(pointer.firstEvent, pointer.lastEvent, id2);
}
function pointermove(d3_event) {
var id2 = (d3_event.pointerId || "mouse").toString();
if (_downPointers[id2]) {
_downPointers[id2].lastEvent = d3_event;
}
if (!d3_event.pointerType || d3_event.pointerType === "mouse") {
_lastMouseEvent = d3_event;
if (_downPointers.spacebar) {
_downPointers.spacebar.lastEvent = d3_event;
}
}
}
function pointerup(d3_event) {
var id2 = (d3_event.pointerId || "mouse").toString();
var pointer = _downPointers[id2];
if (!pointer)
return;
delete _downPointers[id2];
if (_multiselectionPointerId === id2) {
_multiselectionPointerId = null;
}
if (pointer.done)
return;
click(pointer.firstEvent, d3_event, id2);
}
function pointercancel(d3_event) {
var id2 = (d3_event.pointerId || "mouse").toString();
if (!_downPointers[id2])
return;
delete _downPointers[id2];
if (_multiselectionPointerId === id2) {
_multiselectionPointerId = null;
}
}
function contextmenu(d3_event) {
d3_event.preventDefault();
if (!+d3_event.clientX && !+d3_event.clientY) {
if (_lastMouseEvent) {
d3_event.sourceEvent = _lastMouseEvent;
} else {
return;
}
} else {
_lastMouseEvent = d3_event;
_lastInteractionType = "rightclick";
}
_showMenu = true;
click(d3_event, d3_event);
}
function click(firstEvent, lastEvent, pointerId) {
cancelLongPress();
var mapNode = context.container().select(".main-map").node();
var pointGetter = utilFastMouse(mapNode);
var p1 = pointGetter(firstEvent);
var p2 = pointGetter(lastEvent);
var dist = geoVecLength(p1, p2);
if (dist > _tolerancePx || !mapContains(lastEvent)) {
resetProperties();
return;
}
var targetDatum = lastEvent.target.__data__;
var multiselectEntityId;
if (!_multiselectionPointerId) {
var selectPointerInfo = pointerDownOnSelection(pointerId);
if (selectPointerInfo) {
_multiselectionPointerId = selectPointerInfo.pointerId;
multiselectEntityId = !selectPointerInfo.selected && selectPointerInfo.entityId;
_downPointers[selectPointerInfo.pointerId].done = true;
}
}
var isMultiselect = context.mode().id === "select" && (lastEvent && lastEvent.shiftKey || context.surface().select(".lasso").node() || _multiselectionPointerId && !multiselectEntityId);
processClick(targetDatum, isMultiselect, p2, multiselectEntityId);
function mapContains(event) {
var rect = mapNode.getBoundingClientRect();
return event.clientX >= rect.left && event.clientX <= rect.right && event.clientY >= rect.top && event.clientY <= rect.bottom;
}
function pointerDownOnSelection(skipPointerId) {
var mode = context.mode();
var selectedIDs = mode.id === "select" ? mode.selectedIDs() : [];
for (var pointerId2 in _downPointers) {
if (pointerId2 === "spacebar" || pointerId2 === skipPointerId)
continue;
var pointerInfo = _downPointers[pointerId2];
var p12 = pointGetter(pointerInfo.firstEvent);
var p22 = pointGetter(pointerInfo.lastEvent);
if (geoVecLength(p12, p22) > _tolerancePx)
continue;
var datum2 = pointerInfo.firstEvent.target.__data__;
var entity = datum2 && datum2.properties && datum2.properties.entity || datum2;
if (context.graph().hasEntity(entity.id)) {
return {
pointerId: pointerId2,
entityId: entity.id,
selected: selectedIDs.indexOf(entity.id) !== -1
};
}
}
return null;
}
}
function processClick(datum2, isMultiselect, point, alsoSelectId) {
var mode = context.mode();
var showMenu = _showMenu;
var interactionType = _lastInteractionType;
var entity = datum2 && datum2.properties && datum2.properties.entity;
if (entity)
datum2 = entity;
if (datum2 && datum2.type === "midpoint") {
datum2 = datum2.parents[0];
}
var newMode;
if (datum2 instanceof osmEntity) {
var selectedIDs = context.selectedIDs();
context.selectedNoteID(null);
context.selectedErrorID(null);
if (!isMultiselect) {
if (!showMenu || selectedIDs.length <= 1 || selectedIDs.indexOf(datum2.id) === -1) {
if (alsoSelectId === datum2.id)
alsoSelectId = null;
selectedIDs = (alsoSelectId ? [alsoSelectId] : []).concat([datum2.id]);
newMode = mode.id === "select" ? mode.selectedIDs(selectedIDs) : modeSelect(context, selectedIDs).selectBehavior(behavior);
context.enter(newMode);
}
} else {
if (selectedIDs.indexOf(datum2.id) !== -1) {
if (!showMenu) {
selectedIDs = selectedIDs.filter(function(id2) {
return id2 !== datum2.id;
});
newMode = selectedIDs.length ? mode.selectedIDs(selectedIDs) : modeBrowse(context).selectBehavior(behavior);
context.enter(newMode);
}
} else {
selectedIDs = selectedIDs.concat([datum2.id]);
newMode = mode.selectedIDs(selectedIDs);
context.enter(newMode);
}
}
} else if (datum2 && datum2.__featurehash__ && !isMultiselect) {
context.selectedNoteID(null).enter(modeSelectData(context, datum2));
} else if (datum2 instanceof osmNote && !isMultiselect) {
context.selectedNoteID(datum2.id).enter(modeSelectNote(context, datum2.id));
} else if (datum2 instanceof QAItem && !isMultiselect) {
context.selectedErrorID(datum2.id).enter(modeSelectError(context, datum2.id, datum2.service));
} else {
context.selectedNoteID(null);
context.selectedErrorID(null);
if (!isMultiselect && mode.id !== "browse") {
context.enter(modeBrowse(context));
}
}
context.ui().closeEditMenu();
if (showMenu)
context.ui().showEditMenu(point, interactionType);
resetProperties();
}
function cancelLongPress() {
if (_longPressTimeout)
window.clearTimeout(_longPressTimeout);
_longPressTimeout = null;
}
function resetProperties() {
cancelLongPress();
_showMenu = false;
_lastInteractionType = null;
}
function behavior(selection2) {
resetProperties();
_lastMouseEvent = context.map().lastPointerEvent();
select_default2(window).on("keydown.select", keydown).on("keyup.select", keyup).on(_pointerPrefix + "move.select", pointermove, true).on(_pointerPrefix + "up.select", pointerup, true).on("pointercancel.select", pointercancel, true).on("contextmenu.select-window", function(d3_event) {
var e = d3_event;
if (+e.clientX === 0 && +e.clientY === 0) {
d3_event.preventDefault();
}
});
selection2.on(_pointerPrefix + "down.select", pointerdown).on("contextmenu.select", contextmenu);
}
behavior.off = function(selection2) {
cancelLongPress();
select_default2(window).on("keydown.select", null).on("keyup.select", null).on("contextmenu.select-window", null).on(_pointerPrefix + "move.select", null, true).on(_pointerPrefix + "up.select", null, true).on("pointercancel.select", null, true);
selection2.on(_pointerPrefix + "down.select", null).on("contextmenu.select", null);
context.surface().classed("behavior-multiselect", false);
};
return behavior;
}
// modules/operations/index.js
var operations_exports = {};
__export(operations_exports, {
operationCircularize: () => operationCircularize,
operationContinue: () => operationContinue,
operationCopy: () => operationCopy,
operationDelete: () => operationDelete,
operationDisconnect: () => operationDisconnect,
operationDowngrade: () => operationDowngrade,
operationExtract: () => operationExtract,
operationMerge: () => operationMerge,
operationMove: () => operationMove,
operationOrthogonalize: () => operationOrthogonalize,
operationPaste: () => operationPaste,
operationReflectLong: () => operationReflectLong,
operationReflectShort: () => operationReflectShort,
operationReverse: () => operationReverse,
operationRotate: () => operationRotate,
operationSplit: () => operationSplit,
operationStraighten: () => operationStraighten
});
// modules/operations/continue.js
function operationContinue(context, selectedIDs) {
var _entities = selectedIDs.map(function(id2) {
return context.graph().entity(id2);
});
var _geometries = Object.assign({ line: [], vertex: [] }, utilArrayGroupBy(_entities, function(entity) {
return entity.geometry(context.graph());
}));
var _vertex = _geometries.vertex.length && _geometries.vertex[0];
function candidateWays() {
return _vertex ? context.graph().parentWays(_vertex).filter(function(parent) {
return parent.geometry(context.graph()) === "line" && !parent.isClosed() && parent.affix(_vertex.id) && (_geometries.line.length === 0 || _geometries.line[0] === parent);
}) : [];
}
var _candidates = candidateWays();
var operation = function() {
var candidate = _candidates[0];
context.enter(modeDrawLine(context, candidate.id, context.graph(), "line", candidate.affix(_vertex.id), true));
};
operation.relatedEntityIds = function() {
return _candidates.length ? [_candidates[0].id] : [];
};
operation.available = function() {
return _geometries.vertex.length === 1 && _geometries.line.length <= 1 && !context.features().hasHiddenConnections(_vertex, context.graph());
};
operation.disabled = function() {
if (_candidates.length === 0) {
return "not_eligible";
} else if (_candidates.length > 1) {
return "multiple";
}
return false;
};
operation.tooltip = function() {
var disable = operation.disabled();
return disable ? _t("operations.continue." + disable) : _t("operations.continue.description");
};
operation.annotation = function() {
return _t("operations.continue.annotation.line");
};
operation.id = "continue";
operation.keys = [_t("operations.continue.key")];
operation.title = _t("operations.continue.title");
operation.behavior = behaviorOperation(context).which(operation);
return operation;
}
// modules/operations/copy.js
function operationCopy(context, selectedIDs) {
function getFilteredIdsToCopy() {
return selectedIDs.filter(function(selectedID) {
var entity = context.graph().hasEntity(selectedID);
return entity.hasInterestingTags() || entity.geometry(context.graph()) !== "vertex";
});
}
var operation = function() {
var graph = context.graph();
var selected = groupEntities(getFilteredIdsToCopy(), graph);
var canCopy = [];
var skip = {};
var entity;
var i2;
for (i2 = 0; i2 < selected.relation.length; i2++) {
entity = selected.relation[i2];
if (!skip[entity.id] && entity.isComplete(graph)) {
canCopy.push(entity.id);
skip = getDescendants(entity.id, graph, skip);
}
}
for (i2 = 0; i2 < selected.way.length; i2++) {
entity = selected.way[i2];
if (!skip[entity.id]) {
canCopy.push(entity.id);
skip = getDescendants(entity.id, graph, skip);
}
}
for (i2 = 0; i2 < selected.node.length; i2++) {
entity = selected.node[i2];
if (!skip[entity.id]) {
canCopy.push(entity.id);
}
}
context.copyIDs(canCopy);
if (_point && (canCopy.length !== 1 || graph.entity(canCopy[0]).type !== "node")) {
context.copyLonLat(context.projection.invert(_point));
} else {
context.copyLonLat(null);
}
};
function groupEntities(ids, graph) {
var entities = ids.map(function(id2) {
return graph.entity(id2);
});
return Object.assign({ relation: [], way: [], node: [] }, utilArrayGroupBy(entities, "type"));
}
function getDescendants(id2, graph, descendants) {
var entity = graph.entity(id2);
var children2;
descendants = descendants || {};
if (entity.type === "relation") {
children2 = entity.members.map(function(m) {
return m.id;
});
} else if (entity.type === "way") {
children2 = entity.nodes;
} else {
children2 = [];
}
for (var i2 = 0; i2 < children2.length; i2++) {
if (!descendants[children2[i2]]) {
descendants[children2[i2]] = true;
descendants = getDescendants(children2[i2], graph, descendants);
}
}
return descendants;
}
operation.available = function() {
return getFilteredIdsToCopy().length > 0;
};
operation.disabled = function() {
var extent = utilTotalExtent(getFilteredIdsToCopy(), context.graph());
if (extent.percentContainedIn(context.map().extent()) < 0.8) {
return "too_large";
}
return false;
};
operation.availableForKeypress = function() {
var selection2 = window.getSelection && window.getSelection();
return !selection2 || !selection2.toString();
};
operation.tooltip = function() {
var disable = operation.disabled();
return disable ? _t("operations.copy." + disable, { n: selectedIDs.length }) : _t("operations.copy.description", { n: selectedIDs.length });
};
operation.annotation = function() {
return _t("operations.copy.annotation", { n: selectedIDs.length });
};
var _point;
operation.point = function(val) {
_point = val;
return operation;
};
operation.id = "copy";
operation.keys = [uiCmd("\u2318C")];
operation.title = _t("operations.copy.title");
operation.behavior = behaviorOperation(context).which(operation);
return operation;
}
// modules/operations/disconnect.js
function operationDisconnect(context, selectedIDs) {
var _vertexIDs = [];
var _wayIDs = [];
var _otherIDs = [];
var _actions = [];
selectedIDs.forEach(function(id2) {
var entity = context.entity(id2);
if (entity.type === "way") {
_wayIDs.push(id2);
} else if (entity.geometry(context.graph()) === "vertex") {
_vertexIDs.push(id2);
} else {
_otherIDs.push(id2);
}
});
var _coords, _descriptionID = "", _annotationID = "features";
var _disconnectingVertexIds = [];
var _disconnectingWayIds = [];
if (_vertexIDs.length > 0) {
_disconnectingVertexIds = _vertexIDs;
_vertexIDs.forEach(function(vertexID) {
var action = actionDisconnect(vertexID);
if (_wayIDs.length > 0) {
var waysIDsForVertex = _wayIDs.filter(function(wayID) {
var way = context.entity(wayID);
return way.nodes.indexOf(vertexID) !== -1;
});
action.limitWays(waysIDsForVertex);
}
_actions.push(action);
_disconnectingWayIds = _disconnectingWayIds.concat(context.graph().parentWays(context.graph().entity(vertexID)).map((d) => d.id));
});
_disconnectingWayIds = utilArrayUniq(_disconnectingWayIds).filter(function(id2) {
return _wayIDs.indexOf(id2) === -1;
});
_descriptionID += _actions.length === 1 ? "single_point." : "multiple_points.";
if (_wayIDs.length === 1) {
_descriptionID += "single_way." + context.graph().geometry(_wayIDs[0]);
} else {
_descriptionID += _wayIDs.length === 0 ? "no_ways" : "multiple_ways";
}
} else if (_wayIDs.length > 0) {
var ways = _wayIDs.map(function(id2) {
return context.entity(id2);
});
var nodes = utilGetAllNodes(_wayIDs, context.graph());
_coords = nodes.map(function(n2) {
return n2.loc;
});
var sharedActions = [];
var sharedNodes = [];
var unsharedActions = [];
var unsharedNodes = [];
nodes.forEach(function(node) {
var action = actionDisconnect(node.id).limitWays(_wayIDs);
if (action.disabled(context.graph()) !== "not_connected") {
var count = 0;
for (var i2 in ways) {
var way = ways[i2];
if (way.nodes.indexOf(node.id) !== -1) {
count += 1;
}
if (count > 1)
break;
}
if (count > 1) {
sharedActions.push(action);
sharedNodes.push(node);
} else {
unsharedActions.push(action);
unsharedNodes.push(node);
}
}
});
_descriptionID += "no_points.";
_descriptionID += _wayIDs.length === 1 ? "single_way." : "multiple_ways.";
if (sharedActions.length) {
_actions = sharedActions;
_disconnectingVertexIds = sharedNodes.map((node) => node.id);
_descriptionID += "conjoined";
_annotationID = "from_each_other";
} else {
_actions = unsharedActions;
_disconnectingVertexIds = unsharedNodes.map((node) => node.id);
if (_wayIDs.length === 1) {
_descriptionID += context.graph().geometry(_wayIDs[0]);
} else {
_descriptionID += "separate";
}
}
}
var _extent = utilTotalExtent(_disconnectingVertexIds, context.graph());
var operation = function() {
context.perform(function(graph) {
return _actions.reduce(function(graph2, action) {
return action(graph2);
}, graph);
}, operation.annotation());
context.validator().validate();
};
operation.relatedEntityIds = function() {
if (_vertexIDs.length) {
return _disconnectingWayIds;
}
return _disconnectingVertexIds;
};
operation.available = function() {
if (_actions.length === 0)
return false;
if (_otherIDs.length !== 0)
return false;
if (_vertexIDs.length !== 0 && _wayIDs.length !== 0 && !_wayIDs.every(function(wayID) {
return _vertexIDs.some(function(vertexID) {
var way = context.entity(wayID);
return way.nodes.indexOf(vertexID) !== -1;
});
}))
return false;
return true;
};
operation.disabled = function() {
var reason;
for (var actionIndex in _actions) {
reason = _actions[actionIndex].disabled(context.graph());
if (reason)
return reason;
}
if (_extent && _extent.percentContainedIn(context.map().extent()) < 0.8) {
return "too_large." + ((_vertexIDs.length ? _vertexIDs : _wayIDs).length === 1 ? "single" : "multiple");
} else if (_coords && someMissing()) {
return "not_downloaded";
} else if (selectedIDs.some(context.hasHiddenConnections)) {
return "connected_to_hidden";
}
return false;
function someMissing() {
if (context.inIntro())
return false;
var osm = context.connection();
if (osm) {
var missing = _coords.filter(function(loc) {
return !osm.isDataLoaded(loc);
});
if (missing.length) {
missing.forEach(function(loc) {
context.loadTileAtLoc(loc);
});
return true;
}
}
return false;
}
};
operation.tooltip = function() {
var disable = operation.disabled();
if (disable) {
return _t("operations.disconnect." + disable);
}
return _t("operations.disconnect.description." + _descriptionID);
};
operation.annotation = function() {
return _t("operations.disconnect.annotation." + _annotationID);
};
operation.id = "disconnect";
operation.keys = [_t("operations.disconnect.key")];
operation.title = _t("operations.disconnect.title");
operation.behavior = behaviorOperation(context).which(operation);
return operation;
}
// modules/operations/downgrade.js
function operationDowngrade(context, selectedIDs) {
var _affectedFeatureCount = 0;
var _downgradeType = downgradeTypeForEntityIDs(selectedIDs);
var _multi = _affectedFeatureCount === 1 ? "single" : "multiple";
function downgradeTypeForEntityIDs(entityIds) {
var downgradeType;
_affectedFeatureCount = 0;
for (var i2 in entityIds) {
var entityID = entityIds[i2];
var type3 = downgradeTypeForEntityID(entityID);
if (type3) {
_affectedFeatureCount += 1;
if (downgradeType && type3 !== downgradeType) {
if (downgradeType !== "generic" && type3 !== "generic") {
downgradeType = "building_address";
} else {
downgradeType = "generic";
}
} else {
downgradeType = type3;
}
}
}
return downgradeType;
}
function downgradeTypeForEntityID(entityID) {
var graph = context.graph();
var entity = graph.entity(entityID);
var preset = _mainPresetIndex.match(entity, graph);
if (!preset || preset.isFallback())
return null;
if (entity.type === "node" && preset.id !== "address" && Object.keys(entity.tags).some(function(key) {
return key.match(/^addr:.{1,}/);
})) {
return "address";
}
var geometry = entity.geometry(graph);
if (geometry === "area" && entity.tags.building && !preset.tags.building) {
return "building";
}
if (geometry === "vertex" && Object.keys(entity.tags).length) {
return "generic";
}
return null;
}
var buildingKeysToKeep = ["architect", "building", "height", "layer", "source", "type", "wheelchair"];
var addressKeysToKeep = ["source"];
var operation = function() {
context.perform(function(graph) {
for (var i2 in selectedIDs) {
var entityID = selectedIDs[i2];
var type3 = downgradeTypeForEntityID(entityID);
if (!type3)
continue;
var tags = Object.assign({}, graph.entity(entityID).tags);
for (var key in tags) {
if (type3 === "address" && addressKeysToKeep.indexOf(key) !== -1)
continue;
if (type3 === "building") {
if (buildingKeysToKeep.indexOf(key) !== -1 || key.match(/^building:.{1,}/) || key.match(/^roof:.{1,}/))
continue;
}
if (type3 !== "generic") {
if (key.match(/^addr:.{1,}/) || key.match(/^source:.{1,}/))
continue;
}
delete tags[key];
}
graph = actionChangeTags(entityID, tags)(graph);
}
return graph;
}, operation.annotation());
context.validator().validate();
context.enter(modeSelect(context, selectedIDs));
};
operation.available = function() {
return _downgradeType;
};
operation.disabled = function() {
if (selectedIDs.some(hasWikidataTag)) {
return "has_wikidata_tag";
}
return false;
function hasWikidataTag(id2) {
var entity = context.entity(id2);
return entity.tags.wikidata && entity.tags.wikidata.trim().length > 0;
}
};
operation.tooltip = function() {
var disable = operation.disabled();
return disable ? _t("operations.downgrade." + disable + "." + _multi) : _t("operations.downgrade.description." + _downgradeType);
};
operation.annotation = function() {
var suffix;
if (_downgradeType === "building_address") {
suffix = "generic";
} else {
suffix = _downgradeType;
}
return _t("operations.downgrade.annotation." + suffix, { n: _affectedFeatureCount });
};
operation.id = "downgrade";
operation.keys = [uiCmd("\u232B")];
operation.title = _t("operations.downgrade.title");
operation.behavior = behaviorOperation(context).which(operation);
return operation;
}
// modules/operations/extract.js
function operationExtract(context, selectedIDs) {
var _amount = selectedIDs.length === 1 ? "single" : "multiple";
var _geometries = utilArrayUniq(selectedIDs.map(function(entityID) {
return context.graph().hasEntity(entityID) && context.graph().geometry(entityID);
}).filter(Boolean));
var _geometryID = _geometries.length === 1 ? _geometries[0] : "feature";
var _extent;
var _actions = selectedIDs.map(function(entityID) {
var graph = context.graph();
var entity = graph.hasEntity(entityID);
if (!entity || !entity.hasInterestingTags())
return null;
if (entity.type === "node" && graph.parentWays(entity).length === 0)
return null;
if (entity.type !== "node") {
var preset = _mainPresetIndex.match(entity, graph);
if (preset.geometry.indexOf("point") === -1)
return null;
}
_extent = _extent ? _extent.extend(entity.extent(graph)) : entity.extent(graph);
return actionExtract(entityID, context.projection);
}).filter(Boolean);
var operation = function() {
var combinedAction = function(graph) {
_actions.forEach(function(action) {
graph = action(graph);
});
return graph;
};
context.perform(combinedAction, operation.annotation());
var extractedNodeIDs = _actions.map(function(action) {
return action.getExtractedNodeID();
});
context.enter(modeSelect(context, extractedNodeIDs));
};
operation.available = function() {
return _actions.length && selectedIDs.length === _actions.length;
};
operation.disabled = function() {
if (_extent && _extent.percentContainedIn(context.map().extent()) < 0.8) {
return "too_large";
} else if (selectedIDs.some(function(entityID) {
return context.graph().geometry(entityID) === "vertex" && context.hasHiddenConnections(entityID);
})) {
return "connected_to_hidden";
}
return false;
};
operation.tooltip = function() {
var disableReason = operation.disabled();
if (disableReason) {
return _t("operations.extract." + disableReason + "." + _amount);
} else {
return _t("operations.extract.description." + _geometryID + "." + _amount);
}
};
operation.annotation = function() {
return _t("operations.extract.annotation", { n: selectedIDs.length });
};
operation.id = "extract";
operation.keys = [_t("operations.extract.key")];
operation.title = _t("operations.extract.title");
operation.behavior = behaviorOperation(context).which(operation);
return operation;
}
// modules/operations/merge.js
function operationMerge(context, selectedIDs) {
var _action = getAction();
function getAction() {
var join = actionJoin(selectedIDs);
if (!join.disabled(context.graph()))
return join;
var merge3 = actionMerge(selectedIDs);
if (!merge3.disabled(context.graph()))
return merge3;
var mergePolygon = actionMergePolygon(selectedIDs);
if (!mergePolygon.disabled(context.graph()))
return mergePolygon;
var mergeNodes = actionMergeNodes(selectedIDs);
if (!mergeNodes.disabled(context.graph()))
return mergeNodes;
if (join.disabled(context.graph()) !== "not_eligible")
return join;
if (merge3.disabled(context.graph()) !== "not_eligible")
return merge3;
if (mergePolygon.disabled(context.graph()) !== "not_eligible")
return mergePolygon;
return mergeNodes;
}
var operation = function() {
if (operation.disabled())
return;
context.perform(_action, operation.annotation());
context.validator().validate();
var resultIDs = selectedIDs.filter(context.hasEntity);
if (resultIDs.length > 1) {
var interestingIDs = resultIDs.filter(function(id2) {
return context.entity(id2).hasInterestingTags();
});
if (interestingIDs.length)
resultIDs = interestingIDs;
}
context.enter(modeSelect(context, resultIDs));
};
operation.available = function() {
return selectedIDs.length >= 2;
};
operation.disabled = function() {
var actionDisabled = _action.disabled(context.graph());
if (actionDisabled)
return actionDisabled;
var osm = context.connection();
if (osm && _action.resultingWayNodesLength && _action.resultingWayNodesLength(context.graph()) > osm.maxWayNodes()) {
return "too_many_vertices";
}
return false;
};
operation.tooltip = function() {
var disabled = operation.disabled();
if (disabled) {
if (disabled === "conflicting_relations") {
return _t("operations.merge.conflicting_relations");
}
if (disabled === "restriction" || disabled === "connectivity") {
return _t("operations.merge.damage_relation", { relation: _mainPresetIndex.item("type/" + disabled).name() });
}
return _t("operations.merge." + disabled);
}
return _t("operations.merge.description");
};
operation.annotation = function() {
return _t("operations.merge.annotation", { n: selectedIDs.length });
};
operation.id = "merge";
operation.keys = [_t("operations.merge.key")];
operation.title = _t("operations.merge.title");
operation.behavior = behaviorOperation(context).which(operation);
return operation;
}
// modules/operations/paste.js
function operationPaste(context) {
var _pastePoint;
var operation = function() {
if (!_pastePoint)
return;
var oldIDs = context.copyIDs();
if (!oldIDs.length)
return;
var projection2 = context.projection;
var extent = geoExtent();
var oldGraph = context.copyGraph();
var newIDs = [];
var action = actionCopyEntities(oldIDs, oldGraph);
context.perform(action);
var copies = action.copies();
var originals = /* @__PURE__ */ new Set();
Object.values(copies).forEach(function(entity) {
originals.add(entity.id);
});
for (var id2 in copies) {
var oldEntity = oldGraph.entity(id2);
var newEntity = copies[id2];
extent._extend(oldEntity.extent(oldGraph));
var parents = context.graph().parentWays(newEntity);
var parentCopied = parents.some(function(parent) {
return originals.has(parent.id);
});
if (!parentCopied) {
newIDs.push(newEntity.id);
}
}
var copyPoint = context.copyLonLat() && projection2(context.copyLonLat()) || projection2(extent.center());
var delta = geoVecSubtract(_pastePoint, copyPoint);
context.replace(actionMove(newIDs, delta, projection2), operation.annotation());
context.enter(modeSelect(context, newIDs));
};
operation.point = function(val) {
_pastePoint = val;
return operation;
};
operation.available = function() {
return context.mode().id === "browse";
};
operation.disabled = function() {
return !context.copyIDs().length;
};
operation.tooltip = function() {
var oldGraph = context.copyGraph();
var ids = context.copyIDs();
if (!ids.length) {
return _t("operations.paste.nothing_copied");
}
return _t("operations.paste.description", { feature: utilDisplayLabel(oldGraph.entity(ids[0]), oldGraph), n: ids.length });
};
operation.annotation = function() {
var ids = context.copyIDs();
return _t("operations.paste.annotation", { n: ids.length });
};
operation.id = "paste";
operation.keys = [uiCmd("\u2318V")];
operation.title = _t("operations.paste.title");
return operation;
}
// modules/operations/reverse.js
function operationReverse(context, selectedIDs) {
var operation = function() {
context.perform(function combinedReverseAction(graph) {
actions().forEach(function(action) {
graph = action(graph);
});
return graph;
}, operation.annotation());
context.validator().validate();
};
function actions(situation) {
return selectedIDs.map(function(entityID) {
var entity = context.hasEntity(entityID);
if (!entity)
return null;
if (situation === "toolbar") {
if (entity.type === "way" && (!entity.isOneWay() && !entity.isSided()))
return null;
}
var geometry = entity.geometry(context.graph());
if (entity.type !== "node" && geometry !== "line")
return null;
var action = actionReverse(entityID);
if (action.disabled(context.graph()))
return null;
return action;
}).filter(Boolean);
}
function reverseTypeID() {
var acts = actions();
var nodeActionCount = acts.filter(function(act) {
var entity = context.hasEntity(act.entityID());
return entity && entity.type === "node";
}).length;
if (nodeActionCount === 0)
return "line";
if (nodeActionCount === acts.length)
return "point";
return "feature";
}
operation.available = function(situation) {
return actions(situation).length > 0;
};
operation.disabled = function() {
return false;
};
operation.tooltip = function() {
return _t("operations.reverse.description." + reverseTypeID());
};
operation.annotation = function() {
var acts = actions();
return _t("operations.reverse.annotation." + reverseTypeID(), { n: acts.length });
};
operation.id = "reverse";
operation.keys = [_t("operations.reverse.key")];
operation.title = _t("operations.reverse.title");
operation.behavior = behaviorOperation(context).which(operation);
return operation;
}
// modules/operations/split.js
function operationSplit(context, selectedIDs) {
var _vertexIds = selectedIDs.filter(function(id2) {
return context.graph().geometry(id2) === "vertex";
});
var _selectedWayIds = selectedIDs.filter(function(id2) {
var entity = context.graph().hasEntity(id2);
return entity && entity.type === "way";
});
var _isAvailable = _vertexIds.length > 0 && _vertexIds.length + _selectedWayIds.length === selectedIDs.length;
var _action = actionSplit(_vertexIds);
var _ways = [];
var _geometry = "feature";
var _waysAmount = "single";
var _nodesAmount = _vertexIds.length === 1 ? "single" : "multiple";
if (_isAvailable) {
if (_selectedWayIds.length)
_action.limitWays(_selectedWayIds);
_ways = _action.ways(context.graph());
var geometries = {};
_ways.forEach(function(way) {
geometries[way.geometry(context.graph())] = true;
});
if (Object.keys(geometries).length === 1) {
_geometry = Object.keys(geometries)[0];
}
_waysAmount = _ways.length === 1 ? "single" : "multiple";
}
var operation = function() {
var difference = context.perform(_action, operation.annotation());
var idsToSelect = _vertexIds.concat(difference.extantIDs().filter(function(id2) {
return context.entity(id2).type === "way";
}));
context.enter(modeSelect(context, idsToSelect));
};
operation.relatedEntityIds = function() {
return _selectedWayIds.length ? [] : _ways.map((way) => way.id);
};
operation.available = function() {
return _isAvailable;
};
operation.disabled = function() {
var reason = _action.disabled(context.graph());
if (reason) {
return reason;
} else if (selectedIDs.some(context.hasHiddenConnections)) {
return "connected_to_hidden";
}
return false;
};
operation.tooltip = function() {
var disable = operation.disabled();
if (disable)
return _t("operations.split." + disable);
return _t("operations.split.description." + _geometry + "." + _waysAmount + "." + _nodesAmount + "_node");
};
operation.annotation = function() {
return _t("operations.split.annotation." + _geometry, { n: _ways.length });
};
operation.icon = function() {
if (_waysAmount === "multiple") {
return "#iD-operation-split-multiple";
} else {
return "#iD-operation-split";
}
};
operation.id = "split";
operation.keys = [_t("operations.split.key")];
operation.title = _t("operations.split.title");
operation.behavior = behaviorOperation(context).which(operation);
return operation;
}
// modules/operations/straighten.js
function operationStraighten(context, selectedIDs) {
var _wayIDs = selectedIDs.filter(function(id2) {
return id2.charAt(0) === "w";
});
var _nodeIDs = selectedIDs.filter(function(id2) {
return id2.charAt(0) === "n";
});
var _amount = (_wayIDs.length ? _wayIDs : _nodeIDs).length === 1 ? "single" : "multiple";
var _nodes = utilGetAllNodes(selectedIDs, context.graph());
var _coords = _nodes.map(function(n2) {
return n2.loc;
});
var _extent = utilTotalExtent(selectedIDs, context.graph());
var _action = chooseAction();
var _geometry;
function chooseAction() {
if (_wayIDs.length === 0 && _nodeIDs.length > 2) {
_geometry = "point";
return actionStraightenNodes(_nodeIDs, context.projection);
} else if (_wayIDs.length > 0 && (_nodeIDs.length === 0 || _nodeIDs.length === 2)) {
var startNodeIDs = [];
var endNodeIDs = [];
for (var i2 = 0; i2 < selectedIDs.length; i2++) {
var entity = context.entity(selectedIDs[i2]);
if (entity.type === "node") {
continue;
} else if (entity.type !== "way" || entity.isClosed()) {
return null;
}
startNodeIDs.push(entity.first());
endNodeIDs.push(entity.last());
}
startNodeIDs = startNodeIDs.filter(function(n2) {
return startNodeIDs.indexOf(n2) === startNodeIDs.lastIndexOf(n2);
});
endNodeIDs = endNodeIDs.filter(function(n2) {
return endNodeIDs.indexOf(n2) === endNodeIDs.lastIndexOf(n2);
});
if (utilArrayDifference(startNodeIDs, endNodeIDs).length + utilArrayDifference(endNodeIDs, startNodeIDs).length !== 2)
return null;
var wayNodeIDs = utilGetAllNodes(_wayIDs, context.graph()).map(function(node) {
return node.id;
});
if (wayNodeIDs.length <= 2)
return null;
if (_nodeIDs.length === 2 && (wayNodeIDs.indexOf(_nodeIDs[0]) === -1 || wayNodeIDs.indexOf(_nodeIDs[1]) === -1))
return null;
if (_nodeIDs.length) {
_extent = utilTotalExtent(_nodeIDs, context.graph());
}
_geometry = "line";
return actionStraightenWay(selectedIDs, context.projection);
}
return null;
}
function operation() {
if (!_action)
return;
context.perform(_action, operation.annotation());
window.setTimeout(function() {
context.validator().validate();
}, 300);
}
operation.available = function() {
return Boolean(_action);
};
operation.disabled = function() {
var reason = _action.disabled(context.graph());
if (reason) {
return reason;
} else if (_extent.percentContainedIn(context.map().extent()) < 0.8) {
return "too_large";
} else if (someMissing()) {
return "not_downloaded";
} else if (selectedIDs.some(context.hasHiddenConnections)) {
return "connected_to_hidden";
}
return false;
function someMissing() {
if (context.inIntro())
return false;
var osm = context.connection();
if (osm) {
var missing = _coords.filter(function(loc) {
return !osm.isDataLoaded(loc);
});
if (missing.length) {
missing.forEach(function(loc) {
context.loadTileAtLoc(loc);
});
return true;
}
}
return false;
}
};
operation.tooltip = function() {
var disable = operation.disabled();
return disable ? _t("operations.straighten." + disable + "." + _amount) : _t("operations.straighten.description." + _geometry + (_wayIDs.length === 1 ? "" : "s"));
};
operation.annotation = function() {
return _t("operations.straighten.annotation." + _geometry, { n: _wayIDs.length ? _wayIDs.length : _nodeIDs.length });
};
operation.id = "straighten";
operation.keys = [_t("operations.straighten.key")];
operation.title = _t("operations.straighten.title");
operation.behavior = behaviorOperation(context).which(operation);
return operation;
}
// modules/modes/select.js
function modeSelect(context, selectedIDs) {
var mode = {
id: "select",
button: "browse"
};
var keybinding = utilKeybinding("select");
var _breatheBehavior = behaviorBreathe(context);
var _modeDragNode = modeDragNode(context);
var _selectBehavior;
var _behaviors = [];
var _operations = [];
var _newFeature = false;
var _follow = false;
var _focusedParentWayId;
var _focusedVertexIds;
function singular() {
if (selectedIDs && selectedIDs.length === 1) {
return context.hasEntity(selectedIDs[0]);
}
}
function selectedEntities() {
return selectedIDs.map(function(id2) {
return context.hasEntity(id2);
}).filter(Boolean);
}
function checkSelectedIDs() {
var ids = [];
if (Array.isArray(selectedIDs)) {
ids = selectedIDs.filter(function(id2) {
return context.hasEntity(id2);
});
}
if (!ids.length) {
context.enter(modeBrowse(context));
return false;
} else if (selectedIDs.length > 1 && ids.length === 1 || selectedIDs.length === 1 && ids.length > 1) {
context.enter(modeSelect(context, ids));
return false;
}
selectedIDs = ids;
return true;
}
function parentWaysIdsOfSelection(onlyCommonParents) {
var graph = context.graph();
var parents = [];
for (var i2 = 0; i2 < selectedIDs.length; i2++) {
var entity = context.hasEntity(selectedIDs[i2]);
if (!entity || entity.geometry(graph) !== "vertex") {
return [];
}
var currParents = graph.parentWays(entity).map(function(w) {
return w.id;
});
if (!parents.length) {
parents = currParents;
continue;
}
parents = (onlyCommonParents ? utilArrayIntersection : utilArrayUnion)(parents, currParents);
if (!parents.length) {
return [];
}
}
return parents;
}
function childNodeIdsOfSelection(onlyCommon) {
var graph = context.graph();
var childs = [];
for (var i2 = 0; i2 < selectedIDs.length; i2++) {
var entity = context.hasEntity(selectedIDs[i2]);
if (!entity || !["area", "line"].includes(entity.geometry(graph))) {
return [];
}
var currChilds = graph.childNodes(entity).map(function(node) {
return node.id;
});
if (!childs.length) {
childs = currChilds;
continue;
}
childs = (onlyCommon ? utilArrayIntersection : utilArrayUnion)(childs, currChilds);
if (!childs.length) {
return [];
}
}
return childs;
}
function checkFocusedParent() {
if (_focusedParentWayId) {
var parents = parentWaysIdsOfSelection(true);
if (parents.indexOf(_focusedParentWayId) === -1)
_focusedParentWayId = null;
}
}
function parentWayIdForVertexNavigation() {
var parentIds = parentWaysIdsOfSelection(true);
if (_focusedParentWayId && parentIds.indexOf(_focusedParentWayId) !== -1) {
return _focusedParentWayId;
}
return parentIds.length ? parentIds[0] : null;
}
mode.selectedIDs = function(val) {
if (!arguments.length)
return selectedIDs;
selectedIDs = val;
return mode;
};
mode.zoomToSelected = function() {
context.map().zoomToEase(selectedEntities());
};
mode.newFeature = function(val) {
if (!arguments.length)
return _newFeature;
_newFeature = val;
return mode;
};
mode.selectBehavior = function(val) {
if (!arguments.length)
return _selectBehavior;
_selectBehavior = val;
return mode;
};
mode.follow = function(val) {
if (!arguments.length)
return _follow;
_follow = val;
return mode;
};
function loadOperations() {
_operations.forEach(function(operation) {
if (operation.behavior) {
context.uninstall(operation.behavior);
}
});
_operations = Object.values(operations_exports).map(function(o) {
return o(context, selectedIDs);
}).filter(function(o) {
return o.id !== "delete" && o.id !== "downgrade" && o.id !== "copy";
}).concat([
operationCopy(context, selectedIDs),
operationDowngrade(context, selectedIDs),
operationDelete(context, selectedIDs)
]).filter(function(operation) {
return operation.available();
});
_operations.forEach(function(operation) {
if (operation.behavior) {
context.install(operation.behavior);
}
});
context.ui().closeEditMenu();
}
mode.operations = function() {
return _operations;
};
mode.enter = function() {
if (!checkSelectedIDs())
return;
context.features().forceVisible(selectedIDs);
_modeDragNode.restoreSelectedIDs(selectedIDs);
loadOperations();
if (!_behaviors.length) {
if (!_selectBehavior)
_selectBehavior = behaviorSelect(context);
_behaviors = [
behaviorPaste(context),
_breatheBehavior,
behaviorHover(context).on("hover", context.ui().sidebar.hoverModeSelect),
_selectBehavior,
behaviorLasso(context),
_modeDragNode.behavior,
modeDragNote(context).behavior
];
}
_behaviors.forEach(context.install);
keybinding.on(_t("inspector.zoom_to.key"), mode.zoomToSelected).on(["[", "pgup"], previousVertex).on(["]", "pgdown"], nextVertex).on(["{", uiCmd("\u2318["), "home"], firstVertex).on(["}", uiCmd("\u2318]"), "end"], lastVertex).on(uiCmd("\u21E7\u2190"), nudgeSelection([-10, 0])).on(uiCmd("\u21E7\u2191"), nudgeSelection([0, -10])).on(uiCmd("\u21E7\u2192"), nudgeSelection([10, 0])).on(uiCmd("\u21E7\u2193"), nudgeSelection([0, 10])).on(uiCmd("\u21E7\u2325\u2190"), nudgeSelection([-100, 0])).on(uiCmd("\u21E7\u2325\u2191"), nudgeSelection([0, -100])).on(uiCmd("\u21E7\u2325\u2192"), nudgeSelection([100, 0])).on(uiCmd("\u21E7\u2325\u2193"), nudgeSelection([0, 100])).on(utilKeybinding.plusKeys.map((key) => uiCmd("\u21E7" + key)), scaleSelection(1.05)).on(utilKeybinding.plusKeys.map((key) => uiCmd("\u21E7\u2325" + key)), scaleSelection(Math.pow(1.05, 5))).on(utilKeybinding.minusKeys.map((key) => uiCmd("\u21E7" + key)), scaleSelection(1 / 1.05)).on(utilKeybinding.minusKeys.map((key) => uiCmd("\u21E7\u2325" + key)), scaleSelection(1 / Math.pow(1.05, 5))).on(["\\", "pause"], focusNextParent).on(uiCmd("\u2318\u2191"), selectParent).on(uiCmd("\u2318\u2193"), selectChild).on("\u238B", esc, true);
select_default2(document).call(keybinding);
context.ui().sidebar.select(selectedIDs, _newFeature);
context.history().on("change.select", function() {
loadOperations();
selectElements();
}).on("undone.select", checkSelectedIDs).on("redone.select", checkSelectedIDs);
context.map().on("drawn.select", selectElements).on("crossEditableZoom.select", function() {
selectElements();
_breatheBehavior.restartIfNeeded(context.surface());
});
context.map().doubleUpHandler().on("doubleUp.modeSelect", didDoubleUp);
selectElements();
if (_follow) {
var extent = geoExtent();
var graph = context.graph();
selectedIDs.forEach(function(id2) {
var entity = context.entity(id2);
extent._extend(entity.extent(graph));
});
var loc = extent.center();
context.map().centerEase(loc);
_follow = false;
}
function nudgeSelection(delta) {
return function() {
if (!context.map().withinEditableZoom())
return;
var moveOp = operationMove(context, selectedIDs);
if (moveOp.disabled()) {
context.ui().flash.duration(4e3).iconName("#iD-operation-" + moveOp.id).iconClass("operation disabled").label(moveOp.tooltip)();
} else {
context.perform(actionMove(selectedIDs, delta, context.projection), moveOp.annotation());
context.validator().validate();
}
};
}
function scaleSelection(factor) {
return function() {
if (!context.map().withinEditableZoom())
return;
let nodes = utilGetAllNodes(selectedIDs, context.graph());
let isUp = factor > 1;
if (nodes.length <= 1)
return;
let extent2 = utilTotalExtent(selectedIDs, context.graph());
function scalingDisabled() {
if (tooSmall()) {
return "too_small";
} else if (extent2.percentContainedIn(context.map().extent()) < 0.8) {
return "too_large";
} else if (someMissing() || selectedIDs.some(incompleteRelation)) {
return "not_downloaded";
} else if (selectedIDs.some(context.hasHiddenConnections)) {
return "connected_to_hidden";
}
return false;
function tooSmall() {
if (isUp)
return false;
let dLon = Math.abs(extent2[1][0] - extent2[0][0]);
let dLat = Math.abs(extent2[1][1] - extent2[0][1]);
return dLon < geoMetersToLon(1, extent2[1][1]) && dLat < geoMetersToLat(1);
}
function someMissing() {
if (context.inIntro())
return false;
let osm = context.connection();
if (osm) {
let missing = nodes.filter(function(n2) {
return !osm.isDataLoaded(n2.loc);
});
if (missing.length) {
missing.forEach(function(loc2) {
context.loadTileAtLoc(loc2);
});
return true;
}
}
return false;
}
function incompleteRelation(id2) {
let entity = context.entity(id2);
return entity.type === "relation" && !entity.isComplete(context.graph());
}
}
const disabled = scalingDisabled();
if (disabled) {
let multi = selectedIDs.length === 1 ? "single" : "multiple";
context.ui().flash.duration(4e3).iconName("#iD-icon-no").iconClass("operation disabled").label(_t.html("operations.scale." + disabled + "." + multi))();
} else {
const pivot = context.projection(extent2.center());
const annotation = _t("operations.scale.annotation." + (isUp ? "up" : "down") + ".feature", { n: selectedIDs.length });
context.perform(actionScale(selectedIDs, pivot, factor, context.projection), annotation);
context.validator().validate();
}
};
}
function didDoubleUp(d3_event, loc2) {
if (!context.map().withinEditableZoom())
return;
var target = select_default2(d3_event.target);
var datum2 = target.datum();
var entity = datum2 && datum2.properties && datum2.properties.entity;
if (!entity)
return;
if (entity instanceof osmWay && target.classed("target")) {
var choice = geoChooseEdge(context.graph().childNodes(entity), loc2, context.projection);
var prev = entity.nodes[choice.index - 1];
var next = entity.nodes[choice.index];
context.perform(actionAddMidpoint({ loc: choice.loc, edge: [prev, next] }, osmNode()), _t("operations.add.annotation.vertex"));
context.validator().validate();
} else if (entity.type === "midpoint") {
context.perform(actionAddMidpoint({ loc: entity.loc, edge: entity.edge }, osmNode()), _t("operations.add.annotation.vertex"));
context.validator().validate();
}
}
function selectElements() {
if (!checkSelectedIDs())
return;
var surface = context.surface();
surface.selectAll(".selected-member").classed("selected-member", false);
surface.selectAll(".selected").classed("selected", false);
surface.selectAll(".related").classed("related", false);
checkFocusedParent();
if (_focusedParentWayId) {
surface.selectAll(utilEntitySelector([_focusedParentWayId])).classed("related", true);
}
if (context.map().withinEditableZoom()) {
surface.selectAll(utilDeepMemberSelector(selectedIDs, context.graph(), true)).classed("selected-member", true);
surface.selectAll(utilEntityOrDeepMemberSelector(selectedIDs, context.graph())).classed("selected", true);
}
}
function esc() {
if (context.container().select(".combobox").size())
return;
context.enter(modeBrowse(context));
}
function firstVertex(d3_event) {
d3_event.preventDefault();
var entity = singular();
var parentId = parentWayIdForVertexNavigation();
var way;
if (entity && entity.type === "way") {
way = entity;
} else if (parentId) {
way = context.entity(parentId);
}
_focusedParentWayId = way && way.id;
if (way) {
context.enter(mode.selectedIDs([way.first()]).follow(true));
}
}
function lastVertex(d3_event) {
d3_event.preventDefault();
var entity = singular();
var parentId = parentWayIdForVertexNavigation();
var way;
if (entity && entity.type === "way") {
way = entity;
} else if (parentId) {
way = context.entity(parentId);
}
_focusedParentWayId = way && way.id;
if (way) {
context.enter(mode.selectedIDs([way.last()]).follow(true));
}
}
function previousVertex(d3_event) {
d3_event.preventDefault();
var parentId = parentWayIdForVertexNavigation();
_focusedParentWayId = parentId;
if (!parentId)
return;
var way = context.entity(parentId);
var length = way.nodes.length;
var curr = way.nodes.indexOf(selectedIDs[0]);
var index = -1;
if (curr > 0) {
index = curr - 1;
} else if (way.isClosed()) {
index = length - 2;
}
if (index !== -1) {
context.enter(mode.selectedIDs([way.nodes[index]]).follow(true));
}
}
function nextVertex(d3_event) {
d3_event.preventDefault();
var parentId = parentWayIdForVertexNavigation();
_focusedParentWayId = parentId;
if (!parentId)
return;
var way = context.entity(parentId);
var length = way.nodes.length;
var curr = way.nodes.indexOf(selectedIDs[0]);
var index = -1;
if (curr < length - 1) {
index = curr + 1;
} else if (way.isClosed()) {
index = 0;
}
if (index !== -1) {
context.enter(mode.selectedIDs([way.nodes[index]]).follow(true));
}
}
function focusNextParent(d3_event) {
d3_event.preventDefault();
var parents = parentWaysIdsOfSelection(true);
if (!parents || parents.length < 2)
return;
var index = parents.indexOf(_focusedParentWayId);
if (index < 0 || index > parents.length - 2) {
_focusedParentWayId = parents[0];
} else {
_focusedParentWayId = parents[index + 1];
}
var surface = context.surface();
surface.selectAll(".related").classed("related", false);
if (_focusedParentWayId) {
surface.selectAll(utilEntitySelector([_focusedParentWayId])).classed("related", true);
}
}
function selectParent(d3_event) {
d3_event.preventDefault();
var currentSelectedIds = mode.selectedIDs();
var parentIds = _focusedParentWayId ? [_focusedParentWayId] : parentWaysIdsOfSelection(false);
if (!parentIds.length)
return;
context.enter(mode.selectedIDs(parentIds));
_focusedVertexIds = currentSelectedIds;
}
function selectChild(d3_event) {
d3_event.preventDefault();
var currentSelectedIds = mode.selectedIDs();
var childIds = _focusedVertexIds ? _focusedVertexIds.filter((id2) => context.hasEntity(id2)) : childNodeIdsOfSelection(true);
if (!childIds || !childIds.length)
return;
if (currentSelectedIds.length === 1)
_focusedParentWayId = currentSelectedIds[0];
context.enter(mode.selectedIDs(childIds));
}
};
mode.exit = function() {
_newFeature = false;
_focusedVertexIds = null;
_operations.forEach(function(operation) {
if (operation.behavior) {
context.uninstall(operation.behavior);
}
});
_operations = [];
_behaviors.forEach(context.uninstall);
select_default2(document).call(keybinding.unbind);
context.ui().closeEditMenu();
context.history().on("change.select", null).on("undone.select", null).on("redone.select", null);
var surface = context.surface();
surface.selectAll(".selected-member").classed("selected-member", false);
surface.selectAll(".selected").classed("selected", false);
surface.selectAll(".highlighted").classed("highlighted", false);
surface.selectAll(".related").classed("related", false);
context.map().on("drawn.select", null);
context.ui().sidebar.hide();
context.features().forceVisible([]);
var entity = singular();
if (_newFeature && entity && entity.type === "relation" && Object.keys(entity.tags).length === 0 && context.graph().parentRelations(entity).length === 0 && (entity.members.length === 0 || entity.members.length === 1 && !entity.members[0].role)) {
var deleteAction = actionDeleteRelation(entity.id, true);
context.perform(deleteAction, _t("operations.delete.annotation.relation"));
context.validator().validate();
}
};
return mode;
}
// modules/behavior/lasso.js
function behaviorLasso(context) {
var _pointerPrefix = "PointerEvent" in window ? "pointer" : "mouse";
var behavior = function(selection2) {
var lasso;
function pointerdown(d3_event) {
var button = 0;
if (d3_event.button === button && d3_event.shiftKey === true) {
lasso = null;
select_default2(window).on(_pointerPrefix + "move.lasso", pointermove).on(_pointerPrefix + "up.lasso", pointerup);
d3_event.stopPropagation();
}
}
function pointermove() {
if (!lasso) {
lasso = uiLasso(context);
context.surface().call(lasso);
}
lasso.p(context.map().mouse());
}
function normalize2(a, b) {
return [
[Math.min(a[0], b[0]), Math.min(a[1], b[1])],
[Math.max(a[0], b[0]), Math.max(a[1], b[1])]
];
}
function lassoed() {
if (!lasso)
return [];
var graph = context.graph();
var limitToNodes;
if (context.map().editableDataEnabled(true) && context.map().isInWideSelection()) {
limitToNodes = new Set(utilGetAllNodes(context.selectedIDs(), graph));
} else if (!context.map().editableDataEnabled()) {
return [];
}
var bounds = lasso.extent().map(context.projection.invert);
var extent = geoExtent(normalize2(bounds[0], bounds[1]));
var intersects = context.history().intersects(extent).filter(function(entity) {
return entity.type === "node" && (!limitToNodes || limitToNodes.has(entity)) && geoPointInPolygon(context.projection(entity.loc), lasso.coordinates) && !context.features().isHidden(entity, graph, entity.geometry(graph));
});
intersects.sort(function(node1, node2) {
var parents1 = graph.parentWays(node1);
var parents2 = graph.parentWays(node2);
if (parents1.length && parents2.length) {
var sharedParents = utilArrayIntersection(parents1, parents2);
if (sharedParents.length) {
var sharedParentNodes = sharedParents[0].nodes;
return sharedParentNodes.indexOf(node1.id) - sharedParentNodes.indexOf(node2.id);
} else {
return parseFloat(parents1[0].id.slice(1)) - parseFloat(parents2[0].id.slice(1));
}
} else if (parents1.length || parents2.length) {
return parents1.length - parents2.length;
}
return node1.loc[0] - node2.loc[0];
});
return intersects.map(function(entity) {
return entity.id;
});
}
function pointerup() {
select_default2(window).on(_pointerPrefix + "move.lasso", null).on(_pointerPrefix + "up.lasso", null);
if (!lasso)
return;
var ids = lassoed();
lasso.close();
if (ids.length) {
context.enter(modeSelect(context, ids));
}
}
selection2.on(_pointerPrefix + "down.lasso", pointerdown);
};
behavior.off = function(selection2) {
selection2.on(_pointerPrefix + "down.lasso", null);
};
return behavior;
}
// modules/modes/browse.js
function modeBrowse(context) {
var mode = {
button: "browse",
id: "browse",
title: _t("modes.browse.title"),
description: _t("modes.browse.description")
};
var sidebar;
var _selectBehavior;
var _behaviors = [];
mode.selectBehavior = function(val) {
if (!arguments.length)
return _selectBehavior;
_selectBehavior = val;
return mode;
};
mode.enter = function() {
if (!_behaviors.length) {
if (!_selectBehavior)
_selectBehavior = behaviorSelect(context);
_behaviors = [
behaviorPaste(context),
behaviorHover(context).on("hover", context.ui().sidebar.hover),
_selectBehavior,
behaviorLasso(context),
modeDragNode(context).behavior,
modeDragNote(context).behavior
];
}
_behaviors.forEach(context.install);
if (document.activeElement && document.activeElement.blur) {
document.activeElement.blur();
}
if (sidebar) {
context.ui().sidebar.show(sidebar);
} else {
context.ui().sidebar.select(null);
}
};
mode.exit = function() {
context.ui().sidebar.hover.cancel();
_behaviors.forEach(context.uninstall);
if (sidebar) {
context.ui().sidebar.hide();
}
};
mode.sidebar = function(_) {
if (!arguments.length)
return sidebar;
sidebar = _;
return mode;
};
mode.operations = function() {
return [operationPaste(context)];
};
return mode;
}
// modules/behavior/add_way.js
function behaviorAddWay(context) {
var dispatch10 = dispatch_default("start", "startFromWay", "startFromNode");
var draw = behaviorDraw(context);
function behavior(surface) {
draw.on("click", function() {
dispatch10.apply("start", this, arguments);
}).on("clickWay", function() {
dispatch10.apply("startFromWay", this, arguments);
}).on("clickNode", function() {
dispatch10.apply("startFromNode", this, arguments);
}).on("cancel", behavior.cancel).on("finish", behavior.cancel);
context.map().dblclickZoomEnable(false);
surface.call(draw);
}
behavior.off = function(surface) {
surface.call(draw.off);
};
behavior.cancel = function() {
window.setTimeout(function() {
context.map().dblclickZoomEnable(true);
}, 1e3);
context.enter(modeBrowse(context));
};
return utilRebind(behavior, dispatch10, "on");
}
// modules/behavior/hash.js
function behaviorHash(context) {
var _cachedHash = null;
var _latitudeLimit = 90 - 1e-8;
function computedHashParameters() {
var map2 = context.map();
var center = map2.center();
var zoom = map2.zoom();
var precision2 = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2));
var oldParams = utilObjectOmit(utilStringQs(window.location.hash), ["comment", "source", "hashtags", "walkthrough"]);
var newParams = {};
delete oldParams.id;
var selected = context.selectedIDs().filter(function(id2) {
return context.hasEntity(id2);
});
if (selected.length) {
newParams.id = selected.join(",");
}
newParams.map = zoom.toFixed(2) + "/" + center[1].toFixed(precision2) + "/" + center[0].toFixed(precision2);
return Object.assign(oldParams, newParams);
}
function computedHash() {
return "#" + utilQsString(computedHashParameters(), true);
}
function computedTitle(includeChangeCount) {
var baseTitle = context.documentTitleBase() || "iD";
var contextual;
var changeCount;
var titleID;
var selected = context.selectedIDs().filter(function(id2) {
return context.hasEntity(id2);
});
if (selected.length) {
var firstLabel = utilDisplayLabel(context.entity(selected[0]), context.graph());
if (selected.length > 1) {
contextual = _t("title.labeled_and_more", {
labeled: firstLabel,
count: selected.length - 1
});
} else {
contextual = firstLabel;
}
titleID = "context";
}
if (includeChangeCount) {
changeCount = context.history().difference().summary().length;
if (changeCount > 0) {
titleID = contextual ? "changes_context" : "changes";
}
}
if (titleID) {
return _t("title.format." + titleID, {
changes: changeCount,
base: baseTitle,
context: contextual
});
}
return baseTitle;
}
function updateTitle(includeChangeCount) {
if (!context.setsDocumentTitle())
return;
var newTitle = computedTitle(includeChangeCount);
if (document.title !== newTitle) {
document.title = newTitle;
}
}
function updateHashIfNeeded() {
if (context.inIntro())
return;
var latestHash = computedHash();
if (_cachedHash !== latestHash) {
_cachedHash = latestHash;
window.history.replaceState(null, computedTitle(false), latestHash);
updateTitle(true);
}
}
var _throttledUpdate = throttle_default(updateHashIfNeeded, 500);
var _throttledUpdateTitle = throttle_default(function() {
updateTitle(true);
}, 500);
function hashchange() {
if (window.location.hash === _cachedHash)
return;
_cachedHash = window.location.hash;
var q = utilStringQs(_cachedHash);
var mapArgs = (q.map || "").split("/").map(Number);
if (mapArgs.length < 3 || mapArgs.some(isNaN)) {
updateHashIfNeeded();
} else {
if (_cachedHash === computedHash())
return;
var mode = context.mode();
context.map().centerZoom([mapArgs[2], Math.min(_latitudeLimit, Math.max(-_latitudeLimit, mapArgs[1]))], mapArgs[0]);
if (q.id && mode) {
var ids = q.id.split(",").filter(function(id2) {
return context.hasEntity(id2);
});
if (ids.length && (mode.id === "browse" || mode.id === "select" && !utilArrayIdentical(mode.selectedIDs(), ids))) {
context.enter(modeSelect(context, ids));
return;
}
}
var center = context.map().center();
var dist = geoSphericalDistance(center, [mapArgs[2], mapArgs[1]]);
var maxdist = 500;
if (mode && mode.id.match(/^draw/) !== null && dist > maxdist) {
context.enter(modeBrowse(context));
return;
}
}
}
function behavior() {
context.map().on("move.behaviorHash", _throttledUpdate);
context.history().on("change.behaviorHash", _throttledUpdateTitle);
context.on("enter.behaviorHash", _throttledUpdate);
select_default2(window).on("hashchange.behaviorHash", hashchange);
if (window.location.hash) {
var q = utilStringQs(window.location.hash);
if (q.id) {
context.zoomToEntity(q.id.split(",")[0], !q.map);
}
if (q.walkthrough === "true") {
behavior.startWalkthrough = true;
}
if (q.map) {
behavior.hadHash = true;
}
hashchange();
updateTitle(false);
}
}
behavior.off = function() {
_throttledUpdate.cancel();
_throttledUpdateTitle.cancel();
context.map().on("move.behaviorHash", null);
context.on("enter.behaviorHash", null);
select_default2(window).on("hashchange.behaviorHash", null);
window.location.hash = "";
};
return behavior;
}
// node_modules/d3-brush/src/brush.js
var { abs: abs2, max: max2, min: min2 } = Math;
function number1(e) {
return [+e[0], +e[1]];
}
function number22(e) {
return [number1(e[0]), number1(e[1])];
}
var X = {
name: "x",
handles: ["w", "e"].map(type2),
input: function(x, e) {
return x == null ? null : [[+x[0], e[0][1]], [+x[1], e[1][1]]];
},
output: function(xy) {
return xy && [xy[0][0], xy[1][0]];
}
};
var Y = {
name: "y",
handles: ["n", "s"].map(type2),
input: function(y, e) {
return y == null ? null : [[e[0][0], +y[0]], [e[1][0], +y[1]]];
},
output: function(xy) {
return xy && [xy[0][1], xy[1][1]];
}
};
var XY = {
name: "xy",
handles: ["n", "w", "e", "s", "nw", "ne", "sw", "se"].map(type2),
input: function(xy) {
return xy == null ? null : number22(xy);
},
output: function(xy) {
return xy;
}
};
function type2(t) {
return { type: t };
}
// modules/index.js
var debug = false;
var d3 = {
dispatch: dispatch_default,
geoMercator: mercator_default,
geoProjection: projection,
polygonArea: area_default3,
polygonCentroid: centroid_default2,
select: select_default2,
selectAll: selectAll_default2,
timerFlush
};
// modules/id.js
window.requestIdleCallback = window.requestIdleCallback || function(cb) {
var start2 = Date.now();
return window.requestAnimationFrame(function() {
cb({
didTimeout: false,
timeRemaining: function() {
return Math.max(0, 50 - (Date.now() - start2));
}
});
});
};
window.cancelIdleCallback = window.cancelIdleCallback || function(id2) {
window.cancelAnimationFrame(id2);
};
window.iD = modules_exports;
})();
//# sourceMappingURL=iD.js.map