did-intersect
This modifier triggers a callback when intersection events are observed on the target element.
Powered by intersection-observer-admin for performance.
When you should use this modifier
You should use this modifier whenever you need to monitor if an element is intersecting another element or the viewport itself. It might be useful for implementing features like showing/hiding sticky header, highlighting element(s) when intersected, and tracking.
You should not use this modifier until you've exhausted all native solutions. Native solutions based on html and css should always
be prioritized when reasonable. For example, a basic sticky header can be implemented using just position: sticky in your css.
Basic Usage
did-intersect expects at least one of the 2 callback handlers, onEnter and onExit::
<div ></div>
The handler will be called with an instance of IntersectionObserverEntry
@action
onEnteringIntersection(entry) {
// do something
}
You can also set a maximum limit on the number of times the callbacks should trigger for each onEnter and onExit via maxEnter and maxExit respectively. By default, there is no limit.
Note: This function passes over a single element entry compared to the vanilla IntersectionObserver API that sends an array of elements.
Advanced Usage
Options
did-intersect also supports passing an options object into IntersectionObserver:
<div ></div>
The options supported are documented in the MDN site under Intersection observer options.
Other arguments
Besides onEnter, onExit, and options, accepts the following named arguments:
maxEnter: a maximum number of times to allow theIntersectionObserverto be triggered for entering the viewportmaxExit: a maximum number of times to allow theIntersectionObserverto be triggered for entering the viewportisObserving: whether to allow theIntersectionObserverto trigger at all. Useful for times when you want to programmatically control enabling and disabling observation of an element based on some tracked state in your own code.
Testing
Since the underlying IntersectionObserver behavior is non-deterministic, we provide a did-intersect-mock test helper to help you test did-intersect deterministically.
did-intersect-mock creates a mock provides 2 APIs
enter(elementString)triggers theonEntercallback, given an DOM element stringexit(elementString)triggers theonExitcallback, given an DOM element string
import mockDidIntersect from 'ember-scroll-modifiers/test-support/did-intersect-mock';
...
const didIntersectMock = mockDidIntersect(sinon);
await render(hbs`
<div
data-test-did-intersect
{{did-intersect onEnter=this.onEnteringIntersection onExit=this.onExitingIntersection}}
>
</div>
`)
...
await didIntersectMock.enter('[data-test-did-intersect]');
...
await didIntersectMock.exit('[data-test-did-intersect]');
Even though, this effectively allows you to trigger the did-intersect on demand without requiring real app interactions, you should still do it as best practice.
...
await triggerEvent('[data-test-root-element-selector]', 'scroll');
await didIntersectMock.enter('[data-test-did-intersect]');
...
You can also construct and pass you own IntersectionObserverEntry, enter(elementString, IntersectionObserverEntry), exit(elementString, IntersectionObserverEntry)
...
await didIntersectMock.enter('[data-test-did-intersect]', {time: 100});
await didIntersectMock.exit('[data-test-did-intersect]', {time: 100});
...
Browser Support
This feature is supported in the latest versions of every browser except IE 11. In browsers where IntersectionObserver is not supported, this modifier becomes a no-op. It will not error, nor will it employ a fallback. Features built with this addon will simply gracefully not respond to intersection events.
Polyfilling is possible, but unrecommended.