intersection-observer 0.4.3 → 0.7.0

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 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": {