├── .gitignore ├── .npmignore ├── LICENSE ├── LICENSE.md ├── README.md ├── app ├── app.component.ts ├── build │ ├── app.js │ └── app.js.map ├── index.html ├── main.ts ├── systemjs.config.js └── webpack.config.js ├── dist ├── index.d.ts ├── index.js ├── index.js.map ├── index.metadata.json ├── infinite-list.directive.d.ts ├── infinite-list.directive.js ├── infinite-list.directive.js.map ├── infinite-list.directive.metadata.json ├── infinite-list.umd.js └── infinite-list.umd.js.map ├── favicon.ico ├── package.json ├── src ├── index.ts └── infinite-list.directive.ts ├── tsconfig.json ├── tsconfig.ngc.json └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | .idea 3 | node_modules 4 | typings 5 | *.log -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .idea 2 | test 3 | src 4 | build.sh 5 | tsconfig.json 6 | typings.json 7 | node_modules 8 | typings 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 JS valley 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Allen Kim 2 | 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # infinite-list 2 | Angular2 Infinite List directive 3 | 4 | ## IMPORTANT: NOT-MAINTAINED 5 | Accepting volunteers and ready to transfer ownership. 6 | 7 | 8 | 9 | 10 | 11 | Plunker Example: http://plnkr.co/edit/3LTMdS?p=preview 12 | 13 | ## Install 14 | 15 | 1. install @ngui/infinite-list 16 | 17 | $ npm install @ngui/infinite-list --save 18 | 19 | 2. add `map` and `packages` to your `systemjs.config.js` 20 | 21 | map['@ngui/infinite-list'] = 'node_modules/@ngui/infinite-list/dist/infinite-list.umd.js'; 22 | 23 | 3. import NguiInfiniteList to your AppModule 24 | 25 | import { NgModule } from '@angular/core'; 26 | import { FormsModule } from "@angular/forms"; 27 | import { BrowserModule } from '@angular/platform-browser'; 28 | import { AppComponent } from './app.component'; 29 | import { NguiInfiniteListModule } from '@ngui/infinite-list'; 30 | 31 | @NgModule({ 32 | imports: [BrowserModule, FormsModule, NguiInfiniteListModule], 33 | declarations: [AppComponent], 34 | bootstrap: [ AppComponent ] 35 | }) 36 | export class AppModule { } 37 | 38 | ## Use it in your code 39 | 40 | ``` 41 | 49 | ``` 50 | 51 | For full example, please check out `test` directory to see the example of; 52 | 53 | - `systemjs.config.js` 54 | - `app.module.ts` 55 | - and `app.component.ts`. 56 | 57 | ## **ng2-ui** welcomes new members and contributors 58 | 59 | This module is only improved and maintained by contributors like you. 60 | 61 | As a contributor, it's NOT required to be skilled in Javascript nor Angular2. 62 | You are only to be open-minded and interested in helping others. 63 | As a contributor, you do following; 64 | 65 | * Updating README.md 66 | * Improving code comments 67 | * Answering issues and building FAQ 68 | * Documentation 69 | * Translation 70 | 71 | In result of your active contribution, you will be listed as a core contributor 72 | on https://ng2-ui.github.io, and a member of ng2-ui too. 73 | 74 | If you are interested in becoming a contributor and/or a member of ng-ui, 75 | please send me email to `allenhwkim AT gmail.com` with your github id. 76 | 77 | ## For Developers 78 | 79 | ### To start 80 | 81 | $ git clone https://github.com/ng2-ui/infinite-list.git 82 | $ cd infinite-list 83 | $ npm install 84 | $ npm start 85 | -------------------------------------------------------------------------------- /app/app.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, Type} from '@angular/core' 2 | 3 | @Component({ 4 | selector: 'my-app', 5 | template: ` 6 | 14 | loading in progress : {{set1.loadingInProgress}} 15 | 16 |
18 |
{{item+1}}
19 |
20 |   21 |
Loading
22 |
End Of List
23 |
24 |
25 | loading in progress : {{set2.loadingInProgress}} 26 | `, 27 | styles: [` 28 | .infinite-list { 29 | overflow: auto; 30 | border: 10px solid #333; 31 | height: 200px; 32 | position: relative; 33 | } 34 | .infinite-list > * { 35 | min-height: 20px 36 | } 37 | 38 | .infinite-list > *:nth-child(odd) { 39 | background-color: #eee 40 | } 41 | 42 | .infinite-list.horizontal { 43 | height: 100px; 44 | white-space: nowrap; 45 | overflow-y: hidden; 46 | } 47 | .infinite-list.horizontal > div { 48 | border: 1px solid #666; 49 | width: 50px; 50 | height: 80px; 51 | display: inline-block; 52 | margin: 10px; 53 | vertical-align: top; 54 | }`] 55 | }) 56 | export class AppComponent { 57 | set1: any = { 58 | limit: 10, offset: 0, endOfList: false, loadingInProgress: false, list: [] 59 | }; 60 | set2: any = { 61 | limit: 10, offset: 0, endOfList: false, loadingInProgress: false, list: [] 62 | }; 63 | 64 | loadMore(data) { 65 | if (data.offset > 99) { // detect the end of list 66 | data.endOfList = true; 67 | } else { 68 | setTimeout(() => data.loadingInProgress = true); 69 | setTimeout(() => { // mimics http call delay 70 | let max = data.offset + data.limit; 71 | for (let i = data.offset; i < max; i++) { 72 | data.list.push(i); 73 | } 74 | data.offset = max; 75 | data.loadingInProgress = false; 76 | }, 1000); 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Angular2 Npm Package Example 5 | 6 | 7 | 8 | Loading... 9 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /app/main.ts: -------------------------------------------------------------------------------- 1 | // polyfills, comment the following out for debugging purpose 2 | import 'core-js/es6'; 3 | import 'core-js/es7/reflect'; 4 | import 'zone.js/dist/zone'; 5 | 6 | // The browser platform with a compiler 7 | import { NgModule } from '@angular/core'; 8 | import { BrowserModule } from '@angular/platform-browser'; 9 | import { FormsModule } from "@angular/forms"; 10 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 11 | 12 | import { AppComponent } from './app.component'; 13 | 14 | //noinspection TypeScriptCheckImport 15 | import { NguiInfiniteListModule } from '@ngui/infinite-list'; 16 | 17 | @NgModule({ 18 | imports: [BrowserModule, FormsModule, NguiInfiniteListModule], 19 | declarations: [AppComponent], 20 | bootstrap: [ AppComponent ] 21 | }) 22 | export class AppModule { } 23 | 24 | platformBrowserDynamic().bootstrapModule(AppModule); 25 | -------------------------------------------------------------------------------- /app/systemjs.config.js: -------------------------------------------------------------------------------- 1 | (function(global) { 2 | var map = { 3 | app: ".", 4 | '@angular': '../node_modules/@angular', 5 | 'rxjs': '../node_modules/rxjs' 6 | }; 7 | var packages = { 8 | app: { main: './main.ts', defaultExtension: 'ts' }, 9 | '@angular/common': { main: 'bundles/common.umd.js', defaultExtension: 'js' }, 10 | '@angular/compiler': { main: 'bundles/compiler.umd.js', defaultExtension: 'js' }, 11 | '@angular/core': { main: 'bundles/core.umd.js', defaultExtension: 'js' }, 12 | '@angular/forms': { main: 'bundles/forms.umd.js', defaultExtension: 'js' }, 13 | '@angular/http': { main: 'bundles/http.umd.js', defaultExtension: 'js' }, 14 | '@angular/platform-browser': { main: 'bundles/platform-browser.umd.js', defaultExtension: 'js' }, 15 | '@angular/platform-browser-dynamic': { main: 'bundles/platform-browser-dynamic.umd.js', defaultExtension: 'js' }, 16 | rxjs: { defaultExtension: 'js' } 17 | }; 18 | 19 | map['@ngui/infinite-list'] = '../dist/infinite-list.umd.js'; 20 | 21 | System.config({ 22 | transpiler: 'typescript', //use typescript for compilation 23 | typescriptOptions: { //typescript compiler options 24 | emitDecoratorMetadata: true 25 | }, 26 | map: map, 27 | packages: packages 28 | }); 29 | })(this); 30 | -------------------------------------------------------------------------------- /app/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | const webpack = require('webpack'); 3 | 4 | const config = { 5 | resolve: { 6 | extensions: ['.ts', '.webpack.js', '.web.js', '.js'], 7 | alias: { 8 | '@ngui/infinite-list': path.join(__dirname, '..', 'src', 'index') 9 | } 10 | }, 11 | devtool: 'source-map', 12 | entry: './app/main.ts', 13 | module: { 14 | rules: [ 15 | { 16 | test: /\.ts$/, 17 | use: [ 18 | { 19 | loader: 'ts-loader', 20 | options: { 21 | include: ['src/**/*.ts', 'app/**/*.ts'] 22 | }, 23 | }, 24 | 'angular2-template-loader' 25 | ], 26 | }, 27 | { test: /\.html$/, use: ['raw-loader'] } 28 | ] 29 | }, 30 | plugins: [], 31 | output: { 32 | path: `${__dirname}/build/`, 33 | publicPath: '/build/', 34 | filename: 'app.js' 35 | } 36 | }; 37 | 38 | if (process.env.NODE_ENV === 'prod') { 39 | config.plugins = [ 40 | new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } }) 41 | ]; 42 | config.module.rules.push({ 43 | test: /\.ts$/, use: 'strip-loader?strip[]=debug,strip[]=console.log' 44 | }); 45 | } 46 | 47 | module.exports = config; 48 | -------------------------------------------------------------------------------- /dist/index.d.ts: -------------------------------------------------------------------------------- 1 | import { NguiInfiniteListDirective } from "./infinite-list.directive"; 2 | export { NguiInfiniteListDirective }; 3 | export declare class NguiInfiniteListModule { 4 | } 5 | -------------------------------------------------------------------------------- /dist/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var core_1 = require("@angular/core"); 4 | var forms_1 = require("@angular/forms"); 5 | var platform_browser_1 = require("@angular/platform-browser"); 6 | var infinite_list_directive_1 = require("./infinite-list.directive"); 7 | exports.NguiInfiniteListDirective = infinite_list_directive_1.NguiInfiniteListDirective; 8 | var NguiInfiniteListModule = (function () { 9 | function NguiInfiniteListModule() { 10 | } 11 | return NguiInfiniteListModule; 12 | }()); 13 | NguiInfiniteListModule.decorators = [ 14 | { type: core_1.NgModule, args: [{ 15 | imports: [platform_browser_1.BrowserModule, forms_1.FormsModule], 16 | declarations: [infinite_list_directive_1.NguiInfiniteListDirective], 17 | exports: [infinite_list_directive_1.NguiInfiniteListDirective] 18 | },] }, 19 | ]; 20 | /** @nocollapse */ 21 | NguiInfiniteListModule.ctorParameters = function () { return []; }; 22 | exports.NguiInfiniteListModule = NguiInfiniteListModule; 23 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /dist/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;AAAA,sCAAyC;AACzC,wCAA6C;AAC7C,8DAA2D;AAE3D,qEAAsE;AAGpE,wFAAyB;AAI3B;IAAA;IAUA,CAAC;IAAD,6BAAC;AAAD,CAVA,AAUC;AAV2C,iCAAU,GAA0B;IAChF,EAAE,IAAI,EAAE,eAAQ,EAAE,IAAI,EAAE,CAAC;gBACvB,OAAO,EAAE,CAAE,gCAAa,EAAE,mBAAW,CAAE;gBACvC,YAAY,EAAE,CAAC,mDAAyB,CAAC;gBACzC,OAAO,EAAG,CAAC,mDAAyB,CAAC;aACtC,EAAG,EAAE;CACL,CAAC;AACF,kBAAkB;AACX,qCAAc,GAAmE,cAAM,OAAA,EAC7F,EAD6F,CAC7F,CAAC;AATW,wDAAsB","file":"index.js","sourceRoot":""} -------------------------------------------------------------------------------- /dist/index.metadata.json: -------------------------------------------------------------------------------- 1 | [{"__symbolic":"module","version":3,"metadata":{"NguiInfiniteListDirective":{"__symbolic":"reference","module":"./infinite-list.directive","name":"NguiInfiniteListDirective"},"NguiInfiniteListModule":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"NgModule"},"arguments":[{"imports":[{"__symbolic":"reference","module":"@angular/platform-browser","name":"BrowserModule"},{"__symbolic":"reference","module":"@angular/forms","name":"FormsModule"}],"declarations":[{"__symbolic":"reference","module":"./infinite-list.directive","name":"NguiInfiniteListDirective"}],"exports":[{"__symbolic":"reference","module":"./infinite-list.directive","name":"NguiInfiniteListDirective"}]}]}]}}},{"__symbolic":"module","version":1,"metadata":{"NguiInfiniteListDirective":{"__symbolic":"reference","module":"./infinite-list.directive","name":"NguiInfiniteListDirective"},"NguiInfiniteListModule":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"NgModule"},"arguments":[{"imports":[{"__symbolic":"reference","module":"@angular/platform-browser","name":"BrowserModule"},{"__symbolic":"reference","module":"@angular/forms","name":"FormsModule"}],"declarations":[{"__symbolic":"reference","module":"./infinite-list.directive","name":"NguiInfiniteListDirective"}],"exports":[{"__symbolic":"reference","module":"./infinite-list.directive","name":"NguiInfiniteListDirective"}]}]}]}}}] -------------------------------------------------------------------------------- /dist/infinite-list.directive.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementRef, EventEmitter } from '@angular/core'; 2 | export declare class NguiInfiniteListDirective { 3 | horizontal: boolean; 4 | enableWindowScroll: boolean; 5 | disableScrollListener: boolean; 6 | endVisible: EventEmitter<{}>; 7 | el: HTMLElement; 8 | endEl: HTMLElement; 9 | elementVisible: any; 10 | /** 11 | * Creates an instance of NguiInfiniteListDirective. 12 | * @param {ElementRef} el 13 | * 14 | * @memberOf NguiInfiniteListDirective 15 | */ 16 | constructor(el: ElementRef); 17 | /** 18 | * Setup list of sections 19 | * 20 | * @memberOf NguiInfiniteListDirective 21 | */ 22 | ngOnInit(): void; 23 | /** 24 | * Handles the scroll listener event. 25 | * 26 | * @memberOf NguiInfiniteListDirective 27 | */ 28 | scrollListener: () => void; 29 | } 30 | -------------------------------------------------------------------------------- /dist/infinite-list.directive.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var core_1 = require("@angular/core"); 4 | var utils_1 = require("@ngui/utils"); 5 | var NguiInfiniteListDirective = (function () { 6 | /** 7 | * Creates an instance of NguiInfiniteListDirective. 8 | * @param {ElementRef} el 9 | * 10 | * @memberOf NguiInfiniteListDirective 11 | */ 12 | function NguiInfiniteListDirective(el) { 13 | var _this = this; 14 | this.enableWindowScroll = false; 15 | this.disableScrollListener = false; 16 | this.endVisible = new core_1.EventEmitter(); 17 | this.elementVisible = utils_1.elementVisible; 18 | /** 19 | * Handles the scroll listener event. 20 | * 21 | * @memberOf NguiInfiniteListDirective 22 | */ 23 | this.scrollListener = function () { 24 | if (!_this.disableScrollListener) { 25 | var visible = void 0; 26 | if (_this.enableWindowScroll) { 27 | visible = _this.elementVisible(_this.endEl, window); 28 | } 29 | else { 30 | visible = _this.elementVisible(_this.endEl, _this.el); 31 | } 32 | if (_this.horizontal && (visible.left || visible.right)) { 33 | _this.endVisible.emit(true); 34 | } 35 | else if (!_this.horizontal && (visible.top || visible.bottom)) { 36 | _this.endVisible.emit(true); 37 | } 38 | } 39 | }; 40 | this.el = el.nativeElement; 41 | } 42 | /** 43 | * Setup list of sections 44 | * 45 | * @memberOf NguiInfiniteListDirective 46 | */ 47 | NguiInfiniteListDirective.prototype.ngOnInit = function () { 48 | this.endEl = this.el.querySelector('[ngui-infinite-list-end]'); 49 | if (!this.endEl) { 50 | throw "Invalid 'ngui-infinite-list-end"; 51 | } 52 | this.scrollListener(); 53 | if (this.enableWindowScroll) { 54 | window.addEventListener('scroll', this.scrollListener); 55 | } 56 | else { 57 | this.el.addEventListener('scroll', this.scrollListener); 58 | } 59 | window.addEventListener('resize', this.scrollListener); 60 | }; 61 | return NguiInfiniteListDirective; 62 | }()); 63 | NguiInfiniteListDirective.decorators = [ 64 | { type: core_1.Directive, args: [{ selector: '[ngui-infinite-list]' },] }, 65 | ]; 66 | /** @nocollapse */ 67 | NguiInfiniteListDirective.ctorParameters = function () { return [ 68 | { type: core_1.ElementRef, }, 69 | ]; }; 70 | NguiInfiniteListDirective.propDecorators = { 71 | 'horizontal': [{ type: core_1.Input },], 72 | 'enableWindowScroll': [{ type: core_1.Input },], 73 | 'disableScrollListener': [{ type: core_1.Input },], 74 | 'endVisible': [{ type: core_1.Output },], 75 | }; 76 | exports.NguiInfiniteListDirective = NguiInfiniteListDirective; 77 | //# sourceMappingURL=infinite-list.directive.js.map -------------------------------------------------------------------------------- /dist/infinite-list.directive.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["../src/infinite-list.directive.ts"],"names":[],"mappings":";;AAAA,sCAAiF;AACjF,qCAA6C;AAG7C;IAiBE;;;;;OAKG;IACH,mCAAY,EAAc;QAA1B,iBAEC;QApBM,uBAAkB,GAAa,KAAK,CAAC;QAErC,0BAAqB,GAAY,KAAK,CAAC;QAGvC,eAAU,GAAG,IAAI,mBAAY,EAAE,CAAC;QAIhC,mBAAc,GAAQ,sBAAc,CAAC;QAiC5C;;;;WAIG;QACH,mBAAc,GAAG;YACf,EAAE,CAAC,CAAC,CAAC,KAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC;gBAChC,IAAI,OAAO,SAAA,CAAC;gBACZ,EAAE,CAAA,CAAC,KAAI,CAAC,kBAAkB,CAAC,CAAA,CAAC;oBAC1B,OAAO,GAAG,KAAI,CAAC,cAAc,CAAC,KAAI,CAAC,KAAK,EAAC,MAAM,CAAC,CAAA;gBAClD,CAAC;gBAAC,IAAI,CAAC,CAAC;oBACN,OAAO,GAAG,KAAI,CAAC,cAAc,CAAC,KAAI,CAAC,KAAK,EAAE,KAAI,CAAC,EAAE,CAAC,CAAC;gBACrD,CAAC;gBAED,EAAE,CAAC,CAAC,KAAI,CAAC,UAAU,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;oBACvD,KAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC7B,CAAC;gBAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,KAAI,CAAC,UAAU,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;oBAC/D,KAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC7B,CAAC;YACL,CAAC;QACD,CAAC,CAAA;QA3CC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC;IAC7B,CAAC;IAED;;;;OAIG;IACH,4CAAQ,GAAR;QACE,IAAI,CAAC,KAAK,GAAgB,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,0BAA0B,CAAC,CAAC;QAC5E,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;YAAC,MAAM,iCAAiC,CAAC;QAAA,CAAC;QAC5D,IAAI,CAAC,cAAc,EAAE,CAAC;QAEtB,EAAE,CAAA,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAA,CAAC;YAC1B,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACxD,CAAC;QAAC,IAAI,CAAA,CAAC;YACL,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;QAC1D,CAAC;QAED,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;IACzD,CAAC;IAsCH,gCAAC;AAAD,CAlFA,AAkFC;AAbM,oCAAU,GAA0B;IAC3C,EAAE,IAAI,EAAE,gBAAS,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,sBAAsB,EAAE,EAAG,EAAE;CAClE,CAAC;AACF,kBAAkB;AACX,wCAAc,GAAmE,cAAM,OAAA;IAC9F,EAAC,IAAI,EAAE,iBAAU,GAAG;CACnB,EAF6F,CAE7F,CAAC;AACK,wCAAc,GAA2C;IAChE,YAAY,EAAE,CAAC,EAAE,IAAI,EAAE,YAAK,EAAE,EAAE;IAChC,oBAAoB,EAAE,CAAC,EAAE,IAAI,EAAE,YAAK,EAAE,EAAE;IACxC,uBAAuB,EAAE,CAAC,EAAE,IAAI,EAAE,YAAK,EAAE,EAAE;IAC3C,YAAY,EAAE,CAAC,EAAE,IAAI,EAAE,aAAM,EAAE,EAAE;CAChC,CAAC;AAjFW,8DAAyB","file":"infinite-list.directive.js","sourceRoot":""} -------------------------------------------------------------------------------- /dist/infinite-list.directive.metadata.json: -------------------------------------------------------------------------------- 1 | [{"__symbolic":"module","version":3,"metadata":{"NguiInfiniteListDirective":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Directive"},"arguments":[{"selector":"[ngui-infinite-list]"}]}],"members":{"horizontal":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"}}]}],"enableWindowScroll":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"}}]}],"disableScrollListener":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"}}]}],"endVisible":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Output"}}]}],"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"@angular/core","name":"ElementRef"}]}],"ngOnInit":[{"__symbolic":"method"}]}}}},{"__symbolic":"module","version":1,"metadata":{"NguiInfiniteListDirective":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Directive"},"arguments":[{"selector":"[ngui-infinite-list]"}]}],"members":{"horizontal":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"}}]}],"enableWindowScroll":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"}}]}],"disableScrollListener":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"}}]}],"endVisible":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Output"}}]}],"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"@angular/core","name":"ElementRef"}]}],"ngOnInit":[{"__symbolic":"method"}]}}}}] -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ng2-ui/infinite-list/451d7a50295bdebcad60101b72353346281752a8/favicon.ico -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ngui/infinite-list", 3 | "version": "0.6.1", 4 | "description": "Angular2 Infinite List Directive", 5 | "main": "dist/infinite-list.umd.js", 6 | "module": "dist/index.js", 7 | "typings": "dist/index.d.ts", 8 | "license": "MIT", 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/ng2-ui/infinite-list.git" 12 | }, 13 | "author": "Allen Kim ", 14 | "bugs": { 15 | "url": "https://github.com/ng2-ui/infinite-list/issues" 16 | }, 17 | "homepage": "https://github.com/ng2-ui/infinite-list#readme", 18 | "scripts": { 19 | "start": "NODE_ENV=dev webpack-dev-server --quiet --port 9001 --content-base app --config app/webpack.config --open", 20 | "lint": "tslint 'src/**/*.ts' 'app/**/*.ts'", 21 | "clean": "rimraf dist", 22 | "build": "npm-run-all --serial upgrade clean build:ngc build:umd build:app", 23 | "build:ngc": "ngc -p tsconfig.ngc.json", 24 | "build:umd": "NODE_ENV=prod webpack", 25 | "build:app": "NODE_ENV=prod webpack --config app/webpack.config.js", 26 | "upgrade": "npm-check-updates --upgradeAll" 27 | }, 28 | "dependencies": { 29 | "@ngui/utils": "^0.8.1" 30 | }, 31 | "devDependencies": { 32 | "@angular/common": "^4.0.3", 33 | "@angular/compiler": "^4.0.3", 34 | "@angular/compiler-cli": "^4.0.3", 35 | "@angular/core": "^4.0.3", 36 | "@angular/forms": "^4.0.3", 37 | "@angular/http": "^4.0.3", 38 | "@angular/platform-browser": "^4.0.3", 39 | "@angular/platform-browser-dynamic": "^4.0.3", 40 | "@angular/router": "^4.0.3", 41 | "@types/node": "^7.0.13", 42 | "angular2-template-loader": "^0.6.2", 43 | "codelyzer": "^3.0.0", 44 | "core-js": "^2.4.1", 45 | "npm-check-updates": "^2.11.0", 46 | "npm-run-all": "^4.0.2", 47 | "raw-loader": "^0.5.1", 48 | "rimraf": "^2.6.1", 49 | "rxjs": "^5.3.0", 50 | "strip-loader": "^0.1.2", 51 | "ts-loader": "^2.0.3", 52 | "tslint": "^5.1.0", 53 | "typescript": "^2.2.2", 54 | "webpack": "^2.4.1", 55 | "webpack-dev-server": "^2.4.4", 56 | "zone.js": "^0.8.9" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { FormsModule } from "@angular/forms"; 3 | import { BrowserModule } from '@angular/platform-browser'; 4 | 5 | import { NguiInfiniteListDirective } from "./infinite-list.directive"; 6 | 7 | export { 8 | NguiInfiniteListDirective, 9 | }; 10 | 11 | @NgModule({ 12 | imports: [ BrowserModule, FormsModule ], 13 | declarations: [NguiInfiniteListDirective], 14 | exports: [NguiInfiniteListDirective] 15 | }) 16 | export class NguiInfiniteListModule {} 17 | -------------------------------------------------------------------------------- /src/infinite-list.directive.ts: -------------------------------------------------------------------------------- 1 | import {Directive, ElementRef, EventEmitter, Output, Input} from '@angular/core'; 2 | import { elementVisible } from "@ngui/utils"; 3 | 4 | @Directive({ selector: '[ngui-infinite-list]' }) 5 | export class NguiInfiniteListDirective { 6 | 7 | @Input() 8 | public horizontal: boolean; 9 | @Input() 10 | public enableWindowScroll : boolean = false; 11 | @Input() 12 | public disableScrollListener: boolean = false; 13 | 14 | @Output() 15 | public endVisible = new EventEmitter(); 16 | 17 | public el: HTMLElement; 18 | public endEl: HTMLElement; 19 | public elementVisible: any = elementVisible; 20 | 21 | 22 | /** 23 | * Creates an instance of NguiInfiniteListDirective. 24 | * @param {ElementRef} el 25 | * 26 | * @memberOf NguiInfiniteListDirective 27 | */ 28 | constructor(el: ElementRef) { 29 | this.el = el.nativeElement; 30 | } 31 | 32 | /** 33 | * Setup list of sections 34 | * 35 | * @memberOf NguiInfiniteListDirective 36 | */ 37 | ngOnInit(): void { 38 | this.endEl = this.el.querySelector('[ngui-infinite-list-end]'); 39 | if (!this.endEl) { throw "Invalid 'ngui-infinite-list-end";} 40 | this.scrollListener(); 41 | 42 | if(this.enableWindowScroll){ 43 | window.addEventListener('scroll',this.scrollListener); 44 | } else{ 45 | this.el.addEventListener('scroll', this.scrollListener); 46 | } 47 | 48 | window.addEventListener('resize', this.scrollListener); 49 | } 50 | 51 | 52 | /** 53 | * Handles the scroll listener event. 54 | * 55 | * @memberOf NguiInfiniteListDirective 56 | */ 57 | scrollListener = () => { 58 | if (!this.disableScrollListener) { 59 | let visible; 60 | if(this.enableWindowScroll){ 61 | visible = this.elementVisible(this.endEl,window) 62 | } else { 63 | visible = this.elementVisible(this.endEl, this.el); 64 | } 65 | 66 | if (this.horizontal && (visible.left || visible.right)) { 67 | this.endVisible.emit(true); 68 | } else if (!this.horizontal && (visible.top || visible.bottom)) { 69 | this.endVisible.emit(true); 70 | } 71 | } 72 | } 73 | 74 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["es5", "es6", "dom"], 5 | "module": "commonjs", 6 | "moduleResolution": "node", 7 | "emitDecoratorMetadata": true, 8 | "experimentalDecorators": true, 9 | "sourceMap": true, 10 | "pretty": true, 11 | "allowUnreachableCode": true, 12 | "allowUnusedLabels": true, 13 | "noImplicitAny": false, 14 | "noImplicitReturns": false, 15 | "noImplicitUseStrict": false, 16 | "allowSyntheticDefaultImports": true, 17 | "suppressExcessPropertyErrors": true, 18 | "suppressImplicitAnyIndexErrors": true, 19 | "skipDefaultLibCheck": true, 20 | "noEmitHelpers": false, 21 | "isolatedModules": false, 22 | "strictNullChecks": false, 23 | "outDir": "dist", 24 | "baseUrl": "src", 25 | "paths": { 26 | "@ngui/infinite-list": ["./index"] 27 | } 28 | }, 29 | "files": [ 30 | "src/index.ts" 31 | ], 32 | "exclude": [ 33 | "node_modules" 34 | ], 35 | "compileOnSave": false, 36 | "buildOnSave": false, 37 | "angularCompilerOptions": { 38 | "strictMetadataEmit": true, 39 | "skipTemplateCodegen": true 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tsconfig.ngc.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["es5", "es6", "dom"], 5 | "module": "commonjs", 6 | "moduleResolution": "node", 7 | "declaration": true, 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "sourceMap": true, 11 | "pretty": true, 12 | "allowUnreachableCode": true, 13 | "allowUnusedLabels": true, 14 | "noImplicitAny": false, 15 | "noImplicitReturns": false, 16 | "noImplicitUseStrict": false, 17 | "allowSyntheticDefaultImports": true, 18 | "suppressExcessPropertyErrors": true, 19 | "suppressImplicitAnyIndexErrors": true, 20 | "skipDefaultLibCheck": true, 21 | "noEmitHelpers": false, 22 | "isolatedModules": false, 23 | "strictNullChecks": false, 24 | "outDir": "dist", 25 | "baseUrl": "src", 26 | "paths": { 27 | "@ngui/infinite-list": ["./index"] 28 | } 29 | }, 30 | "files": [ 31 | "src/index.ts" 32 | ], 33 | "exclude": [ 34 | "node_modules" 35 | ], 36 | "compileOnSave": false, 37 | "buildOnSave": false, 38 | "angularCompilerOptions": { 39 | "strictMetadataEmit": true, 40 | "skipTemplateCodegen": true 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require("path"); 2 | var webpack = require('webpack'); 3 | 4 | var config = { 5 | entry: { 6 | '@ngui/infinite-list': path.join(__dirname, 'src', 'index.ts') 7 | }, 8 | resolve: { 9 | extensions: ['.ts', '.js', '.json', '.css', '.html'] 10 | }, 11 | resolveLoader: { 12 | modules: [path.join(__dirname, 'node_modules')] 13 | }, 14 | output: { 15 | path: path.join(__dirname, 'dist'), 16 | filename: "infinite-list.umd.js", 17 | library: ["infinite-list"], 18 | libraryTarget: "umd" 19 | }, 20 | externals: [ 21 | /^rxjs\//, //.... any other way? rx.umd.min.js does work? 22 | /^@angular\// 23 | ], 24 | devtool: 'source-map', 25 | module: { 26 | rules: [ 27 | { 28 | test: /\.ts$/, 29 | use: [ 'ts-loader', 'angular2-template-loader' ] 30 | } 31 | ] 32 | } 33 | }; 34 | 35 | //Different Environment Setup 36 | 37 | if (process.env.NODE_ENV === 'prod') { 38 | config.module.rules.push({ 39 | test: /\.ts$/, use: 'strip-loader?strip[]=debug,strip[]=console.log' 40 | }); 41 | } 42 | 43 | module.exports = config; 44 | --------------------------------------------------------------------------------