5 Commits
v1.1 ... v1.3.1

9 changed files with 54 additions and 130 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
PLAN-*

View File

@@ -50,22 +50,23 @@
} }
/* /*
* Click-and-drag horizontal scrolling (added by Asset/js/drag-scroll.js when the * Make the top scrollbar thick enough to grab easily (touch / big fingers).
* "Drag the board background to scroll" setting is enabled). The .sv-drag-scroll class * WebKit/Blink (most desktop browsers and mobile Chrome/Safari) let us size the
* is set on #board-container by the script, so these rules are inert when disabled. * scrollbar; styling the thumb/track is needed for it to stay visible once customised.
* A grab cursor advertises the empty background; cards keep the normal cursor since * Thickness comes from the --sv-bar-size variable (Settings -> Shrink Vertically),
* pressing them does a card drag, not a pan. * injected in the page head; falls back to 25px. Chromium/WebKit only (Chrome/Edge/
* Safari, mobile Chrome/Safari); Firefox ignores ::-webkit-scrollbar and keeps its
* default thin bar -- accepted for now.
*/ */
#board-container.sv-drag-scroll { .sv-top-scroll::-webkit-scrollbar {
cursor: grab; height: var(--sv-bar-size, 25px);
} }
#board-container.sv-drag-scroll .task-board { .sv-top-scroll::-webkit-scrollbar-track {
cursor: default; background: rgba(0, 0, 0, 0.05);
} }
.sv-grabbing, .sv-top-scroll::-webkit-scrollbar-thumb {
.sv-grabbing * { background: rgba(0, 0, 0, 0.35);
cursor: grabbing !important; border-radius: 6px;
user-select: none !important;
} }

View File

@@ -1,75 +0,0 @@
/*
* ShrinkVertically -- optional click-and-drag horizontal scrolling of the board.
*
* Like the Trello board canvas: press the empty board background and drag left/right
* to scroll #board-container horizontally. The pan only starts on empty background --
* pressing a task card, a drag handle, or any interactive control is ignored, so this
* never interferes with Kanboard's own card and column drag-and-drop.
*
* Loaded only when the "Drag the board background to scroll" setting is enabled.
*/
(function () {
"use strict";
// Pressing any of these (or their descendants) must NOT start a background pan.
var IGNORE = "a, button, input, textarea, select, label, " +
".task-board, [data-task-id], .task-board-sort-handle, " +
".draggable-row-handle, .dropdown, .ui-sortable-handle";
function isIgnored(el) {
return !!(el && el.closest && el.closest(IGNORE));
}
function init() {
var container = document.getElementById("board-container");
if (!container || container.getAttribute("data-sv-drag") === "1") {
return;
}
container.setAttribute("data-sv-drag", "1");
container.classList.add("sv-drag-scroll");
var dragging = false;
var startX = 0;
var startScrollLeft = 0;
container.addEventListener("mousedown", function (e) {
// Left button only, and only on empty board background.
if (e.button !== 0 || isIgnored(e.target)) {
return;
}
dragging = true;
startX = e.clientX;
startScrollLeft = container.scrollLeft;
container.classList.add("sv-grabbing");
e.preventDefault();
});
document.addEventListener("mousemove", function (e) {
if (!dragging) {
return;
}
container.scrollLeft = startScrollLeft - (e.clientX - startX);
e.preventDefault();
});
function stop() {
if (!dragging) {
return;
}
dragging = false;
container.classList.remove("sv-grabbing");
}
document.addEventListener("mouseup", stop);
document.addEventListener("mouseleave", stop);
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", init);
} else {
init();
}
})();

View File

