Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,23 @@ Type: `Number`
Either a single number or an array of numbers which indicate at what percentage of the target's visibility the observer's callback should be executed. From the [IntersectionObserver API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#Intersection_observer_options).
Default: `0.1`

### options.unbindAfterIntersect
Type: `Boolean`
Determines if the observed elements should be unobserved after crossing their respective observation thresholds for the first time.
Default: `true`

#### options.onIntersectionCallback
Type: `Function`
Returns: `Element`
An optional callback that will override the default image-loading behavior, and simply return the observed element that has entered the viewport.
Default: `null`

#### options.onNonIntersectionCallback
Type: `Function`
Returns: `Element`
An optional callback that will return the observed element that has left the viewport.
Default: `null`

## Methods

### .observe(els)
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "lazy",
"version": "1.0.0",
"version": "1.1.0",
"description": "A lazy loader based on the IntersectionObserver API",
"keywords": [
"lazy",
Expand Down
28 changes: 20 additions & 8 deletions src/lazy.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,19 @@ const lazy = (options = {}) => {
root: null,
rootMargin: '200px 0px',
threshold: 0.1,
onIntersectionCallback: null
unbindAfterIntersect: true,
onIntersectionCallback: null,
onNonIntersectionCallback: null
};
let initialIntersection = true;
let observer = null;
let settings;
let els;

const init = () => {
settings = {...defaults, ...options};
els = [...document.querySelectorAll(`${settings.elSelector}`)];
if (els.length > 0) {
intersectionObserverIsSupported() ? bindObserver(els) : load(els);
}
intersectionObserverIsSupported() ? bindObserver(els) : load(els);
};

const bindObserver = els => {
Expand All @@ -31,14 +32,24 @@ const lazy = (options = {}) => {

const onIntersection = entries => {
entries.forEach(entry => {
if (entry.intersectionRatio > 0) {
const el = entry.target;
const el = entry.target;
if (entry.isIntersecting) {
load(el);
} else {
onNonIntersection(el);
}
});
};

const observe = els => {
const onNonIntersection = el => {
if (settings.onNonIntersectionCallback !== null &&
initialIntersection === false) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if the element is within the viewport at page load, and then the user scrolls down the page and the element leaves the viewport? You'd probably want the non-intersection callback to fire in that scenario, but I don't think it would because initialIntersection would be true.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe also setting initialIntersection to false in your load() method would solve this problem?

settings.onNonIntersectionCallback(el);
}
initialIntersection = false;
};

const observe = (els = null) => {
if (els && observer !== null) {
const elsArr = ensureArray(els);
elsArr.forEach(el => observer.observe(el));
Expand All @@ -56,11 +67,12 @@ const lazy = (options = {}) => {
setElAttrs(el);
}
});
initialIntersection = false;
}
};

const unbindObserver = el => {
if (observer) {
if (observer && settings.unbindAfterIntersect === true) {
observer.unobserve(el);
}
};
Expand Down