UNPKG

5.01 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.default = isElementDisplayed;
7
8function isElementDisplayed(element) {
9 function nodeIsElement(node) {
10 if (!node) {
11 return false;
12 }
13
14 switch (node.nodeType) {
15 case Node.ELEMENT_NODE:
16 case Node.DOCUMENT_NODE:
17 case Node.DOCUMENT_FRAGMENT_NODE:
18 return true;
19
20 default:
21 return false;
22 }
23 }
24
25 function parentElementForElement(element) {
26 if (!element) {
27 return null;
28 }
29
30 return enclosingNodeOrSelfMatchingPredicate(element.parentNode, nodeIsElement);
31 }
32
33 function enclosingNodeOrSelfMatchingPredicate(targetNode, predicate) {
34 for (let node = targetNode; node && node !== targetNode.ownerDocument; node = node.parentNode) if (predicate(node)) {
35 return node;
36 }
37
38 return null;
39 }
40
41 function enclosingElementOrSelfMatchingPredicate(targetElement, predicate) {
42 for (let element = targetElement; element && element !== targetElement.ownerDocument; element = parentElementForElement(element)) if (predicate(element)) {
43 return element;
44 }
45
46 return null;
47 }
48
49 function cascadedStylePropertyForElement(element, property) {
50 if (!element || !property) {
51 return null;
52 }
53
54 if (element instanceof DocumentFragment) {
55 element = element.host;
56 }
57
58 let computedStyle = window.getComputedStyle(element);
59 let computedStyleProperty = computedStyle.getPropertyValue(property);
60
61 if (computedStyleProperty && computedStyleProperty !== 'inherit') {
62 return computedStyleProperty;
63 }
64
65 let parentElement = parentElementForElement(element);
66 return cascadedStylePropertyForElement(parentElement, property);
67 }
68
69 function elementSubtreeHasNonZeroDimensions(element) {
70 let boundingBox = element.getBoundingClientRect();
71
72 if (boundingBox.width > 0 && boundingBox.height > 0) {
73 return true;
74 }
75
76 if (element.tagName.toUpperCase() === 'PATH' && boundingBox.width + boundingBox.height > 0) {
77 let strokeWidth = cascadedStylePropertyForElement(element, 'stroke-width');
78 return !!strokeWidth && parseInt(strokeWidth, 10) > 0;
79 }
80
81 let cascadedOverflow = cascadedStylePropertyForElement(element, 'overflow');
82
83 if (cascadedOverflow === 'hidden') {
84 return false;
85 }
86
87 return Array.from(element.childNodes).some(childNode => {
88 if (childNode.nodeType === Node.TEXT_NODE) {
89 return true;
90 }
91
92 if (nodeIsElement(childNode)) {
93 return elementSubtreeHasNonZeroDimensions(childNode);
94 }
95
96 return false;
97 });
98 }
99
100 function elementOverflowsContainer(element) {
101 let cascadedOverflow = cascadedStylePropertyForElement(element, 'overflow');
102
103 if (cascadedOverflow !== 'hidden') {
104 return false;
105 }
106
107 return true;
108 }
109
110 function isElementSubtreeHiddenByOverflow(element) {
111 if (!element) {
112 return false;
113 }
114
115 if (!elementOverflowsContainer(element)) {
116 return false;
117 }
118
119 if (!element.childNodes.length) {
120 return false;
121 }
122
123 return Array.from(element.childNodes).every(childNode => {
124 if (childNode.nodeType === Node.TEXT_NODE) {
125 return false;
126 }
127
128 if (!nodeIsElement(childNode)) {
129 return true;
130 }
131
132 if (!elementSubtreeHasNonZeroDimensions(childNode)) {
133 return true;
134 }
135
136 return isElementSubtreeHiddenByOverflow(childNode);
137 });
138 }
139
140 function isElementInsideShadowRoot(element) {
141 if (!element) {
142 return false;
143 }
144
145 if (element.parentNode && element.parentNode.host) {
146 return true;
147 }
148
149 return isElementInsideShadowRoot(element.parentNode);
150 }
151
152 if (!isElementInsideShadowRoot(element) && !document.contains(element)) {
153 return false;
154 }
155
156 switch (element.tagName.toUpperCase()) {
157 case 'BODY':
158 return true;
159
160 case 'SCRIPT':
161 case 'NOSCRIPT':
162 return false;
163
164 case 'OPTGROUP':
165 case 'OPTION':
166 {
167 let enclosingSelectElement = enclosingNodeOrSelfMatchingPredicate(element, e => e.tagName.toUpperCase() === 'SELECT');
168 return isElementDisplayed(enclosingSelectElement);
169 }
170
171 case 'INPUT':
172 if (element.type === 'hidden') {
173 return false;
174 }
175
176 break;
177
178 default:
179 break;
180 }
181
182 if (cascadedStylePropertyForElement(element, 'visibility') !== 'visible') {
183 return false;
184 }
185
186 let hasAncestorWithZeroOpacity = !!enclosingElementOrSelfMatchingPredicate(element, e => {
187 return Number(cascadedStylePropertyForElement(e, 'opacity')) === 0;
188 });
189 let hasAncestorWithDisplayNone = !!enclosingElementOrSelfMatchingPredicate(element, e => {
190 return cascadedStylePropertyForElement(e, 'display') === 'none';
191 });
192
193 if (hasAncestorWithZeroOpacity || hasAncestorWithDisplayNone) {
194 return false;
195 }
196
197 if (!elementSubtreeHasNonZeroDimensions(element)) {
198 return false;
199 }
200
201 if (isElementSubtreeHiddenByOverflow(element)) {
202 return false;
203 }
204
205 return true;
206}
\No newline at end of file