diff --git a/public/index.html b/public/index.html index 0653bb048..9b84047f7 100644 --- a/public/index.html +++ b/public/index.html @@ -4482,7 +4482,7 @@
-
+

diff --git a/public/scripts/keyboard.js b/public/scripts/keyboard.js index 374a2dc69..d28fe243a 100644 --- a/public/scripts/keyboard.js +++ b/public/scripts/keyboard.js @@ -29,34 +29,43 @@ export const NOT_FOCUSABLE_CONTROL_CLASS = 'not_focusable'; export const DISABLED_CONTROL_CLASS = 'disabled'; /** - * An observer that will check if any new interactables are added to the body + * An observer that will check if any new interactables or scroll reset containers are added to the body * @type {MutationObserver} */ const observer = new MutationObserver(mutations => { mutations.forEach(mutation => { if (mutation.type === 'childList') { - mutation.addedNodes.forEach(node => { - if (node.nodeType === Node.ELEMENT_NODE && node instanceof Element) { - // Check if the node itself is an interactable - if (isKeyboardInteractable(node)) { - makeKeyboardInteractable(node); - } - // Check for any descendants that might be an interactable - const interactables = getAllInteractables(node); - makeKeyboardInteractable(...interactables); - } - }); - } else if (mutation.type === 'attributes') { + mutation.addedNodes.forEach(handleNodeChange); + } + if (mutation.type === 'attributes') { const target = mutation.target; if (mutation.attributeName === 'class' && target instanceof Element) { - if (isKeyboardInteractable(target)) { - makeKeyboardInteractable(target); - } + handleNodeChange(target); } } }); }); +/** + * Function to handle node changes (added or modified nodes) + * @param {Element} node + */ +function handleNodeChange(node) { + if (node.nodeType === Node.ELEMENT_NODE && node instanceof Element) { + // Handle keyboard interactables + if (isKeyboardInteractable(node)) { + makeKeyboardInteractable(node); + } + initializeInteractables(node); + + // Handle scroll reset containers + if (node.classList.contains('scroll-reset-container')) { + applyScrollResetBehavior(node); + } + initializeScrollResetBehaviors(node); + } +} + /** * Registers an interactable class (for example for an extension) and makes it keyboard interactable. * Optionally apply the 'not_focusable' and 'disabled' classes if needed. @@ -138,7 +147,6 @@ export function makeKeyboardInteractable(...interactables) { }); } - /** * Initializes the focusability of controls on the given element or the document * @@ -160,6 +168,32 @@ function getAllInteractables(element) { return [].concat(...interactableSelectors.map(selector => Array.from(element.querySelectorAll(`${selector}`)))); } +/** + * Function to apply scroll reset behavior to a container + * @param {Element} container - The container + */ +const applyScrollResetBehavior = (container) => { + container.addEventListener('focusout', (e) => { + setTimeout(() => { + const focusedElement = document.activeElement; + if (!container.contains(focusedElement)) { + container.scrollTop = 0; + container.scrollLeft = 0; + } + }, 0); + }); +}; + +/** + * Initializes the scroll reset behavior on the given element or the document + * + * @param {Element|Document} [element=document] - The element on which to initialize the scroll reset behavior. Defaults to the document. + */ +function initializeScrollResetBehaviors(element = document) { + const scrollResetContainers = element.querySelectorAll('.scroll-reset-container'); + scrollResetContainers.forEach(container => applyScrollResetBehavior(container)); +} + /** * Handles keydown events on the document to trigger click on Enter key press for interactables * @@ -200,8 +234,9 @@ export function initKeyboard() { attributeFilter: ['class'] }); - // Initialize interactable state for already existing controls + // Initialize already existing controls initializeInteractables(); + initializeScrollResetBehaviors(); // Add a global keydown listener document.addEventListener('keydown', handleGlobalKeyDown); diff --git a/public/style.css b/public/style.css index 631ee352a..c6a01502e 100644 --- a/public/style.css +++ b/public/style.css @@ -5164,3 +5164,24 @@ body:not(.movingUI) .drawer-content.maximized { .regex-highlight { color: #FAF8F6; } + +.pagination-indicators { + position: absolute; + bottom: 10px; + left: 50%; + transform: translateX(-50%); + display: flex; + gap: 5px; +} + +.pagination-indicator { + width: 10px; + height: 10px; + background-color: #ddd; + border-radius: 50%; + cursor: pointer; +} + +.pagination-indicator.active { + background-color: #333; +}