fix(tableaux): barre pleine largeur viewport + masquage par table #82

- adjustBarWidth() brise le padding Bootstrap (margin-left négatif +
  width: 100vw) pour que la barre s'étende jusqu'au bord de la fenêtre
- metrics() utilise window.innerWidth comme largeur de piste (cohérent
  avec la barre pleine largeur)
- hasOverflow mesure la largeur de .cell-table de CETTE table via
  getBoundingClientRect(), plutôt que document.documentElement.scrollWidth
  → les petits tableaux (top10 /acheteur, /titulaire, /observatoire)
  n'affichent pas de barre s'ils ne débordent pas individuellement

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Colin Maudry
2026-06-23 19:02:36 +02:00
parent 9c5fc9257a
commit 3c0cf6bc07
+30 -11
View File
@@ -19,15 +19,22 @@
bar.appendChild(thumb); bar.appendChild(thumb);
wrapper.insertBefore(bar, wrapper.firstChild); wrapper.insertBefore(bar, wrapper.firstChild);
// --- Métriques communes --- // Étend la barre à toute la largeur du viewport, hors du container Bootstrap.
// wrapper.getBoundingClientRect().left donne le décalage horizontal du conteneur.
const adjustBarWidth = () => {
const left = wrapper.getBoundingClientRect().left;
bar.style.marginLeft = -left + "px";
bar.style.width = window.innerWidth + "px";
};
// Métriques basées sur window.innerWidth (la barre occupe exactement la largeur du viewport).
const metrics = () => { const metrics = () => {
const total = document.documentElement.scrollWidth; const total = document.documentElement.scrollWidth;
const visible = window.innerWidth; const visible = window.innerWidth;
const trackW = bar.clientWidth; const thumbW = Math.max(40, (visible / total) * visible);
const thumbW = Math.max(40, (visible / total) * trackW);
const scrollRange = total - visible; const scrollRange = total - visible;
const thumbRange = trackW - thumbW; const thumbRange = visible - thumbW;
return { total, visible, trackW, thumbW, scrollRange, thumbRange }; return { total, visible, thumbW, scrollRange, thumbRange };
}; };
// --- Mise à jour de la position du thumb --- // --- Mise à jour de la position du thumb ---
@@ -91,22 +98,31 @@
// Clic sur le track (hors thumb) : saute à la position cliquée. // Clic sur le track (hors thumb) : saute à la position cliquée.
bar.addEventListener("click", (e) => { bar.addEventListener("click", (e) => {
if (e.target === thumb) return; if (e.target === thumb) return;
const rect = bar.getBoundingClientRect();
const { scrollRange, thumbW, thumbRange } = metrics(); const { scrollRange, thumbW, thumbRange } = metrics();
const fraction = Math.max( const fraction = Math.max(
0, 0,
Math.min(1, (e.clientX - rect.left - thumbW / 2) / thumbRange) Math.min(
1,
(e.clientX - bar.getBoundingClientRect().left - thumbW / 2) /
thumbRange
)
); );
window.scrollTo(fraction * scrollRange, window.scrollY); window.scrollTo(fraction * scrollRange, window.scrollY);
}); });
// Synchronise le thumb quand la page défile (via clavier, molette, etc.). // Synchronise le thumb quand la page défile (clavier, molette, barre native, etc.).
// SPA : ce listener est intentionnellement conservé pour toute la durée de vie de la page. // SPA : ce listener est intentionnellement conservé pour toute la durée de vie de la page.
window.addEventListener("scroll", syncThumb); window.addEventListener("scroll", syncThumb);
const refresh = () => { const refresh = () => {
const { total, visible } = metrics(); adjustBarWidth();
const hasOverflow = total > visible + 1; // Mesure la largeur réelle de CETTE table (pas de la page entière) pour
// ne pas afficher la barre sur les petits tableaux d'une page qui a aussi
// un grand tableau (ex. top10 sur /acheteur, /titulaire, /observatoire).
const tableEl =
dashContainer.querySelector(".cell-table") || dashContainer;
const tableWidth = tableEl.getBoundingClientRect().width;
const hasOverflow = tableWidth > window.innerWidth + 1;
bar.classList.toggle("is-hidden", !hasOverflow); bar.classList.toggle("is-hidden", !hasOverflow);
if (hasOverflow) syncThumb(); if (hasOverflow) syncThumb();
}; };
@@ -119,7 +135,10 @@
attributes: true, attributes: true,
}); });
// SPA : ce listener est intentionnellement conservé pour toute la durée de vie de la page. // SPA : ce listener est intentionnellement conservé pour toute la durée de vie de la page.
window.addEventListener("resize", refresh); window.addEventListener("resize", () => {
adjustBarWidth();
refresh();
});
refresh(); refresh();
} }