carhop__dynamiques-theme__P.../resources/js/singles/index-panel.ts
Nonimart 0040c76b3f
All checks were successful
continuous-integration/drone/push Build is passing
FEATURE optimizing mobile index-panel on singles articles
2025-09-04 17:43:54 +02:00

162 lines
5.6 KiB
TypeScript

import { scrollToFootnote } from './footnote-format';
import { handleSmoothScrollToTitle } from './sommaire';
export default function handleIndexPanel(): void {
const indexPanel = document.querySelector('.index-panel');
if (!indexPanel) return;
observeTabsButtons();
observeFootnotesLinks();
observeSommaireLinks();
handleMobileOpenToggle();
}
function handleMobileOpenToggle(): void {
const mobileOpenToggle = document.querySelector('#mobile-open-toggle');
const indexPanel = document.querySelector('.index-panel');
if (!mobileOpenToggle) return;
if (!indexPanel) return;
mobileOpenToggle.addEventListener('click', () => {
const isMobileOpen = indexPanel.getAttribute('data-mobile-open');
console.log(isMobileOpen);
if (isMobileOpen === 'true') {
indexPanel.setAttribute('data-mobile-open', 'false');
} else {
indexPanel.setAttribute('data-mobile-open', 'true');
}
});
}
// HANDLE TABS
function observeTabsButtons(): void {
const buttons = document.querySelectorAll('.index-panel__header button');
buttons.forEach((button) => {
button.addEventListener('click', () => {
toggleActiveTabPanel(button.getAttribute('data-index') as string);
});
});
}
export function toggleActiveTabPanel(dataIndex: string): void {
const activePanel = document.querySelector<HTMLElement>(
`.index-panel__content > [data-index="${dataIndex}"]`
);
const activeButton = document.querySelector<HTMLElement>(
`.index-panel__header button[data-index="${dataIndex}"]`
);
if (!dataIndex || !activePanel || !activeButton) return;
// Hide all buttons and panels
const allButtons = document.querySelectorAll<HTMLElement>('.index-panel__header button');
const allPanels = document.querySelectorAll<HTMLElement>('.index-panel__content > [data-index]');
allButtons.forEach((button) => {
button.setAttribute('aria-selected', 'false');
});
allPanels.forEach((panel) => {
panel.setAttribute('aria-hidden', 'true');
});
activeButton.setAttribute('aria-selected', 'true');
activePanel.setAttribute('aria-hidden', 'false');
}
// ********************************************************
// ************* SOMMAIRE *********************************
// ********************************************************
function observeSommaireLinks(): void {
const sommaireTitles: NodeListOf<Element> = document.querySelectorAll('.sommaire-index li a');
for (const title of sommaireTitles) {
title.addEventListener('click', (e) => {
e.preventDefault();
const href = title.getAttribute('href');
if (!href) return;
const targetId = href.startsWith('#') ? href.substring(1) : href;
if (!targetId) return;
handleSmoothScrollToTitle(targetId);
toggleActiveChapterLinkInIndexPanel(targetId);
});
}
}
function toggleActiveChapterLinkInIndexPanel(targetId: string): void {
const sommaireLinks: NodeListOf<Element> = document.querySelectorAll('.sommaire-index li a');
const indexPanel = document.querySelector('.index-panel') as HTMLElement;
const currentLink = indexPanel.querySelector(`a[href="#${targetId}"]`) as HTMLElement;
if (!currentLink) return;
for (const link of sommaireLinks) {
link.setAttribute('active', 'false');
}
currentLink?.setAttribute('active', 'true');
}
// ********************************************************
// ************* FOOTNOTES *********************************
// ********************************************************
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);
});
});
}
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');
}
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',
});
}
}