npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@wezom/zz-load

v0.2.0-beta

Published

Lazy loader based on IntersectionObserver API

Downloads

34

Readme

zz-load

types BSD-3-Clause License badge NPM package badge Test and Build status badge

Lazy loader based on IntersectionObserver API

Live preview: https://wezomcompany.github.io/zz-load/

Coverage

| Statements | Branches | Functions | Lines | | --------------------------------------------------------------------- | ------------------------------------------------------------------- | -------------------------------------------------------------------- | ---------------------------------------------------------------- | | Statements | Branches | Functions | Lines |


Code-base features

🌟 Fully treeshackable
🌟 Types included
🌟 ESNext distribute
🌟 CommonJS version available


Table of Content:

  1. Usage
    1. Install npm package
    2. Import to your codebase
  2. Progressive Enhancement
  3. API
  4. Contributing
  5. License

Usage

Install npm package

npm i @wezom/zz-load

Import to your codebase

ESNext

We use TypeScript as main development language and distribute our lib in the maximum compliance with modern JavaScript specifications. You project bundler (webpack or something else) must not exclude this installed package from node_modules folder.

The package babel-loader-exclude-node-modules-except can help you with this

CommonJS Version

If you cannot change your bundler config or if you don not want to include esnext code version into your project - for this we have compiled CommonJS version of each library file and you can import *.cjs.js files. They ready to use without excluding node_modules and else. These files may have redundant code that is necessary for them to work "out of the box". And they will also be deprived of all the features of the ESNext specifications.

// no ES6 features but ready for use as is, without transpiling
import zzLoad from '@wezom/zz-load/dist/index.cjs';

Usage example

<img
    alt
    width="640"
    height="320"
    class="js-lazy-load"
    data-zzload-source-img="https://placeimg.com/640/320/nature"
    src='data:image/svg+xml,&lt;svg xmlns="http://www.w3.org/2000/svg" width="640" height="320"&gt;&lt;/svg&gt;'
/>
import zzLoad from '@wezom/zz-load';
// create and run observer for elements
const observer = zzLoad('.js-lazy-load');
observer.observe();

See in action https://wezomcompany.github.io/zz-load/

▲ Go Top | ▲ Table of Content


Progressive Enhancement

If you do not know what "Progressive Enhancement" is, watch this video from Heydon Pickering, we assure you you will not regret.

We have browsers that support Intersection Observer API, and browsers that do not support Intersection Observer API.
We can detect the feature and apply polyfill for API if needed.

An example:

// zz-load-init.js
import zzLoad from '@wezom/zz-load';
const observer = zzLoad('.js-lazy-load');
observer.observe();
// lazy-loading-progressive-enhancement.js
(function () {
    if ('IntersectionObserver' in window) {
        import('./zz-load-init');
    } else {
        import('intersection-observer').then(() => {
            import('./zz-load-init');
        });
    }
})();

Why I need to use zz-load when we have native loading attribute?

Not all browser support native loading!

If you want to make real "progressive enhancement" with browser native lazy loading as primary implementation - please consider next two circumstances:

  1. Not all cases can be covered with native loading
  2. You should be able to influence the template of your markup on the server.

Since the browser environment (for reliable verification) will not be available to you on the server - you can determine support of native loading baserd on the browser version by comparing with the table caniuse.com. Based on the result of the check, you can render the markup for native loading or markup for JavaScript implementation. After that, we need to extend our previous script

// lazy-loading-progressive-enhancement.js
(function () {
    const lazyLoadingElements = document.querySelectorAll('.js-lazy-load');
    // if render was for native loading implementation it should be empty
    // otherwise - initialize JS implemetation
    if (lazyLoadingElements.length > 0) {
        if ('IntersectionObserver' in window) {
            import('./zz-load-init');
        } else {
            import('intersection-observer').then(() => {
                import('./zz-load-init');
            });
        }
    }
})();

▲ Go Top | ▲ Table of Content


API

zzLoad()

zzLoad(elements: RootElement, options: Options = {}): Observer

type RootElement = string | Element | Element[] | NodeList | JQuery;

