(function () {
'use strict';
var mapsPromise = null;
var mapStates = [];
function settings() {
var core = window.MeinWeimarCore || {};
return core.googleMaps || {};
}
function loadGoogleMaps() {
if (window.google && window.google.maps) {
return Promise.resolve(window.google.maps);
}
if (mapsPromise) {
return mapsPromise;
}
var apiKey = String(settings().api_key || '').trim();
if (!apiKey) {
return Promise.reject(new Error('google_maps_key_missing'));
}
mapsPromise = new Promise(function (resolve, reject) {
var callbackName = '__meinweimarGoogleMapsReady';
window[callbackName] = function () {
if (window.google && window.google.maps) {
resolve(window.google.maps);
return;
}
reject(new Error('google_maps_api_missing'));
};
var existing = document.querySelector('script[data-meinweimar-google-maps]');
if (existing) {
if (window.google && window.google.maps) {
resolve(window.google.maps);
}
existing.addEventListener('error', function () {
reject(new Error('google_maps_load_failed'));
}, { once: true });
return;
}
var script = document.createElement('script');
script.async = true;
script.defer = true;
script.dataset.meinweimarGoogleMaps = 'true';
script.src = 'https://maps.googleapis.com/maps/api/js?key=' + encodeURIComponent(apiKey) + '&loading=async&callback=' + callbackName + '&libraries=geometry';
script.onerror = function () {
reject(new Error('google_maps_load_failed'));
};
document.head.appendChild(script);
});
return mapsPromise;
}
function position(value) {
if (!value || !isFinite(Number(value.lat)) || !isFinite(Number(value.lng))) {
return null;
}
return { lat: Number(value.lat), lng: Number(value.lng) };
}
function markerUrl(item, core) {
var direct = item && item.marker && item.marker.image_url;
if (direct) {
return String(direct);
}
var route = item && (item.resource || item.type) || '';
var resource = core.geo && core.geo.markers && core.geo.markers.by_resource
? core.geo.markers.by_resource[route]
: null;
if (resource && resource.image_url) {
return String(resource.image_url);
}
var fallback = core.geo && core.geo.markers ? core.geo.markers.fallback : null;
return fallback && fallback.image_url ? String(fallback.image_url) : '';
}
function scaledIcon(url, maxWidth, maxHeight) {
return new Promise(function (resolve) {
var image = new Image();
image.onload = function () {
var width = Number(image.naturalWidth) || maxWidth;
var height = Number(image.naturalHeight) || maxHeight;
var scale = Math.min(maxWidth / width, maxHeight / height, 1);
var scaledWidth = Math.max(1, Math.round(width * scale));
var scaledHeight = Math.max(1, Math.round(height * scale));
resolve({
url: url,
scaledSize: new window.google.maps.Size(scaledWidth, scaledHeight),
anchor: new window.google.maps.Point(Math.round(scaledWidth / 2), scaledHeight)
});
};
image.onerror = function () { resolve(null); };
image.src = url;
});
}
function clearState(state) {
state.markers.forEach(function (marker) { marker.setMap(null); });
state.markers = [];
state.mapRoot.classList.remove('has-google-maps');
}
function createMarker(state, maps, item, point, title, url, onClick, isUser) {
var marker = new maps.Marker({
map: state.map,
position: point,
title: title || '',
opacity: url ? 0 : 1,
zIndex: isUser ? 1000 : undefined
});
if (typeof onClick === 'function') {
marker.addListener('click', onClick);
}
state.markers.push(marker);
if (url) {
scaledIcon(url, isUser ? 44 : 48, isUser ? 52 : 58).then(function (icon) {
if (!icon) {
marker.setOpacity(1);
return;
}
marker.setIcon(icon);
marker.setOpacity(1);
});
}
return marker;
}
function updateMap(payload, maps) {
var mapRoot = payload && payload.element;
var container = mapRoot && mapRoot.querySelector('[data-google-map]');
if (!container) {
return;
}
// Google Maps cannot calculate its internal viewport while the shared
// map panel is hidden. Keep the latest payload and initialize only after
// the user switches to the visible map mode.
if (mapRoot.hidden) {
mapRoot.__meinweimarGoogleMapsPending = payload;
return;
}
var state = mapStates.filter(function (entry) { return entry.container === container; })[0];
var core = window.MeinWeimarCore || {};
var geo = core.geo || {};
var items = Array.isArray(payload.items) ? payload.items : [];
var points = items.map(function (item) { return position(item.geo); }).filter(Boolean);
var center = position(payload.center) || points[0] || position({ lat: geo.default_latitude, lng: geo.default_longitude }) || { lat: 50.9795, lng: 11.3235 };
if (!state) {
mapRoot.classList.add('has-google-maps');
state = {
container: container,
mapRoot: mapRoot,
map: new maps.Map(container, {
center: center,
zoom: Number(geo.default_map_zoom) || 13,
mapTypeControl: false,
streetViewControl: false,
fullscreenControl: false,
clickableIcons: false
}),
markers: []
};
mapStates.push(state);
}
clearState(state);
state.map.setCenter(center);
var bounds = new maps.LatLngBounds();
var hasBounds = false;
items.forEach(function (item) {
var point = position(item.geo);
if (!point) {
return;
}
bounds.extend(point);
hasBounds = true;
createMarker(state, maps, item, point, item.title || '', markerUrl(item, core), function () {
if (typeof payload.onSelect === 'function') {
payload.onSelect(item.id);
}
}, false);
});
var markerConfig = geo.markers || {};
var userPosition = position(payload.userLocation);
if (userPosition) {
createMarker(state, maps, null, userPosition, (core.strings || {}).currentLocationLabel || '', markerConfig.user && markerConfig.user.image_url, null, true);
bounds.extend(userPosition);
hasBounds = true;
}
var searchPosition = position(payload.searchPosition);
if (searchPosition && (!userPosition || searchPosition.lat !== userPosition.lat || searchPosition.lng !== userPosition.lng)) {
createMarker(state, maps, null, searchPosition, (core.strings || {}).searchLocationLabel || '', markerConfig.fallback && markerConfig.fallback.image_url, null, true);
bounds.extend(searchPosition);
hasBounds = true;
}
if (hasBounds && !payload.center && points.length > 1) {
state.map.fitBounds(bounds, 40);
} else {
state.map.setCenter(center);
}
mapRoot.classList.add('has-google-maps');
if (mapRoot.querySelector('[data-markers]')) {
mapRoot.querySelector('[data-markers]').innerHTML = '';
}
}
window.MeinWeimarMapAdapter = {
update: function (payload) {
loadGoogleMaps().then(function (maps) {
updateMap(payload, maps);
}).catch(function () {
var mapRoot = payload && payload.element;
var markers = mapRoot && mapRoot.querySelector('[data-markers]');
var strings = (window.MeinWeimarCore || {}).strings || {};
if (markers) {
markers.textContent = '';
var state = document.createElement('p');
state.className = 'mw-discovery__map-state';
state.textContent = String(strings.mapProviderPending || '');
markers.appendChild(state);
}
});
},
resize: function (element) {
var container = element && element.querySelector ? element.querySelector('[data-google-map]') : null;
var state = container && mapStates.filter(function (entry) { return entry.container === container; })[0];
if (state && window.google && window.google.maps) {
window.google.maps.event.trigger(state.map, 'resize');
}
}
};
}());
