Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

yall-js

Package Overview
Dependencies
Maintainers
1
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

yall-js - npm Package Compare versions

Comparing version 2.2.2 to 2.3.0

223

dist/yall.js
'use strict';
/**
* yall.js version 2.2.2
* Yet Another Lazy loader
**/
function yall (options) {
if (!options) {
options = {};
}
// The eponymous function
function yall (userOptions) {
// Environmental stuff. Stores feature support information, as well as other
// stuff yall needs to refer to during operation.
const env = {
intersectionObserverSupport: "IntersectionObserver" in window && "IntersectionObserverEntry" in window && "intersectionRatio" in window.IntersectionObserverEntry.prototype,
mutationObserverSupport: "MutationObserver" in window,
idleCallbackSupport: "requestIdleCallback" in window,
eventsToBind: [
[document, "scroll"],
[document, "touchmove"],
[window, "resize"],
[window, "orientationchange"]
]
};
// Default options, merged with user options.
const options = {
lazyClass: "lazy",
lazyBackgroundClass: "lazy-bg",
lazyBackgroundLoaded: "lazy-bg-loaded",
throttleTime: 200,
idlyLoad: false,
idleLoadTimeout: 100,
threshold: 200,
observeChanges: false,
observeRootSelector: "body",
mutationObserverOptions: {
childList: true,
subtree: true
},
...userOptions
};
// CSS selector for all the lazy little elements.
const selectorString = `img.${options.lazyClass},video.${options.lazyClass},iframe.${options.lazyClass},.${options.lazyBackgroundClass}`;
// Options that get passed to requestIdleCallback
const intersectionObserverSupport = "IntersectionObserver" in window && "IntersectionObserverEntry" in window && "intersectionRatio" in window.IntersectionObserverEntry.prototype;
const idleCallbackSupport = "requestIdleCallback" in window;
const eventsToBind = [
[document, "scroll"],
[document, "touchmove"],
[window, "resize"],
[window, "orientationchange"]
];
const lazyClass = options.lazyClass || "lazy";
const lazyBackgroundClass = options.lazyBackgroundClass || "lazy-bg";
const idleLoadTimeout = options.idleLoadTimeout || 100;
const threshold = options.threshold || 200;
const observeChanges = options.observeChanges || false;
const selectorString = `img.${lazyClass},video.${lazyClass},iframe.${lazyClass},.${lazyBackgroundClass}`;
const dataAttrs = ["srcset", "src", "poster"];
const idleCallbackOptions = {
timeout: options.idleLoadTimeout
timeout: idleLoadTimeout
};
// This small abstraction saves a few bytes.
const sliceCall = arr => [].slice.call(arr);

@@ -56,37 +31,43 @@

const yallLoad = element => {
// Lazy load <img> elements
if (element.tagName === "IMG") {
let parentElement = element.parentNode;
switch (element.nodeName) {
case "IMG":
let parentElement = element.parentNode;
// Is the parent element a <picture>?
if (parentElement.tagName === "PICTURE") {
sliceCall(parentElement.querySelectorAll("source")).forEach(source => yallFlipDataAttrs(source));
}
// Is the parent element a <picture>?
if (parentElement.nodeName == "PICTURE") {
sliceCall(parentElement.querySelectorAll("source")).forEach(source => {
yallFlipDataAttrs(source);
});
}
yallFlipDataAttrs(element);
}
yallFlipDataAttrs(element);
// Lazy load <video> elements
if (element.tagName === "VIDEO") {
sliceCall(element.querySelectorAll("source")).forEach(source => yallFlipDataAttrs(source));
break;
// We didn't need this before, but with the addition of lazy loading
// `poster` images, we need to run the flip attributes function on the
// video element itself so we can trigger lazy loading behavior on those.
yallFlipDataAttrs(element);
case "VIDEO":
sliceCall(element.querySelectorAll("source")).forEach(source => {
yallFlipDataAttrs(source);
});
if (element.autoplay === true) {
element.load();
}
}
// We didn't need this before, but with the addition of lazy loading
// `poster` images, we need to run the flip attributes function on the
// video element itself so we can trigger lazy loading behavior on those.
yallFlipDataAttrs(element);
// Lazy load <iframe> elements
if (element.tagName === "IFRAME") {
yallFlipDataAttrs(element);
if (element.autoplay) {
element.load();
}
break;
case "IFRAME":
yallFlipDataAttrs(element);
break;
}
// Lazy load CSS background images
if (element.classList.contains(options.lazyBackgroundClass)) {
element.classList.remove(options.lazyBackgroundClass);
element.classList.add(options.lazyBackgroundLoaded);
if (element.classList.contains(lazyBackgroundClass)) {
element.classList.remove(lazyBackgroundClass);
element.classList.add(options.lazyBackgroundLoaded || "lazy-bg-loaded");
}

@@ -98,15 +79,7 @@ };

const yallFlipDataAttrs = element => {
// Do `srcset` first. Doing `src` first can cause loading of additional
// assets on Safari (and possibly other webkit browsers).
if (element.getAttribute("data-srcset") !== null) {
element.setAttribute("srcset", element.getAttribute("data-srcset"));
}
if (element.getAttribute("data-src") !== null) {
element.setAttribute("src", element.getAttribute("data-src"));
}
if (element.getAttribute("data-poster") !== null) {
element.setAttribute("poster", element.getAttribute("data-poster"));
}
dataAttrs.forEach(dataAttr => {
if (dataAttr in element.dataset) {
element[dataAttr] = element.dataset[dataAttr];
}
});
};

@@ -116,6 +89,6 @@

// (and other) event handlers to load images the "old" way.
const yallBack = function() {
const yallBack = () => {
let active = false;
if (active === false && lazyElements.length > 0) {
if (!active && lazyElements.length) {
active = true;

@@ -125,4 +98,4 @@

lazyElements.forEach(lazyElement => {
if (lazyElement.getBoundingClientRect().top <= (window.innerHeight + options.threshold) && lazyElement.getBoundingClientRect().bottom >= -(options.threshold) && getComputedStyle(lazyElement).display !== "none") {
if (options.idlyLoad === true && env.idleCallbackSupport === true) {
if (lazyElement.getBoundingClientRect().top <= (window.innerHeight + threshold) && lazyElement.getBoundingClientRect().bottom >= -threshold && getComputedStyle(lazyElement).display != "none") {
if (idleCallbackSupport && idleLoadTimeout) {
requestIdleCallback(() => {

@@ -135,4 +108,4 @@ yallLoad(lazyElement);

lazyElement.classList.remove(options.lazyClass);
lazyElements = lazyElements.filter(element => element !== lazyElement);
lazyElement.classList.remove(lazyClass);
lazyElements = lazyElements.filter(element => element != lazyElement);
}

@@ -143,6 +116,8 @@ });

if (lazyElements.length === 0 && options.observeChanges === false) {
env.eventsToBind.forEach(eventPair => eventPair[0].removeEventListener(eventPair[1], yallBack));
if (!lazyElements.length && !observeChanges) {
eventsToBind.forEach(eventPair => {
eventPair[0].removeEventListener(eventPair[1], yallBack);
});
}
}, options.throttleTime);
}, options.throttleTime || 200);
}

@@ -153,10 +128,22 @@ };

if (env.intersectionObserverSupport === true) {
// If the current user agent is a known crawler, immediately load all media
// for the elements yall is listening for and halt execution (good for SEO).
if (/(google|bing|yandex|duckduck)bot/i.test(navigator.userAgent)) {
lazyElements.forEach(lazyElement => {
yallLoad(lazyElement);
});
return;
}
if (intersectionObserverSupport) {
var intersectionListener = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting === true || entry.intersectionRatio > 0) {
if (entry.isIntersecting) {
let element = entry.target;
if (options.idlyLoad === true && env.idleCallbackSupport === true) {
requestIdleCallback(() => yallLoad(element), idleCallbackOptions);
if (idleCallbackSupport && idleLoadTimeout) {
requestIdleCallback(() => {
yallLoad(element);
}, idleCallbackOptions);
} else {

@@ -166,31 +153,41 @@ yallLoad(element);

element.classList.remove(options.lazyClass);
element.classList.remove(lazyClass);
observer.unobserve(element);
lazyElements = lazyElements.filter(lazyElement => lazyElement !== element);
lazyElements = lazyElements.filter(lazyElement => lazyElement != element);
}
});
}, {
rootMargin: `${options.threshold}px 0%`
rootMargin: `${threshold}px 0%`
});
lazyElements.forEach(lazyElement => intersectionListener.observe(lazyElement));
lazyElements.forEach(lazyElement => {
intersectionListener.observe(lazyElement);
});
} else {
env.eventsToBind.forEach(eventPair => eventPair[0].addEventListener(eventPair[1], yallBack));
eventsToBind.forEach(eventPair => {
eventPair[0].addEventListener(eventPair[1], yallBack);
});
yallBack();
}
if (env.mutationObserverSupport === true && options.observeChanges === true) {
new MutationObserver(mutations => mutations.forEach(() => {
sliceCall(document.querySelectorAll(selectorString)).forEach(newElement => {
if (lazyElements.indexOf(newElement) === -1) {
lazyElements.push(newElement);
if ("MutationObserver" in window && observeChanges) {
new MutationObserver(mutations => {
mutations.forEach(() => {
sliceCall(document.querySelectorAll(selectorString)).forEach(newElement => {
if (lazyElements.indexOf(newElement) == -1) {
lazyElements.push(newElement);
if (env.intersectionObserverSupport === true) {
intersectionListener.observe(newElement);
} else {
yallBack();
if (intersectionObserverSupport) {
intersectionListener.observe(newElement);
} else {
yallBack();
}
}
}
});
});
})).observe(document.querySelector(options.observeRootSelector), options.mutationObserverOptions);
}).observe(document.querySelector(options.observeRootSelector || "body"), options.mutationObserverOptions || {
childList: true,
subtree: true
});
}

@@ -197,0 +194,0 @@ }

@@ -1,2 +0,2 @@

/* yall.js v2.2.2 */
var yall=function(){"use strict";function _extends(){return(_extends=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(e[n]=r[n])}return e}).apply(this,arguments)}return function(e){var t={intersectionObserverSupport:"IntersectionObserver"in window&&"IntersectionObserverEntry"in window&&"intersectionRatio"in window.IntersectionObserverEntry.prototype,mutationObserverSupport:"MutationObserver"in window,idleCallbackSupport:"requestIdleCallback"in window,eventsToBind:[[document,"scroll"],[document,"touchmove"],[window,"resize"],[window,"orientationchange"]]},r=_extends({lazyClass:"lazy",lazyBackgroundClass:"lazy-bg",lazyBackgroundLoaded:"lazy-bg-loaded",throttleTime:200,idlyLoad:!1,idleLoadTimeout:100,threshold:200,observeChanges:!1,observeRootSelector:"body",mutationObserverOptions:{childList:!0,subtree:!0}},e),n="img."+r.lazyClass+",video."+r.lazyClass+",iframe."+r.lazyClass+",."+r.lazyBackgroundClass,o={timeout:r.idleLoadTimeout},a=function(e){return[].slice.call(e)},i=function(e){if("IMG"===e.tagName){var t=e.parentNode;"PICTURE"===t.tagName&&a(t.querySelectorAll("source")).forEach(function(e){return s(e)}),s(e)}"VIDEO"===e.tagName&&(a(e.querySelectorAll("source")).forEach(function(e){return s(e)}),s(e),!0===e.autoplay&&e.load()),"IFRAME"===e.tagName&&s(e),e.classList.contains(r.lazyBackgroundClass)&&(e.classList.remove(r.lazyBackgroundClass),e.classList.add(r.lazyBackgroundLoaded))},s=function(e){null!==e.getAttribute("data-srcset")&&e.setAttribute("srcset",e.getAttribute("data-srcset")),null!==e.getAttribute("data-src")&&e.setAttribute("src",e.getAttribute("data-src")),null!==e.getAttribute("data-poster")&&e.setAttribute("poster",e.getAttribute("data-poster"))},l=function yallBack(){var e=!1;!1===e&&u.length>0&&(e=!0,setTimeout(function(){u.forEach(function(e){e.getBoundingClientRect().top<=window.innerHeight+r.threshold&&e.getBoundingClientRect().bottom>=-r.threshold&&"none"!==getComputedStyle(e).display&&(!0===r.idlyLoad&&!0===t.idleCallbackSupport?requestIdleCallback(function(){i(e)},o):i(e),e.classList.remove(r.lazyClass),u=u.filter(function(t){return t!==e}))}),e=!1,0===u.length&&!1===r.observeChanges&&t.eventsToBind.forEach(function(e){return e[0].removeEventListener(e[1],yallBack)})},r.throttleTime))},u=a(document.querySelectorAll(n));if(!0===t.intersectionObserverSupport){var c=new IntersectionObserver(function(e,n){e.forEach(function(e){if(!0===e.isIntersecting||e.intersectionRatio>0){var a=e.target;!0===r.idlyLoad&&!0===t.idleCallbackSupport?requestIdleCallback(function(){return i(a)},o):i(a),a.classList.remove(r.lazyClass),n.unobserve(a),u=u.filter(function(e){return e!==a})}})},{rootMargin:r.threshold+"px 0%"});u.forEach(function(e){return c.observe(e)})}else t.eventsToBind.forEach(function(e){return e[0].addEventListener(e[1],l)}),l();!0===t.mutationObserverSupport&&!0===r.observeChanges&&new MutationObserver(function(e){return e.forEach(function(){a(document.querySelectorAll(n)).forEach(function(e){-1===u.indexOf(e)&&(u.push(e),!0===t.intersectionObserverSupport?c.observe(e):l())})})}).observe(document.querySelector(r.observeRootSelector),r.mutationObserverOptions)}}();
/*yall.js 2.3.0*/
var yall=function(){"use strict";return function(e){e||(e={});var t="IntersectionObserver"in window&&"IntersectionObserverEntry"in window&&"intersectionRatio"in window.IntersectionObserverEntry.prototype,n="requestIdleCallback"in window,o=[[document,"scroll"],[document,"touchmove"],[window,"resize"],[window,"orientationchange"]],r=e.lazyClass||"lazy",i=e.lazyBackgroundClass||"lazy-bg",c=e.idleLoadTimeout||100,a=e.threshold||200,s=e.observeChanges||!1,l="img."+r+",video."+r+",iframe."+r+",."+i,u=["srcset","src","poster"],d={timeout:c},f=function(e){return[].slice.call(e)},v=function(t){switch(t.nodeName){case"IMG":var n=t.parentNode;"PICTURE"==n.nodeName&&f(n.querySelectorAll("source")).forEach(function(e){b(e)}),b(t);break;case"VIDEO":f(t.querySelectorAll("source")).forEach(function(e){b(e)}),b(t),t.autoplay&&t.load();break;case"IFRAME":b(t)}t.classList.contains(i)&&(t.classList.remove(i),t.classList.add(e.lazyBackgroundLoaded||"lazy-bg-loaded"))},b=function(e){u.forEach(function(t){t in e.dataset&&(e[t]=e.dataset[t])})},g=function yallBack(){var t=!1;!t&&h.length&&(t=!0,setTimeout(function(){h.forEach(function(e){e.getBoundingClientRect().top<=window.innerHeight+a&&e.getBoundingClientRect().bottom>=-a&&"none"!=getComputedStyle(e).display&&(n&&c?requestIdleCallback(function(){v(e)},d):v(e),e.classList.remove(r),h=h.filter(function(t){return t!=e}))}),t=!1,h.length||s||o.forEach(function(e){e[0].removeEventListener(e[1],yallBack)})},e.throttleTime||200))},h=f(document.querySelectorAll(l));if(/(google|bing|yandex|duckduck)bot/i.test(navigator.userAgent))h.forEach(function(e){v(e)});else{if(t){var m=new IntersectionObserver(function(e,t){e.forEach(function(e){if(e.isIntersecting){var o=e.target;n&&c?requestIdleCallback(function(){v(o)},d):v(o),o.classList.remove(r),t.unobserve(o),h=h.filter(function(e){return e!=o})}})},{rootMargin:a+"px 0%"});h.forEach(function(e){m.observe(e)})}else o.forEach(function(e){e[0].addEventListener(e[1],g)}),g();"MutationObserver"in window&&s&&new MutationObserver(function(e){e.forEach(function(){f(document.querySelectorAll(l)).forEach(function(e){-1==h.indexOf(e)&&(h.push(e),t?m.observe(e):g())})})}).observe(document.querySelector(e.observeRootSelector||"body"),e.mutationObserverOptions||{childList:!0,subtree:!0})}}}();
{
"name": "yall-js",
"version": "2.2.2",
"version": "2.3.0",
"description": "Yet Another Lazy Loader",
"main": "./dist/yall.js",
"module": "./src/yall.mjs",
"jsnext:main": "./src/yall.mjs",
"scripts": {

@@ -15,3 +16,3 @@ "clean": "npx rimraf ./dist",

"type": "git",
"urnl": "git+ssh://git@github.com/malchata/yall.js.git"
"url": "git+ssh://git@github.com/malchata/yall.js.git"
},

@@ -34,9 +35,9 @@ "keywords": [

"@babel/cli": "^7.2.3",
"@babel/core": "^7.2.2",
"@babel/plugin-proposal-object-rest-spread": "^7.3.2",
"@babel/preset-env": "^7.3.1",
"eslint": "^5.13.0",
"@babel/core": "^7.3.4",
"@babel/plugin-proposal-object-rest-spread": "^7.3.4",
"@babel/preset-env": "^7.3.4",
"eslint": "^5.15.2",
"express": "^4.16.4",
"rimraf": "^2.6.3",
"rollup": "^1.1.2",
"rollup": "^1.6.0",
"rollup-plugin-babel": "^4.3.2",

@@ -43,0 +44,0 @@ "rollup-plugin-copy": "^0.2.3",

# yall.js (Yet Another Lazy Loader)
[![Build Status](https://travis-ci.org/malchata/yall.js.svg?branch=master)](https://travis-ci.org/malchata/yall.js) ![](https://img.badgesize.io/malchata/yall.js/master/dist/yall.min.js?label=Uncompressed) ![](https://img.badgesize.io/malchata/yall.js/master/dist/yall.min.js?compression=gzip&label=gzip) ![](https://img.badgesize.io/malchata/yall.js/master/dist/yall.min.js?compression=brotli&label=brotli)
<p align="center">
<strong>ES5 (.js) version</strong>
</p>
<p align="center">
<img src="https://img.badgesize.io/malchata/yall.js/master/dist/yall.min.js?label=Uncompressed" alt="Uncompressed size.">&nbsp;<img src="https://img.badgesize.io/malchata/yall.js/master/dist/yall.min.js?compression=gzip&label=gzip" alt="gzip size.">&nbsp;<img src="https://img.badgesize.io/malchata/yall.js/master/dist/yall.min.js?compression=brotli&label=brotli" alt="Brotli size.">
</p>
<p align="center">
<strong>ES6 (.mjs) version</strong>
</p>
<p align="center">
<img src="https://img.badgesize.io/malchata/yall.js/master/dist/yall.min.mjs?label=Uncompressed" alt="Uncompressed size.">&nbsp;<img src="https://img.badgesize.io/malchata/yall.js/master/dist/yall.min.mjs?compression=gzip&label=gzip" alt="gzip size.">&nbsp;<img src="https://img.badgesize.io/malchata/yall.js/master/dist/yall.min.mjs?compression=brotli&label=brotli" alt="Brotli size.">
</p>
yall.js is a featured-packed script that lazy loads content for `<img>`, `<picture>`, `<video>` and `<iframe>` elements, and can also lazy load CSS background images. It works in all modern browsers including IE11. It uses [Intersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) where available, but falls back to `scroll`, `touchmove`, `resize`, and `orientationchange` events where necessary. It can also monitor the DOM for changes using [Mutation Observer](https://hacks.mozilla.org/2012/05/dom-mutationobserver-reacting-to-dom-changes-without-killing-browser-performance/) to lazy load media elements that have been appended to the DOM after initial page render, which may be desirable for single page applications. It can also (optionally) optimize use of browser idle time using [`requestIdleCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback).
yall.js is a featured-packed SEO-friendly lazy loader for `<img>`, `<picture>`, `<video>` and `<iframe>` elements, and can also lazy load CSS background images. It works in all modern browsers as well as IE11. It uses [Intersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) where available, but falls back to `scroll`, `touchmove`, `resize`, and `orientationchange` events where necessary. It can also monitor the DOM for changes using [Mutation Observer](https://hacks.mozilla.org/2012/05/dom-mutationobserver-reacting-to-dom-changes-without-killing-browser-performance/) to lazy load media elements that have been appended to the DOM after initial page render, which may be desirable for single page applications. It can also (optionally) optimize use of browser idle time using [`requestIdleCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback).

@@ -204,4 +215,3 @@ While yall.js has only been offered in the past as a drop-in script, it's now installable as an npm package:

- `throttleTime` (default: `200`): In cases where Intersection Observer isn't available, standard event handlers are used. `throttleTime` allows you to control how often the code within these event handlers fire in milliseconds.
- `idlyLoad` (default: `false`): If set to `true`, `requestIdleCallback` is used to optimize use of browser idle time to limit monopolization of the main thread. _**Notes:** This setting is ignored if set to `true` in a browser that doesn't support `requestIdleCallback`! Additionally, enabling this could cause lazy loading to be delayed significantly more than you might be okay with! This option trades off some degree of seamless lazy loading in favor of optimized use of browser idle time. Test extensively, and consider increasing the `threshold` option if you set this option to `true`!_
- `idleLoadTimeout` (default: `100`): If `idlyLoad` is set to `true`, this option sets a deadline in milliseconds for `requestIdleCallback` to kick off lazy loading for an element.
- `idleLoadTimeout` (default: `100`): In environments where `requestIdleCallback` is available, this option sets a deadline in milliseconds for `requestIdleCallback` to kick off lazy loading for an element. If this option is set to `0`, `requestIdleCallback` is never called, and lazy loading for the affected element(s) will begin immediately once they're in the viewport.
- `threshold` (default: `200`): The threshold (in pixels) for how far elements need to be within the viewport to begin lazy loading.

@@ -212,5 +222,5 @@ - `observeChanges` (default: `false`): Use a Mutation Observer to examine the DOM for changes. This is useful if you're using yall.js in a single page application and want to lazy load resources for markup injected into the page after initial page render. _**Note:** This option is ignored if set to `true` in a browser that doesn't support Mutation Observer!_

## Words of wisdom
## Words of advice
yall.js doesn't care about placeholders, and won't try to minimize layout shifting for you. Use appropriate `width` and `height` attributes on elements, as well as lightweight placeholders
It is not yall.js's job to minimize layout shifting for you. Use appropriate `width` and `height` attributes on elements, as well as lightweight placeholders for your images.

@@ -217,0 +227,0 @@ In the case of `<video>`, avoid lazy loading a placeholder with the `data-poster` attribute for autoplaying videos and just use `poster`. On the other hand _do_ consider lazy loading a placeholder image with `data-poster` for non-autoplaying videos.

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc