/* * ShrinkVertically -- "Auto adjust" mode. Measure the collapsed board live and set the * --sv-shrink-offset CSS variable so the columns exactly fill the remaining viewport and the * native right-side vertical scrollbar is not needed. Loaded only when the setting is on * (Settings -> Shrink Vertically); it overrides the static offset injected by layout/variable.php. * * The collapsed column height is calc(100vh - var(--sv-shrink-offset)). To fit the screen we need: * offset = (task-list top, i.e. the chrome above) + (horizontal scrollbar below) + a small margin * so column_bottom + scrollbar stays within the viewport. Both terms are measured from the DOM, so * this adapts to any screen size, theme, or header height. * * Re-measures on resize, on collapse/expand (a class toggle), and after a board refresh * (BoardDragAndDrop replaces #board-container -- so, like the other plugins, the observer is bound * to the STABLE parent, not to the container that gets swapped out). */ (function () { "use strict"; var BOTTOM_MARGIN = 16; // breathing room below the columns var scheduled = false; function apply() { scheduled = false; var list = document.querySelector("#board .board-task-list.board-task-list-compact"); if (! list) { return; // board not collapsed -> nothing to auto-size } var top = list.getBoundingClientRect().top; var container = document.getElementById("board-container"); var bar = container ? (container.offsetHeight - container.clientHeight) : 0; // horizontal scrollbar if (bar < 0) { bar = 0; } var offset = Math.ceil(top + bar + BOTTOM_MARGIN); if (offset < 0) { offset = 0; } var next = offset + "px"; var root = document.documentElement; // Only write when it actually changes, so mid-drag class churn does not thrash layout. if (root.style.getPropertyValue("--sv-shrink-offset") !== next) { root.style.setProperty("--sv-shrink-offset", next); } } function schedule() { if (! scheduled) { scheduled = true; window.requestAnimationFrame(apply); } } function init() { var container = document.getElementById("board-container"); if (! container) { return; // not a board page } schedule(); window.addEventListener("resize", schedule); if (window.MutationObserver && container.parentNode) { new MutationObserver(schedule).observe(container.parentNode, { childList: true, subtree: true, attributes: true, attributeFilter: ["class"] }); } } if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", init); } else { init(); } })();