Create New Item
×
Item Type
File
Folder
Item Name
×
Search file in folder and subfolders...
File Manager
/
sommilito-bank2
/
splide-4.1.3
/
src
/
js
/
components
/
LazyLoad
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
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, }; }