vanilla-lazyload
Advanced tools
Comparing version 8.12.0 to 8.13.0
@@ -45,3 +45,3 @@ { | ||
"no-loop-func": 1, | ||
"no-magic-numbers": [2, { "ignore": [0, 1, -1] }], | ||
"no-magic-numbers": [1, {"ignore": [-1, 0, 1]}], | ||
"no-multi-spaces": 1, | ||
@@ -48,0 +48,0 @@ "no-multi-str": 1, |
@@ -1,7 +0,1 @@ | ||
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : | ||
typeof define === 'function' && define.amd ? define(factory) : | ||
(global.LazyLoad = factory()); | ||
}(this, (function () { 'use strict'; | ||
var getDefaultSettings = () => ({ | ||
@@ -192,9 +186,8 @@ elements_selector: "img", | ||
const isBot = | ||
(runningOnBrowser && !("onscroll" in window)) || | ||
/(gle|ing|ro)bot|crawl|spider/i.test(navigator.userAgent); | ||
const supportsClassList = | ||
runningOnBrowser && "classList" in document.createElement("p"); | ||
const isBot = | ||
(runningOnBrowser && !("onscroll" in window)) || | ||
/glebot|bingbot|crawler|spider|robot|crawling/i.test(navigator.userAgent); | ||
const addClass = (element, className) => { | ||
@@ -433,4 +426,2 @@ if (supportsClassList) { | ||
return LazyLoad; | ||
}))); | ||
export default LazyLoad; |
@@ -175,6 +175,5 @@ var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
var isBot = runningOnBrowser && !("onscroll" in window) || /(gle|ing|ro)bot|crawl|spider/i.test(navigator.userAgent); | ||
var supportsClassList = runningOnBrowser && "classList" in document.createElement("p"); | ||
var isBot = runningOnBrowser && !("onscroll" in window) || /glebot|bingbot|crawler|spider|robot|crawling/i.test(navigator.userAgent); | ||
var addClass = function addClass(element, className) { | ||
@@ -181,0 +180,0 @@ if (supportsClassList) { |
@@ -1,1 +0,2 @@ | ||
var _extends=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(e[o]=n[o])}return e},_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};!function(e,t){"object"===("undefined"==typeof exports?"undefined":_typeof(exports))&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.LazyLoad=t()}(this,function(){"use strict";var d=function(e,t){e&&e(t)},o=function(e){return e.getBoundingClientRect().top+window.pageYOffset-e.ownerDocument.documentElement.clientTop},h=function(e,t,n){return(t===window?window.innerHeight+window.pageYOffset:o(t)+t.offsetHeight)<=o(e)-n},i=function(e){return e.getBoundingClientRect().left+window.pageXOffset-e.ownerDocument.documentElement.clientLeft},f=function(e,t,n){var o=window.innerWidth;return(t===window?o+window.pageXOffset:i(t)+o)<=i(e)-n},_=function(e,t,n){return(t===window?window.pageYOffset:o(t))>=o(e)+n+e.offsetHeight},p=function(e,t,n){return(t===window?window.pageXOffset:i(t))>=i(e)+n+e.offsetWidth};var s=function(e,t){var n,o="LazyLoad::Initialized",i=new e(t);try{n=new CustomEvent(o,{detail:{instance:i}})}catch(e){(n=document.createEvent("CustomEvent")).initCustomEvent(o,!1,!1,{instance:i})}window.dispatchEvent(n)};var r="data-",l="was-processed",a="true",u=function(e,t){return e.getAttribute(r+t)},m=function(e){return t=l,n=a,e.setAttribute(r+t,n);var t,n},c=function(e){return u(e,l)===a},g=function(e,t,n){for(var o,i=0;o=e.children[i];i+=1)if("SOURCE"===o.tagName){var s=u(o,n);s&&o.setAttribute(t,s)}},v=function(e,t,n){n&&e.setAttribute(t,n)};var e="undefined"!=typeof window,n=e&&"classList"in document.createElement("p"),w=e&&!("onscroll"in window)||/glebot|bingbot|crawler|spider|robot|crawling/i.test(navigator.userAgent),b=function(e,t){n?e.classList.add(t):e.className+=(e.className?" ":"")+t},y=function(e,t){n?e.classList.remove(t):e.className=e.className.replace(new RegExp("(^|\\s+)"+t+"(\\s+|$)")," ").replace(/^\s+/,"").replace(/\s+$/,"")},t=function(e){this._settings=_extends({},{elements_selector:"img",container:window,threshold:300,throttle:150,data_src:"src",data_srcset:"srcset",data_sizes:"sizes",class_loading:"loading",class_loaded:"loaded",class_error:"error",class_initial:"initial",skip_invisible:!0,callback_load:null,callback_error:null,callback_set:null,callback_processed:null,callback_enter:null},e),this._queryOriginNode=this._settings.container===window?document:this._settings.container,this._previousLoopTime=0,this._loopTimeout=null,this._boundHandleScroll=this.handleScroll.bind(this),this._isFirstLoop=!0,window.addEventListener("resize",this._boundHandleScroll),this.update()};t.prototype={_reveal:function(t,e){if(e||!c(t)){var n=this._settings,o=function e(){n&&(t.removeEventListener("load",i),t.removeEventListener("error",e),y(t,n.class_loading),b(t,n.class_error),d(n.callback_error,t))},i=function e(){n&&(y(t,n.class_loading),b(t,n.class_loaded),t.removeEventListener("load",e),t.removeEventListener("error",o),d(n.callback_load,t))};d(n.callback_enter,t),-1<["IMG","IFRAME","VIDEO"].indexOf(t.tagName)&&(t.addEventListener("load",i),t.addEventListener("error",o),b(t,n.class_loading)),function(e,t){var n=t.data_sizes,o=t.data_srcset,i=t.data_src,s=u(e,i),r=e.tagName;if("IMG"===r){var l=e.parentNode;l&&"PICTURE"===l.tagName&&g(l,"srcset",o);var a=u(e,n);v(e,"sizes",a);var c=u(e,o);return v(e,"srcset",c),v(e,"src",s)}if("IFRAME"!==r)return"VIDEO"===r?(g(e,"src",i),v(e,"src",s)):s&&(e.style.backgroundImage='url("'+s+'")');v(e,"src",s)}(t,n),d(n.callback_set,t)}},_loopThroughElements:function(e){var t,n,o,i=this._settings,s=this._elements,r=s?s.length:0,l=void 0,a=[],c=this._isFirstLoop;for(l=0;l<r;l++){var u=s[l];i.skip_invisible&&null===u.offsetParent||(!w&&!e&&(t=u,n=i.container,o=i.threshold,h(t,n,o)||_(t,n,o)||f(t,n,o)||p(t,n,o))||(c&&b(u,i.class_initial),this.load(u),a.push(l),m(u)))}for(;a.length;)s.splice(a.pop(),1),d(i.callback_processed,s.length);0===r&&this._stopScrollHandler(),c&&(this._isFirstLoop=!1)},_purgeElements:function(){var e=this._elements,t=e.length,n=void 0,o=[];for(n=0;n<t;n++){var i=e[n];c(i)&&o.push(n)}for(;0<o.length;)e.splice(o.pop(),1)},_startScrollHandler:function(){this._isHandlingScroll||(this._isHandlingScroll=!0,this._settings.container.addEventListener("scroll",this._boundHandleScroll))},_stopScrollHandler:function(){this._isHandlingScroll&&(this._isHandlingScroll=!1,this._settings.container.removeEventListener("scroll",this._boundHandleScroll))},handleScroll:function(){var e=this._settings.throttle;if(0!==e){var t=Date.now(),n=e-(t-this._previousLoopTime);n<=0||e<n?(this._loopTimeout&&(clearTimeout(this._loopTimeout),this._loopTimeout=null),this._previousLoopTime=t,this._loopThroughElements()):this._loopTimeout||(this._loopTimeout=setTimeout(function(){this._previousLoopTime=Date.now(),this._loopTimeout=null,this._loopThroughElements()}.bind(this),n))}else this._loopThroughElements()},loadAll:function(){this._loopThroughElements(!0)},update:function(){this._elements=Array.prototype.slice.call(this._queryOriginNode.querySelectorAll(this._settings.elements_selector)),this._purgeElements(),this._loopThroughElements(),this._startScrollHandler()},destroy:function(){window.removeEventListener("resize",this._boundHandleScroll),this._loopTimeout&&(clearTimeout(this._loopTimeout),this._loopTimeout=null),this._stopScrollHandler(),this._elements=null,this._queryOriginNode=null,this._settings=null},load:function(e,t){this._reveal(e,t)}};var E=window.lazyLoadOptions;return e&&E&&function(e,t){var n=t.length;if(n)for(var o=0;o<n;o++)s(e,t[o]);else s(e,t)}(t,E),t}); | ||
var _extends=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(e[o]=n[o])}return e},_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};!function(e,t){"object"===("undefined"==typeof exports?"undefined":_typeof(exports))&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.LazyLoad=t()}(this,function(){"use strict";function e(e,t,n){return!(s(e,t,n)||a(e,t,n)||l(e,t,n)||c(e,t,n))}function t(e,t){var n=t.data_sizes,o=t.data_srcset,i=t.data_src,s=d(e,i),r=e.tagName;if("IMG"===r){var l=e.parentNode;l&&"PICTURE"===l.tagName&&p(l,"srcset",o);var a=d(e,n);m(e,"sizes",a);var c=d(e,o);return m(e,"srcset",c),void m(e,"src",s)}if("IFRAME"!==r)return"VIDEO"===r?(p(e,"src",i),void m(e,"src",s)):void(s&&(e.style.backgroundImage='url("'+s+'")'));m(e,"src",s)}var n=function(){return{elements_selector:"img",container:window,threshold:300,throttle:150,data_src:"src",data_srcset:"srcset",data_sizes:"sizes",class_loading:"loading",class_loaded:"loaded",class_error:"error",class_initial:"initial",skip_invisible:!0,callback_load:null,callback_error:null,callback_set:null,callback_processed:null,callback_enter:null}},o=function(e,t){e&&e(t)},i=function(e){return e.getBoundingClientRect().top+window.pageYOffset-e.ownerDocument.documentElement.clientTop},s=function(e,t,n){return(t===window?window.innerHeight+window.pageYOffset:i(t)+t.offsetHeight)<=i(e)-n},r=function(e){return e.getBoundingClientRect().left+window.pageXOffset-e.ownerDocument.documentElement.clientLeft},l=function(e,t,n){var o=window.innerWidth;return(t===window?o+window.pageXOffset:r(t)+o)<=r(e)-n},a=function(e,t,n){return(t===window?window.pageYOffset:i(t))>=i(e)+n+e.offsetHeight},c=function(e,t,n){return(t===window?window.pageXOffset:r(t))>=r(e)+n+e.offsetWidth},u=function(e,t){var n,o=new e(t);try{n=new CustomEvent("LazyLoad::Initialized",{detail:{instance:o}})}catch(e){(n=document.createEvent("CustomEvent")).initCustomEvent("LazyLoad::Initialized",!1,!1,{instance:o})}window.dispatchEvent(n)},d=function(e,t){return e.getAttribute("data-"+t)},f=function(e,t,n){return e.setAttribute("data-"+t,n)},h=function(e){return f(e,"was-processed","true")},_=function(e){return"true"===d(e,"was-processed")},p=function(e,t,n){for(var o,i=0;o=e.children[i];i+=1)if("SOURCE"===o.tagName){var s=d(o,n);s&&o.setAttribute(t,s)}},m=function(e,t,n){n&&e.setAttribute(t,n)},g="undefined"!=typeof window,v=g&&!("onscroll"in window)||/(gle|ing|ro)bot|crawl|spider/i.test(navigator.userAgent),w=g&&"classList"in document.createElement("p"),b=function(e,t){w?e.classList.add(t):e.className+=(e.className?" ":"")+t},y=function(e,t){w?e.classList.remove(t):e.className=e.className.replace(new RegExp("(^|\\s+)"+t+"(\\s+|$)")," ").replace(/^\s+/,"").replace(/\s+$/,"")},E=function(e){this._settings=_extends({},n(),e),this._queryOriginNode=this._settings.container===window?document:this._settings.container,this._previousLoopTime=0,this._loopTimeout=null,this._boundHandleScroll=this.handleScroll.bind(this),this._isFirstLoop=!0,window.addEventListener("resize",this._boundHandleScroll),this.update()};E.prototype={_reveal:function(e,n){if(n||!_(e)){var i=this._settings,s=function t(){i&&(e.removeEventListener("load",r),e.removeEventListener("error",t),y(e,i.class_loading),b(e,i.class_error),o(i.callback_error,e))},r=function t(){i&&(y(e,i.class_loading),b(e,i.class_loaded),e.removeEventListener("load",t),e.removeEventListener("error",s),o(i.callback_load,e))};o(i.callback_enter,e),["IMG","IFRAME","VIDEO"].indexOf(e.tagName)>-1&&(e.addEventListener("load",r),e.addEventListener("error",s),b(e,i.class_loading)),t(e,i),o(i.callback_set,e)}},_loopThroughElements:function(t){var n=this._settings,i=this._elements,s=i?i.length:0,r=void 0,l=[],a=this._isFirstLoop;for(r=0;r<s;r++){var c=i[r];n.skip_invisible&&null===c.offsetParent||(v||t||e(c,n.container,n.threshold))&&(a&&b(c,n.class_initial),this.load(c),l.push(r),h(c))}for(;l.length;)i.splice(l.pop(),1),o(n.callback_processed,i.length);0===s&&this._stopScrollHandler(),a&&(this._isFirstLoop=!1)},_purgeElements:function(){var e=this._elements,t=e.length,n=void 0,o=[];for(n=0;n<t;n++){var i=e[n];_(i)&&o.push(n)}for(;o.length>0;)e.splice(o.pop(),1)},_startScrollHandler:function(){this._isHandlingScroll||(this._isHandlingScroll=!0,this._settings.container.addEventListener("scroll",this._boundHandleScroll))},_stopScrollHandler:function(){this._isHandlingScroll&&(this._isHandlingScroll=!1,this._settings.container.removeEventListener("scroll",this._boundHandleScroll))},handleScroll:function(){var e=this._settings.throttle;if(0!==e){var t=Date.now(),n=e-(t-this._previousLoopTime);n<=0||n>e?(this._loopTimeout&&(clearTimeout(this._loopTimeout),this._loopTimeout=null),this._previousLoopTime=t,this._loopThroughElements()):this._loopTimeout||(this._loopTimeout=setTimeout(function(){this._previousLoopTime=Date.now(),this._loopTimeout=null,this._loopThroughElements()}.bind(this),n))}else this._loopThroughElements()},loadAll:function(){this._loopThroughElements(!0)},update:function(){this._elements=Array.prototype.slice.call(this._queryOriginNode.querySelectorAll(this._settings.elements_selector)),this._purgeElements(),this._loopThroughElements(),this._startScrollHandler()},destroy:function(){window.removeEventListener("resize",this._boundHandleScroll),this._loopTimeout&&(clearTimeout(this._loopTimeout),this._loopTimeout=null),this._stopScrollHandler(),this._elements=null,this._queryOriginNode=null,this._settings=null},load:function(e,t){this._reveal(e,t)}};var L=window.lazyLoadOptions;return g&&L&&function(e,t){var n=t.length;if(n)for(var o=0;o<n;o++)u(e,t[o]);else u(e,t)}(E,L),E}); | ||
//# sourceMappingURL=lazyload.min.js.map |
102
gulpfile.js
var gulp = require("gulp"); | ||
var eslint = require("gulp-eslint"); | ||
var rollup = require("gulp-rollup"); | ||
var sourcemaps = require("gulp-sourcemaps"); | ||
var rename = require("gulp-rename"); | ||
@@ -9,4 +10,9 @@ var babel = require("gulp-babel"); | ||
var destFolder = "./dist"; | ||
var babelOptions = { | ||
presets: [["es2015", { modules: false }]], | ||
sourceMap: false, | ||
plugins: ["transform-object-assign"] | ||
}; | ||
gulp.task("default", function() { | ||
gulp.task("lint", function() { | ||
process.env.NODE_ENV = "release"; | ||
@@ -19,7 +25,15 @@ return ( | ||
pipe(eslint.format()). | ||
pipe(eslint.failAfterError()). // --> failing if errors | ||
pipe(eslint.failAfterError()) // --> failing if errors | ||
); | ||
}); | ||
gulp.task("dist-es", function() { | ||
process.env.NODE_ENV = "release"; | ||
return ( | ||
gulp. | ||
src("./src/**/*.js"). | ||
// ----------- rolling up -------------- | ||
pipe( | ||
rollup({ | ||
output: { name: "LazyLoad", format: "umd" }, | ||
output: { name: "LazyLoad", format: "es" }, | ||
input: "./src/lazyload.js" | ||
@@ -29,11 +43,46 @@ }) | ||
pipe(rename("lazyload.es2015.js")). | ||
pipe(gulp.dest(destFolder)). // --> writing rolledup | ||
pipe(gulp.dest(destFolder)) // --> writing rolledup | ||
); | ||
}); | ||
gulp.task("dist-amd", function() { | ||
process.env.NODE_ENV = "release"; | ||
return ( | ||
gulp. | ||
src("./src/**/*.js"). | ||
pipe(sourcemaps.init()). | ||
// ----------- rolling up -------------- | ||
pipe( | ||
rollup({ | ||
output: { name: "LazyLoad", format: "amd" }, | ||
input: "./src/lazyload.js" | ||
}) | ||
). | ||
// ----------- babelizing -------------- | ||
pipe(babel(babelOptions)). | ||
pipe(rename("lazyload.amd.js")). | ||
pipe(gulp.dest(destFolder)). // --> writing babelized ES5 | ||
// ----------- minifying -------------- | ||
pipe(uglify()). | ||
pipe(rename("lazyload.amd.min.js")). | ||
pipe(sourcemaps.write("")). // --> writing sourcemap | ||
pipe(gulp.dest(destFolder)) // --> writing uglified | ||
); | ||
}); | ||
gulp.task("dist-umd", function() { | ||
process.env.NODE_ENV = "release"; | ||
return ( | ||
gulp. | ||
src("./src/**/*.js"). | ||
pipe(sourcemaps.init()). | ||
// ----------- rolling up -------------- | ||
pipe( | ||
babel({ | ||
presets: [["es2015", { modules: false }]], | ||
sourceMap: false, | ||
plugins: ["transform-object-assign"] | ||
rollup({ | ||
output: { name: "LazyLoad", format: "umd" }, | ||
input: "./src/lazyload.js" | ||
}) | ||
). | ||
// ----------- babelizing -------------- | ||
pipe(babel(babelOptions)). | ||
pipe(rename("lazyload.js")). | ||
@@ -44,2 +93,3 @@ pipe(gulp.dest(destFolder)). // --> writing babelized ES5 | ||
pipe(rename("lazyload.min.js")). | ||
pipe(sourcemaps.write("")). // --> writing sourcemap | ||
pipe(gulp.dest(destFolder)) // --> writing uglified | ||
@@ -49,5 +99,37 @@ ); | ||
gulp.task("dist-iife", function() { | ||
process.env.NODE_ENV = "release"; | ||
return ( | ||
gulp. | ||
src("./src/**/*.js"). | ||
pipe(sourcemaps.init()). | ||
// ----------- rolling up -------------- | ||
pipe( | ||
rollup({ | ||
output: { name: "LazyLoad", format: "iife" }, | ||
input: "./src/lazyload.js" | ||
}) | ||
). | ||
// ----------- babelizing -------------- | ||
pipe(babel(babelOptions)). | ||
pipe(rename("lazyload.iife.js")). | ||
pipe(gulp.dest(destFolder)). // --> writing babelized ES5 | ||
// ----------- minifying -------------- | ||
pipe(uglify()). | ||
pipe(rename("lazyload.iife.min.js")). | ||
pipe(sourcemaps.write("")). // --> writing sourcemap | ||
pipe(gulp.dest(destFolder)) // --> writing uglified | ||
); | ||
}); | ||
gulp.task("watch", function() { | ||
gulp.watch("./src/**/*.js", ["default"]); | ||
// Other watchers | ||
gulp.watch("./src/**/*.js", [ | ||
"lint", | ||
"dist-umd", | ||
"dist-es", | ||
"dist-amd", | ||
"dist-iife" | ||
]); | ||
}); | ||
gulp.task("default", ["lint", "dist-umd", "dist-es", "dist-amd", "dist-iife"]); |
{ | ||
"name": "vanilla-lazyload", | ||
"version": "8.12.0", | ||
"version": "8.13.0", | ||
"description": "A fast, lightweight script to load images as they enter the viewport. SEO friendly, it supports responsive images (both srcset + sizes and picture) and progressive JPEG", | ||
"main": "dist/lazyload.min.js", | ||
"module": "dist/lazyload.es2015.js", | ||
"browser": "dist/lazyload.iife.min.js", | ||
"devDependencies": { | ||
"babel-core": "^6.26.0", | ||
"babel-plugin-transform-object-assign": "^6.22.0", | ||
"babel-preset-env": "^1.6.0", | ||
"babel-preset-es2015": "^6.24.1", | ||
"gulp": "^3.9.1", | ||
"gulp-babel": "^7.0.0", | ||
"gulp-babel": "^7.0.1", | ||
"gulp-eslint": "^4.0.0", | ||
"gulp-notify": "^3.0.0", | ||
"gulp-rename": "^1.2.2", | ||
"gulp-rollup": "^2.14.0", | ||
"gulp-uglify": "^3.0.0" | ||
"gulp-rollup": "^2.16.2", | ||
"gulp-sourcemaps": "^2.6.4", | ||
"gulp-uglify": "^3.0.0", | ||
"jest-cli": "^20.0.4" | ||
}, | ||
@@ -36,5 +38,4 @@ "scripts": {}, | ||
"perfmatters", | ||
"no-jquery", | ||
"gulp", | ||
"async" | ||
"async", | ||
"no-jquery" | ||
], | ||
@@ -41,0 +42,0 @@ "author": "Andrea \"verlok\" Verlicchi", |
238
README.md
@@ -1,5 +0,3 @@ | ||
LazyLoad is a fast, lightweight and flexible script that _speeds up your web application_ by **loading images only as they enter the viewport**. LazyLoad is written in plain (vanilla) Javascript, it supports [responsive images](https://alistapart.com/article/responsive-images-in-practice), it's SEO friendly and it has some other [notable features](#notable-features). | ||
LazyLoad is a fast, lightweight and flexible script that _speeds up your web application_ by **loading images, video or iframes as they enter the viewport**. It's written in plain "vanilla" JavaScript, uses [Intersection Observers](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API), and supports [responsive images](https://alistapart.com/article/responsive-images-in-practice). It's also SEO-friendly and it has some other [notable features](#notable-features). | ||
Check out the [LazyLoad website](https://verlok.github.io/lazyload/), in case you're reading this on GitHub. | ||
Jump to: | ||
@@ -10,19 +8,51 @@ | ||
## Include the script | ||
## Include the script / browser support | ||
### From [cdnjs](https://cdnjs.com/libraries/vanilla-lazyload) | ||
### Simple: direct include from cdnjs | ||
Just include the [latest version](https://cdnjs.com/libraries/vanilla-lazyload) script, e.g. like that: | ||
The **universal, recommended version** of LazyLoad is 8.x since it **supports ALL browsers** from IE9 up. | ||
```html | ||
<script src="https://cdnjs.cloudflare.com/ajax/libs/vanilla-lazyload/8.0.1/lazyload.min.js"></script> | ||
<script src="https://cdnjs.cloudflare.com/ajax/libs/vanilla-lazyload/8.13.0/lazyload.min.js"></script> | ||
``` | ||
Starting from version 9, LazyLoad uses the IntersectionObserver API, which is not supported by Internet Explorer and Safari (yet). As a result, if you included the latest version of LazyLoad, all the images would be loaded at once in those browsers. | ||
To include the [latest version](https://cdnjs.com/libraries/vanilla-lazyload) of LazyLoad, use the following script: | ||
```html | ||
<script src="https://cdnjs.cloudflare.com/ajax/libs/vanilla-lazyload/10.13.0/lazyload.min.js"></script> | ||
``` | ||
### Advanced and best option: conditionally load version 8 or 10 | ||
The best thing you can do is to conditionally load the best version of LazyLoad **depending on the browser's support of the IntersectionObserver API**. | ||
You can do it with the following script: | ||
```js | ||
(function(w, d){ | ||
var b = d.getElementsByTagName('body')[0]; | ||
var s = d.createElement("script"); s.async = true; | ||
var v = !("IntersectionObserver" in w) ? "8.13.0" : "10.13.0"; | ||
s.src = "https://cdnjs.cloudflare.com/ajax/libs/vanilla-lazyload/" + v + "/lazyload.min.js"; | ||
w.lazyLoadOptions = {}; // Your options here. See "recipes" for more information about async. | ||
b.appendChild(s); | ||
}(window, document)); | ||
``` | ||
See the conditional_load.html file in the demos folder to try it or play around with it. | ||
### Local install | ||
If you prefer to install LazyLoad locally in your project, you can either: | ||
- [download it from the `dist` folder](https://github.com/verlok/lazyload/tree/master/dist). The file you typically want to use is **lazyload.min.js**. | ||
- install it with `npm install --save vanilla-lazyload` | ||
- install it with `bower install vanilla-lazyload`. | ||
- **download it** from the [`dist` folder](https://github.com/verlok/lazyload/tree/master/dist) | ||
The file you typically want to use is `lazyload.min.js` | ||
If you prefer the ES2015 version, use `lazyload.es2015.js` | ||
- **install it with npm** | ||
Recommended version `npm install vanilla-lazyload@8.13.0` | ||
Latest version `npm install vanilla-lazyload` | ||
- **install it with bower** | ||
Recommended version `bower install vanilla-lazyload#8.13.0` | ||
Latest version `bower install vanilla-lazyload` | ||
### Async script | ||
@@ -41,3 +71,3 @@ | ||
```html | ||
<img alt="..." | ||
<img class="lazy" alt="..." | ||
data-src="../img/44721746JJ_15_a.jpg" | ||
@@ -50,3 +80,5 @@ width="220" height="280"> | ||
```js | ||
var myLazyLoad = new LazyLoad(); | ||
var myLazyLoad = new LazyLoad({ | ||
elements_selector: ".lazy" | ||
}); | ||
``` | ||
@@ -63,5 +95,5 @@ | ||
```html | ||
<img data-src="/your/image1.jpg" | ||
<img class="lazy" data-src="/your/image1.jpg" | ||
data-srcset="/your/image1.jpg 200w, /your/image1@2x.jpg 400w" | ||
sizes="(min-width: 20em) 35vw, 100vw"> | ||
data-sizes="(min-width: 20em) 35vw, 100vw"> | ||
``` | ||
@@ -72,6 +104,8 @@ | ||
```js | ||
var myLazyLoad = new LazyLoad(); | ||
var myLazyLoad = new LazyLoad({ | ||
elements_selector: ".lazy" | ||
}); | ||
``` | ||
[DEMO](http://verlok.github.io/lazyload/demos/with_srcset_sizes.html) | [SOURCE](https://github.com/verlok/lazyload/blob/master/demos/with_srcset_sizes.html) | [API](#api) | ||
[DEMO](http://verlok.github.io/lazyload/demos/with_srcset_lazy_sizes.html) | [SOURCE](https://github.com/verlok/lazyload/blob/master/demos/with_srcset_lazy_sizes.html) | [API](#api) | ||
@@ -88,3 +122,3 @@ ### Responsive images - picture | ||
<source media="(min-width: 500px)" data-srcset="/your/image1b.jpg" /> | ||
<img alt="Stivaletti" data-src="/your/image1.jpg"> | ||
<img class="lazy" alt="Stivaletti" data-src="/your/image1.jpg"> | ||
</picture> | ||
@@ -96,3 +130,5 @@ ``` | ||
```js | ||
var myLazyLoad = new LazyLoad(); | ||
var myLazyLoad = new LazyLoad({ | ||
elements_selector: ".lazy" | ||
}); | ||
``` | ||
@@ -102,2 +138,47 @@ | ||
### Videos | ||
> **When to use**: you want to lazily load videos using the `video` tag. | ||
HTML | ||
```html | ||
<video class="lazy" controls width="620" | ||
data-src="/your/video.mp4" poster="/your/poster.jpg"> | ||
<source type="video/mp4" data-src="/your/video.mp4"> | ||
<source type="video/ogg" data-src="/your/video.ogg"> | ||
<source type="video/avi" data-src="/your/video.avi"> | ||
</video> | ||
``` | ||
Javascript | ||
```js | ||
var myLazyLoad = new LazyLoad({ | ||
elements_selector: ".lazy" | ||
}); | ||
``` | ||
[DEMO](http://verlok.github.io/lazyload/demos/video.html) | [SOURCE](https://github.com/verlok/lazyload/blob/master/demos/video.html) | [API](#api) | ||
### Iframes | ||
> **When to use**: you want to lazily load `iframe`s. | ||
HTML | ||
```html | ||
<iframe class="lazy" data-src="https://some.page.com" frameborder="0"></iframe> | ||
``` | ||
Javascript | ||
```js | ||
var myLazyLoad = new LazyLoad({ | ||
elements_selector: ".lazy" | ||
}); | ||
``` | ||
[DEMO](http://verlok.github.io/lazyload/demos/iframes.html) | [SOURCE](https://github.com/verlok/lazyload/blob/master/demos/iframes.html) | [API](#api) | ||
### Async script + auto initialization | ||
@@ -137,3 +218,3 @@ | ||
Please note that if you put the script at the beginning of your HTML page, LazyLoad will be sometimes executed before the browser has loaded all the DOM. | ||
Please note that if you put the script at the beginning of your HTML page, LazyLoad will sometimes be executed before the browser has loaded all the DOM. | ||
In that case, you need to store the instance in a variable and use the `update` method on it. This will make it check the DOM again. See [API](#api). | ||
@@ -194,3 +275,3 @@ | ||
### Scolling panel | ||
### Scrolling panel | ||
@@ -316,3 +397,3 @@ > **When to use**: when your scrolling container is not the main browser window, but a scrolling container. | ||
> **When to use**: when you have a lot of scrolling containers in the page and you want to insantiate a LazyLoad only on the ones that are in the viewport. | ||
> **When to use**: when you have a lot of scrolling containers in the page and you want to instantiate a LazyLoad only on the ones that are in the viewport. | ||
@@ -412,3 +493,3 @@ HTML | ||
Images should be shown while they load, and not after, to give your users the best perceived performance. This is especially true if you use a progressive loading format like **progressive JPEG**. | ||
Images should be shown while they load, and not after, to give your users the best perceived performance. This is especially true if you use a progressive loading format like **Progressive JPEG**. | ||
@@ -426,4 +507,15 @@ In order to make your images visible as soon as LazyLoad sets the `src`/`srcset` attribute to it, you can either: | ||
Or do it using the **CSS classes** set by LazyLoad when loading starts - see [API](#api). | ||
Or instead of the above `:not()` selector do it using the **CSS classes** of `class_loading` and `class_loaded` set by LazyLoad when loading starts or is completed - see [API](#api). | ||
### Do NOT use placeholder images | ||
We do not recommend to use a placeholder image (like a transparent pixel GIF) in your HTML. | ||
* For **best perceived preformance, leave the `src` and `srcset` attributes blank**. Doing so, the image will be shown as soon as LazyLoad starts loading the image. See [this video](https://youtu.be/2E3ociaFJS0) or [this pen](https://codepen.io/verlok/pen/bKYggE?editors=0110) to test the difference (remember to disable the cache and to set a slower connection speed if you have a very fast one). | ||
* If you put anything in the src (like a transparent GIF), then LazyLoad starts loading the image but it won't be shown by browsers until the new image is loaded, leading to a **worse perceived performance**. | ||
It's safe not to put any value in the `src` nor `srcset` attributes, even if your HTML won't validate by a static code analyzer. The reason is that once JavaScript is executed, those values will be set by LazyLoad. For SEO, if the client is a crawler like Googlebot, it will be detected by LazyLoad which will fix the HTML. | ||
<!-- | ||
@@ -436,4 +528,42 @@ MOAR points to add to the README: | ||
### Dealing with Microsoft Edge problems | ||
According to what reported in #152, for Microsoft Edge to fire the IntersectionObserver for an `img` element, it must have a size. Since `img`s are displayed `inline-block` as standard, MS Edge (version not specified) doesn't read them correctly. | ||
By setting the following, edge is able to see the images and they get loaded. | ||
```css | ||
img[data-src], | ||
img[data-srcset] { | ||
display: block; | ||
min-height: 1px; | ||
} | ||
``` | ||
## API | ||
### Constructor arguments | ||
The `new LazyLoad()` instruction you execute on your page can take 2 parameters | ||
| Required | What to pass | Type | Default value | | ||
| -------- | ----------------------------------------------- | ------------ | ------------- | | ||
| No | The option object for this instance of LazyLoad | Plain Object | `{}` | | ||
| No | A NodeSet of elements to execute LazyLoad on | NodeSet | `null` | | ||
The most common usage of LazyLoad constructor is to pass only the options object (see "options" in the next section). For example: | ||
```js | ||
var lazyLoadOptions = { /* options here */ }; | ||
var aLazyLoad = new LazyLoad(lazyLoadOptions); | ||
``` | ||
In the rare cases where you can't or don't want to select the elements using `elements_selector` and you have a reference variable to your elements set (can be a NodeSet or an array of elements), you can pass the elements set as second parameter. | ||
```js | ||
var lazyLoadOptions = { /* options here */ }; | ||
var elementsToLazyLoad = getElementSetFromSomewhere(); | ||
var aLazyLoad = new LazyLoad(lazyLoadOptions, elementsToLazyLoad); | ||
``` | ||
### Options | ||
@@ -444,21 +574,18 @@ | ||
| Name | Meaning | Default value | | ||
| ---- | ----| ---- | | ||
| `container` | The scrolling container, and the container of the elements in the `elements_selector` option. | `window` | | ||
| `elements_selector` | The selector of the image elements inside the container, as descendants of the element in the `container` option | `"img"` | | ||
| `threshold` | The distance out of the viewport, expressed in pixel, before which to start loading the images | `300` | | ||
| `throttle` | The time that has to pass between one element parsing and the following, when fast scroll events occur | `150` | | ||
| `data_src` | The name of the data attribute containing the src image source, excluding the `data-`, e.g. if your data attribute is named `data-src`, just pass `src` | `"src"` | | ||
| `data_srcset` | The name of the data attribute containing the src image source set in either `img` and `source` tags. , e.g. if your data attribute is named `data-srcset`, just pass `srcset` | `"srcset"` | | ||
| `class_loading` | The class applied to the elements while the loading is in progress. | `"loading"` | | ||
| `class_loaded` | The class applied to the elements when the loading is complete | `"loaded"` | | ||
| `class_error` | The class applied to the elements when the element causes an error | `"error"` | | ||
| `class_initial` | The class applied to the first batch elements to be loaded in the page | `"initial"` | | ||
| `skip_invisible` | Specifies whether the script has to consider invisible images or not | `true` | | ||
| `callback_load` | A function to be called when an element was loaded. | `null` | | ||
| `callback_error` | A function to be called when an element triggers an error. | `null` | | ||
| `callback_set` | A function to be called when the src of an image is set in the DOM. | `null` | | ||
| `callback_processed` | A function to be called when an image was processed. | `null` | | ||
| Name | Meaning | Default value | | ||
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | | ||
| `container` | The scrolling container, and the container of the elements in the `elements_selector` option. | `document` | | ||
| `elements_selector` | The string selector of the elements to load lazily, to be selected as descendants of the `container` object. For multiple elements, you can add the css selectors for the same followed by a comma. E.g.: `'iframe, img, .container_class'`. This will lazy load images for iframe and img elements along with the images/background images under `'container_class'` | `"img"` | | ||
| `threshold` | The distance out of the viewport, expressed in pixel, before which to start loading the images | `300` | | ||
| `data_src` | The name of the data attribute containing the original image source, excluding the `"data-"` part. E.g. if your data attribute is named `"data-src"`, just pass `"src"` | `"src"` | | ||
| `data_srcset` | The name of the data attribute containing the original image source set in either `img` and `source` tags, excluding the `"data-"` part. E.g. if your data attribute is named `"data-original-set"`, just pass `"original-set"` | `"srcset"` | | ||
| `data_sizes` | The name of the data attribute containing the sizes attribute to use, excluding the `"data-"` part. E.g. if your data attribute is named `"data-sizes"`, just pass `"sizes"` | `"sizes"` | | ||
| `class_loading` | The class applied to the elements while the loading is in progress. | `"loading"` | | ||
| `class_loaded` | The class applied to the elements when the loading is complete | `"loaded"` | | ||
| `class_error` | The class applied to the elements when the element causes an error | `"error"` | | ||
| `callback_enter` | A function to be called when the DOM element enters the viewport. | `null` | | ||
| `callback_set` | A function to be called after the src of an image is set in the DOM. | `null` | | ||
| `callback_load` | A function to be called when an element was loaded. | `null` | | ||
| `callback_error` | A function to be called when an element triggers an error. | `null` | | ||
### Methods | ||
@@ -468,7 +595,8 @@ | ||
| Method name | Effect | | ||
|------------------|------------------------------------------------------------------------------------------------------| | ||
| `update()` | Tells _LazyLoad_ that new lazy images have arrived in the container, so it must start to manage them | | ||
| `destroy()` | Destroys the instance, unsetting instance variables and removing listeners. | | ||
| `handleScroll()` | A throttled scroll handler. This is called automatically from LazyLoad if the container element fires a `scroll` event, but it's exposed as a public method to allow you to use LazyLoad otherwise (i.g. when using iScroll) | | ||
| Method name | Effect | | ||
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| `update()` | Make LazyLoad to check for new lazy images in the container, using the `elements_selector` option. | | ||
| `loadAll()` | Loads all the lazy images right away, no matter if they are inside or outside the viewport. | | ||
| `load(element, force)` | Immediately loads any lazy `element`, even if it isn't selectable by the `elements_selector` option. Note that this method works only once on a specific `element`, unless you force it passing `true` as second parameter. | | ||
| `destroy()` | Destroys the instance, unsetting instance variables and removing listeners. | | ||
@@ -479,8 +607,4 @@ ## Notable features | ||
LazyLoad **doesn't hide your images from search engines**, even if you don't specify any initial `src` you your image. | ||
LazyLoad **doesn't hide your images from search engines**, even if you don't specify any initial `src` for your image. | ||
### Progressive JPEG support --> improve perceived performance | ||
[Progressive JPEG](http://blog.patrickmeenan.com/2013/06/progressive-jpegs-ftw.html) is an image format which is very good for perceived performance because it's rendered sooner, and refined in progressive passes. `LazyLoad` shows your images while they load, letting *progressive JPEG* do its magic. | ||
### It works with your favourite framework | ||
@@ -494,8 +618,12 @@ | ||
### Throttled execution for optimized CPU usage | ||
### Progressive JPEG support --> improve perceived performance | ||
_LazyLoad_'s listeners to the container's `scroll` and `resize` events are throttled by default, meaning that the main function of the script will not overload the CPU of devices with a smooth scroll. | ||
[Progressive JPEG](http://blog.patrickmeenan.com/2013/06/progressive-jpegs-ftw.html) is an image format which is very good for perceived performance because it's rendered sooner, and refined in progressive passes. `LazyLoad` shows your images while they load, letting *progressive JPEG* do its magic. | ||
### Intersection Observer API for optimized CPU usage | ||
Instead of listening to the `scroll` and `resize` events, LazyLoad uses the Intersection Observer API which is a new, blazing fast method to detect if an element is inside the browser viewport. Your users will see the difference in slow and even in fast devices or computers. | ||
### Much faster than jQuery\_lazyload | ||
This script is comparable to the notorious jQuery\_lazyload, but **_LazyLoad_ is 6x faster**, because LazyLoad uses only optimized, **native javascript** functions and methods, instead of jQuery. Your users will see the difference, even in slow devices or computers. | ||
This script is comparable to the notorious jQuery\_lazyload, but **_LazyLoad_ is 10x faster**, because LazyLoad uses only optimized, **native javascript** functions and methods, instead of jQuery. |
export const runningOnBrowser = typeof window !== "undefined"; | ||
export const supportsClassList = | ||
runningOnBrowser && "classList" in document.createElement("p"); | ||
export const isBot = | ||
(runningOnBrowser && !("onscroll" in window)) || | ||
/glebot|bingbot|crawler|spider|robot|crawling/i.test(navigator.userAgent); | ||
/(gle|ing|ro)bot|crawl|spider/i.test(navigator.userAgent); | ||
export const supportsClassList = | ||
runningOnBrowser && "classList" in document.createElement("p"); |
1051368
138
2107
612
5