mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-06-25 08:09:18 +02:00
- Add searchLanguages, getAllLanguagesWithCount, renameLanguage, mergeLanguage, deleteLanguage to Database - Create actions/language.php handler with rename/merge/merge_bulk/delete actions - Add merge_bulk action to actions/tag.php - Add Mots-clés section to contenus template with HTMX search, select checkboxes, rename/delete/merge buttons, and multi-select merge toolbar - Add Langues section to contenus template with same pattern - Create contenus-tags-fragment.php and contenus-languages-fragment.php HTMX fragments - Remove form-settings- from flat-fieldset CSS selector so fieldsets in contenus retain border/padding - contenus.php: add 'Gérer les mots-clés' link to /admin/tags.php - contenus.php: add Langues fieldset with HTMX search + table (rename/merge/delete/bulk) - tags.php: add HTMX search bar, checkbox column, bulk merge toolbar - Create tags-fragment.php and contenus-langues-fragment.php for HTMX - Remove tab component and associated CSS - Simplify JS: separate tags/langues-prefixed functions - Fix redirects: tag.php defaults to /admin/tags.php, supports return override - Keep tags.php standalone page and Mots-clés button unchanged
79 lines
2.3 KiB
PHP
79 lines
2.3 KiB
PHP
<?php
|
|
/**
|
|
* admin-toc.php — sidebar table-of-contents for long admin pages.
|
|
*
|
|
* Scans <section aria-labelledby="..."> elements in #main-content and builds a
|
|
* slim vertical nav. Uses IntersectionObserver to highlight the active section.
|
|
*
|
|
* Usage: include APP_ROOT . '/templates/admin/partials/admin-toc.php';
|
|
*/
|
|
?>
|
|
<nav id="admin-toc" class="admin-toc" aria-label="Sur cette page">
|
|
<ul class="admin-toc-list" id="admin-toc-list">
|
|
<!-- populated by JS -->
|
|
</ul>
|
|
</nav>
|
|
|
|
<script>
|
|
(function() {
|
|
var main = document.getElementById('main-content');
|
|
if (!main) return;
|
|
|
|
var tocList = document.getElementById('admin-toc-list');
|
|
if (!tocList) return;
|
|
|
|
// Find all labelled sections
|
|
var sections = main.querySelectorAll('section[aria-labelledby]');
|
|
if (sections.length < 2) {
|
|
document.getElementById('admin-toc').style.display = 'none';
|
|
return;
|
|
}
|
|
|
|
var items = [];
|
|
|
|
sections.forEach(function(sec) {
|
|
var headingId = sec.getAttribute('aria-labelledby');
|
|
var heading = document.getElementById(headingId);
|
|
if (!heading) return;
|
|
|
|
var li = document.createElement('li');
|
|
var a = document.createElement('a');
|
|
a.href = '#' + sec.id;
|
|
a.textContent = heading.textContent;
|
|
a.setAttribute('data-toc-target', sec.id);
|
|
li.appendChild(a);
|
|
tocList.appendChild(li);
|
|
|
|
// Ensure section has an id for anchoring
|
|
if (!sec.id) {
|
|
sec.id = headingId;
|
|
}
|
|
|
|
items.push({ section: sec, link: a });
|
|
});
|
|
|
|
// IntersectionObserver: highlight the link whose section is most visible
|
|
var observer = new IntersectionObserver(function(entries) {
|
|
var best = null;
|
|
var bestRatio = 0;
|
|
entries.forEach(function(e) {
|
|
if (e.intersectionRatio > bestRatio) {
|
|
bestRatio = e.intersectionRatio;
|
|
best = e.target;
|
|
}
|
|
});
|
|
if (best) {
|
|
items.forEach(function(item) {
|
|
var isActive = item.section === best;
|
|
item.link.classList.toggle('admin-toc-active', isActive);
|
|
});
|
|
}
|
|
}, {
|
|
rootMargin: '-10% 0px -70% 0px',
|
|
threshold: [0, 0.25, 0.5, 0.75, 1]
|
|
});
|
|
|
|
items.forEach(function(item) { observer.observe(item.section); });
|
|
})();
|
|
</script>
|