Compare commits

...

2 Commits

Author SHA1 Message Date
Jürgen Mummert ba321fdc23 Map: show event markers only for future events 2026-02-26 21:16:36 +01:00
Jürgen Mummert d5bfb66eee Fix spiderfy reliability after event toggle 2026-02-26 21:08:37 +01:00
3 changed files with 70 additions and 72 deletions
@@ -107,4 +107,4 @@
</style> </style>
<script type="application/json" id="{{ mapDataElementId|e('html_attr') }}">{{ mapItemsJson|raw }}</script> <script type="application/json" id="{{ mapDataElementId|e('html_attr') }}">{{ mapItemsJson|raw }}</script>
<script type="module" src="/bundles/mummertmediaeventmanager/assets/map-module.js?v=20260226d"></script> <script type="module" src="/bundles/mummertmediaeventmanager/assets/map-module.js?v=20260226g"></script>
+68 -45
View File
@@ -532,6 +532,7 @@ const bindExternalTagFilters = (container, map, organizationMarkerManager, event
const eventToggleButton = wrapper.querySelector('[data-map-event-toggle="1"]'); const eventToggleButton = wrapper.querySelector('[data-map-event-toggle="1"]');
const canFilterByTag = tagButtons.length > 0; const canFilterByTag = tagButtons.length > 0;
const canFilterByEvents = !!eventToggleButton; const canFilterByEvents = !!eventToggleButton;
const canToggleEvents = !!(eventToggleButton && eventLayerManager);
const setEventButtonState = (isActive) => { const setEventButtonState = (isActive) => {
if (!eventToggleButton) { if (!eventToggleButton) {
@@ -549,6 +550,26 @@ const bindExternalTagFilters = (container, map, organizationMarkerManager, event
let activeTagId = null; let activeTagId = null;
let eventsOnly = false; let eventsOnly = false;
const updateExclusiveButtonAccessibility = () => {
tagButtons.forEach((button) => {
const isActive = button.getAttribute('aria-pressed') === 'true';
button.setAttribute('aria-disabled', isActive ? 'true' : 'false');
});
if (!eventToggleButton) {
return;
}
if (!canToggleEvents) {
eventToggleButton.setAttribute('aria-disabled', 'true');
return;
}
const isEventActive = eventToggleButton.getAttribute('aria-pressed') === 'true';
eventToggleButton.setAttribute('aria-disabled', isEventActive ? 'true' : 'false');
};
const applyFilter = () => { const applyFilter = () => {
if (eventsOnly) { if (eventsOnly) {
organizationMarkerManager.setVisible(false); organizationMarkerManager.setVisible(false);
@@ -581,14 +602,17 @@ const bindExternalTagFilters = (container, map, organizationMarkerManager, event
tagButtons.forEach((button) => { tagButtons.forEach((button) => {
button.addEventListener('click', () => { button.addEventListener('click', () => {
if (button.getAttribute('aria-disabled') === 'true') {
return;
}
const clickedTagId = String(button.dataset.mapTagFilter || '').trim(); const clickedTagId = String(button.dataset.mapTagFilter || '').trim();
if (!/^\d+$/.test(clickedTagId)) { if (!/^\d+$/.test(clickedTagId)) {
return; return;
} }
const isActive = button.getAttribute('aria-pressed') === 'true'; activeTagId = clickedTagId;
activeTagId = isActive ? null : clickedTagId;
eventsOnly = false; eventsOnly = false;
tagButtons.forEach((otherButton) => { tagButtons.forEach((otherButton) => {
@@ -597,6 +621,7 @@ const bindExternalTagFilters = (container, map, organizationMarkerManager, event
}); });
setEventButtonState(false); setEventButtonState(false);
updateExclusiveButtonAccessibility();
applyFilter(); applyFilter();
}); });
}); });
@@ -628,12 +653,16 @@ const bindExternalTagFilters = (container, map, organizationMarkerManager, event
if (eventToggleButton && eventLayerManager) { if (eventToggleButton && eventLayerManager) {
eventToggleButton.addEventListener('click', () => { eventToggleButton.addEventListener('click', () => {
const isActive = eventToggleButton.getAttribute('aria-pressed') === 'true'; if (eventToggleButton.getAttribute('aria-disabled') === 'true') {
eventsOnly = !isActive; return;
}
eventsOnly = true;
activeTagId = null; activeTagId = null;
tagButtons.forEach((button) => setButtonState(button, false)); tagButtons.forEach((button) => setButtonState(button, false));
setEventButtonState(eventsOnly); setEventButtonState(eventsOnly);
updateExclusiveButtonAccessibility();
applyFilter(); applyFilter();
}); });
} else if (eventToggleButton) { } else if (eventToggleButton) {
@@ -711,9 +740,11 @@ const bindExternalTagFilters = (container, map, organizationMarkerManager, event
setButtonState(button, null !== activeTagId && tagId === activeTagId); setButtonState(button, null !== activeTagId && tagId === activeTagId);
}); });
setEventButtonState(eventsOnly); setEventButtonState(eventsOnly);
updateExclusiveButtonAccessibility();
}; };
applyInitialDisplayMode(); applyInitialDisplayMode();
updateExclusiveButtonAccessibility();
applyFilter(); applyFilter();
applyMapStyleMode(); applyMapStyleMode();
}; };
@@ -748,6 +779,7 @@ const initLocationLayers = (map, locationItems, markerImageId) => {
}, },
paint: { paint: {
'icon-opacity': 1, 'icon-opacity': 1,
'icon-translate': [0, 4],
}, },
}); });
@@ -831,19 +863,9 @@ const initLocationLayers = (map, locationItems, markerImageId) => {
const initEventLayers = (map, eventItems, eventColor, markerImageId, clusterMarkerImageId) => { const initEventLayers = (map, eventItems, eventColor, markerImageId, clusterMarkerImageId) => {
const sourceId = 'eventmanager-events-source'; const sourceId = 'eventmanager-events-source';
const clusterLayerId = EVENT_CLUSTER_LAYER_ID; const clusterLayerId = EVENT_CLUSTER_LAYER_ID;
const clusterSpiderfyLayerId = EVENT_CLUSTER_SPIDERFY_LAYER_ID;
const unclusteredLayerId = EVENT_UNCLUSTERED_LAYER_ID; const unclusteredLayerId = EVENT_UNCLUSTERED_LAYER_ID;
const spiderfyHitAreaImageId = 'eventmanager-spiderfy-hit-area';
const features = eventItems.map(toFeature); const features = eventItems.map(toFeature);
if (!map.hasImage(spiderfyHitAreaImageId)) {
map.addImage(spiderfyHitAreaImageId, {
width: 1,
height: 1,
data: new Uint8Array([0, 0, 0, 0]),
});
}
map.addSource(sourceId, { map.addSource(sourceId, {
type: 'geojson', type: 'geojson',
data: { data: {
@@ -875,25 +897,10 @@ const initEventLayers = (map, eventItems, eventColor, markerImageId, clusterMark
}, },
paint: { paint: {
'icon-opacity': 1, 'icon-opacity': 1,
'icon-translate': [0, 4],
'text-color': '#FFFFFF', 'text-color': '#FFFFFF',
'text-opacity': 1, 'text-opacity': 1,
}, 'text-translate': [0, 4],
});
map.addLayer({
id: clusterSpiderfyLayerId,
type: 'symbol',
source: sourceId,
filter: ['has', 'point_count'],
layout: {
'icon-image': spiderfyHitAreaImageId,
'icon-size': 36,
'icon-anchor': 'bottom',
'icon-offset': [0, -1.0],
'icon-allow-overlap': true,
},
paint: {
'icon-opacity': 0,
}, },
}); });
@@ -911,6 +918,7 @@ const initEventLayers = (map, eventItems, eventColor, markerImageId, clusterMark
}, },
paint: { paint: {
'icon-opacity': 1, 'icon-opacity': 1,
'icon-translate': [0, 4],
}, },
}); });
@@ -1016,7 +1024,7 @@ const initEventLayers = (map, eventItems, eventColor, markerImageId, clusterMark
}, },
spiderLeavesPaint: { spiderLeavesPaint: {
'icon-opacity': 1, 'icon-opacity': 1,
'icon-translate': [0, 8], 'icon-translate': [0, 9],
}, },
onLeafClick: (feature, spiderEvent) => { onLeafClick: (feature, spiderEvent) => {
const clickCoordinates = spiderEvent?.lngLat const clickCoordinates = spiderEvent?.lngLat
@@ -1048,14 +1056,6 @@ const initEventLayers = (map, eventItems, eventColor, markerImageId, clusterMark
map.getCanvas().style.cursor = ''; map.getCanvas().style.cursor = '';
}); });
const setLayerLayoutVisibility = (layerId, isVisible) => {
if (!map.getLayer(layerId)) {
return;
}
map.setLayoutProperty(layerId, 'visibility', isVisible ? 'visible' : 'none');
};
const fadeLayerOpacity = (layerId, property, value, duration = EVENT_FADE_DURATION_MS) => { const fadeLayerOpacity = (layerId, property, value, duration = EVENT_FADE_DURATION_MS) => {
if (!map.getLayer(layerId)) { if (!map.getLayer(layerId)) {
return; return;
@@ -1067,14 +1067,31 @@ const initEventLayers = (map, eventItems, eventColor, markerImageId, clusterMark
const eventLayerIds = [ const eventLayerIds = [
clusterLayerId, clusterLayerId,
clusterSpiderfyLayerId,
unclusteredLayerId, unclusteredLayerId,
]; ];
const clusterFilter = ['has', 'point_count'];
const unclusteredFilter = ['!', ['has', 'point_count']];
const hiddenFilter = ['has', '__eventmanager_hidden__'];
let hideLayersTimeoutId = null;
const setLayerFilter = (layerId, filter) => {
if (!map.getLayer(layerId)) {
return;
}
map.setFilter(layerId, filter);
};
return { return {
setVisible: (isVisible) => { setVisible: (isVisible) => {
if (isVisible) { if (isVisible) {
eventLayerIds.forEach((layerId) => setLayerLayoutVisibility(layerId, true)); if (null !== hideLayersTimeoutId) {
window.clearTimeout(hideLayersTimeoutId);
hideLayersTimeoutId = null;
}
setLayerFilter(clusterLayerId, clusterFilter);
setLayerFilter(unclusteredLayerId, unclusteredFilter);
fadeLayerOpacity(clusterLayerId, 'icon-opacity', 1); fadeLayerOpacity(clusterLayerId, 'icon-opacity', 1);
fadeLayerOpacity(clusterLayerId, 'text-opacity', 1); fadeLayerOpacity(clusterLayerId, 'text-opacity', 1);
@@ -1083,16 +1100,22 @@ const initEventLayers = (map, eventItems, eventColor, markerImageId, clusterMark
return; return;
} }
if (spiderfyInstance && typeof spiderfyInstance.unspiderfyAll === 'function') { if (spiderfyInstance) {
if (typeof spiderfyInstance._clearSpiderifiedCluster === 'function') {
spiderfyInstance._clearSpiderifiedCluster();
} else if (typeof spiderfyInstance.unspiderfyAll === 'function') {
spiderfyInstance.unspiderfyAll(); spiderfyInstance.unspiderfyAll();
} }
}
fadeLayerOpacity(clusterLayerId, 'icon-opacity', 0); fadeLayerOpacity(clusterLayerId, 'icon-opacity', 0);
fadeLayerOpacity(clusterLayerId, 'text-opacity', 0); fadeLayerOpacity(clusterLayerId, 'text-opacity', 0);
fadeLayerOpacity(unclusteredLayerId, 'icon-opacity', 0); fadeLayerOpacity(unclusteredLayerId, 'icon-opacity', 0);
window.setTimeout(() => { hideLayersTimeoutId = window.setTimeout(() => {
eventLayerIds.forEach((layerId) => setLayerLayoutVisibility(layerId, false)); setLayerFilter(clusterLayerId, hiddenFilter);
setLayerFilter(unclusteredLayerId, hiddenFilter);
hideLayersTimeoutId = null;
}, EVENT_FADE_DURATION_MS + 10); }, EVENT_FADE_DURATION_MS + 10);
}, },
}; };
-25
View File
@@ -103,31 +103,6 @@ class MapModuleDataProvider
} }
if ($includeEvents) { if ($includeEvents) {
foreach ($this->fetchLocationRows($locationTable, $locationGeoColumns) as $row) {
$id = (int) ($row['id'] ?? 0);
if ($id <= 0 || isset($seen['location'][$id])) {
continue;
}
$coords = $this->extractCoordinates($row['latitude'] ?? null, $row['longitude'] ?? null);
if (null === $coords) {
continue;
}
$seen['location'][$id] = true;
$items[] = [
'type' => 'location',
'markerType' => 'location',
'id' => $id,
'title' => trim((string) ($row['title'] ?? '')),
'latitude' => $coords['latitude'],
'longitude' => $coords['longitude'],
'extra' => [],
];
}
foreach ($this->fetchEventRows($locationTable, $locationGeoColumns) as $row) { foreach ($this->fetchEventRows($locationTable, $locationGeoColumns) as $row) {
$id = (int) ($row['event_id'] ?? 0); $id = (int) ($row['event_id'] ?? 0);