carhop__dynamiques-theme__P.../resources/js/singles/footnote-format.ts
Nonimart 53e280383e
All checks were successful
continuous-integration/drone/push Build is passing
FEATURE + REFACTOR Handling sommaire chapter progression + refactoring footnote hebaviour
2025-09-25 11:59:29 +02:00

96 lines
3.6 KiB
TypeScript

import { toggleActiveTabPanel } from './index-panel';
/* ********************************************************
* ************* SCROLLING FUNCTIONS *********************
* ********************************************************
*/
export function scrollToFootnoteInIndexPanel(footnoteId: string): void {
const footnotesIndex = document.querySelector('#footnotes-index') as HTMLElement;
const footnotesIndexContainer = document.querySelector('ul#footnotes-index');
const indexPanelContent = document.querySelector('.index-panel__content') as HTMLElement;
const currentFootnote = footnotesIndexContainer?.querySelector(
`a[href="#${footnoteId}"]`
) as HTMLElement;
if (currentFootnote && footnotesIndexContainer) {
const containerRect = footnotesIndexContainer.getBoundingClientRect();
const elementRect = currentFootnote.getBoundingClientRect();
const relativeTop = elementRect.top - containerRect.top;
const scrollTop = footnotesIndexContainer.scrollTop + relativeTop - 20;
footnotesIndexContainer.scrollTo({
top: scrollTop,
behavior: 'smooth',
});
}
}
export function scrollToFootnote(footnoteId: string): void {
const footnote = document.querySelector(`a.footnote-reference#${footnoteId}`);
if (!footnote) return;
footnote.scrollIntoView({ behavior: 'smooth' });
}
/* ********************************************************
* ************* TOGGLE ACTIVE ***************************
* ********************************************************
*/
export function toggleActiveFootnoteLinkInIndexPanel(footnoteId: string): void {
const footnotesIndexLinks = document.querySelectorAll('.footnote-reference-item');
const indexPanel = document.querySelector('.index-panel') as HTMLElement;
const currentFootnote = indexPanel.querySelector(`a[href="#${footnoteId}"]`) as HTMLElement;
footnotesIndexLinks.forEach((footnoteLink) => {
footnoteLink.setAttribute('active', 'false');
});
currentFootnote?.setAttribute('active', 'true');
}
/* ********************************************************
* ************* OBSERVE LINKS ***************************
* ********************************************************
*/
export function observeFootnotesLinks(): void {
const footnotesLinks = document.querySelectorAll('.footnotes-index a');
footnotesLinks.forEach((footnoteLink) => {
footnoteLink.addEventListener('click', (e) => {
e.preventDefault();
const target = e.target as HTMLElement;
const href = target.getAttribute('href');
if (!href) return;
const targetId = href.startsWith('#') ? href.substring(1) : href;
if (!targetId) return;
scrollToFootnote(targetId);
// document.querySelector(`#${targetId}`)?.scrollIntoView({ behavior: 'smooth' });
toggleActiveFootnoteLinkInIndexPanel(targetId);
scrollToFootnoteInIndexPanel(targetId);
});
});
}
/* ********************************************************
* ************* MAIN — HANDLE GENERAL BEHAVIOUR *********
* ********************************************************
*/
export default function handleFootnoteFormat(): void {
const footnotes = document.querySelectorAll('.content-area .footnote-reference');
footnotes.forEach((footnote) => {
const footnoteId = footnote.getAttribute('id');
if (!footnoteId) return;
footnote.addEventListener('click', () => {
toggleActiveTabPanel('footnotes');
scrollToFootnoteInIndexPanel(footnoteId);
toggleActiveFootnoteLinkInIndexPanel(footnoteId);
});
});
}