File "LazyLoad.ts"
Full path: /home/fsibplc/public_html/sommilito-bank2/splide-4.1.3/src/js/components/LazyLoad/LazyLoad.ts
File
size: 4.54 B (4.54 KB bytes)
MIME-type: text/x-java
Charset: utf-8
Download Open Edit Advanced Editor Back
import { CLASS_LOADING } from '../../constants/classes';
import {
EVENT_LAZYLOAD_LOADED,
EVENT_MOVED,
EVENT_REFRESH,
EVENT_RESIZE,
EVENT_SCROLLED,
} from '../../constants/events';
import { EventInterface } from '../../constructors';
import { Splide } from '../../core/Splide/Splide';
import { BaseComponent, Components, Options } from '../../types';
import {
addClass,
apply,
child,
create,
display,
empty,
getAttribute,
queryAll,
remove,
removeAttribute,
removeClass,
setAttribute,
} from '../../utils';
import { SlideComponent } from '../Slides/Slide';
import { IMAGE_SELECTOR, SRC_DATA_ATTRIBUTE, SRCSET_DATA_ATTRIBUTE } from './constants';
/**
* The interface for the LazyLoad component.
*
* @since 3.0.0
*/
export interface LazyLoadComponent extends BaseComponent {
/** @internal */
check(): void;
}
/**
* The type for each entry.
* Use a tuple for better compression.
*
* @since 4.0.0
*/
type LazyLoadEntry = [ HTMLImageElement, SlideComponent, HTMLSpanElement ];
/**
* The component for lazily loading images.
*
* @since 3.0.0
*
* @param Splide - A Splide instance.
* @param Components - A collection of components.
* @param options - Options.
*
* @return An LazyLoad component object.
*/
export function LazyLoad( Splide: Splide, Components: Components, options: Options ): LazyLoadComponent {
const { on, off, bind, emit } = EventInterface( Splide );
const isSequential = options.lazyLoad === 'sequential';
const events = [ EVENT_MOVED, EVENT_SCROLLED ];
/**
* Stores data of images.
*/
let entries: LazyLoadEntry[] = [];
/**
* Called when the component is mounted.
*/
function mount(): void {
if ( options.lazyLoad ) {
init();
on( EVENT_REFRESH, init );
}
}
/**
* Initializes the component and start loading images.
* Be aware that `refresh` also calls this method.
*/
function init() {
empty( entries );
register();
if ( isSequential ) {
loadNext();
} else {
off( events );
on( events, check );
check();
}
}
/**
* Finds images and register them as entries with creating spinner elements.
* Note that spinner can be already available because of `refresh()`.
*/
function register(): void {
Components.Slides.forEach( Slide => {
queryAll<HTMLImageElement>( Slide.slide, IMAGE_SELECTOR ).forEach( img => {
const src = getAttribute( img, SRC_DATA_ATTRIBUTE );
const srcset = getAttribute( img, SRCSET_DATA_ATTRIBUTE );
if ( src !== img.src || srcset !== img.srcset ) {
const className = options.classes.spinner;
const parent = img.parentElement;
const spinner = child( parent, `.${ className }` ) || create( 'span', className, parent );
entries.push( [ img, Slide, spinner ] );
img.src || display( img, 'none' );
}
} );
} );
}
/**
* Checks how close each image is from the active slide, and determines whether to start loading or not.
* The last `+1` is for the current page.
*/
function check(): void {
entries = entries.filter( data => {
const distance = options.perPage * ( ( options.preloadPages || 1 ) + 1 ) - 1;
return data[ 1 ].isWithin( Splide.index, distance ) ? load( data ) : true;
} );
entries.length || off( events );
}
/**
* Starts loading the image in the provided data.
*
* @param data - A LazyLoadEntry object.
*/
function load( data: LazyLoadEntry ): void {
const [ img ] = data;
addClass( data[ 1 ].slide, CLASS_LOADING );
bind( img, 'load error', apply( onLoad, data ) );
setAttribute( img, 'src', getAttribute( img, SRC_DATA_ATTRIBUTE ) );
setAttribute( img, 'srcset', getAttribute( img, SRCSET_DATA_ATTRIBUTE ) );
removeAttribute( img, SRC_DATA_ATTRIBUTE );
removeAttribute( img, SRCSET_DATA_ATTRIBUTE );
}
/**
* Called when the image is loaded or any error occurs.
*
* @param data - A LazyLoadEntry object.
* @param e - An Event object.
*/
function onLoad( data: LazyLoadEntry, e: Event ): void {
const [ img, Slide ] = data;
removeClass( Slide.slide, CLASS_LOADING );
if ( e.type !== 'error' ) {
remove( data[ 2 ] );
display( img, '' );
emit( EVENT_LAZYLOAD_LOADED, img, Slide );
emit( EVENT_RESIZE );
}
isSequential && loadNext();
}
/**
* Starts loading a next image.
*/
function loadNext(): void {
entries.length && load( entries.shift() );
}
return {
mount,
destroy: apply( empty, entries ),
check,
};
}