Feature: Hover-Vorschau auf Kartenmarkern

Marker zeigen jetzt beim Mouseover zusaetzlich zum bestehenden
Klick-Popup eine kompakte Vorschau (Leaflet-Tooltip) mit Name,
Kategorie, Kurzbeschreibung sowie Kurzfakten (Altersempfehlung,
Kostenart, Bewertung, falls vorhanden) - ohne dass geklickt werden muss.
Inhalt wird wie ueberall sonst als DOM-Node ueber el()/textContent
erzeugt, kein innerHTML.
This commit is contained in:
2026-07-24 13:01:35 +02:00
parent 2d41bce063
commit 1b26cfda7a
2 changed files with 93 additions and 0 deletions
+51
View File
@@ -41,6 +41,46 @@
]);
}
const COST_LABELS = { free: 'Kostenlos', paid: 'Kostenpflichtig', mixed: 'Teils kostenpflichtig', unknown: null };
function formatTooltipAge(ageRecommendation) {
const { min, max } = ageRecommendation || {};
if (min == null && max == null) return null;
if (min != null && max != null) return `${min}${max} Jahre`;
if (min != null) return `Ab ${min} Jahren`;
return `Bis ${max} Jahre`;
}
/** Kompakte Hover-Vorschau (Leaflet-Tooltip), zusätzlich zum Klick-Popup. */
function buildTooltipContent(place) {
const category = getPlaceCategory(place);
const facts = [];
const age = formatTooltipAge(place.ageRecommendation);
if (age) facts.push(age);
const costLabel = COST_LABELS[(place.cost || {}).type];
if (costLabel) facts.push(costLabel);
if (typeof place.rating === 'number') facts.push(`${place.rating.toFixed(1)}`);
const children = [
el('strong', { className: 'eventmap-tooltip__title', text: place.name }),
el('div', {
className: 'eventmap-tooltip__category',
style: { color: category.color },
text: `${category.icon} ${category.label}`,
}),
];
if (place.shortDescription) {
children.push(el('p', { className: 'eventmap-tooltip__desc', text: place.shortDescription }));
}
if (facts.length > 0) {
children.push(el('p', { className: 'eventmap-tooltip__facts', text: facts.join(' · ') }));
}
return el('div', { className: 'eventmap-tooltip' }, children);
}
/**
* Erzeugt einen Leaflet-Marker für ein Place-Objekt.
* @param {object} place
@@ -51,6 +91,17 @@
const marker = L.marker([lat, lng], { icon: getIconForCategory(place.category) });
marker.bindPopup(buildPopupContent(place));
// Hover-Vorschau zusätzlich zum Klick-Popup: sticky folgt dem Mauszeiger,
// damit die Vorschau nicht die Position wechselt, während man über den
// Marker fährt. Schließt sich automatisch bei mouseout bzw. wenn der
// Klick-Popup geöffnet wird.
marker.bindTooltip(buildTooltipContent(place), {
direction: 'top',
offset: [0, -18],
opacity: 0.97,
sticky: false,
className: 'eventmap-tooltip-wrapper',
});
marker.on('click', () => {
if (onSelect) {
onSelect(place.id);