footnotes.js (2079B)
1 /** 2 * Footnotes - Sistema de notas flutuantes (floater) 3 */ 4 5 let activeFloater = null; 6 7 document.addEventListener('click', (e) => { 8 const fn = e.target.closest('a[href^="#fn:"]'); 9 const close = e.target.closest('.f-close'); 10 11 if (close) { 12 closeFloater(); 13 return; 14 } 15 16 if (fn) { 17 e.preventDefault(); 18 e.stopPropagation(); 19 closeFloater(); 20 21 const el = document.getElementById(fn.getAttribute('href').slice(1)); 22 if (!el) return; 23 24 const clone = el.cloneNode(true); 25 clone.querySelector('.footnote-backref')?.remove(); 26 27 const parent = fn.closest('p, li'); 28 const quote = parent ? parent.innerText.slice(0, 40) + '…' : 'Nota'; 29 30 openFloater(fn, quote, clone.innerHTML); 31 fn.classList.add('active'); 32 } else if (activeFloater && !e.target.closest('.floater')) { 33 closeFloater(); 34 } 35 }); 36 37 function openFloater(target, quote, html) { 38 const f = document.createElement('div'); 39 f.className = 'floater'; 40 f.innerHTML = `<div class="f-label"><span>comentário</span><span class="f-close" role="button" tabindex="0" aria-label="Fechar nota">×</span></div><div class="f-quote">${quote}</div><div>${html}</div>`; 41 42 document.body.appendChild(f); 43 44 const r = target.getBoundingClientRect(); 45 const top = window.scrollY + r.bottom + 8; 46 const padding = 20; 47 let left = window.scrollX + r.left; 48 const maxLeft = window.innerWidth - f.offsetWidth - padding; 49 50 if (left > maxLeft) left = Math.max(padding, maxLeft); 51 52 f.style.top = top + 'px'; 53 f.style.left = left + 'px'; 54 55 activeFloater = f; 56 57 // Permitir fechar com Enter ou Space 58 f.querySelector('.f-close').addEventListener('keydown', (e) => { 59 if (e.key === 'Enter' || e.key === ' ') { 60 e.preventDefault(); 61 closeFloater(); 62 } 63 }); 64 } 65 66 function closeFloater() { 67 if (activeFloater) { 68 activeFloater.remove(); 69 activeFloater = null; 70 } 71 document.querySelectorAll('a[href^="#fn:"]').forEach((a) => a.classList.remove('active')); 72 } 73 74 // Fechar com Escape 75 document.addEventListener('keydown', (e) => { 76 if (e.key === 'Escape') closeFloater(); 77 });