interface Options {
    rootMargin?: string;
    threshold?: number;
    clearSourceAttrs?: boolean;
    setSourcesOnlyOnLoad?: boolean;
    onProcess?(element: Element, resource?: string): void;
    onLoad?(element: Element, resource?: string): void;
    onError?(element: Element, resource?: string): void;
}

interface Observer {See `https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#Intersection_observer_options`
    observe(): void;
    triggerLoad(triggerElements: RootElement, triggerOptions?: Options): void;
}

Parameters:

Name | Data type | Argument | Default value | Description --- | --- | --- | --- | --- elements | string, Element, Element[], NodeList, JQuery | required | | String selector or already programmatically received Elements. You can give it even jQuery collection, if use it. options | Object | optional | undefined | Observing options options.rootMargin | string | | '0px' | Margin around the root. Can have values similar to the CSS margin property, e.g. "10px 20px 30px 40px" (top, right, bottom, left). The values can be percentages. This set of values serves to grow or shrink each side of the root element's bounding box before computing intersections. Defaults to all zeros. See Intersection observer options -> rootMargin options.threshold | number | | 0 | 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. If you only want to detect when visibility passes the 50% mark, you can use a value of 0.5. If you want the callback to run every time visibility passes another 25%, you would specify the array [0, 0.25, 0.5, 0.75, 1]. The default is 0 (meaning as soon as even one pixel is visible, the callback will be run). A value of 1.0 means that the threshold isn't considered passed until every pixel is visible. See Intersection observer options -> rootMargin options.setSourcesOnlyOnLoad | boolean | | true | Setting resource attributes to the element only after successful loading options.clearSourceAttrs | boolean | | false | Removing all zz-load source attributes from element after successful loading options.onProcess | Function | | undefined | Method called before starting to load resources for element. options.onLoad | Function | | undefined | Callback after successful after successful loading resources for element. options.onFail | Function | | undefined | Callback on error loading resources for element.

Return type: Observer

import zzLoad from '@wezom/zz-load';
const observer = zzLoad('.my-js-selector', {
    rootMargin: '0px 10%'
});

Observer.observe()

observe(): void;
import zzLoad from '@wezom/zz-load';
const observer = zzLoad('.my-js-selector', {
    rootMargin: '0px 10%'
});

// run observer
observer.observe();

Observer.triggerLoad()

triggerLoad(triggerElements: RootElement, triggerOptions?: Options): void;
import zzLoad from '@wezom/zz-load';
const observer = zzLoad('.my-js-selector', {
    rootMargin: '0px 10%'
});

// run observer
observer.observe();

// ..code conditions
observer.triggerLoad('#load-me-immediately-now');

Attrs NS

Library attributes namespace
See source

import zzLoad, { attrs } from '@wezom/zz-load';
const observer = zzLoad(`[${attrs.sourceImg}]`); // zzLoad('[data-zzload-source-img]')

Dataset NS

Library dataset namespace
See source

import zzLoad, { dataset } from '@wezom/zz-load';

const picture = document.querySelector('.my-picture-element');
if (picture !== null) {
    const sources = [
        {
            media: '(min-width: 1280px)',
            srcset: 'https://via.placeholder.com/1280x720/0000FF/000000'
        },
        {
            media: '(min-width: 750px)',
            srcset: 'https://via.placeholder.com/800x450/7878ff/000000'
        }
    ]
    picture.dataset[dataset.sourceSources] = JSON.stringify(sources);

    const observer = zzLoad(picture);
    observer.observe();
}

Events NS

Library events namespace.
See source

import zzLoad, { events } from '@wezom/zz-load';

const picture = document.querySelector('.my-picture-element');
if (picture !== null) {
    picture.addEventListener(events.observed, () => {
        console.log('Start observing');
    });
    picture.addEventListener(events.processed, () => {
        console.log('Start loading');
    });
    picture.addEventListener(events.loaded, () => {
        console.log('Successfully loaded');
    });
    picture.addEventListener(events.failed, () => {
        console.log('Loading failed');
    });
    picture.addEventListener(events.inView, (event) => {
        console.log('Element is visible', event.detail.visible);
    });
}

▲ Go Top | ▲ Table of Content


Contributing

Please fill free to create issues or send PR

Licence

BSD-3-Clause License