intersection-observer 0.4.3 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -4,6 +4,7 @@ This library polyfills the native [`IntersectionObserver`](http://w3c.github.io/
4
4
 
5
5
  - [Installation](#installation)
6
6
  - [Configuring the polyfill](#configuring-the-polyfill)
7
+ - [Limitations](#limitations)
7
8
  - [Browser support](#browser-support)
8
9
  - [Running the tests](#running-the-tests)
9
10
 
@@ -81,6 +82,26 @@ io.observe(someTargetElement);
81
82
 
82
83
  **Note:** the `POLL_INTERVAL` property must be set prior to calling the `.observe` method, or the default configuration will be used.
83
84
 
85
+ **Ignoring DOM changes**
86
+
87
+ 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)
88
+
89
+ ```js
90
+ IntersectionObserver.prototype.USE_MUTATION_OBSERVER = false; // Globally
91
+
92
+ // for an instance
93
+ var io = new IntersectionObserver(callback);
94
+ io.USE_MUTATION_OBSERVER = false;
95
+ ```
96
+
97
+ 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.
98
+
99
+ ## Limitations
100
+
101
+ This polyfill does not attempt to report intersections across same-origin `iframe` boundaries. While supporting same-origin iframes is technically possible, it would drastically reduce performance. Since most `iframe` usage on the web is cross-origin, this polyfill chooses to optimize for performantly handling the most common use cases. (Note: neither this polyfill nor native implementations support reporting intersections across cross-origin `iframe` boundaries.)
102
+
103
+ This polyfill also does not support the [proposed v2 additions](https://github.com/szager-chromium/IntersectionObserver/blob/v2/explainer.md), as these features are not currently possible to do with JavaScript and existing web APIs.
104
+
84
105
  ## Browser support
85
106
 
86
107
  The polyfill has been tested and known to work in the latest version of all browsers.
@@ -724,6 +724,30 @@ describe('IntersectionObserver', function() {
724
724
 
725
725
  io.observe(targetEl1);
726
726
  });
727
+
728
+ it('handles roots in shadow DOM', function(done) {
729
+ var shadowRoot = grandParentEl.attachShadow({mode: 'open'});
730
+
731
+ shadowRoot.innerHTML =
732
+ '<style>' +
733
+ '#slot-parent {' +
734
+ ' position: relative;' +
735
+ ' width: 400px;' +
736
+ ' height: 200px;' +
737
+ '}' +
738
+ '</style>' +
739
+ '<div id="slot-parent"><slot></slot></div>';
740
+
741
+ var slotParent = shadowRoot.getElementById('slot-parent');
742
+
743
+ io = new IntersectionObserver(function(records) {
744
+ expect(records.length).to.be(1);
745
+ expect(records[0].intersectionRatio).to.be(1);
746
+ done();
747
+ }, {root: slotParent});
748
+
749
+ io.observe(targetEl1);
750
+ });
727
751
  }
728
752
 
729
753
 
@@ -4,14 +4,17 @@
4
4
  * Licensed under the W3C SOFTWARE AND DOCUMENT NOTICE AND LICENSE.
5
5
  *
6
6
  * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
7
- *
7
+ *
8
8
  */
9
-
10
- (function(window, document) {
9
+ (function() {
11
10
  'use strict';
12
11
 
12
+ // Exit early if we're not running in a browser.
13
+ if (typeof window !== 'object') {
14
+ return;
15
+ }
13
16
 
14
- // Exits early if all IntersectionObserver and IntersectionObserverEntry
17
+ // Exit early if all IntersectionObserver and IntersectionObserverEntry
15
18
  // features are natively supported.
16
19
  if ('IntersectionObserver' in window &&
17
20
  'IntersectionObserverEntry' in window &&
@@ -31,9 +34,15 @@ if ('IntersectionObserver' in window &&
31
34
  }
32
35
 
33
36
 
37
+ /**
38
+ * A local reference to the document.
39
+ */
40
+ var document = window.document;
41
+
42
+
34
43
  /**
35
44
  * An IntersectionObserver registry. This registry exists to hold a strong
36
- * reference to IntersectionObserver instances currently observering a target
45
+ * reference to IntersectionObserver instances currently observing a target
37
46
  * element. Without this registry, instances without another reference may be
38
47
  * garbage collected.
39
48
  */
@@ -62,7 +71,9 @@ function IntersectionObserverEntry(entry) {
62
71
 
63
72
  // Sets intersection ratio.
64
73
  if (targetArea) {
65
- this.intersectionRatio = intersectionArea / targetArea;
74
+ // Round the intersection ratio to avoid floating point math issues:
75
+ // https://github.com/w3c/IntersectionObserver/issues/324
76
+ this.intersectionRatio = Number((intersectionArea / targetArea).toFixed(4));
66
77
  } else {
67
78
  // If area is zero and is intersecting, sets to 1, otherwise to 0
68
79
  this.intersectionRatio = this.isIntersecting ? 1 : 0;
@@ -124,6 +135,12 @@ IntersectionObserver.prototype.THROTTLE_TIMEOUT = 100;
124
135
  */
125
136
  IntersectionObserver.prototype.POLL_INTERVAL = null;
126
137
 
138
+ /**
139
+ * Use a mutation observer on the root element
140
+ * to detect intersection changes.
141
+ */
142
+ IntersectionObserver.prototype.USE_MUTATION_OBSERVER = true;
143
+
127
144
 
128
145
  /**
129
146
  * Starts observing a target element for intersection changes based on
@@ -131,10 +148,11 @@ IntersectionObserver.prototype.POLL_INTERVAL = null;
131
148
  * @param {Element} target The DOM element to observe.
132
149
  */
133
150
  IntersectionObserver.prototype.observe = function(target) {
134
- // If the target is already being observed, do nothing.
135
- if (this._observationTargets.some(function(item) {
151
+ var isTargetAlreadyObserved = this._observationTargets.some(function(item) {
136
152
  return item.element == target;
137
- })) {
153
+ });
154
+
155
+ if (isTargetAlreadyObserved) {
138
156
  return;
139
157
  }
140
158
 
@@ -243,7 +261,7 @@ IntersectionObserver.prototype._parseRootMargin = function(opt_rootMargin) {
243
261
 
244
262
  /**
245
263
  * Starts polling for intersection changes if the polling is not already
246
- * happening, and if the page's visibilty state is visible.
264
+ * happening, and if the page's visibility state is visible.
247
265
  * @private
248
266
  */
249
267
  IntersectionObserver.prototype._monitorIntersections = function() {
@@ -260,7 +278,7 @@ IntersectionObserver.prototype._monitorIntersections = function() {
260
278
  addEvent(window, 'resize', this._checkForIntersections, true);
261
279
  addEvent(document, 'scroll', this._checkForIntersections, true);
262
280
 
263
- if ('MutationObserver' in window) {
281
+ if (this.USE_MUTATION_OBSERVER && 'MutationObserver' in window) {
264
282
  this._domObserver = new MutationObserver(this._checkForIntersections);
265
283
  this._domObserver.observe(document, {
266
284
  attributes: true,
@@ -545,7 +563,7 @@ function now() {
545
563
 
546
564
 
547
565
  /**
548
- * Throttles a function and delays its executiong, so it's only called at most
566
+ * Throttles a function and delays its execution, so it's only called at most
549
567
  * once within a given time period.
550
568
  * @param {Function} fn The function to throttle.
551
569
  * @param {number} timeout The amount of time that must pass before the
@@ -676,7 +694,7 @@ function getEmptyRect() {
676
694
  }
677
695
 
678
696
  /**
679
- * Checks to see if a parent element contains a child elemnt (including inside
697
+ * Checks to see if a parent element contains a child element (including inside
680
698
  * shadow DOM).
681
699
  * @param {Node} parent The parent element.
682
700
  * @param {Node} child The child element.
@@ -706,6 +724,12 @@ function getParentNode(node) {
706
724
  // If the parent is a shadow root, return the host element.
707
725
  return parent.host;
708
726
  }
727
+
728
+ if (parent && parent.assignedSlot) {
729
+ // If the parent is distributed in a <slot>, return the parent of a slot.
730
+ return parent.assignedSlot.parentNode;
731
+ }
732
+
709
733
  return parent;
710
734
  }
711
735
 
@@ -714,4 +738,4 @@ function getParentNode(node) {
714
738
  window.IntersectionObserver = IntersectionObserver;
715
739
  window.IntersectionObserverEntry = IntersectionObserverEntry;
716
740
 
717
- }(window, document));
741
+ }());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "intersection-observer",
3
- "version": "0.4.3",
3
+ "version": "0.7.0",
4
4
  "description": "A polyfill for IntersectionObserver",
5
5
  "main": "intersection-observer",
6
6
  "repository": {