UNPKG

@trendster-io/ng-lazy-image

Version:

An Angular directive to efficiently lazy load images using the IntersectionObserver API.

188 lines (184 loc) 5 kB
import { Directive, ElementRef, Input, Output, HostBinding, EventEmitter, NgModule } from '@angular/core'; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ var LazyImageDirective = /** @class */ (function () { function LazyImageDirective(el) { this.el = el; this.willLoad = new EventEmitter(); this.decodingAttr = 'async'; } Object.defineProperty(LazyImageDirective.prototype, "visibilityStyle", { get: /** * @return {?} */ function () { return this.srcAttr ? 'visible' : 'hidden'; }, enumerable: true, configurable: true }); /** * @param {?} changes * @return {?} */ LazyImageDirective.prototype.ngOnChanges = /** * @param {?} changes * @return {?} */ function (changes) { if (changes.src && changes.src.currentValue) { this.addIO(); } }; /** * @return {?} */ LazyImageDirective.prototype.ngOnDestroy = /** * @return {?} */ function () { if (this.io) { this.removeIO(); } }; /** * @private * @return {?} */ LazyImageDirective.prototype.canLazyLoad = /** * @private * @return {?} */ function () { return typeof window !== 'undefined' && 'IntersectionObserver' in window; }; /** * @private * @return {?} */ LazyImageDirective.prototype.load = /** * @private * @return {?} */ function () { this.srcAttr = this.src; this.willLoad.emit(); }; /** * @private * @return {?} */ LazyImageDirective.prototype.lazyLoadImage = /** * @private * @return {?} */ function () { var _this = this; // Remove any previous observer if exists if (this.io) { this.removeIO(); } this.io = new IntersectionObserver((/** * @param {?} entry * @return {?} */ function (entry) { // because there will only ever be one instance // of the element we are observing // we can just use entry[0] if (entry[0].isIntersecting) { _this.load(); _this.removeIO(); } }), { root: this.root, rootMargin: this.rootMargin, threshold: this.threshold }); this.io.observe(this.el.nativeElement); }; /** * @private * @return {?} */ LazyImageDirective.prototype.loadImage = /** * @private * @return {?} */ function () { var _this = this; setTimeout((/** * @return {?} */ function () { return _this.load(); }), 200); }; /** * @private * @return {?} */ LazyImageDirective.prototype.addIO = /** * @private * @return {?} */ function () { // Check if window is defined to handle SSR, as well as check for IntersectionObserever support in the browser if (this.canLazyLoad()) { this.lazyLoadImage(); } else { // Fallback to setTimeout if IntersectionObserver-based lazy loading is not supported this.loadImage(); } }; /** * @private * @return {?} */ LazyImageDirective.prototype.removeIO = /** * @private * @return {?} */ function () { this.io.disconnect(); this.io = null; }; LazyImageDirective.decorators = [ { type: Directive, args: [{ selector: 'img[lazy]' },] } ]; /** @nocollapse */ LazyImageDirective.ctorParameters = function () { return [ { type: ElementRef } ]; }; LazyImageDirective.propDecorators = { src: [{ type: Input }], root: [{ type: Input }], rootMargin: [{ type: Input }], threshold: [{ type: Input }], willLoad: [{ type: Output }], srcAttr: [{ type: HostBinding, args: ['attr.src',] }], decodingAttr: [{ type: HostBinding, args: ['attr.decoding',] }], visibilityStyle: [{ type: HostBinding, args: ['style.visibility',] }] }; return LazyImageDirective; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ var LazyImageModule = /** @class */ (function () { function LazyImageModule() { } LazyImageModule.decorators = [ { type: NgModule, args: [{ declarations: [LazyImageDirective], exports: [LazyImageDirective] },] } ]; return LazyImageModule; }()); export { LazyImageDirective, LazyImageModule }; //# sourceMappingURL=trendster-io-ng-lazy-image.js.map