87 lines
2.9 KiB
JavaScript
87 lines
2.9 KiB
JavaScript
|
|
/*
|
||
|
|
* 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();
|
||
|
|
}
|
||
|
|
})();
|