Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
orizens committed Sep 26, 2017
1 parent aa6d9ae commit f042c6a
Show file tree
Hide file tree
Showing 15 changed files with 272 additions and 43 deletions.
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
[![Build Status](https://travis-ci.org/orizens/ngx-infinite-scroll.svg?branch=master)](https://travis-ci.org/orizens/ngx-infinite-scroll)

# Angular Infinite Scroll
Inspired by [ng-infinite-scroll](https://github.com/sroze/ngInfiniteScroll) directive for angular (> 2, 4).
Inspired by [ng-infinite-scroll](https://github.com/sroze/ngInfiniteScroll) directive for angular.

## Angular Support
Supports Angular **> 4**
**Supports Angular > 4**
For Angular version **<= 2.3.1**, you can use ```npm i angular2-infinite-scroll``` (latest version is 0.3.42) - please notice **the angular2-infinite-scroll** package is deprecated

## Angular Consulting Services
Expand All @@ -31,6 +31,8 @@ Currently supported attributes:
* **scrollWindow**<_boolean_> - (optional, default: **true**) - listens to the window scroll instead of the actual element scroll. this allows to invoke a callback function in the scope of the element while listenning to the window scroll.
* **immediateCheck**<_boolean_> - (optional, default: **false**) - invokes the handler immediately to check if a scroll event has been already triggred when the page has been loaded (i.e. - when you refresh a page that has been scrolled).
* **infiniteScrollDisabled**<_boolean_> - (optional, default: **false**) - doesn't invoke the handler if set to true
* **horizontal**<_boolean_> - (optional, default: false) - sets the scroll to listen for horizontal events
* **alwaysCallback**<_boolean_> - (optional, default: false) - instructs the scroller to always trigger events

## Behavior
By default, the directive listens to the **window scroll** event and invoked the callback.
Expand Down Expand Up @@ -73,7 +75,7 @@ import { Component } from '@angular/core';
<div class="search-results"
infiniteScroll
[infiniteScrollDistance]="2"
[infiniteScrollThrottle]="300"
[infiniteScrollThrottle]="50"
(scrolled)="onScroll()">
</div>
`
Expand Down Expand Up @@ -101,7 +103,7 @@ import { Component } from '@angular/core';
<div class="search-results"
infiniteScroll
[infiniteScrollDistance]="2"
[infiniteScrollThrottle]="500"
[infiniteScrollThrottle]="50"
(scrolled)="onScroll()"
[scrollWindow]="false">
</div>
Expand All @@ -128,7 +130,7 @@ import { InfiniteScroll } from 'ngx-infinite-scroll';
infiniteScroll
[infiniteScrollDistance]="2"
[infiniteScrollUpDistance]="1.5"
[infiniteScrollThrottle]="500"
[infiniteScrollThrottle]="50"
(scrolled)="onScrollDown()"
(scrolledUp)="onScrollUp()">
</div>
Expand Down
5 changes: 5 additions & 0 deletions example/bs-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"port": 8000,
"files": ["./example**/*.{html,htm,css,js}"],
"server": [ "./example", "./dist/bundles" ]
}
56 changes: 56 additions & 0 deletions example/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
let systemConfig = {
//use typescript for compilation
transpiler: 'typescript',
//typescript compiler options
typescriptOptions: {
emitDecoratorMetadata: true
},
//map tells the System loader where to look for things
map: {
app: './src',
'@angular': 'https://unpkg.com/@angular',
'@angular/common': 'https://unpkg.com/@angular/[email protected]',
'@angular/core': 'https://unpkg.com/@angular/[email protected]',
'@angular/compiler': 'https://unpkg.com/@angular/[email protected]',
'@angular/platform-browser-dynamic': 'https://unpkg.com/@angular/[email protected]',
'@angular/platform-browser': 'https://unpkg.com/@angular/[email protected]',
'rxjs': 'https://unpkg.com/[email protected]'
// 'ngx-infinite-scroll': 'https://unpkg.com/ngx-infinite-scroll'
},
//packages defines our app package
packages: {
app: {
main: './main.ts',
defaultExtension: 'ts'
},
'@angular/core': {
main: 'bundles/core.umd.js',
defaultExtension: 'js'
},
'@angular/compiler': {
main: 'bundles/compiler.umd.js',
defaultExtension: 'js'
},
'@angular/common': {
main: 'bundles/common.umd.js',
defaultExtension: 'js'
},
'@angular/platform-browser-dynamic': {
main: 'bundles/platform-browser-dynamic.umd.js',
defaultExtension: 'js'
},
'@angular/platform-browser': {
main: 'bundles/platform-browser.umd.js',
defaultExtension: 'js'
},
rxjs: {
defaultExtension: 'js'
},
'ngx-infinite-scroll': {
main: '../ngx-infinite-scroll.umd.js',
defaultExtension: 'js'
}
}
};
System.config(systemConfig);
module.exports = systemConfig;
28 changes: 28 additions & 0 deletions example/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html>

<head>
<title>Angular Playground</title>
<link rel="stylesheet" href="style.css" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" type="text/css" />
<script src="https://unpkg.com/core-js/client/shim.min.js"></script>

<script src="https://unpkg.com/[email protected]?main=browser"></script>
<script src="https://unpkg.com/[email protected]"></script>
<script src="https://unpkg.com/[email protected]/dist/system.src.js"></script>
<script src="https://code.angularjs.org/tools/typescript.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chance/1.0.4/chance.min.js"></script>
<script src="config.js"></script>
<script>
System.import('app')
.catch(console.error.bind(console));
</script>
</head>

<body>
<my-app>
loading...
</my-app>
</body>

</html>
80 changes: 80 additions & 0 deletions example/src/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// our root app component
import { Component, ViewEncapsulation } from '@angular/core';
import * as config from '../config';

@Component({
selector: 'my-app',
styleUrls: [ './style.css' ],
template: `
<h1 class="title well">
{{ title }}
<section>
<small>items: {{sum}}, now triggering scroll: {{direction}}</small>
</section>
</h1>
<div class="search-results"
data-infinite-scroll
debounce
[infiniteScrollDistance]="scrollDistance"
[infiniteScrollUpDistance]="scrollUpDistance"
[infiniteScrollThrottle]="throttle"
(scrolled)="onScrollDown()"
(scrolledUp)="onUp()">
<p *ngFor="let i of array">
{{ i }}
</p>
</div>
`
})
export class AppComponent {
array = [];
sum = 100;
throttle = 300;
scrollDistance = 1;
scrollUpDistance = 2;
direction = '';
// title = 'This is Angular InfiniteScroll v' + systemConfig.map['ngx-infinite-scroll'].split('@')[1];

constructor() {
this.appendItems(0, this.sum);
// debugger
// console.log(systemConfig);
}

addItems(startIndex, endIndex, _method) {
for (let i = 0; i < this.sum; ++i) {
this.array[_method]([i, ' ', this.generateWord()].join(''));
}
}

appendItems(startIndex, endIndex) {
this.addItems(startIndex, endIndex, 'push');
}

prependItems(startIndex, endIndex) {
this.addItems(startIndex, endIndex, 'unshift');
}

onScrollDown (ev) {
console.log('scrolled down!!', ev);

// add another 20 items
const start = this.sum;
this.sum += 20;
this.appendItems(start, this.sum);

this.direction = 'down';
}

onUp(ev) {
console.log('scrolled up!', ev);
const start = this.sum;
this.sum += 20;
this.prependItems(start, this.sum);

this.direction = 'up';
}
generateWord() {
return chance.word();
}
}
15 changes: 15 additions & 0 deletions example/src/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// main entry point
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { InfiniteScrollModule } from 'ngx-infinite-scroll';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppComponent } from './app';

@NgModule({
declarations: [ AppComponent ],
imports: [ BrowserModule, InfiniteScrollModule ],
bootstrap: [ AppComponent ]
})
export class AppModule { }

platformBrowserDynamic().bootstrapModule(AppModule);
14 changes: 14 additions & 0 deletions example/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.search-results {
height: 100%;
}
.title {
position: fixed;
top: 0;
left: 0;
background-color: rgba(0,0,0,.5);
color: white;
width: 100%;
}
.title small {
color: #eaeaea;
}
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ngx-infinite-scroll",
"version": "0.5.1",
"version": "0.5.2",
"description": "An infinite scroll directive for Angular compatible with AoT compilation and Tree shaking",
"main": "./bundles/ngx-infinite-scroll.umd.js",
"module": "./modules/ngx-infinite-scroll.es5.js",
Expand All @@ -13,7 +13,8 @@
"publish:beta": "npm publish --tag beta ./dist",
"compodoc": "compodoc -p tsconfig.json",
"compodoc-serve": "compodoc -s",
"transpile": "ngc -p ./tsconfig.json"
"transpile": "ngc -p ./tsconfig.json",
"serve:prod": "npm run build && lite-server -c ./example/bs-config.json"
},
"typings": "./ngx-infinite-scroll.d.ts",
"author": "Oren Farhi (orizens.com)",
Expand Down
50 changes: 31 additions & 19 deletions src/modules/infinite-scroll.directive.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
import { InfiniteScrollEvent, IScrollStats, IPositionStats, IResolver } from '../models';
import {
Directive, ElementRef, Input, Output,
EventEmitter, OnDestroy, OnInit,
SimpleChanges, NgZone
Directive,
ElementRef,
EventEmitter,
Input,
NgZone,
OnChanges,
OnDestroy,
OnInit,
Output,
SimpleChanges,
} from '@angular/core';
import { PositionResolver } from '../services/position-resolver';
import { ScrollRegister, IScrollRegisterConfig } from '../services/scroll-register';
import { ScrollResolver } from '../services/scroll-resolver';
import { AxisResolver } from '../services/axis-resolver';
import { resolveContainerElement } from '../services/ngx-ins-utils';

import { Subscription } from 'rxjs/Subscription';

@Directive({
selector: '[infiniteScroll], [infinite-scroll], [data-infinite-scroll]'
providers: [ScrollResolver],
selector: '[infiniteScroll], [infinite-scroll], [data-infinite-scroll]',
})
export class InfiniteScrollDirective implements OnDestroy, OnInit {
export class InfiniteScrollDirective implements OnDestroy, OnInit, OnChanges {
@Output() scrolled = new EventEmitter<InfiniteScrollEvent>();
@Output() scrolledUp = new EventEmitter<InfiniteScrollEvent>();

Expand All @@ -39,9 +48,21 @@ export class InfiniteScrollDirective implements OnDestroy, OnInit {
) {}

ngOnInit() {
this.setup();
}

ngOnChanges({ infiniteScrollContainer }: SimpleChanges) {
const scrollContainerChanged = infiniteScrollContainer && !infiniteScrollContainer.firstChange;
if (scrollContainerChanged) {
this.destroyScroller();
this.setup();
}
}

setup() {
if (typeof window !== 'undefined') {
this.zone.runOutsideAngular(() => {
const containerElement = this.resolveContainerElement();
const containerElement = resolveContainerElement(this.infiniteScrollContainer, this.scrollWindow, this.element);
const resolver = this.positionResolver.create({
axis: new AxisResolver(!this.horizontal),
windowElement: containerElement,
Expand Down Expand Up @@ -81,9 +102,7 @@ export class InfiniteScrollDirective implements OnDestroy, OnInit {
}

ngOnDestroy () {
if (this.disposeScroller) {
this.disposeScroller.unsubscribe();
}
this.destroyScroller();
}

onScrollDown(data: InfiniteScrollEvent = { currentScrollPosition: 0 }) {
Expand All @@ -94,16 +113,9 @@ export class InfiniteScrollDirective implements OnDestroy, OnInit {
this.zone.run(() => this.scrolledUp.emit(data));
}

private resolveContainerElement(): any {
const selector = this.infiniteScrollContainer;
const hasWindow = window && window.hasOwnProperty('document');
const containerIsString = selector && hasWindow && typeof(this.infiniteScrollContainer) === 'string';
let container = containerIsString
? window.document.querySelector(selector)
: selector;
if (!selector) {
container = this.scrollWindow ? window : this.element;
destroyScroller() {
if (this.disposeScroller) {
this.disposeScroller.unsubscribe();
}
return container;
}
}
4 changes: 1 addition & 3 deletions src/modules/ngx-infinite-scroll.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,14 @@ import { NgModule } from '@angular/core';
import { InfiniteScrollDirective } from './infinite-scroll.directive';
import { PositionResolver } from '../services/position-resolver';
import { ScrollRegister } from '../services/scroll-register';
import { ScrollResolver } from '../services/scroll-resolver';

@NgModule({
declarations: [InfiniteScrollDirective],
exports: [InfiniteScrollDirective],
imports: [],
providers: [
PositionResolver,
ScrollRegister,
ScrollResolver
ScrollRegister
]
})
export class InfiniteScrollModule { }
11 changes: 11 additions & 0 deletions src/services/ngx-ins-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export function resolveContainerElement(selector: string | any, scrollWindow, defaultElement): any {
const hasWindow = window && window.hasOwnProperty('document');
const containerIsString = selector && hasWindow && typeof(selector) === 'string';
let container = containerIsString
? window.document.querySelector(selector)
: selector;
if (!selector) {
container = scrollWindow ? window : defaultElement;
}
return container;
}
Loading

0 comments on commit f042c6a

Please sign in to comment.