From f1c7e5433ca27cda12cc8e41778f1dbed8c2fec1 Mon Sep 17 00:00:00 2001 From: Joshua Friend Date: Thu, 8 Feb 2018 13:58:16 -0600 Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=8E=89=20Add=20loaded=20callback?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dist/lozad.js | 12 ++++++++---- dist/lozad.min.js | 4 ++-- src/lozad.js | 9 ++++++--- test/index.js | 12 ++++++++++++ 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/dist/lozad.js b/dist/lozad.js index 4030a60..df31b88 100644 --- a/dist/lozad.js +++ b/dist/lozad.js @@ -1,4 +1,4 @@ -/*! lozad.js - v1.2.0 - 2018-01-24 +/*! lozad.js - v1.2.0 - 2018-02-08 * https://github.com/ApoorvSaxena/lozad.js * Copyright (c) 2018 Apoorv Saxena; Licensed MIT */ @@ -38,6 +38,9 @@ var defaultConfig = { if (element.getAttribute('data-background-image')) { element.style.backgroundImage = 'url(' + element.getAttribute('data-background-image') + ')'; } + }, + loaded: function loaded(element) { + markAsLoaded(element); } }; @@ -81,7 +84,8 @@ var lozad = function () { var _defaultConfig$option = _extends({}, defaultConfig, options), rootMargin = _defaultConfig$option.rootMargin, threshold = _defaultConfig$option.threshold, - load = _defaultConfig$option.load; + load = _defaultConfig$option.load, + loaded = _defaultConfig$option.loaded; var observer = void 0; @@ -105,7 +109,7 @@ var lozad = function () { continue; } load(elements[i]); - markAsLoaded(elements[i]); + loaded(elements[i]); } }, triggerLoad: function triggerLoad(element) { @@ -114,7 +118,7 @@ var lozad = function () { } load(element); - markAsLoaded(element); + loaded(element); } }; }; diff --git a/dist/lozad.min.js b/dist/lozad.min.js index a6160c8..eeb3605 100644 --- a/dist/lozad.min.js +++ b/dist/lozad.min.js @@ -1,4 +1,4 @@ -/*! lozad.js - v1.2.0 - 2018-01-24 +/*! lozad.js - v1.2.0 - 2018-02-08 * https://github.com/ApoorvSaxena/lozad.js * Copyright (c) 2018 Apoorv Saxena; Licensed MIT */ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.lozad=e()}(this,function(){"use strict";function t(t){t.setAttribute("data-loaded",!0)}var e=Object.assign||function(t){for(var e=1;e0&&(n.unobserve(r.target),o(r.target)||(e(r.target),t(r.target)))})}},i=function(t){return t instanceof Element?[t]:t instanceof NodeList?t:document.querySelectorAll(t)};return function(){var r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:".lozad",d=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},u=e({},n,d),c=u.rootMargin,s=u.threshold,g=u.load,f=void 0;return window.IntersectionObserver&&(f=new IntersectionObserver(a(g),{rootMargin:c,threshold:s})),{observe:function(){for(var e=i(r),n=0;n0&&(n.unobserve(r.target),o(r.target)||(e(r.target),t(r.target)))})}},i=function(t){return t instanceof Element?[t]:t instanceof NodeList?t:document.querySelectorAll(t)};return function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:".lozad",r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},d=e({},n,r),u=d.rootMargin,c=d.threshold,s=d.load,g=d.loaded,f=void 0;return window.IntersectionObserver&&(f=new IntersectionObserver(a(s),{rootMargin:u,threshold:c})),{observe:function(){for(var e=i(t),r=0;r { } export default function (selector = '.lozad', options = {}) { - const {rootMargin, threshold, load} = {...defaultConfig, ...options} + const {rootMargin, threshold, load, loaded} = {...defaultConfig, ...options} let observer if (window.IntersectionObserver) { @@ -81,7 +84,7 @@ export default function (selector = '.lozad', options = {}) { continue } load(elements[i]) - markAsLoaded(elements[i]) + loaded(elements[i]) } }, triggerLoad(element) { @@ -90,7 +93,7 @@ export default function (selector = '.lozad', options = {}) { } load(element) - markAsLoaded(element) + loaded(element) } } } diff --git a/test/index.js b/test/index.js index 259936c..85edfee 100644 --- a/test/index.js +++ b/test/index.js @@ -182,5 +182,17 @@ describe('lozad', () => { assert.equal('true', image.dataset.loaded) assert.equal(image.getAttribute('src'), image.dataset.src) }) + + it('should run loaded function after loading an element', () => { + const observer = lozad('.lozad', { + loaded(element) { + element.classList.add('loaded') + } + }) + const image = document.getElementsByTagName('img')[0] + image.setAttribute('class', 'lozad') + observer.triggerLoad(image) + assert.equal(true, image.classList.contains('loaded')) + }) }) }) From 9c26fb5f0fc59ff8f06ba225e8cac2f6545407c2 Mon Sep 17 00:00:00 2001 From: Joshua Friend Date: Thu, 8 Feb 2018 14:05:13 -0600 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=93=9D=20Add=20documentation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index f2bd735..fdb2a3e 100644 --- a/README.md +++ b/README.md @@ -112,6 +112,16 @@ lozad('.lozad', { }); ``` +If you would like to override the `loaded` state of elements, you can add the loaded option: +```js +lozad('.lozad', { + loaded: function(el) { + // Custom implementation on a loaded element + el.classList.add('loaded'); + } +}); +``` + If you want to lazy load dynamically added elements: ```js From 7cd6fde0ffa9e77915adb0be473b48ecccaf79c9 Mon Sep 17 00:00:00 2001 From: Joshua Friend Date: Sat, 10 Feb 2018 18:04:28 -0600 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=90=9B=20Fix=20overwriting=20of=20mar?= =?UTF-8?q?kAsLoaded=20method?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `markAsLoaded` is required to run for the `isLoaded` method to be useful. Also added a negative test for when a custom `load` option is passed in. --- README.md | 4 ++- dist/lozad.js | 13 ++++---- dist/lozad.min.js | 4 +-- src/lozad.js | 11 ++++--- test/index.js | 82 +++++++++++++++++++++++++++++++++++++++++------ 5 files changed, 90 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index fdb2a3e..2345e5f 100644 --- a/README.md +++ b/README.md @@ -112,7 +112,9 @@ lozad('.lozad', { }); ``` -If you would like to override the `loaded` state of elements, you can add the loaded option: +If you would like to extend the `loaded` state of elements, you can add the loaded option: + +> **Note**: The `"data-loaded"="true"` attribute is used by lozad to determine if an element has been previously loaded. ```js lozad('.lozad', { loaded: function(el) { diff --git a/dist/lozad.js b/dist/lozad.js index df31b88..6f49774 100644 --- a/dist/lozad.js +++ b/dist/lozad.js @@ -1,4 +1,4 @@ -/*! lozad.js - v1.2.0 - 2018-02-08 +/*! lozad.js - v1.2.0 - 2018-02-10 * https://github.com/ApoorvSaxena/lozad.js * Copyright (c) 2018 Apoorv Saxena; Licensed MIT */ @@ -39,9 +39,7 @@ var defaultConfig = { element.style.backgroundImage = 'url(' + element.getAttribute('data-background-image') + ')'; } }, - loaded: function loaded(element) { - markAsLoaded(element); - } + loaded: function loaded() {} }; function markAsLoaded(element) { @@ -52,7 +50,7 @@ var isLoaded = function isLoaded(element) { return element.getAttribute('data-loaded') === 'true'; }; -var onIntersection = function onIntersection(load) { +var onIntersection = function onIntersection(load, loaded) { return function (entries, observer) { entries.forEach(function (entry) { if (entry.intersectionRatio > 0) { @@ -61,6 +59,7 @@ var onIntersection = function onIntersection(load) { if (!isLoaded(entry.target)) { load(entry.target); markAsLoaded(entry.target); + loaded(entry.target); } } }); @@ -90,7 +89,7 @@ var lozad = function () { var observer = void 0; if (window.IntersectionObserver) { - observer = new IntersectionObserver(onIntersection(load), { + observer = new IntersectionObserver(onIntersection(load, loaded), { rootMargin: rootMargin, threshold: threshold }); @@ -109,6 +108,7 @@ var lozad = function () { continue; } load(elements[i]); + markAsLoaded(elements[i]); loaded(elements[i]); } }, @@ -118,6 +118,7 @@ var lozad = function () { } load(element); + markAsLoaded(element); loaded(element); } }; diff --git a/dist/lozad.min.js b/dist/lozad.min.js index eeb3605..87eeb2e 100644 --- a/dist/lozad.min.js +++ b/dist/lozad.min.js @@ -1,4 +1,4 @@ -/*! lozad.js - v1.2.0 - 2018-02-08 +/*! lozad.js - v1.2.0 - 2018-02-10 * https://github.com/ApoorvSaxena/lozad.js * Copyright (c) 2018 Apoorv Saxena; Licensed MIT */ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.lozad=e()}(this,function(){"use strict";function t(t){t.setAttribute("data-loaded",!0)}var e=Object.assign||function(t){for(var e=1;e0&&(n.unobserve(r.target),o(r.target)||(e(r.target),t(r.target)))})}},i=function(t){return t instanceof Element?[t]:t instanceof NodeList?t:document.querySelectorAll(t)};return function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:".lozad",r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},d=e({},n,r),u=d.rootMargin,c=d.threshold,s=d.load,g=d.loaded,f=void 0;return window.IntersectionObserver&&(f=new IntersectionObserver(a(s),{rootMargin:u,threshold:c})),{observe:function(){for(var e=i(t),r=0;r0&&(a.unobserve(n.target),o(n.target)||(e(n.target),t(n.target),r(n.target)))})}},i=function(t){return t instanceof Element?[t]:t instanceof NodeList?t:document.querySelectorAll(t)};return function(){var r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:".lozad",d=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},u=e({},n,d),c=u.rootMargin,s=u.threshold,g=u.load,f=u.loaded,l=void 0;return window.IntersectionObserver&&(l=new IntersectionObserver(a(g,f),{rootMargin:c,threshold:s})),{observe:function(){for(var e=i(r),n=0;n element.getAttribute('data-loaded') === 'true' -const onIntersection = load => (entries, observer) => { +const onIntersection = (load, loaded) => (entries, observer) => { entries.forEach(entry => { if (entry.intersectionRatio > 0) { observer.unobserve(entry.target) @@ -45,6 +43,7 @@ const onIntersection = load => (entries, observer) => { if (!isLoaded(entry.target)) { load(entry.target) markAsLoaded(entry.target) + loaded(entry.target) } } }) @@ -65,7 +64,7 @@ export default function (selector = '.lozad', options = {}) { let observer if (window.IntersectionObserver) { - observer = new IntersectionObserver(onIntersection(load), { + observer = new IntersectionObserver(onIntersection(load, loaded), { rootMargin, threshold }) @@ -84,6 +83,7 @@ export default function (selector = '.lozad', options = {}) { continue } load(elements[i]) + markAsLoaded(elements[i]) loaded(elements[i]) } }, @@ -93,6 +93,7 @@ export default function (selector = '.lozad', options = {}) { } load(element) + markAsLoaded(element) loaded(element) } } diff --git a/test/index.js b/test/index.js index 85edfee..8322ff3 100644 --- a/test/index.js +++ b/test/index.js @@ -162,7 +162,7 @@ describe('lozad', () => { }) }) - describe('public API functions', () => { + describe('when passing options', () => { beforeEach(() => { document.body.innerHTML = '' const image = document.createElement('img') @@ -172,18 +172,20 @@ describe('lozad', () => { document.body.appendChild(image) }) - it('should load image via triggerLoad function', () => { - const dataSrcSetAttr = 'test-srcset' - const observer = lozad() + it('should not load elements by default when custom load option is passed in', () => { + const observer = lozad('.lozad', { + load(element) { + element.classList.add('loaded') + } + }) const image = document.getElementsByTagName('img')[0] image.setAttribute('class', 'lozad') - image.setAttribute('data-srcset', dataSrcSetAttr) - observer.triggerLoad(image) - assert.equal('true', image.dataset.loaded) - assert.equal(image.getAttribute('src'), image.dataset.src) + observer.observe() + assert.equal(true, image.classList.contains('loaded')) + assert.equal(null, image.getAttribute('src')) }) - it('should run loaded function after loading an element', () => { + it('should run loaded option after loading an element', () => { const observer = lozad('.lozad', { loaded(element) { element.classList.add('loaded') @@ -191,8 +193,68 @@ describe('lozad', () => { }) const image = document.getElementsByTagName('img')[0] image.setAttribute('class', 'lozad') - observer.triggerLoad(image) + observer.observe() + assert.equal(true, image.classList.contains('loaded')) + }) + + it('should set data attribute when loaded option is passed in', () => { + const observer = lozad('.lozad', { + loaded(element) { + element.classList.add('loaded') + } + }) + const image = document.getElementsByTagName('img')[0] + image.setAttribute('class', 'lozad') + observer.observe() assert.equal(true, image.classList.contains('loaded')) + assert.equal('true', image.dataset.loaded) + }) + }) + + describe('public API functions', () => { + beforeEach(() => { + document.body.innerHTML = '' + const image = document.createElement('img') + image.dataset.src = Math.random() + .toString(36) + .substring(7) + document.body.appendChild(image) }) + + it('should load image via triggerLoad function', () => { + const dataSrcSetAttr = 'test-srcset' + const observer = lozad() + const image = document.getElementsByTagName('img')[0] + image.setAttribute('class', 'lozad') + image.setAttribute('data-srcset', dataSrcSetAttr) + observer.triggerLoad(image) + assert.equal('true', image.dataset.loaded) + assert.equal(image.getAttribute('src'), image.dataset.src) + }) + + // It('should run loaded function after loading an element', () => { + // const observer = lozad('.lozad', { + // loaded(element) { + // element.classList.add('loaded') + // } + // }) + // const image = document.getElementsByTagName('img')[0] + // image.setAttribute('class', 'lozad') + // observer.triggerLoad(image) + // assert.equal(true, image.classList.contains('loaded')) + // }) + + // it('should set data attribute when custom implementation of loaded is used', () => { + // const observer = lozad('.lozad', { + // loaded(element) { + // element.classList.add('loaded') + // } + // }) + // const image = document.getElementsByTagName('img')[0] + // image.setAttribute('class', 'lozad') + // observer.triggerLoad(image) + // assert.equal(true, image.classList.contains('loaded')) + // assert.equal('true', image.dataset.loaded) + // }) }) }) From a31e42008a9756c04601dc54608d384f9e6d6e3a Mon Sep 17 00:00:00 2001 From: Joshua Friend Date: Tue, 13 Feb 2018 07:45:32 -0600 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=9A=BF=20Remove=20commented=20out=20c?= =?UTF-8?q?ode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/index.js | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/test/index.js b/test/index.js index 8322ff3..3401646 100644 --- a/test/index.js +++ b/test/index.js @@ -231,30 +231,5 @@ describe('lozad', () => { assert.equal('true', image.dataset.loaded) assert.equal(image.getAttribute('src'), image.dataset.src) }) - - // It('should run loaded function after loading an element', () => { - // const observer = lozad('.lozad', { - // loaded(element) { - // element.classList.add('loaded') - // } - // }) - // const image = document.getElementsByTagName('img')[0] - // image.setAttribute('class', 'lozad') - // observer.triggerLoad(image) - // assert.equal(true, image.classList.contains('loaded')) - // }) - - // it('should set data attribute when custom implementation of loaded is used', () => { - // const observer = lozad('.lozad', { - // loaded(element) { - // element.classList.add('loaded') - // } - // }) - // const image = document.getElementsByTagName('img')[0] - // image.setAttribute('class', 'lozad') - // observer.triggerLoad(image) - // assert.equal(true, image.classList.contains('loaded')) - // assert.equal('true', image.dataset.loaded) - // }) }) })