'use strict'; // --------------------------------------------------------------------------- // Footnote popover // --------------------------------------------------------------------------- let currentFootnotePopover = null; let _footnotePopoverTimer = null; function showFootnotePopover(link) { dismissFootnotePopover(); const targetEl = document.getElementById(link.dataset.footnoteRef); if (!targetEl) return; // The note's paragraph, also when the id sits on an inline element in it // (
143 Note…
). const inline = /^(A|SPAN|SUP|SUB|B|I|EM|STRONG|SMALL)$/.test(targetEl.tagName); const container = targetEl.closest('.footnote') || (inline && targetEl.closest('p, li, dd, blockquote')) || targetEl.parentElement; if (!container) return; const clone = container.cloneNode(true); clone.querySelector('sup')?.remove(); clone.querySelectorAll('.epub-pagenum').forEach(e => e.remove()); // The note's own number at its start, a link back to the text ("1 Note…"). const first = Array.from(clone.querySelectorAll('a')).find(a => a.textContent.trim()); const num = first ? first.textContent.trim() : ''; if (/^[\[(]?\d{1,4}[\])]?\.?$/.test(num) && clone.textContent.trim().startsWith(num)) first.remove(); // Only the number: the note (a poem, a long quote) runs on in the next // paragraphs, up to the next note's anchor. if (!clone.textContent.trim()) { let len = 0; for (let next = container.nextElementSibling; next && len < 6000; next = next.nextElementSibling) { if (/^H[1-6]$/.test(next.tagName) || next.querySelector('[id]')) break; if (!next.textContent.trim()) continue; clone.appendChild(next.cloneNode(true)); len += next.textContent.length; } } const popover = document.createElement('div'); popover.className = 'footnote-popover'; const _overlay = document.getElementById('reader-overlay'); ['reader-theme-sepia', 'reader-theme-bright'].forEach(cls => { if (_overlay?.classList.contains(cls)) popover.classList.add(cls); }); popover.innerHTML = clone.innerHTML; const closeBtn = document.createElement('button'); closeBtn.className = 'footnote-popover-close'; closeBtn.textContent = '✕'; closeBtn.addEventListener('click', dismissFootnotePopover); popover.appendChild(closeBtn); const rect = link.getBoundingClientRect(); popover.style.top = (rect.bottom + 8) + 'px'; popover.style.left = Math.max(8, rect.left - 8) + 'px'; popover.addEventListener('mouseenter', () => clearTimeout(_footnotePopoverTimer)); popover.addEventListener('mouseleave', () => { _footnotePopoverTimer = setTimeout(dismissFootnotePopover, 250); }); document.body.appendChild(popover); currentFootnotePopover = popover; currentFootnotePopover._refLink = link; const pr = popover.getBoundingClientRect(); if (pr.right > window.innerWidth - 8) popover.style.left = (window.innerWidth - pr.width - 8) + 'px'; if (pr.bottom > window.innerHeight - 8) popover.style.top = (rect.top - pr.height - 8) + 'px'; } function dismissFootnotePopover() { clearTimeout(_footnotePopoverTimer); currentFootnotePopover?.remove(); currentFootnotePopover = null; }