-
Notifications
You must be signed in to change notification settings - Fork 284
Expand file tree
/
Copy pathisElementVisible.ts
More file actions
66 lines (57 loc) · 1.71 KB
/
isElementVisible.ts
File metadata and controls
66 lines (57 loc) · 1.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/*!
* isElementVisible
* Adapted from https://github.com/testing-library/jest-dom
* Licensed under the MIT License.
*/
function isStyleVisible<T extends Element>(element: T) {
if (!(element instanceof HTMLElement) && !(element instanceof SVGElement)) {
return false
}
const { display, visibility, opacity } = getComputedStyle(element)
return (
display !== 'none' &&
visibility !== 'hidden' &&
visibility !== 'collapse' &&
opacity !== '0'
)
}
/**
* checks if an element is visible by checking its hidden attribute and parent visibility.
* @param element
* @returns boolean
*/
function isElementVisibleByAttribute<T extends Element>(element: T) {
if (element instanceof HTMLElement && element.hidden) {
return false
}
return true
}
/**
* checks if an element is hidden by a closed details element.
* @param element
* @returns boolean
*/
function isHiddenByClosedDetails<T extends Element>(element: T) {
const summary = element.closest('summary')
let parent = element.parentElement
while (parent) {
if (parent.nodeName === 'DETAILS' && !(parent as HTMLDetailsElement).open) {
// If no <summary> ancestor exists, or the <summary> is not a direct child of this <details>,
// then the content is hidden
if (!summary || summary.parentElement !== parent) {
return true
}
}
parent = parent.parentElement
}
return false
}
export function isElementVisible<T extends Element>(element: T): boolean {
return (
element.nodeName !== '#comment' &&
isStyleVisible(element) &&
isElementVisibleByAttribute(element) &&
!isHiddenByClosedDetails(element) &&
(!element.parentElement || isElementVisible(element.parentElement))
)
}