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:
parent
60b09a431a
commit
f67ed6d22a
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue