feat: boutons haut/bas de page dans la sidebar article

This commit is contained in:
Cedric Abonnel
2026-05-13 01:18:24 +02:00
parent 11dce4510b
commit 0a44ab9da2
8 changed files with 415 additions and 18 deletions
+41
View File
@@ -0,0 +1,41 @@
// reactions.js — toggle réactions via fetch, fallback formulaire natif
document.addEventListener('DOMContentLoaded', function () {
document.querySelectorAll('.reaction-form').forEach(function (form) {
form.addEventListener('submit', function (e) {
e.preventDefault();
var btn = form.querySelector('.reaction-btn');
var type = form.querySelector('[name="type"]').value;
var uuid = form.querySelector('[name="uuid"]').value;
var badge = form.querySelector('.reaction-count');
var active = btn.classList.contains('btn-primary');
var data = new URLSearchParams();
data.append('uuid', uuid);
data.append('type', type);
data.append('_ajax', '1');
fetch('/react', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: data.toString(),
})
.then(function (r) { return r.json(); })
.then(function (json) {
if (!json.ok) { form.submit(); return; }
var nowActive = json.active;
btn.classList.toggle('btn-primary', nowActive);
btn.classList.toggle('btn-outline-secondary', !nowActive);
if (badge) {
badge.classList.toggle('bg-light', nowActive);
badge.classList.toggle('text-primary', nowActive);
badge.classList.toggle('bg-secondary', !nowActive);
badge.textContent = json.count;
}
})
.catch(function () { form.submit(); });
});
});
});
+30 -16
View File
@@ -1,23 +1,37 @@
(function () {
var headings = document.querySelectorAll('.post-content h2, .post-content h3');
var links = document.querySelectorAll('.toc-list a');
if (!headings.length || !links.length) return;
var map = {};
links.forEach(function (a) {
map[decodeURIComponent(a.getAttribute('href').slice(1))] = a;
});
var active = null;
var observer = new IntersectionObserver(function (entries) {
entries.forEach(function (entry) {
if (entry.isIntersecting) {
if (active) active.classList.remove('toc-active');
active = map[entry.target.id] || null;
if (active) active.classList.add('toc-active');
}
if (headings.length && links.length) {
var map = {};
links.forEach(function (a) {
map[decodeURIComponent(a.getAttribute('href').slice(1))] = a;
});
}, { rootMargin: '-8% 0px -82% 0px', threshold: 0 });
headings.forEach(function (h) { observer.observe(h); });
var active = null;
var observer = new IntersectionObserver(function (entries) {
entries.forEach(function (entry) {
if (entry.isIntersecting) {
if (active) active.classList.remove('toc-active');
active = map[entry.target.id] || null;
if (active) active.classList.add('toc-active');
}
});
}, { rootMargin: '-8% 0px -82% 0px', threshold: 0 });
headings.forEach(function (h) { observer.observe(h); });
}
var btnTop = document.getElementById('toc-go-top');
var btnBot = document.getElementById('toc-go-bottom');
if (btnTop) {
btnTop.addEventListener('click', function () {
window.scrollTo({ top: 0, behavior: 'smooth' });
});
}
if (btnBot) {
btnBot.addEventListener('click', function () {
window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' });
});
}
})();