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 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>
|
||||||
<div id="HotSwapWrapper" class="alignitemscenter flex-container margin0auto wide100p">
|
<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>
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
|
@ -29,34 +29,43 @@ export const NOT_FOCUSABLE_CONTROL_CLASS = 'not_focusable';
|
||||||
export const DISABLED_CONTROL_CLASS = 'disabled';
|
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}
|
* @type {MutationObserver}
|
||||||
*/
|
*/
|
||||||
const observer = new MutationObserver(mutations => {
|
const observer = new MutationObserver(mutations => {
|
||||||
mutations.forEach(mutation => {
|
mutations.forEach(mutation => {
|
||||||
if (mutation.type === 'childList') {
|
if (mutation.type === 'childList') {
|
||||||
mutation.addedNodes.forEach(node => {
|
mutation.addedNodes.forEach(handleNodeChange);
|
||||||
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
|
if (mutation.type === 'attributes') {
|
||||||
const interactables = getAllInteractables(node);
|
|
||||||
makeKeyboardInteractable(...interactables);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if (mutation.type === 'attributes') {
|
|
||||||
const target = mutation.target;
|
const target = mutation.target;
|
||||||
if (mutation.attributeName === 'class' && target instanceof Element) {
|
if (mutation.attributeName === 'class' && target instanceof Element) {
|
||||||
if (isKeyboardInteractable(target)) {
|
handleNodeChange(target);
|
||||||
makeKeyboardInteractable(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.
|
* Registers an interactable class (for example for an extension) and makes it keyboard interactable.
|
||||||
* Optionally apply the 'not_focusable' and 'disabled' classes if needed.
|
* 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
|
* 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}`))));
|
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
|
* Handles keydown events on the document to trigger click on Enter key press for interactables
|
||||||
*
|
*
|
||||||
|
@ -200,8 +234,9 @@ export function initKeyboard() {
|
||||||
attributeFilter: ['class']
|
attributeFilter: ['class']
|
||||||
});
|
});
|
||||||
|
|
||||||
// Initialize interactable state for already existing controls
|
// Initialize already existing controls
|
||||||
initializeInteractables();
|
initializeInteractables();
|
||||||
|
initializeScrollResetBehaviors();
|
||||||
|
|
||||||
// Add a global keydown listener
|
// Add a global keydown listener
|
||||||
document.addEventListener('keydown', handleGlobalKeyDown);
|
document.addEventListener('keydown', handleGlobalKeyDown);
|
||||||
|
|
|
@ -5164,3 +5164,24 @@ body:not(.movingUI) .drawer-content.maximized {
|
||||||
.regex-highlight {
|
.regex-highlight {
|
||||||
color: #FAF8F6;
|
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