summaryrefslogtreecommitdiff
path: root/static/footnotes.js
diff options
context:
space:
mode:
Diffstat (limited to 'static/footnotes.js')
-rw-r--r--static/footnotes.js77
1 files changed, 77 insertions, 0 deletions
diff --git a/static/footnotes.js b/static/footnotes.js
new file mode 100644
index 0000000..1d2700a
--- /dev/null
+++ b/static/footnotes.js
@@ -0,0 +1,77 @@
+/**
+ * Footnotes - Sistema de notas flutuantes (floater)
+ */
+
+let activeFloater = null;
+
+document.addEventListener('click', (e) => {
+ const fn = e.target.closest('a[href^="#fn:"]');
+ const close = e.target.closest('.f-close');
+
+ if (close) {
+ closeFloater();
+ return;
+ }
+
+ if (fn) {
+ e.preventDefault();
+ e.stopPropagation();
+ closeFloater();
+
+ const el = document.getElementById(fn.getAttribute('href').slice(1));
+ if (!el) return;
+
+ const clone = el.cloneNode(true);
+ clone.querySelector('.footnote-backref')?.remove();
+
+ const parent = fn.closest('p, li');
+ const quote = parent ? parent.innerText.slice(0, 40) + '…' : 'Nota';
+
+ openFloater(fn, quote, clone.innerHTML);
+ fn.classList.add('active');
+ } else if (activeFloater && !e.target.closest('.floater')) {
+ closeFloater();
+ }
+});
+
+function openFloater(target, quote, html) {
+ const f = document.createElement('div');
+ f.className = 'floater';
+ 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>`;
+
+ document.body.appendChild(f);
+
+ const r = target.getBoundingClientRect();
+ const top = window.scrollY + r.bottom + 8;
+ const padding = 20;
+ let left = window.scrollX + r.left;
+ const maxLeft = window.innerWidth - f.offsetWidth - padding;
+
+ if (left > maxLeft) left = Math.max(padding, maxLeft);
+
+ f.style.top = top + 'px';
+ f.style.left = left + 'px';
+
+ activeFloater = f;
+
+ // Permitir fechar com Enter ou Space
+ f.querySelector('.f-close').addEventListener('keydown', (e) => {
+ if (e.key === 'Enter' || e.key === ' ') {
+ e.preventDefault();
+ closeFloater();
+ }
+ });
+}
+
+function closeFloater() {
+ if (activeFloater) {
+ activeFloater.remove();
+ activeFloater = null;
+ }
+ document.querySelectorAll('a[href^="#fn:"]').forEach((a) => a.classList.remove('active'));
+}
+
+// Fechar com Escape
+document.addEventListener('keydown', (e) => {
+ if (e.key === 'Escape') closeFloater();
+});