var zoomBtn = document.getElementById("zoom-");
if (zoomBtn) {
zoomBtn.onclick = async function() {
var layerName = Layer.get("name");
var proxyUrl = "";
var url = proxyUrl + "?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetCapabilities&LAYERS=" + layerName;
try {
const response = await fetch(url);
const text = await response.text();
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(text, "text/xml");
const layerInfo = xmlDoc.getElementsByTagName("Layer");
for (let i = 0; i < layerInfo.length; i++) {
const name = layerInfo[i].getElementsByTagName("Name")[0];
if (name && name.textContent === layerName) {
const bboxes = layerInfo[i].getElementsByTagName("BoundingBox");
let bbox = null;
let sourceSRS = null;
// First try to find EPSG:4326 bbox
for (let j = 0; j < bboxes.length; j++) {
if (bboxes[j].getAttribute("SRS") === "EPSG:4326") {
bbox = bboxes[j];
sourceSRS = "EPSG:4326";
break;
}
}
// If no EPSG:4326 found, use the first available bbox
if (!bbox && bboxes.length > 0) {
bbox = bboxes[0];
sourceSRS = bbox.getAttribute("SRS");
// Ensure the projection is registered
try {
await ensureProjectionRegistered(sourceSRS);
} catch (error) {
console.error("Error registering projection:", error);
return;
}
}
if (bbox) {
const extent = [
parseFloat(bbox.getAttribute("minx")),
parseFloat(bbox.getAttribute("miny")),
parseFloat(bbox.getAttribute("maxx")),
parseFloat(bbox.getAttribute("maxy"))
];
// Add padding to the extent
const width = extent[2] - extent[0];
const height = extent[3] - extent[1];
extent[0] -= width * 0.1;
extent[1] -= height * 0.1;
extent[2] += width * 0.1;
extent[3] += height * 0.1;
try {
let transformedExtent;
if (sourceSRS === "EPSG:4326") {
transformedExtent = ol.proj.transformExtent(extent, "EPSG:4326", "EPSG:3857");
} else {
const wgs84Extent = ol.proj.transformExtent(extent, sourceSRS, "EPSG:4326");
transformedExtent = ol.proj.transformExtent(wgs84Extent, "EPSG:4326", "EPSG:3857");
}
if (isNaN(transformedExtent[0]) || isNaN(transformedExtent[1]) ||
isNaN(transformedExtent[2]) || isNaN(transformedExtent[3])) {
throw new Error("Invalid transformed extent");
}
map.getView().fit(transformedExtent, {
padding: [50, 50, 50, 50],
duration: 1000,
maxZoom: 15
});
} catch (error) {
console.error("Error transforming extent:", error);
const defaultExtent = [-20037508.34, -20037508.34, 20037508.34, 20037508.34];
map.getView().fit(defaultExtent, {
padding: [50, 50, 50, 50],
duration: 1000,
maxZoom: 15
});
}
} else {
console.error("No bounding box found for layer");
}
break;
}
}
} catch (error) {
console.error("Error fetching layer extent:", error);
}
};
}
Custom Map
Layer Table
Loading...
Description:
Created:
1): ?>
0) {
var currentFeatureIndex = 0;
var totalFeatures = data.features.length;
function generatePopupHTML(featureIndex) {
var feature = data.features[featureIndex];
var props = feature.properties;
// Derive correct layer name from feature.id
var layerName = "Unknown Layer";
if (feature && feature.id) {
// GeoServer usually returns "workspace:layername.123"
var idStr = String(feature.id);
if (idStr.indexOf(".") > -1) idStr = idStr.split(".")[0];
if (idStr.indexOf(":") > -1) idStr = idStr.split(":").pop();
layerName = idStr;
} else if (props && (props._layer || props.layer || props.layer_name)) {
layerName = props._layer || props.layer || props.layer_name;
} else if (urlLayers.length > 0) {
layerName = urlLayers[0];
}
var html = "
";
html += "
";
html += "";
html += "" + (featureIndex + 1) + " of " + totalFeatures + "";
html += "";
html += "
";
html += "";
html += "
";
html += "
";
// Layer information
html += "
";
html += "Layer: ";
html += "" + layerName + "";
html += "
";
// Action buttons
html += "
";
html += "";
html += "";
html += "
";
// Feature attributes - show all properties
var propKeys = Object.keys(props);
propKeys.forEach(function(key, index) {
// Highlight important attributes like Name, Address, etc.
var importantKeys = ["name", "address", "title", "description", "type", "category"];
var isHighlighted = importantKeys.some(function(importantKey) {
return key.toLowerCase().includes(importantKey);
});
html += "
";
html += "" + key + ": ";
html += "" + (props[key] || "N/A") + "";
html += "
";
});
html += "
";
return html;
}
// Generate initial popup
popup.innerHTML = generatePopupHTML(currentFeatureIndex);
popup.style.display = "block";
overlay.setPosition(coordinate);
// Add navigation functions to window scope
window.navigateFeature = function(newIndex) {
if (newIndex >= 0 && newIndex < totalFeatures) {
currentFeatureIndex = newIndex;
popup.innerHTML = generatePopupHTML(currentFeatureIndex);
}
};
window.closePopup = function() {
popup.style.display = "none";
overlay.setPosition(undefined);
};
window.showTable = function() {
var f = data.features[currentFeatureIndex] || {};
var props = (f && f.properties) ? f.properties : {};
// ---- Resolve correct layer name from this feature ----
var layerName = "Unknown";
if (f && f.id) {
var idStr = String(f.id);
if (idStr.indexOf(".") > -1) idStr = idStr.split(".")[0]; // strip ".123"
if (idStr.indexOf(":") > -1) idStr = idStr.split(":").pop(); // strip "workspace:"
layerName = idStr || layerName;
} else if (props && (props._layer || props.layer || props.layer_name)) {
layerName = props._layer || props.layer || props.layer_name;
} else if (urlLayers && urlLayers.length > 0) {
layerName = urlLayers[0];
}
// ---- Try to detect a primary key candidate on the clicked feature ----
var pkCandidates = ["id","fid","gid","objectid","feature_id","pk","ogc_fid"];
var pkcol = null;
for (var i = 0; i < pkCandidates.length; i++) {
var k = pkCandidates[i];
if (Object.prototype.hasOwnProperty.call(props, k)) { pkcol = k; break; }
}
// Fallback: first property that ends with "_id"
if (!pkcol) {
Object.keys(props || {}).some(function(k){
if (/_id$/i.test(k)) { pkcol = k; return true; }
return false;
});
}
var pkval = pkcol ? props[pkcol] : null;
var q = "layer=" + encodeURIComponent(layerName);
if (pkcol && pkval !== undefined && pkval !== null) {
q += "&pkcol=" + encodeURIComponent(pkcol) + "&pk=" + encodeURIComponent(pkval);
}
var tableUrl = "view_table.php?" + q;
// Open modal and load content
var modal = new bootstrap.Modal(document.getElementById(\'tableModal\'));
var modalContent = document.getElementById(\'tableViewContent\');
// Update modal title if present
try {
var titleEl = document.querySelector(\'#tableModal .modal-title, #tableModalLabel\');
if (titleEl) { titleEl.textContent = \'Layer Table — \' + layerName; }
} catch(e) {}
// Show loading spinner
modalContent.innerHTML = \'
Loading...
\';
modal.show();
// Load table content via fetch
fetch(tableUrl)
.then(function(response) { return response.text(); })
.then(function(html) {
// Extract just the body content from the response
var parser = new DOMParser();
var doc = parser.parseFromString(html, \'text/html\');
var bodyContent = doc.body.innerHTML;
modalContent.innerHTML = bodyContent;
})
.catch(function(error) {
modalContent.innerHTML = \'
Error loading table: \' + error.message + \'
\';
});
};
window.zoomToFeature = function() {
var f = data.features[currentFeatureIndex];
if (!f || !f.geometry) {
console.warn("No geometry found for feature.", f);
return;
}
try {
// Use ol/format/GeoJSON to convert to ol.Feature
var geojsonFormat = new ol.format.GeoJSON();
var olFeature = geojsonFormat.readFeature(f, {
dataProjection: "EPSG:4326", // Default from GeoServer JSON
featureProjection: map.getView().getProjection()
});
var geom = olFeature.getGeometry();
if (!geom) {
console.warn("No geometry parsed from feature.", f);
return;
}
var extent = geom.getExtent();
// Validate extent; handle cases where geometry extent is empty/invalid
var invalid = (
!extent || extent.length !== 4 ||
!isFinite(extent[0]) || !isFinite(extent[1]) ||
!isFinite(extent[2]) || !isFinite(extent[3]) ||
extent[0] === Infinity || extent[2] === -Infinity
);
if (invalid) {
// Try to derive an extent from the raw GeoJSON point or the click coordinate
var buffer = 5000;
if (f && f.geometry && f.geometry.type === "Point" && Array.isArray(f.geometry.coordinates)) {
var p = ol.proj.transform(f.geometry.coordinates, "EPSG:4326", map.getView().getProjection());
extent = [p[0] - buffer, p[1] - buffer, p[0] + buffer, p[1] + buffer];
} else if (typeof coordinate !== "undefined" && coordinate && coordinate.length === 2) {
extent = [coordinate[0] - buffer, coordinate[1] - buffer, coordinate[0] + buffer, coordinate[1] + buffer];
} else {
console.warn("Empty extent and no fallback available for zoom.", f);
return;
}
}
// For Points, pad extent a bit so it is not zoomed too far in
var isPoint = geom.getType() === "Point";
if (isPoint) {
var buffer = 5000; // meters; adjust for your data context
extent = [
extent[0] - buffer,
extent[1] - buffer,
extent[2] + buffer,
extent[3] + buffer
];
}
map.getView().fit(extent, {
duration: 1000,
padding: [50, 50, 50, 50],
maxZoom: 15
});
} catch (err) {
console.error("Could not zoom to feature:", err, f);
}
};
}
})
.catch(function(error) {
console.error("Error fetching feature info:", error);
});
});
}';
}
?>