diff --git a/README.md b/README.md index 0894da2..8999ab9 100644 --- a/README.md +++ b/README.md @@ -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) diff --git a/package.json b/package.json index 8070dd8..1512db6 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/lazy.js b/src/lazy.js index ef1ff2b..d8aab28 100644 --- a/src/lazy.js +++ b/src/lazy.js @@ -6,8 +6,11 @@ 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; @@ -15,9 +18,7 @@ const lazy = (options = {}) => { 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 => { @@ -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) { + settings.onNonIntersectionCallback(el); + } + initialIntersection = false; + }; + + const observe = (els = null) => { if (els && observer !== null) { const elsArr = ensureArray(els); elsArr.forEach(el => observer.observe(el)); @@ -56,11 +67,12 @@ const lazy = (options = {}) => { setElAttrs(el); } }); + initialIntersection = false; } }; const unbindObserver = el => { - if (observer) { + if (observer && settings.unbindAfterIntersect === true) { observer.unobserve(el); } };