Fix tabbing with hotswap multiple rows

- Add scroll-reset-container CSS class and handling
- Fix tabbing through hotswap favs by resetting position
This commit is contained in:
Wolfsblvt 2024-06-16 23:13:36 +02:00
parent 60b09a431a
commit f67ed6d22a
3 changed files with 75 additions and 19 deletions

View File

@ -4482,7 +4482,7 @@
<div class="right_menu_button fa-solid fa-list-ul" id="rm_button_characters" title="Select/Create Characters" data-i18n="[title]Select/Create Characters"></div>
</div>
<div id="HotSwapWrapper" class="alignitemscenter flex-container margin0auto wide100p">
<div class="hotswap avatars_inline flex-container expander" data-i18n="[no_favs]Favorite characters to add them to HotSwaps" no_favs="Favorite characters to add them to HotSwaps"></div>
<div class="hotswap avatars_inline flex-container scroll-reset-container expander" data-i18n="[no_favs]Favorite characters to add them to HotSwaps" no_favs="Favorite characters to add them to HotSwaps"></div>
</div>
</div>
<hr>

View File

@ -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);
mutation.addedNodes.forEach(handleNodeChange);
}
// Check for any descendants that might be an interactable
const interactables = getAllInteractables(node);
makeKeyboardInteractable(...interactables);
}
});
} else if (mutation.type === 'attributes') {
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);

View File

@ -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;
}