let sharedMapBounds=null;
const OUMUtils=(function (){
function getParameterByName(name){
name=name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
const regex=new RegExp("[\\?&]" + name + "=([^&#]*)"),
results=regex.exec(location.search);
return results===null
? ""
: decodeURIComponent(results[1].replace(/\+/g, " "));
}
function latLngToBounds(lat, lng, zoom, width, height){
lat =
typeof lat==="string"
? parseFloat(lat.replace(/['"]+/g, ""))
: parseFloat(lat);
lng =
typeof lng==="string"
? parseFloat(lng.replace(/['"]+/g, ""))
: parseFloat(lng);
zoom =
typeof zoom==="string"
? parseFloat(zoom.replace(/['"]+/g, ""))
: parseFloat(zoom);
width =
typeof width==="string"
? parseFloat(width.replace(/['"]+/g, ""))
: parseFloat(width);
height =
typeof height==="string"
? parseFloat(height.replace(/['"]+/g, ""))
: parseFloat(height);
if(!validateCoordinates(lat, lng)){
console.warn("Invalid coordinates for latLngToBounds, using defaults");
return [
[OUMConfig.defaults.map.lat, OUMConfig.defaults.map.lng],
[OUMConfig.defaults.map.lat, OUMConfig.defaults.map.lng],
];
}
if(isNaN(width)||width <=0||isNaN(height)||height <=0){
console.warn("Invalid dimensions for latLngToBounds");
width=520;
height=294;
}
if(isNaN(zoom)){
zoom=OUMConfig.defaults.map.zoom;
}else{
zoom=Math.max(1, Math.min(20, zoom));
}
const crs=L.CRS.EPSG3857;
const centerLatLng=L.latLng(lat, lng);
const centerPoint=crs.latLngToPoint(centerLatLng, zoom);
const halfWidth=width / 2;
const halfHeight=height / 2;
const topLeftPoint=L.point(centerPoint.x - halfWidth, centerPoint.y - halfHeight);
const topRightPoint=L.point(centerPoint.x + halfWidth, centerPoint.y - halfHeight);
const bottomLeftPoint=L.point(centerPoint.x - halfWidth, centerPoint.y + halfHeight);
const bottomRightPoint=L.point(centerPoint.x + halfWidth, centerPoint.y + halfHeight);
const topLeftLatLng=crs.pointToLatLng(topLeftPoint, zoom);
const topRightLatLng=crs.pointToLatLng(topRightPoint, zoom);
const bottomLeftLatLng=crs.pointToLatLng(bottomLeftPoint, zoom);
const bottomRightLatLng=crs.pointToLatLng(bottomRightPoint, zoom);
const minLat=Math.min(topLeftLatLng.lat, topRightLatLng.lat, bottomLeftLatLng.lat, bottomRightLatLng.lat);
const maxLat=Math.max(topLeftLatLng.lat, topRightLatLng.lat, bottomLeftLatLng.lat, bottomRightLatLng.lat);
const minLng=Math.min(topLeftLatLng.lng, topRightLatLng.lng, bottomLeftLatLng.lng, bottomRightLatLng.lng);
const maxLng=Math.max(topLeftLatLng.lng, topRightLatLng.lng, bottomLeftLatLng.lng, bottomRightLatLng.lng);
return [
[minLat, minLng],
[maxLat, maxLng],
];
}
function customAutoSuggestText(text, val){
return (
'<div><img src="' +
val.layer.options.icon.options.iconUrl +
'" />' +
val.layer.options.title +
"</div>"
);
}
function initGeosearchProvider(){
let provider;
switch (oum_geosearch_provider){
case "osm":
provider=new GeoSearch.OpenStreetMapProvider();
break;
case "geoapify":
provider=new GeoSearch.GeoapifyProvider({
params: {
apiKey: oum_geosearch_provider_geoapify_key,
},
});
break;
case "here":
provider=new GeoSearch.HereProvider({
params: {
apiKey: oum_geosearch_provider_here_key,
},
});
break;
case "mapbox":
provider=new GeoSearch.MapBoxProvider({
params: {
access_token: oum_geosearch_provider_mapbox_key,
},
});
break;
default:
provider=new GeoSearch.OpenStreetMapProvider();
break;
}
return provider;
}
function validateCoordinates(lat, lng){
const parsedLat=parseFloat(lat);
const parsedLng=parseFloat(lng);
return (
!isNaN(parsedLat) &&
!isNaN(parsedLng) &&
parsedLat >=-90 &&
parsedLat <=90 &&
parsedLng >=-180 &&
parsedLng <=180
);
}
function safeJSONParse(str, fallback=null){
try {
return JSON.parse(str);
} catch (e){
return fallback;
}}
function debounce(func, wait=250){
let timeout;
return function executedFunction(...args){
const later=()=> {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout=setTimeout(later, wait);
};}
function sprintf(str, ...args){
return str.replace(/%(\d+)\$d/g, (match, num)=> args[num - 1]||match);
}
return {
getParameterByName,
latLngToBounds,
customAutoSuggestText,
initGeosearchProvider,
validateCoordinates,
safeJSONParse,
debounce,
sprintf
};})();
const OUMErrorHandler=(function (){
function showError(message, type="error"){
console.error(`OUM Error: ${message}`);
const errorContainer=document.getElementById("oum_add_location_error");
if(errorContainer){
errorContainer.innerHTML=`${message}<br>`;
errorContainer.style.display="block";
}}
function handleAjaxError(error){
showError(`Ajax request failed: ${error.message}`);
}
function validateCoordinates(lat, lng){
const parsedLat=parseFloat(lat);
const parsedLng=parseFloat(lng);
if(isNaN(parsedLat)||isNaN(parsedLng)){
showError("Invalid coordinates provided");
return false;
}
if(parsedLat < -90 ||
parsedLat > 90 ||
parsedLng < -180 ||
parsedLng > 180
){
showError("Coordinates out of valid range");
return false;
}
return true;
}
return {
showError,
handleAjaxError,
validateCoordinates,
};})();
const OUMConfig=(function (){
const defaults={
map: {
lat: 26,
lng: 10,
zoom: 1,
bounds: L.latLngBounds(L.latLng(-85, -200),
L.latLng(85, 200)
),
},
media: {
maxFiles: 5,
validImageExtensions: ["jpeg", "jpg", "png", "webp"],
maxImageSize: (window.oum_max_image_filesize||10) * 1048576,
},
search: {
zoomLevel: window.oum_searchmarkers_zoom||8,
addressLabel: window.oum_searchaddress_label||"Search for address",
markersLabel: window.oum_searchmarkers_label||"Find marker",
},
};
function getMapStyle(){
return window.mapStyle||"Esri.WorldStreetMap";
}
function getTileProviderKey(){
return window.oum_tile_provider_mapbox_key||"";
}
function getGeosearchProvider(){
let provider;
switch (oum_geosearch_provider){
case "geoapify":
provider=new GeoSearch.GeoapifyProvider({
params: {
apiKey: oum_geosearch_provider_geoapify_key,
},
});
break;
case "here":
provider=new GeoSearch.HereProvider({
params: {
apiKey: oum_geosearch_provider_here_key,
},
});
break;
case "mapbox":
provider=new GeoSearch.MapBoxProvider({
params: {
access_token: oum_geosearch_provider_mapbox_key,
},
});
break;
default:
provider=new GeoSearch.OpenStreetMapProvider();
}
return provider;
}
return {
defaults,
getMapStyle,
getTileProviderKey,
getGeosearchProvider,
};})();
const OUMMap=(function (){
let map=null;
let world_bounds=null;
let startPosition={
lat:
typeof start_lat!=="undefined"
? Number(start_lat)
: OUMConfig.defaults.map.lat,
lng:
typeof start_lng!=="undefined"
? Number(start_lng)
: OUMConfig.defaults.map.lng,
zoom:
typeof start_zoom!=="undefined"
? Number(start_zoom)
: OUMConfig.defaults.map.zoom,
};
function initializeStartPosition(){
if(!OUMUtils.validateCoordinates(startPosition.lat, startPosition.lng)){
console.warn("Invalid coordinates, using defaults");
startPosition.lat=OUMConfig.defaults.map.lat;
startPosition.lng=OUMConfig.defaults.map.lng;
}
if(isNaN(startPosition.zoom) ||
startPosition.zoom < 1 ||
startPosition.zoom > 20
){
console.warn("Invalid zoom level, using default");
startPosition.zoom=OUMConfig.defaults.map.zoom;
}}
function isClusterZoomLocked(){
return !!oum_enable_cluster;
}
function normalizeMainMapZoom(zoom){
const parsedZoom=Number(zoom);
if(isNaN(parsedZoom)){
return zoom;
}
return isClusterZoomLocked() ? Math.round(parsedZoom):parsedZoom;
}
function setMainMapView(center, zoom, options={}){
map.setView(center, normalizeMainMapZoom(zoom), options);
}
function flyMainMapTo(center, zoom, options={}){
map.flyTo(center, normalizeMainMapZoom(zoom), options);
}
function flyMainMapToBounds(bounds, options={}){
const flyOptions={ ...options };
if(isClusterZoomLocked()){
flyOptions.maxZoom=normalizeMainMapZoom(map.getBoundsZoom(bounds, false));
}
map.flyToBounds(bounds, flyOptions);
}
function setupMapBounds(){
if(oum_enable_fixed_map_bounds){
const boundsArray=OUMUtils.latLngToBounds(startPosition.lat,
startPosition.lng,
startPosition.zoom,
520,
294 
);
world_bounds=L.latLngBounds(L.latLng(boundsArray[0][0], boundsArray[0][1]),
L.latLng(boundsArray[1][0], boundsArray[1][1])
);
sharedMapBounds=world_bounds;
}else{
world_bounds=OUMConfig.defaults.map.bounds;
sharedMapBounds=world_bounds;
}
const maxVisibleBounds=map.getBoundsZoom(world_bounds);
map.setMinZoom(maxVisibleBounds);
map.setMaxBounds(world_bounds);
let isAdjusting=false;
map.on("moveend", function (){
if(isAdjusting) return;
isAdjusting=true;
const zoom=map.getZoom();
if(zoom > maxVisibleBounds){
const currentBounds=map.getBounds();
const currentCenter=map.getCenter();
let needsAdjustment=false;
let newLat=currentCenter.lat;
let newLng=currentCenter.lng;
const viewportHeight =
currentBounds.getNorth() - currentBounds.getSouth();
const viewportWidth =
currentBounds.getEast() - currentBounds.getWest();
if(currentBounds.getNorth() > world_bounds.getNorth()){
newLat=world_bounds.getNorth() - viewportHeight / 2;
needsAdjustment=true;
}else if(currentBounds.getSouth() < world_bounds.getSouth()){
newLat=world_bounds.getSouth() + viewportHeight / 2;
needsAdjustment=true;
}
if(currentBounds.getEast() > world_bounds.getEast()){
newLng=world_bounds.getEast() - viewportWidth / 2;
needsAdjustment=true;
}else if(currentBounds.getWest() < world_bounds.getWest()){
newLng=world_bounds.getWest() + viewportWidth / 2;
needsAdjustment=true;
}
if(needsAdjustment){
setMainMapView([newLat, newLng], zoom, { animate: false });
}}
isAdjusting=false;
});
}
function setupTileLayer(mapStyle){
let tileLayer;
if(mapStyle=="Custom1"){
tileLayer=L.tileLayer("https://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}.png"
).addTo(map);
L.tileLayer("https://{s}.basemaps.cartocdn.com/rastertiles/voyager_only_labels/{z}/{x}/{y}{r}.png",
{
tileSize: 512,
zoomOffset: -1,
}
).addTo(map);
}else if(mapStyle=="Custom2"){
tileLayer=L.tileLayer("https://{s}.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}.png"
).addTo(map);
L.tileLayer("https://{s}.basemaps.cartocdn.com/rastertiles/voyager_only_labels/{z}/{x}/{y}{r}.png",
{
tileSize: 512,
zoomOffset: -1,
}
).addTo(map);
}else if(mapStyle=="Custom3"){
tileLayer=L.tileLayer("https://{s}.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}.png"
).addTo(map);
L.tileLayer("https://{s}.basemaps.cartocdn.com/rastertiles/voyager_only_labels/{z}/{x}/{y}{r}.png",
{
tileSize: 512,
zoomOffset: -1,
}
).addTo(map);
}else if(mapStyle=="MapBox.streets"){
tileLayer=L.tileLayer
.provider("MapBox", {
id: "mapbox/streets-v12",
accessToken: OUMConfig.getTileProviderKey(),
})
.addTo(map);
}else if(mapStyle=="MapBox.outdoors"){
tileLayer=L.tileLayer
.provider("MapBox", {
id: "mapbox/outdoors-v12",
accessToken: OUMConfig.getTileProviderKey(),
})
.addTo(map);
}else if(mapStyle=="MapBox.light"){
tileLayer=L.tileLayer
.provider("MapBox", {
id: "mapbox/light-v11",
accessToken: OUMConfig.getTileProviderKey(),
})
.addTo(map);
}else if(mapStyle=="MapBox.dark"){
tileLayer=L.tileLayer
.provider("MapBox", {
id: "mapbox/dark-v11",
accessToken: OUMConfig.getTileProviderKey(),
})
.addTo(map);
}else if(mapStyle=="MapBox.satellite"){
tileLayer=L.tileLayer
.provider("MapBox", {
id: "mapbox/satellite-v9",
accessToken: OUMConfig.getTileProviderKey(),
})
.addTo(map);
}else if(mapStyle=="MapBox.satellite-streets"){
tileLayer=L.tileLayer
.provider("MapBox", {
id: "mapbox/satellite-streets-v12",
accessToken: OUMConfig.getTileProviderKey(),
})
.addTo(map);
}else if(mapStyle=="CustomImage"){
setupCustomImageLayer();
if(window.oum_custom_image_hide_tiles){
tileLayer=L.tileLayer('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==', {
attribution: '',
opacity: 0
}).addTo(map);
if(window.oum_custom_image_background_color){
map.getContainer().style.backgroundColor=window.oum_custom_image_background_color;
}}else{
tileLayer=L.tileLayer.provider("OpenStreetMap.Mapnik").addTo(map);
}}else{
tileLayer=L.tileLayer.provider(mapStyle).addTo(map);
}
return tileLayer;
}
function setupCustomImageLayer(){
if(typeof window.oum_custom_image_url!=='undefined'&&window.oum_custom_image_url &&
typeof window.oum_custom_image_bounds!=='undefined'&&window.oum_custom_image_bounds){
const isSVG=window.oum_custom_image_url.toLowerCase().includes('.svg');
if(isSVG){
setupSVGFromFile();
}else{
setupImageOverlay();
}}else{
}}
function setupSVGFromFile(){
try {
const bounds=window.oum_custom_image_bounds;
if(!bounds||typeof bounds.north==='undefined'||typeof bounds.south==='undefined' ||
typeof bounds.east==='undefined'||typeof bounds.west==='undefined' ||
bounds.north===''||bounds.south===''||bounds.east===''||bounds.west===''){
console.warn('Open User Map: Invalid or empty bounds data, skipping SVG file layer');
return;
}
fetch(window.oum_custom_image_url)
.then(response=> response.text())
.then(svgText=> {
const svgElement=createSVGElement(svgText);
if(!svgElement){
console.warn('Open User Map: Cannot create SVG layer from file - invalid SVG element');
return;
}
const svgLayer=L.svgOverlay(svgElement, [
[bounds.south, bounds.west],
[bounds.north, bounds.east]
], {
opacity: 1.0,
interactive: true
});
svgLayer.addTo(map);
window.oumCustomSVGLayer=svgLayer;
console.log('Open User Map: Custom SVG file layer added successfully');
})
.catch(error=> {
console.warn('Open User Map: Error fetching SVG file:', error);
});
} catch (error){
console.warn('Open User Map: Error setting up custom SVG file layer:', error);
}}
function setupImageOverlay(){
try {
const bounds=window.oum_custom_image_bounds;
if(!bounds||typeof bounds.north==='undefined'||typeof bounds.south==='undefined' ||
typeof bounds.east==='undefined'||typeof bounds.west==='undefined' ||
bounds.north===''||bounds.south===''||bounds.east===''||bounds.west===''){
console.warn('Open User Map: Invalid or empty bounds data, skipping image layer');
return;
}
const imageOverlay=L.imageOverlay(window.oum_custom_image_url, [
[bounds.south, bounds.west],
[bounds.north, bounds.east]
], {
opacity: 1.0,
interactive: true
});
imageOverlay.addTo(map);
window.oumCustomImageLayer=imageOverlay;
console.log('Open User Map: Custom image layer added successfully');
} catch (error){
console.warn('Open User Map: Error setting up custom image layer:', error);
}}
function createSVGElement(svgText){
const tempDiv=document.createElement('div');
tempDiv.innerHTML=svgText;
const svgElement=tempDiv.querySelector('svg');
if(!svgElement){
console.warn('Open User Map: No valid SVG element found in SVG text');
return null;
}
if(!svgElement.getAttribute('viewBox')){
const width=svgElement.getAttribute('width');
const height=svgElement.getAttribute('height');
if(width&&height){
const widthNum=parseFloat(width);
const heightNum=parseFloat(height);
if(!isNaN(widthNum)&&!isNaN(heightNum)){
svgElement.setAttribute('viewBox', `0 0 ${widthNum} ${heightNum}`);
}else{
svgElement.setAttribute('viewBox', '0 0 1000 1200');
}}else{
svgElement.setAttribute('viewBox', '0 0 1000 1200');
}}
svgElement.style.width='100%';
svgElement.style.height='100%';
svgElement.style.display='block';
svgElement.setAttribute('preserveAspectRatio', 'none');
console.log('Open User Map: SVG element created successfully:', svgElement);
return svgElement;
}
function setupControls(){
if(oum_enable_searchmarkers_button){
L.control
.search({
textPlaceholder: oum_searchmarkers_label,
layer: window.oumMarkersLayer,
propertyName: "content",
initial: false,
buildTip: OUMUtils.customAutoSuggestText,
autoType: false,
firstTipSubmit: true,
autoCollapse: true,
zoom: oum_searchmarkers_zoom,
})
.addTo(map);
}
if(oum_enable_searchbar&&oum_searchbar_type==="markers"){
L.control
.search({
textPlaceholder: oum_searchmarkers_label,
layer: window.oumMarkersLayer,
propertyName: "content",
initial: false,
buildTip: OUMUtils.customAutoSuggestText,
autoType: false,
firstTipSubmit: true,
autoCollapse: false,
collapsed: false,
zoom: oum_searchmarkers_zoom,
container: 'oum_search_marker'
})
.addTo(map);
}
if(oum_enable_searchbar&&oum_searchbar_type==="address"){
const searchBar=new GeoSearch.GeoSearchControl({
style: "bar",
showMarker: false,
provider: OUMUtils.initGeosearchProvider(),
searchLabel: oum_searchaddress_label,
updateMap: false,
});
map.addControl(searchBar);
}
if(oum_enable_searchaddress_button){
const searchButton=new GeoSearch.GeoSearchControl({
style: "button",
showMarker: false,
provider: OUMUtils.initGeosearchProvider(),
searchLabel: oum_searchaddress_label,
updateMap: false,
});
map.addControl(searchButton);
}
if(oum_enable_currentlocation){
window.map_locate_process=L.control
.locate({
flyTo: true,
showPopup: false,
})
.addTo(map);
}}
function setupMapEvents(){
map.on("moveend", function (ev){
startPosition.lat=map.getCenter().lat;
startPosition.lng=map.getCenter().lng;
startPosition.zoom=map.getZoom();
});
const addLocationPopup=document.querySelector("#add-location-overlay");
const originalContainer=addLocationPopup?.parentElement;
const fullscreenContainer=document.querySelector(".open-user-map .map-wrap"
);
if(addLocationPopup){
map.on("enterFullscreen", function (){
fullscreenContainer.appendChild(addLocationPopup);
});
map.on("exitFullscreen", function (){
originalContainer.appendChild(addLocationPopup);
});
}
map.on("geosearch/showlocation", function(e){
let coords=e.marker._latlng;
let isInBounds=true;
if(oum_enable_fixed_map_bounds==='on'&&sharedMapBounds){
isInBounds=sharedMapBounds.contains(coords);
}
if(!isInBounds&&oum_enable_fixed_map_bounds==='on'){
console.log("This search result is out of reach.");
const searchBar=document.querySelector(`#${map_el} .leaflet-geosearch-bar form`);
if(searchBar){
searchBar.style.boxShadow="0 0 10px rgb(255, 111, 105)";
setTimeout(function (){
searchBar.style.boxShadow="0 1px 5px rgba(255, 255, 255, 0.65)";
}, 2000);
}}else{
if(e.location.bounds){
flyMainMapToBounds(e.location.bounds);
}else if(e.location.raw&&e.location.raw.mapView){
flyMainMapToBounds([
[e.location.raw.mapView.south, e.location.raw.mapView.west],
[e.location.raw.mapView.north, e.location.raw.mapView.east]
]);
}else{
flyMainMapTo([e.location.y, e.location.x], 17);
}}
});
}
function setupRegionEvents(){
document
.querySelectorAll(".open-user-map .change_region")
.forEach(function (btn){
btn.onclick=function (event){
let el=event.currentTarget;
let region_lat=el.getAttribute("data-lat");
let region_lng=el.getAttribute("data-lng");
let region_zoom=el.getAttribute("data-zoom");
const mapContainer=map.getContainer();
const frontendMapWidth=mapContainer.offsetWidth||520;
const frontendMapHeight=mapContainer.offsetHeight||294;
const settingsMapWidth=520;
const settingsMapHeight=294;
let region_bounds=OUMUtils.latLngToBounds(parseFloat(region_lat),
parseFloat(region_lng),
parseFloat(region_zoom),
settingsMapWidth,
settingsMapHeight
);
const regionBounds=L.latLngBounds(L.latLng(region_bounds[0][0], region_bounds[0][1]),
L.latLng(region_bounds[1][0], region_bounds[1][1])
);
const settingsAspectRatio=settingsMapWidth / settingsMapHeight;
const frontendAspectRatio=frontendMapWidth / frontendMapHeight;
const aspectRatioDifference=Math.abs(settingsAspectRatio - frontendAspectRatio);
let region_bounds_zoom;
if(aspectRatioDifference < 0.01){
const widthRatio=frontendMapWidth / settingsMapWidth;
const zoomAdjustment=Math.log2(widthRatio);
region_bounds_zoom=parseFloat(region_zoom) + zoomAdjustment;
}else{
region_bounds_zoom=map.getBoundsZoom(regionBounds, false);
}
flyMainMapTo([region_lat, region_lng], region_bounds_zoom);
document
.querySelectorAll(".open-user-map .change_region")
.forEach(function (el){
el.classList.remove("active");
});
el.classList.add("active");
};
const REGION_ID=OUMUtils.getParameterByName("region");
if(btn.textContent==REGION_ID){
btn.click();
}});
}
return {
init: function (mapEl){
try {
initializeStartPosition();
map=L.map(mapEl, {
gestureHandling: oum_enable_scrollwheel_zoom_map ? false:true,
minZoom: 1,
zoomSnap: isClusterZoomLocked() ? 1:0.01,
zoomDelta: 1,
attributionControl: true,
fullscreenControl: oum_enable_fullscreen,
fullscreenControlOptions: {
position: "topleft",
fullscreenElement: document.querySelector(".open-user-map .map-wrap"
),
},
});
map.attributionControl.setPrefix(false);
setupTileLayer(OUMConfig.getMapStyle());
map.invalidateSize();
const mapContainer=map.getContainer();
const frontendMapWidth=mapContainer.offsetWidth||520;
const frontendMapHeight=mapContainer.offsetHeight||294;
const settingsMapWidth=520;
const settingsMapHeight=294;
const settingsAspectRatio=settingsMapWidth / settingsMapHeight;
const frontendAspectRatio=frontendMapWidth / frontendMapHeight;
const aspectRatioDifference=Math.abs(settingsAspectRatio - frontendAspectRatio);
const settingsBoundsArray=OUMUtils.latLngToBounds(startPosition.lat,
startPosition.lng,
startPosition.zoom,
settingsMapWidth,
settingsMapHeight
);
const settingsBounds=L.latLngBounds(L.latLng(settingsBoundsArray[0][0], settingsBoundsArray[0][1]),
L.latLng(settingsBoundsArray[1][0], settingsBoundsArray[1][1])
);
let targetZoom;
if(aspectRatioDifference < 0.01){
const widthRatio=frontendMapWidth / settingsMapWidth;
const zoomAdjustment=Math.log2(widthRatio);
targetZoom=startPosition.zoom + zoomAdjustment;
}else{
targetZoom=map.getBoundsZoom(settingsBounds, false);
}
targetZoom=normalizeMainMapZoom(targetZoom);
setMainMapView([startPosition.lat, startPosition.lng], targetZoom, {
animate: false
});
setupMapBounds();
setupMapEvents();
setupRegionEvents();
window.oumMap=map;
document.addEventListener('oum:markers_initialized', function(e){
if(e.detail.mapId===mapEl){
setupControls();
}}, { once: true });
document.dispatchEvent(new CustomEvent('oum:map_initialized', {
detail: {
mapId: mapEl,
map: oumMap
}}));
return map;
} catch (error){
OUMErrorHandler.showError("Error initializing map: " + error.message);
throw error;
}},
getMap: function (){
return map;
},
getStartPosition: function (){
return startPosition;
},
};})();
const OUMMarkers=(function (){
let markersLayer=null;
let allMarkers=[];
let map=null;
let locationsById={};
let searchtextFilterValue="";
let categoriesFilterSelection=null;
let customfieldsFilterSelection=null;
let visibleMarkersCount=0;
function initializeMarkersLayer(){
markersLayer = !oum_enable_cluster
? L.layerGroup({ chunkedLoading: true })
: L.markerClusterGroup({
showCoverageOnHover: false,
removeOutsideVisibleBounds: true,
maxClusterRadius: 100,
chunkedLoading: true,
});
}
function oumBubbleLoadingHtml(){
const label =
typeof oum_custom_strings!=="undefined"&&oum_custom_strings.bubble_loading
? String(oum_custom_strings.bubble_loading)
.replace(/\\/g, "\\\\")
.replace(/"/g, "&quot;")
: "Loading";
return (
'<div class="oum-bubble-loading" role="status" aria-live="polite" aria-busy="true" aria-label="' +
label +
'"><span class="oum-bubble-loading-spinner" aria-hidden="true"></span></div>'
);
}
function oumBubbleErrorHtml(){
const msg =
typeof oum_custom_strings!=="undefined"&&oum_custom_strings.bubble_load_error
? oum_custom_strings.bubble_load_error
: "Unable to load location details.";
return '<div class="oum-bubble-error" role="alert">' + msg + "</div>";
}
function finalizeMarkerBubbleUI(popup){
const el=document.querySelector(".open-user-map #location-fullscreen-container");
const locationContentWrap=el ? el.querySelector(".location-content-wrap"):null;
if(locationContentWrap){
locationContentWrap.innerHTML=popup.getContent();
}
if(el){
el.classList.add("visible");
document.querySelector("body").classList.add("oum-location-opened");
}
if(locationContentWrap){
checkEditPermissionAndInjectButton(locationContentWrap);
}
const popupContent=popup.getElement();
if(popupContent){
checkEditPermissionAndInjectButton(popupContent);
}
if(window.OUMVoteHandler&&window.OUMVoteHandler.updateVoteButtonStates){
window.OUMVoteHandler.updateVoteButtonStates();
}
if(window.OUMVoteHandler&&window.OUMVoteHandler.initializeVoteCountsFromData){
const voteButtons=el ? el.querySelectorAll(".oum_vote_button"):[];
if(voteButtons.length > 0){
window.OUMVoteHandler.initializeVoteCountsFromData();
}}
if(window.OUMVoteHandler&&window.OUMVoteHandler.initializeStarRatings){
const starRatings=el ? el.querySelectorAll(".oum_star_rating"):[];
if(starRatings.length > 0){
window.OUMVoteHandler.initializeStarRatings();
}}
if(locationContentWrap){
OUMOpeningHours.setupToggle(locationContentWrap);
}
if(popupContent){
OUMOpeningHours.setupToggle(popupContent);
}}
function createMarker(location){
const searchBody=(location.content||"")
.toString()
.replace(/(<([^>]+)>)/gi, " ")
.replace(/\s\s+/g, " ");
const contentText=(location.title + " | " + searchBody).toLowerCase();
let marker=L.marker([location.lat, location.lng], {
title: location.title,
post_id: location.post_id,
content: contentText,
zoom: location.zoom,
icon: L.icon({
iconUrl: location.icon,
iconSize: [26, 41],
iconAnchor: [13, 41],
popupAnchor: [0, -25],
shadowUrl: marker_shadow_url,
shadowSize: [41, 41],
shadowAnchor: [13, 41],
}),
types: location.types||[],
});
if(typeof oum_hide_location_popup==="undefined"||!oum_hide_location_popup){
const popup=L.responsivePopup().setContent(oumBubbleLoadingHtml());
marker.bindPopup(popup);
}
return marker;
}
function setupMarkerEvents(){
map.on("popupopen", function (locationBubble){
const popup=locationBubble.popup;
const marker=popup._source;
const applyBubbleHtml=(html)=> {
popup.setContent(html);
if(typeof popup.update==="function"){
popup.update();
}
finalizeMarkerBubbleUI(popup);
};
if(!marker||!marker.options||!marker.options.post_id){
finalizeMarkerBubbleUI(popup);
return;
}
if(marker._oumBubbleHtmlCache){
applyBubbleHtml(marker._oumBubbleHtmlCache);
return;
}
marker._oumBubbleFetchId=(marker._oumBubbleFetchId||0) + 1;
const myFetchId=marker._oumBubbleFetchId;
const postId=marker.options.post_id;
popup.setContent(oumBubbleLoadingHtml());
if(typeof popup.update==="function"){
popup.update();
}
finalizeMarkerBubbleUI(popup);
if(typeof jQuery==="undefined" ||
!oum_ajax ||
!oum_ajax.ajaxurl ||
!oum_ajax.bubble_nonce
){
applyBubbleHtml(oumBubbleErrorHtml());
return;
}
jQuery.ajax({
type: "POST",
url: oum_ajax.ajaxurl,
dataType: "json",
data: {
action: oum_ajax.bubble_action||"oum_get_location_bubble",
nonce: oum_ajax.bubble_nonce,
post_id: postId,
},
success: function (response){
if(myFetchId!==marker._oumBubbleFetchId){
return;
}
if(response&&response.success&&response.data&&response.data.html){
marker._oumBubbleHtmlCache=response.data.html;
applyBubbleHtml(response.data.html);
}else{
applyBubbleHtml(oumBubbleErrorHtml());
}},
error: function (){
if(myFetchId!==marker._oumBubbleFetchId){
return;
}
applyBubbleHtml(oumBubbleErrorHtml());
},
});
});
map.on("popupclose", function (){
const el=document.querySelector(".open-user-map #location-fullscreen-container"
);
if(el){
const locationContentWrap=el.querySelector(".location-content-wrap");
if(locationContentWrap){
locationContentWrap.innerHTML='';
}
el.classList.remove("visible");
}
document.querySelector("body").classList.remove("oum-location-opened");
});
}
function checkEditPermissionAndInjectButton(container){
const placeholder=container.querySelector('.edit-location-button-placeholder');
if(!placeholder){
return;
}
const postId=placeholder.getAttribute('data-post-id');
if(!postId){
placeholder.remove();
return;
}
if(typeof jQuery==='undefined'){
placeholder.remove();
return;
}
if(!oum_ajax||!oum_ajax.ajaxurl){
placeholder.remove();
return;
}
jQuery.ajax({
type: 'POST',
url: oum_ajax.ajaxurl,
dataType: 'json',
data: {
action: 'oum_check_edit_permission',
post_id: postId
},
success: function(response){
if(response&&response.success&&response.data&&response.data.can_edit){
const editButton=document.createElement('div');
editButton.className='edit-location-button';
editButton.setAttribute('data-post-id', postId);
editButton.setAttribute('title', oum_custom_strings&&oum_custom_strings.edit_location ? oum_custom_strings.edit_location:'Edit location');
placeholder.parentNode.replaceChild(editButton, placeholder);
}else{
placeholder.remove();
}},
error: function(xhr, status, error){
placeholder.remove();
}});
}
function applyFilters(){
if(!markersLayer){
return;
}
markersLayer.clearLayers();
const filteredMarkers=[];
allMarkers.forEach((marker)=> {
if(markerMatchesSearchtextFilter(marker) &&
markerMatchesCategoriesFilter(marker) &&
markerMatchesCustomfieldsFilter(marker)
){
filteredMarkers.push(marker);
}});
visibleMarkersCount=filteredMarkers.length;
addMarkersToLayer(filteredMarkers);
if(oum_enable_cluster&&typeof markersLayer.refreshClusters==="function"){
markersLayer.refreshClusters();
}}
function addMarkersToLayer(markers){
if(!markersLayer||!markers.length){
return;
}
if(oum_enable_cluster &&
markers.length===1 &&
typeof markersLayer.addLayer==="function"
){
markersLayer.addLayer(markers[0]);
return;
}
if(typeof markersLayer.addLayers==="function"){
markersLayer.addLayers(markers);
return;
}
markers.forEach((marker)=> {
markersLayer.addLayer(marker);
});
}
function markerMatchesSearchtextFilter(marker){
if(!searchtextFilterValue){
return true;
}
return marker.options.content.toLowerCase().includes(searchtextFilterValue);
}
function markerMatchesCategoriesFilter(marker){
const markerTypes=marker.options.types||[];
if(!markerTypes.length){
return true;
}
if(categoriesFilterSelection===null){
return true;
}
if(!categoriesFilterSelection.size){
return false;
}
return markerTypes.some((type)=> categoriesFilterSelection.has(type));
}
function markerMatchesCustomfieldsFilter(marker){
if(!customfieldsFilterSelection||!Object.keys(customfieldsFilterSelection).length){
return true;
}
const locationData=getLocationData(marker.options.post_id);
if(!locationData){
return true;
}
for (const [customFieldId, criterion] of Object.entries(customfieldsFilterSelection)){
if(criterion.type==='opening_hours_open_now'){
const field=locationData.custom_fields?.find((customField)=> String(customField.index)===String(customFieldId)
);
if(field&&typeof field.open_now==='boolean'){
if(field.open_now!==true){
return false;
}}else{
return false;
}
continue;
}
const fieldValue=getCustomFieldValue(locationData, customFieldId);
if(!matchesCriterion(fieldValue, criterion)){
return false;
}}
return true;
}
function getLocationData(postId){
if(!postId){
return null;
}
if(locationsById[String(postId)]){
return locationsById[String(postId)];
}
if(typeof window!=="undefined"&&Array.isArray(window.oum_all_locations)){
const fallback=window.oum_all_locations.find((location)=> String(location.post_id)===String(postId)
);
if(fallback){
locationsById[String(postId)]=fallback;
return fallback;
}}
return null;
}
function getCustomFieldValue(locationData, customFieldId){
if(!locationData||!Array.isArray(locationData.custom_fields)){
return null;
}
const field=locationData.custom_fields.find((customField)=> String(customField.index)===String(customFieldId)
);
return field ? field.val:null;
}
function normalizeFieldValues(fieldValue){
if(Array.isArray(fieldValue)){
return fieldValue.map((val)=> val.toString()).filter((val)=> val!=="");
}
if(typeof fieldValue==="string"){
return fieldValue
.split("|")
.map((val)=> val.trim())
.filter((val)=> val!=="");
}
if(fieldValue!==null&&typeof fieldValue!=="undefined"){
const value=fieldValue.toString();
return value ? [value]:[];
}
return [];
}
function matchesCriterion(fieldValue, criterion){
if(fieldValue===null ||
typeof fieldValue==="undefined" ||
(typeof fieldValue==="string"&&fieldValue.trim()==="") ||
(Array.isArray(fieldValue)&&fieldValue.length===0)
){
return false;
}
switch (criterion.type){
case "text":
return fieldValue.toString().toLowerCase().includes(criterion.value);
case "checkbox": {
const values=normalizeFieldValues(fieldValue);
const relation=criterion.relation||'OR';
if(relation==='AND'){
return criterion.values.length > 0&&criterion.values.every((val)=> values.includes(val));
}else{
return criterion.values.some((val)=> values.includes(val));
}}
case "radio":
case "select": {
const values=normalizeFieldValues(fieldValue);
return values.includes(criterion.value);
}
default:
return true;
}}
function updateSearchtextAndCategoriesFilters(){
const markerFilterInput=document.getElementById("oum_filter_markers");
searchtextFilterValue=markerFilterInput ? markerFilterInput.value.toLowerCase():"";
const categoryInputs=document.querySelectorAll('.open-user-map .oum-filter-controls [name="type"]'
);
categoriesFilterSelection=new Set(
Array.from(categoryInputs)
.filter((input)=> input.checked)
.map((input)=> input.value)
);
applyFilters();
}
function setupFilterListEvents(){
const filterControls=document.querySelector(".open-user-map .oum-filter-controls"
);
if(!filterControls) return;
const closeButton=filterControls.querySelector(".close-filter-list");
const toggle=filterControls.querySelector(".oum-filter-toggle");
const filterWrapper=filterControls.closest(".oum-map-filter-wrapper");
if(closeButton){
closeButton.addEventListener("click", function(e){
e.stopPropagation();
filterControls.classList.remove("active");
filterControls.classList.add("use-collapse");
});
}
if(toggle){
toggle.addEventListener("click", function(e){
e.stopPropagation();
filterControls.classList.toggle("active");
});
}
if(filterWrapper){
document.addEventListener("click", function(e){
if(filterControls.classList.contains("use-collapse")&&!filterWrapper.contains(e.target)){
filterControls.classList.remove("active");
}});
}
function setupToggleAll(){
const toggleAllCheckbox=filterControls.querySelector(".oum-toggle-all-checkbox"
);
const categoryCheckboxes=filterControls.querySelectorAll('[name="type"]'
);
if(!toggleAllCheckbox||categoryCheckboxes.length===0) return;
function updateToggleAllState(){
const checkedCount=Array.from(categoryCheckboxes).filter((cb)=> cb.checked
).length;
const totalCount=categoryCheckboxes.length;
if(checkedCount===0){
toggleAllCheckbox.checked=false;
toggleAllCheckbox.indeterminate=false;
}else if(checkedCount===totalCount){
toggleAllCheckbox.checked=true;
toggleAllCheckbox.indeterminate=false;
}else{
toggleAllCheckbox.checked=false;
toggleAllCheckbox.indeterminate=true;
}}
function toggleAllCategories(){
const checkedCount=Array.from(categoryCheckboxes).filter((cb)=> cb.checked
).length;
const totalCount=categoryCheckboxes.length;
const shouldCheck=checkedCount < totalCount;
categoryCheckboxes.forEach((checkbox)=> {
checkbox.checked=shouldCheck;
});
updateSearchtextAndCategoriesFilters();
}
toggleAllCheckbox.addEventListener("change", toggleAllCategories);
categoryCheckboxes.forEach((checkbox)=> {
checkbox.addEventListener("change", updateToggleAllState);
});
updateToggleAllState();
}
setupToggleAll();
}
function handleAutoOpenMarker(markerId){
const targetMarker=allMarkers.find((m)=> m.options.post_id===markerId);
if(targetMarker){
const openPopup=typeof oum_hide_location_popup==="undefined"||!oum_hide_location_popup;
if(oum_enable_cluster){
setTimeout(()=> {
markersLayer.zoomToShowLayer(targetMarker, ()=> {
if(openPopup) targetMarker.openPopup();
});
}, 500);
}else{
map.setView(targetMarker.getLatLng(), targetMarker.options.zoom);
if(openPopup) targetMarker.openPopup();
}}
}
return {
init: function (mapInstance){
map=mapInstance;
initializeMarkersLayer();
markersLayer.addTo(map);
setupMarkerEvents();
setupFilterListEvents();
window.oumMarkersLayer=markersLayer;
window.oumAllMarkers=allMarkers;
document.dispatchEvent(new CustomEvent('oum:markers_initialized', {
detail: {
mapId: map._container.id,
markersLayer: markersLayer
}}));
return this;
},
addMarkers: function (locations){
locations.forEach((location)=> {
const marker=createMarker(location);
allMarkers.push(marker);
locationsById[String(location.post_id)]=location;
});
applyFilters();
const POPUP_MARKER_ID=OUMUtils.getParameterByName("markerid");
if(POPUP_MARKER_ID){
handleAutoOpenMarker(POPUP_MARKER_ID);
}},
updateSearchtextAndCategoriesFilters: updateSearchtextAndCategoriesFilters,
getMarkersLayer: function (){
return markersLayer;
},
getAllMarkers: function (){
return allMarkers;
},
getAllLocations: function (){
return Object.values(locationsById);
},
setCustomfieldsFilter: function (criteria){
if(criteria&&Object.keys(criteria).length > 0){
customfieldsFilterSelection=criteria;
}else{
customfieldsFilterSelection=null;
}
applyFilters();
},
getFilterState: function (){
return {
searchtext: searchtextFilterValue,
categories:
categoriesFilterSelection===null
? null
: Array.from(categoriesFilterSelection),
customfields: customfieldsFilterSelection
};},
getFilteredMarkersCount: function (){
return visibleMarkersCount;
},
invalidateBubbleHtmlCacheForPost: function (postId){
const id=String(postId);
allMarkers.forEach((m)=> {
if(m&&m.options&&String(m.options.post_id)===id){
delete m._oumBubbleHtmlCache;
m._oumBubbleFetchId=0;
}});
},
};})();
const OUMFormMap=(function (){
let formMap=null;
let locationMarker=null;
let markerIsVisible=false;
let isAdjusting=false;
let isInitialized=false;
function initializeFormMap(){
if(isInitialized){
return;
}
formMap=L.map("mapGetLocation", {
attributionControl: false,
gestureHandling: true,
minZoom: 1,
zoomSnap: 0.01,
zoomDelta: 1,
fullscreenControl: oum_enable_fullscreen,
fullscreenControlOptions: {
position: "topleft",
},
});
window.oumMap2=formMap;
setupTileLayer();
setupControls();
setupMarker();
setupMapEvents();
formMap.invalidateSize();
const boundsToUse=oum_enable_fixed_map_bounds
? sharedMapBounds
: OUMConfig.defaults.map.bounds;
formMap.setMaxBounds(boundsToUse);
let maxVisibleBounds;
if(oum_enable_fixed_map_bounds&&sharedMapBounds){
formMap.invalidateSize();
maxVisibleBounds=formMap.getBoundsZoom(sharedMapBounds);
formMap.setMinZoom(maxVisibleBounds);
}else{
maxVisibleBounds=formMap.getBoundsZoom(boundsToUse);
}
formMap.on("moveend", function (){
if(isAdjusting) return;
isAdjusting=true;
const zoom=formMap.getZoom();
if(zoom > maxVisibleBounds){
const currentBounds=formMap.getBounds();
const currentCenter=formMap.getCenter();
let needsAdjustment=false;
let newLat=currentCenter.lat;
let newLng=currentCenter.lng;
const viewportHeight=currentBounds.getNorth() - currentBounds.getSouth();
const viewportWidth=currentBounds.getEast() - currentBounds.getWest();
if(currentBounds.getNorth() > boundsToUse.getNorth()){
newLat=boundsToUse.getNorth() - viewportHeight / 2;
needsAdjustment=true;
}else if(currentBounds.getSouth() < boundsToUse.getSouth()){
newLat=boundsToUse.getSouth() + viewportHeight / 2;
needsAdjustment=true;
}
if(currentBounds.getEast() > boundsToUse.getEast()){
newLng=boundsToUse.getEast() - viewportWidth / 2;
needsAdjustment=true;
}else if(currentBounds.getWest() < boundsToUse.getWest()){
newLng=boundsToUse.getWest() + viewportWidth / 2;
needsAdjustment=true;
}
if(needsAdjustment){
formMap.setView([newLat, newLng], zoom, { animate: false });
}}
isAdjusting=false;
});
formMap.on("zoomend", function (){
syncLocationZoomField();
});
updateMinZoom();
isInitialized=true;
}
function updateMinZoom(){
if(!formMap) return;
if(oum_enable_fixed_map_bounds&&sharedMapBounds){
formMap.invalidateSize();
const maxVisibleBounds=formMap.getBoundsZoom(sharedMapBounds);
formMap.setMinZoom(maxVisibleBounds);
}}
function setupTileLayer(){
const mapStyle=window.mapStyle||'OpenStreetMap.Mapnik';
if(mapStyle==="Custom1"){
L.tileLayer("https://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}.png").addTo(formMap);
L.tileLayer("https://{s}.basemaps.cartocdn.com/rastertiles/voyager_only_labels/{z}/{x}/{y}{r}.png", {
tileSize: 512,
zoomOffset: -1,
}).addTo(formMap);
}else if(mapStyle==="Custom2"){
L.tileLayer("https://{s}.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}.png").addTo(formMap);
L.tileLayer("https://{s}.basemaps.cartocdn.com/rastertiles/voyager_only_labels/{z}/{x}/{y}{r}.png", {
tileSize: 512,
zoomOffset: -1,
}).addTo(formMap);
}else if(mapStyle==="Custom3"){
L.tileLayer("https://{s}.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}.png").addTo(formMap);
L.tileLayer("https://{s}.basemaps.cartocdn.com/rastertiles/voyager_only_labels/{z}/{x}/{y}{r}.png", {
tileSize: 512,
zoomOffset: -1,
}).addTo(formMap);
}else if(mapStyle.startsWith("MapBox.")){
L.tileLayer.provider("MapBox", {
id: mapStyle.replace("MapBox.", "mapbox/") + (mapStyle.includes("-v") ? "":"-v12"),
accessToken: OUMConfig.getTileProviderKey(),
}).addTo(formMap);
}else if(mapStyle=="CustomImage"){
setupCustomImageLayer();
if(window.oum_custom_image_hide_tiles){
L.tileLayer('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==', {
attribution: '',
opacity: 0
}).addTo(formMap);
if(window.oum_custom_image_background_color){
formMap.getContainer().style.backgroundColor=window.oum_custom_image_background_color;
}}else{
L.tileLayer.provider("OpenStreetMap.Mapnik").addTo(formMap);
}}else{
L.tileLayer.provider(mapStyle).addTo(formMap);
}}
function setupControls(){
const search=new GeoSearch.GeoSearchControl({
style: "bar",
showMarker: false,
provider: OUMUtils.initGeosearchProvider(),
searchLabel: oum_searchaddress_label,
updateMap: false,
});
formMap.addControl(search);
if(oum_enable_currentlocation){
window.formMap_locate_process=L.control.locate({
flyTo: true,
showPopup: false,
}).addTo(formMap);
}}
function setupMarker(){
let markerIcon=L.icon({
iconUrl: marker_icon_url,
iconSize: [26, 41],
iconAnchor: [13, 41],
popupAnchor: [0, -25],
shadowUrl: marker_shadow_url,
shadowSize: [41, 41],
shadowAnchor: [13, 41],
});
locationMarker=L.marker([0, 0], {
icon: markerIcon,
draggable: true,
});
window.locationMarker=locationMarker;
window.markerIsVisible=markerIsVisible;
locationMarker.on("dragend", function (e){
setLocationLatLng(e.target.getLatLng());
});
}
function setupMapEvents(){
formMap.on("click locationfound", function (e){
let coords=e.latlng;
locationMarker.setLatLng(coords);
if(!markerIsVisible){
locationMarker.addTo(formMap);
markerIsVisible=true;
window.markerIsVisible=true;
}
setLocationLatLng(coords);
});
formMap.on("geosearch/showlocation", handleGeosearchSuccess);
}
function handleGeosearchSuccess(e){
let coords=e.marker._latlng;
let label=e.location.label;
const searchBar=document.querySelector(`#mapGetLocation .leaflet-geosearch-bar form`);
let isInBounds=true;
if(oum_enable_fixed_map_bounds==='on'&&sharedMapBounds){
isInBounds=sharedMapBounds.contains(coords);
}
if(!isInBounds&&oum_enable_fixed_map_bounds==='on'){
console.log("This search result is out of reach.");
if(searchBar){
searchBar.style.boxShadow="0 0 10px rgb(255, 111, 105)";
setTimeout(function (){
searchBar.style.boxShadow="0 1px 5px rgba(255, 255, 255, 0.65)";
}, 2000);
}}else{
setLocationLatLng(coords, label);
locationMarker.setLatLng(coords);
if(!markerIsVisible){
locationMarker.addTo(formMap);
markerIsVisible=true;
window.markerIsVisible=true;
}
handleValidGeosearchResult(e.location);
}}
function handleValidGeosearchResult(location){
if(location.bounds!==null){
formMap.flyToBounds(location.bounds);
}else if(location.raw.mapView){
formMap.flyToBounds([
[location.raw.mapView.south, location.raw.mapView.west],
[location.raw.mapView.north, location.raw.mapView.east],
]);
}else{
formMap.flyTo([location.y, location.x], 17);
}}
function setLocationLatLng(markerLatLng, address){
document.getElementById("oum_location_lat").value=markerLatLng.lat;
document.getElementById("oum_location_lng").value=markerLatLng.lng;
syncLocationZoomField();
if(shouldPerformReverseGeocoding()){
reverseGeocode(markerLatLng.lat, markerLatLng.lng, address);
}}
function syncLocationZoomField(){
const zoomField=document.getElementById("oum_location_zoom");
if(!zoomField||!formMap){
return;
}
zoomField.value=formMap.getZoom();
}
function shouldPerformReverseGeocoding(){
const subtitleEnabled=typeof window.oum_enable_address!=='undefined'&&window.oum_enable_address==='on';
const autofillEnabled=typeof window.oum_enable_address_autofill!=='undefined'&&window.oum_enable_address_autofill==='on';
return subtitleEnabled&&autofillEnabled;
}
function formatAddressFromResponse(addressData, displayName){
const addressParts=[];
if(addressData.house_number) addressParts.push(addressData.house_number);
if(addressData.road) addressParts.push(addressData.road);
if(addressData.suburb) addressParts.push(addressData.suburb);
if(addressData.city||addressData.town||addressData.village){
addressParts.push(addressData.city||addressData.town||addressData.village);
}
if(addressData.postcode) addressParts.push(addressData.postcode);
if(addressData.country) addressParts.push(addressData.country);
return addressParts.length > 0 
? addressParts.join(', ')
: displayName||'Address not found';
}
function reverseGeocode(lat, lng, providedAddress){
if(providedAddress&&providedAddress.trim()){
handleAddressResult(providedAddress.trim());
return;
}
if(!OUMUtils.validateCoordinates(lat, lng)){
console.warn('Open User Map: Invalid coordinates for reverse geocoding');
return;
}
const url=`https://nominatim.openstreetmap.org/reverse?format=json&lat=${lat}&lon=${lng}&zoom=18&addressdetails=1`;
fetch(url, {
headers: {
'User-Agent': 'OpenUserMap/1.0'
}})
.then(response=> {
if(!response.ok){
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then(data=> {
if(data&&data.address){
const address=formatAddressFromResponse(data.address, data.display_name);
handleAddressResult(address);
}else{
console.log('Open User Map: No address found for coordinates:', lat, lng);
}})
.catch(error=> {
console.warn('Open User Map: Reverse geocoding error:', error);
});
}
function handleAddressResult(address){
if(!address||typeof address!=='string'){
return;
}
console.log('Open User Map: Address:', address);
if(shouldPerformReverseGeocoding()){
const subtitleField=document.getElementById('oum_location_address');
if(subtitleField){
subtitleField.value=address;
}}
}
function setupCustomImageLayer(){
if(typeof window.oum_custom_image_url!=='undefined'&&window.oum_custom_image_url &&
typeof window.oum_custom_image_bounds!=='undefined'&&window.oum_custom_image_bounds){
const isSVG=window.oum_custom_image_url.toLowerCase().includes('.svg');
if(isSVG){
setupSVGFromFile();
}else{
setupImageOverlay();
}}else{
}}
function setupSVGFromFile(){
try {
const bounds=window.oum_custom_image_bounds;
if(!bounds||typeof bounds.north==='undefined'||typeof bounds.south==='undefined' ||
typeof bounds.east==='undefined'||typeof bounds.west==='undefined' ||
bounds.north===''||bounds.south===''||bounds.east===''||bounds.west===''){
console.warn('Open User Map: Invalid or empty bounds data, skipping SVG file layer');
return;
}
fetch(window.oum_custom_image_url)
.then(response=> response.text())
.then(svgText=> {
const svgElement=createSVGElement(svgText);
if(!svgElement){
console.warn('Open User Map: Cannot create SVG layer from file - invalid SVG element');
return;
}
const svgLayer=L.svgOverlay(svgElement, [
[bounds.north, bounds.west],
[bounds.south, bounds.east]
], {
opacity: 1.0,
interactive: true
});
svgLayer.addTo(formMap);
window.oumCustomSVGLayer=svgLayer;
console.log('Open User Map: Custom SVG file layer added successfully');
})
.catch(error=> {
console.warn('Open User Map: Error fetching SVG file:', error);
});
} catch (error){
console.warn('Open User Map: Error setting up custom SVG file layer:', error);
}}
function setupImageOverlay(){
try {
const bounds=window.oum_custom_image_bounds;
if(!bounds||typeof bounds.north==='undefined'||typeof bounds.south==='undefined' ||
typeof bounds.east==='undefined'||typeof bounds.west==='undefined' ||
bounds.north===''||bounds.south===''||bounds.east===''||bounds.west===''){
console.warn('Open User Map: Invalid or empty bounds data, skipping image layer');
return;
}
const imageOverlay=L.imageOverlay(window.oum_custom_image_url, [
[bounds.north, bounds.west],
[bounds.south, bounds.east]
], {
opacity: 1.0,
interactive: true
});
imageOverlay.addTo(formMap);
window.oumCustomImageLayer=imageOverlay;
console.log('Open User Map: Custom image layer added successfully');
} catch (error){
console.warn('Open User Map: Error setting up custom image layer:', error);
}}
function createSVGElement(svgText){
const tempDiv=document.createElement('div');
tempDiv.innerHTML=svgText;
const svgElement=tempDiv.querySelector('svg');
if(!svgElement){
console.warn('Open User Map: No valid SVG element found in SVG text');
return null;
}
if(!svgElement.getAttribute('viewBox')){
const width=svgElement.getAttribute('width');
const height=svgElement.getAttribute('height');
if(width&&height){
const widthNum=parseFloat(width);
const heightNum=parseFloat(height);
if(!isNaN(widthNum)&&!isNaN(heightNum)){
svgElement.setAttribute('viewBox', `0 0 ${widthNum} ${heightNum}`);
}else{
svgElement.setAttribute('viewBox', '0 0 1000 1200');
}}else{
svgElement.setAttribute('viewBox', '0 0 1000 1200');
}}
svgElement.style.width='100%';
svgElement.style.height='100%';
svgElement.style.display='block';
svgElement.setAttribute('preserveAspectRatio', 'none');
console.log('Open User Map: SVG element created successfully:', svgElement);
return svgElement;
}
return {
init: function(){
if(!document.getElementById("mapGetLocation")){
return;
}
initializeFormMap();
},
setLocation: function(lat, lng){
if(!locationMarker) return;
locationMarker.setLatLng([lat, lng]);
if(!markerIsVisible){
locationMarker.addTo(formMap);
markerIsVisible=true;
window.markerIsVisible=true;
}
setLocationLatLng({lat, lng});
},
clearMarker: function(){
if(locationMarker&&formMap){
locationMarker.remove();
markerIsVisible=false;
window.markerIsVisible=false;
}},
invalidateSize: function(){
if(formMap){
formMap.invalidateSize();
}},
updateMinZoom: function(){
updateMinZoom();
},
getMap: function(){
return formMap;
},
setView: function(lat, lng, zoom){
if(formMap){
formMap.setView([lat, lng], zoom);
syncLocationZoomField();
}},
setViewToMatchMainMap: function(mainMap){
if(!formMap||!mainMap) return;
formMap.invalidateSize();
const mainBounds=mainMap.getBounds();
const mainCenter=mainMap.getCenter();
const mainZoom=mainMap.getZoom();
const formMapContainer=formMap.getContainer();
const formMapWidth=formMapContainer.offsetWidth||520;
const formMapHeight=formMapContainer.offsetHeight||294;
const mainMapContainer=mainMap.getContainer();
const mainMapWidth=mainMapContainer.offsetWidth||520;
const mainMapHeight=mainMapContainer.offsetHeight||294;
const mainAspectRatio=mainMapWidth / mainMapHeight;
const formAspectRatio=formMapWidth / formMapHeight;
const aspectRatioDifference=Math.abs(mainAspectRatio - formAspectRatio);
let targetZoom;
if(aspectRatioDifference < 0.01){
const widthRatio=formMapWidth / mainMapWidth;
const zoomAdjustment=Math.log2(widthRatio);
targetZoom=mainZoom + zoomAdjustment;
}else{
targetZoom=formMap.getBoundsZoom(mainBounds, false);
}
formMap.setView([mainCenter.lat, mainCenter.lng], targetZoom, {
animate: false
});
}};})();
const OUMFormController=(function (){
let isEditMode=false;
let currentLocationId=null;
let selectedFiles=[];
function showFormMessage(type, headline, message, buttonText=null, buttonCallback=null){
const form=document.getElementById('oum_add_location');
const errorDiv=document.getElementById('oum_add_location_error');
const thankyouDiv=document.getElementById('oum_add_location_thankyou');
if(!form||!errorDiv||!thankyouDiv){
console.error('Required form elements not found');
return;
}
form.style.display='none';
errorDiv.style.display='none';
const headlineEl=thankyouDiv.querySelector('h3');
const messageEl=thankyouDiv.querySelector('.oum-add-location-thankyou-text');
const buttonEl=thankyouDiv.querySelector('button');
if(!headlineEl||!messageEl||!buttonEl){
if(!headlineEl){
const newHeadline=document.createElement('h3');
thankyouDiv.appendChild(newHeadline);
}
if(!messageEl){
const newMessage=document.createElement('p');
newMessage.className='oum-add-location-thankyou-text';
thankyouDiv.appendChild(newMessage);
}
if(!buttonEl){
const newButton=document.createElement('button');
thankyouDiv.appendChild(newButton);
}}
const finalHeadlineEl=thankyouDiv.querySelector('h3');
const finalMessageEl=thankyouDiv.querySelector('.oum-add-location-thankyou-text');
const finalButtonEl=thankyouDiv.querySelector('button');
thankyouDiv.className=type==='confirm-delete' ? 'oum-delete-confirmation':'';
if(finalHeadlineEl) finalHeadlineEl.textContent=headline||'';
if(finalMessageEl) finalMessageEl.textContent=message||'';
if(finalButtonEl){
if(buttonText&&buttonCallback){
finalButtonEl.textContent=buttonText;
finalButtonEl.onclick=buttonCallback;
finalButtonEl.style.display='inline-block';
}else{
finalButtonEl.style.display='none';
}}
thankyouDiv.style.display='block';
}
function setupDeleteButton(){
const deleteBtn=document.getElementById('oum_delete_location_btn');
if(deleteBtn){
deleteBtn.addEventListener('click', function(e){
e.preventDefault();
showFormMessage(
'confirm-delete',
oum_custom_strings.delete_location,
oum_custom_strings.delete_location_message,
oum_custom_strings.delete_location_button,
function(){
document.getElementById('oum_delete_location').value='true';
const form=document.getElementById('oum_add_location');
const formData=new FormData(form);
formData.append('action', 'oum_add_location_from_frontend');
jQuery.ajax({
type: 'POST',
url: oum_ajax.ajaxurl,
cache: false,
contentType: false,
processData: false,
data: formData,
success: function(response){
if(response.success){
showFormMessage(
'success',
oum_custom_strings.location_deleted,
oum_custom_strings.delete_success,
oum_custom_strings.close_and_refresh,
function(){
window.location.reload();
}
);
}else{
oumShowError(response.data);
}},
error: function(XMLHttpRequest, textStatus, errorThrown){
console.log(errorThrown);
oumShowError([{message: oum_custom_strings.delete_error}]);
}});
}
);
});
}}
function setupFormEvents(){
const addLocationBtn=document.getElementById("open-add-location-overlay");
if(addLocationBtn){
addLocationBtn.addEventListener("click", handleAddLocationClick);
}
document.addEventListener('click', function(e){
if(e.target&&e.target.classList.contains('edit-location-button')){
e.preventDefault();
const locationId=e.target.getAttribute('data-post-id');
const location=window.oum_all_locations.find(loc=> loc.post_id===locationId);
if(location){
resetForm();
openForm(location);
}}
});
setupCloseEvents();
setupNotificationEvents();
setupMediaEvents();
}
function refreshLocationNonce(){
const formEl=document.getElementById('oum_add_location');
if(!formEl||typeof oum_ajax==='undefined'){
return Promise.resolve();
}
const nonceField=formEl.querySelector('input[name="oum_location_nonce"]');
if(!nonceField||!oum_ajax.ajaxurl){
return Promise.resolve();
}
const action=oum_ajax.refresh_nonce_action||'oum_refresh_location_nonce';
return jQuery.ajax({
type: 'POST',
url: oum_ajax.ajaxurl,
dataType: 'json',
data: { action },
}).done(function(response){
if(response&&response.success&&response.data&&response.data.nonce){
nonceField.value=response.data.nonce;
}}).fail(function(){
console.warn('Open User Map: Unable to refresh nonce.');
});
}
function handleAddLocationClick(){
resetForm();
openForm();
}
function openForm(location=null){
refreshLocationNonce();
document.querySelector(".add-location").classList.add("active");
document.body.classList.add("oum-add-location-opened");
setTimeout(function (){
OUMFormMap.init();
setTimeout(function(){
OUMFormMap.updateMinZoom();
}, 100);
const applyAspectRatioAndView=()=> {
const mainMapEl=document.querySelector(`#${map_el}`);
if(mainMapEl){
const mainMap=window.oumMap;
if(mainMap){
const mainMapContainer=mainMap.getContainer();
const mainMapWidth=mainMapContainer.offsetWidth;
const mainMapHeight=mainMapContainer.offsetHeight;
if(mainMapWidth&&mainMapHeight){
const aspectRatio=mainMapWidth / mainMapHeight;
const formMapWrap=document.querySelector('.add-location .location-overlay-content .map-wrap');
if(formMapWrap){
formMapWrap.style.aspectRatio=aspectRatio.toString();
formMapWrap.style.height='auto';
}}
}}
if(location){
populateForm(location);
}else{
const mainMapEl=document.querySelector(`#${map_el}`);
if(mainMapEl){
const mainMap=window.oumMap;
OUMFormMap.setViewToMatchMainMap(mainMap);
}}
};
applyAspectRatioAndView();
requestAnimationFrame(applyAspectRatioAndView);
setTimeout(()=> {
OUMFormMap.invalidateSize();
if(!location){
const mainMapEl=document.querySelector(`#${map_el}`);
if(mainMapEl){
const mainMap=window.oumMap;
OUMFormMap.setViewToMatchMainMap(mainMap);
}}
}, 200);
}, 150);
}
function setupCloseEvents(){
const closeBtn=document.getElementById("close-add-location-overlay");
if(!closeBtn) return;
closeBtn.addEventListener("click", closeForm);
document.addEventListener("keydown", function(evt){
evt=evt||window.event;
if(evt.key==="Escape"&&document.getElementById("add-location-overlay").classList.contains("active")){
closeForm();
}});
document.getElementById("add-location-overlay").addEventListener("click", function(event){
if(event.target===this){
closeForm();
}});
}
function closeForm(){
const addLocationOverlay=document.getElementById("add-location-overlay");
if(addLocationOverlay){
addLocationOverlay.classList.remove("active");
}
if(window.formMap_locate_process){
window.formMap_locate_process.stop();
}
document.querySelector("body").classList.remove("oum-add-location-opened");
resetForm();
OUMFormMap.clearMarker();
}
function setupNotificationEvents(){
const notificationCheckbox=document.getElementById("oum_location_notification");
if(notificationCheckbox){
notificationCheckbox.addEventListener("change", function(){
const authorFields=document.getElementById("oum_author");
const nameField=document.getElementById("oum_location_author_name");
const emailField=document.getElementById("oum_location_author_email");
if(this.checked){
authorFields.classList.add("active");
nameField.required=true;
emailField.required=true;
}else{
authorFields.classList.remove("active");
nameField.required=false;
emailField.required=false;
}});
}}
function setupMediaEvents(){
const imageInput=document.getElementById("oum_location_images");
if(imageInput){
OUMMedia.initializeImageUpload(imageInput);
}
const removeImageBtn=document.getElementById("oum_remove_image");
if(removeImageBtn){
removeImageBtn.addEventListener("click", function(){
document.getElementById("oum_location_images_preview").innerHTML="";
});
}
const removeAudioBtn=document.getElementById("oum_remove_audio");
if(removeAudioBtn){
removeAudioBtn.addEventListener("click", function(){
const audioInput=document.getElementById("oum_location_audio");
const previewContainer=audioInput.nextElementSibling;
const previewDiv=previewContainer.querySelector('.audio-preview');
audioInput.value="";
if(previewDiv){
previewDiv.innerHTML='';
}
previewContainer.classList.remove("active");
document.getElementById("oum_remove_existing_audio").value="1";
});
}}
function setupCategoryDropdownIcons(){
const categorySelect=document.querySelector('select#oum_marker_icon');
if(categorySelect){
const wrapper=document.createElement('div');
wrapper.className='oum-category-dropdown-wrapper';
wrapper.style.position='relative';
categorySelect.parentNode.insertBefore(wrapper, categorySelect);
wrapper.appendChild(categorySelect);
const display=document.createElement('div');
display.className='oum-category-dropdown-display';
const icon=document.createElement('img');
icon.className='oum-category-dropdown-icon';
const text=document.createElement('span');
text.className='oum-category-dropdown-text';
display.appendChild(icon);
display.appendChild(text);
wrapper.insertBefore(display, categorySelect);
categorySelect.style.cssText=`
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
cursor: pointer;
z-index: 1;
`;
function updateDisplay(){
const selectedOption=categorySelect.options[categorySelect.selectedIndex];
if(selectedOption&&selectedOption.value){
const iconUrl=selectedOption.getAttribute('data-icon');
if(iconUrl){
icon.src=iconUrl;
icon.style.display='block';
}else{
icon.style.display='none';
}
text.textContent=selectedOption.textContent;
}else{
icon.style.display='none';
text.textContent='Select a category...';
}}
updateDisplay();
categorySelect.addEventListener('change', updateDisplay);
display.setAttribute('tabindex', '0');
display.addEventListener('keydown', function(e){
if(e.key==='Enter'||e.key===' '){
e.preventDefault();
categorySelect.focus();
categorySelect.click();
}});
}}
function populateForm(location){
isEditMode=true;
currentLocationId=location.post_id;
const addLocationEl=document.querySelector(".add-location");
if(addLocationEl){
addLocationEl.classList.add("edit-location");
}
const postIdField=document.getElementById("oum_post_id");
if(postIdField){
postIdField.value=location.post_id;
}
const titleField=document.getElementById("oum_location_title");
const latField=document.getElementById("oum_location_lat");
const lngField=document.getElementById("oum_location_lng");
const addressField=document.getElementById("oum_location_address");
if(titleField) titleField.value=location.title||"";
if(latField) latField.value=location.lat||"";
if(lngField) lngField.value=location.lng||"";
if(addressField) addressField.value=location.address||"";
if(location.types&&Array.isArray(location.types)){
if(typeof oum_enable_multiple_marker_types!=='undefined'&&oum_enable_multiple_marker_types=='true'){
const checkboxes=document.querySelectorAll('input[name="oum_marker_icon[]"]');
if(checkboxes.length > 0){
checkboxes.forEach(checkbox=> {
checkbox.checked=location.types.includes(checkbox.value);
});
}}else{
const markerSelect=document.querySelector('select#oum_marker_icon');
if(markerSelect){
markerSelect.value=location.types[0]||'';
const customDisplay=document.querySelector('.oum-category-dropdown-display');
if(customDisplay){
markerSelect.dispatchEvent(new Event('change'));
}}
}}
const descriptionField=document.getElementById("oum_location_text");
if(descriptionField){
descriptionField.value=location.text||"";
}
const videoField=document.getElementById("oum_location_video");
if(videoField&&location.video){
videoField.value=location.video;
}
if(location.custom_fields&&Array.isArray(location.custom_fields)){
location.custom_fields.forEach(field=> {
if(!field||typeof field.index==='undefined') return;
if(field.fieldtype==='checkbox'){
const fieldValues=Array.isArray(field.val) ? field.val:[field.val];
const checkboxes=document.querySelectorAll(`input[type="checkbox"][name="oum_location_custom_fields[${field.index}][]"]`
);
if(checkboxes.length > 0){
checkboxes.forEach(checkbox=> {
if(checkbox){
const checkboxValue=checkbox.value.trim();
const normalizedValues=fieldValues.map(val=> (val||'').toString().trim());
checkbox.checked=normalizedValues.includes(checkboxValue);
}});
}}else if(field.fieldtype==='radio'){
const radioInputs=document.querySelectorAll(`input[type="radio"][name="oum_location_custom_fields[${field.index}]"]`
);
if(radioInputs.length > 0){
radioInputs.forEach(radio=> {
if(radio){
radio.checked=radio.value===field.val;
}});
}}else if(field.fieldtype==='select'){
let input=document.querySelector(`[name="oum_location_custom_fields[${field.index}][]"]`);
const isMultiple = !!input;
if(!input){
input=document.querySelector(`[name="oum_location_custom_fields[${field.index}]"]`);
}
if(input&&input.tagName==='SELECT'){
const values=Array.isArray(field.val) ? field.val.map(v=> (v||'').toString().trim()):[(field.val||'').toString().trim()];
Array.from(input.options).forEach(opt=> {
opt.selected=values.includes((opt.value||'').toString().trim());
});
}}else if(field.fieldtype==='opening_hours'){
try {
const openingHoursData=JSON.parse(field.val);
if(openingHoursData&&typeof openingHoursData==='object'){
const hoursInput=document.querySelector(`input[name="oum_location_custom_fields[${field.index}][hours]"]`);
const fieldContainer=document.querySelector(`[data-custom-field-index="${field.index}"]`);
const use12hour=fieldContainer&&fieldContainer.dataset.use12hour==='1';
if(hoursInput&&typeof OUMOpeningHours!=='undefined'){
hoursInput.value=OUMOpeningHours.formatForInput(openingHoursData, use12hour);
}}
} catch (e){
const input=document.querySelector(`input[name="oum_location_custom_fields[${field.index}][hours]"]`);
if(input){
input.value=field.val||'';
}}
}else{
const input=document.querySelector(`[name="oum_location_custom_fields[${field.index}]"]`);
if(input){
input.value=field.val||'';
}}
});
}
if(location.image){
const imageUrls=location.image.split('|').filter(url=> url);
const previewContainer=document.getElementById('oum_location_images_preview');
const imageInput=document.getElementById('oum_location_images');
if(imageInput&&imageUrls.length > 0){
imageInput.removeAttribute('required');
}
if(previewContainer){
previewContainer.innerHTML='';
imageUrls.forEach(url=> {
if(!url) return;
const previewItem=document.createElement('div');
previewItem.className='image-preview-item existing-image';
previewItem.dataset.url=url;
previewItem.innerHTML=`
<img src="${url}" alt="Preview">
<div class="remove-image" title="Remove image">&times;</div>
<div class="drag-handle" title="Drag to reorder">⋮⋮</div>
<input type="hidden" name="existing_images[]" value="${url}">
`;
const removeButton=previewItem.querySelector('.remove-image');
if(removeButton){
removeButton.addEventListener('click', OUMMedia.handleRemoveImage);
}
OUMMedia.setupDragAndDrop(previewItem);
previewItem.style.opacity="0";
previewItem.style.transform="scale(0.9)";
previewItem.style.transition="all 0.3s ease";
previewItem.style.opacity="1";
previewItem.style.transform="scale(1)";
previewContainer.appendChild(previewItem);
});
}}
if(location.audio){
OUMMedia.setExistingAudio(location.audio);
document.getElementById("oum_remove_existing_audio").value="0";
}
if(location.lat&&location.lng){
const locationZoom=location.zoom ? Number(location.zoom):12;
OUMFormMap.setView(location.lat, location.lng, locationZoom);
OUMFormMap.setLocation(location.lat, location.lng);
}
OUMCheckboxValidation.syncAllGroups();
}
function resetForm(){
isEditMode=false;
currentLocationId=null;
selectedFiles=[];
window.oumSelectedFiles=[];
const addLocationEl=document.querySelector(".add-location");
if(addLocationEl){
addLocationEl.classList.remove("edit-location");
}
const form=document.getElementById("oum_add_location");
const errorDiv=document.getElementById("oum_add_location_error");
const thankyouDiv=document.getElementById("oum_add_location_thankyou");
if(form){
form.reset();
form.style.display='block';
}
if(window.map_locate_process){
window.map_locate_process.stop();
}
const customFields=document.querySelectorAll('[name^="oum_location_custom_fields"]');
if(customFields){
customFields.forEach(field=> {
if(field.type==='checkbox'||field.type==='radio'){
field.checked=false;
}else if(field.type==='select-one'){
field.selectedIndex=0;
}else{
field.value='';
}});
}
const postIdField=document.getElementById("oum_post_id");
if(postIdField){
postIdField.value="";
}
const deleteLocationField=document.getElementById("oum_delete_location");
if(deleteLocationField){
deleteLocationField.value="";
}
if(errorDiv){
errorDiv.style.display='none';
}
if(thankyouDiv){
thankyouDiv.style.display='none';
thankyouDiv.classList.remove('oum-delete-confirmation');
}
const previewContainer=document.getElementById("oum_location_images_preview");
if(previewContainer){
previewContainer.innerHTML="";
}
const audioInput=document.getElementById("oum_location_audio");
if(audioInput){
const previewContainer=audioInput.nextElementSibling;
const previewDiv=previewContainer.querySelector('.audio-preview');
audioInput.value="";
if(previewDiv){
previewDiv.innerHTML='';
}
previewContainer.classList.remove("active");
}
const removeExistingImage=document.getElementById("oum_remove_existing_image");
if(removeExistingImage){
removeExistingImage.value="0";
}
const removeExistingAudio=document.getElementById("oum_remove_existing_audio");
if(removeExistingAudio){
removeExistingAudio.value="0";
}
const authorSection=document.getElementById("oum_author");
if(authorSection){
authorSection.classList.remove("active");
}
const nameField=document.getElementById("oum_location_author_name");
const emailField=document.getElementById("oum_location_author_email");
if(nameField&&emailField){
nameField.required=false;
emailField.required=false;
}}
return {
init: function(){
setupFormEvents();
setupDeleteButton();
setupCategoryDropdownIcons();
},
showFormMessage: showFormMessage,
openForm: openForm,
closeForm: closeForm,
resetForm: resetForm,
populateForm: populateForm,
isEditMode: function(){
return isEditMode;
},
getCurrentLocationId: function(){
return currentLocationId;
}};})();
const OUMMedia=(function (){
let selectedFiles=[];
let startX, startY, originalPosition, placeholder;
let isDragging=false;
function initializeImageUpload(imageInput){
if(!imageInput) return;
const uploadLabel=imageInput.parentElement.querySelector('label[for="oum_location_images"]'
);
if(uploadLabel){
uploadLabel.addEventListener("click", function (e){
e.preventDefault();
imageInput.click();
});
}
document.addEventListener("mousemove", handleDragMove);
document.addEventListener("mouseup", handleDragEnd);
if(imageInput.parentElement.querySelector(".image-preview-container")){
imageInput.parentElement.querySelector(".image-preview-container").addEventListener("dragover", handleDragOver);
}
imageInput.addEventListener("change", handleImageInputChange);
}
function initializeAudioUpload(){
const audioInput=document.getElementById('oum_location_audio');
if(!audioInput) return;
const uploadLabel=audioInput.parentElement.querySelector('label[for="oum_location_audio"]'
);
if(uploadLabel){
uploadLabel.addEventListener("click", function (e){
e.preventDefault();
audioInput.click();
});
}
audioInput.addEventListener("change", handleAudioInputChange);
}
function handleAudioInputChange(e){
const audioInput=e.target;
const previewContainer=audioInput.nextElementSibling;
const previewDiv=previewContainer.querySelector('.audio-preview');
if(audioInput.files&&audioInput.files[0]){
const file=audioInput.files[0];
previewContainer.classList.add('active');
const audio=document.createElement('audio');
audio.controls=true;
audio.style.width='100%';
const source=document.createElement('source');
source.src=URL.createObjectURL(file);
source.type=file.type;
audio.appendChild(source);
previewDiv.innerHTML='';
previewDiv.appendChild(audio);
}}
function setExistingAudio(audioUrl){
if(!audioUrl) return;
const audioInput=document.getElementById('oum_location_audio');
if(!audioInput) return;
const previewContainer=audioInput.nextElementSibling;
const previewDiv=previewContainer.querySelector('.audio-preview');
previewContainer.classList.add('active');
const audio=document.createElement('audio');
audio.controls=true;
audio.style.width='100%';
const source=document.createElement('source');
source.src=audioUrl;
source.type='audio/' + audioUrl.split('.').pop();
audio.appendChild(source);
previewDiv.innerHTML='';
previewDiv.appendChild(audio);
}
function handleImageInputChange(e){
const imageInput=e.target;
const previewContainer=document.getElementById("oum_location_images_preview"
);
const maxFiles=parseInt(imageInput.dataset.maxFiles)||5;
const maxFileSize=OUMConfig.defaults.media.maxImageSize;
const files=Array.prototype.slice.call(e.target.files);
const existingCount=selectedFiles.length;
const totalFiles=existingCount + files.length;
if(totalFiles > maxFiles){
alert(
OUMUtils.sprintf(oum_custom_strings.max_files_exceeded,
maxFiles,
maxFiles - existingCount
)
);
}
const remainingSlots=maxFiles - existingCount;
const filesToProcess=files.slice(0, remainingSlots);
const validFiles=[];
const invalidFiles=[];
filesToProcess.forEach(file=> {
if(file.size > maxFileSize){
invalidFiles.push(file.name);
}else{
validFiles.push(file);
}});
if(invalidFiles.length > 0){
const maxSizeMB=Math.round(maxFileSize / (1024 * 1024));
alert(
OUMUtils.sprintf(oum_custom_strings.max_filesize_exceeded,
maxSizeMB,
invalidFiles.join('\n')
)
);
}
selectedFiles=[...selectedFiles, ...validFiles];
createImagePreviews(validFiles, previewContainer);
window.oumSelectedFiles=selectedFiles;
}
function createImagePreviews(files, container){
files.forEach((file)=> {
const reader=new FileReader();
reader.onload=function (e){
const previewItem=createPreviewItem(e.target.result, file.name);
previewItem.style.opacity="0";
previewItem.style.transform="scale(0.9)";
container.appendChild(previewItem);
setTimeout(()=> {
previewItem.style.transition="all 0.3s ease";
previewItem.style.opacity="1";
previewItem.style.transform="scale(1)";
}, 50);
};
reader.readAsDataURL(file);
});
}
function createPreviewItem(imgSrc, fileName){
const previewItem=document.createElement("div");
previewItem.className="image-preview-item";
previewItem.dataset.fileName=fileName;
previewItem.innerHTML=`
<img src="${imgSrc}" alt="Preview">
<div class="remove-image" title="Remove image">&times;</div>
<div class="drag-handle" title="Drag to reorder">⋮⋮</div>
`;
const removeButton=previewItem.querySelector('.remove-image');
if(removeButton){
removeButton.addEventListener('click', handleRemoveImage);
}
setupDragAndDrop(previewItem);
return previewItem;
}
function handleRemoveImage(e){
e.preventDefault();
const previewItem=this.closest(".image-preview-item");
if(previewItem.classList.contains("existing-image")){
const imgUrl=previewItem.querySelector("[name='existing_images[]']").value;
const removedImagesInput=document.getElementById("oum_remove_existing_image");
const currentValue=removedImagesInput.value==="0" ? []:removedImagesInput.value.split('|');
currentValue.push(imgUrl);
removedImagesInput.value=currentValue.join('|');
}else{
const fileName=previewItem.dataset.fileName;
selectedFiles=selectedFiles.filter(file=> file.name!==fileName);
window.oumSelectedFiles=selectedFiles;
}
previewItem.style.transition="all 0.3s ease";
previewItem.style.transform="scale(0.8)";
previewItem.style.opacity="0";
setTimeout(()=> {
previewItem.remove();
}, 300);
}
function setupDragAndDrop(previewItem){
previewItem.setAttribute('draggable', 'true');
previewItem.addEventListener('mousedown', function(e){
if(e.target.classList.contains('remove-image')) return;
isDragging=true;
this.classList.add('dragging');
const rect=this.getBoundingClientRect();
this.style.width=rect.width + 'px';
this.style.height=rect.height + 'px';
this.initialContainer=this.closest('.oum-image-preview-grid');
createPlaceholder(this);
this.style.position='fixed';
this.style.zIndex='1000';
this.style.opacity='0.9';
this.style.transform='scale(1.05) rotate(1deg)';
this.style.pointerEvents='none';
this.style.boxShadow='0 5px 15px rgba(0,0,0,0.15)';
moveDraggedElement(this, e);
document.body.style.cursor='grabbing';
});
previewItem.addEventListener('touchstart', handleTouchStart);
}
function createPlaceholder(element){
placeholder=document.createElement("div");
placeholder.classList.add("image-preview-placeholder");
placeholder.style.width=element.offsetWidth + "px";
placeholder.style.height=element.offsetHeight + "px";
placeholder.style.transition="transform 0.2s ease";
placeholder.style.border="2px dashed #e82c71";
placeholder.style.borderRadius="4px";
placeholder.style.backgroundColor="rgba(224, 42, 175, 0.05)";
element.parentNode.insertBefore(placeholder, element);
}
function moveDraggedElement(draggable, e){
const rect=draggable.getBoundingClientRect();
const centerOffsetX=rect.width / 2;
const centerOffsetY=rect.height / 2;
draggable.style.left=(e.clientX - centerOffsetX) + 'px';
draggable.style.top=(e.clientY - centerOffsetY) + 'px';
}
function updatePlaceholderPosition(e){
const previewContainer=document.getElementById("oum_location_images_preview");
if(!previewContainer) return;
const draggable=document.querySelector('.dragging');
if(!draggable) return;
const siblings=[...previewContainer.querySelectorAll(".image-preview-item:not(.dragging)")];
const closestSibling=siblings.reduce((closest, child)=> {
const rect=child.getBoundingClientRect();
const centerX=rect.left + rect.width / 2;
const offset=e.clientX - centerX;
if(offset < 0&&(!closest.element||offset > closest.offset)){
return { offset: offset, element: child };}
return closest;
}, { offset: Number.NEGATIVE_INFINITY, element: null });
if(closestSibling.element){
previewContainer.insertBefore(placeholder, closestSibling.element);
}else{
previewContainer.appendChild(placeholder);
}}
function handleDragMove(e){
if(!isDragging) return;
const draggable=document.querySelector(".dragging");
if(!draggable) return;
moveDraggedElement(draggable, e);
const gridContainer=document.getElementById("oum_location_images_preview");
if(!gridContainer) return;
const gridRect=gridContainer.getBoundingClientRect();
const isWithinGrid=e.clientX >=gridRect.left - 50 &&
e.clientX <=gridRect.right + 50 &&
e.clientY >=gridRect.top - 50 &&
e.clientY <=gridRect.bottom + 50;
if(!isWithinGrid&&placeholder){
placeholder.style.display='none';
}else if(placeholder){
placeholder.style.display='block';
updatePlaceholderPosition(e);
}}
function handleDragEnd(){
const draggable=document.querySelector(".dragging");
if(!draggable) return;
document.body.style.cursor="";
const gridContainer=document.getElementById("oum_location_images_preview");
if(!gridContainer){
if(draggable.initialContainer){
draggable.initialContainer.appendChild(draggable);
}}else{
if(placeholder&&placeholder.style.display!=='none'){
draggable.style.transition="none";
placeholder.parentNode.insertBefore(draggable, placeholder);
}else{
gridContainer.appendChild(draggable);
}}
if(placeholder){
placeholder.remove();
}
draggable.style.position="";
draggable.style.zIndex="";
draggable.style.top="";
draggable.style.left="";
draggable.style.width="";
draggable.style.height="";
draggable.style.transform="";
draggable.style.pointerEvents="";
draggable.style.boxShadow="";
draggable.classList.remove("dragging");
isDragging=false;
}
function handleTouchStart(e){
const touch=e.touches[0];
const mouseEvent=new MouseEvent("mousedown", {
clientX: touch.clientX,
clientY: touch.clientY
});
this.dispatchEvent(mouseEvent);
}
function handleDragOver(e){
e.preventDefault();
e.stopPropagation();
const draggable=document.querySelector(".dragging");
if(!draggable) return;
const afterElement=getDragAfterElement(this, e.clientX);
if(afterElement==null){
this.appendChild(placeholder);
}else{
this.insertBefore(placeholder, afterElement);
}}
return {
init: function (){
initializeAudioUpload();
},
initializeImageUpload: function(imageInput){
initializeImageUpload(imageInput);
},
getSelectedFiles: function (){
return selectedFiles;
},
setupDragAndDrop: setupDragAndDrop,
handleRemoveImage: handleRemoveImage,
setExistingAudio: setExistingAudio
};})();
const OUMCheckboxValidation=(function (){
function syncRequired(group){
const anyChecked=group.some(cb=> cb.checked);
const first=group[0];
first.required = !anyChecked;
}
function getCheckboxGroups(){
const checkboxGroups=document.querySelectorAll('.oum-checkbox-group.is-required input[type="checkbox"]');
if(!checkboxGroups.length) return {};
const groups={};
checkboxGroups.forEach(checkbox=> {
const name=checkbox.name;
if(!groups[name]) groups[name]=[];
groups[name].push(checkbox);
});
return groups;
}
function processCheckboxGroup(group, setupEvents=true){
const first=group[0];
if(!first.required) return;
if(setupEvents){
group.forEach(cb=> cb.addEventListener('change', ()=> syncRequired(group)));
}
syncRequired(group);
}
function initCheckboxGroups(){
const groups=getCheckboxGroups();
Object.keys(groups).forEach(groupName=> {
processCheckboxGroup(groups[groupName], true);
});
}
return {
init: function(){
initCheckboxGroups();
},
syncAllGroups: function(){
const groups=getCheckboxGroups();
Object.keys(groups).forEach(groupName=> {
processCheckboxGroup(groups[groupName], false);
});
}};})();
const OUMAdvancedFilter=(function (){
let isInitialized=false;
let filterSidebar=null;
function init(){
if(isInitialized) return;
filterSidebar=document.querySelector('.oum-advanced-filter-sidebar');
if(!filterSidebar){
return;
}
setupFilterEvents();
setupFloatingPanelToggle();
isInitialized=true;
}
function setupFloatingPanelToggle(){
const floatingPanel=document.querySelector('.oum-advanced-filter-button, .oum-advanced-filter-panel');
if(!floatingPanel||!floatingPanel.classList.contains('use-collapse')){
return;
}
const toggle=floatingPanel.querySelector('.oum-advanced-filter-toggle');
const closeButton=floatingPanel.querySelector('.close-advanced-filter');
const filterWrapper=floatingPanel.closest('.oum-map-filter-wrapper');
if(toggle){
toggle.addEventListener('click', function(e){
e.stopPropagation();
floatingPanel.classList.toggle('active');
});
}
if(closeButton){
closeButton.addEventListener('click', function(e){
e.stopPropagation();
floatingPanel.classList.remove('active');
});
}
if(filterWrapper){
document.addEventListener('click', function(e){
if(!filterWrapper.contains(e.target)){
floatingPanel.classList.remove('active');
}});
}}
function setupFilterEvents(){
const filterInputs=filterSidebar.querySelectorAll('.oum-advanced-filter-input');
const filterCheckboxes=filterSidebar.querySelectorAll('.oum-advanced-filter-checkbox');
const filterRadios=filterSidebar.querySelectorAll('.oum-advanced-filter-radio');
const filterSelects=filterSidebar.querySelectorAll('.oum-advanced-filter-select');
filterInputs.forEach(input=> {
input.addEventListener('input', handleFilterChange);
});
filterCheckboxes.forEach(checkbox=> {
checkbox.addEventListener('change', handleFilterChange);
});
filterRadios.forEach(radio=> {
radio.addEventListener('change', handleFilterChange);
});
filterSelects.forEach(select=> {
select.addEventListener('change', handleFilterChange);
});
const resetButton=filterSidebar.querySelector('#oum-advanced-filter-reset');
if(resetButton){
resetButton.addEventListener('click', resetAllFilters);
}}
function handleFilterChange(){
if(typeof OUMMarkers==='undefined'||!OUMMarkers.setCustomfieldsFilter){
console.warn('OUMMarkers not available for advanced filtering');
return;
}
const filterCriteria=getFilterCriteria();
OUMMarkers.setCustomfieldsFilter(filterCriteria);
}
function getFilterCriteria(){
const criteria={};
if(!filterSidebar) return criteria;
const textInputs=filterSidebar.querySelectorAll('.oum-advanced-filter-input');
textInputs.forEach(input=> {
const customFieldId=input.dataset.customFieldId;
if(customFieldId&&input.value.trim()){
criteria[customFieldId]={
type: 'text',
value: input.value.trim().toLowerCase()
};}});
const checkboxes=filterSidebar.querySelectorAll('.oum-advanced-filter-checkbox');
checkboxes.forEach(checkbox=> {
const customFieldId=checkbox.dataset.customFieldId;
const filterType=checkbox.dataset.filterType;
if(customFieldId){
if(filterType==='opening_hours_open_now'){
if(checkbox.checked){
criteria[customFieldId]={
type: 'opening_hours_open_now',
value: 'open'
};}}else{
if(!criteria[customFieldId]){
const fieldset=checkbox.closest('.oum-checkbox-group');
const relation=fieldset ? (fieldset.dataset.checkboxRelation||'OR'):'OR';
criteria[customFieldId]={ type: 'checkbox', values: [], relation: relation };}
if(checkbox.checked){
criteria[customFieldId].values.push(checkbox.value);
}}
}});
const radios=filterSidebar.querySelectorAll('.oum-advanced-filter-radio');
radios.forEach(radio=> {
const customFieldId=radio.dataset.customFieldId;
if(customFieldId&&radio.checked){
criteria[customFieldId]={
type: 'radio',
value: radio.value
};}});
const selects=filterSidebar.querySelectorAll('.oum-advanced-filter-select');
selects.forEach(select=> {
const customFieldId=select.dataset.customFieldId;
if(customFieldId&&select.value){
criteria[customFieldId]={
type: 'select',
value: select.value
};}});
Object.keys(criteria).forEach(key=> {
const criterion=criteria[key];
if(criterion.type==='checkbox'&&criterion.values.length===0){
delete criteria[key];
}});
return criteria;
}
function resetAllFilters(){
const filterInputs=filterSidebar.querySelectorAll('.oum-advanced-filter-input');
filterInputs.forEach(input=> {
input.value='';
});
const filterCheckboxes=filterSidebar.querySelectorAll('.oum-advanced-filter-checkbox');
filterCheckboxes.forEach(checkbox=> {
checkbox.checked=false;
});
const filterRadios=filterSidebar.querySelectorAll('.oum-advanced-filter-radio');
filterRadios.forEach(radio=> {
radio.checked=false;
});
const filterSelects=filterSidebar.querySelectorAll('.oum-advanced-filter-select');
filterSelects.forEach(select=> {
select.selectedIndex=0;
});
if(typeof OUMMarkers!=='undefined'&&OUMMarkers.setCustomfieldsFilter){
OUMMarkers.setCustomfieldsFilter(null);
}}
return {
init: init
};})();
function oumInitializeMap(){
if(!document.getElementById(map_el)){
console.warn('‼️ Open User Map: Map container missing. Initialization aborted. Disable page caching if applicable, or contact support@open-user-map.com for help.');
return;
}
OUMOpeningHours.init();
window.L=window.OUMLeaflet.L;
const mapInstance=OUMMap.init(map_el);
const markersModule=OUMMarkers.init(mapInstance);
if(typeof oum_all_locations!=="undefined" &&
Array.isArray(oum_all_locations)
){
markersModule.addMarkers(oum_all_locations);
}
OUMFormMap.init(mapInstance);
OUMFormController.init();
OUMMedia.init();
OUMCheckboxValidation.init();
OUMAdvancedFilter.init();
const markerFilterInput=document.getElementById("oum_filter_markers");
if(markerFilterInput){
markerFilterInput.addEventListener("input", OUMMarkers.updateSearchtextAndCategoriesFilters);
}
const categoryInputs=document.querySelectorAll('.open-user-map .oum-filter-controls [name="type"]'
);
if(categoryInputs.length > 0){
categoryInputs.forEach((input)=> {
input.addEventListener("change", OUMMarkers.updateSearchtextAndCategoriesFilters);
});
}
if(typeof custom_js!=="undefined"&&custom_js.snippet){
try {
const wrappedJS=`
try {
if(typeof document!=='undefined'){
if(${custom_js.snippet.includes("oumMap2")}){
const observer=new MutationObserver((mutations)=> {
if(window.oumMap2){
try {
${custom_js.snippet}} catch (e){
console.warn('Custom JS execution error (deferred):', e);
}
observer.disconnect();
}});
observer.observe(document.body, {
childList: true,
subtree: true
});
}else{
${custom_js.snippet}}
}} catch (e){
console.warn('Custom JS execution error:', e);
}
`;
Function(wrappedJS)();
} catch (error){
console.warn("Error executing custom JS:", error);
}}
};