Making one popover
Ein Popover enthält weiterführende Informationen und kann über einen Button sichtbar gemacht werden. Die meisten Popover erscheinen rechts, links, oberhalb oder unterhalb dieses Buttons.
Making a trigger
Section titled “Making a trigger”Ein Popover benötigt einen Trigger. Wir verwenden dazu natürlich einen Button, da er ja auch mit der Tastatur bedienbar sein soll.
<button class="popover-trigger">...</button>Für diese Komponente verwenden wir einen Pfeil als Trigger, diese erzeugen wir mit einem SVG.
<button class="trigger"> <svg viewBox="0 0 40 20"> <use xlink:href="#arrow"></use> </svg></button>Building the popover
Section titled “Building the popover”Popovers sollten über allen anderen Elementen liegen. Daher sollten sie ein direkter Nachfahre von <body> sein. Wenn ein Popover innerhalb eines anderen Elements platziert wird, könnte es abgeschnitten werden, wenn das Elternelement ein transform oder overflow benutzt.
<body> <!-- other elements --> <div class="popover"> <p>The quick brown fox jumps over the lazy dog.</p> </div></body>Das Popover muss noch wissen, wo es erscheinen soll. Dafür können wir ein custom data-attribute verwenden.
<div class="popover" data-position="top"> <p>The quick brown fox jumps over the lazy dog.</p></div>Um das Popover direkt über dem Trigger zu positionieren, muss es absolut positioniert werden. Dafür brauchen wir die richtigen Werte für top und left. Diese erhalten wir mit JavaScript.
Calculating popover’s left position
Section titled “Calculating popover’s left position”Zuerst brauchen wir den Trigger und das Popover:
const popoverTrigger = document.querySelector('.popover-trigger');const popover = document.querySelector('.popover');Um das Popover oberhalb des Triggers zu positionieren, müssen wir auch den Mittelpunkt des Triggers kennen: triggerLeft + triggerRight / 2.
Wir erhalten diese mit getBoundingClientRect:
const popoverTriggerRect = popoverTrigger.getBoundingClientRect();const triggerCenter = (popoverTriggerRect.left + popoverTriggerRect.right) / 2;Der Mittelpunkt des Triggers ist gleichzeitig der Mittelpunkt des Popovers. Wenn wir die Breite des Popovers durch zwei teilen und vom Mittelpunkt abziehen, erhalten wir die Position für left.
const popoverRect = popover.getBoundingclientRect();const leftPosition = triggerCenter - popoverRect.width / 2;Die Position für left können wir mit der style-Eigenschaft setzen:
popover.style.left = `${leftPosition}px`;Calculationg popover’s top position
Section titled “Calculationg popover’s top position”Um die top-Position zu finden, müssen wir zuerst die top-Position des Triggers ermitteln. Diese finden wir auch wieder mit getBoundingClientRect:
const triggerTop = popoverTriggerRect.top;Der top-Wert des Triggers ist gleich der Summe des top-Wergtes des Popovers, der Höhe des Popovers und etwas Abstand zwischen Popover und Trigger.
Nehmen wir den Weißraum mit 20px an. Die Höhe des Popovers erhalten wir aus popoverRect.
const space = 20px;const topPosition = triggerTop - popoverRect.height - space;Die top-Position setzen wir wieder mit der style-Eigenschaft:
popover.style.top = `${topPosition}px`;Hiding the popover
Section titled “Hiding the popover”Das Popover soll anfangs versteckt sein. Dazu verwenden wir das hidden-Attribut. Wichtig: Das hidden-Attribut muss nach der Positionierung des Popovers stehen!
popover.style.left = `${leftPosition}px`;popover.style.top = `${topPosition}px`;
// Hiding the popoverpopover.setAttribute('hidden', true);Showing and hiding the popover
Section titled “Showing and hiding the popover”Wir müssen das Popover anzeigen, wenn der Trigger geklickt wird, d.h., wir richten einen Event-Listener ein und entfernen das hidden-Attribut:
popoverTrigger.addEventListener('click', e => { popover.removeAttribute('hidden');});Wenn der User den Trigger wieder klickt, wollen wir das Popover verstecken. Dazu können wir ein if-Statement verwenden.
popoverTrigger.addEventListener('click', e => { if (popover.hasAttribute('hidden')) { popover.removeAttribute('hidden'); } else { popover.setAttribute('hidden', true); }});Wir wollen das Popover auch verstecken, wenn der User außerhalb des Popovers und des Triggers klickt. Dafür richten wir einen EventListener auf das Dokument ein. Wenn e.target nicht .popover oder .popover-trigger ist, dann wissen wir, dass der User außerhalb des Triggers bzw. des Popups geklickt hat.
document.addEventListener('click', e => { if ( e.target.closest('.popover') || e.target.closest('.popover-trigger') ) return; popover.setAttribute('hidden', true);});