@@ -14,18 +14,22 @@ class ConfigController extends BaseController
const MIN_OFFSET = 0; const MIN_OFFSET = 0;
const MAX_OFFSET = 2000; const MAX_OFFSET = 2000;
const DEFAULT_BAR_SIZE = 25;
const MIN_BAR_SIZE = 0;
const MAX_BAR_SIZE = 200;
public function show() public function show()
{ {
$offset = (int) $this->configModel->get('shrink_vertically_offset', self::DEFAULT_OFFSET); $offset = (int) $this->configModel->get('shrink_vertically_offset', self::DEFAULT_OFFSET);
$topScrollbar = (int) $this->configModel->get('shrink_vertically_top_scrollbar', 0); $barSize = (int) $this->configModel->get('shrink_vertically_bar_size', self::DEFAULT_BAR_SIZE);
$dragScroll = (int) $this->configModel->get('shrink_vertically_drag_scroll', 0); $topScrollbar = (int) $this->configModel->get('shrink_vertically_top_scrollbar', 1);
$this->response->html($this->helper->layout->config('shrinkVertically:config/show', array( $this->response->html($this->helper->layout->config('shrinkVertically:config/show', array(
'title' => t('Settings').' > '.t('Shrink Vertically'), 'title' => t('Settings').' > '.t('Shrink Vertically'),
'values' => array( 'values' => array(
'shrink_vertically_offset' => $offset, 'shrink_vertically_offset' => $offset,
'shrink_vertically_bar_size' => $barSize,
'shrink_vertically_top_scrollbar' => $topScrollbar, 'shrink_vertically_top_scrollbar' => $topScrollbar,
'shrink_vertically_drag_scroll' => $dragScroll,
), ),
'errors' => array(), 'errors' => array(),
))); )));
@@ -38,13 +42,15 @@ class ConfigController extends BaseController
$offset = isset($values['shrink_vertically_offset']) ? (int) $values['shrink_vertically_offset'] : self::DEFAULT_OFFSET; $offset = isset($values['shrink_vertically_offset']) ? (int) $values['shrink_vertically_offset'] : self::DEFAULT_OFFSET;
$offset = max(self::MIN_OFFSET, min(self::MAX_OFFSET, $offset)); $offset = max(self::MIN_OFFSET, min(self::MAX_OFFSET, $offset));
$barSize = isset($values['shrink_vertically_bar_size']) ? (int) $values['shrink_vertically_bar_size'] : self::DEFAULT_BAR_SIZE;
$barSize = max(self::MIN_BAR_SIZE, min(self::MAX_BAR_SIZE, $barSize));
$topScrollbar = isset($values['shrink_vertically_top_scrollbar']) ? 1 : 0; $topScrollbar = isset($values['shrink_vertically_top_scrollbar']) ? 1 : 0;
$dragScroll = isset($values['shrink_vertically_drag_scroll']) ? 1 : 0;
if ($this->configModel->save(array( if ($this->configModel->save(array(
'shrink_vertically_offset' => $offset, 'shrink_vertically_offset' => $offset,
'shrink_vertically_bar_size' => $barSize,
'shrink_vertically_top_scrollbar' => $topScrollbar, 'shrink_vertically_top_scrollbar' => $topScrollbar,
'shrink_vertically_drag_scroll' => $dragScroll,
))) { ))) {
$this->flash->success(t('Settings saved successfully.')); $this->flash->success(t('Settings saved successfully.'));
} else { } else {

View File

@@ -27,18 +27,11 @@ class Plugin extends Base
$this->template->hook->attach('template:config:sidebar', 'shrinkVertically:config/sidebar'); $this->template->hook->attach('template:config:sidebar', 'shrinkVertically:config/sidebar');
// Optional: a second, mirrored horizontal scrollbar above the board columns. // Optional: a second, mirrored horizontal scrollbar above the board columns.
if ((int) $this->configModel->get('shrink_vertically_top_scrollbar', 0) === 1) { if ((int) $this->configModel->get('shrink_vertically_top_scrollbar', 1) === 1) {
$this->hook->on('template:layout:js', array( $this->hook->on('template:layout:js', array(
'template' => 'plugins/ShrinkVertically/Asset/js/top-scrollbar.js', 'template' => 'plugins/ShrinkVertically/Asset/js/top-scrollbar.js',
)); ));
} }
// Optional: click-and-drag the board background to scroll horizontally.
if ((int) $this->configModel->get('shrink_vertically_drag_scroll', 0) === 1) {
$this->hook->on('template:layout:js', array(
'template' => 'plugins/ShrinkVertically/Asset/js/drag-scroll.js',
));
}
} }
public function getPluginName() public function getPluginName()
@@ -58,7 +51,7 @@ class Plugin extends Base
public function getPluginVersion() public function getPluginVersion()
{ {
return '1.1.0'; return '1.3.1';
} }
public function getPluginHomepage() public function getPluginHomepage()

View File

@@ -1,11 +1,13 @@
# ShrinkVertically -- keep the board horizontal scrollbar visible # ShrinkVertically -- keep the board horizontal scrollbar visible
A small Kanboard plugin focused on getting around the board horizontally. It fixes the A small Kanboard plugin focused on the vertically-collapsed board view. It fixes the
vertically-collapsed board view so the bottom scrollbar stays on screen, can optionally collapse so the bottom horizontal scrollbar stays on screen, and can optionally add a
add a second mirrored scrollbar above the columns, and can optionally let you drag the second mirrored scrollbar above the columns. Configurable under
board background to scroll (like Trello). Everything is configurable under
"Settings -> Shrink Vertically". "Settings -> Shrink Vertically".
Board drag/touch and column-gap options that used to live here have moved to the separate
`TweakDrag` plugin.
## The problem ## The problem
Kanboard's board gear menu has an "expand vertically / collapse vertically" toggle. When Kanboard's board gear menu has an "expand vertically / collapse vertically" toggle. When
@@ -72,28 +74,19 @@ a second, mirrored scrollbar just above the columns. A small script
strip above `#board-container` and keeps its scroll position in sync with the board both strip above `#board-container` and keeps its scroll position in sync with the board both
ways. ways.
## Drag to scroll (optional)
Kanboard has no way to pan the board by grabbing it; you must use the scrollbar. Enable
"Drag the board background to scroll" to click and drag on the empty board background to
scroll the columns sideways, like the Trello board canvas. A small script
(`Asset/js/drag-scroll.js`, loaded only when the option is on) starts a horizontal pan on
`#board-container` only when the press lands on empty background -- pressing a task card,
a drag handle or any control is ignored, so Kanboard's own card and column drag-and-drop
keep working unchanged.
## Settings ## Settings
Go to "Settings -> Shrink Vertically": These settings are global (per Kanboard instance) and admin-only. Go to
"Settings -> Shrink Vertically":
- **Vertical offset in pixels** -- pixels reserved around the collapsed columns. Stored in - **Vertical offset in pixels** -- pixels reserved around the collapsed columns. Injected
the Kanboard configuration and injected in the page head as the `--sv-shrink-offset` CSS in the page head as the `--sv-shrink-offset` CSS variable. Increase it if the scrollbar
variable. Increase it if the scrollbar is still clipped (for example with a taller theme is still clipped (for example with a taller theme header); decrease it to make the
header); decrease it to make the collapsed columns taller. Default: 240. collapsed columns taller. Default: 240.
- **Top Horizontal Scrollbar thickness in pixels** -- thickness of the top scrollbar
(Chromium/WebKit only). Injected as the `--sv-bar-size` CSS variable. Default: 25.
- **Add a top horizontal scrollbar to the board** -- toggles the mirrored top scrollbar - **Add a top horizontal scrollbar to the board** -- toggles the mirrored top scrollbar
described above. described above. Default: on.
- **Drag the board background to scroll horizontally** -- toggles the Trello-style
click-and-drag panning described above.
## License ## License

View File

@@ -14,16 +14,17 @@
</fieldset> </fieldset>
<fieldset> <fieldset>
<?= $this->form->checkbox('shrink_vertically_top_scrollbar', t('Add a top horizontal scrollbar to the board'), 1, isset($values['shrink_vertically_top_scrollbar']) && $values['shrink_vertically_top_scrollbar'] == 1) ?> <?= $this->form->label(t('Top Horizontal Scrollbar thickness in pixels'), 'shrink_vertically_bar_size') ?>
<?= $this->form->number('shrink_vertically_bar_size', $values, $errors) ?>
<p class="form-help"> <p class="form-help">
<?= t('Adds a second horizontal scrollbar above the columns, mirrored with the board scrollbar, so you do not have to scroll to the bottom to move sideways.') ?> <?= t('Thickness of the top horizontal scrollbar (Chromium/WebKit browsers only). Default: 25.') ?>
</p> </p>
</fieldset> </fieldset>
<fieldset> <fieldset>
<?= $this->form->checkbox('shrink_vertically_drag_scroll', t('Drag the board background to scroll horizontally'), 1, isset($values['shrink_vertically_drag_scroll']) && $values['shrink_vertically_drag_scroll'] == 1) ?> <?= $this->form->checkbox('shrink_vertically_top_scrollbar', t('Add a top horizontal scrollbar to the board'), 1, isset($values['shrink_vertically_top_scrollbar']) && $values['shrink_vertically_top_scrollbar'] == 1) ?>
<p class="form-help"> <p class="form-help">
<?= t('Like Trello: click and drag on the empty board background to scroll the columns sideways. Dragging a task card or a handle still works as usual.') ?> <?= t('Adds a second horizontal scrollbar above the columns, mirrored with the board scrollbar, so you do not have to scroll to the bottom to move sideways.') ?>
</p> </p>
</fieldset> </fieldset>

View File

@@ -1,3 +1,6 @@
<style type="text/css"> <style type="text/css">
:root { --sv-shrink-offset: <?= (int) $this->app->config('shrink_vertically_offset', 240) ?>px; } :root {
--sv-shrink-offset: <?= (int) $this->app->config('shrink_vertically_offset', 240) ?>px;
--sv-bar-size: <?= (int) $this->app->config('shrink_vertically_bar_size', 25) ?>px;
}
</style> </style>

View File

@@ -1 +1 @@
ShrinkVertically v1.1 ShrinkVertically v1.3.1