Map: pitch option, marker ordering and event popup improvements
This commit is contained in:
@@ -118,6 +118,21 @@ const escapeHtml = (value) => {
|
||||
.replace(/'/g, ''');
|
||||
};
|
||||
|
||||
const decodeHtmlEntities = (value) => {
|
||||
const stringValue = String(value ?? '');
|
||||
|
||||
if ('undefined' === typeof document || !document.createElement) {
|
||||
return stringValue;
|
||||
}
|
||||
|
||||
const textarea = document.createElement('textarea');
|
||||
textarea.innerHTML = stringValue;
|
||||
|
||||
return textarea.value;
|
||||
};
|
||||
|
||||
const sanitizeDisplayText = (value) => escapeHtml(decodeHtmlEntities(value));
|
||||
|
||||
const parseItems = (container) => {
|
||||
const dataElementId = container.dataset.mapDataId || '';
|
||||
|
||||
@@ -406,17 +421,24 @@ const ensureMarkerImage = (map, color, prefix = 'eventmanager-marker', options =
|
||||
|
||||
const popupHtmlFor = (item) => {
|
||||
if (item.type === 'event') {
|
||||
const locationTitle = escapeHtml(item.extra.locationTitle || '');
|
||||
const startDate = escapeHtml(item.extra.startDate || '');
|
||||
const title = sanitizeDisplayText(item.title || '');
|
||||
const locationTitle = sanitizeDisplayText(item.extra.locationTitle || '');
|
||||
const startDate = sanitizeDisplayText(item.extra.startDate || '');
|
||||
const detailUrl = String(item.extra.detailUrl || '').trim();
|
||||
const hasDetailUrl = /^(https?:\/\/|\/)/i.test(detailUrl);
|
||||
const detailLink = hasDetailUrl
|
||||
? `<div><a href="${escapeHtml(detailUrl)}">mehr Infos</a></div>`
|
||||
: '';
|
||||
|
||||
return [
|
||||
`<strong>${escapeHtml(item.title)}</strong>`,
|
||||
`<strong>${title}</strong>`,
|
||||
locationTitle ? `<div>${locationTitle}</div>` : '',
|
||||
startDate ? `<div>${startDate}</div>` : '',
|
||||
detailLink,
|
||||
].join('');
|
||||
}
|
||||
|
||||
return `<strong>${escapeHtml(item.title)}</strong>`;
|
||||
return `<strong>${sanitizeDisplayText(item.title)}</strong>`;
|
||||
};
|
||||
|
||||
const toFeature = (item) => ({
|
||||
@@ -432,6 +454,7 @@ const toFeature = (item) => ({
|
||||
markerTagIds: Array.isArray(item.extra?.organizationTagIds) ? item.extra.organizationTagIds : [],
|
||||
markerTagLabels: Array.isArray(item.extra?.organizationTagLabels) ? item.extra.organizationTagLabels : [],
|
||||
title: item.title,
|
||||
latitude: item.latitude,
|
||||
popupHtml: popupHtmlFor(item),
|
||||
},
|
||||
});
|
||||
@@ -445,7 +468,9 @@ const initOrganizationMarkers = (map, organizationItems, organizationColor) => {
|
||||
};
|
||||
}
|
||||
|
||||
const markerEntries = organizationItems.map((item) => {
|
||||
const sortedOrganizationItems = [...organizationItems].sort((firstItem, secondItem) => secondItem.latitude - firstItem.latitude);
|
||||
|
||||
const markerEntries = sortedOrganizationItems.map((item) => {
|
||||
const popupHtml = popupHtmlFor(item);
|
||||
const marker = new maplibregl.Marker(organizationColor ? { color: organizationColor } : undefined)
|
||||
.setLngLat([item.longitude, item.latitude]);
|
||||
@@ -456,6 +481,12 @@ const initOrganizationMarkers = (map, organizationItems, organizationColor) => {
|
||||
|
||||
marker.addTo(map);
|
||||
|
||||
const markerElement = marker.getElement();
|
||||
|
||||
if (markerElement) {
|
||||
markerElement.style.zIndex = String(Math.round((90 - item.latitude) * 1000));
|
||||
}
|
||||
|
||||
return {
|
||||
marker,
|
||||
tagIds: normalizeTagIds(item.extra?.organizationTagIds),
|
||||
@@ -776,6 +807,7 @@ const initLocationLayers = (map, locationItems, markerImageId) => {
|
||||
'icon-anchor': 'bottom',
|
||||
'icon-allow-overlap': true,
|
||||
'icon-ignore-placement': true,
|
||||
'symbol-sort-key': ['*', -1, ['to-number', ['get', 'latitude'], 0]],
|
||||
},
|
||||
paint: {
|
||||
'icon-opacity': 1,
|
||||
@@ -915,6 +947,7 @@ const initEventLayers = (map, eventItems, eventColor, markerImageId, clusterMark
|
||||
'icon-anchor': 'bottom',
|
||||
'icon-allow-overlap': true,
|
||||
'icon-ignore-placement': true,
|
||||
'symbol-sort-key': ['*', -1, ['to-number', ['get', 'latitude'], 0]],
|
||||
},
|
||||
paint: {
|
||||
'icon-opacity': 1,
|
||||
@@ -1132,8 +1165,12 @@ const initSingleMap = (container) => {
|
||||
const customLat = parseCoordinate(container.dataset.mapCenterLat);
|
||||
const customLng = parseCoordinate(container.dataset.mapCenterLng);
|
||||
const customZoom = Number(container.dataset.mapCenterZoom);
|
||||
const customPitch = Number(container.dataset.mapPitch);
|
||||
const eventColor = normalizeHexColor(container.dataset.mapEventColor, DEFAULT_EVENT_COLOR);
|
||||
const hasCustomCenter = null !== customLat && null !== customLng;
|
||||
const initialPitch = Number.isFinite(customPitch)
|
||||
? Math.max(0, Math.min(85, customPitch))
|
||||
: 0;
|
||||
|
||||
let initialCenter = DEFAULT_CENTER;
|
||||
let initialZoom = DEFAULT_ZOOM;
|
||||
@@ -1165,7 +1202,7 @@ const initSingleMap = (container) => {
|
||||
container,
|
||||
style,
|
||||
zoom: initialZoom,
|
||||
pitch: 0,
|
||||
pitch: initialPitch,
|
||||
bearing: 0,
|
||||
center: initialCenter,
|
||||
transformRequest: (url, resourceType) => {
|
||||
@@ -1227,9 +1264,15 @@ const initSingleMap = (container) => {
|
||||
map.on('load', async () => {
|
||||
applyDefaultProjection(map);
|
||||
|
||||
const organizationItems = items.filter((item) => item.type === 'organisation');
|
||||
const locationItems = items.filter((item) => item.type === 'location');
|
||||
const eventItems = items.filter((item) => item.type === 'event');
|
||||
const organizationItems = items
|
||||
.filter((item) => item.type === 'organisation')
|
||||
.sort((firstItem, secondItem) => secondItem.latitude - firstItem.latitude);
|
||||
const locationItems = items
|
||||
.filter((item) => item.type === 'location')
|
||||
.sort((firstItem, secondItem) => secondItem.latitude - firstItem.latitude);
|
||||
const eventItems = items
|
||||
.filter((item) => item.type === 'event')
|
||||
.sort((firstItem, secondItem) => secondItem.latitude - firstItem.latitude);
|
||||
const allCoordinates = items.map((item) => [item.longitude, item.latitude]);
|
||||
const organizationColor = normalizeHexColor(
|
||||
container.dataset.mapOrganizationColor,
|
||||
|
||||
Reference in New Issue
Block a user