Back to .net8.0 api/v4/InfinityQS ApiExplorerSettings Wafer Counter Color Sorting
122 lines
4.8 KiB
JavaScript
122 lines
4.8 KiB
JavaScript
/**
|
|
* Copy/pasted from https://github.com/andreasbm/focus-trap
|
|
*/
|
|
/**
|
|
* Traverses the slots of the open shadowroots and returns all children matching the query.
|
|
* We need to traverse each child-depth one at a time because if an element should be skipped
|
|
* (for example because it is hidden) we need to skip all of it's children. If we use querySelectorAll("*")
|
|
* the information of whether the children is within a hidden parent is lost.
|
|
* @param {ShadowRoot | HTMLElement} root
|
|
* @param skipNode
|
|
* @param isMatch
|
|
* @param {number} maxDepth
|
|
* @param {number} depth
|
|
* @returns {HTMLElement[]}
|
|
*/
|
|
export function queryShadowRoot(root, skipNode, isMatch, maxDepth = 20, depth = 0) {
|
|
const matches = [];
|
|
// If the depth is above the max depth, abort the searching here.
|
|
if (depth >= maxDepth) {
|
|
return matches;
|
|
}
|
|
// Traverses a slot element
|
|
const traverseSlot = ($slot) => {
|
|
// Only check nodes that are of the type Node.ELEMENT_NODE
|
|
// Read more here https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
|
|
const assignedNodes = $slot
|
|
.assignedNodes()
|
|
.filter((node) => node.nodeType === 1);
|
|
if (assignedNodes.length > 0) {
|
|
const $slotParent = assignedNodes[0].parentElement;
|
|
return queryShadowRoot($slotParent, skipNode, isMatch, maxDepth, depth + 1);
|
|
}
|
|
return [];
|
|
};
|
|
// Go through each child and continue the traversing if necessary
|
|
// Even though the typing says that children can't be undefined, Edge 15 sometimes gives an undefined value.
|
|
// Therefore we fallback to an empty array if it is undefined.
|
|
const children = Array.from(root.children || []);
|
|
for (const $child of children) {
|
|
// Check if the element and its descendants should be skipped
|
|
if (skipNode($child)) {
|
|
// console.log('-- SKIP', $child);
|
|
continue;
|
|
}
|
|
// console.log('$child', $child);
|
|
// If the element matches we always add it
|
|
if (isMatch($child)) {
|
|
matches.push($child);
|
|
}
|
|
if ($child.shadowRoot != null) {
|
|
// If the element has a shadow root we need to traverse it
|
|
matches.push(...queryShadowRoot($child.shadowRoot, skipNode, isMatch, maxDepth, depth + 1));
|
|
}
|
|
else if ($child.tagName === 'SLOT') {
|
|
// If the child is a slot we need to traverse each assigned node
|
|
matches.push(...traverseSlot($child));
|
|
}
|
|
else {
|
|
// Traverse the children of the element
|
|
matches.push(...queryShadowRoot($child, skipNode, isMatch, maxDepth, depth + 1));
|
|
}
|
|
}
|
|
return matches;
|
|
}
|
|
/**
|
|
* Returns whether the element is hidden.
|
|
* @param $elem
|
|
*/
|
|
export function isHidden($elem) {
|
|
return ($elem.hasAttribute('hidden') ||
|
|
($elem.hasAttribute('aria-hidden') &&
|
|
$elem.getAttribute('aria-hidden') !== 'false') ||
|
|
// A quick and dirty way to check whether the element is hidden.
|
|
// For a more fine-grained check we could use "window.getComputedStyle" but we don't because of bad performance.
|
|
// If the element has visibility set to "hidden" or "collapse", display set to "none" or opacity set to "0" through CSS
|
|
// we won't be able to catch it here. We accept it due to the huge performance benefits.
|
|
$elem.style.display === `none` ||
|
|
$elem.style.opacity === `0` ||
|
|
$elem.style.visibility === `hidden` ||
|
|
$elem.style.visibility === `collapse`);
|
|
// If offsetParent is null we can assume that the element is hidden
|
|
// https://stackoverflow.com/questions/306305/what-would-make-offsetparent-null
|
|
// || $elem.offsetParent == null;
|
|
}
|
|
/**
|
|
* Returns whether the element is disabled.
|
|
* @param $elem
|
|
*/
|
|
export function isDisabled($elem) {
|
|
return ($elem.hasAttribute('disabled') ||
|
|
($elem.hasAttribute('aria-disabled') &&
|
|
$elem.getAttribute('aria-disabled') !== 'false'));
|
|
}
|
|
/**
|
|
* Determines whether an element is focusable.
|
|
* Read more here: https://stackoverflow.com/questions/1599660/which-html-elements-can-receive-focus/1600194#1600194
|
|
* Or here: https://stackoverflow.com/questions/18261595/how-to-check-if-a-dom-element-is-focusable
|
|
* @param $elem
|
|
*/
|
|
export function isFocusable($elem) {
|
|
// Discard elements that are removed from the tab order.
|
|
if ($elem.getAttribute('tabindex') === '-1' ||
|
|
isHidden($elem) ||
|
|
isDisabled($elem)) {
|
|
return false;
|
|
}
|
|
return (
|
|
// At this point we know that the element can have focus (eg. won't be -1) if the tabindex attribute exists
|
|
$elem.hasAttribute('tabindex') ||
|
|
// Anchor tags or area tags with a href set
|
|
(($elem instanceof HTMLAnchorElement || $elem instanceof HTMLAreaElement) &&
|
|
$elem.hasAttribute('href')) ||
|
|
// Form elements which are not disabled
|
|
$elem instanceof HTMLButtonElement ||
|
|
$elem instanceof HTMLInputElement ||
|
|
$elem instanceof HTMLTextAreaElement ||
|
|
$elem instanceof HTMLSelectElement ||
|
|
// IFrames
|
|
$elem instanceof HTMLIFrameElement);
|
|
}
|
|
//# sourceMappingURL=focus-trap.js.map
|