UNPKG

@trademe/ng-defer-load

Version:

Angular directive to load elements lazily

127 lines 16.8 kB
import { isPlatformBrowser, isPlatformServer } from '@angular/common'; import { Directive, EventEmitter, Inject, Input, Output, PLATFORM_ID } from '@angular/core'; import { fromEvent } from 'rxjs'; import { debounceTime } from 'rxjs/operators'; import * as i0 from "@angular/core"; export class DeferLoadDirective { constructor(_element, _zone, platformId) { this._element = _element; this._zone = _zone; this.platformId = platformId; this.preRender = true; this.fallbackEnabled = true; this.removeListenersAfterLoad = true; this.deferLoad = new EventEmitter(); this.checkForIntersection = (entries) => { entries.forEach((entry) => { if (this.checkIfIntersecting(entry)) { this.load(); if (this._intersectionObserver && this._element.nativeElement) { this._intersectionObserver.unobserve((this._element.nativeElement)); } } }); }; this.onScroll = () => { if (this.isVisible()) { this._zone.run(() => this.load()); } }; } ngOnInit() { if ((isPlatformServer(this.platformId) && this.preRender) || (isPlatformBrowser(this.platformId) && !this.fallbackEnabled && !this.hasCompatibleBrowser())) { this.load(); } } ngAfterViewInit() { if (isPlatformBrowser(this.platformId)) { if (this.hasCompatibleBrowser()) { this.registerIntersectionObserver(); if (this._intersectionObserver && this._element.nativeElement) { this._intersectionObserver.observe((this._element.nativeElement)); } } else if (this.fallbackEnabled) { this.addScrollListeners(); } } } hasCompatibleBrowser() { const hasIntersectionObserver = 'IntersectionObserver' in window; const userAgent = window.navigator.userAgent; const matches = userAgent.match(/Edge\/(\d*)\./i); const isEdge = !!matches && matches.length > 1; const isEdgeVersion16OrBetter = isEdge && (!!matches && parseInt(matches[1], 10) > 15); return hasIntersectionObserver && (!isEdge || isEdgeVersion16OrBetter); } ngOnDestroy() { this.removeListeners(); } registerIntersectionObserver() { if (!!this._intersectionObserver) { return; } this._intersectionObserver = new IntersectionObserver(entries => { this.checkForIntersection(entries); }, {}); } checkIfIntersecting(entry) { // For Samsung native browser, IO has been partially implemented whereby the // callback fires, but entry object is empty. We will check manually. if (entry && entry.time) { return entry.isIntersecting && entry.target === this._element.nativeElement; } return this.isVisible(); } load() { if (this.removeListenersAfterLoad) { this.removeListeners(); } this.deferLoad.emit(); } addScrollListeners() { if (this.isVisible()) { this.load(); return; } this._zone.runOutsideAngular(() => { this._scrollSubscription = fromEvent(window, 'scroll') .pipe(debounceTime(50)) .subscribe(this.onScroll); }); } removeListeners() { this._scrollSubscription?.unsubscribe(); this._intersectionObserver?.disconnect(); } isVisible() { let scrollPosition = this.getScrollPosition(); let elementOffset = this._element.nativeElement.getBoundingClientRect().top + window.scrollY; return elementOffset <= scrollPosition; } getScrollPosition() { // Getting screen size and scroll position for IE return window.scrollY + (document.documentElement.clientHeight || document.body.clientHeight); } } DeferLoadDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: DeferLoadDirective, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Directive }); DeferLoadDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.2.12", type: DeferLoadDirective, selector: "[deferLoad]", inputs: { preRender: "preRender", fallbackEnabled: "fallbackEnabled", removeListenersAfterLoad: "removeListenersAfterLoad" }, outputs: { deferLoad: "deferLoad" }, ngImport: i0 }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: DeferLoadDirective, decorators: [{ type: Directive, args: [{ selector: '[deferLoad]' }] }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.NgZone }, { type: Object, decorators: [{ type: Inject, args: [PLATFORM_ID] }] }]; }, propDecorators: { preRender: [{ type: Input }], fallbackEnabled: [{ type: Input }], removeListenersAfterLoad: [{ type: Input }], deferLoad: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVmZXItbG9hZC5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZGVmZXItbG9hZC5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGlCQUFpQixFQUFFLGdCQUFnQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDdEUsT0FBTyxFQUFpQixTQUFTLEVBQWMsWUFBWSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQTZCLE1BQU0sRUFBRSxXQUFXLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDbEosT0FBTyxFQUFFLFNBQVMsRUFBZ0IsTUFBTSxNQUFNLENBQUM7QUFDL0MsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGdCQUFnQixDQUFDOztBQUs5QyxNQUFNLE9BQU8sa0JBQWtCO0lBVTNCLFlBQ1ksUUFBb0IsRUFDcEIsS0FBYSxFQUNRLFVBQWtCO1FBRnZDLGFBQVEsR0FBUixRQUFRLENBQVk7UUFDcEIsVUFBSyxHQUFMLEtBQUssQ0FBUTtRQUNRLGVBQVUsR0FBVixVQUFVLENBQVE7UUFYbkMsY0FBUyxHQUFZLElBQUksQ0FBQztRQUMxQixvQkFBZSxHQUFZLElBQUksQ0FBQztRQUNoQyw2QkFBd0IsR0FBWSxJQUFJLENBQUM7UUFDeEMsY0FBUyxHQUFzQixJQUFJLFlBQVksRUFBRSxDQUFDO1FBdUQzRCx5QkFBb0IsR0FBRyxDQUFDLE9BQXlDLEVBQUUsRUFBRTtZQUN6RSxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsS0FBZ0MsRUFBRSxFQUFFO2dCQUNqRCxJQUFJLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxLQUFLLENBQUMsRUFBRTtvQkFDakMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO29CQUNaLElBQUksSUFBSSxDQUFDLHFCQUFxQixJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxFQUFFO3dCQUMzRCxJQUFJLENBQUMscUJBQXFCLENBQUMsU0FBUyxDQUFVLENBQUMs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YWYsV0FBVztvR0FiZCxrQkFBa0I7NEZBQWxCLGtCQUFrQjtrQkFIOUIsU0FBUzttQkFBQztvQkFDUCxRQUFRLEVBQUUsYUFBYTtpQkFDMUI7OzBCQWNRLE1BQU07MkJBQUMsV0FBVzs0Q0FYUCxTQUFTO3NCQUF4QixLQUFLO2dCQUNVLGVBQWU7c0JBQTlCLEtBQUs7Z0JBQ1Usd0JBQXdCO3NCQUF2QyxLQUFLO2dCQUNXLFNBQVM7c0JBQXpCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBpc1BsYXRmb3JtQnJvd3NlciwgaXNQbGF0Zm9ybVNlcnZlciB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBBZnRlclZpZXdJbml0LCBEaXJlY3RpdmUsIEVsZW1lbnRSZWYsIEV2ZW50RW1pdHRlciwgSW5qZWN0LCBJbnB1dCwgTmdab25lLCBPbkRlc3Ryb3ksIE9uSW5pdCwgT3V0cHV0LCBQTEFURk9STV9JRCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgZnJvbUV2ZW50LCBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGRlYm91bmNlVGltZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuQERpcmVjdGl2ZSh7XG4gICAgc2VsZWN0b3I6ICdbZGVmZXJMb2FkXSdcbn0pXG5leHBvcnQgY2xhc3MgRGVmZXJMb2FkRGlyZWN0aXZlIGltcGxlbWVudHMgT25Jbml0LCBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3kge1xuXG4gICAgQElucHV0KCkgcHVibGljIHByZVJlbmRlcjogYm9vbGVhbiA9IHRydWU7XG4gICAgQElucHV0KCkgcHVibGljIGZhbGxiYWNrRW5hYmxlZDogYm9vbGVhbiA9IHRydWU7XG4gICAgQElucHV0KCkgcHVibGljIHJlbW92ZUxpc3RlbmVyc0FmdGVyTG9hZDogYm9vbGVhbiA9IHRydWU7XG4gICAgQE91dHB1dCgpIHB1YmxpYyBkZWZlckxvYWQ6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gICAgcHJpdmF0ZSBfaW50ZXJzZWN0aW9uT2JzZXJ2ZXI/OiBJbnRlcnNlY3Rpb25PYnNlcnZlcjtcbiAgICBwcml2YXRlIF9zY3JvbGxTdWJzY3JpcHRpb24/OiBTdWJzY3JpcHRpb247XG5cbiAgICBjb25zdHJ1Y3RvciAoXG4gICAgICAgIHByaXZhdGUgX2VsZW1lbnQ6IEVsZW1lbnRSZWYsXG4gICAgICAgIHByaXZhdGUgX3pvbmU6IE5nWm9uZSxcbiAgICAgICAgQEluamVjdChQTEFURk9STV9JRCkgcHJpdmF0ZSBwbGF0Zm9ybUlkOiBPYmplY3RcbiAgICApIHsgfVxuXG4gICAgcHVibGljIG5nT25Jbml0ICgpIHtcbiAgICAgICAgaWYgKChpc1BsYXRmb3JtU2VydmVyKHRoaXMucGxhdGZvcm1JZCkgJiYgdGhpcy5wcmVSZW5kZXIpXG4gICAgICAgICAgICB8fCAoaXNQbGF0Zm9ybUJyb3dzZXIodGhpcy5wbGF0Zm9ybUlkKSAmJiAhdGhpcy5mYWxsYmFja0VuYWJsZWQgJiYgIXRoaXMuaGFzQ29tcGF0aWJsZUJyb3dzZXIoKSkpIHtcbiAgICAgICAgICAgIHRoaXMubG9hZCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIG5nQWZ0ZXJWaWV3SW5pdCAoKSB7XG4gICAgICAgIGlmIChpc1BsYXRmb3JtQnJvd3Nlcih0aGlzLnBsYXRmb3JtSWQpKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5oYXNDb21wYXRpYmxlQnJvd3NlcigpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWdpc3RlckludGVyc2VjdGlvbk9ic2VydmVyKCk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX2ludGVyc2VjdGlvbk9ic2VydmVyICYmIHRoaXMuX2VsZW1lbnQubmF0aXZlRWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9pbnRlcnNlY3Rpb25PYnNlcnZlci5vYnNlcnZlKDxFbGVtZW50Pih0aGlzLl9lbGVtZW50Lm5hdGl2ZUVsZW1lbnQpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZmFsbGJhY2tFbmFibGVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRTY3JvbGxMaXN0ZW5lcnMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBoYXNDb21wYXRpYmxlQnJvd3NlciAoKTogYm9vbGVhbiB7XG4gICAgICAgIGNvbnN0IGhhc0ludGVyc2VjdGlvbk9ic2VydmVyID0gJ0ludGVyc2VjdGlvbk9ic2VydmVyJyBpbiB3aW5kb3c7XG4gICAgICAgIGNvbnN0IHVzZXJBZ2VudCA9IHdpbmRvdy5uYXZpZ2F0b3IudXNlckFnZW50O1xuICAgICAgICBjb25zdCBtYXRjaGVzID0gdXNlckFnZW50Lm1hdGNoKC9FZGdlXFwvKFxcZCopXFwuL2kpO1xuXG4gICAgICAgIGNvbnN0IGlzRWRnZSA9ICEhbWF0Y2hlcyAmJiBtYXRjaGVzLmxlbmd0aCA+IDE7XG4gICAgICAgIGNvbnN0IGlzRWRnZVZlcnNpb24xNk9yQmV0dGVyID0gaXNFZGdlICYmICghIW1hdGNoZXMgJiYgcGFyc2VJbnQobWF0Y2hlc1sxXSwgMTApID4gMTUpO1xuXG4gICAgICAgIHJldHVybiBoYXNJbnRlcnNlY3Rpb25PYnNlcnZlciAmJiAoIWlzRWRnZSB8fCBpc0VkZ2VWZXJzaW9uMTZPckJldHRlcik7XG4gICAgfVxuXG4gICAgcHVibGljIG5nT25EZXN0cm95ICgpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcnMoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHJlZ2lzdGVySW50ZXJzZWN0aW9uT2JzZXJ2ZXIgKCk6IHZvaWQge1xuICAgICAgICBpZiAoISF0aGlzLl9pbnRlcnNlY3Rpb25PYnNlcnZlcikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2ludGVyc2VjdGlvbk9ic2VydmVyID0gbmV3IEludGVyc2VjdGlvbk9ic2VydmVyKGVudHJpZXMgPT4ge1xuICAgICAgICAgICAgdGhpcy5jaGVja0ZvckludGVyc2VjdGlvbihlbnRyaWVzKTtcbiAgICAgICAgfSwge30pO1xuICAgIH1cblxuICAgIHByaXZhdGUgY2hlY2tGb3JJbnRlcnNlY3Rpb24gPSAoZW50cmllczogQXJyYXk8SW50ZXJzZWN0aW9uT2JzZXJ2ZXJFbnRyeT4pID0+IHtcbiAgICAgICAgZW50cmllcy5mb3JFYWNoKChlbnRyeTogSW50ZXJzZWN0aW9uT2JzZXJ2ZXJFbnRyeSkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuY2hlY2tJZkludGVyc2VjdGluZyhlbnRyeSkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvYWQoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5faW50ZXJzZWN0aW9uT2JzZXJ2ZXIgJiYgdGhpcy5fZWxlbWVudC5uYXRpdmVFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2ludGVyc2VjdGlvbk9ic2VydmVyLnVub2JzZXJ2ZSg8RWxlbWVudD4odGhpcy5fZWxlbWVudC5uYXRpdmVFbGVtZW50KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNoZWNrSWZJbnRlcnNlY3RpbmcgKGVudHJ5OiBJbnRlcnNlY3Rpb25PYnNlcnZlckVudHJ5KSB7XG4gICAgICAgIC8vIEZvciBTYW1zdW5nIG5hdGl2ZSBicm93c2VyLCBJTyBoYXMgYmVlbiBwYXJ0aWFsbHkgaW1wbGVtZW50ZWQgd2hlcmVieSB0aGVcbiAgICAgICAgLy8gY2FsbGJhY2sgZmlyZXMsIGJ1dCBlbnRyeSBvYmplY3QgaXMgZW1wdHkuIFdlIHdpbGwgY2hlY2sgbWFudWFsbHkuXG4gICAgICAgIGlmIChlbnRyeSAmJiBlbnRyeS50aW1lKSB7XG4gICAgICAgICAgICByZXR1cm4gZW50cnkuaXNJbnRlcnNlY3RpbmcgJiYgZW50cnkudGFyZ2V0ID09PSB0aGlzLl9lbGVtZW50Lm5hdGl2ZUVsZW1lbnQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuaXNWaXNpYmxlKCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBsb2FkICgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMucmVtb3ZlTGlzdGVuZXJzQWZ0ZXJMb2FkKSB7XG4gICAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVycygpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZGVmZXJMb2FkLmVtaXQoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFkZFNjcm9sbExpc3RlbmVycyAoKSB7XG4gICAgICAgIGlmICh0aGlzLmlzVmlzaWJsZSgpKSB7XG4gICAgICAgICAgICB0aGlzLmxvYWQoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl96b25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuX3Njcm9sbFN1YnNjcmlwdGlvbiA9IGZyb21FdmVudCh3aW5kb3csICdzY3JvbGwnKVxuICAgICAgICAgICAgICAgIC5waXBlKGRlYm91bmNlVGltZSg1MCkpXG4gICAgICAgICAgICAgICAgLnN1YnNjcmliZSh0aGlzLm9uU2Nyb2xsKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSByZW1vdmVMaXN0ZW5lcnMgKCkge1xuICAgICAgICB0aGlzLl9zY3JvbGxTdWJzY3JpcHRpb24/LnVuc3Vic2NyaWJlKCk7XG4gICAgICAgIHRoaXMuX2ludGVyc2VjdGlvbk9ic2VydmVyPy5kaXNjb25uZWN0KCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvblNjcm9sbCA9ICgpID0+IHtcbiAgICAgICAgaWYgKHRoaXMuaXNWaXNpYmxlKCkpIHtcbiAgICAgICAgICAgIHRoaXMuX3pvbmUucnVuKCgpID0+IHRoaXMubG9hZCgpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgaXNWaXNpYmxlICgpIHtcbiAgICAgICAgbGV0IHNjcm9sbFBvc2l0aW9uID0gdGhpcy5nZXRTY3JvbGxQb3NpdGlvbigpO1xuICAgICAgICBsZXQgZWxlbWVudE9mZnNldCA9IHRoaXMuX2VsZW1lbnQubmF0aXZlRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS50b3AgKyB3aW5kb3cuc2Nyb2xsWTtcbiAgICAgICAgcmV0dXJuIGVsZW1lbnRPZmZzZXQgPD0gc2Nyb2xsUG9zaXRpb247XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRTY3JvbGxQb3NpdGlvbiAoKSB7XG4gICAgICAgIC8vIEdldHRpbmcgc2NyZWVuIHNpemUgYW5kIHNjcm9sbCBwb3NpdGlvbiBmb3IgSUVcbiAgICAgICAgcmV0dXJuIHdpbmRvdy5zY3JvbGxZICsgKGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRIZWlnaHQgfHwgZG9jdW1lbnQuYm9keS5jbGllbnRIZWlnaHQpO1xuICAgIH1cbn1cbiJdfQ==