From e7835c73f24dda216d832e9f7ce0d23b16b0feb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20K=C5=82osko?= Date: Tue, 15 Mar 2022 11:52:29 +0100 Subject: [PATCH] Use the first cell in viewport as the default for j/k navigation (#1054) --- assets/js/lib/utils.js | 5 +++++ assets/js/session/index.js | 14 ++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/assets/js/lib/utils.js b/assets/js/lib/utils.js index 8f94c30d5..9ae3359f8 100644 --- a/assets/js/lib/utils.js +++ b/assets/js/lib/utils.js @@ -12,6 +12,11 @@ export function isEditableElement(element) { ); } +export function isElementInViewport(element) { + const box = element.getBoundingClientRect(); + return box.bottom >= 0 && box.top <= window.innerHeight; +} + export function clamp(n, x, y) { return Math.min(Math.max(n, x), y); } diff --git a/assets/js/session/index.js b/assets/js/session/index.js index 1873cdab0..b341ea889 100644 --- a/assets/js/session/index.js +++ b/assets/js/session/index.js @@ -6,6 +6,7 @@ import { smoothlyScrollToElement, setFavicon, cancelEvent, + isElementInViewport, } from "../lib/utils"; import { getAttributeOrDefault } from "../lib/attribute"; import KeyBuffer from "./key_buffer"; @@ -1057,6 +1058,12 @@ function nearbyFocusableId(focusableId, offset) { const idx = focusableIds.indexOf(focusableId); if (idx === -1) { + const focusableElInViewport = getFocusableEls().find(isElementInViewport); + + if (focusableElInViewport) { + return focusableElInViewport.getAttribute("data-focusable-id"); + } + return focusableIds[0]; } else { const siblingIdx = clamp(idx + offset, 0, focusableIds.length - 1); @@ -1083,9 +1090,12 @@ function getFocusableEl(focusableId) { return document.querySelector(`[data-focusable-id="${focusableId}"]`); } +function getFocusableEls() { + return Array.from(document.querySelectorAll(`[data-focusable-id]`)); +} + function getFocusableIds() { - const elements = Array.from(document.querySelectorAll(`[data-focusable-id]`)); - return elements.map((el) => el.getAttribute("data-focusable-id")); + return getFocusableEls().map((el) => el.getAttribute("data-focusable-id")); } function getSectionIdByFocusableId(focusableId) {