├── components ├── table │ ├── title.md │ ├── ng-table-paging.directive.ts │ ├── ng-table.component.spec.ts │ ├── ng-table-sorting.directive.ts │ ├── ng-table-filtering.directive.ts │ ├── readme.md │ └── ng-table.component.ts ├── ng-table-directives.ts └── ng-table-module.ts ├── demo ├── custom-typings.d.ts ├── getting-started.md ├── assets │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ ├── glyphicons-halflings-regular.woff2 │ │ └── glyphicons-halflings-regular.svg │ └── css │ │ ├── prism-okaidia.css │ │ ├── style.css │ │ └── glyphicons.css ├── index.ts ├── polyfills.ts ├── vendor.ts ├── components │ ├── table-section.ts │ ├── table │ │ ├── table-demo.html │ │ ├── table-demo.ts │ │ └── table-data.ts │ └── table-section.html ├── demo.module.ts ├── demo.component.ts └── index.html ├── .eslintrc.json ├── karma.conf.js ├── protractor.conf.js ├── gulpfile.js ├── tslint.json ├── .editorconfig ├── .npmignore ├── gulp-tasks └── lint.js ├── .travis.yml ├── .gitignore ├── tsconfig.json ├── .ng2-config.js ├── tsconfig.publish.json ├── ng2-table.ts ├── LICENSE ├── webpack.config.js ├── spec-bundle.js ├── CHANGELOG.md ├── .config └── bundle-system.js ├── package.json ├── README.md └── .eslintrc /components/table/title.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /demo/custom-typings.d.ts: -------------------------------------------------------------------------------- 1 | declare const ENV:string; 2 | -------------------------------------------------------------------------------- /demo/getting-started.md: -------------------------------------------------------------------------------- 1 | # Getting started 2 | 3 | ### First of all, Welcome! 4 | 5 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/eslint-config-valorsoft/.eslintrc.json", 3 | "env": { 4 | "node": true 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const config = require('./.ng2-config'); 4 | 5 | module.exports = require('ng2-webpack-config').karma(config); 6 | -------------------------------------------------------------------------------- /demo/assets/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/valor-software/ng2-table/HEAD/demo/assets/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /demo/assets/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/valor-software/ng2-table/HEAD/demo/assets/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /demo/assets/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/valor-software/ng2-table/HEAD/demo/assets/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /demo/assets/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/valor-software/ng2-table/HEAD/demo/assets/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /protractor.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const config = require('./.ng2-config'); 4 | 5 | module.exports.config = require('ng2-webpack-config').protractor(config); 6 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const gulp = require('gulp'); 4 | 5 | require('require-dir')('./gulp-tasks'); 6 | 7 | gulp.task('default', () => { 8 | gulp.start('lint'); 9 | }); 10 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tslint-config-valorsoft", 3 | "rulesDirectory": "./node_modules/codelyzer", 4 | "rules": { 5 | "component-selector-name": [false, ""], 6 | "only-arrow-functions": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | indent_style = space 8 | indent_size = 2 9 | end_of_line = lf 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true -------------------------------------------------------------------------------- /demo/index.ts: -------------------------------------------------------------------------------- 1 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 2 | import { enableProdMode } from '@angular/core'; 3 | 4 | if (ENV === 'production') { 5 | enableProdMode(); 6 | } 7 | 8 | import { Ng2TableDemoModule } from './demo.module'; 9 | platformBrowserDynamic().bootstrapModule(Ng2TableDemoModule); 10 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .idea 2 | gulp-tasks 3 | logs 4 | 5 | # typings 6 | typings 7 | 8 | # testing 9 | karma.conf.js 10 | spec-bundle.js 11 | coverage 12 | 13 | # demo build 14 | demo 15 | demo-build 16 | webpack.config.js 17 | 18 | #typescript sources 19 | *.ts 20 | *.js.map 21 | !*.d.ts 22 | /components/**/*.ts 23 | !/components/**/*.d.ts 24 | 25 | factories 26 | -------------------------------------------------------------------------------- /components/ng-table-directives.ts: -------------------------------------------------------------------------------- 1 | import { NgTableComponent } from './table/ng-table.component'; 2 | import { NgTableFilteringDirective } from './table/ng-table-filtering.directive'; 3 | import { NgTablePagingDirective } from './table/ng-table-paging.directive'; 4 | import { NgTableSortingDirective } from './table/ng-table-sorting.directive'; 5 | export const NG_TABLE_DIRECTIVES = [NgTableComponent, NgTableFilteringDirective, NgTablePagingDirective, NgTableSortingDirective]; 6 | -------------------------------------------------------------------------------- /gulp-tasks/lint.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const gulp = require('gulp'); 4 | const tslint = require('gulp-tslint'); 5 | const gitignore = require('gitignore-to-glob')(); 6 | 7 | gitignore.push('**/*.ts'); 8 | 9 | gulp.task('tslint', () => 10 | gulp 11 | .src(gitignore) 12 | .pipe(tslint({ 13 | formatter: 'verbose', 14 | emitError: true, 15 | summarizeFailureOutput: true, 16 | reportLimit: 50 17 | })) 18 | .pipe(tslint.report()) 19 | ); 20 | 21 | gulp.task('lint', ['tslint']); 22 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "6" 4 | 5 | before_install: npm i -g npm@latest 6 | 7 | script: 8 | - npm test 9 | 10 | after_success: 11 | - ./node_modules/.bin/codecov -f coverage/coverage-final.json 12 | 13 | addons: 14 | # sauce labs tunel connector (read more https://docs.travis-ci.com/user/sauce-connect/ ) 15 | sauce_connect: true 16 | firefox: "42.0" 17 | apt: 18 | sources: 19 | - ubuntu-toolchain-r-test 20 | # required by node-gyp to build some packages 21 | packages: 22 | - g++-4.8 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependency directory 2 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 3 | /node_modules 4 | npm-debug.log 5 | 6 | # type script artifacts 7 | /typings 8 | 9 | # WebStorm 10 | .idea 11 | 12 | # ignore build and dist for now 13 | /bundles 14 | /demo-build 15 | /dist 16 | /coverage 17 | /ts 18 | 19 | /demo/**/*.js 20 | /demo/**/*.js.map 21 | /demo/**/*.d.ts 22 | !/demo/custom-typings.d.ts 23 | /components/**/*.js 24 | /components/**/*.js.map 25 | /components/**/*.d.ts 26 | ng2-table.js 27 | ng2-table.js.map 28 | ng2-table.d.ts 29 | 30 | /logs 31 | 32 | factories 33 | 34 | /**/*.metadata.json 35 | /**/*.ngfactory.ts 36 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "emitDecoratorMetadata": true, 7 | "experimentalDecorators": true, 8 | "sourceMap": true, 9 | "noEmitHelpers": true, 10 | "noImplicitAny": true, 11 | "declaration": false, 12 | "skipLibCheck": true, 13 | "stripInternal": true, 14 | "lib": ["dom", "es6"], 15 | "types": [ 16 | "jasmine", 17 | "node", 18 | "webpack" 19 | ] 20 | }, 21 | "exclude": [ 22 | "node_modules", "bundles", "dist" 23 | ], 24 | "files": [ 25 | "./demo/custom-typings.d.ts", 26 | "./ng2-table.ts" 27 | ], 28 | "atom": { "rewriteTsconfig": false } 29 | } 30 | -------------------------------------------------------------------------------- /.ng2-config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var pkg = require('./package.json'); 3 | 4 | module.exports = { 5 | // metadata 6 | title: pkg.description, 7 | baseUrl: '/', 8 | // root folder name 9 | src: 'demo', 10 | dist: 'demo-build', 11 | htmlIndexes: ['index.html'], 12 | // karma bundle src 13 | spec: './spec-bundle.js', 14 | // webpack entry 15 | entry: { 16 | polyfills: './demo/polyfills.ts', 17 | vendor: './demo/vendor.ts', 18 | main: './demo/index.ts' 19 | }, 20 | commonChunks: { 21 | name: ['polyfills', 'vendor'].reverse() 22 | }, 23 | // webpack alias 24 | alias: {}, 25 | copy: [ 26 | {from: 'demo/favicon.ico', to: 'favicon.ico'}, 27 | {from: 'demo/assets', to: 'assets'} 28 | ] 29 | }; 30 | -------------------------------------------------------------------------------- /demo/polyfills.ts: -------------------------------------------------------------------------------- 1 | // Polyfills 2 | // (these modules are what are in 'angular2/bundles/angular2-polyfills' so don't use that here) 3 | 4 | // import 'ie-shim'; // Internet Explorer 5 | // import 'es6-shim'; 6 | // import 'es6-promise'; 7 | // import 'es7-reflect-metadata'; 8 | 9 | // Prefer CoreJS over the polyfills above 10 | import 'core-js/es6'; 11 | import 'core-js/es7/reflect'; 12 | require('zone.js/dist/zone'); 13 | require('reflect-metadata'); 14 | 15 | // Typescript emit helpers polyfill 16 | import 'ts-helpers'; 17 | 18 | if ('production' === ENV) { 19 | // Production 20 | 21 | } else { 22 | // Development 23 | 24 | (Error as any).stackTraceLimit = Infinity; 25 | 26 | require('zone.js/dist/long-stack-trace-zone'); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /tsconfig.publish.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "emitDecoratorMetadata": true, 7 | "experimentalDecorators": true, 8 | "sourceMap": false, 9 | "noEmitHelpers": false, 10 | "noImplicitAny": true, 11 | "declaration": true, 12 | "skipLibCheck": true, 13 | "stripInternal": true, 14 | "lib": ["dom", "es6"], 15 | "types": [ 16 | "jasmine", 17 | "node", 18 | "webpack" 19 | ] 20 | }, 21 | "exclude": [ 22 | "node_modules" 23 | ], 24 | "files": [ 25 | "./demo/custom-typings.d.ts", 26 | "./ng2-table.ts" 27 | ], 28 | "angularCompilerOptions": { 29 | "genDir": "factories" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /components/ng-table-module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { NgTableComponent } from './table/ng-table.component'; 5 | import { NgTableFilteringDirective } from './table/ng-table-filtering.directive'; 6 | import { NgTablePagingDirective } from './table/ng-table-paging.directive'; 7 | import { NgTableSortingDirective } from './table/ng-table-sorting.directive'; 8 | 9 | @NgModule({ 10 | imports: [CommonModule], 11 | declarations: [NgTableComponent, NgTableFilteringDirective, NgTablePagingDirective, NgTableSortingDirective], 12 | exports: [NgTableComponent, NgTableFilteringDirective, NgTablePagingDirective, NgTableSortingDirective] 13 | }) 14 | export class Ng2TableModule { 15 | } 16 | -------------------------------------------------------------------------------- /demo/vendor.ts: -------------------------------------------------------------------------------- 1 | // For vendors for example jQuery, Lodash, angular2-jwt just import them here unless you plan on 2 | // chunking vendors files for async loading. You would need to import the async loaded vendors 3 | // at the entry point of the async loaded file. Also see custom-typings.d.ts as you also need to 4 | // run `typings install x` where `x` is your module 5 | 6 | // Angular 2 7 | import '@angular/common'; 8 | import '@angular/core'; 9 | import '@angular/forms'; 10 | import '@angular/platform-browser'; 11 | import '@angular/platform-browser-dynamic'; 12 | 13 | // RxJS 14 | import 'rxjs/add/operator/map'; 15 | import 'rxjs/add/operator/mergeMap'; 16 | 17 | if ('production' === ENV) { 18 | // Production 19 | 20 | } else { 21 | // Development 22 | 23 | } 24 | -------------------------------------------------------------------------------- /components/table/ng-table-paging.directive.ts: -------------------------------------------------------------------------------- 1 | import { Directive, EventEmitter, Input, Output, HostListener } from '@angular/core'; 2 | 3 | @Directive({selector: '[ngTablePaging]'}) 4 | export class NgTablePagingDirective { 5 | @Input() public ngTablePaging:boolean = true; 6 | @Output() public tableChanged:EventEmitter = new EventEmitter(); 7 | 8 | @Input() 9 | public get config():any { 10 | return this.ngTablePaging; 11 | } 12 | 13 | public set config(value:any) { 14 | this.ngTablePaging = value; 15 | } 16 | 17 | @HostListener('pagechanged', ['$event']) 18 | public onChangePage(event:any):void { 19 | // Object.assign(this.config, event); 20 | if (this.ngTablePaging) { 21 | this.tableChanged.emit({paging: event}); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /demo/components/table-section.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | // webpack html imports 3 | let doc = require('../../components/table/readme.md'); 4 | let titleDoc = require('../../components/table/title.md'); 5 | let ts = require('!!prismjs?lang=typescript!./table/table-demo.ts'); 6 | let html = require('!!prismjs?lang=markup!./table/table-demo.html'); 7 | 8 | @Component({ 9 | selector: 'table-section', 10 | template: require('./table-section.html') 11 | }) 12 | export class TableSectionComponent { 13 | public name:string = 'Table'; 14 | public src:string = 'https://github.com/valor-software/ng2-table/tree/master/components/table'; 15 | public ts:string = ts; 16 | public doc:string = doc; 17 | public titleDoc:string = titleDoc; 18 | public html:string = html; 19 | } 20 | -------------------------------------------------------------------------------- /ng2-table.ts: -------------------------------------------------------------------------------- 1 | import { NgTableComponent } from './components/table/ng-table.component'; 2 | 3 | import { NgTableFilteringDirective } from './components/table/ng-table-filtering.directive'; 4 | import { NgTablePagingDirective } from './components/table/ng-table-paging.directive'; 5 | import { NgTableSortingDirective } from './components/table/ng-table-sorting.directive'; 6 | 7 | export * from './components/table/ng-table.component'; 8 | 9 | export * from './components/table/ng-table-filtering.directive'; 10 | export * from './components/table/ng-table-paging.directive'; 11 | export * from './components/table/ng-table-sorting.directive'; 12 | 13 | export * from './components/ng-table-directives'; 14 | 15 | export default { 16 | directives: [ 17 | NgTableComponent, 18 | NgTableFilteringDirective, 19 | NgTableSortingDirective, 20 | NgTablePagingDirective 21 | ] 22 | }; 23 | 24 | export { Ng2TableModule } from './components/ng-table-module'; 25 | -------------------------------------------------------------------------------- /demo/demo.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { FormsModule } from '@angular/forms'; 3 | import { BrowserModule } from '@angular/platform-browser'; 4 | import { CommonModule } from '@angular/common'; 5 | 6 | import { PaginationModule } from 'ng2-bootstrap/ng2-bootstrap'; 7 | import { TabsModule } from 'ng2-bootstrap/ng2-bootstrap'; 8 | 9 | import { Ng2TableModule } from '../components/ng-table-module'; 10 | 11 | import { TableDemoComponent } from './components/table/table-demo'; 12 | import { TableSectionComponent } from './components/table-section'; 13 | 14 | import { DemoComponent } from './demo.component'; 15 | 16 | @NgModule({ 17 | declarations: [ 18 | DemoComponent, 19 | TableDemoComponent, 20 | TableSectionComponent 21 | ], 22 | imports: [ 23 | BrowserModule, 24 | FormsModule, 25 | Ng2TableModule, 26 | PaginationModule, 27 | TabsModule, 28 | CommonModule 29 | ], 30 | providers: [], 31 | bootstrap: [DemoComponent] 32 | }) 33 | 34 | export class Ng2TableDemoModule { 35 | } 36 | -------------------------------------------------------------------------------- /demo/components/table/table-demo.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 7 |
8 |
9 |
10 | 14 | 15 | 25 | 26 |
Page: {{page}} / {{numPages}}
27 | -------------------------------------------------------------------------------- /components/table/ng-table.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 3 | 4 | import { Ng2TableModule } from '../ng-table-module'; 5 | 6 | const html = ``; 7 | 8 | describe('Component: ng2-table', () => { 9 | let fixture:ComponentFixture; 10 | let context:TestTableComponent; 11 | let element:any; 12 | let clean:any; 13 | 14 | beforeEach(() => { 15 | TestBed.configureTestingModule({ 16 | declarations: [TestTableComponent], 17 | imports: [Ng2TableModule] 18 | }); 19 | TestBed.overrideComponent(TestTableComponent, {set: {template: html}}); 20 | fixture = TestBed.createComponent(TestTableComponent); 21 | context = fixture.componentInstance; 22 | element = fixture.nativeElement.querySelector('#c1'); 23 | clean = fixture.nativeElement.querySelector('#c2'); 24 | fixture.detectChanges(); 25 | }); 26 | 27 | it('should be true', () => { 28 | expect(true).toBe(true); 29 | }); 30 | }); 31 | 32 | @Component({ 33 | selector: 'table-test', 34 | template: '' 35 | }) 36 | 37 | class TestTableComponent { 38 | } 39 | -------------------------------------------------------------------------------- /components/table/ng-table-sorting.directive.ts: -------------------------------------------------------------------------------- 1 | import { Directive, EventEmitter, Input, Output, HostListener } from '@angular/core'; 2 | 3 | @Directive({selector: '[ngTableSorting]'}) 4 | export class NgTableSortingDirective { 5 | @Input() public ngTableSorting:any; 6 | @Input() public column:any; 7 | @Output() public sortChanged:EventEmitter = new EventEmitter(); 8 | 9 | @Input() 10 | public get config():any { 11 | return this.ngTableSorting; 12 | } 13 | 14 | public set config(value:any) { 15 | this.ngTableSorting = value; 16 | } 17 | 18 | @HostListener('click', ['$event']) 19 | public onToggleSort(event:any):void { 20 | if (event) { 21 | event.preventDefault(); 22 | } 23 | 24 | if (this.ngTableSorting && this.column && this.column.sort !== false) { 25 | switch (this.column.sort) { 26 | case 'asc': 27 | this.column.sort = 'desc'; 28 | break; 29 | case 'desc': 30 | this.column.sort = ''; 31 | break; 32 | default: 33 | this.column.sort = 'asc'; 34 | break; 35 | } 36 | 37 | this.sortChanged.emit(this.column); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2016 Dmitriy Shekhovtsov 4 | Copyright (c) 2015-2016 Valor Software 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /demo/components/table-section.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

{{name}}(src)

4 | 5 |
6 | 7 |
8 | 9 |
10 |

Example

11 |
12 | 13 |
14 |
15 | 16 |
17 | 18 |
19 | 20 | 21 |
22 |
23 |
24 |
25 | 26 |
27 |
28 |
29 |
30 |
31 |
32 | 33 |
34 | 35 |
36 |

API

37 |
38 |
39 |
40 | -------------------------------------------------------------------------------- /components/table/ng-table-filtering.directive.ts: -------------------------------------------------------------------------------- 1 | import { Directive, EventEmitter, ElementRef, Renderer, HostListener, Input, Output } from '@angular/core'; 2 | 3 | // import {setProperty} from 'angular2/ts/src/core/forms/directives/shared'; 4 | function setProperty(renderer:Renderer, elementRef:ElementRef, propName:string, propValue:any):void { 5 | renderer.setElementProperty(elementRef, propName, propValue); 6 | } 7 | 8 | @Directive({selector: '[ngTableFiltering]'}) 9 | export class NgTableFilteringDirective { 10 | @Input() public ngTableFiltering:any = { 11 | filterString: '', 12 | columnName: 'name' 13 | }; 14 | 15 | @Output() public tableChanged:EventEmitter = new EventEmitter(); 16 | 17 | @Input() 18 | public get config():any { 19 | return this.ngTableFiltering; 20 | } 21 | 22 | public set config(value:any) { 23 | this.ngTableFiltering = value; 24 | } 25 | 26 | private element:ElementRef; 27 | private renderer:Renderer; 28 | 29 | @HostListener('input', ['$event.target.value']) 30 | public onChangeFilter(event:any):void { 31 | this.ngTableFiltering.filterString = event; 32 | this.tableChanged.emit({filtering: this.ngTableFiltering}); 33 | } 34 | 35 | public constructor(element:ElementRef, renderer:Renderer) { 36 | this.element = element; 37 | this.renderer = renderer; 38 | // Set default value for filter 39 | setProperty(this.renderer, this.element, 'value', this.ngTableFiltering.filterString); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /demo/demo.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | let gettingStarted = require('./getting-started.md'); 4 | 5 | @Component({ 6 | selector: 'app', 7 | template: ` 8 |
9 |
10 |

ng2-table

11 |

Native Angular2 directives for Table

12 | View on GitHub 13 |
14 |
15 |
16 |
17 |
18 |
19 | 20 |
21 |
${gettingStarted}
22 | 23 | 24 |
25 | 26 | 31 | ` 32 | }) 33 | export class DemoComponent { 34 | } 35 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | /* eslint no-process-env: 0, global-require:0 */ 2 | /** 3 | * @author: @AngularClass 4 | */ 5 | 'use strict'; 6 | 7 | const reqPrism = require('prismjs'); 8 | const marked = require('marked'); 9 | 10 | marked.Renderer.prototype.code = function renderCode(code, lang) { 11 | const out = this.options.highlight(code, lang); 12 | const classMap = this.options.langPrefix + lang; 13 | 14 | if (!lang) { 15 | return `
${out}\n
`; 16 | } 17 | return `
${out}\n
\n`; 18 | }; 19 | 20 | // Look in ./config folder for webpack.dev.js 21 | const conf = getWebpackConfig(process.env.NODE_ENV, require('./.ng2-config')); 22 | 23 | conf.markdownLoader = { 24 | langPrefix: 'language-', 25 | highlight(code, lang) { 26 | const language = !lang || lang === 'html' ? 'markup' : lang; 27 | const Prism = global.Prism || reqPrism; 28 | 29 | if (!Prism.languages[language]) { 30 | require(`prismjs/components/prism-${language}.js`); 31 | } 32 | return Prism.highlight(code, Prism.languages[language]); 33 | } 34 | }; 35 | 36 | module.exports = conf; 37 | 38 | function getWebpackConfig(env, config) { 39 | switch (env) { 40 | case 'prod': 41 | case 'production': 42 | return require('ng2-webpack-config').webpack.prod(config); 43 | case 'test': 44 | case 'testing': 45 | return require('ng2-webpack-config').webpack.test(config); 46 | case 'dev': 47 | case 'development': 48 | default: 49 | return require('ng2-webpack-config').webpack.dev(config); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Angular2 Table 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 33 | 34 | 35 | 36 | Loading... 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /spec-bundle.js: -------------------------------------------------------------------------------- 1 | /* eslint no-var: 0, vars-on-top: 0 */ 2 | /** 3 | * @author: @AngularClass 4 | */ 5 | 6 | /* 7 | * When testing with webpack and ES6, we have to do some extra 8 | * things to get testing to work right. Because we are gonna write tests 9 | * in ES6 too, we have to compile those as well. That's handled in 10 | * karma.conf.js with the karma-webpack plugin. This is the entry 11 | * file for webpack test. Just like webpack will create a bundle.js 12 | * file for our client, when we run test, it will compile and bundle them 13 | * all here! Crazy huh. So we need to do some setup 14 | */ 15 | 'use strict'; 16 | Error.stackTraceLimit = Infinity; 17 | 18 | require('core-js'); 19 | 20 | // Typescript emit helpers polyfill 21 | require('ts-helpers'); 22 | 23 | require('zone.js/dist/zone'); 24 | require('zone.js/dist/long-stack-trace-zone'); 25 | require('zone.js/dist/async-test'); 26 | require('zone.js/dist/fake-async-test'); 27 | require('zone.js/dist/sync-test'); 28 | require('zone.js/dist/proxy'); 29 | require('zone.js/dist/jasmine-patch'); 30 | 31 | // RxJS 32 | require('rxjs/Rx'); 33 | 34 | var testing = require('@angular/core/testing'); 35 | var browser = require('@angular/platform-browser-dynamic/testing'); 36 | 37 | testing.TestBed.initTestEnvironment( 38 | browser.BrowserDynamicTestingModule, 39 | browser.platformBrowserDynamicTesting() 40 | ); 41 | 42 | Object.assign(global, testing); 43 | 44 | /* 45 | * Ok, this is kinda crazy. We can use the the context method on 46 | * require that webpack created in order to tell webpack 47 | * what files we actually want to require or import. 48 | * Below, context will be an function/object with file names as keys. 49 | * using that regex we are saying look in ./src/app and ./test then find 50 | * any file that ends with spec.js and get its path. By passing in true 51 | * we say do this recursively 52 | */ 53 | var testContext = require.context('./components', true, /\.spec\.ts/); 54 | 55 | /* 56 | * get all the files, for each file, call the context function 57 | * that will require the file and load it up here. Context will 58 | * loop and require those spec files here 59 | */ 60 | function requireAll(requireContext) { 61 | return requireContext.keys().map(requireContext); 62 | } 63 | 64 | // requires and returns all modules that match 65 | requireAll(testContext); 66 | -------------------------------------------------------------------------------- /demo/assets/css/prism-okaidia.css: -------------------------------------------------------------------------------- 1 | /** 2 | * okaidia theme for JavaScript, CSS and HTML 3 | * Loosely based on Monokai textmate theme by http://www.monokai.nl/ 4 | * @author ocodia 5 | */ 6 | 7 | code[class*="language-"], 8 | pre[class*="language-"] { 9 | color: #f8f8f2; 10 | text-shadow: 0 1px rgba(0, 0, 0, 0.3); 11 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; 12 | direction: ltr; 13 | text-align: left; 14 | white-space: pre; 15 | word-spacing: normal; 16 | word-break: normal; 17 | line-height: 1.5; 18 | 19 | -moz-tab-size: 4; 20 | -o-tab-size: 4; 21 | tab-size: 4; 22 | 23 | -webkit-hyphens: none; 24 | -moz-hyphens: none; 25 | -ms-hyphens: none; 26 | hyphens: none; 27 | } 28 | 29 | /* Code blocks */ 30 | pre[class*="language-"] { 31 | padding: 1em; 32 | margin: .5em 0; 33 | overflow: auto; 34 | border-radius: 0.3em; 35 | } 36 | 37 | :not(pre) > code[class*="language-"], 38 | pre[class*="language-"] { 39 | background: #272822; 40 | } 41 | 42 | /* Inline code */ 43 | :not(pre) > code[class*="language-"] { 44 | padding: .1em; 45 | border-radius: .3em; 46 | } 47 | 48 | .token.comment, 49 | .token.prolog, 50 | .token.doctype, 51 | .token.cdata { 52 | color: slategray; 53 | } 54 | 55 | .token.punctuation { 56 | color: #f8f8f2; 57 | } 58 | 59 | .namespace { 60 | opacity: .7; 61 | } 62 | 63 | .token.property, 64 | .token.tag, 65 | .token.constant, 66 | .token.symbol, 67 | .token.deleted { 68 | color: #f92672; 69 | } 70 | 71 | .token.boolean, 72 | .token.number { 73 | color: #ae81ff; 74 | } 75 | 76 | .token.selector, 77 | .token.attr-name, 78 | .token.string, 79 | .token.char, 80 | .token.builtin, 81 | .token.inserted { 82 | color: #a6e22e; 83 | } 84 | 85 | .token.operator, 86 | .token.entity, 87 | .token.url, 88 | .language-css .token.string, 89 | .style .token.string, 90 | .token.variable { 91 | color: #f8f8f2; 92 | } 93 | 94 | .token.atrule, 95 | .token.attr-value, 96 | .token.function { 97 | color: #e6db74; 98 | } 99 | 100 | .token.keyword { 101 | color: #66d9ef; 102 | } 103 | 104 | .token.regex, 105 | .token.important { 106 | color: #fd971f; 107 | } 108 | 109 | .token.important, 110 | .token.bold { 111 | font-weight: bold; 112 | } 113 | .token.italic { 114 | font-style: italic; 115 | } 116 | 117 | .token.entity { 118 | cursor: help; 119 | } 120 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | ## [1.3.2](https://github.com/valor-software/ng2-table/compare/v1.3.1...v1.3.2) (2016-10-07) 3 | 4 | 5 | 6 | 7 | ## [1.3.1](https://github.com/valor-software/ng2-table/compare/v1.3.0...v1.3.1) (2016-10-07) 8 | 9 | 10 | ### Bug Fixes 11 | 12 | * **demo:** demo page link to html fixed ([17764d4](https://github.com/valor-software/ng2-table/commit/17764d4)) 13 | 14 | 15 | ### Features 16 | 17 | * **compiler-cli:** use ngc to generate *.metadata.json ([#308](https://github.com/valor-software/ng2-table/issues/308)) ([0f2b707](https://github.com/valor-software/ng2-table/commit/0f2b707)) 18 | 19 | 20 | 21 | 22 | # [1.3.0](https://github.com/valor-software/ng2-table/compare/v1.1.0...v1.3.0) (2016-10-05) 23 | 24 | 25 | 26 | 27 | # [1.1.0](https://github.com/valor-software/ng2-table/compare/v1.0.2...v1.1.0) (2016-09-05) 28 | 29 | 30 | ### Bug Fixes 31 | 32 | * **sorting:** bug was allowing to sort columns even when they're set to 'false' ([#155](https://github.com/valor-software/ng2-table/issues/155)) ([9621f91](https://github.com/valor-software/ng2-table/commit/9621f91)) 33 | 34 | 35 | ### Features 36 | 37 | * **package:** update dependency version, use [@angular](https://github.com/angular)/forms, fix gulp task ([#232](https://github.com/valor-software/ng2-table/issues/232)) ([026ef38](https://github.com/valor-software/ng2-table/commit/026ef38)) 38 | * **package:** update to rc.5 and use ng2-webpack-config ([#268](https://github.com/valor-software/ng2-table/issues/268)) ([edf3cba](https://github.com/valor-software/ng2-table/commit/edf3cba)) 39 | 40 | 41 | 42 | 43 | ## 1.0.2 (2016-05-18) 44 | 45 | 46 | ### Bug Fixes 47 | 48 | * **sorting:** it does not allow multiple columns to sort (fixes [#40](https://github.com/valor-software/ng2-table/issues/40)) ([47256a6](https://github.com/valor-software/ng2-table/commit/47256a6)), closes [#40](https://github.com/valor-software/ng2-table/issues/40) 49 | 50 | 51 | ### Features 52 | 53 | * **build:** ng-tables updated to common: ([91c07af](https://github.com/valor-software/ng2-table/commit/91c07af)) 54 | * **options:** Allow access to properties that are deeper down the object tree. (fixes [#81](https://github.com/valor-software/ng2-table/issues/81)) ([b7de4ad](https://github.com/valor-software/ng2-table/commit/b7de4ad)), closes [#81](https://github.com/valor-software/ng2-table/issues/81) 55 | * **package:** update to angular 2 rc1 ([#140](https://github.com/valor-software/ng2-table/issues/140)) ([2cade91](https://github.com/valor-software/ng2-table/commit/2cade91)) 56 | 57 | 58 | ### BREAKING CHANGES 59 | 60 | * build: S: 61 | - selector changed from to ngTable to ng-table 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /.config/bundle-system.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 'use strict'; 3 | 4 | /*eslint no-console: 0, no-sync: 0*/ 5 | 6 | // System.js bundler 7 | // simple and yet reusable system.js bundler 8 | // bundles, minifies and gzips 9 | 10 | const fs = require('fs'); 11 | const del = require('del'); 12 | const path = require('path'); 13 | const zlib = require('zlib'); 14 | const async = require('async'); 15 | const Builder = require('systemjs-builder'); 16 | 17 | const pkg = require('../package.json'); 18 | const name = pkg.name; 19 | const targetFolder = path.resolve('./bundles'); 20 | 21 | async.waterfall([ 22 | cleanBundlesFolder, 23 | getSystemJsBundleConfig, 24 | buildSystemJs({minify: false, sourceMaps: true, mangle: false}), 25 | getSystemJsBundleConfig, 26 | buildSystemJs({minify: true, sourceMaps: true, mangle: false}), 27 | gzipSystemJsBundle 28 | ], err => { 29 | if (err) { 30 | throw err; 31 | } 32 | }); 33 | 34 | function getSystemJsBundleConfig(cb) { 35 | const config = { 36 | baseURL: '..', 37 | transpiler: 'typescript', 38 | typescriptOptions: { 39 | module: 'cjs' 40 | }, 41 | map: { 42 | typescript: path.resolve('node_modules/typescript/lib/typescript.js'), 43 | '@angular/core': path.resolve('node_modules/@angular/core/index.js'), 44 | '@angular/common': path.resolve('node_modules/@angular/common/index.js'), 45 | '@angular/compiler': path.resolve('node_modules/@angular/compiler/index.js'), 46 | '@angular/platform-browser': path.resolve('node_modules/@angular/platform-browser/index.js'), 47 | '@angular/platform-browser-dynamic': path.resolve('node_modules/@angular/platform-browser-dynamic/'), 48 | rxjs: path.resolve('node_modules/rxjs') 49 | }, 50 | paths: { 51 | '*': '*.js' 52 | } 53 | }; 54 | 55 | config.meta = ['@angular/common','@angular/compiler','@angular/core', 56 | '@angular/platform-browser','@angular/platform-browser-dynamic', 'rxjs'].reduce((memo, currentValue) => { 57 | memo[path.resolve(`node_modules/${currentValue}/*`)] = {build: false}; 58 | return memo; 59 | }, {}); 60 | config.meta.moment = {build: false}; 61 | return cb(null, config); 62 | } 63 | 64 | function cleanBundlesFolder(cb) { 65 | return del(targetFolder) 66 | .then(paths => { 67 | console.log('Deleted files and folders:\n', paths.join('\n')); 68 | cb(); 69 | }); 70 | } 71 | 72 | function buildSystemJs(options) { 73 | return (config, cb) => { 74 | const minPostFix = options && options.minify ? '.min' : ''; 75 | const fileName = `${name}${minPostFix}.js`; 76 | const dest = path.resolve(__dirname, targetFolder, fileName); 77 | const builder = new Builder(); 78 | 79 | console.log('Bundling system.js file:', fileName, options); 80 | builder.config(config); 81 | return builder 82 | .bundle([name, name].join('/'), dest, options) 83 | .then(() => cb()) 84 | .catch(cb); 85 | }; 86 | } 87 | 88 | function gzipSystemJsBundle(cb) { 89 | const files = fs 90 | .readdirSync(path.resolve(targetFolder)) 91 | .map(file => path.resolve(targetFolder, file)) 92 | .filter(file => fs.statSync(file).isFile()) 93 | .filter(file => path.extname(file) !== 'gz'); 94 | 95 | return async.eachSeries(files, (file, gzipcb) => { 96 | process.nextTick(() => { 97 | console.log('Gzipping ', file); 98 | const gzip = zlib.createGzip({level: 9}); 99 | const inp = fs.createReadStream(file); 100 | const out = fs.createWriteStream(`${file}.gz`); 101 | 102 | inp.on('end', () => gzipcb()); 103 | inp.on('error', err => gzipcb(err)); 104 | return inp.pipe(gzip).pipe(out); 105 | }); 106 | }, cb); 107 | } 108 | -------------------------------------------------------------------------------- /components/table/readme.md: -------------------------------------------------------------------------------- 1 | ### Usage 2 | ```typescript 3 | import { Ng2TableModule } from 'ng2-table/ng2-table'; 4 | ``` 5 | or if you want to import specified plugins (Table component is required, the others are optional): 6 | ```typescript 7 | import { NgTableComponent, NgTableFilteringDirective, NgTablePagingDirective, NgTableSortingDirective } from 'ng2-table/ng2-table'; 8 | ``` 9 | in this case, don't forget to include all of the imported entities to your module 10 | 11 | ### Utilisation 12 | 13 | There are only simple table with 3 plugins/directives: `filtering`, `paging`, `sorting`. You don't need special `config` variable for storing settings for all plugins as is used in demo example. It's just showing usage sample. 14 | 15 | ### Inputs (Properties) 16 | 17 | - `page` (`number`) - the default page after the table component loading 18 | - `itemsPerPage` (`number`) - number of the displaying items (rows) on a page 19 | - `maxSize` (`number`) - number of the displaying pages before `...` 20 | - `numPages` (`number`) - total number of the pages 21 | - `length` (`number`) - total number of the items after filtering (of it's chosen) 22 | 23 | - `config` (`?any`) - config for setup all plugins (filtering, sorting, paging): 24 | - `paging` (`?boolean`) - - switch on the paging plugin 25 | - `sorting` (`?any`) - switch on the sorting plugin 26 | - `columns` (`Array`) - only list of the columns for sorting 27 | - `filtering` (`?any`) - switch on the filtering plugin 28 | - `filterString` (`string`) - the default value for filter 29 | - `columnName` (`string`) - the property name in raw data 30 | - `className` (`string|Array`) - additional CSS classes that should be added to a 31 | 32 | - `rows` (`?Array`) - only list of the rows which should be displayed 33 | - `columns` (`?Array`) - config for columns (+ sorting settings if it's needed) 34 | - `title` (`string`) - the title of column header 35 | - `name` (`string`) - the property name in data 36 | - `sort` (`?string|boolean`) - config for columns (+ sorting settings if it's needed), sorting is switched on by default for each column 37 | - `className` (`string|Array`) - additional CSS classes that should be added to a column header 38 | - `filtering` (`?any`) - switch on the filtering plugin 39 | - `filterString` (`string`) - the default value for filter 40 | - `columnName` (`string`) - the property name in raw data 41 | 42 | ### Outputs (Events) 43 | 44 | - `tableChanged`: data change event handler 45 | - `cellClicked`: onclick event handler 46 | 47 | ### Filter 48 | 49 | The responsibility of the filtering issue falls on user. You should choose on which columns the filter would be applied. You could add any number of different filters. 50 | Filter string - it's a string for matching values in raw data. Column name refers to the property name in raw data. The rest logic you could organize by yourself (the order of filters, data formats, etc). Even you could use filter for list of data columns. 51 | 52 | You can also set up `filtering` param for columns, in this case filter box will appear in first row of the table. 53 | 54 | ### Sorting 55 | 56 | Data sorting could be in 3 modes: asc, desc and without sorting data (as it comes from backend or somewhere else). If you want to switch off the sorting for some of the columns then you should set it forcibly in columns config (set property sort to false value for each column you want) 57 | 58 | ### Paging 59 | 60 | Pagination could be used from [ng2-bootstrap](https://github.com/valor-software/ng2-bootstrap) - [pagination component](http://valor-software.github.io/ng2-bootstrap/#pagination). When the page is changed, the pagination component will emit event `tableChanged` with an object {page, itemsPerPage}. Then you can easily subscribe on it and request corresponding raw data. 61 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ng2-table", 3 | "version": "1.3.2", 4 | "description": "Simple angular2 table components with sorting, filtering...", 5 | "scripts": { 6 | "flow.compile": "npm run flow.compile:common && npm run flow.compile:system ", 7 | "flow.compile:common": "ngc -p tsconfig.publish.json", 8 | "flow.compile:system": "node ./.config/bundle-system.js", 9 | "flow.copy:src": "cpy ng2-table.ts \"components/*.ts\" ts --parents", 10 | "flow.clean": "del-cli bundles coverage demo-build \"components/**/*.+(js|d.ts|js.map|metadata.json)\" dist \"ng2-table.+(js|d.ts|js.map|metadata.json)\" factories", 11 | "flow.deploy:gh-pages": "npm run flow.build:prod && gh-pages -d demo-build", 12 | "flow.eslint": "eslint --ignore-path .gitignore --ext js --fix . .config", 13 | "flow.tslint": "gulp lint", 14 | "flow.lint": "npm run flow.eslint && npm run flow.tslint", 15 | "flow.changelog": "conventional-changelog -i CHANGELOG.md -s -p angular -v", 16 | "flow.github-release": "conventional-github-releaser -p angular", 17 | "flow.build:prod": "NODE_ENV=production webpack --progress --color", 18 | "flow.build:dev": "webpack --progress --color", 19 | "flow.serve:dev": "webpack-dev-server --hot --inline --colors --display-error-details --display-cached", 20 | "flow.serve:prod": "NODE_ENV=production webpack-dev-server --hot --inline --colors --display-error-details --display-cached", 21 | "prepublish": "npm run flow.clean && npm run flow.compile", 22 | "postpublish": "npm run flow.deploy:gh-pages", 23 | "start": "npm run flow.serve:dev", 24 | "pretest": "npm run flow.lint", 25 | "test": "NODE_ENV=test karma start", 26 | "preversion": "npm test", 27 | "version": "npm run flow.changelog && git add -A", 28 | "postversion": "git push origin development && git push --tags" 29 | }, 30 | "main": "ng2-table.js", 31 | "typings": "ng2-table.d.ts", 32 | "keywords": [ 33 | "angular2", 34 | "angularjs", 35 | "table", 36 | "filter", 37 | "sort" 38 | ], 39 | "author": "Dmitriy Shekhovtsov ", 40 | "license": "MIT", 41 | "repository": { 42 | "type": "git", 43 | "url": "git+ssh://git@github.com/valor-software/ng2-table.git" 44 | }, 45 | "bugs": { 46 | "url": "https://github.com/valor-software/ng2-table/issues" 47 | }, 48 | "homepage": "https://github.com/valor-software/ng2-table#readme", 49 | "dependencies": {}, 50 | "peerDependencies": { 51 | "@angular/common": "^2.0.0", 52 | "@angular/compiler": "^2.0.0", 53 | "@angular/core": "^2.0.0", 54 | "@angular/forms": "^2.0.0" 55 | }, 56 | "devDependencies": { 57 | "@angular/common": "2.0.1", 58 | "@angular/compiler": "2.0.1", 59 | "@angular/compiler-cli": "0.6.3", 60 | "@angular/core": "2.0.1", 61 | "@angular/forms": "2.0.1", 62 | "@angular/platform-browser": "2.0.1", 63 | "@angular/platform-browser-dynamic": "2.0.1", 64 | "@angular/platform-server": "2.0.1", 65 | "@types/jasmine": "2.2.34", 66 | "@types/node": "6.0.42", 67 | "@types/webpack": "1.12.34", 68 | "async": "2.0.1", 69 | "codecov": "1.0.1", 70 | "conventional-changelog-cli": "1.2.0", 71 | "conventional-github-releaser": "1.1.3", 72 | "cpy-cli": "1.0.1", 73 | "del-cli": "0.2.0", 74 | "es6-promise": "4.0.5", 75 | "es6-shim": "0.35.1", 76 | "es7-reflect-metadata": "1.6.0", 77 | "eslint-config-valorsoft": "0.1.0", 78 | "gh-pages": "0.11.0", 79 | "gitignore-to-glob": "0.2.1", 80 | "gulp": "3.9.1", 81 | "gulp-size": "2.1.0", 82 | "gulp-tslint": "6.1.2", 83 | "lite-server": "2.2.2", 84 | "marked": "0.3.6", 85 | "ng2-bootstrap": "1.1.8", 86 | "ng2-webpack-config": "0.0.5", 87 | "pre-commit": "1.1.3", 88 | "prismjs": "1.5.1", 89 | "prismjs-loader": "0.0.4", 90 | "reflect-metadata": "0.1.8", 91 | "require-dir": "0.3.0", 92 | "rxjs": "5.0.0-beta.12", 93 | "systemjs-builder": "0.15.32", 94 | "tslint-config-valorsoft": "1.1.1", 95 | "typescript": "2.0.3", 96 | "zone.js": "0.6.25" 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /components/table/ng-table.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, EventEmitter, Input, Output } from '@angular/core'; 2 | import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; 3 | 4 | @Component({ 5 | selector: 'ng-table', 6 | template: ` 7 |
9 | 10 | 11 | 17 | 18 | 19 | 20 | 21 | 28 | 29 | 30 | 31 | 32 | 33 |
13 | {{column.title}} 14 | 16 |
22 | 27 |
34 | ` 35 | }) 36 | export class NgTableComponent { 37 | // Table values 38 | @Input() public rows:Array = []; 39 | 40 | @Input() 41 | public set config(conf:any) { 42 | if (!conf.className) { 43 | conf.className = 'table-striped table-bordered'; 44 | } 45 | if (conf.className instanceof Array) { 46 | conf.className = conf.className.join(' '); 47 | } 48 | this._config = conf; 49 | } 50 | 51 | // Outputs (Events) 52 | @Output() public tableChanged:EventEmitter = new EventEmitter(); 53 | @Output() public cellClicked:EventEmitter = new EventEmitter(); 54 | 55 | public showFilterRow:Boolean = false; 56 | 57 | @Input() 58 | public set columns(values:Array) { 59 | values.forEach((value:any) => { 60 | if (value.filtering) { 61 | this.showFilterRow = true; 62 | } 63 | if (value.className && value.className instanceof Array) { 64 | value.className = value.className.join(' '); 65 | } 66 | let column = this._columns.find((col:any) => col.name === value.name); 67 | if (column) { 68 | Object.assign(column, value); 69 | } 70 | if (!column) { 71 | this._columns.push(value); 72 | } 73 | }); 74 | } 75 | 76 | private _columns:Array = []; 77 | private _config:any = {}; 78 | 79 | public constructor(private sanitizer:DomSanitizer) { 80 | } 81 | 82 | public sanitize(html:string):SafeHtml { 83 | return this.sanitizer.bypassSecurityTrustHtml(html); 84 | } 85 | 86 | public get columns():Array { 87 | return this._columns; 88 | } 89 | 90 | public get config():any { 91 | return this._config; 92 | } 93 | 94 | public get configColumns():any { 95 | let sortColumns:Array = []; 96 | 97 | this.columns.forEach((column:any) => { 98 | if (column.sort) { 99 | sortColumns.push(column); 100 | } 101 | }); 102 | 103 | return {columns: sortColumns}; 104 | } 105 | 106 | public onChangeTable(column:any):void { 107 | this._columns.forEach((col:any) => { 108 | if (col.name !== column.name && col.sort !== false) { 109 | col.sort = ''; 110 | } 111 | }); 112 | this.tableChanged.emit({sorting: this.configColumns}); 113 | } 114 | 115 | public getData(row:any, propertyName:string):string { 116 | return propertyName.split('.').reduce((prev:any, curr:string) => prev[curr], row); 117 | } 118 | 119 | public cellClick(row:any, column:any):void { 120 | this.cellClicked.emit({row, column}); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /demo/components/table/table-demo.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { TableData } from './table-data'; 3 | 4 | // webpack html imports 5 | let template = require('./table-demo.html'); 6 | 7 | @Component({ 8 | selector: 'table-demo', 9 | template 10 | }) 11 | export class TableDemoComponent implements OnInit { 12 | public rows:Array = []; 13 | public columns:Array = [ 14 | {title: 'Name', name: 'name', filtering: {filterString: '', placeholder: 'Filter by name'}}, 15 | { 16 | title: 'Position', 17 | name: 'position', 18 | sort: false, 19 | filtering: {filterString: '', placeholder: 'Filter by position'} 20 | }, 21 | {title: 'Office', className: ['office-header', 'text-success'], name: 'office', sort: 'asc'}, 22 | {title: 'Extn.', name: 'ext', sort: '', filtering: {filterString: '', placeholder: 'Filter by extn.'}}, 23 | {title: 'Start date', className: 'text-warning', name: 'startDate'}, 24 | {title: 'Salary ($)', name: 'salary'} 25 | ]; 26 | public page:number = 1; 27 | public itemsPerPage:number = 10; 28 | public maxSize:number = 5; 29 | public numPages:number = 1; 30 | public length:number = 0; 31 | 32 | public config:any = { 33 | paging: true, 34 | sorting: {columns: this.columns}, 35 | filtering: {filterString: ''}, 36 | className: ['table-striped', 'table-bordered'] 37 | }; 38 | 39 | private data:Array = TableData; 40 | 41 | public constructor() { 42 | this.length = this.data.length; 43 | } 44 | 45 | public ngOnInit():void { 46 | this.onChangeTable(this.config); 47 | } 48 | 49 | public changePage(page:any, data:Array = this.data):Array { 50 | let start = (page.page - 1) * page.itemsPerPage; 51 | let end = page.itemsPerPage > -1 ? (start + page.itemsPerPage) : data.length; 52 | return data.slice(start, end); 53 | } 54 | 55 | public changeSort(data:any, config:any):any { 56 | if (!config.sorting) { 57 | return data; 58 | } 59 | 60 | let columns = this.config.sorting.columns || []; 61 | let columnName:string = void 0; 62 | let sort:string = void 0; 63 | 64 | for (let i = 0; i < columns.length; i++) { 65 | if (columns[i].sort !== '' && columns[i].sort !== false) { 66 | columnName = columns[i].name; 67 | sort = columns[i].sort; 68 | } 69 | } 70 | 71 | if (!columnName) { 72 | return data; 73 | } 74 | 75 | // simple sorting 76 | return data.sort((previous:any, current:any) => { 77 | if (previous[columnName] > current[columnName]) { 78 | return sort === 'desc' ? -1 : 1; 79 | } else if (previous[columnName] < current[columnName]) { 80 | return sort === 'asc' ? -1 : 1; 81 | } 82 | return 0; 83 | }); 84 | } 85 | 86 | public changeFilter(data:any, config:any):any { 87 | let filteredData:Array = data; 88 | this.columns.forEach((column:any) => { 89 | if (column.filtering) { 90 | filteredData = filteredData.filter((item:any) => { 91 | return item[column.name].match(column.filtering.filterString); 92 | }); 93 | } 94 | }); 95 | 96 | if (!config.filtering) { 97 | return filteredData; 98 | } 99 | 100 | if (config.filtering.columnName) { 101 | return filteredData.filter((item:any) => 102 | item[config.filtering.columnName].match(this.config.filtering.filterString)); 103 | } 104 | 105 | let tempArray:Array = []; 106 | filteredData.forEach((item:any) => { 107 | let flag = false; 108 | this.columns.forEach((column:any) => { 109 | if (item[column.name].toString().match(this.config.filtering.filterString)) { 110 | flag = true; 111 | } 112 | }); 113 | if (flag) { 114 | tempArray.push(item); 115 | } 116 | }); 117 | filteredData = tempArray; 118 | 119 | return filteredData; 120 | } 121 | 122 | public onChangeTable(config:any, page:any = {page: this.page, itemsPerPage: this.itemsPerPage}):any { 123 | if (config.filtering) { 124 | Object.assign(this.config.filtering, config.filtering); 125 | } 126 | 127 | if (config.sorting) { 128 | Object.assign(this.config.sorting, config.sorting); 129 | } 130 | 131 | let filteredData = this.changeFilter(this.data, this.config); 132 | let sortedData = this.changeSort(filteredData, this.config); 133 | this.rows = page && config.paging ? this.changePage(page, sortedData) : sortedData; 134 | this.length = sortedData.length; 135 | } 136 | 137 | public onCellClick(data: any): any { 138 | console.log(data); 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ng2-table [![npm version](https://badge.fury.io/js/ng2-table.svg)](http://badge.fury.io/js/ng2-table) 2 | Simple table extension with sorting, filtering, paging... for Angular2 apps 3 | 4 | Follow me [![twitter](https://img.shields.io/twitter/follow/valorkin.svg?style=social&label=%20valorkin)](https://twitter.com/valorkin) to be notified about new releases. 5 | 6 | [![Angular 2 Style Guide](https://mgechev.github.io/angular2-style-guide/images/badge.svg)](https://github.com/mgechev/angular2-style-guide) 7 | [![Build Status](https://travis-ci.org/valor-software/ng2-table.svg?branch=master)](https://travis-ci.org/valor-software/ng2-table) 8 | [![Code Climate](https://codeclimate.com/github/valor-software/ng2-table/badges/gpa.svg)](https://codeclimate.com/github/valor-software/ng2-table) 9 | [![Join the chat at https://gitter.im/valor-software/ng2-bootstrap](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/valor-software/ng2-bootstrap?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 10 | [![Dependency Status](https://david-dm.org/valor-software/ng2-table.svg)](https://david-dm.org/valor-software/ng2-table) 11 | [![devDependency Status](https://david-dm.org/valor-software/ng2-table/dev-status.svg)](https://david-dm.org/valor-software/ng2-table#info=devDependencies) 12 | [![Throughput Graph](https://graphs.waffle.io/valor-software/ng2-table/throughput.svg)](https://waffle.io/valor-software/ng2-table/metrics) 13 | 14 | # Usage & Demo 15 | [http://valor-software.github.io/ng2-table/](http://valor-software.github.io/ng2-table/) 16 | 17 | 18 | - - - 19 | 20 | ## Installation 21 | 22 | 1. A recommended way to install ***ng2-table*** is through [npm](https://www.npmjs.com/search?q=ng2-table) package manager using the following command: 23 | 24 | ```bash 25 | npm i ng2-table --save 26 | ``` 27 | 28 | Alternatively, you can [download it in a ZIP file](https://github.com/valor-software/ng2-table/archive/master.zip). 29 | 30 | 2. More information regarding using of ***ng2-table*** is located in 31 | [demo](http://valor-software.github.io/ng2-table/) and [demo sources](https://github.com/valor-software/ng2-table/tree/master/demo). 32 | 33 | ## Documentation 34 | 35 | ### Inputs (Properties) 36 | 37 | - `page` (`number`) - the default page after the table component loading 38 | - `itemsPerPage` (`number`) - number of the displaying items (rows) on a page 39 | - `maxSize` (`number`) - number of the displaying pages before `...` 40 | - `numPages` (`number`) - total number of the pages 41 | - `length` (`number`) - total number of the items after filtering (of it's chosen) 42 | 43 | - `config` (`?any`) - config for setup all plugins (filtering, sorting, paging): 44 | - `paging` (`?boolean`) - - switch on the paging plugin 45 | - `sorting` (`?any`) - switch on the sorting plugin 46 | - `columns` (`Array`) - only list of the columns for sorting 47 | - `filtering` (`?any`) - switch on the filtering plugin 48 | - `filterString` (`string`) - the default value for filter 49 | - `columnName` (`string`) - the property name in raw data 50 | - `className` (`string|Array`) - additional CSS classes that should be added to a 51 | 52 | - `rows` (`?Array`) - only list of the rows which should be displayed 53 | - `columns` (`?Array`) - config for columns (+ sorting settings if it's needed) 54 | - `title` (`string`) - the title of column header 55 | - `name` (`string`) - the property name in data 56 | - `sort` (`?string|boolean`) - config for columns (+ sorting settings if it's needed), sorting is switched on by default for each column 57 | - `className` (`string|Array`) - additional CSS classes that should be added to a column header 58 | - `filtering` (`?any`) - switch on the filtering plugin 59 | - `filterString` (`string`) - the default value for filter 60 | - `columnName` (`string`) - the property name in raw data 61 | 62 | ### Outputs (Events) 63 | 64 | - `tableChanged`: data change event handler 65 | - `cellClicked`: onclick event handler 66 | 67 | ### Filter 68 | 69 | The responsibility of the filtering issue falls on user. You should choose on which columns the filter would be applied. You could add any number of different filters. 70 | Filter string - it's a string for matching values in raw data. Column name refers to the property name in raw data. The rest logic you could organize by yourself (the order of filters, data formats, etc). Even you could use filter for list of data columns. 71 | 72 | You can also set up `filtering` param for columns, in this case filter box will appear in first row of the table. 73 | 74 | ### Sorting 75 | 76 | Data sorting could be in 3 modes: asc, desc and without sorting data (as it comes from backend or somewhere else). If you want to switch off the sorting for some of the columns then you should set it forcibly in columns config (set property sort to false value for each column you want) 77 | 78 | ### Paging 79 | 80 | Pagination could be used from [ng2-bootstrap](https://github.com/valor-software/ng2-bootstrap) - [pagination component](http://valor-software.github.io/ng2-bootstrap/#pagination). When the page is changed, the pagination component will emit event `change-table` with an object {page, itemsPerPage}. Then you can easily subscribe on it and request corresponding raw data. 81 | 82 | 83 | ## Troubleshooting 84 | 85 | Please follow this guidelines when reporting bugs and feature requests: 86 | 87 | 1. Use [GitHub Issues](https://github.com/valor-software/ng2-table/issues) board to report bugs and feature requests (not our email address) 88 | 2. Please **always** write steps to reproduce the error. That way we can focus on fixing the bug, not scratching our heads trying to reproduce it. 89 | 90 | Thanks for understanding! 91 | 92 | ### License 93 | 94 | The MIT License (see the [LICENSE](https://github.com/valor-software/ng2-table/blob/master/LICENSE) file for the full text) 95 | -------------------------------------------------------------------------------- /demo/assets/css/style.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Docs (http://getbootstrap.com) 3 | * Copyright 2011-2014 Twitter, Inc. 4 | * Licensed under the Creative Commons Attribution 3.0 Unported License. For 5 | * details, see http://creativecommons.org/licenses/by/3.0/. 6 | */ 7 | 8 | .h1, .h2, .h3, h1, h2, h3 { 9 | margin-top: 20px; 10 | margin-bottom: 10px; 11 | } 12 | 13 | .h1, h1 { 14 | font-size: 36px; 15 | } 16 | 17 | .btn-group-lg > .btn, .btn-lg { 18 | font-size: 18px; 19 | } 20 | 21 | section { 22 | padding-top: 30px; 23 | } 24 | 25 | .bd-pageheader { 26 | margin-top: 51px; 27 | } 28 | 29 | .page-header { 30 | padding-bottom: 9px; 31 | margin: 40px 0 20px; 32 | border-bottom: 1px solid #eee; 33 | } 34 | 35 | .navbar-default .navbar-nav > li > a { 36 | color: #777; 37 | } 38 | 39 | .navbar { 40 | padding: 0; 41 | } 42 | 43 | .navbar-nav .nav-item { 44 | margin-left: 0 !important; 45 | } 46 | 47 | .nav > li > a { 48 | position: relative; 49 | display: block; 50 | padding: 10px 15px; 51 | } 52 | 53 | .nav .navbar-brand { 54 | float: left; 55 | height: 50px; 56 | padding: 15px 15px; 57 | font-size: 18px; 58 | line-height: 20px; 59 | margin-right: 0 !important; 60 | } 61 | 62 | .navbar-brand { 63 | color: #777; 64 | float: left; 65 | height: 50px; 66 | padding: 15px 15px; 67 | font-size: 18px; 68 | line-height: 20px; 69 | } 70 | 71 | .navbar-toggler { 72 | margin-top: 8px; 73 | margin-right: 15px; 74 | } 75 | 76 | .navbar-default .navbar-nav > li > a:focus, .navbar-default .navbar-nav > li > a:hover { 77 | color: #333; 78 | background-color: transparent; 79 | } 80 | 81 | .bd-pageheader, .bs-docs-masthead { 82 | position: relative; 83 | padding: 30px 0; 84 | color: #cdbfe3; 85 | text-align: center; 86 | text-shadow: 0 1px 0 rgba(0, 0, 0, .1); 87 | background-color: #6f5499; 88 | background-image: -webkit-gradient(linear, left top, left bottom, from(#563d7c), to(#6f5499)); 89 | background-image: -webkit-linear-gradient(top, #563d7c 0, #6f5499 100%); 90 | background-image: -o-linear-gradient(top, #563d7c 0, #6f5499 100%); 91 | background-image: linear-gradient(to bottom, #563d7c 0, #6f5499 100%); 92 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#563d7c', endColorstr='#6F5499', GradientType=0); 93 | background-repeat: repeat-x; 94 | } 95 | 96 | .bd-pageheader { 97 | margin-bottom: 40px; 98 | font-size: 20px; 99 | } 100 | 101 | .bd-pageheader h1 { 102 | margin-top: 0; 103 | color: #fff; 104 | } 105 | 106 | .bd-pageheader p { 107 | margin-bottom: 0; 108 | font-weight: 300; 109 | line-height: 1.4; 110 | } 111 | 112 | .bd-pageheader .btn { 113 | margin: 10px 0; 114 | } 115 | 116 | .scrollable-menu .nav-link { 117 | color: #337ab7; 118 | font-size: 14px; 119 | } 120 | 121 | .scrollable-menu .nav-link:hover { 122 | color: #23527c; 123 | background-color: #eee; 124 | } 125 | 126 | @media (min-width: 992px) { 127 | .bd-pageheader h1, .bd-pageheader p { 128 | margin-right: 380px; 129 | } 130 | } 131 | 132 | @media (min-width: 768px) { 133 | .bd-pageheader { 134 | padding-top: 60px; 135 | padding-bottom: 60px; 136 | font-size: 24px; 137 | text-align: left; 138 | } 139 | 140 | .bd-pageheader h1 { 141 | font-size: 60px; 142 | line-height: 1; 143 | } 144 | 145 | .navbar-nav > li > a.nav-link { 146 | padding-top: 15px; 147 | padding-bottom: 15px; 148 | font-size: 14px; 149 | } 150 | 151 | .navbar > .container .navbar-brand, .navbar > .container-fluid .navbar-brand { 152 | margin-left: -15px; 153 | } 154 | } 155 | 156 | @media (max-width: 767px) { 157 | .hidden-xs { 158 | display: none !important; 159 | } 160 | 161 | .navbar .container { 162 | width: 100%; 163 | max-width: 100%; 164 | } 165 | .navbar .container, 166 | .navbar .container .navbar-header { 167 | padding: 0; 168 | margin: 0; 169 | } 170 | } 171 | 172 | @media (max-width: 400px) { 173 | code, kbd { 174 | font-size: 60%; 175 | } 176 | } 177 | 178 | /** 179 | * VH and VW units can cause issues on iOS devices: http://caniuse.com/#feat=viewport-units 180 | * 181 | * To overcome this, create media queries that target the width, height, and orientation of iOS devices. 182 | * It isn't optimal, but there is really no other way to solve the problem. In this example, I am fixing 183 | * the height of element '.scrollable-menu' —which is a full width and height cover image. 184 | * 185 | * iOS Resolution Quick Reference: http://www.iosres.com/ 186 | */ 187 | 188 | .scrollable-menu { 189 | height: 90vh !important; 190 | width: 100vw; 191 | overflow-x: hidden; 192 | padding: 0 0 20px; 193 | } 194 | 195 | /** 196 | * iPad with portrait orientation. 197 | */ 198 | @media all and (device-width: 768px) and (device-height: 1024px) and (orientation: portrait) { 199 | .scrollable-menu { 200 | height: 1024px !important; 201 | } 202 | } 203 | 204 | /** 205 | * iPad with landscape orientation. 206 | */ 207 | @media all and (device-width: 768px) and (device-height: 1024px) and (orientation: landscape) { 208 | .scrollable-menu { 209 | height: 768px !important; 210 | } 211 | } 212 | 213 | /** 214 | * iPhone 5 215 | * You can also target devices with aspect ratio. 216 | */ 217 | @media screen and (device-aspect-ratio: 40/71) { 218 | .scrollable-menu { 219 | height: 500px !important; 220 | } 221 | } 222 | 223 | .navbar-default .navbar-toggle .icon-bar { 224 | background-color: #888; 225 | } 226 | 227 | .navbar-toggle:focus { 228 | outline: 0 229 | } 230 | 231 | .navbar-toggle .icon-bar { 232 | display: block; 233 | width: 22px; 234 | height: 2px; 235 | border-radius: 1px 236 | } 237 | 238 | .navbar-toggle .icon-bar + .icon-bar { 239 | margin-top: 4px 240 | } 241 | 242 | pre { 243 | white-space: pre-wrap; /* CSS 3 */ 244 | white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ 245 | white-space: -pre-wrap; /* Opera 4-6 */ 246 | white-space: -o-pre-wrap; /* Opera 7 */ 247 | word-wrap: break-word; /* Internet Explorer 5.5+ */ 248 | } 249 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": 2, 4 | "node": 2, 5 | "mocha": 2, 6 | "es6": 2 7 | }, 8 | "ecmaFeatures": { 9 | "modules": true 10 | }, 11 | "globals": { 12 | "_": 2, 13 | "$": 2, 14 | "angular": 2, 15 | "jQuery": 2 16 | }, 17 | "rules": { 18 | // Possible Errors 19 | "comma-dangle": 2, 20 | // no-comma-dangle - (deprecated) 21 | "no-cond-assign": [2, "always"], 22 | "no-console": 2, 23 | "no-constant-condition": 2, 24 | "no-control-regex": 2, 25 | "no-debugger": 2, 26 | "no-dupe-keys": 2, 27 | "no-dupe-args": 2, 28 | "no-duplicate-case": 2, 29 | "no-empty-character-class": 2, 30 | // no-empty-class - (deprecated) 31 | "no-empty": 2, 32 | "no-ex-assign": 2, 33 | "no-extra-boolean-cast": 2, 34 | "no-extra-parens": 2, 35 | "no-extra-semi": 2, 36 | "no-func-assign": 2, 37 | "no-inner-declarations": 2, 38 | "no-invalid-regexp": 2, 39 | "no-irregular-whitespace": 2, 40 | "no-negated-in-lhs": 2, 41 | "no-obj-calls": 2, 42 | "no-regex-spaces": 2, 43 | "no-sparse-arrays": 2, 44 | "no-unreachable": 2, 45 | "use-isnan": 2, 46 | "valid-jsdoc": 2, 47 | "valid-typeof": 2, 48 | "no-unexpected-multiline": 2, 49 | 50 | // Best Practices 51 | // not sure 52 | "accessor-pairs": [2, {"getWithoutSet": false, "setWithoutGet": true}], 53 | "block-scoped-var": 2, 54 | "complexity": [2, 6], 55 | "consistent-return": 2, 56 | "curly": 2, 57 | "default-case": 2, 58 | "dot-notation": 2, 59 | // not good for chain calls, but not for properties 60 | "dot-location": [2, "property"], 61 | "eqeqeq": 2, 62 | "guard-for-in": 2, 63 | "no-alert": 2, 64 | "no-caller": 2, 65 | "no-div-regex": 2, 66 | "no-else-return": 2, 67 | "no-empty-label": 2, 68 | "no-eq-null": 2, 69 | "no-eval": 2, 70 | "no-extend-native": 2, 71 | "no-extra-bind": 2, 72 | "no-fallthrough": 2, 73 | "no-floating-decimal": 2, 74 | "no-implied-eval": 2, 75 | "no-iterator": 2, 76 | "no-labels": 2, 77 | "no-lone-blocks": 2, 78 | "no-loop-func": 2, 79 | "no-multi-spaces": 2, 80 | "no-multi-str": 2, 81 | "no-native-reassign": 2, 82 | "no-new": 2, 83 | "no-new-func": 2, 84 | "no-new-wrappers": 2, 85 | "no-octal": 2, 86 | "no-octal-escape": 2, 87 | "no-param-reassign": 2, 88 | "no-process-env": 2, 89 | "no-proto": 2, 90 | "no-redeclare": 2, 91 | "no-return-assign": 2, 92 | "no-script-url": 2, 93 | "no-self-compare": 2, 94 | "no-sequences": 2, 95 | "no-throw-literal": 2, 96 | "no-unused-expressions": 2, 97 | "no-void": 2, 98 | "no-warning-comments": [1, { "terms": ["todo", "fixme"], "location": "anywhere" }], 99 | "no-with": 2, 100 | "radix": 2, 101 | "vars-on-top": 0, 102 | "wrap-iife": [2, "inside"], 103 | "yoda": [2, "never"], 104 | 105 | // Strict Mode 106 | "strict": [2, "global"], 107 | 108 | // Variables 109 | "no-catch-shadow": 2, 110 | "no-delete-var": 2, 111 | "no-label-var": 2, 112 | "no-shadow": 2, 113 | "no-shadow-restricted-names": 2, 114 | "no-undef": 2, 115 | "no-undef-init": 2, 116 | "no-undefined": 2, 117 | "no-unused-vars": 2, 118 | "no-use-before-define": [2, "nofunc"], 119 | 120 | // Node.js 121 | "handle-callback-err": [2, "^.*(e|E)rr" ], 122 | "no-mixed-requires": [2, true], 123 | "no-new-require": 2, 124 | "no-path-concat": 2, 125 | "no-process-exit": 2, 126 | "no-sync": 2, 127 | 128 | // Stylistic Issues 129 | "array-bracket-spacing": [2, "never"], 130 | "brace-style": [2, "1tbs", { "allowSingleLine": true }], 131 | "camelcase": 2, 132 | "comma-spacing": [2, {"before": false, "after": true}], 133 | "comma-style": [2, "last"], 134 | "computed-property-spacing": [2, "never"], 135 | "consistent-this": [2, "self"], 136 | // not sure 137 | "eol-last": 0, 138 | "func-names": 0, 139 | "func-style": [2, "declaration"], 140 | "indent": [2, 2], 141 | "key-spacing": [2, { "beforeColon": false, "afterColon": true}], 142 | "max-nested-callbacks": [2, 3], 143 | "new-cap": [2, {"newIsCap": true, "capIsNew": true, "capIsNewExceptions":[ 144 | "ObjectId", 145 | "Object", 146 | "Function", 147 | "Number", 148 | "String", 149 | "Boolean", 150 | "Date", 151 | "Array", 152 | "Symbol", 153 | "RegExp" 154 | ]}], 155 | "new-parens": 2, 156 | "newline-after-var": 0, 157 | "no-array-constructor": 2, 158 | "no-inline-comments": 2, 159 | "no-lonely-if": 2, 160 | "no-mixed-spaces-and-tabs": 2, 161 | "no-multiple-empty-lines": [2, {"max": 1}], 162 | "no-nested-ternary": 2, 163 | "no-new-object": 2, 164 | "no-spaced-func": 2, 165 | "no-ternary": 0, 166 | "no-trailing-spaces": 2, 167 | "no-underscore-dangle": 2, 168 | "no-unneeded-ternary": 2, 169 | "object-curly-spacing": [2, "never"], 170 | "one-var": [2, { 171 | "var": "never", // Exactly one var declaration per function 172 | "let": "never", // Exactly one let declaration per block 173 | "const": "never" // Exactly one declarator per const declaration per block 174 | }], 175 | "operator-assignment": [1, "always"], 176 | "operator-linebreak": [2, "after"], 177 | "padded-blocks": [2, "never"], 178 | "quote-props": [2, "as-needed"], 179 | "quotes": [2, "single", "avoid-escape"], 180 | "semi": [2, "always"], 181 | "semi-spacing": 2, 182 | // "sort-vars": [1, { "ignoreCase": true }], 183 | "space-after-keywords": [2, "always" ], 184 | "space-before-blocks": [2, "always"], 185 | "space-in-parens": [2, "never"], 186 | "space-infix-ops": 2, 187 | "space-return-throw-case": 2, 188 | "space-unary-ops": [2, { "words": true, "nonwords": false }], 189 | "spaced-comment": 0, 190 | "wrap-regexp": 0, 191 | 192 | // Legacy 193 | "max-len": [1, 120, 4], 194 | // todo: apply max-params 195 | "max-params": [0, 3], 196 | // todo: apply max-statements 197 | "max-statements": [2, 30], 198 | "no-bitwise": 2 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /demo/assets/css/glyphicons.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Glyphicons Halflings'; 3 | 4 | src: url('../fonts/glyphicons-halflings-regular.eot'); 5 | src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); 6 | } 7 | .glyphicon { 8 | position: relative; 9 | top: 1px; 10 | display: inline-block; 11 | font-family: 'Glyphicons Halflings'; 12 | font-style: normal; 13 | font-weight: normal; 14 | line-height: 1; 15 | 16 | -webkit-font-smoothing: antialiased; 17 | -moz-osx-font-smoothing: grayscale; 18 | } 19 | .glyphicon-asterisk:before { 20 | content: "\2a"; 21 | } 22 | .glyphicon-plus:before { 23 | content: "\2b"; 24 | } 25 | .glyphicon-euro:before, 26 | .glyphicon-eur:before { 27 | content: "\20ac"; 28 | } 29 | .glyphicon-minus:before { 30 | content: "\2212"; 31 | } 32 | .glyphicon-cloud:before { 33 | content: "\2601"; 34 | } 35 | .glyphicon-envelope:before { 36 | content: "\2709"; 37 | } 38 | .glyphicon-pencil:before { 39 | content: "\270f"; 40 | } 41 | .glyphicon-glass:before { 42 | content: "\e001"; 43 | } 44 | .glyphicon-music:before { 45 | content: "\e002"; 46 | } 47 | .glyphicon-search:before { 48 | content: "\e003"; 49 | } 50 | .glyphicon-heart:before { 51 | content: "\e005"; 52 | } 53 | .glyphicon-star:before { 54 | content: "\e006"; 55 | } 56 | .glyphicon-star-empty:before { 57 | content: "\e007"; 58 | } 59 | .glyphicon-user:before { 60 | content: "\e008"; 61 | } 62 | .glyphicon-film:before { 63 | content: "\e009"; 64 | } 65 | .glyphicon-th-large:before { 66 | content: "\e010"; 67 | } 68 | .glyphicon-th:before { 69 | content: "\e011"; 70 | } 71 | .glyphicon-th-list:before { 72 | content: "\e012"; 73 | } 74 | .glyphicon-ok:before { 75 | content: "\e013"; 76 | } 77 | .glyphicon-remove:before { 78 | content: "\e014"; 79 | } 80 | .glyphicon-zoom-in:before { 81 | content: "\e015"; 82 | } 83 | .glyphicon-zoom-out:before { 84 | content: "\e016"; 85 | } 86 | .glyphicon-off:before { 87 | content: "\e017"; 88 | } 89 | .glyphicon-signal:before { 90 | content: "\e018"; 91 | } 92 | .glyphicon-cog:before { 93 | content: "\e019"; 94 | } 95 | .glyphicon-trash:before { 96 | content: "\e020"; 97 | } 98 | .glyphicon-home:before { 99 | content: "\e021"; 100 | } 101 | .glyphicon-file:before { 102 | content: "\e022"; 103 | } 104 | .glyphicon-time:before { 105 | content: "\e023"; 106 | } 107 | .glyphicon-road:before { 108 | content: "\e024"; 109 | } 110 | .glyphicon-download-alt:before { 111 | content: "\e025"; 112 | } 113 | .glyphicon-download:before { 114 | content: "\e026"; 115 | } 116 | .glyphicon-upload:before { 117 | content: "\e027"; 118 | } 119 | .glyphicon-inbox:before { 120 | content: "\e028"; 121 | } 122 | .glyphicon-play-circle:before { 123 | content: "\e029"; 124 | } 125 | .glyphicon-repeat:before { 126 | content: "\e030"; 127 | } 128 | .glyphicon-refresh:before { 129 | content: "\e031"; 130 | } 131 | .glyphicon-list-alt:before { 132 | content: "\e032"; 133 | } 134 | .glyphicon-lock:before { 135 | content: "\e033"; 136 | } 137 | .glyphicon-flag:before { 138 | content: "\e034"; 139 | } 140 | .glyphicon-headphones:before { 141 | content: "\e035"; 142 | } 143 | .glyphicon-volume-off:before { 144 | content: "\e036"; 145 | } 146 | .glyphicon-volume-down:before { 147 | content: "\e037"; 148 | } 149 | .glyphicon-volume-up:before { 150 | content: "\e038"; 151 | } 152 | .glyphicon-qrcode:before { 153 | content: "\e039"; 154 | } 155 | .glyphicon-barcode:before { 156 | content: "\e040"; 157 | } 158 | .glyphicon-tag:before { 159 | content: "\e041"; 160 | } 161 | .glyphicon-tags:before { 162 | content: "\e042"; 163 | } 164 | .glyphicon-book:before { 165 | content: "\e043"; 166 | } 167 | .glyphicon-bookmark:before { 168 | content: "\e044"; 169 | } 170 | .glyphicon-print:before { 171 | content: "\e045"; 172 | } 173 | .glyphicon-camera:before { 174 | content: "\e046"; 175 | } 176 | .glyphicon-font:before { 177 | content: "\e047"; 178 | } 179 | .glyphicon-bold:before { 180 | content: "\e048"; 181 | } 182 | .glyphicon-italic:before { 183 | content: "\e049"; 184 | } 185 | .glyphicon-text-height:before { 186 | content: "\e050"; 187 | } 188 | .glyphicon-text-width:before { 189 | content: "\e051"; 190 | } 191 | .glyphicon-align-left:before { 192 | content: "\e052"; 193 | } 194 | .glyphicon-align-center:before { 195 | content: "\e053"; 196 | } 197 | .glyphicon-align-right:before { 198 | content: "\e054"; 199 | } 200 | .glyphicon-align-justify:before { 201 | content: "\e055"; 202 | } 203 | .glyphicon-list:before { 204 | content: "\e056"; 205 | } 206 | .glyphicon-indent-left:before { 207 | content: "\e057"; 208 | } 209 | .glyphicon-indent-right:before { 210 | content: "\e058"; 211 | } 212 | .glyphicon-facetime-video:before { 213 | content: "\e059"; 214 | } 215 | .glyphicon-picture:before { 216 | content: "\e060"; 217 | } 218 | .glyphicon-map-marker:before { 219 | content: "\e062"; 220 | } 221 | .glyphicon-adjust:before { 222 | content: "\e063"; 223 | } 224 | .glyphicon-tint:before { 225 | content: "\e064"; 226 | } 227 | .glyphicon-edit:before { 228 | content: "\e065"; 229 | } 230 | .glyphicon-share:before { 231 | content: "\e066"; 232 | } 233 | .glyphicon-check:before { 234 | content: "\e067"; 235 | } 236 | .glyphicon-move:before { 237 | content: "\e068"; 238 | } 239 | .glyphicon-step-backward:before { 240 | content: "\e069"; 241 | } 242 | .glyphicon-fast-backward:before { 243 | content: "\e070"; 244 | } 245 | .glyphicon-backward:before { 246 | content: "\e071"; 247 | } 248 | .glyphicon-play:before { 249 | content: "\e072"; 250 | } 251 | .glyphicon-pause:before { 252 | content: "\e073"; 253 | } 254 | .glyphicon-stop:before { 255 | content: "\e074"; 256 | } 257 | .glyphicon-forward:before { 258 | content: "\e075"; 259 | } 260 | .glyphicon-fast-forward:before { 261 | content: "\e076"; 262 | } 263 | .glyphicon-step-forward:before { 264 | content: "\e077"; 265 | } 266 | .glyphicon-eject:before { 267 | content: "\e078"; 268 | } 269 | .glyphicon-chevron-left:before { 270 | content: "\e079"; 271 | } 272 | .glyphicon-chevron-right:before { 273 | content: "\e080"; 274 | } 275 | .glyphicon-plus-sign:before { 276 | content: "\e081"; 277 | } 278 | .glyphicon-minus-sign:before { 279 | content: "\e082"; 280 | } 281 | .glyphicon-remove-sign:before { 282 | content: "\e083"; 283 | } 284 | .glyphicon-ok-sign:before { 285 | content: "\e084"; 286 | } 287 | .glyphicon-question-sign:before { 288 | content: "\e085"; 289 | } 290 | .glyphicon-info-sign:before { 291 | content: "\e086"; 292 | } 293 | .glyphicon-screenshot:before { 294 | content: "\e087"; 295 | } 296 | .glyphicon-remove-circle:before { 297 | content: "\e088"; 298 | } 299 | .glyphicon-ok-circle:before { 300 | content: "\e089"; 301 | } 302 | .glyphicon-ban-circle:before { 303 | content: "\e090"; 304 | } 305 | .glyphicon-arrow-left:before { 306 | content: "\e091"; 307 | } 308 | .glyphicon-arrow-right:before { 309 | content: "\e092"; 310 | } 311 | .glyphicon-arrow-up:before { 312 | content: "\e093"; 313 | } 314 | .glyphicon-arrow-down:before { 315 | content: "\e094"; 316 | } 317 | .glyphicon-share-alt:before { 318 | content: "\e095"; 319 | } 320 | .glyphicon-resize-full:before { 321 | content: "\e096"; 322 | } 323 | .glyphicon-resize-small:before { 324 | content: "\e097"; 325 | } 326 | .glyphicon-exclamation-sign:before { 327 | content: "\e101"; 328 | } 329 | .glyphicon-gift:before { 330 | content: "\e102"; 331 | } 332 | .glyphicon-leaf:before { 333 | content: "\e103"; 334 | } 335 | .glyphicon-fire:before { 336 | content: "\e104"; 337 | } 338 | .glyphicon-eye-open:before { 339 | content: "\e105"; 340 | } 341 | .glyphicon-eye-close:before { 342 | content: "\e106"; 343 | } 344 | .glyphicon-warning-sign:before { 345 | content: "\e107"; 346 | } 347 | .glyphicon-plane:before { 348 | content: "\e108"; 349 | } 350 | .glyphicon-calendar:before { 351 | content: "\e109"; 352 | } 353 | .glyphicon-random:before { 354 | content: "\e110"; 355 | } 356 | .glyphicon-comment:before { 357 | content: "\e111"; 358 | } 359 | .glyphicon-magnet:before { 360 | content: "\e112"; 361 | } 362 | .glyphicon-chevron-up:before { 363 | content: "\e113"; 364 | } 365 | .glyphicon-chevron-down:before { 366 | content: "\e114"; 367 | } 368 | .glyphicon-retweet:before { 369 | content: "\e115"; 370 | } 371 | .glyphicon-shopping-cart:before { 372 | content: "\e116"; 373 | } 374 | .glyphicon-folder-close:before { 375 | content: "\e117"; 376 | } 377 | .glyphicon-folder-open:before { 378 | content: "\e118"; 379 | } 380 | .glyphicon-resize-vertical:before { 381 | content: "\e119"; 382 | } 383 | .glyphicon-resize-horizontal:before { 384 | content: "\e120"; 385 | } 386 | .glyphicon-hdd:before { 387 | content: "\e121"; 388 | } 389 | .glyphicon-bullhorn:before { 390 | content: "\e122"; 391 | } 392 | .glyphicon-bell:before { 393 | content: "\e123"; 394 | } 395 | .glyphicon-certificate:before { 396 | content: "\e124"; 397 | } 398 | .glyphicon-thumbs-up:before { 399 | content: "\e125"; 400 | } 401 | .glyphicon-thumbs-down:before { 402 | content: "\e126"; 403 | } 404 | .glyphicon-hand-right:before { 405 | content: "\e127"; 406 | } 407 | .glyphicon-hand-left:before { 408 | content: "\e128"; 409 | } 410 | .glyphicon-hand-up:before { 411 | content: "\e129"; 412 | } 413 | .glyphicon-hand-down:before { 414 | content: "\e130"; 415 | } 416 | .glyphicon-circle-arrow-right:before { 417 | content: "\e131"; 418 | } 419 | .glyphicon-circle-arrow-left:before { 420 | content: "\e132"; 421 | } 422 | .glyphicon-circle-arrow-up:before { 423 | content: "\e133"; 424 | } 425 | .glyphicon-circle-arrow-down:before { 426 | content: "\e134"; 427 | } 428 | .glyphicon-globe:before { 429 | content: "\e135"; 430 | } 431 | .glyphicon-wrench:before { 432 | content: "\e136"; 433 | } 434 | .glyphicon-tasks:before { 435 | content: "\e137"; 436 | } 437 | .glyphicon-filter:before { 438 | content: "\e138"; 439 | } 440 | .glyphicon-briefcase:before { 441 | content: "\e139"; 442 | } 443 | .glyphicon-fullscreen:before { 444 | content: "\e140"; 445 | } 446 | .glyphicon-dashboard:before { 447 | content: "\e141"; 448 | } 449 | .glyphicon-paperclip:before { 450 | content: "\e142"; 451 | } 452 | .glyphicon-heart-empty:before { 453 | content: "\e143"; 454 | } 455 | .glyphicon-link:before { 456 | content: "\e144"; 457 | } 458 | .glyphicon-phone:before { 459 | content: "\e145"; 460 | } 461 | .glyphicon-pushpin:before { 462 | content: "\e146"; 463 | } 464 | .glyphicon-usd:before { 465 | content: "\e148"; 466 | } 467 | .glyphicon-gbp:before { 468 | content: "\e149"; 469 | } 470 | .glyphicon-sort:before { 471 | content: "\e150"; 472 | } 473 | .glyphicon-sort-by-alphabet:before { 474 | content: "\e151"; 475 | } 476 | .glyphicon-sort-by-alphabet-alt:before { 477 | content: "\e152"; 478 | } 479 | .glyphicon-sort-by-order:before { 480 | content: "\e153"; 481 | } 482 | .glyphicon-sort-by-order-alt:before { 483 | content: "\e154"; 484 | } 485 | .glyphicon-sort-by-attributes:before { 486 | content: "\e155"; 487 | } 488 | .glyphicon-sort-by-attributes-alt:before { 489 | content: "\e156"; 490 | } 491 | .glyphicon-unchecked:before { 492 | content: "\e157"; 493 | } 494 | .glyphicon-expand:before { 495 | content: "\e158"; 496 | } 497 | .glyphicon-collapse-down:before { 498 | content: "\e159"; 499 | } 500 | .glyphicon-collapse-up:before { 501 | content: "\e160"; 502 | } 503 | .glyphicon-log-in:before { 504 | content: "\e161"; 505 | } 506 | .glyphicon-flash:before { 507 | content: "\e162"; 508 | } 509 | .glyphicon-log-out:before { 510 | content: "\e163"; 511 | } 512 | .glyphicon-new-window:before { 513 | content: "\e164"; 514 | } 515 | .glyphicon-record:before { 516 | content: "\e165"; 517 | } 518 | .glyphicon-save:before { 519 | content: "\e166"; 520 | } 521 | .glyphicon-open:before { 522 | content: "\e167"; 523 | } 524 | .glyphicon-saved:before { 525 | content: "\e168"; 526 | } 527 | .glyphicon-import:before { 528 | content: "\e169"; 529 | } 530 | .glyphicon-export:before { 531 | content: "\e170"; 532 | } 533 | .glyphicon-send:before { 534 | content: "\e171"; 535 | } 536 | .glyphicon-floppy-disk:before { 537 | content: "\e172"; 538 | } 539 | .glyphicon-floppy-saved:before { 540 | content: "\e173"; 541 | } 542 | .glyphicon-floppy-remove:before { 543 | content: "\e174"; 544 | } 545 | .glyphicon-floppy-save:before { 546 | content: "\e175"; 547 | } 548 | .glyphicon-floppy-open:before { 549 | content: "\e176"; 550 | } 551 | .glyphicon-credit-card:before { 552 | content: "\e177"; 553 | } 554 | .glyphicon-transfer:before { 555 | content: "\e178"; 556 | } 557 | .glyphicon-cutlery:before { 558 | content: "\e179"; 559 | } 560 | .glyphicon-header:before { 561 | content: "\e180"; 562 | } 563 | .glyphicon-compressed:before { 564 | content: "\e181"; 565 | } 566 | .glyphicon-earphone:before { 567 | content: "\e182"; 568 | } 569 | .glyphicon-phone-alt:before { 570 | content: "\e183"; 571 | } 572 | .glyphicon-tower:before { 573 | content: "\e184"; 574 | } 575 | .glyphicon-stats:before { 576 | content: "\e185"; 577 | } 578 | .glyphicon-sd-video:before { 579 | content: "\e186"; 580 | } 581 | .glyphicon-hd-video:before { 582 | content: "\e187"; 583 | } 584 | .glyphicon-subtitles:before { 585 | content: "\e188"; 586 | } 587 | .glyphicon-sound-stereo:before { 588 | content: "\e189"; 589 | } 590 | .glyphicon-sound-dolby:before { 591 | content: "\e190"; 592 | } 593 | .glyphicon-sound-5-1:before { 594 | content: "\e191"; 595 | } 596 | .glyphicon-sound-6-1:before { 597 | content: "\e192"; 598 | } 599 | .glyphicon-sound-7-1:before { 600 | content: "\e193"; 601 | } 602 | .glyphicon-copyright-mark:before { 603 | content: "\e194"; 604 | } 605 | .glyphicon-registration-mark:before { 606 | content: "\e195"; 607 | } 608 | .glyphicon-cloud-download:before { 609 | content: "\e197"; 610 | } 611 | .glyphicon-cloud-upload:before { 612 | content: "\e198"; 613 | } 614 | .glyphicon-tree-conifer:before { 615 | content: "\e199"; 616 | } 617 | .glyphicon-tree-deciduous:before { 618 | content: "\e200"; 619 | } 620 | .glyphicon-cd:before { 621 | content: "\e201"; 622 | } 623 | .glyphicon-save-file:before { 624 | content: "\e202"; 625 | } 626 | .glyphicon-open-file:before { 627 | content: "\e203"; 628 | } 629 | .glyphicon-level-up:before { 630 | content: "\e204"; 631 | } 632 | .glyphicon-copy:before { 633 | content: "\e205"; 634 | } 635 | .glyphicon-paste:before { 636 | content: "\e206"; 637 | } 638 | .glyphicon-alert:before { 639 | content: "\e209"; 640 | } 641 | .glyphicon-equalizer:before { 642 | content: "\e210"; 643 | } 644 | .glyphicon-king:before { 645 | content: "\e211"; 646 | } 647 | .glyphicon-queen:before { 648 | content: "\e212"; 649 | } 650 | .glyphicon-pawn:before { 651 | content: "\e213"; 652 | } 653 | .glyphicon-bishop:before { 654 | content: "\e214"; 655 | } 656 | .glyphicon-knight:before { 657 | content: "\e215"; 658 | } 659 | .glyphicon-baby-formula:before { 660 | content: "\e216"; 661 | } 662 | .glyphicon-tent:before { 663 | content: "\26fa"; 664 | } 665 | .glyphicon-blackboard:before { 666 | content: "\e218"; 667 | } 668 | .glyphicon-bed:before { 669 | content: "\e219"; 670 | } 671 | .glyphicon-apple:before { 672 | content: "\f8ff"; 673 | } 674 | .glyphicon-erase:before { 675 | content: "\e221"; 676 | } 677 | .glyphicon-hourglass:before { 678 | content: "\231b"; 679 | } 680 | .glyphicon-lamp:before { 681 | content: "\e223"; 682 | } 683 | .glyphicon-duplicate:before { 684 | content: "\e224"; 685 | } 686 | .glyphicon-piggy-bank:before { 687 | content: "\e225"; 688 | } 689 | .glyphicon-scissors:before { 690 | content: "\e226"; 691 | } 692 | .glyphicon-bitcoin:before { 693 | content: "\e227"; 694 | } 695 | .glyphicon-btc:before { 696 | content: "\e227"; 697 | } 698 | .glyphicon-xbt:before { 699 | content: "\e227"; 700 | } 701 | .glyphicon-yen:before { 702 | content: "\00a5"; 703 | } 704 | .glyphicon-jpy:before { 705 | content: "\00a5"; 706 | } 707 | .glyphicon-ruble:before { 708 | content: "\20bd"; 709 | } 710 | .glyphicon-rub:before { 711 | content: "\20bd"; 712 | } 713 | .glyphicon-scale:before { 714 | content: "\e230"; 715 | } 716 | .glyphicon-ice-lolly:before { 717 | content: "\e231"; 718 | } 719 | .glyphicon-ice-lolly-tasted:before { 720 | content: "\e232"; 721 | } 722 | .glyphicon-education:before { 723 | content: "\e233"; 724 | } 725 | .glyphicon-option-horizontal:before { 726 | content: "\e234"; 727 | } 728 | .glyphicon-option-vertical:before { 729 | content: "\e235"; 730 | } 731 | .glyphicon-menu-hamburger:before { 732 | content: "\e236"; 733 | } 734 | .glyphicon-modal-window:before { 735 | content: "\e237"; 736 | } 737 | .glyphicon-oil:before { 738 | content: "\e238"; 739 | } 740 | .glyphicon-grain:before { 741 | content: "\e239"; 742 | } 743 | .glyphicon-sunglasses:before { 744 | content: "\e240"; 745 | } 746 | .glyphicon-text-size:before { 747 | content: "\e241"; 748 | } 749 | .glyphicon-text-color:before { 750 | content: "\e242"; 751 | } 752 | .glyphicon-text-background:before { 753 | content: "\e243"; 754 | } 755 | .glyphicon-object-align-top:before { 756 | content: "\e244"; 757 | } 758 | .glyphicon-object-align-bottom:before { 759 | content: "\e245"; 760 | } 761 | .glyphicon-object-align-horizontal:before { 762 | content: "\e246"; 763 | } 764 | .glyphicon-object-align-left:before { 765 | content: "\e247"; 766 | } 767 | .glyphicon-object-align-vertical:before { 768 | content: "\e248"; 769 | } 770 | .glyphicon-object-align-right:before { 771 | content: "\e249"; 772 | } 773 | .glyphicon-triangle-right:before { 774 | content: "\e250"; 775 | } 776 | .glyphicon-triangle-left:before { 777 | content: "\e251"; 778 | } 779 | .glyphicon-triangle-bottom:before { 780 | content: "\e252"; 781 | } 782 | .glyphicon-triangle-top:before { 783 | content: "\e253"; 784 | } 785 | .glyphicon-console:before { 786 | content: "\e254"; 787 | } 788 | .glyphicon-superscript:before { 789 | content: "\e255"; 790 | } 791 | .glyphicon-subscript:before { 792 | content: "\e256"; 793 | } 794 | .glyphicon-menu-left:before { 795 | content: "\e257"; 796 | } 797 | .glyphicon-menu-right:before { 798 | content: "\e258"; 799 | } 800 | .glyphicon-menu-down:before { 801 | content: "\e259"; 802 | } 803 | .glyphicon-menu-up:before { 804 | content: "\e260"; 805 | } 806 | -------------------------------------------------------------------------------- /demo/components/table/table-data.ts: -------------------------------------------------------------------------------- 1 | export const TableData:Array = [ 2 | { 3 | 'name': 'Victoria Cantrell', 4 | 'position': 'Integer Corporation', 5 | 'office': 'Croatia', 6 | 'ext': `0839`, 7 | 'startDate': '2015/08/19', 8 | 'salary': 208.178 9 | }, { 10 | 'name': 'Pearl Crosby', 11 | 'position': 'In PC', 12 | 'office': 'Cambodia', 13 | 'ext': `8262`, 14 | 'startDate': '2014/10/08', 15 | 'salary': 114.367 16 | }, { 17 | 'name': 'Colette Foley', 18 | 'position': 'Lorem Inc.', 19 | 'office': 'Korea, North', 20 | 'ext': '8968', 21 | 'startDate': '2015/07/19', 22 | 'salary': 721.473 23 | }, { 24 | 'name': 'Anastasia Shaffer', 25 | 'position': 'Dolor Nulla Semper LLC', 26 | 'office': 'Suriname', 27 | 'ext': '7980', 28 | 'startDate': '2015/04/20', 29 | 'salary': 264.620 30 | }, { 31 | 'name': 'Gabriel Castro', 32 | 'position': 'Sed Limited', 33 | 'office': 'Bahrain', 34 | 'ext': '0757', 35 | 'startDate': '2015/03/04', 36 | 'salary': 651.350 37 | }, { 38 | 'name': 'Cherokee Ware', 39 | 'position': 'Tincidunt LLC', 40 | 'office': 'United Kingdom (Great Britain)', 41 | 'ext': '3995', 42 | 'startDate': '2015/06/17', 43 | 'salary': 666.259 44 | }, { 45 | 'name': 'Barry Moss', 46 | 'position': 'Sociis Industries', 47 | 'office': 'Western Sahara', 48 | 'ext': '6697', 49 | 'startDate': '2015/08/13', 50 | 'salary': 541.631 51 | }, { 52 | 'name': 'Maryam Tucker', 53 | 'position': 'Elit Pede Malesuada Inc.', 54 | 'office': 'Brazil', 55 | 'ext': '5203', 56 | 'startDate': '2014/10/02', 57 | 'salary': 182.294 58 | }, { 59 | 'name': 'Constance Clayton', 60 | 'position': 'Auctor Velit Aliquam LLP', 61 | 'office': 'United Arab Emirates', 62 | 'ext': '4204', 63 | 'startDate': '2015/08/01', 64 | 'salary': 218.597 65 | }, { 66 | 'name': 'Rogan Tucker', 67 | 'position': 'Arcu Vestibulum Ante Associates', 68 | 'office': 'Jersey', 69 | 'ext': '0885', 70 | 'startDate': '2015/01/04', 71 | 'salary': 861.632 72 | }, { 73 | 'name': 'Emery Mcdowell', 74 | 'position': 'Gravida Company', 75 | 'office': 'New Zealand', 76 | 'ext': '3951', 77 | 'startDate': '2015/06/02', 78 | 'salary': 413.568 79 | }, { 80 | 'name': 'Yael Greer', 81 | 'position': 'Orci Limited', 82 | 'office': 'Madagascar', 83 | 'ext': '1416', 84 | 'startDate': '2014/12/04', 85 | 'salary': 121.831 86 | }, { 87 | 'name': 'Jared Burgess', 88 | 'position': 'Auctor Incorporated', 89 | 'office': 'Burundi', 90 | 'ext': '4673', 91 | 'startDate': '2015/01/12', 92 | 'salary': 62.243 93 | }, { 94 | 'name': 'Sharon Campbell', 95 | 'position': 'Elit Curabitur Sed Consulting', 96 | 'office': 'Comoros', 97 | 'ext': '6274', 98 | 'startDate': '2014/09/14', 99 | 'salary': 200.854 100 | }, { 101 | 'name': 'Yeo Church', 102 | 'position': 'Donec Vitae Erat PC', 103 | 'office': 'Saudi Arabia', 104 | 'ext': '0269', 105 | 'startDate': '2015/06/07', 106 | 'salary': 581.193 107 | }, { 108 | 'name': 'Kylie Barlow', 109 | 'position': 'Fermentum Risus Corporation', 110 | 'office': 'Papua New Guinea', 111 | 'ext': '2010', 112 | 'startDate': '2014/12/03', 113 | 'salary': 418.115 114 | }, { 115 | 'name': 'Nell Leonard', 116 | 'position': 'Vestibulum Consulting', 117 | 'office': 'Saudi Arabia', 118 | 'ext': '4839', 119 | 'startDate': '2015/05/29', 120 | 'salary': 466.201 121 | }, { 122 | 'name': 'Brandon Fleming', 123 | 'position': 'Donec Egestas Associates', 124 | 'office': 'Poland', 125 | 'ext': '0622', 126 | 'startDate': '2015/01/22', 127 | 'salary': 800.011 128 | }, { 129 | 'name': 'Inga Pena', 130 | 'position': 'Et Magnis Dis Limited', 131 | 'office': 'Belgium', 132 | 'ext': '8140', 133 | 'startDate': '2015/05/18', 134 | 'salary': 564.245 135 | }, { 136 | 'name': 'Arden Russo', 137 | 'position': 'Est Tempor Bibendum Corp.', 138 | 'office': 'Dominican Republic', 139 | 'ext': '6774', 140 | 'startDate': '2015/07/23', 141 | 'salary': 357.222 142 | }, { 143 | 'name': 'Liberty Gallegos', 144 | 'position': 'Nec Diam LLC', 145 | 'office': 'Ghana', 146 | 'ext': '9266', 147 | 'startDate': '2015/06/18', 148 | 'salary': 554.375 149 | }, { 150 | 'name': 'Dennis York', 151 | 'position': 'Nullam Suscipit Foundation', 152 | 'office': 'Namibia', 153 | 'ext': '3133', 154 | 'startDate': '2015/03/20', 155 | 'salary': 90.417 156 | }, { 157 | 'name': 'Petra Chandler', 158 | 'position': 'Pede Nonummy Inc.', 159 | 'office': 'Namibia', 160 | 'ext': '3367', 161 | 'startDate': '2015/03/26', 162 | 'salary': 598.915 163 | }, { 164 | 'name': 'Aurelia Marshall', 165 | 'position': 'Donec Consulting', 166 | 'office': 'Nicaragua', 167 | 'ext': '2690', 168 | 'startDate': '2015/08/18', 169 | 'salary': 201.680 170 | }, { 171 | 'name': 'Rose Carter', 172 | 'position': 'Enim Consequat Purus Industries', 173 | 'office': 'Morocco', 174 | 'ext': '0619', 175 | 'startDate': '2015/03/06', 176 | 'salary': 220.187 177 | }, { 178 | 'name': 'Denton Atkins', 179 | 'position': 'Non Vestibulum PC', 180 | 'office': 'Mali', 181 | 'ext': '5806', 182 | 'startDate': '2015/04/19', 183 | 'salary': 324.588 184 | }, { 185 | 'name': 'Germaine Osborn', 186 | 'position': 'Tristique Aliquet PC', 187 | 'office': 'Lesotho', 188 | 'ext': '4469', 189 | 'startDate': '2015/01/19', 190 | 'salary': 351.108 191 | }, { 192 | 'name': 'Nell Butler', 193 | 'position': 'Sit Amet Dapibus Industries', 194 | 'office': 'Cuba', 195 | 'ext': '7860', 196 | 'startDate': '2015/01/06', 197 | 'salary': 230.072 198 | }, { 199 | 'name': 'Brent Stein', 200 | 'position': 'Eu Augue Porttitor LLP', 201 | 'office': 'Cyprus', 202 | 'ext': '4697', 203 | 'startDate': '2014/11/02', 204 | 'salary': 853.413 205 | }, { 206 | 'name': 'Alexandra Shaw', 207 | 'position': 'Aenean Gravida Limited', 208 | 'office': 'Uruguay', 209 | 'ext': '1140', 210 | 'startDate': '2015/05/16', 211 | 'salary': 401.970 212 | }, { 213 | 'name': 'Veronica Allison', 214 | 'position': 'Aliquet Diam Sed Institute', 215 | 'office': 'Samoa', 216 | 'ext': '9966', 217 | 'startDate': '2015/05/17', 218 | 'salary': 79.193 219 | }, { 220 | 'name': 'Katelyn Gamble', 221 | 'position': 'Sed Associates', 222 | 'office': 'Mauritius', 223 | 'ext': '4767', 224 | 'startDate': '2015/03/20', 225 | 'salary': 484.299 226 | }, { 227 | 'name': 'James Greer', 228 | 'position': 'A Dui Incorporated', 229 | 'office': 'Norway', 230 | 'ext': '5517', 231 | 'startDate': '2015/02/21', 232 | 'salary': 333.518 233 | }, { 234 | 'name': 'Cain Vasquez', 235 | 'position': 'Nulla Facilisis Suspendisse Institute', 236 | 'office': 'China', 237 | 'ext': '3179', 238 | 'startDate': '2015/05/27', 239 | 'salary': 651.761 240 | }, { 241 | 'name': 'Shaeleigh Barr', 242 | 'position': 'Eleifend Cras Institute', 243 | 'office': 'Ghana', 244 | 'ext': '5904', 245 | 'startDate': '2015/04/01', 246 | 'salary': 627.095 247 | }, { 248 | 'name': 'Baker Mckay', 249 | 'position': 'Ut Sagittis Associates', 250 | 'office': 'Isle of Man', 251 | 'ext': '9840', 252 | 'startDate': '2015/01/12', 253 | 'salary': 742.247 254 | }, { 255 | 'name': 'Jayme Pace', 256 | 'position': 'Cras Eu Tellus Associates', 257 | 'office': 'Bouvet Island', 258 | 'ext': '4580', 259 | 'startDate': '2015/08/12', 260 | 'salary': 591.588 261 | }, { 262 | 'name': 'Reuben Albert', 263 | 'position': 'Lobortis Institute', 264 | 'office': 'Zambia', 265 | 'ext': '8725', 266 | 'startDate': '2015/04/04', 267 | 'salary': 791.408 268 | }, { 269 | 'name': 'Idola Burns', 270 | 'position': 'Non Industries', 271 | 'office': 'Myanmar', 272 | 'ext': '3201', 273 | 'startDate': '2015/06/24', 274 | 'salary': 142.906 275 | }, { 276 | 'name': 'Laura Macias', 277 | 'position': 'Phasellus Inc.', 278 | 'office': 'Mauritania', 279 | 'ext': '2033', 280 | 'startDate': '2014/11/21', 281 | 'salary': 226.591 282 | }, { 283 | 'name': 'Nichole Salas', 284 | 'position': 'Duis PC', 285 | 'office': 'Madagascar', 286 | 'ext': '4397', 287 | 'startDate': '2015/01/18', 288 | 'salary': 234.196 289 | }, { 290 | 'name': 'Hunter Walter', 291 | 'position': 'Ullamcorper Duis Cursus Foundation', 292 | 'office': 'Brazil', 293 | 'ext': '2227', 294 | 'startDate': '2015/02/28', 295 | 'salary': 655.052 296 | }, { 297 | 'name': 'Asher Rich', 298 | 'position': 'Mauris Ipsum LLP', 299 | 'office': 'Paraguay', 300 | 'ext': '7288', 301 | 'startDate': '2015/08/08', 302 | 'salary': 222.946 303 | }, { 304 | 'name': 'Angela Carlson', 305 | 'position': 'Donec Tempor Institute', 306 | 'office': 'Papua New Guinea', 307 | 'ext': '5416', 308 | 'startDate': '2015/02/12', 309 | 'salary': 562.194 310 | }, { 311 | 'name': 'James Dorsey', 312 | 'position': 'Ipsum Leo Associates', 313 | 'office': 'Congo (Brazzaville)', 314 | 'ext': '6019', 315 | 'startDate': '2015/01/10', 316 | 'salary': 629.925 317 | }, { 318 | 'name': 'Wesley Cobb', 319 | 'position': 'Nunc Est Incorporated', 320 | 'office': 'Australia', 321 | 'ext': '6466', 322 | 'startDate': '2015/01/30', 323 | 'salary': 343.476 324 | }, { 325 | 'name': 'Meghan Stephens', 326 | 'position': 'Interdum PC', 327 | 'office': 'Turkey', 328 | 'ext': '8001', 329 | 'startDate': '2014/10/11', 330 | 'salary': 469.305 331 | }, { 332 | 'name': 'Bertha Herrera', 333 | 'position': 'Amet Limited', 334 | 'office': 'Kenya', 335 | 'ext': '4799', 336 | 'startDate': '2014/11/22', 337 | 'salary': 56.606 338 | }, { 339 | 'name': 'Karina Key', 340 | 'position': 'Quisque Varius Nam Company', 341 | 'office': 'France', 342 | 'ext': '3907', 343 | 'startDate': '2015/03/26', 344 | 'salary': 314.260 345 | }, { 346 | 'name': 'Uriel Carson', 347 | 'position': 'Penatibus PC', 348 | 'office': 'Venezuela', 349 | 'ext': '5902', 350 | 'startDate': '2015/01/07', 351 | 'salary': 106.335 352 | }, { 353 | 'name': 'Mira Baird', 354 | 'position': 'Felis Orci PC', 355 | 'office': 'Niue', 356 | 'ext': '4189', 357 | 'startDate': '2015/08/25', 358 | 'salary': 515.671 359 | }, { 360 | 'name': 'Ursula Parrish', 361 | 'position': 'Ac Corporation', 362 | 'office': 'Macao', 363 | 'ext': '4771', 364 | 'startDate': '2015/06/30', 365 | 'salary': 72.295 366 | }, { 367 | 'name': 'Josephine Sykes', 368 | 'position': 'Blandit Congue Limited', 369 | 'office': 'Holy See (Vatican City State)', 370 | 'ext': '4684', 371 | 'startDate': '2014/12/22', 372 | 'salary': 694.656 373 | }, { 374 | 'name': 'Maggie Sims', 375 | 'position': 'Vulputate Posuere Industries', 376 | 'office': 'Sudan', 377 | 'ext': '6482', 378 | 'startDate': '2014/11/22', 379 | 'salary': 363.743 380 | }, { 381 | 'name': 'Rogan Fuentes', 382 | 'position': 'Vestibulum Accumsan Neque Company', 383 | 'office': 'Jersey', 384 | 'ext': '4837', 385 | 'startDate': '2015/07/29', 386 | 'salary': 606.004 387 | }, { 388 | 'name': 'Maya Haney', 389 | 'position': 'Ac Foundation', 390 | 'office': 'Falkland Islands', 391 | 'ext': '5752', 392 | 'startDate': '2015/09/03', 393 | 'salary': 745.500 394 | }, { 395 | 'name': 'Aquila Battle', 396 | 'position': 'Sociis Natoque Penatibus Foundation', 397 | 'office': 'Azerbaijan', 398 | 'ext': '8470', 399 | 'startDate': '2015/03/06', 400 | 'salary': 582.265 401 | }, { 402 | 'name': 'Connor Coleman', 403 | 'position': 'Orci Lacus Vestibulum Foundation', 404 | 'office': 'Croatia', 405 | 'ext': '6217', 406 | 'startDate': '2014/10/21', 407 | 'salary': 416.958 408 | }, { 409 | 'name': 'Charity Thomas', 410 | 'position': 'Convallis Ligula Donec Inc.', 411 | 'office': 'Benin', 412 | 'ext': '6240', 413 | 'startDate': '2015/07/12', 414 | 'salary': 540.999 415 | }, { 416 | 'name': 'Blythe Powers', 417 | 'position': 'Amet Orci Limited', 418 | 'office': 'Falkland Islands', 419 | 'ext': '5608', 420 | 'startDate': '2015/01/23', 421 | 'salary': 480.067 422 | }, { 423 | 'name': 'Adria Battle', 424 | 'position': 'Ornare Lectus Incorporated', 425 | 'office': 'British Indian Ocean Territory', 426 | 'ext': '7419', 427 | 'startDate': '2015/05/28', 428 | 'salary': 257.937 429 | }, { 430 | 'name': 'Melanie Mcintyre', 431 | 'position': 'Nunc Corp.', 432 | 'office': 'Mongolia', 433 | 'ext': '4326', 434 | 'startDate': '2015/01/06', 435 | 'salary': 359.737 436 | }, { 437 | 'name': 'Keely Bauer', 438 | 'position': 'Nec Tempus Institute', 439 | 'office': 'Somalia', 440 | 'ext': '8372', 441 | 'startDate': '2015/03/09', 442 | 'salary': 99.718 443 | }, { 444 | 'name': 'Noelani Strong', 445 | 'position': 'Nec LLP', 446 | 'office': 'Iran', 447 | 'ext': '0049', 448 | 'startDate': '2015/08/24', 449 | 'salary': 480.718 450 | }, { 451 | 'name': 'Jeanette Henderson', 452 | 'position': 'Eu Elit Nulla Corporation', 453 | 'office': 'Italy', 454 | 'ext': '7586', 455 | 'startDate': '2015/06/19', 456 | 'salary': 253.772 457 | }, { 458 | 'name': 'Candace Huber', 459 | 'position': 'Sed Institute', 460 | 'office': 'Uganda', 461 | 'ext': '7183', 462 | 'startDate': '2015/06/16', 463 | 'salary': 388.879 464 | }, { 465 | 'name': 'Bethany Potter', 466 | 'position': 'Vivamus Nibh Dolor Incorporated', 467 | 'office': 'Puerto Rico', 468 | 'ext': '3354', 469 | 'startDate': '2014/11/12', 470 | 'salary': 747.310 471 | }, { 472 | 'name': 'Whoopi Burks', 473 | 'position': 'Justo Inc.', 474 | 'office': 'Fiji', 475 | 'ext': '2185', 476 | 'startDate': '2014/09/24', 477 | 'salary': 803.037 478 | }, { 479 | 'name': 'Sheila Long', 480 | 'position': 'Diam Associates', 481 | 'office': 'Sao Tome and Principe', 482 | 'ext': '7760', 483 | 'startDate': '2014/12/21', 484 | 'salary': 674.379 485 | }, { 486 | 'name': 'Sonya Church', 487 | 'position': 'Laoreet Institute', 488 | 'office': 'Grenada', 489 | 'ext': '8920', 490 | 'startDate': '2015/06/03', 491 | 'salary': 625.147 492 | }, { 493 | 'name': 'Shaine Forbes', 494 | 'position': 'Eu Arcu LLP', 495 | 'office': 'Cyprus', 496 | 'ext': '2369', 497 | 'startDate': '2015/01/18', 498 | 'salary': 208.100 499 | }, { 500 | 'name': 'Alexandra Patrick', 501 | 'position': 'Ligula Donec Inc.', 502 | 'office': 'Viet Nam', 503 | 'ext': '8531', 504 | 'startDate': '2015/04/09', 505 | 'salary': 104.063 506 | }, { 507 | 'name': 'Patience Vincent', 508 | 'position': 'Sem Molestie Associates', 509 | 'office': 'Philippines', 510 | 'ext': '8888', 511 | 'startDate': '2015/07/04', 512 | 'salary': 673.556 513 | }, { 514 | 'name': 'Evelyn Smith', 515 | 'position': 'Fusce Industries', 516 | 'office': 'Togo', 517 | 'ext': '5051', 518 | 'startDate': '2015/08/15', 519 | 'salary': 737.284 520 | }, { 521 | 'name': 'Kieran Gonzalez', 522 | 'position': 'Non Corp.', 523 | 'office': 'Equatorial Guinea', 524 | 'ext': '4834', 525 | 'startDate': '2015/08/24', 526 | 'salary': 90.195 527 | }, { 528 | 'name': 'Molly Oneil', 529 | 'position': 'Non Dui Consulting', 530 | 'office': 'Belize', 531 | 'ext': '7501', 532 | 'startDate': '2014/10/28', 533 | 'salary': 140.767 534 | }, { 535 | 'name': 'Nigel Davenport', 536 | 'position': 'Ullamcorper Velit In Industries', 537 | 'office': 'Vanuatu', 538 | 'ext': '0976', 539 | 'startDate': '2015/03/16', 540 | 'salary': 70.536 541 | }, { 542 | 'name': 'Thor Young', 543 | 'position': 'Malesuada Consulting', 544 | 'office': 'French Southern Territories', 545 | 'ext': '0211', 546 | 'startDate': '2015/01/28', 547 | 'salary': 75.501 548 | }, { 549 | 'name': 'Finn Delacruz', 550 | 'position': 'Lorem Industries', 551 | 'office': 'Cocos (Keeling) Islands', 552 | 'ext': '2980', 553 | 'startDate': '2014/12/11', 554 | 'salary': 754.967 555 | }, { 556 | 'name': 'Lane Henderson', 557 | 'position': 'Pede Foundation', 558 | 'office': 'Kazakhstan', 559 | 'ext': '1446', 560 | 'startDate': '2015/07/02', 561 | 'salary': 842.050 562 | }, { 563 | 'name': 'Shea Potter', 564 | 'position': 'Curabitur Limited', 565 | 'office': 'Timor-Leste', 566 | 'ext': '4654', 567 | 'startDate': '2015/05/07', 568 | 'salary': 263.629 569 | }, { 570 | 'name': 'Brynn Yang', 571 | 'position': 'Ut Limited', 572 | 'office': 'Mayotte', 573 | 'ext': '4668', 574 | 'startDate': '2015/01/17', 575 | 'salary': 74.292 576 | }, { 577 | 'name': 'Kylan Fuentes', 578 | 'position': 'Sapien Aenean Associates', 579 | 'office': 'Brazil', 580 | 'ext': '6623', 581 | 'startDate': '2014/12/28', 582 | 'salary': 108.632 583 | }, { 584 | 'name': 'Lionel Mcbride', 585 | 'position': 'Ipsum PC', 586 | 'office': 'Portugal', 587 | 'ext': '3978', 588 | 'startDate': '2015/07/11', 589 | 'salary': 34.244 590 | }, { 591 | 'name': 'Paul Lucas', 592 | 'position': 'Eget LLP', 593 | 'office': 'Nicaragua', 594 | 'ext': '8890', 595 | 'startDate': '2014/09/30', 596 | 'salary': 690.834 597 | }, { 598 | 'name': 'Lareina Williamson', 599 | 'position': 'Imperdiet Ullamcorper Ltd', 600 | 'office': 'Cocos (Keeling) Islands', 601 | 'ext': '9489', 602 | 'startDate': '2014/12/01', 603 | 'salary': 603.498 604 | }, { 605 | 'name': 'Amy Acevedo', 606 | 'position': 'Id Institute', 607 | 'office': 'Cook Islands', 608 | 'ext': '5592', 609 | 'startDate': '2015/02/04', 610 | 'salary': 125.165 611 | }, { 612 | 'name': 'Nomlanga Silva', 613 | 'position': 'Eget LLC', 614 | 'office': 'Belize', 615 | 'ext': '3110', 616 | 'startDate': '2015/01/31', 617 | 'salary': 268.509 618 | }, { 619 | 'name': 'Amena Stone', 620 | 'position': 'Enim Incorporated', 621 | 'office': 'Guinea', 622 | 'ext': '1211', 623 | 'startDate': '2014/09/23', 624 | 'salary': 214.381 625 | }, { 626 | 'name': 'Danielle Coffey', 627 | 'position': 'Feugiat Placerat Corp.', 628 | 'office': 'Sao Tome and Principe', 629 | 'ext': '8176', 630 | 'startDate': '2015/06/17', 631 | 'salary': 137.423 632 | }, { 633 | 'name': 'Buffy Russell', 634 | 'position': 'Lacus Quisque Ltd', 635 | 'office': 'Ecuador', 636 | 'ext': '6741', 637 | 'startDate': '2014/10/17', 638 | 'salary': 612.184 639 | }, { 640 | 'name': 'Kaitlin Lamb', 641 | 'position': 'Malesuada Fringilla Est Associates', 642 | 'office': 'Algeria', 643 | 'ext': '5054', 644 | 'startDate': '2014/10/18', 645 | 'salary': 327.367 646 | }, { 647 | 'name': 'Leilani Yates', 648 | 'position': 'Mus Proin LLC', 649 | 'office': 'South Sudan', 650 | 'ext': '1550', 651 | 'startDate': '2015/05/27', 652 | 'salary': 743.493 653 | }, { 654 | 'name': 'Jemima Moon', 655 | 'position': 'Phasellus Corp.', 656 | 'office': 'South Georgia and The South Sandwich Islands', 657 | 'ext': '7582', 658 | 'startDate': '2015/05/21', 659 | 'salary': 496.067 660 | }, { 661 | 'name': 'Hiroko Schwartz', 662 | 'position': 'Neque Institute', 663 | 'office': 'Saint Vincent and The Grenadines', 664 | 'ext': '9368', 665 | 'startDate': '2015/03/13', 666 | 'salary': 178.782 667 | }, { 668 | 'name': 'Nathaniel Jensen', 669 | 'position': 'Mi Tempor Limited', 670 | 'office': 'Dominica', 671 | 'ext': '8331', 672 | 'startDate': '2014/12/05', 673 | 'salary': 37.441 674 | }, { 675 | 'name': 'Silas Sweeney', 676 | 'position': 'Ultrices Institute', 677 | 'office': 'Turkmenistan', 678 | 'ext': '0746', 679 | 'startDate': '2014/11/13', 680 | 'salary': 152.980 681 | }, { 682 | 'name': 'Jermaine Barry', 683 | 'position': 'Dapibus Corporation', 684 | 'office': 'Uzbekistan', 685 | 'ext': '1545', 686 | 'startDate': '2015/03/06', 687 | 'salary': 409.463 688 | }, { 689 | 'name': 'Tatiana Nichols', 690 | 'position': 'Nec Diam Industries', 691 | 'office': 'Cook Islands', 692 | 'ext': '4395', 693 | 'startDate': '2015/05/22', 694 | 'salary': 51.155 695 | }, { 696 | 'name': 'Rama Waller', 697 | 'position': 'Sem Pellentesque LLC', 698 | 'office': 'Andorra', 699 | 'ext': '2973', 700 | 'startDate': '2014/12/01', 701 | 'salary': 223.227 702 | } 703 | ]; 704 | -------------------------------------------------------------------------------- /demo/assets/fonts/glyphicons-halflings-regular.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | --------------------------------------------------------------------------------