Last active
April 11, 2022 09:02
-
-
Save lansana/2c04abe668d1c97aded7e5ad9d0d74d9 to your computer and use it in GitHub Desktop.
Revisions
-
lansana revised this gist
Jul 11, 2017 . 1 changed file with 39 additions and 54 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -18,13 +18,16 @@ // </div> // </div> import { Directive, Input, Output, EventEmitter, ElementRef, OnInit } from '@angular/core'; import { Observable } from 'rxjs/Observable'; import 'rxjs/add/observable/fromEvent'; import 'rxjs/add/operator/debounceTime'; import 'rxjs/add/operator/map'; export interface Viewport { width: number; height: number; } // InfiniteScrollContext represents the context in which the directive will run. @@ -40,70 +43,52 @@ export type InfiniteScrollContext = 'self' | 'document'; selector: '[infiniteScroll]', }) export class InfiniteScrollDirective implements OnInit { private el: any; private viewport: Viewport; private scrollEvent$: Observable<any>; @Input() infiniteScrollContext: InfiniteScrollContext = 'document'; @Output() infiniteScrollAction: EventEmitter<any> = new EventEmitter(); constructor(private element: ElementRef) { this.el = element.nativeElement; this.viewport = this.getViewport(window); } ngOnInit() { if (this.infiniteScrollContext === 'self') { this.scrollEvent$ = Observable.fromEvent(this.el, 'scroll').debounceTime(250); this.scrollEvent$.subscribe((e: any) => { if (e.target.scrollTop + e.target.offsetHeight >= e.target.scrollHeight) { this.infiniteScrollAction.emit(null); } }); } else if (this.infiniteScrollContext === 'document') { this.scrollEvent$ = Observable.fromEvent(window.document, 'scroll').debounceTime(250); this.scrollEvent$.subscribe(() => { const rect = this.el.getBoundingClientRect(); const elementTopRelativeToViewport = rect.top; const elementTopRelativeToDocument = elementTopRelativeToViewport + this.win.pageYOffset; const scrollableDistance = this.el.offsetHeight + elementTopRelativeToDocument; const currentPos = window.pageYOffset + this.viewport.height; if (currentPos > scrollableDistance) { this.infiniteScrollAction.emit(null); } }); } else { throw new Error(`'infiniteScrollContext' contains invalid value ${this.infiniteScrollContext}. Only 'self' and 'document' are allowed.`); } } private getViewport(win: Window): Viewport { // This works for all browsers except IE8 and before if (win.innerWidth != null) { return { width: win.innerWidth, height: win.innerHeight }; } @@ -112,15 +97,15 @@ export class InfiniteScrollDirective implements OnInit { if (document.compatMode == 'CSS1Compat') { return { width: d.documentElement.clientWidth, height: d.documentElement.clientHeight }; } // For browsers in Quirks mode return { width: d.body.clientWidth, height: d.body.clientHeight }; } } -
lansana revised this gist
Jun 1, 2017 . 1 changed file with 7 additions and 5 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -6,11 +6,6 @@ // you effectively increase the height of the element and thus begin the process of the infiniteScroll directive // again, over and over until the element height stops increasing. // // <div class="container" infiniteScroll (infiniteScrollAction)="loadMoreArticles()"> // <div class="article" *ngFor="let article of articles"> // ... @@ -32,6 +27,13 @@ export interface Viewport { w: number; } // InfiniteScrollContext represents the context in which the directive will run. // // The default is 'document' and this will trigger your action when the end of // your element has been reached relative to the documents scrollbar. // // If you use 'self', your action will be triggered when the end of your element // has been reached relative to your elements own scrollbar. export type InfiniteScrollContext = 'self' | 'document'; @Directive({ -
lansana revised this gist
Jun 1, 2017 . 1 changed file with 28 additions and 20 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -45,7 +45,11 @@ export class InfiniteScrollDirective implements OnInit { @Input() infiniteScrollContext: InfiniteScrollContext = 'document'; @Output() infiniteScrollAction: EventEmitter<any> = new EventEmitter(); @HostListener('scroll', ['$event']) onElementScroll() { if (this.infiniteScrollContext === 'self') { if (this.elementEndReachedInSelfScrollbarContext() && this.canTriggerAction) { this.triggerAction(); } } } constructor(private element: ElementRef) { @@ -56,33 +60,37 @@ export class InfiniteScrollDirective implements OnInit { ngOnInit() { if (this.infiniteScrollContext === 'document') { document.addEventListener('scroll', () => { if (this.elementEndReachedInDocumentScrollbarContext(window, this.el) && this.canTriggerAction) { this.triggerAction(); } }); } } triggerAction() { this.canTriggerAction = false; this.infiniteScrollAction.emit(null); } elementEndReachedInSelfScrollbarContext(): boolean { if (this.el.scrollTop + this.el.offsetHeight >= this.el.scrollHeight) { this.canTriggerAction = true; return true; } return false; } elementEndReachedInDocumentScrollbarContext(win: Window, el: any): boolean { const rect = el.getBoundingClientRect(); const elementTopRelativeToViewport = rect.top; const elementTopRelativeToDocument = elementTopRelativeToViewport + win.pageYOffset; const scrollableDistance = el.offsetHeight + elementTopRelativeToDocument; const currentPos = win.pageYOffset + this.viewport.h; if (currentPos > scrollableDistance) { this.canTriggerAction = true; return true; } return false; -
lansana revised this gist
Jun 1, 2017 . 1 changed file with 51 additions and 20 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -6,52 +6,83 @@ // you effectively increase the height of the element and thus begin the process of the infiniteScroll directive // again, over and over until the element height stops increasing. // // There is a flag @Input() called 'infiniteScrollContext'. You can pass in two options: 'self', or 'document'. // The default selection is document, and this means that the directive will run in the context of the documents // scrollbar. If you use 'self', then the directive will run in the context of the respective elements scrollbar. // All other functionality stays the same. // // <div class="container" infiniteScroll (infiniteScrollAction)="loadMoreArticles()"> // <div class="article" *ngFor="let article of articles"> // ... // </div> // </div> // // <div class="container" infiniteScroll [infiniteScrollContext]="'self'" (infiniteScrollAction)="loadMoreArticles()"> // <div class="article" *ngFor="let article of articles"> // ... // </div> // </div> import { Directive, Input, Output, EventEmitter, ElementRef, HostListener, OnInit } from '@angular/core'; export interface Viewport { h: number; w: number; } export type InfiniteScrollContext = 'self' | 'document'; @Directive({ selector: '[infiniteScroll]', }) export class InfiniteScrollDirective implements OnInit { el: any; viewport: Viewport; canTriggerAction: boolean = true; @Input() infiniteScrollContext: InfiniteScrollContext = 'document'; @Output() infiniteScrollAction: EventEmitter<any> = new EventEmitter(); @HostListener('scroll', ['$event']) onElementScroll() { if (this.endReached(window, this.el)) this.trigger(); } constructor(private element: ElementRef) { this.el = element.nativeElement; this.viewport = this.getViewport(window); } ngOnInit() { if (this.infiniteScrollContext === 'document') { document.addEventListener('scroll', () => { if (this.endReached(window, this.el) && this.canTriggerAction) this.trigger(); }); } } trigger() { this.canTriggerAction = false; this.infiniteScrollAction.emit(null); } endReached(win: Window, el: any): boolean { if (this.infiniteScrollContext === 'self') { if (this.el.scrollTop + this.el.offsetHeight >= this.el.scrollHeight) { this.canTriggerAction = true; return true; } } else if (this.infiniteScrollContext === 'document') { const rect = el.getBoundingClientRect(); const elementTopRelativeToViewport = rect.top; const elementTopRelativeToDocument = elementTopRelativeToViewport + win.pageYOffset; const scrollableDistance = el.offsetHeight + elementTopRelativeToDocument; const currentPos = win.pageYOffset + this.viewport.h; if (currentPos > scrollableDistance) { this.canTriggerAction = true; return true; } } return false; -
lansana revised this gist
May 31, 2017 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -29,7 +29,7 @@ export class InfiniteScrollDirective { canTriggerAction: boolean = true; @Output() infiniteScrollAction: EventEmitter<any> = new EventEmitter(); constructor(private element: ElementRef) { const el = element.nativeElement; this.viewport = this.getViewport(window); -
lansana created this gist
May 31, 2017 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,85 @@ // USAGE: // // When you attach the infiniteScroll directive to an element, it will emit the infiniteScrollAction // @Output() event every time the user has scrolled to the bottom of the element. Your loadMoreArticles // function can make an HTTP call and append the results to the articles list, for example. In doing this, // you effectively increase the height of the element and thus begin the process of the infiniteScroll directive // again, over and over until the element height stops increasing. // // <div class="container" infiniteScroll (infiniteScrollAction)="loadMoreArticles()"> // <div class="article" *ngFor="let article of articles"> // ... // </div> // </div> import { Directive, Output, EventEmitter, ElementRef } from '@angular/core'; interface Viewport { h: number; w: number; } @Directive({ selector: '[infiniteScroll]', }) export class InfiniteScrollDirective { viewport: Viewport; canTriggerAction: boolean = true; @Output() infiniteScrollAction: EventEmitter<any> = new EventEmitter(); constructor(private element: ElementRef,) { const el = element.nativeElement; this.viewport = this.getViewport(window); document.addEventListener('scroll', () => { if (this.elementEndReached(window, el) && this.canTriggerAction) { this.canTriggerAction = false; this.infiniteScrollAction.emit(null); } }); } elementEndReached(win: Window, el: any): boolean { const rect = el.getBoundingClientRect(); const elementTopRelativeToViewport = rect.top; const elementTopRelativeToDocument = elementTopRelativeToViewport + win.pageYOffset; const scrollableDistance = el.offsetHeight + elementTopRelativeToDocument; const currentPos = win.pageYOffset + this.viewport.h; if (currentPos > scrollableDistance) { this.canTriggerAction = true; return true; } return false; } private getViewport(win: Window): Viewport { // This works for all browsers except IE8 and before if (win.innerWidth != null) { return { w: win.innerWidth, h: win.innerHeight }; } // For IE (or any browser) in Standards mode let d = win.document; if (document.compatMode == 'CSS1Compat') { return { w: d.documentElement.clientWidth, h: d.documentElement.clientHeight }; } // For browsers in Quirks mode return { w: d.body.clientWidth, h: d.body.clientHeight }; } }