import {NgModule,Component,ElementRef,OnInit,AfterViewInit,AfterContentInit,DoCheck,OnDestroy,Input,Output,Renderer2,NgZone,ViewChild,EventEmitter,ContentChild,ContentChildren,QueryList,TemplateRef} from '@angular/core';
import {CommonModule} from '@angular/common';
import {Header,Footer,PrimeTemplate,SharedModule} from '../common/shared';
import {DomHandler} from '../dom/domhandler';
@Component({
selector: 'p-dataScroller',
template:`
`,
providers: [DomHandler]
})
export class DataScroller implements OnInit,AfterViewInit,OnDestroy {
@Input() value: any[];
@Input() rows: number;
@Input() lazy: boolean;
@Input() style: any;
@Input() styleClass: string;
@Input() buffer: number = 0.9;
@Input() inline: boolean;
@Input() scrollHeight: any;
@Input() loader: any;
@Input() totalRecords: number;
@Input() trackBy: Function = (index: number, item: any) => item;
@ContentChild(Header) header;
@ContentChild(Footer) footer;
@ContentChildren(PrimeTemplate) templates: QueryList;
@ViewChild('content') contentViewChild: ElementRef;
@Output() onLazyLoad: EventEmitter = new EventEmitter();
itemTemplate: TemplateRef;
dataToRender: any[] = [];
first: number = 0;
contentElement: HTMLDivElement;
inlineScrollListener: any;
windowScrollListener: any;
loaderClickListener: any;
page: number = 0;
constructor(public el: ElementRef, public renderer: Renderer2, public domHandler: DomHandler, public zone: NgZone) {}
ngOnInit() {
this.load();
}
ngAfterViewInit() {
if(this.loader) {
this.loaderClickListener = this.renderer.listen(this.loader, 'click', () => {
this.load();
});
}
else {
this.bindScrollListener();
}
}
ngAfterContentInit() {
this.templates.forEach((item) => {
switch(item.getType()) {
case 'item':
this.itemTemplate = item.template;
break;
default:
this.itemTemplate = item.template;
break;
}
});
}
load() {
if(this.lazy) {
this.onLazyLoad.emit({
first: this.page * this.rows,
rows: this.rows
});
}
this.page = this.page + 1;
}
shouldLoad() {
if(this.lazy)
return (this.rows * this.page < this.totalRecords);
else
return this.value && this.value.length && (this.rows * this.page < this.value.length);
}
reset() {
this.page = 0;
}
isEmpty() {
return !this.value||(this.value.length == 0);
}
bindScrollListener() {
this.zone.runOutsideAngular(() => {
if(this.inline) {
this.inlineScrollListener = this.onInlineScroll.bind(this);
this.contentViewChild.nativeElement.addEventListener('scroll', this.inlineScrollListener);
}
else {
this.windowScrollListener = this.onWindowScroll.bind(this);
window.addEventListener('scroll', this.windowScrollListener);
}
});
}
unbindScrollListener() {
if(this.inlineScrollListener) {
this.contentViewChild.nativeElement.removeEventListener('scroll', this.inlineScrollListener);
}
if(this.windowScrollListener) {
window.removeEventListener('scroll', this.windowScrollListener);
}
if(this.loaderClickListener) {
this.loaderClickListener();
this.loaderClickListener = null;
}
}
onInlineScroll() {
let scrollTop = this.contentViewChild.nativeElement.scrollTop;
let scrollHeight = this.contentViewChild.nativeElement.scrollHeight;
let viewportHeight = this.contentViewChild.nativeElement.clientHeight;
if((scrollTop >= ((scrollHeight * this.buffer) - (viewportHeight)))) {
if(this.shouldLoad()) {
this.zone.run(() => {
this.load();
});
}
}
}
onWindowScroll() {
let docBody = document.body;
let docElement = document.documentElement;
let scrollTop = (window.pageYOffset||document.documentElement.scrollTop);
let winHeight = docElement.clientHeight;
let docHeight = Math.max(docBody.scrollHeight, docBody.offsetHeight, winHeight, docElement.scrollHeight, docElement.offsetHeight);
if(scrollTop >= ((docHeight * this.buffer) - winHeight)) {
if(this.shouldLoad()) {
this.zone.run(() => {
this.load();
});
}
}
}
ngOnDestroy() {
this.unbindScrollListener();
}
}
@NgModule({
imports: [CommonModule],
exports: [DataScroller,SharedModule],
declarations: [DataScroller]
})
export class DataScrollerModule { }