intersection-observer
Advanced tools
Comparing version 0.8.0 to 0.9.0
@@ -51,4 +51,17 @@ /** | ||
/** | ||
* The signal updater for cross-origin intersection. When not null, it means | ||
* that the polyfill is configured to work in a cross-origin mode. | ||
* @type {function(DOMRect, DOMRect)} | ||
*/ | ||
var crossOriginUpdater = null; | ||
/** | ||
* The current cross-origin intersection. Only used in the cross-origin mode. | ||
* @type {DOMRect} | ||
*/ | ||
var crossOriginRect = null; | ||
/** | ||
* Creates the global IntersectionObserverEntry constructor. | ||
@@ -152,2 +165,41 @@ * https://w3c.github.io/IntersectionObserver/#intersection-observer-entry | ||
/** | ||
* Sets up the polyfill in the cross-origin mode. The result is the | ||
* updater function that accepts two arguments: `boundingClientRect` and | ||
* `intersectionRect` - just as these fields would be available to the | ||
* parent via `IntersectionObserverEntry`. This function should be called | ||
* each time the iframe receives intersection information from the parent | ||
* window, e.g. via messaging. | ||
* @return {function(DOMRect, DOMRect)} | ||
*/ | ||
IntersectionObserver._setupCrossOriginUpdater = function() { | ||
if (!crossOriginUpdater) { | ||
/** | ||
* @param {DOMRect} boundingClientRect | ||
* @param {DOMRect} intersectionRect | ||
*/ | ||
crossOriginUpdater = function(boundingClientRect, intersectionRect) { | ||
if (!boundingClientRect || !intersectionRect) { | ||
crossOriginRect = getEmptyRect(); | ||
} else { | ||
crossOriginRect = convertFromParentRect(boundingClientRect, intersectionRect); | ||
} | ||
registry.forEach(function(observer) { | ||
observer._checkForIntersections(); | ||
}); | ||
}; | ||
} | ||
return crossOriginUpdater; | ||
}; | ||
/** | ||
* Resets the cross-origin mode. | ||
*/ | ||
IntersectionObserver._resetCrossOriginUpdater = function() { | ||
crossOriginUpdater = null; | ||
crossOriginRect = null; | ||
}; | ||
/** | ||
* Starts observing a target element for intersection changes based on | ||
@@ -410,2 +462,7 @@ * the thresholds values. | ||
IntersectionObserver.prototype._checkForIntersections = function() { | ||
if (!this.root && crossOriginUpdater && !crossOriginRect) { | ||
// Cross origin monitoring, but no initial data available yet. | ||
return; | ||
} | ||
var rootIsInDom = this._rootIsInDom(); | ||
@@ -426,3 +483,3 @@ var rootRect = rootIsInDom ? this._getRootRect() : getEmptyRect(); | ||
boundingClientRect: targetRect, | ||
rootBounds: rootRect, | ||
rootBounds: crossOriginUpdater && !this.root ? null : rootRect, | ||
intersectionRect: intersectionRect | ||
@@ -488,3 +545,15 @@ }); | ||
if (parent == this.root || parent == document) { | ||
parentRect = rootRect; | ||
if (crossOriginUpdater && !this.root) { | ||
if (!crossOriginRect || | ||
crossOriginRect.width == 0 && crossOriginRect.height == 0) { | ||
// A 0-size cross-origin intersection means no-intersection. | ||
parent = null; | ||
parentRect = null; | ||
intersectionRect = null; | ||
} else { | ||
parentRect = crossOriginRect; | ||
} | ||
} else { | ||
parentRect = rootRect; | ||
} | ||
} else { | ||
@@ -491,0 +560,0 @@ // Check if there's a frame that can be navigated to. |
{ | ||
"name": "intersection-observer", | ||
"version": "0.8.0", | ||
"version": "0.9.0", | ||
"description": "A polyfill for IntersectionObserver", | ||
@@ -5,0 +5,0 @@ "main": "intersection-observer", |
@@ -99,2 +99,63 @@ # `IntersectionObserver` polyfill | ||
## iframe support | ||
### Same-origin iframes | ||
Same-origin iframes are supported by the polyfill out of the box. | ||
### Cross-origin iframes | ||
Additional code and configuration are required to support cross-origin iframes, | ||
both on the iframe and host sides. | ||
The setup is as following: | ||
1. The host and iframe will establish a messaging channel. | ||
2. The host will setup its own IntersectionObserver instance for the | ||
cross-origin iframe element. It can either use the this polyfill or any other | ||
approach. For each IntersectionObserverEntry for the iframe it will forward | ||
intersection data to the iframe via messaging. | ||
3. The iframe will load the polyfill and configure it by calling the | ||
`_setupCrossOriginUpdater()` method. It will call the provided callback | ||
whenever it receives the intersection data from the the parent via messaging. | ||
A hypothetical host code: | ||
```javascript | ||
function forwardIntersectionToIframe(iframe) { | ||
createMessagingChannel(iframe, function(port) { | ||
var io = new IntersectionObserver(function() { | ||
port.postMessage({ | ||
boundingClientRect: serialize(boundingClientRect), | ||
intersectionRect: serialize(intersectionRect) | ||
}); | ||
}, {threshold: [0, 0.1, ..., 1]}); | ||
io.observe(iframe); | ||
}); | ||
} | ||
``` | ||
Notice that the host should provide a `threshold` argument for the desired | ||
level of precision. Otherwise, the iframe side may not update as frequently as | ||
desired. | ||
A hypothetical iframe code: | ||
```javascript | ||
createMessagingChannel(parent, function(port) { | ||
if (IntersectionObserver._setupCrossOriginUpdater) { | ||
var crossOriginUpdater = IntersectionObserver._setupCrossOriginUpdater(); | ||
port.onmessage = function(event) { | ||
crossOriginUpdater( | ||
deserialize(event.data.boundingClientRect), | ||
deserialize(event.data.intersectionRect) | ||
); | ||
}; | ||
} | ||
}); | ||
``` | ||
## Limitations | ||
@@ -101,0 +162,0 @@ |
Sorry, the diff of this file is too big to display
129197
3050
214