intersection-observer 0.4.1 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -2
- package/border-test.html +47 -0
- package/frame1.html +9 -0
- package/frame2.html +9 -0
- package/frames.html +33 -0
- package/intersection-observer-test.html +3 -11
- package/intersection-observer-test.js +20 -13
- package/intersection-observer.js +26 -25
- package/package.json +4 -4
- package/slot.html +93 -0
- package/.npmignore +0 -3
package/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# `IntersectionObserver` polyfill
|
2
2
|
|
3
|
-
This library polyfills the native [`IntersectionObserver`](http://
|
3
|
+
This library polyfills the native [`IntersectionObserver`](http://w3c.github.io/IntersectionObserver/) API in unsupporting browsers. See the [API documentation](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) for usage information.
|
4
4
|
|
5
5
|
- [Installation](#installation)
|
6
6
|
- [Configuring the polyfill](#configuring-the-polyfill)
|
@@ -9,7 +9,7 @@ This library polyfills the native [`IntersectionObserver`](http://wicg.github.io
|
|
9
9
|
|
10
10
|
## Installation
|
11
11
|
|
12
|
-
You can install the polyfill via npm or by downloading a [zip](https://github.com/
|
12
|
+
You can install the polyfill via npm or by downloading a [zip](https://github.com/w3c/IntersectionObserver/archive/gh-pages.zip) of this repository:
|
13
13
|
|
14
14
|
```sh
|
15
15
|
npm install intersection-observer
|
@@ -81,6 +81,20 @@ io.observe(someTargetElement);
|
|
81
81
|
|
82
82
|
**Note:** the `POLL_INTERVAL` property must be set prior to calling the `.observe` method, or the default configuration will be used.
|
83
83
|
|
84
|
+
**Ignoring DOM changes**
|
85
|
+
|
86
|
+
You can also choose to not check for intersections when the DOM changes by setting an observer's `USE_MUTATION_OBSERVER` property to `false` (either globally on the prototype or per-instance)
|
87
|
+
|
88
|
+
```js
|
89
|
+
IntersectionObserver.prototype.USE_MUTATION_OBSERVER = false; // Globally
|
90
|
+
|
91
|
+
// for an instance
|
92
|
+
var io = new IntersectionObserver(callback);
|
93
|
+
io.USE_MUTATION_OBSERVER = false;
|
94
|
+
```
|
95
|
+
|
96
|
+
This is recommended in cases where the DOM will update frequently but you know those updates will have no affect on the position or your target elements.
|
97
|
+
|
84
98
|
## Browser support
|
85
99
|
|
86
100
|
The polyfill has been tested and known to work in the latest version of all browsers.
|
package/border-test.html
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<script>
|
6
|
+
// delete window.IntersectionObserver;
|
7
|
+
</script>
|
8
|
+
<script src="intersection-observer.js"></script>
|
9
|
+
<script>
|
10
|
+
function init() {
|
11
|
+
function callback(entries, observer) {
|
12
|
+
Array.prototype.forEach.call(entries, function(entry) {
|
13
|
+
if (entry.intersectionRatio > 0) {
|
14
|
+
entry.target.classList.add('visible');
|
15
|
+
}
|
16
|
+
});
|
17
|
+
}
|
18
|
+
var observer = new IntersectionObserver(callback, { root: document.getElementById('outer') });
|
19
|
+
Array.prototype.forEach.call(document.querySelectorAll('#outer div'), function(el) {
|
20
|
+
observer.observe(el);
|
21
|
+
});
|
22
|
+
}
|
23
|
+
window.addEventListener('load', init);
|
24
|
+
</script>
|
25
|
+
<style>
|
26
|
+
#outer {
|
27
|
+
overflow-y: hidden;
|
28
|
+
height: 2em;
|
29
|
+
border: 10px solid #0000;
|
30
|
+
}
|
31
|
+
#outer div {
|
32
|
+
height: 100%;
|
33
|
+
}
|
34
|
+
#el2 {
|
35
|
+
background: red;
|
36
|
+
}
|
37
|
+
|
38
|
+
</style>
|
39
|
+
</head>
|
40
|
+
<body>
|
41
|
+
<div id="outer">
|
42
|
+
<div id="el1">Element 1</div>
|
43
|
+
<div id="el2">Element 2</div>
|
44
|
+
<div id="el3">Element 3</div>
|
45
|
+
</div>
|
46
|
+
</body>
|
47
|
+
</html>
|
package/frame1.html
ADDED
package/frame2.html
ADDED
package/frames.html
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
<!--
|
2
|
+
Copyright 2016 Google Inc. All Rights Reserved.
|
3
|
+
|
4
|
+
Licensed under the W3C SOFTWARE AND DOCUMENT NOTICE AND LICENSE.
|
5
|
+
|
6
|
+
https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
|
7
|
+
-->
|
8
|
+
<!DOCTYPE html>
|
9
|
+
<html lang="en">
|
10
|
+
<head>
|
11
|
+
<meta charset="utf-8">
|
12
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
13
|
+
<title>IntersectionObserver Tests</title>
|
14
|
+
|
15
|
+
<!-- Dependencies -->
|
16
|
+
<!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.5.3/mocha.min.css">
|
17
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.5.3/mocha.min.js"></script>
|
18
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/expect.js/0.2.0/expect.min.js"></script>
|
19
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/sinon.js/3.2.1/sinon.min.js"></script>
|
20
|
+
|
21
|
+
-->
|
22
|
+
|
23
|
+
<styles>
|
24
|
+
|
25
|
+
</styles>
|
26
|
+
</head>
|
27
|
+
<body>
|
28
|
+
|
29
|
+
<iframe src="frame1.html"></iframe>
|
30
|
+
<iframe src="frame2.html"></iframe>
|
31
|
+
|
32
|
+
</body>
|
33
|
+
</html>
|
@@ -1,17 +1,9 @@
|
|
1
1
|
<!--
|
2
2
|
Copyright 2016 Google Inc. All Rights Reserved.
|
3
3
|
|
4
|
-
Licensed under the
|
5
|
-
you may not use this file except in compliance with the License.
|
6
|
-
You may obtain a copy of the License at
|
4
|
+
Licensed under the W3C SOFTWARE AND DOCUMENT NOTICE AND LICENSE.
|
7
5
|
|
8
|
-
|
9
|
-
|
10
|
-
Unless required by applicable law or agreed to in writing, software
|
11
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
-
See the License for the specific language governing permissions and
|
14
|
-
limitations under the License.
|
6
|
+
https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
|
15
7
|
-->
|
16
8
|
<!DOCTYPE html>
|
17
9
|
<html lang="en">
|
@@ -24,7 +16,7 @@ limitations under the License.
|
|
24
16
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.5.3/mocha.min.css">
|
25
17
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.5.3/mocha.min.js"></script>
|
26
18
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/expect.js/0.2.0/expect.min.js"></script>
|
27
|
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/sinon.js/
|
19
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/sinon.js/3.2.1/sinon.min.js"></script>
|
28
20
|
|
29
21
|
<!-- Polyfills for IE7-8 -->
|
30
22
|
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=es5,getComputedStyle"></script>
|
@@ -1,17 +1,10 @@
|
|
1
1
|
/**
|
2
2
|
* Copyright 2016 Google Inc. All Rights Reserved.
|
3
3
|
*
|
4
|
-
* Licensed under the
|
5
|
-
* you may not use this file except in compliance with the License.
|
6
|
-
* You may obtain a copy of the License at
|
4
|
+
* Licensed under the W3C SOFTWARE AND DOCUMENT NOTICE AND LICENSE.
|
7
5
|
*
|
8
|
-
*
|
6
|
+
* https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
|
9
7
|
*
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
-
* See the License for the specific language governing permissions and
|
14
|
-
* limitations under the License.
|
15
8
|
*/
|
16
9
|
|
17
10
|
|
@@ -142,14 +135,14 @@ describe('IntersectionObserver', function() {
|
|
142
135
|
it('throws when a threshold is not a number', function() {
|
143
136
|
expect(function() {
|
144
137
|
io = new IntersectionObserver(noop, {threshold: ['foo']});
|
145
|
-
}).to.throwException(
|
138
|
+
}).to.throwException();
|
146
139
|
});
|
147
140
|
|
148
141
|
|
149
142
|
it('throws when a threshold value is not between 0 and 1', function() {
|
150
143
|
expect(function() {
|
151
144
|
io = new IntersectionObserver(noop, {threshold: [0, -1]});
|
152
|
-
}).to.throwException(
|
145
|
+
}).to.throwException();
|
153
146
|
});
|
154
147
|
|
155
148
|
});
|
@@ -161,7 +154,7 @@ describe('IntersectionObserver', function() {
|
|
161
154
|
expect(function() {
|
162
155
|
io = new IntersectionObserver(noop);
|
163
156
|
io.observe(null);
|
164
|
-
}).to.throwException(
|
157
|
+
}).to.throwException();
|
165
158
|
});
|
166
159
|
|
167
160
|
|
@@ -178,6 +171,20 @@ describe('IntersectionObserver', function() {
|
|
178
171
|
io.observe(targetEl2);
|
179
172
|
});
|
180
173
|
|
174
|
+
it('triggers for existing targets when observing begins after monitoring has begun', function(done) {
|
175
|
+
var spy = sinon.spy();
|
176
|
+
io = new IntersectionObserver(spy, {root: rootEl});
|
177
|
+
|
178
|
+
io.observe(targetEl1);
|
179
|
+
setTimeout(function() {
|
180
|
+
io.observe(targetEl2);
|
181
|
+
setTimeout(function() {
|
182
|
+
expect(spy.callCount).to.be(2);
|
183
|
+
done();
|
184
|
+
}, ASYNC_TIMEOUT);
|
185
|
+
}, ASYNC_TIMEOUT);
|
186
|
+
});
|
187
|
+
|
181
188
|
|
182
189
|
it('triggers with the correct arguments', function(done) {
|
183
190
|
io = new IntersectionObserver(function(records, observer) {
|
@@ -632,7 +639,7 @@ describe('IntersectionObserver', function() {
|
|
632
639
|
|
633
640
|
// targetEl5 is initially not in the DOM. Note that this element must be
|
634
641
|
// created outside of the addFixtures() function to catch the IE11 error
|
635
|
-
// described here: https://github.com/
|
642
|
+
// described here: https://github.com/w3c/IntersectionObserver/pull/205
|
636
643
|
var targetEl5 = document.createElement('div');
|
637
644
|
targetEl5.setAttribute('id', 'target5');
|
638
645
|
|
package/intersection-observer.js
CHANGED
@@ -1,17 +1,10 @@
|
|
1
1
|
/**
|
2
2
|
* Copyright 2016 Google Inc. All Rights Reserved.
|
3
3
|
*
|
4
|
-
* Licensed under the
|
5
|
-
* you may not use this file except in compliance with the License.
|
6
|
-
* You may obtain a copy of the License at
|
4
|
+
* Licensed under the W3C SOFTWARE AND DOCUMENT NOTICE AND LICENSE.
|
7
5
|
*
|
8
|
-
*
|
6
|
+
* https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
|
9
7
|
*
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
-
* See the License for the specific language governing permissions and
|
14
|
-
* limitations under the License.
|
15
8
|
*/
|
16
9
|
|
17
10
|
(function(window, document) {
|
@@ -25,7 +18,7 @@ if ('IntersectionObserver' in window &&
|
|
25
18
|
'intersectionRatio' in window.IntersectionObserverEntry.prototype) {
|
26
19
|
|
27
20
|
// Minimal polyfill for Edge 15's lack of `isIntersecting`
|
28
|
-
// See: https://github.com/
|
21
|
+
// See: https://github.com/w3c/IntersectionObserver/issues/211
|
29
22
|
if (!('isIntersecting' in window.IntersectionObserverEntry.prototype)) {
|
30
23
|
Object.defineProperty(window.IntersectionObserverEntry.prototype,
|
31
24
|
'isIntersecting', {
|
@@ -40,7 +33,7 @@ if ('IntersectionObserver' in window &&
|
|
40
33
|
|
41
34
|
/**
|
42
35
|
* An IntersectionObserver registry. This registry exists to hold a strong
|
43
|
-
* reference to IntersectionObserver instances currently
|
36
|
+
* reference to IntersectionObserver instances currently observing a target
|
44
37
|
* element. Without this registry, instances without another reference may be
|
45
38
|
* garbage collected.
|
46
39
|
*/
|
@@ -49,7 +42,7 @@ var registry = [];
|
|
49
42
|
|
50
43
|
/**
|
51
44
|
* Creates the global IntersectionObserverEntry constructor.
|
52
|
-
* https://
|
45
|
+
* https://w3c.github.io/IntersectionObserver/#intersection-observer-entry
|
53
46
|
* @param {Object} entry A dictionary of instance properties.
|
54
47
|
* @constructor
|
55
48
|
*/
|
@@ -69,7 +62,9 @@ function IntersectionObserverEntry(entry) {
|
|
69
62
|
|
70
63
|
// Sets intersection ratio.
|
71
64
|
if (targetArea) {
|
72
|
-
|
65
|
+
// Round the intersection ratio to avoid floating point math issues:
|
66
|
+
// https://github.com/w3c/IntersectionObserver/issues/324
|
67
|
+
this.intersectionRatio = Number((intersectionArea / targetArea).toFixed(4));
|
73
68
|
} else {
|
74
69
|
// If area is zero and is intersecting, sets to 1, otherwise to 0
|
75
70
|
this.intersectionRatio = this.isIntersecting ? 1 : 0;
|
@@ -79,7 +74,7 @@ function IntersectionObserverEntry(entry) {
|
|
79
74
|
|
80
75
|
/**
|
81
76
|
* Creates the global IntersectionObserver constructor.
|
82
|
-
* https://
|
77
|
+
* https://w3c.github.io/IntersectionObserver/#intersection-observer-interface
|
83
78
|
* @param {Function} callback The function to be invoked after intersection
|
84
79
|
* changes have queued. The function is not invoked if the queue has
|
85
80
|
* been emptied by calling the `takeRecords` method.
|
@@ -131,6 +126,12 @@ IntersectionObserver.prototype.THROTTLE_TIMEOUT = 100;
|
|
131
126
|
*/
|
132
127
|
IntersectionObserver.prototype.POLL_INTERVAL = null;
|
133
128
|
|
129
|
+
/**
|
130
|
+
* Use a mutation observer on the root element
|
131
|
+
* to detect intersection changes.
|
132
|
+
*/
|
133
|
+
IntersectionObserver.prototype.USE_MUTATION_OBSERVER = true;
|
134
|
+
|
134
135
|
|
135
136
|
/**
|
136
137
|
* Starts observing a target element for intersection changes based on
|
@@ -138,10 +139,11 @@ IntersectionObserver.prototype.POLL_INTERVAL = null;
|
|
138
139
|
* @param {Element} target The DOM element to observe.
|
139
140
|
*/
|
140
141
|
IntersectionObserver.prototype.observe = function(target) {
|
141
|
-
|
142
|
-
if (this._observationTargets.some(function(item) {
|
142
|
+
var isTargetAlreadyObserved = this._observationTargets.some(function(item) {
|
143
143
|
return item.element == target;
|
144
|
-
})
|
144
|
+
});
|
145
|
+
|
146
|
+
if (isTargetAlreadyObserved) {
|
145
147
|
return;
|
146
148
|
}
|
147
149
|
|
@@ -152,6 +154,7 @@ IntersectionObserver.prototype.observe = function(target) {
|
|
152
154
|
this._registerInstance();
|
153
155
|
this._observationTargets.push({element: target, entry: null});
|
154
156
|
this._monitorIntersections();
|
157
|
+
this._checkForIntersections();
|
155
158
|
};
|
156
159
|
|
157
160
|
|
@@ -249,15 +252,13 @@ IntersectionObserver.prototype._parseRootMargin = function(opt_rootMargin) {
|
|
249
252
|
|
250
253
|
/**
|
251
254
|
* Starts polling for intersection changes if the polling is not already
|
252
|
-
* happening, and if the page's
|
255
|
+
* happening, and if the page's visibility state is visible.
|
253
256
|
* @private
|
254
257
|
*/
|
255
258
|
IntersectionObserver.prototype._monitorIntersections = function() {
|
256
259
|
if (!this._monitoringIntersections) {
|
257
260
|
this._monitoringIntersections = true;
|
258
261
|
|
259
|
-
this._checkForIntersections();
|
260
|
-
|
261
262
|
// If a poll interval is set, use polling instead of listening to
|
262
263
|
// resize and scroll events or DOM mutations.
|
263
264
|
if (this.POLL_INTERVAL) {
|
@@ -268,7 +269,7 @@ IntersectionObserver.prototype._monitorIntersections = function() {
|
|
268
269
|
addEvent(window, 'resize', this._checkForIntersections, true);
|
269
270
|
addEvent(document, 'scroll', this._checkForIntersections, true);
|
270
271
|
|
271
|
-
if ('MutationObserver' in window) {
|
272
|
+
if (this.USE_MUTATION_OBSERVER && 'MutationObserver' in window) {
|
272
273
|
this._domObserver = new MutationObserver(this._checkForIntersections);
|
273
274
|
this._domObserver.observe(document, {
|
274
275
|
attributes: true,
|
@@ -358,7 +359,7 @@ IntersectionObserver.prototype._checkForIntersections = function() {
|
|
358
359
|
* Accepts a target and root rect computes the intersection between then
|
359
360
|
* following the algorithm in the spec.
|
360
361
|
* TODO(philipwalton): at this time clip-path is not considered.
|
361
|
-
* https://
|
362
|
+
* https://w3c.github.io/IntersectionObserver/#calculate-intersection-rect-algo
|
362
363
|
* @param {Element} target The target DOM element
|
363
364
|
* @param {Object} rootRect The bounding rect of the root after being
|
364
365
|
* expanded by the rootMargin value.
|
@@ -553,7 +554,7 @@ function now() {
|
|
553
554
|
|
554
555
|
|
555
556
|
/**
|
556
|
-
* Throttles a function and delays its
|
557
|
+
* Throttles a function and delays its execution, so it's only called at most
|
557
558
|
* once within a given time period.
|
558
559
|
* @param {Function} fn The function to throttle.
|
559
560
|
* @param {number} timeout The amount of time that must pass before the
|
@@ -647,7 +648,7 @@ function getBoundingClientRect(el) {
|
|
647
648
|
rect = el.getBoundingClientRect();
|
648
649
|
} catch (err) {
|
649
650
|
// Ignore Windows 7 IE11 "Unspecified error"
|
650
|
-
// https://github.com/
|
651
|
+
// https://github.com/w3c/IntersectionObserver/pull/205
|
651
652
|
}
|
652
653
|
|
653
654
|
if (!rect) return getEmptyRect();
|
@@ -684,7 +685,7 @@ function getEmptyRect() {
|
|
684
685
|
}
|
685
686
|
|
686
687
|
/**
|
687
|
-
* Checks to see if a parent element contains a child
|
688
|
+
* Checks to see if a parent element contains a child element (including inside
|
688
689
|
* shadow DOM).
|
689
690
|
* @param {Node} parent The parent element.
|
690
691
|
* @param {Node} child The child element.
|
package/package.json
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
{
|
2
2
|
"name": "intersection-observer",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.5.1",
|
4
4
|
"description": "A polyfill for IntersectionObserver",
|
5
5
|
"main": "intersection-observer",
|
6
6
|
"repository": {
|
7
7
|
"type": "git",
|
8
|
-
"url": "git@github.com:
|
8
|
+
"url": "git@github.com:w3c/IntersectionObserver.git"
|
9
9
|
},
|
10
10
|
"keywords": [
|
11
11
|
"Intersection",
|
@@ -16,8 +16,8 @@
|
|
16
16
|
"email": "philip@philipwalton.com",
|
17
17
|
"url": "http://philipwalton.com"
|
18
18
|
},
|
19
|
-
"license": "
|
19
|
+
"license": "W3C-20150513",
|
20
20
|
"bugs": {
|
21
|
-
"url": "https://github.com/
|
21
|
+
"url": "https://github.com/w3c/IntersectionObserver/issues"
|
22
22
|
}
|
23
23
|
}
|
package/slot.html
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
<template id="slot-test">
|
2
|
+
<style>
|
3
|
+
|
4
|
+
</style>
|
5
|
+
<div>
|
6
|
+
<h3>Title</h3>
|
7
|
+
<aside>
|
8
|
+
<slot name="contents"></slot>
|
9
|
+
</aside>
|
10
|
+
</div>
|
11
|
+
</template>
|
12
|
+
|
13
|
+
|
14
|
+
<my-el>
|
15
|
+
<ul slot="contents">
|
16
|
+
<li>one</li>
|
17
|
+
<li>two</li>
|
18
|
+
<li>three</li>
|
19
|
+
</ul>
|
20
|
+
<ul slot="contents">
|
21
|
+
<li>four</li>
|
22
|
+
<li>five</li>
|
23
|
+
<li>six</li>
|
24
|
+
</ul>
|
25
|
+
</my-el>
|
26
|
+
|
27
|
+
|
28
|
+
<script>
|
29
|
+
class MyEl extends HTMLElement {
|
30
|
+
constructor() {
|
31
|
+
super();
|
32
|
+
|
33
|
+
const shadowRoot = this.attachShadow({mode: 'open'});
|
34
|
+
shadowRoot.innerHTML = `
|
35
|
+
<style>
|
36
|
+
|
37
|
+
</style>
|
38
|
+
<div>
|
39
|
+
<h3>Title</h3>
|
40
|
+
<aside>
|
41
|
+
<slot name="contents"></slot>
|
42
|
+
</aside>
|
43
|
+
</div>
|
44
|
+
`;
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
self.customElements.define('my-el', MyEl);
|
49
|
+
|
50
|
+
|
51
|
+
/**
|
52
|
+
* Checks to see if a parent element contains a child elemnt (including inside
|
53
|
+
* shadow DOM).
|
54
|
+
* @param {Node} parent The parent element.
|
55
|
+
* @param {Node} child The child element.
|
56
|
+
* @return {boolean} True if the parent node contains the child node.
|
57
|
+
*/
|
58
|
+
function containsDeep(parent, child) {
|
59
|
+
var node = child;
|
60
|
+
while (node) {
|
61
|
+
if (node == parent) return true;
|
62
|
+
|
63
|
+
node = getParentNode(node);
|
64
|
+
}
|
65
|
+
return false;
|
66
|
+
}
|
67
|
+
|
68
|
+
|
69
|
+
/**
|
70
|
+
* Gets the parent node of an element or its host element if the parent node
|
71
|
+
* is a shadow root.
|
72
|
+
* @param {Node} node The node whose parent to get.
|
73
|
+
* @return {Node|null} The parent node or null if no parent exists.
|
74
|
+
*/
|
75
|
+
function getParentNode(node) {
|
76
|
+
var parent = node.parentNode;
|
77
|
+
|
78
|
+
if (parent) {
|
79
|
+
if (parent.nodeType == 11 && parent.host) {
|
80
|
+
// If the parent is a shadow root, return the host element.
|
81
|
+
return parent.host;
|
82
|
+
}
|
83
|
+
|
84
|
+
if (parent.assignedSlot) {
|
85
|
+
// If the parent is assigned a slot, return the slot's parent.
|
86
|
+
return parent.assignedSlot.parentNode;
|
87
|
+
}
|
88
|
+
}
|
89
|
+
return parent;
|
90
|
+
}
|
91
|
+
|
92
|
+
|
93
|
+
</script>
|
package/.npmignore
DELETED