1 OSM.initializeDataLayer = function (map) {
2 let dataLoader, loadedBounds;
3 const dataLayer = map.dataLayer;
5 dataLayer.isWayArea = function () {
9 dataLayer.on("click", function (e) {
10 const feature = e.layer.feature;
11 OSM.router.click(e.originalEvent, `/${feature.type}/${feature.id}`);
14 dataLayer.on("add", function () {
15 map.fire("overlayadd", { layer: this });
16 map.on("moveend", updateData);
20 dataLayer.on("remove", function () {
21 if (dataLoader) dataLoader.abort();
23 map.off("moveend", updateData);
24 $("#browse_status").empty();
25 map.fire("overlayremove", { layer: this });
28 function updateData() {
29 const bounds = map.getBounds();
30 if (!loadedBounds || !loadedBounds.contains(bounds)) {
35 function displayFeatureWarning(num_features, add, cancel) {
36 $("#browse_status").html(
37 $("<div class='p-3'>").append(
38 $("<div class='d-flex'>").append(
39 $("<h2 class='flex-grow-1 text-break'>")
40 .text(OSM.i18n.t("browse.start_rjs.load_data")),
42 $("<button type='button' class='btn-close'>")
43 .attr("aria-label", OSM.i18n.t("javascripts.close"))
45 $("<p class='alert alert-warning'>")
46 .text(OSM.i18n.t("browse.start_rjs.feature_warning", { num_features })),
47 $("<input type='submit' class='btn btn-primary d-block mx-auto'>")
48 .val(OSM.i18n.t("browse.start_rjs.load_data"))
52 function displayLoadError(message, close) {
53 $("#browse_status").html(
54 $("<div class='p-3'>").append(
55 $("<div class='d-flex'>").append(
56 $("<h2 class='flex-grow-1 text-break'>")
57 .text(OSM.i18n.t("browse.start_rjs.load_data")),
59 $("<button type='button' class='btn-close'>")
60 .attr("aria-label", OSM.i18n.t("javascripts.close"))
62 $("<p class='alert alert-warning'>")
63 .text(OSM.i18n.t("browse.start_rjs.feature_error", { message: message }))));
67 const bounds = map.getBounds();
68 const url = "/api/" + OSM.API_VERSION + "/map.json?bbox=" + bounds.toBBoxString();
71 * Modern browsers are quite happy showing far more than 100 features in
72 * the data browser, so increase the limit to 4000.
74 const maxFeatures = 4000;
76 if (dataLoader) dataLoader.abort();
78 $("#layers-data-loading").remove();
80 const spanLoading = $("<span>")
81 .attr("id", "layers-data-loading")
82 .attr("class", "spinner-border spinner-border-sm ms-1")
83 .attr("role", "status")
84 .html("<span class='visually-hidden'>" + OSM.i18n.t("browse.start_rjs.loading") + "</span>")
85 .appendTo($("#label-layers-data"));
87 dataLoader = new AbortController();
88 fetch(url, { signal: dataLoader.signal })
90 if (response.ok) return response.json();
91 const status = response.statusText || response.status;
92 if (response.status !== 400 && response.status !== 509) throw new Error(status);
93 return response.text().then(text => {
94 throw new Error(text || status);
97 .then(function (data) {
98 dataLayer.clearLayers();
100 const features = dataLayer.buildFeatures(data);
102 function addFeatures() {
103 $("#browse_status").empty();
104 dataLayer.addData(features);
105 loadedBounds = bounds;
108 function cancelAddFeatures() {
109 $("#browse_status").empty();
112 if (features.length < maxFeatures) {
115 displayFeatureWarning(features.length, addFeatures, cancelAddFeatures);
118 if (map._objectLayer) {
119 map._objectLayer.bringToFront();
124 .catch(function (error) {
125 if (error.name === "AbortError") return;
127 displayLoadError(error?.message, () => {
128 $("#browse_status").empty();
134 spanLoading.remove();