flickity
Version:
Touch, responsive, flickable carousels
125 lines (102 loc) • 3.55 kB
JavaScript
// lazyload
( function( window, factory ) {
// universal module definition
if ( typeof module == 'object' && module.exports ) {
// CommonJS
module.exports = factory(
require('./core'),
require('fizzy-ui-utils'),
);
} else {
// browser global
factory(
window.Flickity,
window.fizzyUIUtils,
);
}
}( typeof window != 'undefined' ? window : this, function factory( Flickity, utils ) {
const lazyAttr = 'data-flickity-lazyload';
const lazySrcAttr = `${lazyAttr}-src`;
const lazySrcsetAttr = `${lazyAttr}-srcset`;
const imgSelector = `img[${lazyAttr}], img[${lazySrcAttr}], ` +
`img[${lazySrcsetAttr}], source[${lazySrcsetAttr}]`;
Flickity.create.lazyLoad = function() {
this.on( 'select', this.lazyLoad );
this.handleLazyLoadComplete = this.onLazyLoadComplete.bind( this );
};
let proto = Flickity.prototype;
proto.lazyLoad = function() {
let { lazyLoad } = this.options;
if ( !lazyLoad ) return;
// get adjacent cells, use lazyLoad option for adjacent count
let adjCount = typeof lazyLoad == 'number' ? lazyLoad : 0;
// lazy load images
this.getAdjacentCellElements( adjCount )
.map( getCellLazyImages )
.flat()
.forEach( ( img ) => new LazyLoader( img, this.handleLazyLoadComplete ) );
};
function getCellLazyImages( cellElem ) {
// check if cell element is lazy image
if ( cellElem.matches('img') ) {
let cellAttr = cellElem.getAttribute( lazyAttr );
let cellSrcAttr = cellElem.getAttribute( lazySrcAttr );
let cellSrcsetAttr = cellElem.getAttribute( lazySrcsetAttr );
if ( cellAttr || cellSrcAttr || cellSrcsetAttr ) {
return cellElem;
}
}
// select lazy images in cell
return [ ...cellElem.querySelectorAll( imgSelector ) ];
}
proto.onLazyLoadComplete = function( img, event ) {
let cell = this.getParentCell( img );
let cellElem = cell && cell.element;
this.cellSizeChange( cellElem );
this.dispatchEvent( 'lazyLoad', event, cellElem );
};
// -------------------------- LazyLoader -------------------------- //
/**
* class to handle loading images
* @param {Image} img - Image element
* @param {Function} onComplete - callback function
*/
function LazyLoader( img, onComplete ) {
this.img = img;
this.onComplete = onComplete;
this.load();
}
LazyLoader.prototype.handleEvent = utils.handleEvent;
LazyLoader.prototype.load = function() {
this.img.addEventListener( 'load', this );
this.img.addEventListener( 'error', this );
// get src & srcset
let src = this.img.getAttribute( lazyAttr ) ||
this.img.getAttribute( lazySrcAttr );
let srcset = this.img.getAttribute( lazySrcsetAttr );
// set src & serset
this.img.src = src;
if ( srcset ) this.img.setAttribute( 'srcset', srcset );
// remove attr
this.img.removeAttribute( lazyAttr );
this.img.removeAttribute( lazySrcAttr );
this.img.removeAttribute( lazySrcsetAttr );
};
LazyLoader.prototype.onload = function( event ) {
this.complete( event, 'flickity-lazyloaded' );
};
LazyLoader.prototype.onerror = function( event ) {
this.complete( event, 'flickity-lazyerror' );
};
LazyLoader.prototype.complete = function( event, className ) {
// unbind events
this.img.removeEventListener( 'load', this );
this.img.removeEventListener( 'error', this );
let mediaElem = this.img.parentNode.matches('picture') ? this.img.parentNode : this.img;
mediaElem.classList.add( className );
this.onComplete( this.img, event );
};
// ----- ----- //
Flickity.LazyLoader = LazyLoader;
return Flickity;
} ) );