// "Opret supportsag" in a context menu on findings: right-click a link to /fund/ (any finding list) or the // heading of a finding's own page. Keyboard: Shift+F10 or the context menu key on a focused finding; Escape closes. // Only when the layout says support is available (data-support-available). Without JavaScript the finding page has a // visible "Opret supportsag" button, so nothing depends on this file. (() => { const available = () => document.querySelector('[data-support-available]') !== null; let menu = null; let opener = null; const findingId = (element) => { const marked = element.closest('[data-finding-id]'); if (marked) return marked.dataset.findingId; const link = element.closest('a[href]'); const match = link && /^\/fund\/(\d+)$/.exec(new URL(link.href, document.baseURI).pathname); return match ? match[1] : null; }; const close = (restoreFocus) => { if (!menu) return; menu.remove(); menu = null; if (restoreFocus && opener) opener.focus(); opener = null; }; const open = (id, x, y, target) => { close(false); opener = target.closest('a[href], [tabindex]') || target; menu = document.createElement('div'); menu.className = 'context-menu'; menu.setAttribute('role', 'menu'); menu.setAttribute('aria-label', 'Fund'); const item = document.createElement('a'); item.setAttribute('role', 'menuitem'); item.href = `/support?fund=${encodeURIComponent(id)}`; item.textContent = 'Opret supportsag'; menu.appendChild(item); document.body.appendChild(menu); // Keep it inside the window. Setting style through the CSSOM is allowed by the page's Content-Security-Policy. const width = menu.offsetWidth; const height = menu.offsetHeight; menu.style.left = `${Math.max(4, Math.min(x, window.innerWidth - width - 4)) + window.scrollX}px`; menu.style.top = `${Math.max(4, Math.min(y, window.innerHeight - height - 4)) + window.scrollY}px`; item.focus(); }; document.addEventListener('contextmenu', (event) => { if (!available()) return; const id = findingId(event.target); if (!id) return; event.preventDefault(); // From the keyboard there is no pointer position: place the menu under the focused element. let { clientX: x, clientY: y } = event; if (x === 0 && y === 0) { const box = event.target.getBoundingClientRect(); x = box.left; y = box.bottom + 4; } open(id, x, y, event.target); }); document.addEventListener('keydown', (event) => { if (!menu) return; if (event.key === 'Escape') { event.preventDefault(); close(true); } else if (event.key === 'Tab') { close(false); } }); document.addEventListener('mousedown', (event) => { if (menu && !menu.contains(event.target)) close(false); }); window.addEventListener('scroll', () => close(false), { passive: true }); window.addEventListener('resize', () => close(false)); })();