diff --git a/.angular-cli.json b/.angular-cli.json new file mode 100644 index 00000000000..3462b18888b --- /dev/null +++ b/.angular-cli.json @@ -0,0 +1,68 @@ +{ + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "project": { + "name": "primeng" + }, + "apps": [ + { + "root": "src", + "outDir": "dist", + "assets": [ + "assets", + "favicon.png" + ], + "index": "index.html", + "main": "main.ts", + "polyfills": "polyfills.ts", + "test": "test.ts", + "tsconfig": "tsconfig.app.json", + "testTsconfig": "tsconfig.spec.json", + "prefix": "app", + "styles": [ + "styles.css", + "../node_modules/fullcalendar/dist/fullcalendar.min.css", + "../node_modules/quill/dist/quill.snow.css", + "../node_modules/font-awesome/css/font-awesome.min.css" + ], + "scripts": [ + "../node_modules/jquery/dist/jquery.js", + "../node_modules/moment/moment.js", + "../node_modules/chart.js/dist/Chart.js", + "../node_modules/fullcalendar/dist/fullcalendar.js", + "../node_modules/quill/dist/quill.js", + "../node_modules/prismjs/prism.js", + "../node_modules/prismjs/components/prism-typescript.js" + ], + "environmentSource": "environments/environment.ts", + "environments": { + "dev": "environments/environment.ts", + "prod": "environments/environment.prod.ts" + } + } + ], + "e2e": { + "protractor": { + "config": "./protractor.conf.js" + } + }, + "lint": [ + { + "project": "src/tsconfig.app.json" + }, + { + "project": "src/tsconfig.spec.json" + }, + { + "project": "e2e/tsconfig.e2e.json" + } + ], + "test": { + "karma": { + "config": "./karma.conf.js" + } + }, + "defaults": { + "styleExt": "css", + "component": {} + } +} diff --git a/.editorconfig b/.editorconfig index 58717cd0a17..6e87a003da8 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,11 +1,13 @@ -# http://editorconfig.org - +# Editor configuration, see http://editorconfig.org root = true [*] charset = utf-8 indent_style = space -indent_size = 4 -end_of_line = lf -insert_final_newline = false +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +max_line_length = off trim_trailing_whitespace = false diff --git a/.gitignore b/.gitignore index 0b6047ebd15..825c75d0a42 100644 --- a/.gitignore +++ b/.gitignore @@ -1,32 +1,50 @@ +# See http://help.github.com/ignore-files/ for more about ignoring files. + +# compiled output +/dist +/tmp +/out-tsc +/components +/resources +/aot + # dependencies -node_modules - -# generated by compilation -primeng.js -components/**/*.js -showcase/*.js -showcase/demo/**/*.js -showcase/setup/*.js -showcase/theming/*.js -*.map - -# production showcase bundle -dist - -# distribution resources -resources/**/*.css -resources/images - -# type definition -*.d.ts - -# aot -aot -components/**/*.metadata.json - -# misc -*.log -.DS_STORE -.idea -.vscode -.sass-cache \ No newline at end of file +/node_modules + +# IDEs and editors +/.idea +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# IDE - VSCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +# misc +/.sass-cache +/connect.lock +/coverage +/libpeerconnection.log +npm-debug.log +testem.log +/typings + +# themes +/src/assets/components/themes/**/*.css +/src/assets/components/themes/**/*.map +!/src/assets/components/themes/bootstrap/theme.css + +# e2e +/e2e/*.js +/e2e/*.map + +# System Files +.DS_Store +Thumbs.db diff --git a/.npmignore b/.npmignore index fcd8c372f72..4d1507c6435 100644 --- a/.npmignore +++ b/.npmignore @@ -1,35 +1,53 @@ +# compiled output +/dist +/tmp +/out-tsc +/aot + +# source +src + +# test +e2e +karmaconf.js +protractor.conf.js + # dependencies node_modules -# demo -showcase -index.html -upload.php +# IDEs and editors +/.idea +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace +.editor-config + +# IDE - VSCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json -# typescript -*.ts -!*.d.ts - -# git -.git +# misc +/.sass-cache +/connect.lock +/coverage +/libpeerconnection.log +npm-debug.log +testem.log +/typings .gitignore # config +.angular-cli.json tsconfig.json -tsconfig-aot.json -webpack.config.js -config -gulpfile.js - -# aot -aot - -# misc -.github -.vscode -*.log -prod -.editorconfig - - +tsconfig-release.json +tslint.json +# System Files +.DS_Store +Thumbs.db diff --git a/README.md b/README.md new file mode 100644 index 00000000000..0b027e07bcb --- /dev/null +++ b/README.md @@ -0,0 +1,28 @@ +# Primeng + +This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.1.0. + +## Development server + +Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. + +## Code scaffolding + +Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|module`. + +## Build + +Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build. + +## Running unit tests + +Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). + +## Running end-to-end tests + +Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). +Before running the tests make sure you are serving the app via `ng serve`. + +## Further help + +To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). diff --git a/e2e/app.e2e-spec.ts b/e2e/app.e2e-spec.ts new file mode 100644 index 00000000000..83f61bb6a73 --- /dev/null +++ b/e2e/app.e2e-spec.ts @@ -0,0 +1,16 @@ +import { PrimengPage } from './app.po'; + +describe('primeng App', () => { + let page: PrimengPage; + + beforeEach(() => { + page = new PrimengPage(); + }); + + it('should display welcome message', done => { + page.navigateTo(); + page.getPROText() + .then(msg => expect(msg).toEqual('PrimeNG PRO Support')) + .then(done, done.fail); + }); +}); diff --git a/e2e/app.po.ts b/e2e/app.po.ts new file mode 100644 index 00000000000..7b1a2d7ee41 --- /dev/null +++ b/e2e/app.po.ts @@ -0,0 +1,11 @@ +import { browser, by, element } from 'protractor'; + +export class PrimengPage { + navigateTo() { + return browser.get('/'); + } + + getPROText() { + return element(by.css('.pro-title')).getText(); + } +} diff --git a/e2e/tsconfig.e2e.json b/e2e/tsconfig.e2e.json new file mode 100644 index 00000000000..e2a9a2fc779 --- /dev/null +++ b/e2e/tsconfig.e2e.json @@ -0,0 +1,12 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "outDir": "../out-tsc/e2e", + "module": "commonjs", + "target": "es5", + "types": [ + "jasmine", + "node" + ] + } +} diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 00000000000..b9db99a15d6 --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,50 @@ +'use strict'; + +var gulp = require('gulp'), + concat = require('gulp-concat'), + uglifycss = require('gulp-uglifycss'), + rename = require('gulp-rename'), + del = require('del'), + flatten = require('gulp-flatten'); + +gulp.task('build-css', function() { + gulp.src([ + 'src/app/components/common/common.css', + 'src/app/components/**/*.css' + ]) + .pipe(concat('primeng.css')) + .pipe(gulp.dest('resources')); +}); + +gulp.task('build-css-prod', function() { + gulp.src([ + 'src/app/components/common/common.css', + 'src/app/components/**/*.css' + ]) + .pipe(concat('primeng.css')) + .pipe(gulp.dest('resources')) + .pipe(uglifycss({"uglyComments": true})) + .pipe(rename('primeng.min.css')) + .pipe(gulp.dest('resources')); +}); + +gulp.task('images', function() { + return gulp.src(['src/app/components/**/images/*.png', 'src/app/components/**/images/*.gif']) + .pipe(flatten()) + .pipe(gulp.dest('resources/images')); +}); + +gulp.task('themes', function() { + return gulp.src(['src/assets/components/themes/**/*']) + .pipe(gulp.dest('resources/themes')); +}); + +//Cleaning previous gulp tasks from project +gulp.task('clean', function() { + del(['resources']); +}); + +//Building project with run sequence +gulp.task('build-assets', ['clean','build-css-prod', 'images', 'themes']); + + \ No newline at end of file diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 00000000000..4d9ab9d9482 --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,33 @@ +// Karma configuration file, see link for more information +// https://karma-runner.github.io/0.13/config/configuration-file.html + +module.exports = function (config) { + config.set({ + basePath: '', + frameworks: ['jasmine', '@angular/cli'], + plugins: [ + require('karma-jasmine'), + require('karma-chrome-launcher'), + require('karma-jasmine-html-reporter'), + require('karma-coverage-istanbul-reporter'), + require('@angular/cli/plugins/karma') + ], + client:{ + clearContext: false // leave Jasmine Spec Runner output visible in browser + }, + coverageIstanbulReporter: { + reports: [ 'html', 'lcovonly' ], + fixWebpackSourcePaths: true + }, + angularCli: { + environment: 'dev' + }, + reporters: ['progress', 'kjhtml'], + port: 9876, + colors: true, + logLevel: config.LOG_INFO, + autoWatch: true, + browsers: ['Chrome'], + singleRun: false + }); +}; diff --git a/package.json b/package.json new file mode 100644 index 00000000000..1096b13498c --- /dev/null +++ b/package.json @@ -0,0 +1,65 @@ +{ + "name": "primeng", + "version": "0.0.0", + "license": "MIT", + "scripts": { + "ng": "ng", + "start": "ng serve", + "build": "ng build", + "test": "ng test", + "lint": "ng lint", + "e2e": "ng e2e" + }, + "private": true, + "dependencies": { + "@angular/animations": "^4.0.0", + "@angular/common": "^4.0.0", + "@angular/compiler": "^4.0.0", + "@angular/core": "^4.0.0", + "@angular/forms": "^4.0.0", + "@angular/http": "^4.0.0", + "@angular/platform-browser": "^4.0.0", + "@angular/platform-browser-dynamic": "^4.0.0", + "@angular/router": "^4.0.0", + "core-js": "^2.4.1", + "install": "^0.10.1", + "npm": "^5.0.1", + "rxjs": "^5.1.0", + "zone.js": "^0.8.4", + "chart.js": "2.1.3", + "fullcalendar": "^3.1.0", + "jquery": "^3.1.1", + "moment": "^2.17.1", + "font-awesome":"4.7.0", + "quill": "^1.1.8", + "web-animations-js": "^2.2.2", + "prismjs": "^1.6.0" + }, + "devDependencies": { + "@angular/cli": "1.1.0", + "@angular/compiler-cli": "^4.0.0", + "@angular/language-service": "^4.0.0", + "@types/jasmine": "2.5.45", + "@types/node": "~6.0.60", + "codelyzer": "~3.0.1", + "jasmine-core": "~2.6.2", + "jasmine-spec-reporter": "~4.1.0", + "karma": "~1.7.0", + "karma-chrome-launcher": "~2.1.1", + "karma-cli": "~1.0.1", + "karma-jasmine": "~1.1.0", + "karma-jasmine-html-reporter": "^0.2.2", + "karma-coverage-istanbul-reporter": "^1.2.1", + "protractor": "~5.1.2", + "ts-node": "~3.0.4", + "tslint": "~5.3.2", + "typescript": "~2.3.3", + "del": "^2.2.0", + "gulp": "^3.9.1", + "gulp-concat": "^2.6.0", + "gulp-flatten": "^0.2.0", + "gulp-rename": "^1.2.2", + "gulp-uglify": "^1.5.3", + "gulp-uglifycss": "^1.0.6" + } +} diff --git a/primeng.js b/primeng.js new file mode 100644 index 00000000000..bc92b8d376c --- /dev/null +++ b/primeng.js @@ -0,0 +1,75 @@ +/* Shorthand */ +"use strict"; +function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; +} +Object.defineProperty(exports, "__esModule", { value: true }); +__export(require("./components/common/api")); +__export(require("./components/common/shared")); +__export(require("./components/accordion/accordion")); +__export(require("./components/autocomplete/autocomplete")); +__export(require("./components/blockui/blockui")); +__export(require("./components/breadcrumb/breadcrumb")); +__export(require("./components/button/button")); +__export(require("./components/captcha/captcha")); +__export(require("./components/calendar/calendar")); +__export(require("./components/carousel/carousel")); +__export(require("./components/chart/chart")); +__export(require("./components/checkbox/checkbox")); +__export(require("./components/chips/chips")); +__export(require("./components/codehighlighter/codehighlighter")); +__export(require("./components/contextmenu/contextmenu")); +__export(require("./components/datagrid/datagrid")); +__export(require("./components/datalist/datalist")); +__export(require("./components/datascroller/datascroller")); +__export(require("./components/datatable/datatable")); +__export(require("./components/defer/defer")); +__export(require("./components/confirmdialog/confirmdialog")); +__export(require("./components/dialog/dialog")); +__export(require("./components/dragdrop/dragdrop")); +__export(require("./components/dropdown/dropdown")); +__export(require("./components/editor/editor")); +__export(require("./components/fieldset/fieldset")); +__export(require("./components/fileupload/fileupload")); +__export(require("./components/galleria/galleria")); +__export(require("./components/gmap/gmap")); +__export(require("./components/growl/growl")); +__export(require("./components/inplace/inplace")); +__export(require("./components/inputmask/inputmask")); +__export(require("./components/inputswitch/inputswitch")); +__export(require("./components/inputtext/inputtext")); +__export(require("./components/inputtextarea/inputtextarea")); +__export(require("./components/lightbox/lightbox")); +__export(require("./components/listbox/listbox")); +__export(require("./components/megamenu/megamenu")); +__export(require("./components/menu/menu")); +__export(require("./components/menubar/menubar")); +__export(require("./components/messages/messages")); +__export(require("./components/multiselect/multiselect")); +__export(require("./components/orderlist/orderlist")); +__export(require("./components/overlaypanel/overlaypanel")); +__export(require("./components/paginator/paginator")); +__export(require("./components/panel/panel")); +__export(require("./components/panelmenu/panelmenu")); +__export(require("./components/password/password")); +__export(require("./components/picklist/picklist")); +__export(require("./components/progressbar/progressbar")); +__export(require("./components/radiobutton/radiobutton")); +__export(require("./components/rating/rating")); +__export(require("./components/schedule/schedule")); +__export(require("./components/selectbutton/selectbutton")); +__export(require("./components/slidemenu/slidemenu")); +__export(require("./components/slider/slider")); +__export(require("./components/spinner/spinner")); +__export(require("./components/splitbutton/splitbutton")); +__export(require("./components/steps/steps")); +__export(require("./components/tabview/tabview")); +__export(require("./components/tabmenu/tabmenu")); +__export(require("./components/terminal/terminal")); +__export(require("./components/tieredmenu/tieredmenu")); +__export(require("./components/togglebutton/togglebutton")); +__export(require("./components/toolbar/toolbar")); +__export(require("./components/tooltip/tooltip")); +__export(require("./components/tree/tree")); +__export(require("./components/treetable/treetable")); +__export(require("./components/tristatecheckbox/tristatecheckbox")); \ No newline at end of file diff --git a/protractor.conf.js b/protractor.conf.js new file mode 100644 index 00000000000..7ee3b5ee863 --- /dev/null +++ b/protractor.conf.js @@ -0,0 +1,28 @@ +// Protractor configuration file, see link for more information +// https://github.com/angular/protractor/blob/master/lib/config.ts + +const { SpecReporter } = require('jasmine-spec-reporter'); + +exports.config = { + allScriptsTimeout: 11000, + specs: [ + './e2e/**/*.e2e-spec.ts' + ], + capabilities: { + 'browserName': 'chrome' + }, + directConnect: true, + baseUrl: 'http://localhost:4200/', + framework: 'jasmine', + jasmineNodeOpts: { + showColors: true, + defaultTimeoutInterval: 30000, + print: function() {} + }, + onPrepare() { + require('ts-node').register({ + project: 'e2e/tsconfig.e2e.json' + }); + jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); + } +}; diff --git a/src/app/components/accordion/accordion.css b/src/app/components/accordion/accordion.css new file mode 100644 index 00000000000..75c03fc4edf --- /dev/null +++ b/src/app/components/accordion/accordion.css @@ -0,0 +1,51 @@ +.ui-accordion { + width: 100%; +} + +.ui-accordion .ui-accordion-header { + cursor: pointer; + position: relative; + margin-top: 1px; + zoom: 1; +} + +.ui-accordion .ui-accordion-header a { + display: block; + padding: .5em .5em .5em 2em; +} + +.ui-accordion .ui-accordion-header>.fa { + position: absolute; + left: .5em; + top: 50%; + margin-top: -.5em; +} + +.ui-accordion .ui-accordion-content { + padding: 1em; + border-top: 0; + overflow: visible; + zoom: 1; +} + +.ui-accordion .ui-accordion-header.ui-state-disabled, +.ui-accordion .ui-accordion-header.ui-state-disabled a { + cursor: default; +} + +.ui-accordion-content-wrapper-overflown { + overflow: hidden; +} + +.ui-rtl .ui-accordion .ui-accordion-header a { + padding: .5em 2em .5em .5em; +} + +.ui-rtl .ui-accordion .ui-accordion-header > .fa { + left: initial; + right: .5em; +} + +.ui-rtl .ui-accordion .ui-accordion-header > .fa-caret-right:before { + content: '\f0d9'; +} \ No newline at end of file diff --git a/src/app/components/accordion/accordion.ts b/src/app/components/accordion/accordion.ts new file mode 100644 index 00000000000..ce8e43502a5 --- /dev/null +++ b/src/app/components/accordion/accordion.ts @@ -0,0 +1,148 @@ +import {NgModule,Component,ElementRef,AfterContentInit,Input,Output,EventEmitter,ContentChildren,QueryList} from '@angular/core'; +import {trigger,state,style,transition,animate} from '@angular/animations'; +import {CommonModule} from '@angular/common'; +import {Header} from '../common/shared'; +import {BlockableUI} from '../common/blockableui'; + +@Component({ + selector: 'p-accordion', + template: ` +
+ +
+ `, +}) +export class Accordion implements BlockableUI { + + @Input() multiple: boolean; + + @Output() onClose: EventEmitter = new EventEmitter(); + + @Output() onOpen: EventEmitter = new EventEmitter(); + + @Input() style: any; + + @Input() styleClass: string; + + @Input() lazy: boolean; + + public tabs: AccordionTab[] = []; + + constructor(public el: ElementRef) {} + + addTab(tab: AccordionTab) { + this.tabs.push(tab); + } + + getBlockableElement(): HTMLElement { + return this.el.nativeElement.children[0]; + } +} + +@Component({ + selector: 'p-accordionTab', + template: ` + +
+
+ +
+
+ `, + animations: [ + trigger('tabContent', [ + state('hidden', style({ + height: '0' + })), + state('visible', style({ + height: '*' + })), + transition('visible <=> hidden', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)')) + ]) + ] +}) +export class AccordionTab { + + @Input() header: string; + + @Input() selected: boolean; + + @Input() disabled: boolean; + + @Output() selectedChange: EventEmitter = new EventEmitter(); + + @ContentChildren(Header) headerFacet: QueryList; + + public animating: boolean; + + constructor(public accordion: Accordion) { + this.accordion.addTab(this); + } + + toggle(event) { + if(this.disabled || this.animating) { + return false; + } + + this.animating = true; + let index = this.findTabIndex(); + + if(this.selected) { + this.selected = false; + this.accordion.onClose.emit({originalEvent: event, index: index}); + } + else { + if(!this.accordion.multiple) { + for(var i = 0; i < this.accordion.tabs.length; i++) { + this.accordion.tabs[i].selected = false; + this.accordion.tabs[i].selectedChange.emit(false); + } + } + + this.selected = true; + this.accordion.onOpen.emit({originalEvent: event, index: index}); + } + + this.selectedChange.emit(this.selected); + + event.preventDefault(); + } + + findTabIndex() { + let index = -1; + for(var i = 0; i < this.accordion.tabs.length; i++) { + if(this.accordion.tabs[i] == this) { + index = i; + break; + } + } + return index; + } + + get lazy(): boolean { + return this.accordion.lazy; + } + + get hasHeaderFacet(): boolean { + return this.headerFacet && this.headerFacet.length > 0; + } + + onToggleDone(event: Event) { + this.animating = false; + } +} + +@NgModule({ + imports: [CommonModule], + exports: [Accordion,AccordionTab], + declarations: [Accordion,AccordionTab] +}) +export class AccordionModule { } diff --git a/src/app/components/autocomplete/autocomplete.css b/src/app/components/autocomplete/autocomplete.css new file mode 100644 index 00000000000..e2f89e1e10e --- /dev/null +++ b/src/app/components/autocomplete/autocomplete.css @@ -0,0 +1,142 @@ +.ui-autocomplete { + width: auto; + zoom: 1; + cursor: pointer; + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; + position: relative; + display: inline-block; +} + +.ui-autocomplete .ui-autocomplete-dropdown { + height: 100%; + width: 2em; + margin-right: 0; + vertical-align: top; +} + +.ui-autocomplete-query { + font-weight: bold; +} + +.ui-autocomplete-panel { + position: absolute; + overflow: auto; +} + +.ui-autocomplete-panel .ui-autocomplete-list { + padding: 0.4em; + border: 0 none; +} + +.ui-autocomplete-panel .ui-autocomplete-list-item { + border: 0 none; + cursor: pointer; + font-weight: normal; + margin: 1px 0; + padding: 0.186em 0.313em; + text-align: left; +} + +.ui-autocomplete .ui-button-icon-only, +.ui-autocomplete .ui-button-icon-only:hover, +.ui-autocomplete .ui-button-icon-only:focus, +.ui-autocomplete .ui-button-icon-only:active { + border-left: 0 none; +} + +/* Multiple Selection */ +.ui-autocomplete-multiple-container { + display: inline-block; +} + +.ui-autocomplete-multiple-container.ui-inputtext { + clear: left; + cursor: text; + list-style-type: none; + margin: 0; + overflow: hidden; + padding: 0 .25em; +} + +.ui-autocomplete-token { + cursor: default; + display: inline-block; + vertical-align: middle; + overflow: hidden; + padding: .125em .5em; + white-space: nowrap; + position: relative; + margin-right: .125em; + border: 0 none; + font-size: .9em; +} + +.ui-autocomplete-token-label { + display: block; + margin-right: 2em; +} + +.ui-autocomplete-token-icon { + margin-top: -.5em; + position: absolute; + right: 0.2em; + top: 50%; + cursor: pointer; +} + +.ui-autocomplete-input-token { + display: inline-block; + vertical-align: middle; + list-style-type: none; + margin: 0 0 0 .125em; + padding: .25em .25em .25em 0; +} + +.ui-autocomplete-input-token input { + border: 0 none; + width: 10em; + outline: medium none; + background-color: transparent; + margin: 0; + padding: 0; + box-shadow: none; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; +} + +.ui-autocomplete-dd input.ui-corner-all , +.ui-autocomplete-dd .ui-autocomplete-multiple-container.ui-corner-all { + -moz-border-radius-topright: 0px; + -webkit-border-top-right-radius: 0px; + border-top-right-radius: 0px; + -moz-border-radius-bottomright: 0px; + -webkit-border-bottom-right-radius: 0px; + border-bottom-right-radius: 0px; + } + +.ui-autocomplete-dd .ui-autocomplete-dropdown.ui-corner-all { + -moz-border-radius-topleft: 0px; + -webkit-border-top-left-radius: 0px; + border-top-left-radius: 0px; + -moz-border-radius-bottomleft: 0px; + -webkit-border-bottom-left-radius: 0px; + border-bottom-left-radius: 0px; +} + +/** AutoComplete **/ +.ui-fluid .ui-autocomplete, +.ui-fluid .ui-autocomplete-input { + width: 100%; +} + +.ui-fluid .ui-autocomplete.ui-autocomplete-dd .ui-autocomplete-input, +.ui-fluid .ui-autocomplete.ui-autocomplete-dd .ui-autocomplete-multiple-container { + width: calc(100% - 2em); +} + +.ui-fluid .ui-autocomplete .ui-autocomplete-dropdown.ui-button { + width: 2em; +} \ No newline at end of file diff --git a/src/app/components/autocomplete/autocomplete.ts b/src/app/components/autocomplete/autocomplete.ts new file mode 100644 index 00000000000..c053bd73838 --- /dev/null +++ b/src/app/components/autocomplete/autocomplete.ts @@ -0,0 +1,534 @@ +import {NgModule,Component,ViewChild,ElementRef,AfterViewInit,AfterContentInit,AfterViewChecked,Input,Output,EventEmitter,ContentChildren,QueryList,TemplateRef,Renderer2,forwardRef,ChangeDetectorRef} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {InputTextModule} from '../inputtext/inputtext'; +import {ButtonModule} from '../button/button'; +import {SharedModule,PrimeTemplate} from '../common/shared'; +import {DomHandler} from '../dom/domhandler'; +import {ObjectUtils} from '../utils/ObjectUtils'; +import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; + +export const AUTOCOMPLETE_VALUE_ACCESSOR: any = { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => AutoComplete), + multi: true +}; + +@Component({ + selector: 'p-autoComplete', + template: ` + +
    +
  • + + {{field ? val[field] : val}} + +
  • +
  • + +
  • +
+
+
    +
  • + {{field ? option[field] : option}} + +
  • +
  • {{emptyMessage}}
  • +
+
+
+ `, + host: { + '[class.ui-inputwrapper-filled]': 'filled', + '[class.ui-inputwrapper-focus]': 'focus' + }, + providers: [DomHandler,ObjectUtils,AUTOCOMPLETE_VALUE_ACCESSOR] +}) +export class AutoComplete implements AfterViewInit,AfterViewChecked,ControlValueAccessor { + + @Input() minLength: number = 1; + + @Input() delay: number = 300; + + @Input() style: any; + + @Input() styleClass: string; + + @Input() inputStyle: any; + + @Input() inputId: string; + + @Input() inputStyleClass: string; + + @Input() placeholder: string; + + @Input() readonly: boolean; + + @Input() disabled: boolean; + + @Input() maxlength: number; + + @Input() size: number; + + @Input() appendTo: any; + + @Input() autoHighlight: boolean; + + @Input() type: string = 'text'; + + @Output() completeMethod: EventEmitter = new EventEmitter(); + + @Output() onSelect: EventEmitter = new EventEmitter(); + + @Output() onUnselect: EventEmitter = new EventEmitter(); + + @Output() onFocus: EventEmitter = new EventEmitter(); + + @Output() onBlur: EventEmitter = new EventEmitter(); + + @Output() onDropdownClick: EventEmitter = new EventEmitter(); + + @Input() field: string; + + @Input() scrollHeight: string = '200px'; + + @Input() dropdown: boolean; + + @Input() multiple: boolean; + + @Input() tabindex: number; + + @Input() dataKey: string; + + @Input() emptyMessage: string; + + @ViewChild('in') inputEL: ElementRef; + + @ViewChild('multiIn') multiInputEL: ElementRef; + + @ViewChild('panel') panelEL: ElementRef; + + @ViewChild('multiContainer') multiContainerEL: ElementRef; + + @ContentChildren(PrimeTemplate) templates: QueryList; + + public itemTemplate: TemplateRef; + + public selectedItemTemplate: TemplateRef; + + value: any; + + _suggestions: any[]; + + onModelChange: Function = () => {}; + + onModelTouched: Function = () => {}; + + timeout: any; + + differ: any; + + panelVisible: boolean = false; + + documentClickListener: any; + + suggestionsUpdated: boolean; + + highlightOption: any; + + highlightOptionChanged: boolean; + + focus: boolean = false; + + filled: boolean; + + inputClick: boolean; + + inputKeyDown: boolean; + + noResults: boolean; + + constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2, public objectUtils: ObjectUtils, public cd: ChangeDetectorRef) {} + + @Input() get suggestions(): any[] { + return this._suggestions; + } + + set suggestions(val:any[]) { + this._suggestions = val; + + if(this.panelEL && this.panelEL.nativeElement) { + if(this._suggestions && this._suggestions.length) { + this.noResults = false; + this.show(); + this.suggestionsUpdated = true; + + if(this.autoHighlight) { + this.highlightOption = this._suggestions[0]; + } + } + else { + this.noResults = true; + + if(this.emptyMessage) { + this.show(); + this.suggestionsUpdated = true; + } + else { + this.hide(); + } + } + } + } + + ngAfterContentInit() { + this.templates.forEach((item) => { + switch(item.getType()) { + case 'item': + this.itemTemplate = item.template; + break; + + case 'selectedItem': + this.selectedItemTemplate = item.template; + break; + + default: + this.itemTemplate = item.template; + break; + } + }); + } + + ngAfterViewInit() { + if(this.appendTo) { + if(this.appendTo === 'body') + document.body.appendChild(this.panelEL.nativeElement); + else + this.domHandler.appendChild(this.panelEL.nativeElement, this.appendTo); + } + } + + ngAfterViewChecked() { + if(this.suggestionsUpdated) { + this.align(); + this.suggestionsUpdated = false; + } + + if(this.highlightOptionChanged) { + let listItem = this.domHandler.findSingle(this.panelEL.nativeElement, 'li.ui-state-highlight'); + if(listItem) { + this.domHandler.scrollInView(this.panelEL.nativeElement, listItem); + } + this.highlightOptionChanged = false; + } + } + + writeValue(value: any) : void { + this.value = value; + this.filled = this.value && this.value != ''; + } + + registerOnChange(fn: Function): void { + this.onModelChange = fn; + } + + registerOnTouched(fn: Function): void { + this.onModelTouched = fn; + } + + setDisabledState(val: boolean): void { + this.disabled = val; + } + + onInput(event: KeyboardEvent) { + if(!this.inputKeyDown) { + return; + } + + let value = ( event.target).value; + if(!this.multiple) { + this.onModelChange(value); + } + + if(value.length === 0) { + this.hide(); + } + + if(value.length >= this.minLength) { + //Cancel the search request if user types within the timeout + if(this.timeout) { + clearTimeout(this.timeout); + } + + this.timeout = setTimeout(() => { + this.search(event, value); + }, this.delay); + } + else { + this.suggestions = null; + } + this.updateFilledState(); + this.inputKeyDown = false; + } + + onInputClick(event: MouseEvent) { + if(this.documentClickListener) { + this.inputClick = true; + } + } + + search(event: any, query: string) { + //allow empty string but not undefined or null + if(query === undefined || query === null) { + return; + } + + this.completeMethod.emit({ + originalEvent: event, + query: query + }); + } + + selectItem(option: any) { + if(this.multiple) { + this.multiInputEL.nativeElement.value = ''; + this.value = this.value||[]; + if(!this.isSelected(option)) { + this.value = [...this.value,option]; + this.onModelChange(this.value); + } + } + else { + this.inputEL.nativeElement.value = this.field ? this.objectUtils.resolveFieldData(option, this.field): option; + this.value = option; + this.onModelChange(this.value); + } + + this.onSelect.emit(option); + + this.focusInput(); + } + + show() { + if(this.multiInputEL || this.inputEL) { + let hasFocus = this.multiple ? document.activeElement == this.multiInputEL.nativeElement : document.activeElement == this.inputEL.nativeElement ; + if(!this.panelVisible && hasFocus) { + this.panelVisible = true; + this.panelEL.nativeElement.style.zIndex = ++DomHandler.zindex; + this.domHandler.fadeIn(this.panelEL.nativeElement, 200); + this.bindDocumentClickListener(); + } + } + } + + align() { + if(this.appendTo) + this.domHandler.absolutePosition(this.panelEL.nativeElement, (this.multiple ? this.multiContainerEL.nativeElement : this.inputEL.nativeElement)); + else + this.domHandler.relativePosition(this.panelEL.nativeElement, (this.multiple ? this.multiContainerEL.nativeElement : this.inputEL.nativeElement)); + } + + hide() { + this.panelVisible = false; + this.unbindDocumentClickListener(); + } + + handleDropdownClick(event) { + this.focusInput(); + let queryValue = this.multiple ? this.multiInputEL.nativeElement.value : this.inputEL.nativeElement.value; + this.onDropdownClick.emit({ + originalEvent: event, + query: queryValue + }); + } + + focusInput() { + if(this.multiple) + this.multiInputEL.nativeElement.focus(); + else + this.inputEL.nativeElement.focus(); + } + + removeItem(item: any) { + let itemIndex = this.domHandler.index(item); + let removedValue = this.value[itemIndex]; + this.value = this.value.filter((val, i) => i!=itemIndex); + this.onUnselect.emit(removedValue); + this.onModelChange(this.value); + } + + onKeydown(event) { + if(this.panelVisible) { + let highlightItemIndex = this.findOptionIndex(this.highlightOption); + + switch(event.which) { + //down + case 40: + if(highlightItemIndex != -1) { + var nextItemIndex = highlightItemIndex + 1; + if(nextItemIndex != (this.suggestions.length)) { + this.highlightOption = this.suggestions[nextItemIndex]; + this.highlightOptionChanged = true; + } + } + else { + this.highlightOption = this.suggestions[0]; + } + + event.preventDefault(); + break; + + //up + case 38: + if(highlightItemIndex > 0) { + let prevItemIndex = highlightItemIndex - 1; + this.highlightOption = this.suggestions[prevItemIndex]; + this.highlightOptionChanged = true; + } + + event.preventDefault(); + break; + + //enter + case 13: + if(this.highlightOption) { + this.selectItem(this.highlightOption); + this.hide(); + } + event.preventDefault(); + break; + + //escape + case 27: + this.hide(); + event.preventDefault(); + break; + + + //tab + case 9: + if(this.highlightOption) { + this.selectItem(this.highlightOption); + } + this.hide(); + break; + } + } else { + if(event.which === 40 && this.suggestions) { + this.search(event,event.target.value); + } + } + + if(this.multiple) { + switch(event.which) { + //backspace + case 8: + if(this.value && this.value.length && !this.multiInputEL.nativeElement.value) { + this.value = [...this.value]; + let removedValue = this.value.pop(); + this.onUnselect.emit(removedValue); + this.onModelChange(this.value); + } + break; + } + } + + this.inputKeyDown = true; + } + + onInputFocus(event) { + this.focus = true; + this.onFocus.emit(event); + } + + onInputBlur(event) { + this.focus = false; + this.onModelTouched(); + this.onBlur.emit(event); + } + + onInputChange(event) { + this.value = ( event.target).value; + } + + isSelected(val: any): boolean { + let selected: boolean = false; + if(this.value && this.value.length) { + for(let i = 0; i < this.value.length; i++) { + if(this.objectUtils.equals(this.value[i], val, this.dataKey)) { + selected = true; + break; + } + } + } + return selected; + } + + findOptionIndex(option): number { + let index: number = -1; + if(this.suggestions) { + for(let i = 0; i < this.suggestions.length; i++) { + if(this.objectUtils.equals(option, this.suggestions[i])) { + index = i; + break; + } + } + } + + return index; + } + + updateFilledState() { + if(this.multiple) + this.filled = (this.value && this.value.length) || (this.multiInputEL && this.multiInputEL.nativeElement && this.multiInputEL.nativeElement.value != ''); + else + this.filled = this.inputEL && this.inputEL.nativeElement && this.inputEL.nativeElement.value != ''; + } + + bindDocumentClickListener() { + if(!this.documentClickListener) { + this.documentClickListener = this.renderer.listen('document', 'click', (event) => { + if(event.which === 3) { + return; + } + + if(this.inputClick) + this.inputClick = false; + else + this.hide(); + + this.cd.markForCheck(); + }); + } + } + + unbindDocumentClickListener() { + if(this.documentClickListener) { + this.documentClickListener(); + this.documentClickListener = null; + } + } + + ngOnDestroy() { + this.unbindDocumentClickListener(); + + if(this.appendTo) { + this.el.nativeElement.appendChild(this.panelEL.nativeElement); + } + } +} + +@NgModule({ + imports: [CommonModule,InputTextModule,ButtonModule,SharedModule], + exports: [AutoComplete,SharedModule], + declarations: [AutoComplete] +}) +export class AutoCompleteModule { } \ No newline at end of file diff --git a/src/app/components/blockui/blockui.css b/src/app/components/blockui/blockui.css new file mode 100644 index 00000000000..4b00320e665 --- /dev/null +++ b/src/app/components/blockui/blockui.css @@ -0,0 +1,11 @@ +.ui-blockui { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.ui-blockui-document { + position: fixed; +} \ No newline at end of file diff --git a/src/app/components/blockui/blockui.ts b/src/app/components/blockui/blockui.ts new file mode 100644 index 00000000000..a3859da1223 --- /dev/null +++ b/src/app/components/blockui/blockui.ts @@ -0,0 +1,74 @@ +import {NgModule,Component,Input,AfterViewInit,OnDestroy,EventEmitter,ElementRef,ViewChild} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {DomHandler} from '../dom/domhandler'; +import {BlockableUI} from '../common/blockableui'; + +@Component({ + selector: 'p-blockUI', + template: ` +
+ +
+ `, + providers: [DomHandler] +}) +export class BlockUI implements AfterViewInit,OnDestroy { + + @Input() target: any; + + @ViewChild('mask') mask: ElementRef; + + _blocked: boolean; + + constructor(public el: ElementRef,public domHandler: DomHandler) {} + + @Input() get blocked(): boolean { + return this._blocked; + } + + set blocked(val: boolean) { + this._blocked = val; + + if(this.mask.nativeElement) { + if(this._blocked) + this.block(); + else + this.unblock(); + } + } + + ngAfterViewInit() { + if(this.target && !this.target.getBlockableElement) { + throw 'Target of BlockUI must implement BlockableUI interface'; + } + } + + block() { + if(this.target) { + this.target.getBlockableElement().appendChild(this.mask.nativeElement); + let style = this.target.style||{}; + style.position = 'relative'; + this.target.style = style; + } + else { + document.body.appendChild(this.mask.nativeElement); + } + + this.mask.nativeElement.style.zIndex = String(++DomHandler.zindex); + } + + unblock() { + this.el.nativeElement.appendChild(this.mask.nativeElement); + } + + ngOnDestroy() { + + } +} + +@NgModule({ + imports: [CommonModule], + exports: [BlockUI], + declarations: [BlockUI] +}) +export class BlockUIModule { } \ No newline at end of file diff --git a/src/app/components/breadcrumb/breadcrumb.css b/src/app/components/breadcrumb/breadcrumb.css new file mode 100644 index 00000000000..1a6c5573fd7 --- /dev/null +++ b/src/app/components/breadcrumb/breadcrumb.css @@ -0,0 +1,20 @@ +/** Breadcrumb **/ +.ui-breadcrumb { + margin: 0; + padding: 0; + padding: .3em; +} + +.ui-breadcrumb ul { + margin: 0; + padding: 0; +} + +.ui-breadcrumb ul li { + display: inline-block; + vertical-align: middle; +} + +.ui-breadcrumb ul li .ui-menuitem-link { + text-decoration: none; +} \ No newline at end of file diff --git a/src/app/components/breadcrumb/breadcrumb.ts b/src/app/components/breadcrumb/breadcrumb.ts new file mode 100644 index 00000000000..24681de122c --- /dev/null +++ b/src/app/components/breadcrumb/breadcrumb.ts @@ -0,0 +1,97 @@ +import {NgModule,Component,Input,OnDestroy,EventEmitter} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {MenuItem} from '../common/menuitem'; +import {Location} from '@angular/common'; +import {RouterModule} from '@angular/router'; + +@Component({ + selector: 'p-breadcrumb', + template: ` + + ` +}) +export class Breadcrumb implements OnDestroy { + + @Input() model: MenuItem[]; + + @Input() style: any; + + @Input() styleClass: string; + + @Input() home: MenuItem; + + itemClick(event, item: MenuItem) { + if(item.disabled) { + event.preventDefault(); + return; + } + + if(!item.url) { + event.preventDefault(); + } + + if(item.command) { + if(!item.eventEmitter) { + item.eventEmitter = new EventEmitter(); + item.eventEmitter.subscribe(item.command); + } + + item.eventEmitter.emit({ + originalEvent: event, + item: item + }); + } + } + + onHomeClick(event) { + if(this.home) { + this.itemClick(event, this.home); + } + } + + ngOnDestroy() { + if(this.model) { + for(let item of this.model) { + if(item.eventEmitter) { + item.eventEmitter.unsubscribe(); + } + } + } + } + +} + +@NgModule({ + imports: [CommonModule,RouterModule], + exports: [Breadcrumb,RouterModule], + declarations: [Breadcrumb] +}) +export class BreadcrumbModule { } \ No newline at end of file diff --git a/src/app/components/button/button.css b/src/app/components/button/button.css new file mode 100644 index 00000000000..bdfecfa3da3 --- /dev/null +++ b/src/app/components/button/button.css @@ -0,0 +1,192 @@ +/* Button */ +.ui-button { + display: inline-block; + position: relative; + padding: 0; + margin-right: .1em; + text-decoration: none !important; + cursor: pointer; + text-align: center; + zoom: 1; + overflow: visible; /* the overflow property removes extra width in IE */ +} + +.ui-button-icon-only { + width: 2em; +} + +/*button text element */ +.ui-button .ui-button-text { + display: block; + line-height: normal; +} + +.ui-button-text-only .ui-button-text { + padding: .25em 1em; +} + +.ui-button-icon-only .ui-button-text { + padding: .25em; + text-indent: -9999999px; +} + +.ui-button-text-icon-left .ui-button-text { + padding: .25em 1em .25em 2.1em; +} + +.ui-button-text-icon-right .ui-button-text { + padding: .25em 2.1em .25em 1em; +} + +/*button icon element(s) */ +.ui-button-icon-only .fa, +.ui-button-text-icon-left .fa, +.ui-button-text-icon-right .fa { + position: absolute; + top: 50%; + margin-top: -.5em; +} + +.ui-button-icon-only .fa { + top: 50%; + left: 50%; + margin-top: -.5em; + margin-left: -.6em; +} + +.ui-button-icon-left { + left: .5em; +} + +.ui-button-icon-right { + right: .5em; +} + +/*button sets*/ +.ui-buttonset .ui-button { + margin-left: 0; + margin-right: 0; +} + +/* workarounds */ +button.ui-button::-moz-focus-inner { + border: 0; padding: 0; /* reset extra padding in Firefox */ +} + +/** Fluid **/ +.ui-fluid .ui-button { + width: 100%; + box-sizing: border-box; + -webkit-box-sizing:border-box; + -moz-box-sizing: border-box; +} + +.ui-fluid .ui-button-text-icon-left .ui-button-text, +.ui-fluid .ui-button-text-icon-right .ui-button-text { + padding-left: 1em; + padding-right: 1em; +} + +/** ButtonSet **/ +.ui-fluid .ui-buttonset { + width: 100%; +} + +.ui-fluid .ui-buttonset.ui-buttonset-1 .ui-button {width: 100%;} +.ui-fluid .ui-buttonset.ui-buttonset-2 .ui-button {width: 50%;} +.ui-fluid .ui-buttonset.ui-buttonset-3 .ui-button {width: 33.3%;} +.ui-fluid .ui-buttonset.ui-buttonset-4 .ui-button {width: 25%;} +.ui-fluid .ui-buttonset.ui-buttonset-5 .ui-button {width: 20%;} +.ui-fluid .ui-buttonset.ui-buttonset-6 .ui-button {width: 16.6%;} + +@media (max-width: 640px) { + .ui-fluid .ui-buttonset.ui-buttonset-1 .ui-button, + .ui-fluid .ui-buttonset.ui-buttonset-2 .ui-button, + .ui-fluid .ui-buttonset.ui-buttonset-3 .ui-button, + .ui-fluid .ui-buttonset.ui-buttonset-4 .ui-button, + .ui-fluid .ui-buttonset.ui-buttonset-5 .ui-button, + .ui-fluid .ui-buttonset.ui-buttonset-6 .ui-button { + width: 100%; + } +} + +/* Severity Buttons */ +/* Secondary */ +.ui-button.ui-button-secondary.ui-state-default { + background-color: #ffffff; + border-color: #cccccc; + color: #373a3c; +} + +.ui-button.ui-button-secondary:enabled:hover, +.ui-button.ui-button-secondary:focus { + background-color: #f2f2f2; +} + +.ui-button.ui-button-secondary:enabled:active { + background-color: #e6e6e6; +} + +/* Success */ +.ui-button.ui-button-success.ui-state-default { + background-color: #5cb85c; + border-color: #5cb85c; + color: #ffffff; +} + +.ui-button.ui-button-success:enabled:hover, +.ui-button.ui-button-success:focus { + background-color: #4cae4c; +} + +.ui-button.ui-button-success:enabled:active { + background-color: #449d44; +} + +/* Info */ +.ui-button.ui-button-info.ui-state-default { + background-color: #5bc0de; + border-color: #5bc0de; + color: #ffffff; +} + +.ui-button.ui-button-info:enabled:hover, +.ui-button.ui-button-info:focus { + background-color: #46b8da; +} + +.ui-button.ui-button-info:enabled:active { + background-color: #31b0d5; +} + +/* Warning */ +.ui-button.ui-button-warning.ui-state-default { + background-color: #f0ad4e; + border-color: #f0ad4e; + color: #ffffff; +} + +.ui-button.ui-button-warning:enabled:hover, +.ui-button.ui-button-warning:focus { + background-color: #eea236; +} + +.ui-button.ui-button-warning:enabled:active { + background-color: #ec971f; +} + +/* Danger */ +.ui-button.ui-button-danger.ui-state-default { + background-color: #d9534f; + border-color: #d9534f; + color: #ffffff; +} + +.ui-button.ui-button-danger:enabled:hover, +.ui-button.ui-button-danger:focus { + background-color: #d43f3a; +} + +.ui-button.ui-button-danger:enabled:active { + background-color: #c9302c; +} \ No newline at end of file diff --git a/src/app/components/button/button.ts b/src/app/components/button/button.ts new file mode 100644 index 00000000000..1c0a27f776d --- /dev/null +++ b/src/app/components/button/button.ts @@ -0,0 +1,98 @@ +import {NgModule,Directive,ElementRef,AfterViewInit,OnDestroy,HostBinding,HostListener,Input} from '@angular/core'; +import {DomHandler} from '../dom/domhandler'; +import {CommonModule} from '@angular/common'; + +@Directive({ + selector: '[pButton]', + providers: [DomHandler] +}) +export class Button implements AfterViewInit, OnDestroy { + + @Input() iconPos: string = 'left'; + + @Input() cornerStyleClass: string = 'ui-corner-all'; + + public _label: string; + + public _icon: string; + + public initialized: boolean; + + constructor(public el: ElementRef, public domHandler: DomHandler) {} + + ngAfterViewInit() { + this.domHandler.addMultipleClasses(this.el.nativeElement, this.getStyleClass()); + if(this.icon) { + let iconElement = document.createElement("span"); + let iconPosClass = (this.iconPos == 'right') ? 'ui-button-icon-right': 'ui-button-icon-left'; + iconElement.className = iconPosClass + ' ui-c fa fa-fw ' + this.icon; + this.el.nativeElement.appendChild(iconElement); + } + + let labelElement = document.createElement("span"); + labelElement.className = 'ui-button-text ui-c'; + labelElement.appendChild(document.createTextNode(this.label||'ui-btn')); + this.el.nativeElement.appendChild(labelElement); + this.initialized = true; + } + + getStyleClass(): string { + let styleClass = 'ui-button ui-widget ui-state-default ' + this.cornerStyleClass; + if(this.icon) { + if(this.label != null && this.label != undefined) { + if(this.iconPos == 'left') + styleClass = styleClass + ' ui-button-text-icon-left'; + else + styleClass = styleClass + ' ui-button-text-icon-right'; + } + else { + styleClass = styleClass + ' ui-button-icon-only'; + } + } + else { + styleClass = styleClass + ' ui-button-text-only'; + } + + return styleClass; + } + + @Input() get label(): string { + return this._label; + } + + set label(val: string) { + this._label = val; + + if(this.initialized) { + this.domHandler.findSingle(this.el.nativeElement, '.ui-button-text').textContent = this._label; + } + } + + @Input() get icon(): string { + return this._icon; + } + + set icon(val: string) { + this._icon = val; + + if(this.initialized) { + let iconPosClass = (this.iconPos == 'right') ? 'ui-button-icon-right': 'ui-button-icon-left'; + this.domHandler.findSingle(this.el.nativeElement, '.fa').className = iconPosClass + ' ui-c fa fa-fw ' + this.icon; + } + } + + ngOnDestroy() { + while(this.el.nativeElement.hasChildNodes()) { + this.el.nativeElement.removeChild(this.el.nativeElement.lastChild); + } + + this.initialized = false; + } +} + +@NgModule({ + imports: [CommonModule], + exports: [Button], + declarations: [Button] +}) +export class ButtonModule { } diff --git a/src/app/components/calendar/calendar.css b/src/app/components/calendar/calendar.css new file mode 100644 index 00000000000..faaf79efe0c --- /dev/null +++ b/src/app/components/calendar/calendar.css @@ -0,0 +1,217 @@ +.ui-calendar { + position: relative; + display: inline-block; +} + +.ui-calendar button { + position: absolute; + height: 100%; + border-top-left-radius: 0px; + border-bottom-left-radius: 0px; + position: absolute; + width: 2em; + border-left: 0 none; +} + +.ui-calendar button:enabled:hover, +.ui-calendar button:focus { + border-left: 0 none; +} + +/* Fluid */ +.ui-fluid .ui-calendar { + width: 100%; +} + +.ui-fluid .ui-calendar button { + width: 2em; +} + +.ui-fluid .ui-calendar.ui-calendar-w-btn .ui-inputtext { + width: calc(100% - 2em); +} + +/* Datepicker */ +.ui-datepicker { + width: 17em; + padding: .2em; + display: none; + position: absolute; +} +.ui-datepicker.ui-datepicker-inline { + display: block; + position: static; +} +.ui-datepicker .ui-datepicker-header { + position: relative; + padding: .2em 0; +} +.ui-datepicker .ui-datepicker-prev, +.ui-datepicker .ui-datepicker-next { + position: absolute; + top: .125em; + width: 1.8em; + height: 1.8em; +} + +.ui-datepicker .ui-datepicker-prev { + left: .125em; +} +.ui-datepicker .ui-datepicker-next { + right: .125em; +} +.ui-datepicker .ui-datepicker-prev span, +.ui-datepicker .ui-datepicker-next span { + display: block; + position: absolute; + left: 50%; + top: 50%; + margin-top: -.5em; +} +.ui-datepicker .ui-datepicker-prev span { + margin-left: -.25em; +} +.ui-datepicker .ui-datepicker-next span { + margin-left: -.125em; +} +.ui-datepicker .ui-datepicker-title { + margin: 0 2.3em; + line-height: 1.8em; + text-align: center; +} +.ui-datepicker .ui-datepicker-title select { + font-size: 1em; + margin: .125em 0; +} +.ui-datepicker select.ui-datepicker-month { + width: 55%; +} +.ui-datepicker select.ui-datepicker-year { + width: 35%; +} +.ui-datepicker select.ui-datepicker-month { + margin-right: .25em; +} +.ui-datepicker table { + width: 100%; + font-size: .9em; + border-collapse: collapse; + margin: 0 0 .4em; +} +.ui-datepicker th { + padding: .7em .3em; + text-align: center; + font-weight: bold; + border: 0; +} +.ui-datepicker td { + border: 0; + padding: .125em; +} +.ui-datepicker td span, +.ui-datepicker td a { + display: block; + padding: .2em; + text-align: right; + text-decoration: none; +} +.ui-datepicker .ui-datepicker-buttonpane { + background-image: none; + margin: .7em 0 0 0; + padding: 0 .2em; + border-left: 0; + border-right: 0; + border-bottom: 0; +} +.ui-datepicker .ui-datepicker-buttonpane button { + float: right; + margin: .5em .2em .4em; + cursor: pointer; + padding: .2em .6em .3em .6em; + width: auto; + overflow: visible; +} +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { + float: left; +} + +/* with multiple calendars */ +.ui-datepicker.ui-datepicker-multi { + width: auto; +} +.ui-datepicker-multi .ui-datepicker-group { + float: left; +} +.ui-datepicker-multi .ui-datepicker-group table { + width: 95%; + margin: 0 auto .4em; +} +.ui-datepicker-multi-2 .ui-datepicker-group { + width: 50%; +} +.ui-datepicker-multi-3 .ui-datepicker-group { + width: 33.3%; +} +.ui-datepicker-multi-4 .ui-datepicker-group { + width: 25%; +} +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header, +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { + border-left-width: 0; +} +.ui-datepicker-multi .ui-datepicker-buttonpane { + clear: left; +} +.ui-datepicker-row-break { + clear: both; + width: 100%; + font-size: 0; +} + +.ui-calendar.ui-calendar-w-btn input { + -moz-border-radius-topright: 0px; + -webkit-border-top-right-radius: 0px; + -khtml-border-top-right-radius: 0px; + border-top-right-radius: 0px; + -moz-border-radius-bottomright: 0px; + -webkit-border-bottom-right-radius: 0px; + -khtml-border-bottom-right-radius: 0px; + border-bottom-right-radius: 0px; +} + +.ui-timepicker { + text-align: center; + padding: .5em 0; +} + +.ui-timepicker > div { + display: inline-block; + margin-left: .5em; + min-width: 1.5em; +} + +.ui-timepicker > .ui-minute-picker, +.ui-timepicker > .ui-second-picker { + margin-left: 0; +} + +.ui-timepicker > .ui-separator { + margin-left: 0px; + min-width: .75em; +} + +.ui-timepicker > .ui-separator a { + visibility: hidden; +} + +.ui-timepicker > div a { + display: block; + opacity: 0.7; + filter:Alpha(Opacity=70); +} + +.ui-timepicker > div a:hover { + display: block; + opacity: 1; + filter:Alpha(Opacity=100); +} \ No newline at end of file diff --git a/src/app/components/calendar/calendar.ts b/src/app/components/calendar/calendar.ts new file mode 100644 index 00000000000..54702d909fe --- /dev/null +++ b/src/app/components/calendar/calendar.ts @@ -0,0 +1,1287 @@ +import {NgModule,Component,ElementRef,AfterViewInit,AfterViewChecked,OnDestroy,OnInit,Input,Output,SimpleChange,EventEmitter,forwardRef,Renderer2,ViewChild,ChangeDetectorRef} from '@angular/core'; +import {trigger,state,style,transition,animate} from '@angular/animations'; +import {CommonModule} from '@angular/common'; +import {ButtonModule} from '../button/button'; +import {DomHandler} from '../dom/domhandler'; +import {AbstractControl, NG_VALUE_ACCESSOR, NG_VALIDATORS, ControlValueAccessor} from '@angular/forms'; + +export const CALENDAR_VALUE_ACCESSOR: any = { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => Calendar), + multi: true +}; + +export const CALENDAR_VALIDATOR: any = { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => Calendar), + multi: true +}; + +export interface LocaleSettings { + firstDayOfWeek?: number; + dayNames: string[]; + dayNamesShort: string[]; + dayNamesMin: string[]; + monthNames: string[]; + monthNamesShort: string[]; +} + +@Component({ + selector: 'p-calendar', + template: ` + + + + +
+ +
+ + + + + + + +
+ {{locale.monthNames[currentMonth]}} + + + {{currentYear}} +
+
+ + + + + + + + + + + +
+ {{weekDay}} +
+ {{date.day}} +
+
+
+ + + + 0{{currentHour}} + + + +
+
+ + + + : + + + +
+
+ + + + 0{{currentMinute}} + + + +
+
+ + + + : + + + +
+
+ + + + 0{{currentSecond}} + + + +
+
+ + + + {{pm ? 'PM' : 'AM'}} + + + +
+
+ +
+
+ `, + animations: [ + trigger('overlayState', [ + state('hidden', style({ + opacity: 0 + })), + state('visible', style({ + opacity: 1 + })), + transition('visible => hidden', animate('400ms ease-in')), + transition('hidden => visible', animate('400ms ease-out')) + ]) + ], + host: { + '[class.ui-inputwrapper-filled]': 'filled', + '[class.ui-inputwrapper-focus]': 'focus' + }, + providers: [DomHandler,CALENDAR_VALUE_ACCESSOR,CALENDAR_VALIDATOR] +}) +export class Calendar implements AfterViewInit,AfterViewChecked,OnInit,OnDestroy,ControlValueAccessor { + + @Input() defaultDate: Date; + + @Input() style: string; + + @Input() styleClass: string; + + @Input() inputStyle: string; + + @Input() inputId: string; + + @Input() inputStyleClass: string; + + @Input() placeholder: string; + + @Input() disabled: any; + + @Input() dateFormat: string = 'mm/dd/yy'; + + @Input() inline: boolean = false; + + @Input() showOtherMonths: boolean = true; + + @Input() selectOtherMonths: boolean; + + @Input() showIcon: boolean; + + @Input() icon: string = 'fa-calendar'; + + @Input() appendTo: any; + + @Input() readonlyInput: boolean; + + @Input() shortYearCutoff: any = '+10'; + + @Input() monthNavigator: boolean; + + @Input() yearNavigator: boolean; + + @Input() yearRange: string; + + @Input() showTime: boolean; + + @Input() hourFormat: string = '24'; + + @Input() timeOnly: boolean; + + @Input() stepHour: number = 1; + + @Input() stepMinute: number = 1; + + @Input() stepSecond: number = 1; + + @Input() showSeconds: boolean = false; + + @Input() required: boolean; + + @Input() showOnFocus: boolean = true; + + @Input() dataType: string = 'date'; + + @Input() disabledDates: Array; + + @Input() disabledDays: Array; + + @Input() utc: boolean; + + @Output() onFocus: EventEmitter = new EventEmitter(); + + @Output() onBlur: EventEmitter = new EventEmitter(); + + @Output() onSelect: EventEmitter = new EventEmitter(); + + @Output() onInput: EventEmitter = new EventEmitter(); + + _locale: LocaleSettings = { + firstDayOfWeek: 0, + dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], + dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], + dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], + monthNames: [ "January","February","March","April","May","June","July","August","September","October","November","December" ], + monthNamesShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun","Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ] + }; + + @Input() tabindex: number; + + @ViewChild('datepicker') overlayViewChild: ElementRef; + + @ViewChild('inputfield') inputfieldViewChild: ElementRef; + + value: Date; + + dates: any[]; + + weekDays: string[]; + + currentMonthText: string; + + currentMonth: number; + + currentYear: number; + + currentHour: number; + + currentMinute: number; + + currentSecond: number; + + pm: boolean; + + overlay: HTMLDivElement; + + overlayVisible: boolean; + + overlayShown: boolean; + + closeOverlay: boolean = true; + + dateClick: boolean; + + onModelChange: Function = () => {}; + + onModelTouched: Function = () => {}; + + calendarElement: any; + + documentClickListener: any; + + ticksTo1970: number; + + yearOptions: number[]; + + focus: boolean; + + filled: boolean; + + inputFieldValue: string = null; + + _minDate: Date; + + _maxDate: Date; + + _isValid: boolean = true; + + @Input() get minDate(): Date { + return this._minDate; + } + + set minDate(date: Date) { + this._minDate = date; + this.createMonth(this.currentMonth, this.currentYear); + } + + @Input() get maxDate(): Date { + return this._maxDate; + } + + set maxDate(date: Date) { + this._maxDate = date; + this.createMonth(this.currentMonth, this.currentYear); + } + + get locale() { + return this._locale; + } + + @Input() + set locale(newLocale: LocaleSettings) { + this._locale = newLocale; + this.createWeekDays(); + this.createMonth(this.currentMonth, this.currentYear); + } + + constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2, public cd: ChangeDetectorRef) {} + + ngOnInit() { + let date = this.defaultDate||new Date(); + this.createWeekDays(); + + this.currentMonth = date.getMonth(); + this.currentYear = date.getFullYear(); + this.pm = date.getHours() > 11; + if(this.showTime) { + this.currentMinute = date.getMinutes(); + this.currentSecond = date.getSeconds(); + + if(this.hourFormat == '12') + this.currentHour = date.getHours() == 0 ? 12 : date.getHours() % 12; + else + this.currentHour = date.getHours(); + } + else if(this.timeOnly) { + this.currentMinute = 0; + this.currentHour = 0; + this.currentSecond = 0; + } + + this.createMonth(this.currentMonth, this.currentYear); + + this.ticksTo1970 = (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) + + Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000); + + if(this.yearNavigator && this.yearRange) { + this.yearOptions = []; + let years = this.yearRange.split(':'), + yearStart = parseInt(years[0]), + yearEnd = parseInt(years[1]); + + for(let i = yearStart; i <= yearEnd; i++) { + this.yearOptions.push(i); + } + } + } + + ngAfterViewInit() { + this.overlay = this.overlayViewChild.nativeElement; + + if(!this.inline && this.appendTo) { + if(this.appendTo === 'body') + document.body.appendChild(this.overlay); + else + this.domHandler.appendChild(this.overlay, this.appendTo); + } + } + + ngAfterViewChecked() { + if(this.overlayShown) { + this.alignOverlay(); + this.overlayShown = false; + } + } + + createWeekDays() { + this.weekDays = []; + let dayIndex = this.locale.firstDayOfWeek; + for(let i = 0; i < 7; i++) { + this.weekDays.push(this.locale.dayNamesMin[dayIndex]); + dayIndex = (dayIndex == 6) ? 0 : ++dayIndex; + } + } + + createMonth(month: number, year: number) { + this.dates = []; + this.currentMonth = month; + this.currentYear = year; + this.currentMonthText = this.locale.monthNames[month]; + let firstDay = this.getFirstDayOfMonthIndex(month, year); + let daysLength = this.getDaysCountInMonth(month, year); + let prevMonthDaysLength = this.getDaysCountInPrevMonth(month, year); + let sundayIndex = this.getSundayIndex(); + let dayNo = 1; + let today = new Date(); + + for(let i = 0; i < 6; i++) { + let week = []; + + if(i == 0) { + for(let j = (prevMonthDaysLength - firstDay + 1); j <= prevMonthDaysLength; j++) { + let prev = this.getPreviousMonthAndYear(month, year); + week.push({day: j, month: prev.month, year: prev.year, otherMonth: true, + today: this.isToday(today, j, prev.month, prev.year), selectable: this.isSelectable(j, prev.month, prev.year)}); + } + + let remainingDaysLength = 7 - week.length; + for(let j = 0; j < remainingDaysLength; j++) { + week.push({day: dayNo, month: month, year: year, today: this.isToday(today, dayNo, month, year), + selectable: this.isSelectable(dayNo, month, year)}); + dayNo++; + } + } + else { + for (let j = 0; j < 7; j++) { + if(dayNo > daysLength) { + let next = this.getNextMonthAndYear(month, year); + week.push({day: dayNo - daysLength, month: next.month, year: next.year, otherMonth:true, + today: this.isToday(today, dayNo - daysLength, next.month, next.year), + selectable: this.isSelectable((dayNo - daysLength), next.month, next.year)}); + } + else { + week.push({day: dayNo, month: month, year: year, today: this.isToday(today, dayNo, month, year), + selectable: this.isSelectable(dayNo, month, year)}); + } + + dayNo++; + } + } + + this.dates.push(week); + } + } + + prevMonth(event) { + if(this.disabled) { + event.preventDefault(); + return; + } + + if(this.currentMonth === 0) { + this.currentMonth = 11; + this.currentYear--; + } + else { + this.currentMonth--; + } + + this.createMonth(this.currentMonth, this.currentYear); + event.preventDefault(); + } + + nextMonth(event) { + if(this.disabled) { + event.preventDefault(); + return; + } + + if(this.currentMonth === 11) { + this.currentMonth = 0; + this.currentYear++; + } + else { + this.currentMonth++; + } + + this.createMonth(this.currentMonth, this.currentYear); + event.preventDefault(); + } + + onDateSelect(event,dateMeta) { + if(this.disabled || !dateMeta.selectable) { + event.preventDefault(); + return; + } + + if(dateMeta.otherMonth) { + if(this.selectOtherMonths) { + this.currentMonth = dateMeta.month; + this.currentYear = dateMeta.year; + this.createMonth(this.currentMonth, this.currentYear); + this.selectDate(dateMeta); + } + } + else { + this.selectDate(dateMeta); + } + + this.dateClick = true; + this.updateInputfield(); + event.preventDefault(); + } + + updateInputfield() { + if(this.value) { + let formattedValue; + + if(this.timeOnly) { + formattedValue = this.formatTime(this.value); + } + else { + formattedValue = this.formatDate(this.value, this.dateFormat); + if(this.showTime) { + formattedValue += ' ' + this.formatTime(this.value); + } + } + + this.inputFieldValue = formattedValue; + } + else { + this.inputFieldValue = ''; + } + + this.updateFilledState(); + } + + selectDate(dateMeta) { + if(this.utc) + this.value = new Date(Date.UTC(dateMeta.year, dateMeta.month, dateMeta.day)); + else + this.value = new Date(dateMeta.year, dateMeta.month, dateMeta.day); + + if(this.showTime) { + if(this.hourFormat === '12' && this.pm && this.currentHour != 12) + this.value.setHours(this.currentHour + 12); + else + this.value.setHours(this.currentHour); + + this.value.setMinutes(this.currentMinute); + this.value.setSeconds(this.currentSecond); + } + this._isValid = true; + this.updateModel(); + this.onSelect.emit(this.value); + } + + updateModel() { + if(this.dataType == 'date'){ + this.onModelChange(this.value); + } + else if(this.dataType == 'string') { + if(this.timeOnly) + this.onModelChange(this.formatTime(this.value)); + else + this.onModelChange(this.formatDate(this.value, this.dateFormat)); + } + } + + getFirstDayOfMonthIndex(month: number, year: number) { + let day = new Date(); + day.setDate(1); + day.setMonth(month); + day.setFullYear(year); + + let dayIndex = day.getDay() + this.getSundayIndex(); + return dayIndex >= 7 ? dayIndex - 7 : dayIndex; + } + + getDaysCountInMonth(month: number, year: number) { + return 32 - this.daylightSavingAdjust(new Date(year, month, 32)).getDate(); + } + + getDaysCountInPrevMonth(month: number, year: number) { + let prev = this.getPreviousMonthAndYear(month, year); + return this.getDaysCountInMonth(prev.month, prev.year); + } + + getPreviousMonthAndYear(month: number, year: number) { + let m, y; + + if(month === 0) { + m = 11; + y = year - 1; + } + else { + m = month - 1; + y = year; + } + + return {'month':m,'year':y}; + } + + getNextMonthAndYear(month: number, year: number) { + let m, y; + + if(month === 11) { + m = 0; + y = year + 1; + } + else { + m = month + 1; + y = year; + } + + return {'month':m,'year':y}; + } + + getSundayIndex() { + return this.locale.firstDayOfWeek > 0 ? 7 - this.locale.firstDayOfWeek : 0; + } + + isSelected(dateMeta): boolean { + if(this.value) + return this.value.getDate() === dateMeta.day && this.value.getMonth() === dateMeta.month && this.value.getFullYear() === dateMeta.year; + else + return false; + } + + isToday(today, day, month, year): boolean { + return today.getDate() === day && today.getMonth() === month && today.getFullYear() === year; + } + + isSelectable(day, month, year): boolean { + let validMin = true; + let validMax = true; + let validDate = true; + let validDay = true; + + if(this.minDate) { + if(this.minDate.getFullYear() > year) { + validMin = false; + } + else if(this.minDate.getFullYear() === year) { + if(this.minDate.getMonth() > month) { + validMin = false; + } + else if(this.minDate.getMonth() === month) { + if(this.minDate.getDate() > day) { + validMin = false; + } + } + } + } + + if(this.maxDate) { + if(this.maxDate.getFullYear() < year) { + validMax = false; + } + else if(this.maxDate.getFullYear() === year) { + if(this.maxDate.getMonth() < month) { + validMax = false; + } + else if(this.maxDate.getMonth() === month) { + if(this.maxDate.getDate() < day) { + validMax = false; + } + } + } + } + + if(this.disabledDates) { + validDate = !this.isDateDisabled(day,month,year); + } + + if(this.disabledDays) { + validDay = !this.isDayDisabled(day,month,year) + } + + return validMin && validMax && validDate && validDay; + } + + isDateDisabled(day:number, month:number, year:number):boolean { + if(this.disabledDates) { + for(let disabledDate of this.disabledDates) { + if(disabledDate.getFullYear() === year && disabledDate.getMonth() === month && disabledDate.getDate() === day) { + return true; + } + } + } + + return false; + } + + isDayDisabled(day:number, month:number, year:number):boolean { + if(this.disabledDays) { + let weekday = new Date(year, month, day); + let weekdayNumber = weekday.getDay(); + return this.disabledDays.indexOf(weekdayNumber) !== -1; + } + return false; + } + + onInputFocus(event: Event) { + this.focus = true; + if(this.showOnFocus) { + this.showOverlay(); + } + this.onFocus.emit(event); + } + + onInputBlur(event: Event) { + this.focus = false; + this.onBlur.emit(event); + this.updateInputfield(); + this.onModelTouched(); + } + + onButtonClick(event,inputfield) { + this.closeOverlay = false; + + if(!this.overlay.offsetParent) { + inputfield.focus(); + this.showOverlay(); + } + else + this.closeOverlay = true; + } + + onInputKeydown(event) { + if(event.keyCode === 9) { + this.overlayVisible = false; + } + } + + onMonthDropdownChange(m: string) { + this.currentMonth = parseInt(m); + this.createMonth(this.currentMonth, this.currentYear); + } + + onYearDropdownChange(y: string) { + this.currentYear = parseInt(y); + this.createMonth(this.currentMonth, this.currentYear); + } + + incrementHour(event) { + let newHour = this.currentHour + this.stepHour; + if(this.hourFormat == '24') + this.currentHour = (newHour >= 24) ? (newHour - 24) : newHour; + else if(this.hourFormat == '12') + this.currentHour = (newHour >= 13) ? (newHour - 12) : newHour; + + this.updateTime(); + + event.preventDefault(); + } + + decrementHour(event) { + let newHour = this.currentHour - this.stepHour; + if(this.hourFormat == '24') + this.currentHour = (newHour < 0) ? (24 + newHour) : newHour; + else if(this.hourFormat == '12') + this.currentHour = (newHour <= 0) ? (12 + newHour) : newHour; + + this.updateTime(); + + event.preventDefault(); + } + + incrementMinute(event) { + let newMinute = this.currentMinute + this.stepMinute; + this.currentMinute = (newMinute > 59) ? newMinute - 60 : newMinute; + + this.updateTime(); + + event.preventDefault(); + } + + decrementMinute(event) { + let newMinute = this.currentMinute - this.stepMinute; + this.currentMinute = (newMinute < 0) ? 60 + newMinute : newMinute; + + this.updateTime(); + + event.preventDefault(); + } + + incrementSecond(event) { + let newSecond = this.currentSecond + this.stepSecond; + this.currentSecond = (newSecond > 59) ? newSecond - 60 : newSecond; + + this.updateTime(); + + event.preventDefault(); + } + + decrementSecond(event) { + let newSecond = this.currentSecond - this.stepSecond; + this.currentSecond = (newSecond < 0) ? 60 + newSecond : newSecond; + + this.updateTime(); + + event.preventDefault(); + } + + updateTime() { + this.value = this.value||new Date(); + if(this.hourFormat === '12' && this.pm && this.currentHour != 12) + this.value.setHours(this.currentHour + 12); + else + this.value.setHours(this.currentHour); + + this.value.setMinutes(this.currentMinute); + this.value.setSeconds(this.currentSecond); + this.updateModel(); + this.onSelect.emit(this.value); + this.updateInputfield(); + } + + toggleAMPM(event) { + this.pm = !this.pm; + this.updateTime(); + event.preventDefault(); + } + + onUserInput(event) { + let val = event.target.value; + try { + this.value = this.parseValueFromString(val); + this.updateUI(); + this._isValid = true; + } + catch(err) { + //invalid date + this.value = null; + this._isValid = false; + } + + this.filled = val != null && val.length; + this.updateModel(); + this.onInput.emit(event); + } + + parseValueFromString(text: string): Date { + let dateValue; + let parts: string[] = text.split(' '); + + if(this.timeOnly) { + dateValue = new Date(); + this.populateTime(dateValue, parts[0], parts[1]); + } + else { + if(this.showTime) { + dateValue = this.parseDate(parts[0], this.dateFormat); + this.populateTime(dateValue, parts[1], parts[2]); + } + else { + dateValue = this.parseDate(text, this.dateFormat); + } + } + + return dateValue; + } + + populateTime(value, timeString, ampm) { + if(this.hourFormat == '12' && !ampm) { + throw 'Invalid Time'; + } + + this.pm = (ampm === 'PM' || ampm === 'pm'); + let time = this.parseTime(timeString); + value.setHours(time.hour); + value.setMinutes(time.minute); + value.setSeconds(time.second); + } + + updateUI() { + let val = this.value||this.defaultDate||new Date(); + this.createMonth(val.getMonth(), val.getFullYear()); + + if(this.showTime||this.timeOnly) { + let hours = val.getHours(); + + if(this.hourFormat == '12') { + if(hours >= 12) { + this.currentHour = (hours == 12) ? 12 : hours - 12; + } + else { + this.currentHour = (hours == 0) ? 12 : hours; + } + } + else { + this.currentHour = val.getHours(); + } + + this.currentMinute = val.getMinutes(); + this.currentSecond = val.getSeconds(); + } + } + + onDatePickerClick(event) { + this.closeOverlay = this.dateClick; + } + + showOverlay() { + this.overlayVisible = true; + this.overlayShown = true; + this.overlay.style.zIndex = String(++DomHandler.zindex); + + this.bindDocumentClickListener(); + } + + alignOverlay() { + if(this.appendTo) + this.domHandler.absolutePosition(this.overlay, this.inputfieldViewChild.nativeElement); + else + this.domHandler.relativePosition(this.overlay, this.inputfieldViewChild.nativeElement); + } + + writeValue(value: any) : void { + this.value = value; + if(this.value && typeof this.value === 'string') { + this.value = this.parseValueFromString(this.value); + } + + this.updateInputfield(); + this.updateUI(); + } + + registerOnChange(fn: Function): void { + this.onModelChange = fn; + } + + registerOnTouched(fn: Function): void { + this.onModelTouched = fn; + } + + setDisabledState(val: boolean): void { + this.disabled = val; + } + + // Ported from jquery-ui datepicker formatDate + formatDate(date, format) { + if(!date) { + return ""; + } + + let iFormat, + lookAhead = (match) => { + let matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); + if(matches) { + iFormat++; + } + return matches; + }, + formatNumber = (match, value, len) => { + let num = "" + value; + if(lookAhead(match)) { + while (num.length < len) { + num = "0" + num; + } + } + return num; + }, + formatName = (match, value, shortNames, longNames) => { + return (lookAhead(match) ? longNames[ value ] : shortNames[ value ]); + }, + output = "", + literal = false; + + if(date) { + for(iFormat = 0; iFormat < format.length; iFormat++) { + if(literal) { + if(format.charAt(iFormat) === "'" && !lookAhead("'")) + literal = false; + else + output += format.charAt(iFormat); + } + else { + switch (format.charAt(iFormat)) { + case "d": + output += formatNumber("d", date.getDate(), 2); + break; + case "D": + output += formatName("D", date.getDay(), this.locale.dayNamesShort, this.locale.dayNames); + break; + case "o": + output += formatNumber("o", + Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3); + break; + case "m": + output += formatNumber("m", date.getMonth() + 1, 2); + break; + case "M": + output += formatName("M", date.getMonth(), this.locale.monthNamesShort, this.locale.monthNames); + break; + case "y": + output += (lookAhead("y") ? date.getFullYear() : + (date.getFullYear() % 100 < 10 ? "0" : "") + date.getFullYear() % 100); + break; + case "@": + output += date.getTime(); + break; + case "!": + output += date.getTime() * 10000 + this.ticksTo1970; + break; + case "'": + if(lookAhead("'")) + output += "'"; + else + literal = true; + + break; + default: + output += format.charAt(iFormat); + } + } + } + } + return output; + } + + formatTime(date) { + if(!date) { + return ''; + } + + let output = ''; + let hours = date.getHours(); + let minutes = date.getMinutes(); + let seconds = date.getSeconds(); + + if(this.hourFormat == '12' && hours > 11 && hours != 12) { + hours-=12; + } + + output += (hours < 10) ? '0' + hours : hours; + output += ':'; + output += (minutes < 10) ? '0' + minutes : minutes; + + if(this.showSeconds) { + output += ':'; + output += (seconds < 10) ? '0' + seconds : seconds; + } + + if(this.hourFormat == '12') { + output += date.getHours() > 11 ? ' PM' : ' AM'; + } + + return output; + } + + parseTime(value) { + let tokens: string[] = value.split(':'); + let validTokenLength = this.showSeconds ? 3 : 2; + + if(tokens.length !== validTokenLength) { + throw "Invalid time"; + } + + let h = parseInt(tokens[0]); + let m = parseInt(tokens[1]); + let s = this.showSeconds ? parseInt(tokens[2]) : null; + + if(isNaN(h) || isNaN(m) || h > 23 || m > 59 || (this.hourFormat == '12' && h > 12) || (this.showSeconds && (isNaN(s) || s > 59))) { + throw "Invalid time"; + } + else { + if(this.hourFormat == '12' && h !== 12 && this.pm) { + h+= 12; + } + + return {hour: h, minute: m, second: s}; + } + } + + // Ported from jquery-ui datepicker parseDate + parseDate(value, format) { + if(format == null || value == null) { + throw "Invalid arguments"; + } + + value = (typeof value === "object" ? value.toString() : value + ""); + if(value === "") { + return null; + } + + let iFormat, dim, extra, + iValue = 0, + shortYearCutoff = (typeof this.shortYearCutoff !== "string" ? this.shortYearCutoff : new Date().getFullYear() % 100 + parseInt(this.shortYearCutoff, 10)), + year = -1, + month = -1, + day = -1, + doy = -1, + literal = false, + date, + lookAhead = (match) => { + let matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); + if(matches) { + iFormat++; + } + return matches; + }, + getNumber = (match) => { + let isDoubled = lookAhead(match), + size = (match === "@" ? 14 : (match === "!" ? 20 : + (match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))), + minSize = (match === "y" ? size : 1), + digits = new RegExp("^\\d{" + minSize + "," + size + "}"), + num = value.substring(iValue).match(digits); + if(!num) { + throw "Missing number at position " + iValue; + } + iValue += num[ 0 ].length; + return parseInt(num[ 0 ], 10); + }, + getName = (match, shortNames, longNames) => { + let index = -1; + let arr = lookAhead(match) ? longNames : shortNames; + let names = []; + + for(let i = 0; i < arr.length; i++) { + names.push([i,arr[i]]); + } + names.sort((a,b) => { + return -(a[ 1 ].length - b[ 1 ].length); + }); + + for(let i = 0; i < names.length; i++) { + let name = names[i][1]; + if(value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) { + index = names[i][0]; + iValue += name.length; + break; + } + } + + if(index !== -1) { + return index + 1; + } else { + throw "Unknown name at position " + iValue; + } + }, + checkLiteral = () => { + if(value.charAt(iValue) !== format.charAt(iFormat)) { + throw "Unexpected literal at position " + iValue; + } + iValue++; + }; + + for (iFormat = 0; iFormat < format.length; iFormat++) { + if(literal) { + if(format.charAt(iFormat) === "'" && !lookAhead("'")) { + literal = false; + } else { + checkLiteral(); + } + } else { + switch (format.charAt(iFormat)) { + case "d": + day = getNumber("d"); + break; + case "D": + getName("D", this.locale.dayNamesShort, this.locale.dayNames); + break; + case "o": + doy = getNumber("o"); + break; + case "m": + month = getNumber("m"); + break; + case "M": + month = getName("M", this.locale.monthNamesShort, this.locale.monthNames); + break; + case "y": + year = getNumber("y"); + break; + case "@": + date = new Date(getNumber("@")); + year = date.getFullYear(); + month = date.getMonth() + 1; + day = date.getDate(); + break; + case "!": + date = new Date((getNumber("!") - this.ticksTo1970) / 10000); + year = date.getFullYear(); + month = date.getMonth() + 1; + day = date.getDate(); + break; + case "'": + if(lookAhead("'")) { + checkLiteral(); + } else { + literal = true; + } + break; + default: + checkLiteral(); + } + } + } + + if(iValue < value.length) { + extra = value.substr(iValue); + if(!/^\s+/.test(extra)) { + throw "Extra/unparsed characters found in date: " + extra; + } + } + + if(year === -1) { + year = new Date().getFullYear(); + } else if(year < 100) { + year += new Date().getFullYear() - new Date().getFullYear() % 100 + + (year <= shortYearCutoff ? 0 : -100); + } + + if(doy > -1) { + month = 1; + day = doy; + do { + dim = this.getDaysCountInMonth(year, month - 1); + if(day <= dim) { + break; + } + month++; + day -= dim; + } while (true); + } + + date = this.daylightSavingAdjust(new Date(year, month - 1, day)); + if(date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) { + throw "Invalid date"; // E.g. 31/02/00 + } + return date; + } + + daylightSavingAdjust(date) { + if(!date) { + return null; + } + date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0); + return date; + } + + updateFilledState() { + this.filled = this.inputFieldValue && this.inputFieldValue != ''; + } + + bindDocumentClickListener() { + if(!this.documentClickListener) { + this.documentClickListener = this.renderer.listen('document', 'click', () => { + if(this.closeOverlay) { + this.overlayVisible = false; + } + + this.closeOverlay = true; + this.dateClick = false; + this.cd.detectChanges(); + }); + } + } + + unbindDocumentClickListener() { + if(this.documentClickListener) { + this.documentClickListener(); + this.documentClickListener = null; + } + } + + ngOnDestroy() { + this.unbindDocumentClickListener(); + + if(!this.inline && this.appendTo) { + this.el.nativeElement.appendChild(this.overlay); + } + } + + validate(c: AbstractControl) { + if (!this._isValid) { + return { invalidDate: true }; + } + + return null; + } +} + +@NgModule({ + imports: [CommonModule,ButtonModule], + exports: [Calendar,ButtonModule], + declarations: [Calendar] +}) +export class CalendarModule { } diff --git a/src/app/components/captcha/captcha.ts b/src/app/components/captcha/captcha.ts new file mode 100644 index 00000000000..54cb4c9de75 --- /dev/null +++ b/src/app/components/captcha/captcha.ts @@ -0,0 +1,93 @@ +import {NgModule,AfterViewInit,Component,EventEmitter,Input,NgZone,OnDestroy,Output,ViewChild, ElementRef} from '@angular/core'; +import {CommonModule} from '@angular/common'; + +@Component({ + selector: 'p-captcha', + template: `
` +}) +export class Captcha implements AfterViewInit { + + @Input() siteKey: string = null; + + @Input() theme = 'light'; + + @Input() type = 'image'; + + @Input() size = 'normal'; + + @Input() tabindex = 0; + + @Input() language: string = null; + + @Input() initCallback = "initRecaptcha"; + + @Output() onResponse: EventEmitter = new EventEmitter(); + + @Output() onExpire: EventEmitter = new EventEmitter(); + + @ViewChild('target') el: ElementRef; + + private _instance: any = null; + + constructor(public _zone:NgZone) {} + + ngAfterViewInit() { + if ((window).grecaptcha) + this.init(); + else { + (window)[this.initCallback] = () => { + this.init(); + } + } + } + + init() { + this._instance = (window).grecaptcha.render(this.el.nativeElement, { + 'sitekey': this.siteKey, + 'theme': this.theme, + 'type': this.type, + 'size': this.size, + 'tabindex': this.tabindex, + 'hl': this.language, + 'callback': (response: string) => {this._zone.run(() => this.recaptchaCallback(response))}, + 'expired-callback': () => {this._zone.run(() => this.recaptchaExpiredCallback())} + }); + } + + reset() { + if(this._instance === null) + return; + + (window).grecaptcha.reset(this._instance); + } + + getResponse(): String { + if (this._instance === null) + return null; + + return (window).grecaptcha.getResponse(this._instance); + } + + recaptchaCallback(response: string) { + this.onResponse.emit({ + response: response + }); + } + + recaptchaExpiredCallback() { + this.onExpire.emit(); + } + + ngOnDestroy() { + if (this._instance != null) { + (window).grecaptcha.reset(this._instance); + } + } +} + +@NgModule({ + imports: [CommonModule], + exports: [Captcha], + declarations: [Captcha] +}) +export class CaptchaModule { } diff --git a/src/app/components/carousel/carousel.css b/src/app/components/carousel/carousel.css new file mode 100644 index 00000000000..a10453d839d --- /dev/null +++ b/src/app/components/carousel/carousel.css @@ -0,0 +1,85 @@ +.ui-carousel { + position: relative; + padding: .063em; +} + +.ui-carousel .ui-carousel-viewport .ui-carousel-items { + list-style: none outside none; + margin: 0; + padding:0; + position: relative; + width: 32000px; + left: 0; +} + +.ui-carousel .ui-carousel-viewport .ui-carousel-items .ui-carousel-item { + margin: 1px; + padding: 0; + float: left; + box-sizing: border-box; +} + +.ui-carousel .ui-carousel-viewport { + overflow: hidden; + position: relative; + border: 0; +} + +.ui-carousel .ui-carousel-footer { + margin: 1px 1px 0px 1px; + padding: .5em; + overflow: hidden; +} + +.ui-carousel .ui-carousel-header { + margin: 0 1px; + overflow: hidden; + padding: .625em; +} + +.ui-carousel .ui-carousel-header .ui-carousel-header-title { + display: inline-block; + overflow: hidden; +} + +.ui-carousel .ui-carousel-dropdown, +.ui-carousel .ui-carousel-mobiledropdown { + float: right; + margin: 0px .625em; + background-image: none; +} + +.ui-carousel .ui-carousel-dropdown option, +.ui-carousel .ui-carousel-mobiledropdown option{ + background-image: none; + border: 0 none; + box-shadow: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; +} + +.ui-carousel .ui-carousel-button { + float: right; + margin: .125em; +} + +.ui-carousel .ui-carousel-page-link { + float: left; + margin: 0 .125em; + text-decoration: none; +} + +.ui-carousel .ui-carousel-page-link, +.ui-carousel .ui-carousel-button { + cursor: pointer; +} + +.ui-carousel .ui-carousel-page-links { + margin: 0px .5em; + margin-top: .125em; + float: right; +} + +.ui-carousel .ui-carousel-mobiledropdown { + display: none; +} \ No newline at end of file diff --git a/src/app/components/carousel/carousel.ts b/src/app/components/carousel/carousel.ts new file mode 100644 index 00000000000..63fe8af3a37 --- /dev/null +++ b/src/app/components/carousel/carousel.ts @@ -0,0 +1,330 @@ +import {NgModule,Component,ElementRef,AfterViewInit,AfterViewChecked,AfterContentInit,EventEmitter,OnDestroy,Input,Output,TemplateRef,ContentChildren,QueryList,Renderer2,ViewChild} from '@angular/core'; +import {DomHandler} from '../dom/domhandler'; +import {SharedModule,PrimeTemplate} from '../common/shared'; +import {CommonModule} from '@angular/common'; + +@Component({ + selector: 'p-carousel', + template: ` +
+ + +
+ `, + providers: [DomHandler] +}) +export class Carousel implements AfterViewChecked,AfterViewInit,OnDestroy{ + + @Input() numVisible: number = 3; + + @Input() firstVisible: number = 0; + + @Input() headerText: string; + + @Input() circular: boolean = false; + + @Input() breakpoint: number = 560; + + @Input() responsive: boolean = true; + + @Input() autoplayInterval: number = 0; + + @Input() effectDuration: any = '1s'; + + @Input() easing: string = 'ease-out'; + + @Input() pageLinks: number = 3; + + @Input() style: any; + + @Input() styleClass: string; + + @Output() onPage: EventEmitter = new EventEmitter(); + + @ViewChild('container') containerViewChild: ElementRef; + + @ContentChildren(PrimeTemplate) templates: QueryList; + + public _value: any[]; + + public itemTemplate: TemplateRef; + + public container: any; + + public left: any = 0; + + public viewport: any; + + public itemsContainer: any; + + public items: any; + + public columns: any; + + public page: number; + + public valuesChanged: any; + + public interval: any; + + public anchorPageLinks: any[]; + + public mobileDropdownOptions: any[]; + + public selectDropdownOptions: any[]; + + public shrinked: boolean; + + documentResponsiveListener: any; + + differ: any; + + constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2) {} + + ngAfterContentInit() { + this.templates.forEach((item) => { + switch(item.getType()) { + case 'item': + this.itemTemplate = item.template; + break; + + default: + this.itemTemplate = item.template; + break; + } + }); + } + + @Input() get value(): any[] { + return this._value; + } + + set value(val:any[]) { + this._value = val; + this.handleDataChange(); + } + + handleDataChange() { + if(this.value && this.value.length) { + if(this.value.length && this.firstVisible >= this.value.length) { + this.setPage(this.totalPages - 1); + } + } + else { + this.setPage(0); + } + + this.valuesChanged = true; + } + + ngAfterViewChecked() { + if(this.valuesChanged && this.containerViewChild.nativeElement.offsetParent) { + this.render(); + this.valuesChanged = false; + } + } + + ngAfterViewInit() { + this.container = this.el.nativeElement.children[0]; + this.viewport = this.domHandler.findSingle(this.el.nativeElement, 'div.ui-carousel-viewport'); + this.itemsContainer = this.domHandler.findSingle(this.el.nativeElement, 'ul.ui-carousel-items'); + + if(this.responsive) { + this.documentResponsiveListener = this.renderer.listen('window', 'resize', (event) => { + this.updateState(); + }); + } + } + + updateLinks() { + this.anchorPageLinks = []; + for (let i = 0; i < this.totalPages; i++) { + this.anchorPageLinks.push(i); + } + } + + updateDropdown() { + this.selectDropdownOptions = []; + for (let i = 0; i < this.totalPages; i++) { + this.selectDropdownOptions.push(i); + } + } + + updateMobileDropdown() { + this.mobileDropdownOptions = []; + for (let i = 0; i < this.value.length; i++) { + this.mobileDropdownOptions.push(i); + } + } + + render() { + if(this.autoplayInterval) { + this.stopAutoplay(); + } + + this.items = this.domHandler.find(this.itemsContainer,'li'); + this.calculateColumns(); + this.calculateItemWidths(); + + if(!this.responsive) { + this.container.style.width = (this.domHandler.width(this.container)) + 'px'; + } + + if(this.autoplayInterval) { + this.circular = true; + this.startAutoplay(); + } + + this.updateMobileDropdown(); + this.updateLinks(); + this.updateDropdown(); + } + + calculateItemWidths () { + let firstItem = (this.items && this.items.length) ? this.items[0] : null; + if(firstItem) { + for (let i = 0; i < this.items.length; i++) { + this.items[i].style.width = ((this.domHandler.innerWidth(this.viewport) - (this.domHandler.getHorizontalMargin(firstItem) * this.columns)) / this.columns) + 'px'; + } + } + } + + calculateColumns() { + if(window.innerWidth <= this.breakpoint) { + this.shrinked = true; + this.columns = 1; + } + else { + this.shrinked = false; + this.columns = this.numVisible; + } + this.page = Math.floor(this.firstVisible / this.columns); + } + + onNextNav() { + let lastPage = (this.page === (this.totalPages - 1)); + + if(!lastPage) + this.setPage(this.page + 1); + else if(this.circular) + this.setPage(0); + } + + onPrevNav() { + if(this.page !== 0) + this.setPage(this.page - 1); + else if(this.circular) + this.setPage(this.totalPages - 1); + } + + setPageWithLink(event, p: number) { + this.setPage(p); + event.preventDefault(); + } + + setPage(p, enforce?: boolean) { + if(p !== this.page || enforce) { + this.page = p; + this.left = (-1 * (this.domHandler.innerWidth(this.viewport) * this.page)); + this.firstVisible = this.page * this.columns; + this.onPage.emit({ + page: this.page + }); + } + } + + onDropdownChange(val: string) { + this.setPage(parseInt(val)); + } + + get displayPageLinks(): boolean { + return (this.totalPages <= this.pageLinks && !this.shrinked); + } + + get displayPageDropdown(): boolean { + return (this.totalPages > this.pageLinks && !this.shrinked); + } + + get totalPages(): number { + return (this.value && this.value.length) ? Math.ceil(this.value.length / this.columns) : 0; + } + + routerDisplay () { + let win = window; + if(win.innerWidth <= this.breakpoint) + return true; + else + return false; + } + + updateState() { + let win = window; + if(win.innerWidth <= this.breakpoint) { + this.shrinked = true; + this.columns = 1; + } + else if(this.shrinked) { + this.shrinked = false; + this.columns = this.numVisible; + this.updateLinks(); + this.updateDropdown(); + } + + this.calculateItemWidths(); + this.setPage(Math.floor(this.firstVisible / this.columns), true); + } + + startAutoplay() { + this.interval = setInterval(() => { + if(this.page === (this.totalPages - 1)) + this.setPage(0); + else + this.setPage(this.page + 1); + }, + this.autoplayInterval); + } + + stopAutoplay() { + clearInterval(this.interval); + } + + ngOnDestroy() { + if(this.documentResponsiveListener) { + this.documentResponsiveListener(); + } + + if(this.autoplayInterval) { + this.stopAutoplay(); + } + } +} + +@NgModule({ + imports: [CommonModule,SharedModule], + exports: [Carousel,SharedModule], + declarations: [Carousel] +}) +export class CarouselModule { } \ No newline at end of file diff --git a/src/app/components/chart/chart.ts b/src/app/components/chart/chart.ts new file mode 100644 index 00000000000..e1c027e3754 --- /dev/null +++ b/src/app/components/chart/chart.ts @@ -0,0 +1,107 @@ +import {NgModule,Component,ElementRef,AfterViewInit,OnDestroy,Input,Output,EventEmitter} from '@angular/core'; +import {CommonModule} from '@angular/common'; + +declare var Chart: any; + +@Component({ + selector: 'p-chart', + template: ` +
+ +
+ ` +}) +export class UIChart implements AfterViewInit, OnDestroy { + + @Input() type: string; + + @Input() options: any; + + @Input() width: string; + + @Input() height: string; + + @Output() onDataSelect: EventEmitter = new EventEmitter(); + + initialized: boolean; + + _data: any; + + chart: any; + + constructor(public el: ElementRef) {} + + @Input() get data(): any { + return this._data; + } + + set data(val:any) { + this._data = val; + this.reinit(); + } + + ngAfterViewInit() { + this.initChart(); + this.initialized = true; + } + + onCanvasClick(event) { + if(this.chart) { + let element = this.chart.getElementAtEvent(event); + let dataset = this.chart.getDatasetAtEvent(event); + if(element&&element[0]&&dataset) { + this.onDataSelect.emit({originalEvent: event, element: element[0], dataset: dataset}); + } + } + } + + initChart() { + this.chart = new Chart(this.el.nativeElement.children[0].children[0], { + type: this.type, + data: this.data, + options: this.options + }); + } + + getCanvas() { + return this.el.nativeElement.children[0].children[0]; + } + + getBase64Image() { + return this.chart.toBase64Image(); + } + + generateLegend() { + if(this.chart) { + this.chart.generateLegend(); + } + } + + refresh() { + if(this.chart) { + this.chart.update(); + } + } + + reinit() { + if(this.chart) { + this.chart.destroy(); + this.initChart(); + } + } + + ngOnDestroy() { + if(this.chart) { + this.chart.destroy(); + this.initialized = false; + this.chart = null; + } + } +} + +@NgModule({ + imports: [CommonModule], + exports: [UIChart], + declarations: [UIChart] +}) +export class ChartModule { } diff --git a/src/app/components/checkbox/checkbox.css b/src/app/components/checkbox/checkbox.css new file mode 100644 index 00000000000..2bb84c1b6f5 --- /dev/null +++ b/src/app/components/checkbox/checkbox.css @@ -0,0 +1,26 @@ +.ui-chkbox { + display: inline-block; + cursor: pointer; + vertical-align: middle; + margin-right: .25em; +} + +.ui-chkbox .ui-chkbox-box { + width: 1.125em; + height: 1.125em; + line-height: 1.125em; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + border-radius: 2px; + text-align: center; +} + +.ui-chkbox .ui-chkbox-icon { + line-height: inherit; + display: block; +} + +.ui-chkbox-label { + vertical-align: middle; +} + diff --git a/src/app/components/checkbox/checkbox.ts b/src/app/components/checkbox/checkbox.ts new file mode 100644 index 00000000000..fc7048c0b3b --- /dev/null +++ b/src/app/components/checkbox/checkbox.ts @@ -0,0 +1,149 @@ +import {NgModule,Component,Input,Output,EventEmitter,forwardRef,ChangeDetectorRef} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; + +export const CHECKBOX_VALUE_ACCESSOR: any = { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => Checkbox), + multi: true +}; + +@Component({ + selector: 'p-checkbox', + template: ` +
+
+ +
+
+ +
+
+ + `, + providers: [CHECKBOX_VALUE_ACCESSOR] +}) +export class Checkbox implements ControlValueAccessor { + + @Input() value: any; + + @Input() name: string; + + @Input() disabled: boolean; + + @Input() binary: string; + + @Input() label: string; + + @Input() tabindex: number; + + @Input() inputId: string; + + @Input() style: any; + + @Input() styleClass: string; + + @Output() onChange: EventEmitter = new EventEmitter(); + + model: any; + + onModelChange: Function = () => {}; + + onModelTouched: Function = () => {}; + + focused: boolean = false; + + checked: boolean = false; + + constructor(private cd: ChangeDetectorRef) {} + + onClick(event,checkbox,focus:boolean) { + event.preventDefault(); + + if(this.disabled) { + return; + } + + this.checked = !this.checked; + this.updateModel(); + + if(focus) { + checkbox.focus(); + } + } + + updateModel() { + if(!this.binary) { + if(this.checked) + this.addValue(); + else + this.removeValue(); + + this.onModelChange(this.model); + } + else { + this.onModelChange(this.checked); + } + + this.onChange.emit(this.checked); + } + + handleChange(event) { + this.checked = event.target.checked; + this.updateModel(); + } + + isChecked(): boolean { + if(this.binary) + return this.model; + else + return this.model && this.model.indexOf(this.value) > -1; + } + + removeValue() { + this.model = this.model.filter(val => val !== this.value); + } + + addValue() { + if(this.model) + this.model = [...this.model, this.value]; + else + this.model = [this.value]; + } + + onFocus(event) { + this.focused = true; + } + + onBlur(event) { + this.focused = false; + this.onModelTouched(); + } + + writeValue(model: any) : void { + this.model = model; + this.checked = this.isChecked(); + this.cd.markForCheck(); + } + + registerOnChange(fn: Function): void { + this.onModelChange = fn; + } + + registerOnTouched(fn: Function): void { + this.onModelTouched = fn; + } + + setDisabledState(val: boolean): void { + this.disabled = val; + } +} + +@NgModule({ + imports: [CommonModule], + exports: [Checkbox], + declarations: [Checkbox] +}) +export class CheckboxModule { } \ No newline at end of file diff --git a/src/app/components/chips/chips.css b/src/app/components/chips/chips.css new file mode 100644 index 00000000000..ae3568a936f --- /dev/null +++ b/src/app/components/chips/chips.css @@ -0,0 +1,59 @@ +.ui-chips > ul.ui-inputtext { + clear: left; + cursor: text; + list-style-type: none; + margin: 0; + overflow: hidden; + padding: 0 .25em; +} + +.ui-chips-token { + cursor: default; + display: inline-block; + vertical-align: middle; + overflow: hidden; + padding: .125em .5em; + white-space: nowrap; + position: relative; + margin-right: .125em; + border: 0 none; + font-size: .9em; +} + +.ui-chips-token .ui-chips-token-label { + display: block; + margin-right: 2em; +} + +.ui-chips > .ui-state-disabled .ui-chips-token-label { + margin-right: 0; +} + +.ui-chips-token .ui-chips-token-icon { + margin-top: -.5em; + position: absolute; + right: 0.2em; + top: 50%; + cursor: pointer; +} + +.ui-chips-input-token { + display: inline-block; + vertical-align: middle; + list-style-type: none; + margin: 0 0 0 .125em; + padding: .25em .25em .25em 0; +} + +.ui-chips-input-token input { + border: 0 none; + width: 10em; + outline: medium none; + background-color: transparent; + margin: 0; + padding: 0; + box-shadow: none; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; +} \ No newline at end of file diff --git a/src/app/components/chips/chips.ts b/src/app/components/chips/chips.ts new file mode 100644 index 00000000000..ffea29ee6e7 --- /dev/null +++ b/src/app/components/chips/chips.ts @@ -0,0 +1,191 @@ +import {NgModule,Component,ElementRef,Input,Output,EventEmitter,AfterContentInit,ContentChildren,QueryList,TemplateRef,IterableDiffers,forwardRef} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {SharedModule,PrimeTemplate} from '../common/shared'; +import {InputTextModule} from '../inputtext/inputtext'; +import {DomHandler} from '../dom/domhandler'; +import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; + +export const CHIPS_VALUE_ACCESSOR: any = { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => Chips), + multi: true +}; + +@Component({ + selector: 'p-chips', + template: ` +
+
    +
  • + + {{field ? resolveFieldData(item,field) : item}} + +
  • +
  • + +
  • +
+
+ `, + providers: [DomHandler,CHIPS_VALUE_ACCESSOR] +}) +export class Chips implements AfterContentInit,ControlValueAccessor { + + @Input() style: any; + + @Input() styleClass: string; + + @Input() disabled: boolean; + + @Output() onAdd: EventEmitter = new EventEmitter(); + + @Output() onRemove: EventEmitter = new EventEmitter(); + + @Input() field: string; + + @Input() placeholder: string; + + @Input() max: number; + + @Input() tabindex: number; + + @Input() inputId: string; + + @ContentChildren(PrimeTemplate) templates: QueryList; + + public itemTemplate: TemplateRef; + + value: any; + + onModelChange: Function = () => {}; + + onModelTouched: Function = () => {}; + + valueChanged: boolean; + + focus: boolean; + + constructor(public el: ElementRef, public domHandler: DomHandler) {} + + ngAfterContentInit() { + this.templates.forEach((item) => { + switch(item.getType()) { + case 'item': + this.itemTemplate = item.template; + break; + + default: + this.itemTemplate = item.template; + break; + } + }); + } + + writeValue(value: any) : void { + this.value = value; + } + + registerOnChange(fn: Function): void { + this.onModelChange = fn; + } + + registerOnTouched(fn: Function): void { + this.onModelTouched = fn; + } + + setDisabledState(val: boolean): void { + this.disabled = val; + } + + resolveFieldData(data: any, field: string): any { + if(data && field) { + if(field.indexOf('.') == -1) { + return data[field]; + } + else { + let fields: string[] = field.split('.'); + let value = data; + for(var i = 0, len = fields.length; i < len; ++i) { + value = value[fields[i]]; + } + return value; + } + } + else { + return null; + } + } + + onFocus() { + this.focus = true; + } + + onBlur() { + this.focus = false; + this.onModelTouched(); + } + + removeItem(event: Event, index: number): void { + if(this.disabled) { + return; + } + + let removedItem = this.value[index]; + this.value = this.value.filter((val, i) => i!=index); + this.onModelChange(this.value); + this.onRemove.emit({ + originalEvent: event, + value: removedItem + }); + } + + onKeydown(event: KeyboardEvent, inputEL: HTMLInputElement): void { + switch(event.which) { + //backspace + case 8: + if(inputEL.value.length === 0 && this.value && this.value.length > 0) { + this.value = [...this.value]; + let removedItem = this.value.pop(); + this.onModelChange(this.value); + this.onRemove.emit({ + originalEvent: event, + value: removedItem + }); + } + break; + + //enter + case 13: + this.value = this.value||[]; + if(inputEL.value && inputEL.value.trim().length && (!this.max||this.max > this.value.length)) { + this.value = [...this.value,inputEL.value]; + this.onModelChange(this.value); + this.onAdd.emit({ + originalEvent: event, + value: inputEL.value + }); + } + inputEL.value = ''; + event.preventDefault(); + break; + + default: + if(this.max && this.value && this.max === this.value.length) { + event.preventDefault(); + } + break; + } + } + + get maxedOut(): boolean { + return this.max && this.value && this.max === this.value.length; + } +} + +@NgModule({ + imports: [CommonModule,InputTextModule,SharedModule], + exports: [Chips,InputTextModule,SharedModule], + declarations: [Chips] +}) +export class ChipsModule { } \ No newline at end of file diff --git a/src/app/components/codehighlighter/codehighlighter.ts b/src/app/components/codehighlighter/codehighlighter.ts new file mode 100644 index 00000000000..aefce9b0e76 --- /dev/null +++ b/src/app/components/codehighlighter/codehighlighter.ts @@ -0,0 +1,25 @@ +import {NgModule,Directive,ElementRef,OnInit} from '@angular/core'; +import {CommonModule} from '@angular/common'; + +declare var Prism: any; + +@Directive({ + selector: '[pCode]' +}) +export class CodeHighlighter implements OnInit { + + constructor(public el: ElementRef) {} + + ngOnInit() { + Prism.highlightElement(this.el.nativeElement); + } +} + +@NgModule({ + imports: [CommonModule], + exports: [CodeHighlighter], + declarations: [CodeHighlighter] +}) +export class CodeHighlighterModule { } + + diff --git a/src/app/components/common/api.ts b/src/app/components/common/api.ts new file mode 100644 index 00000000000..f74057ea914 --- /dev/null +++ b/src/app/components/common/api.ts @@ -0,0 +1,24 @@ +export { DomHandler } from '../dom/domhandler'; +export { TreeNode } from './treenode'; +export { TreeDragDropService } from './treedragdropservice'; +export { TreeNodeDragEvent } from './treenodedragevent'; +export { BlockableUI } from './blockableui'; +export { Confirmation } from './confirmation'; +export { ConfirmationService } from './confirmationservice'; +export { FilterMetadata } from './filtermetadata'; +export { LazyLoadEvent } from './lazyloadevent'; +export { MenuItem } from './menuitem'; +export { Message } from './message'; +export { SelectItem } from './selectitem'; +export { SortMeta } from './sortmeta'; + + + + + + + + + + + diff --git a/src/app/components/common/blockableui.ts b/src/app/components/common/blockableui.ts new file mode 100644 index 00000000000..fd62e1705d2 --- /dev/null +++ b/src/app/components/common/blockableui.ts @@ -0,0 +1,3 @@ +export interface BlockableUI { + getBlockableElement(): HTMLElement; +} \ No newline at end of file diff --git a/src/app/components/common/common.css b/src/app/components/common/common.css new file mode 100644 index 00000000000..301959e666c --- /dev/null +++ b/src/app/components/common/common.css @@ -0,0 +1,152 @@ +.ui-widget, .ui-widget * { + box-sizing: border-box; +} +.ui-helper-hidden { + display: none; +} +.ui-helper-hidden-accessible { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} +.ui-helper-reset { + margin: 0; + padding: 0; + border: 0; + outline: 0; + line-height: 1.3; + text-decoration: none; + font-size: 100%; + list-style: none; +} +.ui-helper-clearfix:before, +.ui-helper-clearfix:after { + content: ""; + display: table; +} +.ui-helper-clearfix:after { + clear: both; +} +.ui-helper-clearfix { + zoom: 1; +} +.ui-helper-zfix { + width: 100%; + height: 100%; + top: 0; + left: 0; + position: absolute; + opacity: 0; + filter: Alpha(Opacity=0); +} +.ui-state-disabled { + cursor: default !important; +} +.ui-state-disabled a { + cursor: default !important; +} +.ui-icon { + display: block; + text-indent: -99999px; + overflow: hidden; + background-repeat: no-repeat; +} +.ui-widget-overlay { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} +.ui-resizable { + position: relative; +} +.ui-resizable-handle { + position: absolute; + font-size: 0.1px; + display: block; +} +.ui-resizable-disabled .ui-resizable-handle, +.ui-resizable-autohide .ui-resizable-handle { + display: none; +} +.ui-resizable-n { + cursor: n-resize; + height: 7px; + width: 100%; + top: -5px; + left: 0; +} +.ui-resizable-s { + cursor: s-resize; + height: 7px; + width: 100%; + bottom: -5px; + left: 0; +} +.ui-resizable-e { + cursor: e-resize; + width: 7px; + right: -5px; + top: 0; + height: 100%; +} +.ui-resizable-w { + cursor: w-resize; + width: 7px; + left: -5px; + top: 0; + height: 100%; +} +.ui-resizable-se { + cursor: se-resize; + width: 12px; + height: 12px; + right: 1px; + bottom: 1px; +} +.ui-resizable-sw { + cursor: sw-resize; + width: 9px; + height: 9px; + left: -5px; + bottom: -5px; +} +.ui-resizable-nw { + cursor: nw-resize; + width: 9px; + height: 9px; + left: -5px; + top: -5px; +} +.ui-resizable-ne { + cursor: ne-resize; + width: 9px; + height: 9px; + right: -5px; + top: -5px; +} +.ui-shadow { + -webkit-box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0.3); + box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0.3); +} +.ui-unselectable-text { + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -o-user-select: none; + user-select: none; +} +.ui-scrollbar-measure { + width: 100px; + height: 100px; + overflow: scroll; + position: absolute; + top: -9999px; +} \ No newline at end of file diff --git a/src/app/components/common/confirmation.ts b/src/app/components/common/confirmation.ts new file mode 100644 index 00000000000..27c7e9b49e1 --- /dev/null +++ b/src/app/components/common/confirmation.ts @@ -0,0 +1,14 @@ +import { EventEmitter } from '@angular/core'; + +export interface Confirmation { + message: string; + key?: string; + icon?: string; + header?: string; + accept?: Function; + reject?: Function; + acceptVisible?: boolean; + rejectVisible?: boolean; + acceptEvent?: EventEmitter; + rejectEvent?: EventEmitter; +} diff --git a/src/app/components/common/confirmationservice.ts b/src/app/components/common/confirmationservice.ts new file mode 100644 index 00000000000..c96f104c459 --- /dev/null +++ b/src/app/components/common/confirmationservice.ts @@ -0,0 +1,23 @@ +import { Injectable } from '@angular/core'; +import { Subject } from 'rxjs/Subject'; +import { Observable } from 'rxjs/Observable'; +import { Confirmation } from './confirmation'; + +@Injectable() +export class ConfirmationService { + + private requireConfirmationSource = new Subject(); + private acceptConfirmationSource = new Subject(); + + requireConfirmation$ = this.requireConfirmationSource.asObservable(); + accept = this.acceptConfirmationSource.asObservable(); + + confirm(confirmation: Confirmation) { + this.requireConfirmationSource.next(confirmation); + return this; + } + + onAccept() { + this.acceptConfirmationSource.next(); + } +} \ No newline at end of file diff --git a/src/app/components/common/filtermetadata.ts b/src/app/components/common/filtermetadata.ts new file mode 100644 index 00000000000..2fc78e4f420 --- /dev/null +++ b/src/app/components/common/filtermetadata.ts @@ -0,0 +1,4 @@ +export interface FilterMetadata { + value?: any; + matchMode?: string; +} \ No newline at end of file diff --git a/src/app/components/common/lazyloadevent.ts b/src/app/components/common/lazyloadevent.ts new file mode 100644 index 00000000000..fa962033acd --- /dev/null +++ b/src/app/components/common/lazyloadevent.ts @@ -0,0 +1,12 @@ +import { SortMeta } from './sortmeta'; +import { FilterMetadata } from './filtermetadata'; + +export interface LazyLoadEvent { + first?: number; + rows?: number; + sortField?: string; + sortOrder?: number; + multiSortMeta?: SortMeta[]; + filters?: {[s: string]: FilterMetadata;}; + globalFilter?: any; +} \ No newline at end of file diff --git a/src/app/components/common/menuitem.ts b/src/app/components/common/menuitem.ts new file mode 100644 index 00000000000..62f187fecce --- /dev/null +++ b/src/app/components/common/menuitem.ts @@ -0,0 +1,16 @@ +import {EventEmitter} from '@angular/core'; + +export interface MenuItem { + label?: string; + icon?: string; + command?: (event?: any) => void; + url?: string; + routerLink?: any; + eventEmitter?: EventEmitter; + items?: MenuItem[]; + expanded?: boolean; + disabled?: boolean; + visible?: boolean; + target?: string; + routerLinkActiveOptions?: any; +} \ No newline at end of file diff --git a/src/app/components/common/message.ts b/src/app/components/common/message.ts new file mode 100644 index 00000000000..bbdf4d0b654 --- /dev/null +++ b/src/app/components/common/message.ts @@ -0,0 +1,6 @@ +export interface Message { + severity?: string; + summary?: string; + detail?: string; + id?: any; +} \ No newline at end of file diff --git a/src/app/components/common/selectitem.ts b/src/app/components/common/selectitem.ts new file mode 100644 index 00000000000..04d19e971b8 --- /dev/null +++ b/src/app/components/common/selectitem.ts @@ -0,0 +1,4 @@ +export interface SelectItem { + label: string; + value: any; +} \ No newline at end of file diff --git a/src/app/components/common/shared.ts b/src/app/components/common/shared.ts new file mode 100644 index 00000000000..f134be83308 --- /dev/null +++ b/src/app/components/common/shared.ts @@ -0,0 +1,329 @@ +import {NgModule,EventEmitter,Directive,ViewContainerRef,Input,Output,ContentChildren,ContentChild,TemplateRef,OnInit,OnChanges,OnDestroy,AfterContentInit,QueryList,SimpleChanges,EmbeddedViewRef} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {Component} from '@angular/core'; + +@Component({ + selector: 'p-header', + template: '' +}) +export class Header {} + +@Component({ + selector: 'p-footer', + template: '' +}) +export class Footer {} + +@Directive({ + selector: '[pTemplate]', + host: { + } +}) +export class PrimeTemplate { + + @Input() type: string; + + @Input('pTemplate') name: string; + + constructor(public template: TemplateRef) {} + + getType(): string { + if(this.type) { + console.log('Defining a pTemplate with type property is deprecated use pTemplate="type" instead.'); + return this.type; + } + else { + return this.name; + } + } +} + +@Directive({ + selector: '[pTemplateWrapper]' +}) +export class TemplateWrapper implements OnInit, OnDestroy { + + @Input() item: any; + + @Input() index: number; + + @Input('pTemplateWrapper') templateRef: TemplateRef; + + view: EmbeddedViewRef; + + constructor(public viewContainer: ViewContainerRef) {} + + ngOnInit() { + this.view = this.viewContainer.createEmbeddedView(this.templateRef, { + '\$implicit': this.item, + 'index': this.index + }); + } + + ngOnDestroy() { + this.view.destroy(); + } +} + +@Component({ + selector: 'p-column', + template: `` +}) +export class Column implements AfterContentInit{ + @Input() field: string; + @Input() sortField: string; + @Input() header: string; + @Input() footer: string; + @Input() sortable: any; + @Input() editable: boolean; + @Input() filter: boolean; + @Input() filterMatchMode: string; + @Input() filterType: string = 'text'; + @Input() rowspan: number; + @Input() colspan: number; + @Input() style: any; + @Input() styleClass: string; + @Input() hidden: boolean; + @Input() expander: boolean; + @Input() selectionMode: string; + @Input() filterPlaceholder: string; + @Input() frozen: boolean; + @Output() sortFunction: EventEmitter = new EventEmitter(); + @ContentChildren(PrimeTemplate) templates: QueryList; + @ContentChild(TemplateRef) template: TemplateRef; + + public headerTemplate: TemplateRef; + public bodyTemplate: TemplateRef; + public footerTemplate: TemplateRef; + public filterTemplate: TemplateRef; + public editorTemplate: TemplateRef; + + ngAfterContentInit():void { + this.templates.forEach((item) => { + switch(item.getType()) { + case 'header': + this.headerTemplate = item.template; + break; + + case 'body': + this.bodyTemplate = item.template; + break; + + case 'footer': + this.footerTemplate = item.template; + break; + + case 'filter': + this.filterTemplate = item.template; + break; + + case 'editor': + this.editorTemplate = item.template; + break; + + default: + this.bodyTemplate = item.template; + break; + } + }); + } +} + +@Component({ + selector: 'p-row', + template: `` +}) +export class Row { + + @ContentChildren(Column) columns: QueryList; + +} + +@Component({ + selector: 'p-headerColumnGroup', + template: `` +}) +export class HeaderColumnGroup { + + @ContentChildren(Row) rows: QueryList; +} + +@Component({ + selector: 'p-footerColumnGroup', + template: `` +}) +export class FooterColumnGroup { + + @ContentChildren(Row) rows: QueryList; +} + +@Component({ + selector: 'p-columnBodyTemplateLoader', + template: `` +}) +export class ColumnBodyTemplateLoader implements OnInit, OnChanges, OnDestroy { + + @Input() column: any; + + @Input() rowData: any; + + @Input() rowIndex: number; + + view: EmbeddedViewRef; + + constructor(public viewContainer: ViewContainerRef) {} + + ngOnInit() { + this.view = this.viewContainer.createEmbeddedView(this.column.bodyTemplate, { + '\$implicit': this.column, + 'rowData': this.rowData, + 'rowIndex': this.rowIndex + }); + } + + ngOnChanges(changes: SimpleChanges) { + if(!this.view) { + return; + } + + if('rowIndex' in changes) { + this.view.context.rowIndex = changes['rowIndex'].currentValue; + } + } + + ngOnDestroy() { + this.view.destroy(); + } +} + +@Component({ + selector: 'p-columnHeaderTemplateLoader', + template: `` +}) +export class ColumnHeaderTemplateLoader implements OnInit, OnDestroy { + + @Input() column: any; + + view: EmbeddedViewRef; + + constructor(public viewContainer: ViewContainerRef) {} + + ngOnInit() { + this.view = this.viewContainer.createEmbeddedView(this.column.headerTemplate, { + '\$implicit': this.column + }); + } + + ngOnDestroy() { + this.view.destroy(); + } +} + +@Component({ + selector: 'p-columnFooterTemplateLoader', + template: `` +}) +export class ColumnFooterTemplateLoader implements OnInit, OnDestroy { + + @Input() column: any; + + view: EmbeddedViewRef; + + constructor(public viewContainer: ViewContainerRef) {} + + ngOnInit() { + this.view = this.viewContainer.createEmbeddedView(this.column.footerTemplate, { + '\$implicit': this.column + }); + } + + ngOnDestroy() { + this.view.destroy(); + } +} + +@Component({ + selector: 'p-columnFilterTemplateLoader', + template: `` +}) +export class ColumnFilterTemplateLoader implements OnInit, OnDestroy { + + @Input() column: any; + + view: EmbeddedViewRef; + + constructor(public viewContainer: ViewContainerRef) {} + + ngOnInit() { + this.view = this.viewContainer.createEmbeddedView(this.column.filterTemplate, { + '\$implicit': this.column + }); + } + + ngOnDestroy() { + this.view.destroy(); + } +} + +@Component({ + selector: 'p-columnEditorTemplateLoader', + template: `` +}) +export class ColumnEditorTemplateLoader implements OnInit, OnDestroy { + + @Input() column: any; + + @Input() rowData: any; + + @Input() rowIndex: any; + + view: EmbeddedViewRef; + + constructor(public viewContainer: ViewContainerRef) {} + + ngOnInit() { + this.view = this.viewContainer.createEmbeddedView(this.column.editorTemplate, { + '\$implicit': this.column, + 'rowData': this.rowData, + 'rowIndex': this.rowIndex + }); + } + + ngOnDestroy() { + this.view.destroy(); + } +} + +@Component({ + selector: 'p-templateLoader', + template: `` +}) +export class TemplateLoader implements OnInit, OnDestroy { + + @Input() template: TemplateRef; + + @Input() data: any; + + view: EmbeddedViewRef; + + constructor(public viewContainer: ViewContainerRef) {} + + ngOnInit() { + if(this.template) { + this.view = this.viewContainer.createEmbeddedView(this.template, { + '\$implicit': this.data + }); + } + } + + ngOnDestroy() { + if (this.view) this.view.destroy(); + } +} + +@NgModule({ + imports: [CommonModule], + exports: [Header,Footer,Column,TemplateWrapper,ColumnHeaderTemplateLoader,ColumnBodyTemplateLoader,ColumnFooterTemplateLoader,ColumnFilterTemplateLoader,PrimeTemplate,TemplateLoader,Row,HeaderColumnGroup,FooterColumnGroup,ColumnEditorTemplateLoader], + declarations: [Header,Footer,Column,TemplateWrapper,ColumnHeaderTemplateLoader,ColumnBodyTemplateLoader,ColumnFooterTemplateLoader,ColumnFilterTemplateLoader,PrimeTemplate,TemplateLoader,Row,HeaderColumnGroup,FooterColumnGroup,ColumnEditorTemplateLoader] +}) +export class SharedModule { } diff --git a/src/app/components/common/sortmeta.ts b/src/app/components/common/sortmeta.ts new file mode 100644 index 00000000000..7b2c7e22f2d --- /dev/null +++ b/src/app/components/common/sortmeta.ts @@ -0,0 +1,4 @@ +export interface SortMeta { + field: string; + order: number; +} \ No newline at end of file diff --git a/src/app/components/common/treedragdropservice.ts b/src/app/components/common/treedragdropservice.ts new file mode 100644 index 00000000000..d19bf4a80f8 --- /dev/null +++ b/src/app/components/common/treedragdropservice.ts @@ -0,0 +1,23 @@ +import { Injectable } from '@angular/core'; +import { Subject } from 'rxjs/Subject'; +import { Observable } from 'rxjs/Observable'; +import { TreeNode } from './treenode'; +import { TreeNodeDragEvent } from './treenodedragevent'; + +@Injectable() +export class TreeDragDropService { + + private dragStartSource = new Subject(); + private dragStopSource = new Subject(); + + dragStart$ = this.dragStartSource.asObservable(); + dragStop$ = this.dragStopSource.asObservable(); + + startDrag(event: TreeNodeDragEvent) { + this.dragStartSource.next(event); + } + + stopDrag(event: TreeNodeDragEvent) { + this.dragStopSource.next(event); + } +} \ No newline at end of file diff --git a/src/app/components/common/treenode.ts b/src/app/components/common/treenode.ts new file mode 100644 index 00000000000..42016563cbc --- /dev/null +++ b/src/app/components/common/treenode.ts @@ -0,0 +1,17 @@ +export interface TreeNode { + label?: string; + data?: any; + icon?: any; + expandedIcon?: any; + collapsedIcon?: any; + children?: TreeNode[]; + leaf?: boolean; + expanded?: boolean; + type?: string; + parent?: TreeNode; + partialSelected?: boolean; + styleClass?: string; + draggable?: boolean; + droppable?: boolean; + selectable?: boolean; +} \ No newline at end of file diff --git a/src/app/components/common/treenodedragevent.ts b/src/app/components/common/treenodedragevent.ts new file mode 100644 index 00000000000..0509cfa3bb8 --- /dev/null +++ b/src/app/components/common/treenodedragevent.ts @@ -0,0 +1,9 @@ +import { TreeNode } from './treenode'; + +export interface TreeNodeDragEvent { + tree?: any; + node?: TreeNode; + subNodes?: TreeNode[]; + index?: number; + scope?: any; +} \ No newline at end of file diff --git a/src/app/components/confirmdialog/confirmdialog.ts b/src/app/components/confirmdialog/confirmdialog.ts new file mode 100644 index 00000000000..a8d730cf051 --- /dev/null +++ b/src/app/components/confirmdialog/confirmdialog.ts @@ -0,0 +1,268 @@ +import {NgModule,Component,ElementRef,AfterViewInit,OnDestroy,Input,Output,EventEmitter,Renderer2,ContentChild} from '@angular/core'; +import {trigger,state,style,transition,animate} from '@angular/animations'; +import {CommonModule} from '@angular/common'; +import {DomHandler} from '../dom/domhandler'; +import {Header,Footer,SharedModule} from '../common/shared'; +import {ButtonModule} from '../button/button'; +import {Confirmation} from '../common/confirmation'; +import {ConfirmationService} from '../common/confirmationservice'; +import {Subscription} from 'rxjs/Subscription'; + +@Component({ + selector: 'p-confirmDialog', + template: ` +
+
+ {{header}} + + + +
+
+ + +
+
+ +
+
+ + +
+
+ `, + animations: [ + trigger('dialogState', [ + state('hidden', style({ + opacity: 0 + })), + state('visible', style({ + opacity: 1 + })), + transition('visible => hidden', animate('400ms ease-in')), + transition('hidden => visible', animate('400ms ease-out')) + ]) + ], + providers: [DomHandler] +}) +export class ConfirmDialog implements AfterViewInit,OnDestroy { + + @Input() header: string; + + @Input() icon: string; + + @Input() message: string; + + @Input() acceptIcon: string = 'fa-check'; + + @Input() acceptLabel: string = 'Yes'; + + @Input() acceptVisible: boolean = true; + + @Input() rejectIcon: string = 'fa-close'; + + @Input() rejectLabel: string = 'No'; + + @Input() rejectVisible: boolean = true; + + @Input() width: any; + + @Input() height: any; + + @Input() closeOnEscape: boolean = true; + + @Input() rtl: boolean; + + @Input() closable: boolean = true; + + @Input() responsive: boolean = true; + + @Input() appendTo: any; + + @Input() key: string; + + @ContentChild(Footer) footer; + + confirmation: Confirmation; + + _visible: boolean; + + documentEscapeListener: any; + + documentResponsiveListener: any; + + mask: any; + + contentContainer: any; + + positionInitialized: boolean; + + subscription: Subscription; + + constructor(public el: ElementRef, public domHandler: DomHandler, + public renderer: Renderer2, private confirmationService: ConfirmationService) { + this.subscription = confirmationService.requireConfirmation$.subscribe(confirmation => { + if(confirmation.key === this.key) { + this.confirmation = confirmation; + this.message = this.confirmation.message||this.message; + this.icon = this.confirmation.icon||this.icon; + this.header = this.confirmation.header||this.header; + this.rejectVisible = this.confirmation.rejectVisible == null ? this.rejectVisible : this.confirmation.rejectVisible; + this.acceptVisible = this.confirmation.acceptVisible == null ? this.acceptVisible : this.confirmation.acceptVisible; + + if(this.confirmation.accept) { + this.confirmation.acceptEvent = new EventEmitter(); + this.confirmation.acceptEvent.subscribe(this.confirmation.accept); + } + + if(this.confirmation.reject) { + this.confirmation.rejectEvent = new EventEmitter(); + this.confirmation.rejectEvent.subscribe(this.confirmation.reject); + } + + this.visible = true; + } + }); + } + + @Input() get visible(): boolean { + return this._visible; + } + + set visible(val:boolean) { + this._visible = val; + + if(this._visible) { + if(!this.positionInitialized) { + this.center(); + this.positionInitialized = true; + } + + this.el.nativeElement.children[0].style.zIndex = ++DomHandler.zindex; + } + + if(this._visible) + this.enableModality(); + else + this.disableModality(); + } + + ngAfterViewInit() { + this.contentContainer = this.domHandler.findSingle(this.el.nativeElement, '.ui-dialog-content'); + + if(this.responsive) { + this.documentResponsiveListener = this.renderer.listen('window', 'resize', (event) => { + this.center(); + }); + } + + if(this.closeOnEscape && this.closable) { + this.documentEscapeListener = this.renderer.listen('document', 'keydown', (event) => { + if(event.which == 27) { + if(this.el.nativeElement.children[0].style.zIndex == DomHandler.zindex) { + this.hide(event); + } + } + }); + } + + if(this.appendTo) { + if(this.appendTo === 'body') + document.body.appendChild(this.el.nativeElement); + else + this.domHandler.appendChild(this.el.nativeElement, this.appendTo); + } + } + + center() { + let container = this.el.nativeElement.children[0]; + let elementWidth = this.domHandler.getOuterWidth(container); + let elementHeight = this.domHandler.getOuterHeight(container); + if(elementWidth == 0 && elementHeight == 0) { + container.style.visibility = 'hidden'; + container.style.display = 'block'; + elementWidth = this.domHandler.getOuterWidth(container); + elementHeight = this.domHandler.getOuterHeight(container); + container.style.display = 'none'; + container.style.visibility = 'visible'; + } + let viewport = this.domHandler.getViewport(); + let x = (viewport.width - elementWidth) / 2; + let y = (viewport.height - elementHeight) / 2; + + container.style.left = x + 'px'; + container.style.top = y + 'px'; + } + + enableModality() { + if(!this.mask) { + this.mask = document.createElement('div'); + this.mask.style.zIndex = this.el.nativeElement.children[0].style.zIndex - 1; + this.domHandler.addMultipleClasses(this.mask, 'ui-widget-overlay ui-dialog-mask'); + document.body.appendChild(this.mask); + } + } + + disableModality() { + if(this.mask) { + document.body.removeChild(this.mask); + this.mask = null; + } + } + + hide(event?:Event) { + this.visible = false; + + if(event) { + event.preventDefault(); + } + } + + moveOnTop() { + this.el.nativeElement.children[0].style.zIndex = ++DomHandler.zindex; + } + + ngOnDestroy() { + this.disableModality(); + + if(this.documentResponsiveListener) { + this.documentResponsiveListener(); + } + + if(this.documentEscapeListener) { + this.documentEscapeListener(); + } + + if(this.appendTo && this.appendTo === 'body') { + document.body.removeChild(this.el.nativeElement); + } + + this.subscription.unsubscribe(); + } + + accept() { + if(this.confirmation.acceptEvent) { + this.confirmation.acceptEvent.emit(); + } + + this.hide(); + this.confirmation = null; + } + + reject() { + if(this.confirmation.rejectEvent) { + this.confirmation.rejectEvent.emit(); + } + + this.hide(); + this.confirmation = null; + } +} + +@NgModule({ + imports: [CommonModule,ButtonModule], + exports: [ConfirmDialog,ButtonModule,SharedModule], + declarations: [ConfirmDialog] +}) +export class ConfirmDialogModule { } \ No newline at end of file diff --git a/src/app/components/contextmenu/contextmenu.ts b/src/app/components/contextmenu/contextmenu.ts new file mode 100644 index 00000000000..87853b72531 --- /dev/null +++ b/src/app/components/contextmenu/contextmenu.ts @@ -0,0 +1,278 @@ +import {NgModule,Component,ElementRef,AfterViewInit,OnDestroy,Input,Output,Renderer2,EventEmitter,Inject,forwardRef,ViewChild} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {DomHandler} from '../dom/domhandler'; +import {MenuItem} from '../common/menuitem'; +import {Location} from '@angular/common'; +import {RouterModule} from '@angular/router'; + +@Component({ + selector: 'p-contextMenuSub', + template: ` + + `, + providers: [DomHandler] +}) +export class ContextMenuSub { + + @Input() item: MenuItem; + + @Input() root: boolean; + + constructor(public domHandler: DomHandler, @Inject(forwardRef(() => ContextMenu)) public contextMenu: ContextMenu) {} + + activeItem: any; + + containerLeft: any; + + onItemMouseEnter(event, item, menuitem) { + if(menuitem.disabled) { + return; + } + + this.activeItem = item; + let nextElement = item.children[0].nextElementSibling; + if(nextElement) { + let sublist = nextElement.children[0]; + sublist.style.zIndex = ++DomHandler.zindex; + this.position(sublist, item); + } + } + + onItemMouseLeave(event, link) { + this.activeItem = null; + } + + itemClick(event, item: MenuItem) { + if(item.disabled) { + event.preventDefault(); + return; + } + + if(!item.url) { + event.preventDefault(); + } + + if(item.command) { + if(!item.eventEmitter) { + item.eventEmitter = new EventEmitter(); + item.eventEmitter.subscribe(item.command); + } + + item.eventEmitter.emit({ + originalEvent: event, + item: item + }); + } + } + + listClick(event) { + this.activeItem = null; + } + + position(sublist, item) { + this.containerLeft = this.domHandler.getOffset(item.parentElement) + let viewport = this.domHandler.getViewport(); + let sublistWidth = sublist.offsetParent ? sublist.offsetWidth: this.domHandler.getHiddenElementOuterWidth(sublist); + let itemOuterWidth = this.domHandler.getOuterWidth(item.children[0]); + + sublist.style.top = '0px'; + + if((parseInt(this.containerLeft.left) + itemOuterWidth + sublistWidth) > (viewport.width - this.calculateScrollbarWidth())) { + sublist.style.left = -sublistWidth + 'px'; + } + else { + sublist.style.left = itemOuterWidth + 'px'; + } + } + + calculateScrollbarWidth(): number { + let scrollDiv = document.createElement("div"); + scrollDiv.className = "ui-scrollbar-measure"; + document.body.appendChild(scrollDiv); + + let scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth; + document.body.removeChild(scrollDiv); + + return scrollbarWidth; + } +} + +@Component({ + selector: 'p-contextMenu', + template: ` +
+ +
+ `, + providers: [DomHandler] +}) +export class ContextMenu implements AfterViewInit,OnDestroy { + + @Input() model: MenuItem[]; + + @Input() global: boolean; + + @Input() target: any; + + @Input() style: any; + + @Input() styleClass: string; + + @Input() appendTo: any; + + @ViewChild('container') containerViewChild: ElementRef; + + container: HTMLDivElement; + + visible: boolean; + + documentClickListener: any; + + rightClickListener: any; + + constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2) {} + + ngAfterViewInit() { + this.container = this.containerViewChild.nativeElement; + + this.documentClickListener = this.renderer.listen('document', 'click', () => { + this.hide(); + }); + + if(this.global) { + this.rightClickListener = this.renderer.listen('document', 'contextmenu', (event) => { + this.show(event); + event.preventDefault(); + }); + } + else if(this.target) { + this.rightClickListener = this.renderer.listen(this.target, 'contextmenu', (event) => { + this.show(event); + event.preventDefault(); + event.stopPropagation(); + }); + } + + if(this.appendTo) { + if(this.appendTo === 'body') + document.body.appendChild(this.container); + else + this.domHandler.appendChild(this.container, this.appendTo); + } + } + + show(event?: MouseEvent) { + this.position(event); + this.visible = true; + this.domHandler.fadeIn(this.container, 250); + + if(event) { + event.preventDefault(); + } + } + + hide() { + this.visible = false; + } + + toggle(event?: MouseEvent) { + if(this.visible) + this.hide(); + else + this.show(event); + } + + position(event?: MouseEvent) { + if(event) { + let left = event.pageX + 1; + let top = event.pageY + 1; + let width = this.container.offsetParent ? this.container.offsetWidth: this.domHandler.getHiddenElementOuterWidth(this.container); + let height = this.container.offsetParent ? this.container.offsetHeight: this.domHandler.getHiddenElementOuterHeight(this.container); + let viewport = this.domHandler.getViewport(); + + //flip + if(left + width - document.body.scrollLeft > viewport.width) { + left -= width; + } + + //flip + if(top + height - document.body.scrollTop > viewport.height) { + top -= height; + } + + //fit + if(left < document.body.scrollLeft) { + left = document.body.scrollLeft; + } + + //fit + if(top < document.body.scrollTop) { + top = document.body.scrollTop; + } + + this.container.style.left = left + 'px'; + this.container.style.top = top + 'px'; + } + } + + unsubscribe(item: any) { + if(item.eventEmitter) { + item.eventEmitter.unsubscribe(); + } + + if(item.items) { + for(let childItem of item.items) { + this.unsubscribe(childItem); + } + } + } + + ngOnDestroy() { + if(this.documentClickListener) { + this.documentClickListener(); + } + + if(this.rightClickListener) { + this.rightClickListener(); + } + + if(this.model) { + for(let item of this.model) { + this.unsubscribe(item); + } + } + + if(this.appendTo) { + this.el.nativeElement.appendChild(this.container); + } + } + +} + +@NgModule({ + imports: [CommonModule,RouterModule], + exports: [ContextMenu,RouterModule], + declarations: [ContextMenu,ContextMenuSub] +}) +export class ContextMenuModule { } \ No newline at end of file diff --git a/src/app/components/datagrid/datagrid.css b/src/app/components/datagrid/datagrid.css new file mode 100644 index 00000000000..d044f7b01f0 --- /dev/null +++ b/src/app/components/datagrid/datagrid.css @@ -0,0 +1,35 @@ +.ui-datagrid .ui-paginator { + text-align: center; + border-top: 0 none; +} + +.ui-datagrid-column { + padding: .25em; +} + +.ui-datagrid-content-empty { + padding: .25em .625em; +} + +.ui-datagrid .ui-datagrid-header, +.ui-datagrid .ui-datagrid-footer { + text-align:center; + padding: .5em .75em; +} + +.ui-datagrid .ui-datagrid-header { + border-bottom: 0 none; +} + +.ui-datagrid .ui-datagrid-footer { + border-top: 0 none; +} + +.ui-datagrid .ui-paginator-top { + border-bottom: 0 none; +} + +.ui-datagrid .ui-paginator-bottom { + border-top: 0 none; +} + diff --git a/src/app/components/datagrid/datagrid.ts b/src/app/components/datagrid/datagrid.ts new file mode 100644 index 00000000000..fc55dac4bd2 --- /dev/null +++ b/src/app/components/datagrid/datagrid.ts @@ -0,0 +1,183 @@ +import {NgModule,Component,ElementRef,AfterViewInit,AfterContentInit,OnDestroy,Input,Output,SimpleChange,EventEmitter,ContentChild,ContentChildren,QueryList,TemplateRef} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {Header,Footer,PrimeTemplate,SharedModule} from '../common/shared'; +import {PaginatorModule} from '../paginator/paginator'; +import {BlockableUI} from '../common/blockableui'; + +@Component({ + selector: 'p-dataGrid', + template: ` +
+
+ +
+ +
+
+ +
{{emptyMessage}}
+
+
+ + +
+ ` +}) +export class DataGrid implements AfterViewInit,AfterContentInit,BlockableUI { + + @Input() paginator: boolean; + + @Input() rows: number; + + @Input() totalRecords: number; + + @Input() pageLinks: number = 5; + + @Input() rowsPerPageOptions: number[]; + + @Input() lazy: boolean; + + @Input() emptyMessage: string = 'No records found'; + + @Output() onLazyLoad: EventEmitter = new EventEmitter(); + + @Input() style: any; + + @Input() styleClass: string; + + @Input() paginatorPosition: string = 'bottom'; + + @Input() alwaysShowPaginator: boolean = true; + + @Input() trackBy: Function = (index: number, item: any) => item; + + @Output() onPage: EventEmitter = new EventEmitter(); + + @ContentChild(Header) header; + + @ContentChild(Footer) footer; + + @ContentChildren(PrimeTemplate) templates: QueryList; + + public _value: any[]; + + public itemTemplate: TemplateRef; + + public dataToRender: any[]; + + public first: number = 0; + + public page: number = 0; + + constructor(public el: ElementRef) {} + + ngAfterViewInit() { + if(this.lazy) { + this.onLazyLoad.emit({ + first: this.first, + rows: this.rows + }); + } + } + + ngAfterContentInit() { + this.templates.forEach((item) => { + switch(item.getType()) { + case 'item': + this.itemTemplate = item.template; + break; + + default: + this.itemTemplate = item.template; + break; + } + }); + } + + @Input() get value(): any[] { + return this._value; + } + + set value(val:any[]) { + this._value = val; + this.handleDataChange(); + } + + handleDataChange() { + if(this.paginator) { + this.updatePaginator(); + } + this.updateDataToRender(this.value); + } + + updatePaginator() { + //total records + this.totalRecords = this.lazy ? this.totalRecords : (this.value ? this.value.length: 0); + + //first + if(this.totalRecords && this.first >= this.totalRecords) { + let numberOfPages = Math.ceil(this.totalRecords/this.rows); + this.first = Math.max((numberOfPages-1) * this.rows, 0); + } + } + + paginate(event) { + this.first = event.first; + this.rows = event.rows; + + if(this.lazy) { + this.onLazyLoad.emit(this.createLazyLoadMetadata()); + } + else { + this.updateDataToRender(this.value); + } + + this.onPage.emit({ + first: this.first, + rows: this.rows + }); + } + + updateDataToRender(datasource) { + if(this.paginator && datasource) { + this.dataToRender = []; + let startIndex = this.lazy ? 0 : this.first; + for(let i = startIndex; i < (startIndex+ this.rows); i++) { + if(i >= datasource.length) { + break; + } + + this.dataToRender.push(datasource[i]); + } + } + else { + this.dataToRender = datasource; + } + } + + isEmpty() { + return !this.dataToRender||(this.dataToRender.length == 0); + } + + createLazyLoadMetadata(): any { + return { + first: this.first, + rows: this.rows + }; + } + + getBlockableElement(): HTMLElement { + return this.el.nativeElement.children[0]; + } +} + +@NgModule({ + imports: [CommonModule,SharedModule,PaginatorModule], + exports: [DataGrid,SharedModule], + declarations: [DataGrid] +}) +export class DataGridModule { } diff --git a/src/app/components/datalist/datalist.css b/src/app/components/datalist/datalist.css new file mode 100644 index 00000000000..9aa70e674d4 --- /dev/null +++ b/src/app/components/datalist/datalist.css @@ -0,0 +1,31 @@ +.ui-datalist .ui-datalist-header, +.ui-datalist .ui-datalist-footer { + text-align:center; + padding: .5em .75em; +} + +.ui-datalist .ui-datalist-header { + border-bottom: 0 none; +} + +.ui-datalist .ui-datalist-footer { + border-top: 0 none; +} + +.ui-datalist .ui-paginator { + border-top: 0 none; +} + +.ui-datalist .ui-datalist-data { + margin: 0; + padding: 0; +} + +.ui-datalist .ui-datalist-data > li { + list-style-type: none; + +} + +.ui-datalist .ui-datalist-emptymessage { + padding: .5em .75em; +} \ No newline at end of file diff --git a/src/app/components/datalist/datalist.ts b/src/app/components/datalist/datalist.ts new file mode 100644 index 00000000000..15fa40d9f37 --- /dev/null +++ b/src/app/components/datalist/datalist.ts @@ -0,0 +1,185 @@ +import {NgModule,Component,ElementRef,AfterViewInit,AfterContentInit,OnDestroy,Input,Output,SimpleChange,EventEmitter,ContentChild,ContentChildren,TemplateRef,QueryList} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {SharedModule,Header,Footer,PrimeTemplate} from '../common/shared'; +import {PaginatorModule} from '../paginator/paginator'; +import {BlockableUI} from '../common/blockableui'; + +@Component({ + selector: 'p-dataList', + template: ` +
+
+ +
+ +
+
{{emptyMessage}}
+
    +
  • + +
  • +
+
+ + +
+ ` +}) +export class DataList implements AfterViewInit,AfterContentInit,BlockableUI { + + @Input() paginator: boolean; + + @Input() rows: number; + + @Input() totalRecords: number; + + @Input() pageLinks: number = 5; + + @Input() rowsPerPageOptions: number[]; + + @Input() lazy: boolean; + + @Output() onLazyLoad: EventEmitter = new EventEmitter(); + + @Input() style: any; + + @Input() styleClass: string; + + @Input() paginatorPosition: string = 'bottom'; + + @Input() emptyMessage: string = 'No records found'; + + @Input() alwaysShowPaginator: boolean = true; + + @Input() trackBy: Function = (index: number, item: any) => item; + + @Output() onPage: EventEmitter = new EventEmitter(); + + @ContentChild(Header) header; + + @ContentChild(Footer) footer; + + @ContentChildren(PrimeTemplate) templates: QueryList; + + public _value: any[]; + + public itemTemplate: TemplateRef; + + public dataToRender: any[]; + + public first: number = 0; + + public page: number = 0; + + constructor(public el: ElementRef) {} + + ngAfterContentInit() { + this.templates.forEach((item) => { + switch(item.getType()) { + case 'item': + this.itemTemplate = item.template; + break; + + default: + this.itemTemplate = item.template; + break; + } + }); + } + + ngAfterViewInit() { + if(this.lazy) { + this.onLazyLoad.emit({ + first: this.first, + rows: this.rows + }); + } + } + + @Input() get value(): any[] { + return this._value; + } + + set value(val:any[]) { + this._value = val; + this.handleDataChange(); + } + + handleDataChange() { + if(this.paginator) { + this.updatePaginator(); + } + this.updateDataToRender(this.value); + } + + updatePaginator() { + //total records + this.totalRecords = this.lazy ? this.totalRecords : (this.value ? this.value.length: 0); + + //first + if(this.totalRecords && this.first >= this.totalRecords) { + let numberOfPages = Math.ceil(this.totalRecords/this.rows); + this.first = Math.max((numberOfPages-1) * this.rows, 0); + } + } + + paginate(event) { + this.first = event.first; + this.rows = event.rows; + + if(this.lazy) { + this.onLazyLoad.emit(this.createLazyLoadMetadata()); + } + else { + this.updateDataToRender(this.value); + } + + this.onPage.emit({ + first: this.first, + rows: this.rows + }); + } + + updateDataToRender(datasource) { + if(this.paginator && datasource) { + this.dataToRender = []; + let startIndex = this.lazy ? 0 : this.first; + for(let i = startIndex; i < (startIndex+ this.rows); i++) { + if(i >= datasource.length) { + break; + } + + this.dataToRender.push(datasource[i]); + } + } + else { + this.dataToRender = datasource; + } + } + + isEmpty() { + return !this.dataToRender||(this.dataToRender.length == 0); + } + + createLazyLoadMetadata(): any { + return { + first: this.first, + rows: this.rows + }; + } + + getBlockableElement(): HTMLElement { + return this.el.nativeElement.children[0]; + } +} + +@NgModule({ + imports: [CommonModule,SharedModule,PaginatorModule], + exports: [DataList,SharedModule], + declarations: [DataList] +}) +export class DataListModule { } diff --git a/src/app/components/datascroller/datascroller.css b/src/app/components/datascroller/datascroller.css new file mode 100644 index 00000000000..eefe766a8db --- /dev/null +++ b/src/app/components/datascroller/datascroller.css @@ -0,0 +1,28 @@ +.ui-datascroller { +} + +.ui-datascroller .ui-datascroller-header { + text-align: center; + padding: .5em .75em; + border-bottom: 0 none; +} + +.ui-datascroller .ui-datascroller-footer { + text-align: center; + padding: .25em .625em; + border-top: 0px none; +} + +.ui-datascroller .ui-datascroller-content { + padding: .25em .625em; +} + +.ui-datascroller-inline .ui-datascroller-content { + overflow: auto; +} + +.ui-datascroller .ui-datascroller-list { + list-style-type: none; + margin: 0; + padding: 0; +} \ No newline at end of file diff --git a/src/app/components/datascroller/datascroller.ts b/src/app/components/datascroller/datascroller.ts new file mode 100644 index 00000000000..88868ad6318 --- /dev/null +++ b/src/app/components/datascroller/datascroller.ts @@ -0,0 +1,200 @@ +import {NgModule,Component,ElementRef,AfterViewInit,AfterContentInit,OnDestroy,Input,Output,Renderer2,ViewChild,EventEmitter,ContentChild,ContentChildren,QueryList,TemplateRef} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {Header,Footer,PrimeTemplate,SharedModule} from '../common/shared'; +import {DomHandler} from '../dom/domhandler'; + +@Component({ + selector: 'p-dataScroller', + template: ` +
+
+ +
+
+
    +
  • + +
  • +
+
+ +
+ `, + providers: [DomHandler] +}) +export class DataScroller implements AfterViewInit,OnDestroy { + + @Input() rows: number; + + @Input() lazy: boolean; + + @Output() onLazyLoad: EventEmitter = new EventEmitter(); + + @Input() style: any; + + @Input() styleClass: string; + + @Input() buffer: number = 0.9; + + @Input() inline: boolean; + + @Input() scrollHeight: any; + + @Input() loader: any; + + @ViewChild('content') contentViewChild: ElementRef; + + @ContentChild(Header) header; + + @ContentChild(Footer) footer; + + @ContentChildren(PrimeTemplate) templates: QueryList; + + public _value: any[]; + + public itemTemplate: TemplateRef; + + public dataToRender: any[] = []; + + public first: number = 0; + + scrollFunction: any; + + contentElement: HTMLDivElement; + + constructor(public el: ElementRef, public renderer: Renderer2, public domHandler: DomHandler) {} + + ngAfterViewInit() { + if(this.lazy) { + this.load(); + } + + if(this.loader) { + this.scrollFunction = this.renderer.listen(this.loader, 'click', () => { + this.load(); + }); + } + else { + this.bindScrollListener(); + } + } + + ngAfterContentInit() { + this.templates.forEach((item) => { + switch(item.getType()) { + case 'item': + this.itemTemplate = item.template; + break; + + default: + this.itemTemplate = item.template; + break; + } + }); + } + + @Input() get value(): any[] { + return this._value; + } + + set value(val:any[]) { + this._value = val; + this.handleDataChange(); + } + + handleDataChange() { + if(this.lazy) + this.dataToRender = this.value; + else + this.load(); + } + + load() { + if(this.lazy) { + this.onLazyLoad.emit({ + first: this.first, + rows: this.rows + }); + + this.first = this.first + this.rows; + } + else { + if(this.value) { + for(let i = this.first; i < (this.first + this.rows); i++) { + if(i >= this.value.length) { + break; + } + + this.dataToRender.push(this.value[i]); + } + + this.first = this.first + this.rows; + } + } + } + + reset() { + this.first = 0; + this.dataToRender = []; + this.load(); + } + + isEmpty() { + return !this.dataToRender||(this.dataToRender.length == 0); + } + + createLazyLoadMetadata(): any { + return { + first: this.first, + rows: this.rows + }; + } + + bindScrollListener() { + if(this.inline) { + this.contentElement = this.contentViewChild.nativeElement; + + this.scrollFunction = this.renderer.listen(this.contentElement, 'scroll', () => { + let scrollTop = this.contentElement.scrollTop; + let scrollHeight = this.contentElement.scrollHeight; + let viewportHeight = this.contentElement.clientHeight; + + if((scrollTop >= ((scrollHeight * this.buffer) - (viewportHeight)))) { + this.load(); + } + }); + } + else { + this.scrollFunction = this.renderer.listen('window', 'scroll', () => { + let docBody = document.body; + let docElement = document.documentElement; + let scrollTop = (window.pageYOffset||document.documentElement.scrollTop); + let winHeight = docElement.clientHeight; + let docHeight = Math.max(docBody.scrollHeight, docBody.offsetHeight, winHeight, docElement.scrollHeight, docElement.offsetHeight); + + if(scrollTop >= ((docHeight * this.buffer) - winHeight)) { + this.load(); + } + }); + } + + } + + ngOnDestroy() { + //unbind + if(this.scrollFunction) { + this.scrollFunction(); + this.contentElement = null; + } + } +} + +@NgModule({ + imports: [CommonModule,SharedModule], + exports: [DataScroller,SharedModule], + declarations: [DataScroller] +}) +export class DataScrollerModule { } + diff --git a/src/app/components/datatable/datatable.css b/src/app/components/datatable/datatable.css new file mode 100644 index 00000000000..1157a01446e --- /dev/null +++ b/src/app/components/datatable/datatable.css @@ -0,0 +1,348 @@ +.ui-datatable { + position: relative; +} + +.ui-datatable table { + border-collapse:collapse; + width: 100%; + table-layout: fixed; +} + +.ui-datatable .ui-datatable-header, +.ui-datatable .ui-datatable-caption, +.ui-datatable .ui-datatable-footer { + text-align: center; + padding: .5em .75em; + box-sizing: border-box; +} + +.ui-datatable .ui-datatable-caption, +.ui-datatable .ui-datatable-header { + border-bottom: 0 none; +} + +.ui-datatable .ui-datatable-footer { + border-top: 0 none; +} + +.ui-datatable thead th, .ui-datatable tfoot td { + text-align: center; +} + +.ui-datatable thead tr { + border-width: 0; +} + +.ui-datatable .ui-datatable-thead > tr > th, +.ui-datatable .ui-datatable-tfoot > tr > td, +.ui-datatable .ui-datatable-data > tr > td { + border-color: inherit; + box-sizing: border-box; + padding: .25em .5em; + overflow: hidden; + border-width: 1px; + border-style: solid; +} + +.ui-datatable .ui-datatable-thead > tr > th, +.ui-datatable .ui-datatable-tfoot > tr > td { + font-weight: normal; +} + +.ui-datatable tbody { + outline: 0; +} + +.ui-datatable .ui-sortable-column { + cursor: pointer; +} + +.ui-datatable .ui-sortable-column-icon { + display: inline-block; + margin-left: .125em; +} + +.ui-datatable tr.ui-state-highlight { + cursor: pointer; +} + +/* Scrollable */ +.ui-datatable-scrollable-body { + overflow:auto; +} +.ui-datatable-scrollable-header { + overflow: hidden; +} + +.ui-datatable-scrollable .ui-datatable-scrollable-header, +.ui-datatable-scrollable .ui-datatable-scrollable-footer { + position: relative; + border: 0 none; +} + +.ui-datatable-scrollable .ui-datatable-scrollable-header td { + font-weight: normal; +} + +.ui-datatable .ui-datatable-scrollable-body { + min-height: 0%; +} + +.ui-datatable .ui-datatable-data tr.ui-state-hover, +.ui-datatable .ui-datatable-data tr.ui-state-highlight { + border-color: inherit; + font-weight: inherit; + cursor: pointer; +} + +.ui-datatable .ui-datatable-data tr.ui-rowgroup-header td a, +.ui-datatable .ui-datatable-data tr.ui-rowgroup-header td span.ui-rowgroup-header-name { + display: inline-block; + vertical-align: middle; +} + +.ui-datatable-scrollable-theadclone { + height: 0; +} + +.ui-datatable-scrollable-theadclone tr { + height: 0; +} + +.ui-datatable-scrollable-theadclone th.ui-state-default { + height: 0; + border-bottom-width: 0; + border-top-width: 0; + padding-top: 0; + padding-bottom: 0; + outline: 0 none; +} + +.ui-datatable-scrollable-theadclone th span.ui-column-title { + display: block; + height: 0; +} + +.ui-datatable .ui-paginator { + padding: .125em; + border-top: 0 none; +} + +.ui-datatable-rtl { + direction: rtl; +} + +.ui-datatable-rtl.ui-datatable thead th, +.ui-datatable-rtl.ui-datatable tfoot td { + text-align: right; +} + +/* Row Toggler */ +.ui-row-toggler { + cursor: pointer; +} + +/* Resizable */ +.ui-datatable .ui-column-resizer { + display: block; + position: absolute !important; + top: 0; + right: 0; + margin: 0; + width: .5em; + height: 100%; + padding: 0px; + cursor:col-resize; + border: 1px solid transparent; +} + +.ui-datatable .ui-column-resizer-helper { + width: 1px; + position: absolute; + z-index: 10; + display: none; +} + +.ui-datatable-resizable { + padding-bottom: 1px; /*fix for webkit overlow*/ + overflow:auto; +} + +.ui-datatable-resizable thead th, +.ui-datatable-resizable tbody td, +.ui-datatable-resizable tfoot td { + white-space: nowrap; +} + +.ui-datatable-resizable th.ui-resizable-column { + background-clip: padding-box; + position: relative; +} + +/** Reflow **/ +.ui-datatable-reflow .ui-datatable-data td .ui-column-title { + display: none; +} + +/* Filter */ +.ui-datatable .ui-column-filter { + display: block; + width: 100%; + box-sizing: border-box; + margin-top: .25em; +} + +/* Editing */ +.ui-datatable .ui-editable-column input { + width: 100%; + outline: 0; +} + +.ui-datatable .ui-datatable-data > tr > td.ui-editable-column { + padding: .5em; +} + +.ui-datatable .ui-editable-column .ui-cell-editor { + display: none; +} + +.ui-datatable .ui-datatable-data > tr > td.ui-editable-column.ui-cell-editing { + padding: 1px; +} + +.ui-datatable .ui-editable-column.ui-cell-editing .ui-cell-editor { + display: block; +} + +.ui-datatable .ui-editable-column.ui-cell-editing .ui-cell-data { + display: none; +} + +.ui-datatable-stacked thead th, +.ui-datatable-stacked tfoot td { + display: none !important; +} + +.ui-datatable.ui-datatable-stacked .ui-datatable-data > tr > td { + text-align: left; + display: block; + border: 0 none; + width: 100%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + float: left; + clear: left; +} + +.ui-datatable.ui-datatable-stacked .ui-datatable-data.ui-widget-content { + border: 0 none; +} + +.ui-datatable-stacked .ui-datatable-data tr.ui-widget-content { + border-left: 0 none; + border-right: 0 none; +} + +.ui-datatable-stacked .ui-datatable-data td .ui-column-title { + padding: .4em; + min-width: 30%; + display: inline-block; + margin: -.4em 1em -.4em -.4em; + font-weight: bold; +} + +.ui-datatable .ui-selection-column .ui-chkbox, +.ui-datatable .ui-selection-column .ui-radiobutton { + margin: 0; + display: block; +} + +.ui-datatable .ui-selection-column .ui-chkbox-box, +.ui-datatable .ui-selection-column .ui-radiobutton-box { + display: block; + box-sizing: border-box; + margin: 0; +} + +.ui-datatable-scrollable-wrapper { + position: relative; +} + +.ui-datatable-scrollable-view { + +} + +.ui-datatable-frozen-view .ui-datatable-scrollable-body { + overflow: hidden; +} + +.ui-datatable-unfrozen-view { + position: absolute; + top: 0px; +} + +.ui-datatable .ui-datatable-load-status { + width: 100%; + height: 100%; + top: 0px; + left: 0px; +} + +.ui-datatable .ui-datatable-virtual-table { + position: absolute; + top: 0px; + left: 0px; +} + +.ui-datatable .ui-datatable-loading { + position: absolute; + width: 100%; + height: 100%; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=20)"; + opacity: 0.2; + z-index: 1; +} + +.ui-datatable .ui-datatable-loading-content { + position: absolute; + left: 50%; + top: 25%; + z-index: 2; +} + +@media ( max-width: 35em ) { + .ui-datatable-reflow thead th, + .ui-datatable-reflow tfoot td { + display: none !important; + } + + .ui-datatable-reflow .ui-datatable-data > tr > td { + text-align: left; + display: block; + border: 0 none; + width: 100%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + float: left; + clear: left; + } + + .ui-datatable-reflow .ui-datatable-data.ui-widget-content { + border: 0 none; + } + + .ui-datatable-reflow .ui-datatable-data tr.ui-widget-content { + border-left: 0 none; + border-right: 0 none; + } + + .ui-datatable-reflow .ui-datatable-data td .ui-column-title { + padding: .4em; + min-width: 30%; + display: inline-block; + margin: -.4em 1em -.4em -.4em; + font-weight: bold; + } +} \ No newline at end of file diff --git a/src/app/components/datatable/datatable.ts b/src/app/components/datatable/datatable.ts new file mode 100644 index 00000000000..6e83aaf1199 --- /dev/null +++ b/src/app/components/datatable/datatable.ts @@ -0,0 +1,2144 @@ +import {NgModule,Component,ElementRef,AfterContentInit,AfterViewInit,AfterViewChecked,OnInit,OnDestroy,Input,ViewContainerRef,ViewChild, + Output,SimpleChange,EventEmitter,ContentChild,ContentChildren,Renderer2,QueryList,TemplateRef,ChangeDetectorRef,Inject,forwardRef} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms' +import {SharedModule} from '../common/shared'; +import {PaginatorModule} from '../paginator/paginator'; +import {Column,Header,Footer,HeaderColumnGroup,FooterColumnGroup,PrimeTemplate} from '../common/shared'; +import {LazyLoadEvent} from '../common/lazyloadevent'; +import {FilterMetadata} from '../common/filtermetadata'; +import {SortMeta} from '../common/sortmeta'; +import {DomHandler} from '../dom/domhandler'; +import {ObjectUtils} from '../utils/ObjectUtils'; +import {Subscription} from 'rxjs/Subscription'; +import {BlockableUI} from '../common/blockableui'; + +@Component({ + selector: 'p-dtRadioButton', + template: ` +
+
+ +
+
+ +
+
+ ` +}) +export class DTRadioButton { + + @Input() checked: boolean; + + @Output() onClick: EventEmitter = new EventEmitter(); + + public hover: boolean; + + handleClick(event) { + this.onClick.emit(event); + } +} + +@Component({ + selector: 'p-dtCheckbox', + template: ` +
+
+ +
+
+ +
+
+ ` +}) +export class DTCheckbox { + + @Input() checked: boolean; + + @Input() disabled: boolean; + + @Output() onChange: EventEmitter = new EventEmitter(); + + public hover: boolean; + + handleClick(event) { + if(!this.disabled) { + this.onChange.emit({originalEvent: event, checked: !this.checked}); + } + } +} + +@Component({ + selector: 'p-rowExpansionLoader', + template: `` +}) +export class RowExpansionLoader { + + @Input() template: TemplateRef; + + @Input() rowData: any; + + constructor(public viewContainer: ViewContainerRef) {} + + ngOnInit() { + let view = this.viewContainer.createEmbeddedView(this.template, { + '\$implicit': this.rowData + }); + } +} + +@Component({ + selector: '[pColumnHeaders]', + template: ` + + + + {{col.header}} + + + + + + + + + + ` +}) +export class ColumnHeaders { + + constructor(@Inject(forwardRef(() => DataTable)) public dt:DataTable) {} + + @Input("pColumnHeaders") columns: Column[]; +} + +@Component({ + selector: '[pColumnFooters]', + template: ` + + {{col.footer}} + + + + + ` +}) +export class ColumnFooters { + + constructor(@Inject(forwardRef(() => DataTable)) public dt:DataTable) {} + + @Input("pColumnFooters") columns: Column[]; +} + +@Component({ + selector: '[pTableBody]', + template: ` + + + + + + + + + + + + + + + {{col.header}} + {{dt.resolveFieldData(rowData,col.field)}} + + + +
+ + + + +
+ + + + + + +
+ + + + + + + + + +
+ + + {{dt.emptyMessage}} + + ` +}) +export class TableBody { + + constructor(@Inject(forwardRef(() => DataTable)) public dt:DataTable) {} + + @Input("pTableBody") columns: Column[]; + + visibleColumns() { + return this.columns ? this.columns.filter(c => !c.hidden): []; + } +} + +@Component({ + selector: '[pScrollableView]', + template: ` +
+
+ + + + + + + +
+
+
+
+
+ + + + + +
+
+
+ + ` +}) +export class ScrollableView implements AfterViewInit,AfterViewChecked,OnDestroy { + + constructor(@Inject(forwardRef(() => DataTable)) public dt:DataTable, public domHandler: DomHandler, public el: ElementRef, public renderer: Renderer2) {} + + @Input("pScrollableView") columns: Column[]; + + @ViewChild('scrollHeader') scrollHeaderViewChild: ElementRef; + + @ViewChild('scrollHeaderBox') scrollHeaderBoxViewChild: ElementRef; + + @ViewChild('scrollBody') scrollBodyViewChild: ElementRef; + + @ViewChild('scrollTable') scrollTableViewChild: ElementRef; + + @ViewChild('scrollTableWrapper') scrollTableWrapperViewChild: ElementRef; + + @ViewChild('scrollFooter') scrollFooterViewChild: ElementRef; + + @ViewChild('scrollFooterBox') scrollFooterBoxViewChild: ElementRef; + + @Input() frozen: boolean; + + @Input() width: string; + + @Input() virtualScroll: boolean; + + @Output() onVirtualScroll: EventEmitter = new EventEmitter(); + + @Input() loading: boolean; + + public scrollBody: HTMLDivElement; + + public scrollHeader: HTMLDivElement; + + public scrollHeaderBox: HTMLDivElement; + + public scrollTable: HTMLDivElement; + + public scrollTableWrapper: HTMLDivElement; + + public scrollFooter: HTMLDivElement; + + public scrollFooterBox: HTMLDivElement; + + public bodyScrollListener: Function; + + public headerScrollListener: Function; + + public scrollBodyMouseWheelListener: Function; + + public scrollFunction: Function; + + public rowHeight: number; + + public scrollTimeout: any; + + ngAfterViewInit() { + this.initScrolling(); + } + + ngAfterViewChecked() { + if(this.virtualScroll && !this.rowHeight) { + let row = this.domHandler.findSingle(this.scrollTable, 'tr.ui-widget-content'); + if(row) { + this.rowHeight = this.domHandler.getOuterHeight(row); + } + } + + if(!this.frozen) { + this.alignScrollBar(); + } + } + + initScrolling() { + this.scrollHeader = this.scrollHeaderViewChild.nativeElement; + this.scrollHeaderBox = this.scrollHeaderBoxViewChild.nativeElement; + this.scrollBody = this.scrollBodyViewChild.nativeElement; + this.scrollTable = this.scrollTableViewChild.nativeElement; + this.scrollTableWrapper = this.scrollTableWrapperViewChild.nativeElement; + this.scrollFooter = this.scrollFooterViewChild ? this.scrollFooterViewChild.nativeElement : null; + this.scrollFooterBox = this.scrollFooterBoxViewChild ? this.scrollFooterBoxViewChild.nativeElement : null; + + if(!this.frozen) { + let frozenView = this.el.nativeElement.previousElementSibling; + if(frozenView) { + var frozenScrollBody = this.domHandler.findSingle(frozenView, '.ui-datatable-scrollable-body'); + } + + this.bodyScrollListener = this.renderer.listen(this.scrollBody, 'scroll', (event) => { + this.scrollHeaderBox.style.marginLeft = -1 * this.scrollBody.scrollLeft + 'px'; + if(this.scrollFooterBox) { + this.scrollFooterBox.style.marginLeft = -1 * this.scrollBody.scrollLeft + 'px'; + } + if(frozenScrollBody) { + frozenScrollBody.scrollTop = this.scrollBody.scrollTop; + } + + if(this.virtualScroll) { + clearTimeout(this.scrollTimeout); + this.scrollTimeout = setTimeout(() => { + let viewport = this.domHandler.getOuterHeight(this.scrollBody); + let tableHeight = this.domHandler.getOuterHeight(this.scrollTable); + let pageHeight = this.rowHeight * this.dt.rows; + let virtualTableHeight = parseFloat(this.virtualTableHeight); + let pageCount = (virtualTableHeight / pageHeight)||1; + + if(this.scrollBody.scrollTop + viewport > parseFloat(this.scrollTable.style.top) + tableHeight || this.scrollBody.scrollTop < parseFloat(this.scrollTable.style.top)) { + let page = Math.floor((this.scrollBody.scrollTop * pageCount) / (this.scrollBody.scrollHeight)) + 1; + this.onVirtualScroll.emit({ + page: page + }); + this.scrollTable.style.top = ((page - 1) * pageHeight) + 'px'; + } + }, 200); + } + }); + + //to trigger change detection + this.scrollBodyMouseWheelListener = this.renderer.listen(this.scrollBody, 'mousewheel', (event) => {}); + + this.headerScrollListener = this.renderer.listen(this.scrollHeader, 'scroll', () => { + this.scrollHeader.scrollLeft = 0; + }); + } + + if(!this.frozen) + this.alignScrollBar(); + else + this.scrollBody.style.paddingBottom = this.domHandler.calculateScrollbarWidth() + 'px'; + } + + hasVerticalOverflow() { + return this.domHandler.getOuterHeight(this.scrollTable) > this.domHandler.getOuterHeight(this.scrollBody); + } + + alignScrollBar() { + let scrollBarWidth = this.hasVerticalOverflow() ? this.domHandler.calculateScrollbarWidth() : 0; + + this.scrollHeaderBox.style.marginRight = scrollBarWidth + 'px'; + if(this.scrollFooterBox) { + this.scrollFooterBox.style.marginRight = scrollBarWidth + 'px'; + } + } + + get virtualTableHeight(): string { + let totalRecords = this.dt.lazy ? this.dt.totalRecords : (this.dt.value ? this.dt.value.length: 0); + return (totalRecords * this.rowHeight) + 'px'; + } + + ngOnDestroy() { + if(this.bodyScrollListener) { + this.bodyScrollListener(); + } + + if(this.scrollBodyMouseWheelListener) { + this.scrollBodyMouseWheelListener(); + } + + if(this.headerScrollListener) { + this.headerScrollListener(); + } + } +} + +@Component({ + selector: 'p-dataTable', + template: ` +
+
+
+ +
+
+ +
+ +
+ + + + + + + + + + + + + + +
+
+ + +
+
+
+
+
+ + + + + + + +
+ `, + providers: [DomHandler,ObjectUtils] +}) +export class DataTable implements AfterViewChecked,AfterViewInit,AfterContentInit,OnInit,OnDestroy,BlockableUI { + + @Input() paginator: boolean; + + @Input() rows: number; + + @Input() totalRecords: number; + + @Input() pageLinks: number = 5; + + @Input() rowsPerPageOptions: number[]; + + @Input() responsive: boolean; + + @Input() stacked: boolean; + + @Input() selectionMode: string; + + @Input() selection: any; + + @Output() selectionChange: EventEmitter = new EventEmitter(); + + @Input() editable: boolean; + + @Output() onRowClick: EventEmitter = new EventEmitter(); + + @Output() onRowSelect: EventEmitter = new EventEmitter(); + + @Output() onRowUnselect: EventEmitter = new EventEmitter(); + + @Output() onRowDblclick: EventEmitter = new EventEmitter(); + + @Output() onHeaderCheckboxToggle: EventEmitter = new EventEmitter(); + + @Input() headerCheckboxToggleAllPages: boolean; + + @Output() onContextMenuSelect: EventEmitter = new EventEmitter(); + + @Input() filterDelay: number = 300; + + @Input() lazy: boolean; + + @Output() onLazyLoad: EventEmitter = new EventEmitter(); + + @Input() resizableColumns: boolean; + + @Input() columnResizeMode: string = 'fit'; + + @Output() onColResize: EventEmitter = new EventEmitter(); + + @Input() reorderableColumns: boolean; + + @Output() onColReorder: EventEmitter = new EventEmitter(); + + @Input() scrollable: boolean; + + @Input() virtualScroll: boolean; + + @Input() scrollHeight: any; + + @Input() scrollWidth: any; + + @Input() frozenWidth: any; + + @Input() unfrozenWidth: any; + + @Input() style: any; + + @Input() styleClass: string; + + @Input() tableStyle: any; + + @Input() tableStyleClass: string; + + @Input() globalFilter: any; + + @Input() sortMode: string = 'single'; + + @Input() sortField: string; + + @Input() sortOrder: number = 1; + + @Input() groupField: string; + + @Input() multiSortMeta: SortMeta[]; + + @Input() contextMenu: any; + + @Input() csvSeparator: string = ','; + + @Input() exportFilename: string = 'download'; + + @Input() emptyMessage: string = 'No records found'; + + @Input() paginatorPosition: string = 'bottom'; + + @Input() alwaysShowPaginator: boolean = true; + + @Input() metaKeySelection: boolean = true; + + @Input() rowTrackBy: Function = (index: number, item: any) => item; + + @Output() onEditInit: EventEmitter = new EventEmitter(); + + @Output() onEditComplete: EventEmitter = new EventEmitter(); + + @Output() onEdit: EventEmitter = new EventEmitter(); + + @Output() onEditCancel: EventEmitter = new EventEmitter(); + + @Output() onPage: EventEmitter = new EventEmitter(); + + @Output() onSort: EventEmitter = new EventEmitter(); + + @Output() onFilter: EventEmitter = new EventEmitter(); + + @ContentChild(Header) header; + + @ContentChild(Footer) footer; + + @Input() expandableRows: boolean; + + @Input() expandedRows: any[]; + + @Input() expandableRowGroups: boolean; + + @Input() rowExpandMode: string = 'multiple'; + + @Input() public expandedRowsGroups: any[]; + + @Input() tabindex: number = 1; + + @Input() rowStyleClass: Function; + + @Input() rowGroupMode: string; + + @Input() sortableRowGroup: boolean = true; + + @Input() sortFile: string; + + @Input() rowHover: boolean; + + @Input() first: number = 0; + + @Input() public filters: {[s: string]: FilterMetadata;} = {}; + + @Input() dataKey: string; + + @Input() loading: boolean; + + @Output() onRowExpand: EventEmitter = new EventEmitter(); + + @Output() onRowCollapse: EventEmitter = new EventEmitter(); + + @Output() onRowGroupExpand: EventEmitter = new EventEmitter(); + + @Output() onRowGroupCollapse: EventEmitter = new EventEmitter(); + + @ContentChildren(PrimeTemplate) templates: QueryList; + + @ContentChildren(Column) cols: QueryList; + + @ContentChild(HeaderColumnGroup) headerColumnGroup: HeaderColumnGroup; + + @ContentChild(FooterColumnGroup) footerColumnGroup: FooterColumnGroup; + + public _value: any[]; + + public dataToRender: any[]; + + public page: number = 0; + + public filterTimeout: any; + + public filteredValue: any[]; + + public columns: Column[]; + + public frozenColumns: Column[]; + + public scrollableColumns: Column[]; + + public columnsChanged: boolean = false; + + public sortColumn: Column; + + public columnResizing: boolean; + + public lastResizerHelperX: number; + + public documentClickListener: Function; + + public documentColumnResizeListener: Function; + + public documentColumnResizeEndListener: Function; + + public resizerHelper: any; + + public resizeColumn: any; + + public reorderIndicatorUp: any; + + public reorderIndicatorDown: any; + + public draggedColumn: any; + + public dropPosition: number; + + public tbody: any; + + public rowTouched: boolean; + + public rowGroupToggleClick: boolean; + + public editingCell: any; + + public stopFilterPropagation: boolean; + + public rowGroupMetadata: any; + + public rowGroupHeaderTemplate: TemplateRef; + + public rowGroupFooterTemplate: TemplateRef; + + public rowExpansionTemplate: TemplateRef; + + public scrollBarWidth: number; + + public editorClick: boolean; + + globalFilterFunction: any; + + columnsSubscription: Subscription; + + constructor(public el: ElementRef, public domHandler: DomHandler, + public renderer: Renderer2, public changeDetector: ChangeDetectorRef, public objectUtils: ObjectUtils) { + } + + ngOnInit() { + if(this.lazy) { + this.onLazyLoad.emit(this.createLazyLoadMetadata()); + } + } + + ngAfterContentInit() { + this.initColumns(); + + this.columnsSubscription = this.cols.changes.subscribe(_ => { + this.initColumns(); + this.changeDetector.markForCheck(); + }); + + this.templates.forEach((item) => { + switch(item.getType()) { + case 'rowexpansion': + this.rowExpansionTemplate = item.template; + break; + + case 'rowgroupheader': + this.rowGroupHeaderTemplate = item.template; + break; + + case 'rowgroupfooter': + this.rowGroupFooterTemplate = item.template; + break; + } + }); + } + + ngAfterViewChecked() { + if(this.columnsChanged && this.el.nativeElement.offsetParent) { + if(this.resizableColumns) { + this.initResizableColumns(); + } + + if(this.reorderableColumns) { + this.initColumnReordering(); + } + + this.columnsChanged = false; + } + } + + ngAfterViewInit() { + if(this.globalFilter) { + this.globalFilterFunction = this.renderer.listen(this.globalFilter, 'keyup', () => { + this.filterTimeout = setTimeout(() => { + this._filter(); + this.filterTimeout = null; + }, this.filterDelay); + }); + } + + if(this.editable) { + this.documentClickListener = this.renderer.listen('document', 'click', (event) => { + if(!this.editorClick) { + this.closeCell(); + } + this.editorClick = false; + }); + } + } + + @Input() get value(): any[] { + return this._value; + } + + set value(val:any[]) { + this._value = val ? [...val] : null; + this.handleDataChange(); + } + + handleDataChange() { + if(this.paginator) { + this.updatePaginator(); + } + + if(!this.lazy) { + if(this.hasFilter()) { + this._filter(); + } + + if(this.sortField||this.multiSortMeta) { + if(!this.sortColumn && this.columns) { + this.sortColumn = this.columns.find(col => col.field === this.sortField && col.sortable === 'custom'); + } + + if(this.sortMode == 'single') + this.sortSingle(); + else if(this.sortMode == 'multiple') + this.sortMultiple(); + } + } + + this.updateDataToRender(this.filteredValue||this.value); + } + + initColumns(): void { + this.columns = this.cols.toArray(); + + if(this.scrollable) { + this.scrollableColumns = []; + this.cols.forEach((col) => { + if(col.frozen) { + this.frozenColumns = this.frozenColumns||[]; + this.frozenColumns.push(col); + } + else { + this.scrollableColumns.push(col); + } + }); + } + + this.columnsChanged = true; + } + + resolveFieldData(data: any, field: string): any { + if(data && field) { + if(field.indexOf('.') == -1) { + return data[field]; + } + else { + let fields: string[] = field.split('.'); + let value = data; + for(var i = 0, len = fields.length; i < len; ++i) { + if (value == null) { + return null; + } + value = value[fields[i]]; + } + return value; + } + } + else { + return null; + } + } + + updateRowGroupMetadata() { + this.rowGroupMetadata = {}; + if(this.dataToRender) { + for(let i = 0; i < this.dataToRender.length; i++) { + let rowData = this.dataToRender[i]; + let group = this.resolveFieldData(rowData, this.sortField); + if(i == 0) { + this.rowGroupMetadata[group] = {index:0, size: 1}; + } + else { + let previousRowData = this.dataToRender[i-1]; + let previousRowGroup = this.resolveFieldData(previousRowData, this.sortField); + if(group === previousRowGroup) { + this.rowGroupMetadata[group].size++; + } + else { + this.rowGroupMetadata[group] = {index:i, size: 1}; + } + } + } + } + } + + updatePaginator() { + //total records + this.totalRecords = this.lazy ? this.totalRecords : (this.value ? this.value.length: 0); + + //first + if(this.totalRecords && this.first >= this.totalRecords) { + let numberOfPages = Math.ceil(this.totalRecords/this.rows); + this.first = Math.max((numberOfPages-1) * this.rows, 0); + } + } + + paginate(event) { + this.first = event.first; + this.rows = event.rows; + + if(this.lazy) { + this.stopFilterPropagation = true; + this.onLazyLoad.emit(this.createLazyLoadMetadata()); + } + else { + this.updateDataToRender(this.filteredValue||this.value); + } + + this.onPage.emit({ + first: this.first, + rows: this.rows + }); + } + + updateDataToRender(datasource) { + if((this.paginator || this.virtualScroll) && datasource) { + this.dataToRender = []; + let startIndex: number = this.lazy ? 0 : this.first; + let endIndex: number = this.virtualScroll ? this.first + this.rows * 2 : startIndex + this.rows; + + for(let i = startIndex; i < endIndex; i++) { + if(i >= datasource.length) { + break; + } + + this.dataToRender.push(datasource[i]); + } + } + else { + this.dataToRender = datasource; + } + + if(this.rowGroupMode) { + this.updateRowGroupMetadata(); + } + } + + onVirtualScroll(event) { + this.first = (event.page - 1) * this.rows; + + if(this.lazy) { + this.stopFilterPropagation = true; + this.onLazyLoad.emit(this.createLazyLoadMetadata()); + } + else { + this.updateDataToRender(this.filteredValue||this.value); + } + } + + onHeaderKeydown(event, column: Column) { + if(event.keyCode == 13) { + this.sort(event, column); + event.preventDefault(); + } + } + + onHeaderMousedown(event, header: any) { + if(this.reorderableColumns) { + if(event.target.nodeName !== 'INPUT') { + header.draggable = true; + } else if(event.target.nodeName === 'INPUT') { + header.draggable = false; + } + } + } + + sort(event, column: Column) { + if(!column.sortable) { + return; + } + + let targetNode = event.target.nodeName; + if(targetNode == 'TH' || (targetNode == 'SPAN' && !this.domHandler.hasClass(event.target, 'ui-c'))) { + let columnSortField = column.sortField||column.field; + this.sortOrder = (this.sortField === columnSortField) ? this.sortOrder * -1 : 1; + this.sortField = columnSortField; + this.sortColumn = column; + let metaKey = event.metaKey||event.ctrlKey; + + if(this.sortMode == 'multiple') { + if(!this.multiSortMeta||!metaKey) { + this.multiSortMeta = []; + } + + this.addSortMeta({field: this.sortField, order: this.sortOrder}); + } + + if(this.lazy) { + this.first = 0; + this.stopFilterPropagation = true; + this.onLazyLoad.emit(this.createLazyLoadMetadata()); + } + else { + if(this.sortMode == 'multiple') + this.sortMultiple(); + else + this.sortSingle(); + } + + this.onSort.emit({ + field: this.sortField, + order: this.sortOrder, + multisortmeta: this.multiSortMeta + }); + } + + this.updateDataToRender(this.filteredValue||this.value); + } + + sortSingle() { + if(this.value) { + if(this.sortColumn && this.sortColumn.sortable === 'custom') { + this.sortColumn.sortFunction.emit({ + field: this.sortField, + order: this.sortOrder + }); + } + else { + this.value.sort((data1, data2) => { + let value1 = this.resolveFieldData(data1, this.sortField); + let value2 = this.resolveFieldData(data2, this.sortField); + let result = null; + + if (value1 == null && value2 != null) + result = -1; + else if (value1 != null && value2 == null) + result = 1; + else if (value1 == null && value2 == null) + result = 0; + else if (typeof value1 === 'string' && typeof value2 === 'string') + result = value1.localeCompare(value2); + else + result = (value1 < value2) ? -1 : (value1 > value2) ? 1 : 0; + + return (this.sortOrder * result); + }); + } + + this.first = 0; + + if(this.hasFilter()) { + this._filter(); + } + } + } + + sortMultiple() { + if(this.value) { + this.value.sort((data1,data2) => { + return this.multisortField(data1, data2, this.multiSortMeta, 0); + }); + + if(this.hasFilter()) { + this._filter(); + } + } + } + + multisortField(data1,data2,multiSortMeta,index) { + let value1 = this.resolveFieldData(data1, multiSortMeta[index].field); + let value2 = this.resolveFieldData(data2, multiSortMeta[index].field); + let result = null; + + if (typeof value1 == 'string' || value1 instanceof String) { + if (value1.localeCompare && (value1 != value2)) { + return (multiSortMeta[index].order * value1.localeCompare(value2)); + } + } + else { + result = (value1 < value2) ? -1 : 1; + } + + if(value1 == value2) { + return (multiSortMeta.length - 1) > (index) ? (this.multisortField(data1, data2, multiSortMeta, index + 1)) : 0; + } + + return (multiSortMeta[index].order * result); + } + + addSortMeta(meta) { + var index = -1; + for(var i = 0; i < this.multiSortMeta.length; i++) { + if(this.multiSortMeta[i].field === meta.field) { + index = i; + break; + } + } + + if(index >= 0) + this.multiSortMeta[index] = meta; + else + this.multiSortMeta.push(meta); + } + + isSorted(column: Column) { + if(!column.sortable) { + return false; + } + + let columnSortField = column.sortField||column.field; + + if(this.sortMode === 'single') { + return (this.sortField && columnSortField === this.sortField); + } + else if(this.sortMode === 'multiple') { + let sorted = false; + if(this.multiSortMeta) { + for(let i = 0; i < this.multiSortMeta.length; i++) { + if(this.multiSortMeta[i].field == columnSortField) { + sorted = true; + break; + } + } + } + return sorted; + } + } + + getSortOrder(column: Column) { + let order = 0; + let columnSortField = column.sortField||column.field; + + if(this.sortMode === 'single') { + if(this.sortField && columnSortField === this.sortField) { + order = this.sortOrder; + } + } + else if(this.sortMode === 'multiple') { + if(this.multiSortMeta) { + for(let i = 0; i < this.multiSortMeta.length; i++) { + if(this.multiSortMeta[i].field == columnSortField) { + order = this.multiSortMeta[i].order; + break; + } + } + } + } + return order; + } + + onRowGroupClick(event) { + if(this.rowGroupToggleClick) { + this.rowGroupToggleClick = false; + return; + } + + if(this.sortableRowGroup) { + let targetNode = event.target.nodeName; + if((targetNode == 'TD' || (targetNode == 'SPAN' && !this.domHandler.hasClass(event.target, 'ui-c')))) { + if(this.sortField != this.groupField) { + this.sortField = this.groupField; + this.sortSingle(); + } + else { + this.sortOrder = -1 * this.sortOrder; + this.sortSingle(); + } + } + } + } + + handleRowClick(event, rowData) { + let targetNode = event.target.nodeName; + if(targetNode == 'TD' || (targetNode == 'SPAN' && !this.domHandler.hasClass(event.target, 'ui-c'))) { + this.onRowClick.next({originalEvent: event, data: rowData}); + + if(!this.selectionMode) { + return; + } + + let selected = this.isSelected(rowData); + let metaSelection = this.rowTouched ? false : this.metaKeySelection; + + if(metaSelection) { + let metaKey = event.metaKey||event.ctrlKey; + + if(selected && metaKey) { + if(this.isSingleSelectionMode()) { + this.selection = null; + this.selectionChange.emit(null); + } + else { + let selectionIndex = this.findIndexInSelection(rowData); + this.selection = this.selection.filter((val,i) => i!=selectionIndex); + this.selectionChange.emit(this.selection); + } + + this.onRowUnselect.emit({originalEvent: event, data: rowData, type: 'row'}); + } + else { + if(this.isSingleSelectionMode()) { + this.selection = rowData; + this.selectionChange.emit(rowData); + } + else if(this.isMultipleSelectionMode()) { + if(metaKey) + this.selection = this.selection||[]; + else + this.selection = []; + + this.selection = [...this.selection,rowData]; + this.selectionChange.emit(this.selection); + } + + this.onRowSelect.emit({originalEvent: event, data: rowData, type: 'row'}); + } + } + else { + if(this.isSingleSelectionMode()) { + if(selected) { + this.selection = null; + this.onRowUnselect.emit({originalEvent: event, data: rowData, type: 'row'}); + } + else { + this.selection = rowData; + this.onRowSelect.emit({originalEvent: event, data: rowData, type: 'row'}); + } + } + else { + if(selected) { + let selectionIndex = this.findIndexInSelection(rowData); + this.selection = this.selection.filter((val,i) => i!=selectionIndex); + this.onRowUnselect.emit({originalEvent: event, data: rowData, type: 'row'}); + } + else { + this.selection = [...this.selection||[],rowData]; + this.onRowSelect.emit({originalEvent: event, data: rowData, type: 'row'}); + } + } + + this.selectionChange.emit(this.selection); + } + } + + this.rowTouched = false; + } + + handleRowTouchEnd(event) { + this.rowTouched = true; + } + + selectRowWithRadio(event, rowData:any) { + if(this.selection != rowData) { + this.selection = rowData; + this.selectionChange.emit(this.selection); + this.onRowSelect.emit({originalEvent: event, data: rowData, type: 'radiobutton'}); + } + } + + toggleRowWithCheckbox(event,rowData) { + let selectionIndex = this.findIndexInSelection(rowData); + this.selection = this.selection||[]; + + if(selectionIndex != -1) { + this.selection = this.selection.filter((val,i) => i!=selectionIndex); + this.onRowUnselect.emit({originalEvent: event, data: rowData, type: 'checkbox'}); + } + + else { + this.selection = [...this.selection,rowData]; + this.onRowSelect.emit({originalEvent: event, data: rowData, type: 'checkbox'}); + } + + this.selectionChange.emit(this.selection); + } + + toggleRowsWithCheckbox(event) { + if(event.checked) + this.selection = this.headerCheckboxToggleAllPages ? this.value.slice() : this.dataToRender.slice(); + else + this.selection = []; + + this.selectionChange.emit(this.selection); + + this.onHeaderCheckboxToggle.emit({originalEvent: event, checked: event.checked}); + } + + onRowRightClick(event, rowData) { + if(this.contextMenu) { + let selectionIndex = this.findIndexInSelection(rowData); + let selected = selectionIndex != -1; + + if(!selected) { + if(this.isSingleSelectionMode()) { + this.selection = rowData; + this.selectionChange.emit(rowData); + } + else if(this.isMultipleSelectionMode()) { + this.selection = [rowData]; + this.selectionChange.emit(this.selection); + } + } + + this.contextMenu.show(event); + this.onContextMenuSelect.emit({originalEvent: event, data: rowData}); + } + } + + rowDblclick(event, rowData) { + this.onRowDblclick.emit({originalEvent: event, data: rowData}); + } + + isSingleSelectionMode() { + return this.selectionMode === 'single'; + } + + isMultipleSelectionMode() { + return this.selectionMode === 'multiple'; + } + + findIndexInSelection(rowData: any) { + let index: number = -1; + if(this.selection) { + for(let i = 0; i < this.selection.length; i++) { + if(this.objectUtils.equals(rowData, this.selection[i], this.dataKey)) { + index = i; + break; + } + } + } + + return index; + } + + isSelected(rowData) { + return ((rowData && this.objectUtils.equals(rowData, this.selection, this.dataKey)) || this.findIndexInSelection(rowData) != -1); + } + + get allSelected() { + if(this.headerCheckboxToggleAllPages) { + return this.selection && this.value && this.selection.length === this.value.length; + } + else { + let val = true; + if(this.dataToRender && this.selection && (this.dataToRender.length <= this.selection.length)) { + for(let data of this.dataToRender) { + if(!this.isSelected(data)) { + val = false; + break; + } + } + } + else { + val = false; + } + return val; + } + } + + onFilterKeyup(value, field, matchMode) { + if(this.filterTimeout) { + clearTimeout(this.filterTimeout); + } + + this.filterTimeout = setTimeout(() => { + this.filter(value, field, matchMode); + this.filterTimeout = null; + }, this.filterDelay); + } + + filter(value, field, matchMode) { + if(!this.isFilterBlank(value)) + this.filters[field] = {value: value, matchMode: matchMode}; + else if(this.filters[field]) + delete this.filters[field]; + + this._filter(); + } + + isFilterBlank(filter: any): boolean { + if(filter !== null && filter !== undefined) { + if((typeof filter === 'string' && filter.trim().length == 0) || (filter instanceof Array && filter.length == 0)) + return true; + else + return false; + } + return true; + } + + _filter() { + this.first = 0; + + if(this.lazy) { + this.stopFilterPropagation = true; + this.onLazyLoad.emit(this.createLazyLoadMetadata()); + } + else { + this.filteredValue = []; + + for(let i = 0; i < this.value.length; i++) { + let localMatch = true; + let globalMatch = false; + + for(let j = 0; j < this.columns.length; j++) { + let col = this.columns[j], + filterMeta = this.filters[col.field]; + + //local + if(filterMeta) { + let filterValue = filterMeta.value, + filterField = col.field, + filterMatchMode = filterMeta.matchMode||'startsWith', + dataFieldValue = this.resolveFieldData(this.value[i], filterField); + let filterConstraint = this.filterConstraints[filterMatchMode]; + + if(!filterConstraint(dataFieldValue, filterValue)) { + localMatch = false; + } + + if(!localMatch) { + break; + } + } + + //global + if(this.globalFilter && !globalMatch) { + globalMatch = this.filterConstraints['contains'](this.resolveFieldData(this.value[i], col.field), this.globalFilter.value); + } + } + + let matches = localMatch; + if(this.globalFilter) { + matches = localMatch&&globalMatch; + } + + if(matches) { + this.filteredValue.push(this.value[i]); + } + } + + if(this.filteredValue.length === this.value.length) { + this.filteredValue = null; + } + + if(this.paginator) { + this.totalRecords = this.filteredValue ? this.filteredValue.length: this.value ? this.value.length: 0; + } + + this.updateDataToRender(this.filteredValue||this.value); + } + + this.onFilter.emit({ + filters: this.filters, + filteredValue: this.filteredValue||this.value + }); + } + + hasFilter() { + let empty = true; + for(let prop in this.filters) { + if(this.filters.hasOwnProperty(prop)) { + empty = false; + break; + } + } + + return !empty || (this.globalFilter && this.globalFilter.value && this.globalFilter.value.trim().length); + } + + onFilterInputClick(event) { + event.stopPropagation(); + } + + filterConstraints = { + + startsWith(value, filter): boolean { + if(filter === undefined || filter === null || filter.trim() === '') { + return true; + } + + if(value === undefined || value === null) { + return false; + } + + let filterValue = filter.toLowerCase(); + return value.toString().toLowerCase().slice(0, filterValue.length) === filterValue; + }, + + contains(value, filter): boolean { + if(filter === undefined || filter === null || (typeof filter === 'string' && filter.trim() === '')) { + return true; + } + + if(value === undefined || value === null) { + return false; + } + + return value.toString().toLowerCase().indexOf(filter.toLowerCase()) !== -1; + }, + + endsWith(value, filter): boolean { + if(filter === undefined || filter === null || filter.trim() === '') { + return true; + } + + if(value === undefined || value === null) { + return false; + } + + let filterValue = filter.toString().toLowerCase(); + return value.toString().toLowerCase().indexOf(filterValue, value.toString().length - filterValue.length) !== -1; + }, + + equals(value, filter): boolean { + if(filter === undefined || filter === null || (typeof filter === 'string' && filter.trim() === '')) { + return true; + } + + if(value === undefined || value === null) { + return false; + } + + return value.toString().toLowerCase() == filter.toString().toLowerCase(); + }, + + notEquals(value, filter): boolean { + return !this.equals(value, filter); + }, + + in(value, filter: any[]): boolean { + if(filter === undefined || filter === null || filter.length === 0) { + return true; + } + + if(value === undefined || value === null) { + return false; + } + + for(let i = 0; i < filter.length; i++) { + if(filter[i] === value) + return true; + } + + return false; + } + } + + switchCellToEditMode(cell: any, column: Column, rowData: any) { + if(!this.selectionMode && this.editable && column.editable) { + this.editorClick = true; + + if(cell != this.editingCell) { + if(this.editingCell && this.domHandler.find(this.editingCell, '.ng-invalid.ng-dirty').length == 0) { + this.domHandler.removeClass(this.editingCell, 'ui-cell-editing'); + } + + this.editingCell = cell; + this.onEditInit.emit({column: column, data: rowData}); + this.domHandler.addClass(cell, 'ui-cell-editing'); + let focusable = this.domHandler.findSingle(cell, '.ui-cell-editor input'); + if(focusable) { + setTimeout(() => this.domHandler.invokeElementMethod(focusable, 'focus'), 50); + } + } + } + } + + switchCellToViewMode(element: any) { + this.editingCell = null; + let cell = this.findCell(element); + this.domHandler.removeClass(cell, 'ui-cell-editing'); + } + + closeCell() { + if(this.editingCell) { + this.domHandler.removeClass(this.editingCell, 'ui-cell-editing'); + this.editingCell = null; + } + } + + onCellEditorKeydown(event, column: Column, rowData: any, rowIndex: number) { + if(this.editable) { + this.onEdit.emit({originalEvent: event, column: column, data: rowData, index: rowIndex}); + + //enter + if(event.keyCode == 13) { + this.onEditComplete.emit({column: column, data: rowData, index: rowIndex}); + this.domHandler.invokeElementMethod(event.target, 'blur'); + this.switchCellToViewMode(event.target); + event.preventDefault(); + } + + //escape + else if(event.keyCode == 27) { + this.onEditCancel.emit({column: column, data: rowData, index: rowIndex}); + this.domHandler.invokeElementMethod(event.target, 'blur'); + this.switchCellToViewMode(event.target); + event.preventDefault(); + } + + //tab + else if(event.keyCode == 9) { + this.onEditComplete.emit({column: column, data: rowData, index: rowIndex}); + + if(event.shiftKey) + this.moveToPreviousCell(event); + else + this.moveToNextCell(event); + } + } + } + + moveToPreviousCell(event: KeyboardEvent) { + let currentCell = this.findCell(event.target); + let row = currentCell.parentElement; + let targetCell = this.findPreviousEditableColumn(currentCell); + + if(targetCell) { + this.domHandler.invokeElementMethod(targetCell, 'click'); + event.preventDefault(); + } + } + + moveToNextCell(event: KeyboardEvent) { + let currentCell = this.findCell(event.target); + let row = currentCell.parentElement; + let targetCell = this.findNextEditableColumn(currentCell); + + if(targetCell) { + this.domHandler.invokeElementMethod(targetCell, 'click'); + event.preventDefault(); + } + } + + findPreviousEditableColumn(cell: Element) { + let prevCell = cell.previousElementSibling; + + if(!prevCell) { + let previousRow = cell.parentElement.previousElementSibling; + if(previousRow) { + prevCell = previousRow.lastElementChild; + } + } + + if(prevCell) { + if(this.domHandler.hasClass(prevCell, 'ui-editable-column')) + return prevCell; + else + return this.findPreviousEditableColumn(prevCell); + } + else { + return null; + } + } + + findNextEditableColumn(cell: Element) { + let nextCell = cell.nextElementSibling; + + if(!nextCell) { + let nextRow = cell.parentElement.nextElementSibling; + if(nextRow) { + nextCell = nextRow.firstElementChild; + } + } + + if(nextCell) { + if(this.domHandler.hasClass(nextCell, 'ui-editable-column')) + return nextCell; + else + return this.findNextEditableColumn(nextCell); + } + else { + return null; + } + } + + onCustomEditorFocusPrev(event: KeyboardEvent) { + this.moveToPreviousCell(event); + } + + onCustomEditorFocusNext(event: KeyboardEvent) { + this.moveToNextCell(event); + } + + findCell(element) { + let cell = element; + while(cell.tagName != 'TD') { + cell = cell.parentElement; + } + + return cell; + } + + initResizableColumns() { + this.tbody = this.domHandler.findSingle(this.el.nativeElement, 'tbody.ui-datatable-data'); + this.resizerHelper = this.domHandler.findSingle(this.el.nativeElement, 'div.ui-column-resizer-helper'); + this.fixColumnWidths(); + + this.documentColumnResizeListener = this.renderer.listen('document', 'mousemove', (event) => { + if(this.columnResizing) { + this.onColumnResize(event); + } + }); + + this.documentColumnResizeEndListener = this.renderer.listen('document', 'mouseup', (event) => { + if(this.columnResizing) { + this.columnResizing = false; + this.onColumnResizeEnd(event); + } + }); + } + + initColumnResize(event) { + let container = this.el.nativeElement.children[0]; + let containerLeft = this.domHandler.getOffset(container).left; + this.resizeColumn = event.target.parentElement; + this.columnResizing = true; + this.lastResizerHelperX = (event.pageX - containerLeft); + } + + onColumnResize(event) { + let container = this.el.nativeElement.children[0]; + let containerLeft = this.domHandler.getOffset(container).left; + this.domHandler.addClass(container, 'ui-unselectable-text'); + this.resizerHelper.style.height = container.offsetHeight + 'px'; + this.resizerHelper.style.top = 0 + 'px'; + if(event.pageX > containerLeft && event.pageX < (containerLeft + container.offsetWidth)) { + this.resizerHelper.style.left = (event.pageX - containerLeft) + 'px'; + } + + this.resizerHelper.style.display = 'block'; + } + + onColumnResizeEnd(event) { + let delta = this.resizerHelper.offsetLeft - this.lastResizerHelperX; + let columnWidth = this.resizeColumn.offsetWidth; + let newColumnWidth = columnWidth + delta; + let minWidth = this.resizeColumn.style.minWidth||15; + + if(columnWidth + delta > parseInt(minWidth)) { + if(this.columnResizeMode === 'fit') { + let nextColumn = this.resizeColumn.nextElementSibling; + let nextColumnWidth = nextColumn.offsetWidth - delta; + + if(newColumnWidth > 15 && nextColumnWidth > 15) { + this.resizeColumn.style.width = newColumnWidth + 'px'; + if(nextColumn) { + nextColumn.style.width = nextColumnWidth + 'px'; + } + + + if(this.scrollable) { + let colGroup = this.domHandler.findSingle(this.el.nativeElement, 'colgroup.ui-datatable-scrollable-colgroup'); + let resizeColumnIndex = this.domHandler.index(this.resizeColumn); + colGroup.children[resizeColumnIndex].style.width = newColumnWidth + 'px'; + + if(nextColumn) { + colGroup.children[resizeColumnIndex + 1].style.width = nextColumnWidth + 'px'; + } + } + } + } + else if(this.columnResizeMode === 'expand') { + this.tbody.parentElement.style.width = this.tbody.parentElement.offsetWidth + delta + 'px'; + this.resizeColumn.style.width = newColumnWidth + 'px'; + let containerWidth = this.tbody.parentElement.style.width; + + if(this.scrollable) { + this.scrollBarWidth = this.scrollBarWidth||this.domHandler.calculateScrollbarWidth(); + this.el.nativeElement.children[0].style.width = parseFloat(containerWidth) + this.scrollBarWidth + 'px'; + let colGroup = this.domHandler.findSingle(this.el.nativeElement, 'colgroup.ui-datatable-scrollable-colgroup'); + let resizeColumnIndex = this.domHandler.index(this.resizeColumn); + colGroup.children[resizeColumnIndex].style.width = newColumnWidth + 'px'; + } + else { + this.el.nativeElement.children[0].style.width = containerWidth; + } + } + + this.onColResize.emit({ + element: this.resizeColumn, + delta: delta + }); + } + + this.resizerHelper.style.display = 'none'; + this.resizeColumn = null; + this.domHandler.removeClass(this.el.nativeElement.children[0], 'ui-unselectable-text'); + } + + fixColumnWidths() { + let columns = this.domHandler.find(this.el.nativeElement, 'th.ui-resizable-column'); + let bodyCols; + + for(let i = 0; i < columns.length; i++) { + columns[i].style.width = columns[i].offsetWidth + 'px'; + } + + if(this.scrollable) { + let colGroup = this.domHandler.findSingle(this.el.nativeElement, 'colgroup.ui-datatable-scrollable-colgroup'); + bodyCols = colGroup.children; + + if(bodyCols) { + for(let i = 0; i < columns.length; i++) { + bodyCols[i].style.width = columns[i].offsetWidth + 'px'; + } + } + } + } + + onColumnDragStart(event) { + if (this.columnResizing) { + event.preventDefault(); + return; + } + + this.draggedColumn = this.findParentHeader(event.target); + event.dataTransfer.setData('text', 'b'); // Firefox requires this to make dragging possible + } + + onColumnDragover(event) { + if(this.reorderableColumns && this.draggedColumn) { + event.preventDefault(); + let iconWidth = this.domHandler.getHiddenElementOuterWidth(this.reorderIndicatorUp); + let iconHeight = this.domHandler.getHiddenElementOuterHeight(this.reorderIndicatorUp); + let dropHeader = this.findParentHeader(event.target); + let container = this.el.nativeElement.children[0]; + let containerOffset = this.domHandler.getOffset(container); + let dropHeaderOffset = this.domHandler.getOffset(dropHeader); + + if(this.draggedColumn != dropHeader) { + let targetLeft = dropHeaderOffset.left - containerOffset.left; + let targetTop = containerOffset.top - dropHeaderOffset.top; + let columnCenter = dropHeaderOffset.left + dropHeader.offsetWidth / 2; + + this.reorderIndicatorUp.style.top = dropHeaderOffset.top - containerOffset.top - (iconHeight - 1) + 'px'; + this.reorderIndicatorDown.style.top = dropHeaderOffset.top - containerOffset.top + dropHeader.offsetHeight + 'px'; + + if(event.pageX > columnCenter) { + this.reorderIndicatorUp.style.left = (targetLeft + dropHeader.offsetWidth - Math.ceil(iconWidth / 2)) + 'px'; + this.reorderIndicatorDown.style.left = (targetLeft + dropHeader.offsetWidth - Math.ceil(iconWidth / 2))+ 'px'; + this.dropPosition = 1; + } + else { + this.reorderIndicatorUp.style.left = (targetLeft - Math.ceil(iconWidth / 2)) + 'px'; + this.reorderIndicatorDown.style.left = (targetLeft - Math.ceil(iconWidth / 2))+ 'px'; + this.dropPosition = -1; + } + + this.reorderIndicatorUp.style.display = 'block'; + this.reorderIndicatorDown.style.display = 'block'; + } + else { + event.dataTransfer.dropEffect = 'none'; + } + } + } + + onColumnDragleave(event) { + if(this.reorderableColumns && this.draggedColumn) { + event.preventDefault(); + this.reorderIndicatorUp.style.display = 'none'; + this.reorderIndicatorDown.style.display = 'none'; + } + } + + onColumnDrop(event) { + event.preventDefault(); + if(this.draggedColumn) { + let dragIndex = this.domHandler.index(this.draggedColumn); + let dropIndex = this.domHandler.index(this.findParentHeader(event.target)); + let allowDrop = (dragIndex != dropIndex); + if(allowDrop && ((dropIndex - dragIndex == 1 && this.dropPosition === -1) || (dragIndex - dropIndex == 1 && this.dropPosition === 1))) { + allowDrop = false; + } + + if(allowDrop) { + this.columns.splice(dropIndex, 0, this.columns.splice(dragIndex, 1)[0]); + + this.onColReorder.emit({ + dragIndex: dragIndex, + dropIndex: dropIndex, + columns: this.columns + }); + } + + this.reorderIndicatorUp.style.display = 'none'; + this.reorderIndicatorDown.style.display = 'none'; + this.draggedColumn.draggable = false; + this.draggedColumn = null; + this.dropPosition = null; + } + } + + initColumnReordering() { + this.reorderIndicatorUp = this.domHandler.findSingle(this.el.nativeElement.children[0], 'span.ui-datatable-reorder-indicator-up'); + this.reorderIndicatorDown = this.domHandler.findSingle(this.el.nativeElement.children[0], 'span.ui-datatable-reorder-indicator-down'); + } + + findParentHeader(element) { + if(element.nodeName == 'TH') { + return element; + } + else { + let parent = element.parentElement; + while(parent.nodeName != 'TH') { + parent = parent.parentElement; + } + return parent; + } + } + + hasFooter() { + if(this.footerColumnGroup) { + return true; + } + else { + if(this.columns) { + for(let i = 0; i < this.columns.length; i++) { + if(this.columns[i].footer) { + return true; + } + } + } + + } + return false; + } + + isEmpty() { + return !this.dataToRender||(this.dataToRender.length == 0); + } + + createLazyLoadMetadata(): LazyLoadEvent { + return { + first: this.first, + rows: this.virtualScroll ? this.rows * 2 : this.rows, + sortField: this.sortField, + sortOrder: this.sortOrder, + filters: this.filters, + globalFilter: this.globalFilter ? this.globalFilter.value : null, + multiSortMeta: this.multiSortMeta + }; + } + + toggleRow(row: any, event?: Event) { + if(!this.expandedRows) { + this.expandedRows = []; + } + + let expandedRowIndex = this.findExpandedRowIndex(row); + + if(expandedRowIndex != -1) { + this.expandedRows.splice(expandedRowIndex, 1); + this.onRowCollapse.emit({ + originalEvent: event, + data: row + }); + } + else { + if(this.rowExpandMode === 'single') { + this.expandedRows = []; + } + + this.expandedRows.push(row); + this.onRowExpand.emit({ + originalEvent: event, + data: row + }); + } + + if(event) { + event.preventDefault(); + } + } + + findExpandedRowIndex(row: any): number { + let index = -1 + if(this.expandedRows) { + for(let i = 0; i < this.expandedRows.length; i++) { + if(this.expandedRows[i] == row) { + index = i; + break; + } + } + } + return index; + } + + isRowExpanded(row: any): boolean { + return this.findExpandedRowIndex(row) != -1; + } + + findExpandedRowGroupIndex(row: any): number { + let index = -1; + if(this.expandedRowsGroups && this.expandedRowsGroups.length) { + for(let i = 0; i < this.expandedRowsGroups.length; i++) { + let group = this.expandedRowsGroups[i]; + let rowGroupField = this.resolveFieldData(row, this.groupField); + if(rowGroupField === group) { + index = i; + break; + } + } + } + return index; + } + + isRowGroupExpanded(row: any): boolean { + return this.findExpandedRowGroupIndex(row) != -1; + } + + toggleRowGroup(event: Event, row: any): void { + this.rowGroupToggleClick = true; + let index = this.findExpandedRowGroupIndex(row); + let rowGroupField = this.resolveFieldData(row, this.groupField); + if(index >= 0) { + this.expandedRowsGroups.splice(index, 1); + this.onRowGroupCollapse.emit({ + originalEvent: event, + group: rowGroupField + }); + } + else { + this.expandedRowsGroups = this.expandedRowsGroups||[], + this.expandedRowsGroups.push(rowGroupField); + this.onRowGroupExpand.emit({ + originalEvent: event, + group: rowGroupField + }); + } + event.preventDefault(); + } + + public reset() { + this.sortField = null; + this.sortOrder = 1; + + this.filteredValue = null; + this.filters = {}; + + if(this.paginator) { + this.paginate({ + first: 0, + rows: this.rows + }); + } + else { + this.updateDataToRender(this.value); + } + } + + public exportCSV() { + let data = this.filteredValue||this.value; + let csv = '\ufeff'; + + //headers + for(let i = 0; i < this.columns.length; i++) { + if(this.columns[i].field) { + csv += '"' + (this.columns[i].header || this.columns[i].field) + '"'; + + if(i < (this.columns.length - 1)) { + csv += this.csvSeparator; + } + } + } + + //body + data.forEach((record, i) => { + csv += '\n'; + for(let i = 0; i < this.columns.length; i++) { + if(this.columns[i].field) { + csv += '"' + this.resolveFieldData(record, this.columns[i].field) + '"'; + + if(i < (this.columns.length - 1)) { + csv += this.csvSeparator; + } + } + } + }); + + let blob = new Blob([csv],{ + type: 'text/csv;charset=utf-8;' + }); + + if(window.navigator.msSaveOrOpenBlob) { + navigator.msSaveOrOpenBlob(blob, this.exportFilename + '.csv'); + } + else { + let link = document.createElement("a"); + link.style.display = 'none'; + document.body.appendChild(link); + if(link.download !== undefined) { + link.setAttribute('href', URL.createObjectURL(blob)); + link.setAttribute('download', this.exportFilename + '.csv'); + link.click(); + } + else { + csv = 'data:text/csv;charset=utf-8,' + csv; + window.open(encodeURI(csv)); + } + document.body.removeChild(link); + } + } + + getBlockableElement(): HTMLElement { + return this.el.nativeElement.children[0]; + } + + getRowStyleClass(rowData: any, rowIndex: number) { + let styleClass = 'ui-widget-content'; + if(this.rowStyleClass) { + let rowClass = this.rowStyleClass.call(this, rowData, rowIndex); + if(rowClass) { + styleClass += ' ' + rowClass; + } + } + return styleClass; + } + + visibleColumns() { + return this.columns ? this.columns.filter(c => !c.hidden): []; + } + + get containerWidth() { + if(this.scrollable) { + if(this.scrollWidth) { + return this.scrollWidth; + } + else if(this.frozenWidth && this.unfrozenWidth) { + return parseFloat(this.frozenWidth) + parseFloat(this.unfrozenWidth) + 'px'; + } + } + else { + return this.style ? this.style.width : null; + } + } + + ngOnDestroy() { + //remove event listener + if(this.globalFilterFunction) { + this.globalFilterFunction(); + } + + if(this.resizableColumns && this.documentColumnResizeListener && this.documentColumnResizeEndListener) { + this.documentColumnResizeListener(); + this.documentColumnResizeEndListener(); + } + + if(this.documentClickListener) { + this.documentClickListener(); + } + + if(this.columnsSubscription) { + this.columnsSubscription.unsubscribe(); + } + } +} + +@NgModule({ + imports: [CommonModule,SharedModule,PaginatorModule,FormsModule], + exports: [DataTable,SharedModule], + declarations: [DataTable,DTRadioButton,DTCheckbox,ColumnHeaders,ColumnFooters,TableBody,ScrollableView,RowExpansionLoader] +}) +export class DataTableModule { } diff --git a/src/app/components/defer/defer.ts b/src/app/components/defer/defer.ts new file mode 100644 index 00000000000..c90e31ed9d2 --- /dev/null +++ b/src/app/components/defer/defer.ts @@ -0,0 +1,66 @@ +import {NgModule,Directive,ElementRef,AfterViewInit,OnDestroy,Input,TemplateRef,EmbeddedViewRef, + ViewContainerRef,Renderer2,EventEmitter,Output,ContentChild} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {DomHandler} from '../dom/domhandler'; + +@Directive({ + selector: '[pDefer]', + host: { + }, + providers: [DomHandler] +}) +export class DeferredLoader implements AfterViewInit,OnDestroy { + + @Output() onLoad: EventEmitter = new EventEmitter(); + + @ContentChild(TemplateRef) template: TemplateRef; + + documentScrollListener: Function; + + view: EmbeddedViewRef; + + constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2, public viewContainer: ViewContainerRef) {} + + ngAfterViewInit() { + if(this.shouldLoad()) { + this.load(); + } + + this.documentScrollListener = this.renderer.listen('window', 'scroll', () => { + if(this.shouldLoad()) { + this.load(); + this.documentScrollListener(); + this.documentScrollListener = null; + } + }); + } + + shouldLoad(): boolean { + let rect = this.el.nativeElement.getBoundingClientRect(); + let docElement = document.documentElement; + let scrollTop = (window.pageYOffset||document.documentElement.scrollTop); + let winHeight = docElement.clientHeight; + + return (winHeight >= rect.top); + } + + load(): void { + this.view = this.viewContainer.createEmbeddedView(this.template); + this.onLoad.emit(); + } + + ngOnDestroy() { + this.view = null; + + if(this.documentScrollListener) { + this.documentScrollListener(); + } + } +} + +@NgModule({ + imports: [CommonModule], + exports: [DeferredLoader], + declarations: [DeferredLoader] +}) +export class DeferModule { } \ No newline at end of file diff --git a/src/app/components/dialog/dialog.css b/src/app/components/dialog/dialog.css new file mode 100644 index 00000000000..fefaea3049f --- /dev/null +++ b/src/app/components/dialog/dialog.css @@ -0,0 +1,90 @@ +.ui-dialog { + position: fixed; + padding: 0; +} +.ui-dialog .ui-dialog-titlebar { + padding: .5em .75em; + position: relative; + border: 0; +} +.ui-dialog .ui-dialog-content { + position: relative; + border: 0; + padding: .5em .75em; + background: none; + overflow: auto; + zoom: 1; +} +.ui-dialog .ui-dialog-footer { + padding: .25em .75em; + border-width: 1px 0 0 0; + background-image: none; +} +.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { + float: right; +} +.ui-dialog .ui-dialog-buttonpane button { + margin: .5em .4em .5em 0; + cursor: pointer; + float: right; +} +.ui-dialog .ui-resizable-se { + width: 14px; + height: 14px; + right: 3px; + bottom: 3px; +} +.ui-draggable .ui-dialog-titlebar { + cursor: move; +} +.ui-dialog .ui-dialog-titlebar-icon { + text-decoration: none +} +.ui-dialog .ui-dialog-titlebar-close { + float: right; + padding: .125em; + cursor: pointer; + border: 1px solid transparent; +} +.ui-dialog .ui-dialog-titlebar-close span { + display: block; + margin: 0; +} +.ui-dialog-footer { + padding: .4em 1em; + border-width: 1px 0 0 0; + text-align: left; +} + +.ui-dialog-mask { + position: fixed; + width: 100%; + height: 100%; +} + +/* ConfirmDialog */ +.ui-confirmdialog.ui-dialog .ui-dialog-content { + padding: 1em 2em; +} +.ui-confirmdialog .ui-dialog-content .fa { + font-size: 1.5em; + vertical-align: middle; + margin-right: .5em; +} +.ui-confirmdialog .ui-dialog-content .ui-confirmdialog-message { + vertical-align: middle; +} + +/* Fluid */ +.ui-fluid .ui-dialog-buttonpane .ui-button { + width: auto; +} + +/* RTL */ +.ui-rtl .ui-dialog .ui-dialog-titlebar-close { + float: left; +} + +.ui-rtl .ui-dialog .ui-dialog-buttonpane button { + float: left; +} \ No newline at end of file diff --git a/src/app/components/dialog/dialog.ts b/src/app/components/dialog/dialog.ts new file mode 100644 index 00000000000..f794ac649a7 --- /dev/null +++ b/src/app/components/dialog/dialog.ts @@ -0,0 +1,444 @@ +import {NgModule,Component,ElementRef,AfterViewInit,OnDestroy,Input,Output,EventEmitter,Renderer2,ContentChild,ViewChild} from '@angular/core'; +import {trigger,state,style,transition,animate} from '@angular/animations'; +import {CommonModule} from '@angular/common'; +import {DomHandler} from '../dom/domhandler'; +import {Header,Footer,SharedModule} from '../common/shared'; + +@Component({ + selector: 'p-dialog', + template: ` +
+
+ {{header}} + + + + + + +
+
+ +
+ +
+
+ `, + animations: [ + trigger('dialogState', [ + state('hidden', style({ + opacity: 0 + })), + state('visible', style({ + opacity: 1 + })), + transition('visible => hidden', animate('400ms ease-in')), + transition('hidden => visible', animate('400ms ease-out')) + ]) + ], + providers: [DomHandler] +}) +export class Dialog implements AfterViewInit,OnDestroy { + + @Input() header: string; + + @Input() draggable: boolean = true; + + @Input() resizable: boolean = true; + + @Input() minWidth: number = 150; + + @Input() minHeight: number = 150; + + @Input() width: any; + + @Input() height: any; + + @Input() positionLeft: number; + + @Input() positionTop: number; + + @Input() contentStyle: any; + + @Input() modal: boolean; + + @Input() closeOnEscape: boolean = true; + + @Input() dismissableMask: boolean; + + @Input() rtl: boolean; + + @Input() closable: boolean = true; + + @Input() responsive: boolean = true; + + @Input() appendTo: any; + + @Input() style: any; + + @Input() styleClass: string; + + @Input() showHeader: boolean = true; + + @Input() breakpoint: number = 640; + + @ContentChild(Header) headerFacet; + + @ContentChild(Footer) footerFacet; + + @ViewChild('container') containerViewChild: ElementRef; + + @ViewChild('titlebar') headerViewChild: ElementRef; + + @ViewChild('content') contentViewChild: ElementRef; + + @Output() onShow: EventEmitter = new EventEmitter(); + + @Output() onHide: EventEmitter = new EventEmitter(); + + @Output() visibleChange:EventEmitter = new EventEmitter(); + + _visible: boolean; + + dragging: boolean; + + documentDragListener: Function; + + resizing: boolean; + + documentResizeListener: Function; + + documentResizeEndListener: Function; + + documentResponsiveListener: Function; + + documentEscapeListener: Function; + + maskClickListener: Function; + + lastPageX: number; + + lastPageY: number; + + mask: HTMLDivElement; + + closeIconMouseDown: boolean; + + preWidth: number; + + constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2) {} + + @Input() get visible(): boolean { + return this._visible; + } + + set visible(val:boolean) { + this._visible = val; + + if(this.containerViewChild && this.containerViewChild.nativeElement) { + if(this._visible) + this.show(); + else + this.hide(); + } + } + + show() { + this.onShow.emit({}); + this.positionOverlay(); + this.containerViewChild.nativeElement.style.zIndex = String(++DomHandler.zindex); + this.bindGlobalListeners(); + + if(this.modal) { + this.enableModality(); + } + } + + positionOverlay() { + if(this.positionLeft >= 0 && this.positionTop >= 0) { + this.containerViewChild.nativeElement.style.left = this.positionLeft + 'px'; + this.containerViewChild.nativeElement.style.top = this.positionTop + 'px'; + } + else if (this.positionTop >= 0) { + this.center(); + this.containerViewChild.nativeElement.style.top = this.positionTop + 'px'; + } + else{ + this.center(); + } + } + + hide() { + this.onHide.emit({}); + this.unbindMaskClickListener(); + + if(this.modal) { + this.disableModality(); + } + } + + close(event: Event) { + this.hide(); + this.visibleChange.emit(false); + event.preventDefault(); + } + + ngAfterViewInit() { + if(this.appendTo) { + if(this.appendTo === 'body') + document.body.appendChild(this.containerViewChild.nativeElement); + else + this.domHandler.appendChild(this.containerViewChild.nativeElement, this.appendTo); + } + + if(this.visible) { + this.show(); + } + } + + center() { + let elementWidth = this.domHandler.getOuterWidth(this.containerViewChild.nativeElement); + let elementHeight = this.domHandler.getOuterHeight(this.containerViewChild.nativeElement); + if(elementWidth == 0 && elementHeight == 0) { + this.containerViewChild.nativeElement.style.visibility = 'hidden'; + this.containerViewChild.nativeElement.style.display = 'block'; + elementWidth = this.domHandler.getOuterWidth(this.containerViewChild.nativeElement); + elementHeight = this.domHandler.getOuterHeight(this.containerViewChild.nativeElement); + this.containerViewChild.nativeElement.style.display = 'none'; + this.containerViewChild.nativeElement.style.visibility = 'visible'; + } + let viewport = this.domHandler.getViewport(); + let x = Math.max((viewport.width - elementWidth) / 2, 0); + let y = Math.max((viewport.height - elementHeight) / 2, 0); + + this.containerViewChild.nativeElement.style.left = x + 'px'; + this.containerViewChild.nativeElement.style.top = y + 'px'; + } + + enableModality() { + if(!this.mask) { + this.mask = document.createElement('div'); + this.mask.style.zIndex = String(parseInt(this.containerViewChild.nativeElement.style.zIndex) - 1); + this.domHandler.addMultipleClasses(this.mask, 'ui-widget-overlay ui-dialog-mask'); + + if(this.closable && this.dismissableMask) { + this.maskClickListener = this.renderer.listen(this.mask, 'click', (event: any) => { + this.close(event); + }); + } + document.body.appendChild(this.mask); + } + } + + disableModality() { + if(this.mask) { + document.body.removeChild(this.mask); + this.mask = null; + } + } + + unbindMaskClickListener() { + if(this.maskClickListener) { + this.maskClickListener(); + this.maskClickListener = null; + } + } + + moveOnTop() { + this.containerViewChild.nativeElement.style.zIndex = String(++DomHandler.zindex); + } + + onCloseMouseDown(event: Event) { + this.closeIconMouseDown = true; + } + + initDrag(event: MouseEvent) { + if(this.closeIconMouseDown) { + this.closeIconMouseDown = false; + return; + } + + if(this.draggable) { + this.dragging = true; + this.lastPageX = event.pageX; + this.lastPageY = event.pageY; + } + } + + onDrag(event: MouseEvent) { + if(this.dragging) { + let deltaX = event.pageX - this.lastPageX; + let deltaY = event.pageY - this.lastPageY; + let leftPos = parseInt(this.containerViewChild.nativeElement.style.left); + let topPos = parseInt(this.containerViewChild.nativeElement.style.top); + + this.containerViewChild.nativeElement.style.left = leftPos + deltaX + 'px'; + this.containerViewChild.nativeElement.style.top = topPos + deltaY + 'px'; + + this.lastPageX = event.pageX; + this.lastPageY = event.pageY; + } + } + + endDrag(event: MouseEvent) { + if(this.draggable) { + this.dragging = false; + } + } + + initResize(event: MouseEvent) { + if(this.resizable) { + this.preWidth = null; + this.resizing = true; + this.lastPageX = event.pageX; + this.lastPageY = event.pageY; + } + } + + onResize(event: MouseEvent) { + if(this.resizing) { + let deltaX = event.pageX - this.lastPageX; + let deltaY = event.pageY - this.lastPageY; + let containerWidth = this.domHandler.getOuterWidth(this.containerViewChild.nativeElement); + let containerHeight = this.domHandler.getOuterHeight(this.containerViewChild.nativeElement); + let contentHeight = this.domHandler.getOuterHeight(this.contentViewChild.nativeElement); + let newWidth = containerWidth + deltaX; + let newHeight = containerHeight + deltaY; + + if(newWidth > this.minWidth) { + this.containerViewChild.nativeElement.style.width = newWidth + 'px'; + } + + if(newHeight > this.minHeight) { + this.containerViewChild.nativeElement.style.height = newHeight + 'px'; + this.contentViewChild.nativeElement.style.height = contentHeight + deltaY + 'px'; + } + + this.lastPageX = event.pageX; + this.lastPageY = event.pageY; + } + } + + bindGlobalListeners() { + if(this.draggable) { + this.bindDocumentDragListener(); + } + + if(this.resizable) { + this.bindDocumentResizeListeners(); + } + + if(this.responsive) { + this.bindDocumentResponsiveListener(); + } + + if(this.closeOnEscape && this.closable) { + this.bindDocumentEscapeListener(); + } + } + + unbindGlobalListeners() { + this.unbindDocumentDragListener(); + } + + bindDocumentDragListener() { + this.documentDragListener = this.renderer.listen('document', 'mousemove', (event) => { + this.onDrag(event); + }); + } + + unbindDocumentDragListener() { + if(this.documentDragListener) { + this.documentDragListener(); + this.documentDragListener = null; + } + } + + bindDocumentResizeListeners() { + this.documentResizeListener = this.renderer.listen('document', 'mousemove', (event) => { + this.onResize(event); + }); + + this.documentResizeEndListener = this.renderer.listen('document', 'mouseup', (event) => { + if(this.resizing) { + this.resizing = false; + } + }); + } + + unbindDocumentResizeListeners() { + if(this.documentResizeListener && this.documentResizeEndListener) { + this.documentResizeListener(); + this.documentResizeEndListener(); + this.documentResizeListener = null; + this.documentResizeEndListener = null; + } + } + + bindDocumentResponsiveListener() { + this.documentResponsiveListener = this.renderer.listen('window', 'resize', (event) => { + let viewport = this.domHandler.getViewport(); + let width = this.domHandler.getOuterWidth(this.containerViewChild.nativeElement); + if(viewport.width <= this.breakpoint) { + if(!this.preWidth) { + this.preWidth = width; + } + this.containerViewChild.nativeElement.style.left = '0px'; + this.containerViewChild.nativeElement.style.width = '100%'; + } + else { + this.containerViewChild.nativeElement.style.width = this.preWidth + 'px'; + this.positionOverlay(); + } + }); + } + + unbindDocumentResponseListener() { + if(this.documentResponsiveListener) { + this.documentResponsiveListener(); + this.documentResponsiveListener = null; + } + } + + bindDocumentEscapeListener() { + this.documentEscapeListener = this.renderer.listen('document', 'keydown', (event) => { + if(event.which == 27) { + if(parseInt(this.containerViewChild.nativeElement.style.zIndex) == DomHandler.zindex) { + this.close(event); + } + } + }); + } + + unbindDocumentEscapeListener() { + if(this.documentEscapeListener) { + this.documentEscapeListener(); + this.documentEscapeListener = null; + } + } + + ngOnDestroy() { + this.disableModality(); + + this.unbindGlobalListeners(); + + if(this.appendTo) { + this.el.nativeElement.appendChild(this.containerViewChild.nativeElement); + } + + this.unbindMaskClickListener(); + } + +} + +@NgModule({ + imports: [CommonModule], + exports: [Dialog,SharedModule], + declarations: [Dialog] +}) +export class DialogModule { } diff --git a/src/app/components/dom/domhandler.ts b/src/app/components/dom/domhandler.ts new file mode 100644 index 00000000000..250a605c628 --- /dev/null +++ b/src/app/components/dom/domhandler.ts @@ -0,0 +1,393 @@ +import { Injectable } from '@angular/core'; + +@Injectable() +export class DomHandler { + + public static zindex: number = 1000; + + public addClass(element: any, className: string): void { + if (element.classList) + element.classList.add(className); + else + element.className += ' ' + className; + } + + public addMultipleClasses(element: any, className: string): void { + if (element.classList) { + let styles: string[] = className.split(' '); + for (let i = 0; i < styles.length; i++) { + element.classList.add(styles[i]); + } + + } + else { + let styles: string[] = className.split(' '); + for (let i = 0; i < styles.length; i++) { + element.className += ' ' + styles[i]; + } + } + } + + public removeClass(element: any, className: string): void { + if (element.classList) + element.classList.remove(className); + else + element.className = element.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' '); + } + + public hasClass(element: any, className: string): boolean { + if (element.classList) + return element.classList.contains(className); + else + return new RegExp('(^| )' + className + '( |$)', 'gi').test(element.className); + } + + public siblings(element: any): any { + return Array.prototype.filter.call(element.parentNode.children, function (child) { + return child !== element; + }); + } + + public find(element: any, selector: string): any[] { + return element.querySelectorAll(selector); + } + + public findSingle(element: any, selector: string): any { + return element.querySelector(selector); + } + + public index(element: any): number { + let children = element.parentNode.childNodes; + let num = 0; + for (var i = 0; i < children.length; i++) { + if (children[i] == element) return num; + if (children[i].nodeType == 1) num++; + } + return -1; + } + + public relativePosition(element: any, target: any): void { + let elementDimensions = element.offsetParent ? { width: element.offsetWidth, height: element.offsetHeight } : this.getHiddenElementDimensions(element); + let targetHeight = target.offsetHeight; + let targetWidth = target.offsetWidth; + let targetOffset = target.getBoundingClientRect(); + let viewport = this.getViewport(); + let top, left; + + if ((targetOffset.top + targetHeight + elementDimensions.height) > viewport.height) + top = -1 * (elementDimensions.height); + else + top = targetHeight; + + if ((targetOffset.left + elementDimensions.width) > viewport.width) + left = targetWidth - elementDimensions.width; + else + left = 0; + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + } + + public absolutePosition(element: any, target: any): void { + let elementDimensions = element.offsetParent ? { width: element.offsetWidth, height: element.offsetHeight } : this.getHiddenElementDimensions(element); + let elementOuterHeight = elementDimensions.height; + let elementOuterWidth = elementDimensions.width; + let targetOuterHeight = target.offsetHeight; + let targetOuterWidth = target.offsetWidth; + let targetOffset = target.getBoundingClientRect(); + let windowScrollTop = this.getWindowScrollTop(); + let windowScrollLeft = this.getWindowScrollLeft(); + let viewport = this.getViewport(); + let top, left; + + if (targetOffset.top + targetOuterHeight + elementOuterHeight > viewport.height) { + top = targetOffset.top + windowScrollTop - elementOuterHeight; + if(top < 0) { + top = 0 + windowScrollTop; + } + } + else { + top = targetOuterHeight + targetOffset.top + windowScrollTop; + } + + if (targetOffset.left + targetOuterWidth + elementOuterWidth > viewport.width) + left = targetOffset.left + windowScrollLeft + targetOuterWidth - elementOuterWidth; + else + left = targetOffset.left + windowScrollLeft; + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + } + + public getHiddenElementOuterHeight(element: any): number { + element.style.visibility = 'hidden'; + element.style.display = 'block'; + let elementHeight = element.offsetHeight; + element.style.display = 'none'; + element.style.visibility = 'visible'; + + return elementHeight; + } + + public getHiddenElementOuterWidth(element: any): number { + element.style.visibility = 'hidden'; + element.style.display = 'block'; + let elementWidth = element.offsetWidth; + element.style.display = 'none'; + element.style.visibility = 'visible'; + + return elementWidth; + } + + public getHiddenElementDimensions(element: any): any { + let dimensions: any = {}; + element.style.visibility = 'hidden'; + element.style.display = 'block'; + dimensions.width = element.offsetWidth; + dimensions.height = element.offsetHeight; + element.style.display = 'none'; + element.style.visibility = 'visible'; + + return dimensions; + } + + public scrollInView(container, item) { + let borderTopValue: string = getComputedStyle(container).getPropertyValue('borderTopWidth'); + let borderTop: number = borderTopValue ? parseFloat(borderTopValue) : 0; + let paddingTopValue: string = getComputedStyle(container).getPropertyValue('paddingTop'); + let paddingTop: number = paddingTopValue ? parseFloat(paddingTopValue) : 0; + let containerRect = container.getBoundingClientRect(); + let itemRect = item.getBoundingClientRect(); + let offset = (itemRect.top + document.body.scrollTop) - (containerRect.top + document.body.scrollTop) - borderTop - paddingTop; + let scroll = container.scrollTop; + let elementHeight = container.clientHeight; + let itemHeight = this.getOuterHeight(item); + + if (offset < 0) { + container.scrollTop = scroll + offset; + } + else if ((offset + itemHeight) > elementHeight) { + container.scrollTop = scroll + offset - elementHeight + itemHeight; + } + } + + public fadeIn(element, duration: number): void { + element.style.opacity = 0; + + let last = +new Date(); + let opacity = 0; + let tick = function () { + opacity = +element.style.opacity + (new Date().getTime() - last) / duration; + element.style.opacity = opacity; + last = +new Date(); + + if (+opacity < 1) { + (window.requestAnimationFrame && requestAnimationFrame(tick)) || setTimeout(tick, 16); + } + }; + + tick(); + } + + public fadeOut(element, ms) { + var opacity = 1, + interval = 50, + duration = ms, + gap = interval / duration; + + let fading = setInterval(() => { + opacity = opacity - gap; + + if (opacity <= 0) { + opacity = 0; + clearInterval(fading); + } + + element.style.opacity = opacity; + }, interval); + } + + public getWindowScrollTop(): number { + let doc = document.documentElement; + return (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0); + } + + public getWindowScrollLeft(): number { + let doc = document.documentElement; + return (window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0); + } + + public matches(element, selector: string): boolean { + var p = Element.prototype; + var f = p['matches'] || p.webkitMatchesSelector || p['mozMatchesSelector'] || p.msMatchesSelector || function (s) { + return [].indexOf.call(document.querySelectorAll(s), this) !== -1; + }; + return f.call(element, selector); + } + + public getOuterWidth(el, margin?) { + let width = el.offsetWidth; + + if (margin) { + let style = getComputedStyle(el); + width += parseFloat(style.marginLeft) + parseFloat(style.marginRight); + } + + return width; + } + + public getHorizontalPadding(el) { + let style = getComputedStyle(el); + return parseFloat(style.paddingLeft) + parseFloat(style.paddingRight); + } + + public getHorizontalMargin(el) { + let style = getComputedStyle(el); + return parseFloat(style.marginLeft) + parseFloat(style.marginRight); + } + + public innerWidth(el) { + let width = el.offsetWidth; + let style = getComputedStyle(el); + + width += parseFloat(style.paddingLeft) + parseFloat(style.paddingRight); + return width; + } + + public width(el) { + let width = el.offsetWidth; + let style = getComputedStyle(el); + + width -= parseFloat(style.paddingLeft) + parseFloat(style.paddingRight); + return width; + } + + public getInnerHeight(el) { + let height = el.offsetHeight; + let style = getComputedStyle(el); + + height += parseFloat(style.paddingTop) + parseFloat(style.paddingBottom); + return height; + } + + public getOuterHeight(el, margin?) { + let height = el.offsetHeight; + + if (margin) { + let style = getComputedStyle(el); + height += parseFloat(style.marginTop) + parseFloat(style.marginBottom); + } + + return height; + } + + public getHeight(el): number { + let height = el.offsetHeight; + let style = getComputedStyle(el); + + height -= parseFloat(style.paddingTop) + parseFloat(style.paddingBottom) + parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth); + + return height; + } + + public getWidth(el): number { + let width = el.offsetWidth; + let style = getComputedStyle(el); + + width -= parseFloat(style.paddingLeft) + parseFloat(style.paddingRight) + parseFloat(style.borderLeftWidth) + parseFloat(style.borderRightWidth); + + return width; + } + + public getViewport(): any { + let win = window, + d = document, + e = d.documentElement, + g = d.getElementsByTagName('body')[0], + w = win.innerWidth || e.clientWidth || g.clientWidth, + h = win.innerHeight || e.clientHeight || g.clientHeight; + + return { width: w, height: h }; + } + + public getOffset(el) { + let x = el.offsetLeft; + let y = el.offsetTop; + + while (el = el.offsetParent) { + x += el.offsetLeft; + y += el.offsetTop; + } + + return {left: x, top: y}; + } + + getUserAgent(): string { + return navigator.userAgent; + } + + isIE() { + var ua = window.navigator.userAgent; + + var msie = ua.indexOf('MSIE '); + if (msie > 0) { + // IE 10 or older => return version number + return true; + } + + var trident = ua.indexOf('Trident/'); + if (trident > 0) { + // IE 11 => return version number + var rv = ua.indexOf('rv:'); + return true; + } + + var edge = ua.indexOf('Edge/'); + if (edge > 0) { + // Edge (IE 12+) => return version number + return true; + } + + // other browser + return false; + } + + appendChild(element: any, target: any) { + if(this.isElement(target)) + target.appendChild(element); + else if(target.el && target.el.nativeElement) + target.el.nativeElement.appendChild(element); + else + throw 'Cannot append ' + target + ' to ' + element; + } + + removeChild(element: any, target: any) { + if(this.isElement(target)) + target.removeChild(element); + else if(target.el && target.el.nativeElement) + target.el.nativeElement.removeChild(element); + else + throw 'Cannot remove ' + element + ' from ' + target; + } + + isElement(obj: any) { + return (typeof HTMLElement === "object" ? obj instanceof HTMLElement : + obj && typeof obj === "object" && obj !== null && obj.nodeType === 1 && typeof obj.nodeName === "string" + ); + } + + calculateScrollbarWidth(): number { + let scrollDiv = document.createElement("div"); + scrollDiv.className = "ui-scrollbar-measure"; + document.body.appendChild(scrollDiv); + + let scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth; + document.body.removeChild(scrollDiv); + + return scrollbarWidth; + } + + public invokeElementMethod(element: any, methodName: string, args?: any[]): void { + (element as any)[methodName].apply(element, args); + } +} diff --git a/src/app/components/dragdrop/dragdrop.ts b/src/app/components/dragdrop/dragdrop.ts new file mode 100644 index 00000000000..f98fa41f130 --- /dev/null +++ b/src/app/components/dragdrop/dragdrop.ts @@ -0,0 +1,147 @@ +import {NgModule,Directive,ElementRef,HostListener,Input,Output,EventEmitter} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {DomHandler} from '../dom/domhandler'; + +@Directive({ + selector: '[pDraggable]', + host: { + '[draggable]': 'true' + }, + providers: [DomHandler] +}) +export class Draggable { + + @Input('pDraggable') scope: string; + + @Input() dragEffect: string; + + @Input() dragHandle: string; + + @Output() onDragStart: EventEmitter = new EventEmitter(); + + @Output() onDragEnd: EventEmitter = new EventEmitter(); + + @Output() onDrag: EventEmitter = new EventEmitter(); + + public handle: any; + + constructor(public el: ElementRef, public domHandler: DomHandler) {} + + @HostListener('dragstart', ['$event']) + dragStart(event) { + if(this.allowDrag()) { + if(this.dragEffect) { + event.dataTransfer.effectAllowed = this.dragEffect; + } + event.dataTransfer.setData('text', this.scope); + + this.onDragStart.emit(event); + } + else { + event.preventDefault(); + } + } + + @HostListener('drag', ['$event']) + drag(event) { + this.onDrag.emit(event); + } + + @HostListener('dragend', ['$event']) + dragEnd(event) { + this.onDragEnd.emit(event); + } + + @HostListener('mouseover', ['$event']) + mouseover(event) { + this.handle = event.target; + } + + @HostListener('mouseleave', ['$event']) + mouseleave(event) { + this.handle = null; + } + + allowDrag() : boolean { + if(this.dragHandle && this.handle) + return this.domHandler.matches(this.handle, this.dragHandle); + else + return true; + } + +} + +@Directive({ + selector: '[pDroppable]', + providers: [DomHandler] +}) +export class Droppable { + + @Input('pDroppable') scope: string|string[]; + + @Input() dropEffect: string; + + @Output() onDragEnter: EventEmitter = new EventEmitter(); + + @Output() onDragLeave: EventEmitter = new EventEmitter(); + + @Output() onDrop: EventEmitter = new EventEmitter(); + + @Output() onDragOver: EventEmitter = new EventEmitter(); + + constructor(public el: ElementRef, public domHandler: DomHandler) {} + + @HostListener('drop', ['$event']) + drop(event) { + if(this.allowDrop(event)) { + event.preventDefault(); + this.onDrop.emit(event); + } + } + + @HostListener('dragenter', ['$event']) + dragEnter(event) { + event.preventDefault(); + + if(this.dropEffect) { + event.dataTransfer.dropEffect = this.dropEffect; + } + + this.onDragEnter.emit(event); + } + + @HostListener('dragleave', ['$event']) + dragLeave(event) { + event.preventDefault(); + + this.onDragLeave.emit(event); + } + + @HostListener('dragover', ['$event']) + dragOver(event) { + event.preventDefault(); + this.onDragOver.emit(event); + } + + allowDrop(event): boolean { + let dragScope = event.dataTransfer.getData('text'); + if(typeof (this.scope) == "string" && dragScope == this.scope) { + return true; + } + else if(this.scope instanceof Array) { + for(let j = 0; j < this.scope.length; j++) { + if(dragScope == this.scope[j]) { + return true; + } + } + } + return false; + } +} + +@NgModule({ + imports: [CommonModule], + exports: [Draggable,Droppable], + declarations: [Draggable,Droppable] +}) +export class DragDropModule { } \ No newline at end of file diff --git a/src/app/components/dropdown/dropdown.css b/src/app/components/dropdown/dropdown.css new file mode 100644 index 00000000000..e07a1ab8477 --- /dev/null +++ b/src/app/components/dropdown/dropdown.css @@ -0,0 +1,107 @@ +.ui-dropdown { + display: inline-block; + position: relative; + cursor: pointer; + vertical-align: middle; +} + +.ui-dropdown .ui-dropdown-trigger { + border-right: none; + border-top: none; + border-bottom: none; + cursor: pointer; + width: 1.5em; + height: 100%; + position: absolute; + right: 0; + top: 0; + padding: 0 .25em; +} + +.ui-dropdown .ui-dropdown-trigger .fa { + margin-top: .4em; + margin-left: -.125em; +} + +.ui-dropdown .ui-dropdown-label { + display: block; + border: none; + white-space: nowrap; + overflow: hidden; + font-weight: normal; + width: 100%; + padding-right: 1.5em; +} + +.ui-dropdown .ui-dropdown-item-empty, +.ui-dropdown .ui-dropdown-label-empty { + text-indent: -9999px; +} + +.ui-dropdown.ui-state-disabled .ui-dropdown-trigger, +.ui-dropdown.ui-state-disabled .ui-dropdown-label { + cursor: default; +} + +.ui-dropdown label.ui-dropdown-label { + cursor: pointer; +} + +.ui-dropdown input.ui-dropdown-label { + cursor: default; +} + +.ui-dropdown .ui-dropdown-panel { + min-width: 100%; +} + +.ui-dropdown-panel { + position: absolute; + height: auto; +} + +.ui-dropdown-panel .ui-dropdown-items-wrapper { + overflow: auto; +} + +.ui-dropdown-panel .ui-dropdown-item { + font-weight: normal; + border: 0 none; + cursor: pointer; + margin: 1px 0; + padding: .125em .25em; + text-align: left; +} + +.ui-dropdown-panel .ui-dropdown-item-group { + font-weight: bold; +} + +.ui-dropdown-panel .ui-dropdown-list { + padding: 0.4em; + border: 0 none; +} + +.ui-dropdown-panel .ui-dropdown-filter { + width: 100%; + box-sizing: border-box; + padding-right: 1.5em; +} + +.ui-dropdown-panel .ui-dropdown-filter-container { + position: relative; + margin: 0; + padding: 0.4em; + display: inline-block; +} + +.ui-dropdown-panel .ui-dropdown-filter-container .fa { + position: absolute; + top: .8em; + right: 1em; +} + +/** Dropdown **/ +.ui-fluid .ui-dropdown { + width: 100%; +} \ No newline at end of file diff --git a/src/app/components/dropdown/dropdown.ts b/src/app/components/dropdown/dropdown.ts new file mode 100644 index 00000000000..eb8322b3f8b --- /dev/null +++ b/src/app/components/dropdown/dropdown.ts @@ -0,0 +1,535 @@ +import {NgModule,Component,ElementRef,OnInit,AfterViewInit,AfterContentInit,AfterViewChecked,OnDestroy,Input,Output,Renderer2,EventEmitter,ContentChildren, + QueryList,ViewChild,TemplateRef,forwardRef,ChangeDetectorRef} from '@angular/core'; +import {trigger,state,style,transition,animate} from '@angular/animations'; +import {CommonModule} from '@angular/common'; +import {SelectItem} from '../common/selectitem'; +import {SharedModule,PrimeTemplate} from '../common/shared'; +import {DomHandler} from '../dom/domhandler'; +import {ObjectUtils} from '../utils/ObjectUtils'; +import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; + +export const DROPDOWN_VALUE_ACCESSOR: any = { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => Dropdown), + multi: true +}; + +@Component({ + selector: 'p-dropdown', + template: ` +
+
+ +
+
+ +
+ + +
+ +
+
+
+ + +
+
+
    +
  • + {{option.label||'empty'}} + +
  • +
+
+
+
+ `, + animations: [ + trigger('panelState', [ + state('hidden', style({ + opacity: 0 + })), + state('visible', style({ + opacity: 1 + })), + transition('visible => hidden', animate('400ms ease-in')), + transition('hidden => visible', animate('400ms ease-out')) + ]) + ], + providers: [DomHandler,ObjectUtils,DROPDOWN_VALUE_ACCESSOR] +}) +export class Dropdown implements OnInit,AfterViewInit,AfterContentInit,AfterViewChecked,OnDestroy,ControlValueAccessor { + + @Input() scrollHeight: string = '200px'; + + @Input() filter: boolean; + + @Input() style: any; + + @Input() panelStyle: any; + + @Input() styleClass: string; + + @Input() panelStyleClass: string; + + @Input() disabled: boolean; + + @Input() readonly: boolean; + + @Input() autoWidth: boolean = true; + + @Input() required: boolean; + + @Input() editable: boolean; + + @Input() appendTo: any; + + @Input() tabindex: number; + + @Input() placeholder: string; + + @Input() filterPlaceholder: string; + + @Input() inputId: string; + + @Input() dataKey: string; + + @Output() onChange: EventEmitter = new EventEmitter(); + + @Output() onFocus: EventEmitter = new EventEmitter(); + + @Output() onBlur: EventEmitter = new EventEmitter(); + + @ViewChild('container') containerViewChild: ElementRef; + + @ViewChild('panel') panelViewChild: ElementRef; + + @ViewChild('itemswrapper') itemsWrapperViewChild: ElementRef; + + @ViewChild('filter') filterViewChild: ElementRef; + + @ViewChild('in') focusViewChild: ElementRef; + + @ContentChildren(PrimeTemplate) templates: QueryList; + + public itemTemplate: TemplateRef; + + selectedOption: SelectItem; + + _options: SelectItem[]; + + value: any; + + onModelChange: Function = () => {}; + + onModelTouched: Function = () => {}; + + optionsToDisplay: SelectItem[]; + + hover: boolean; + + focus: boolean; + + public panelVisible: boolean = false; + + public shown: boolean; + + public documentClickListener: any; + + public optionsChanged: boolean; + + public panel: HTMLDivElement; + + public container: HTMLDivElement; + + public itemsWrapper: HTMLDivElement; + + public initialized: boolean; + + public selfClick: boolean; + + public itemClick: boolean; + + public hoveredItem: any; + + public selectedOptionUpdated: boolean; + + constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2, private cd: ChangeDetectorRef, public objectUtils: ObjectUtils) {} + + ngAfterContentInit() { + this.templates.forEach((item) => { + switch(item.getType()) { + case 'item': + this.itemTemplate = item.template; + break; + + default: + this.itemTemplate = item.template; + break; + } + }); + } + + ngOnInit() { + this.optionsToDisplay = this.options; + this.updateSelectedOption(null); + } + + @Input() get options(): SelectItem[] { + return this._options; + } + + set options(opts:SelectItem[]) { + this._options = opts; + this.optionsToDisplay = this._options; + this.updateSelectedOption(this.value); + this.optionsChanged = true; + } + + ngAfterViewInit() { + this.container = this.containerViewChild.nativeElement; + this.panel = this.panelViewChild.nativeElement; + this.itemsWrapper = this.itemsWrapperViewChild.nativeElement; + + this.updateDimensions(); + this.initialized = true; + + if(this.appendTo) { + if(this.appendTo === 'body') + document.body.appendChild(this.panel); + else + this.domHandler.appendChild(this.panel, this.appendTo); + } + } + + get label(): string { + return (this.selectedOption ? this.selectedOption.label : this.placeholder); + } + + get editableLabel(): string { + return this.value || (this.selectedOption ? this.selectedOption.label : null); + } + + onItemClick(event, option) { + this.itemClick = true; + this.selectItem(event, option); + this.focusViewChild.nativeElement.focus(); + + this.hide(); + } + + selectItem(event, option) { + this.selectedOption = option; + this.value = option.value; + + this.onModelChange(this.value); + this.onChange.emit({ + originalEvent: event, + value: this.value + }); + } + + ngAfterViewChecked() { + if(this.shown) { + this.onShow(); + this.shown = false; + } + + if(this.optionsChanged && this.panelVisible) { + this.optionsChanged = false; + } + + if(this.selectedOptionUpdated && this.itemsWrapper) { + let selectedItem = this.domHandler.findSingle(this.panel, 'li.ui-state-highlight'); + if(selectedItem) { + this.domHandler.scrollInView(this.itemsWrapper, this.domHandler.findSingle(this.panel, 'li.ui-state-highlight')); + } + this.selectedOptionUpdated = false; + } + } + + writeValue(value: any): void { + if(this.filter) { + this.resetFilter(); + } + + this.value = value; + this.updateSelectedOption(value); + this.cd.markForCheck(); + } + + resetFilter(): void { + if(this.filterViewChild && this.filterViewChild.nativeElement) { + this.filterViewChild.nativeElement.value = ''; + } + + this.optionsToDisplay = this.options; + } + + updateSelectedOption(val: any): void { + this.selectedOption = this.findOption(val, this.optionsToDisplay); + if(!this.placeholder && !this.selectedOption && this.optionsToDisplay && this.optionsToDisplay.length && !this.editable) { + this.selectedOption = this.optionsToDisplay[0]; + } + this.selectedOptionUpdated = true; + } + + registerOnChange(fn: Function): void { + this.onModelChange = fn; + } + + registerOnTouched(fn: Function): void { + this.onModelTouched = fn; + } + + setDisabledState(val: boolean): void { + this.disabled = val; + } + + updateDimensions() { + if(this.autoWidth) { + let select = this.domHandler.findSingle(this.el.nativeElement, 'select'); + if(!this.style||(!this.style['width']&&!this.style['min-width'])) { + this.el.nativeElement.children[0].style.width = select.offsetWidth + 30 + 'px'; + } + } + } + + onMouseclick(event) { + if(this.disabled||this.readonly) { + return; + } + + this.selfClick = true; + + if(!this.itemClick) { + this.focusViewChild.nativeElement.focus(); + + if(this.panelVisible) + this.hide(); + else { + this.show(); + + if (this.filterViewChild != undefined) { + setTimeout(() => { + this.filterViewChild.nativeElement.focus(); + }, 200); + } + } + } + } + + onEditableInputClick(event) { + this.itemClick = true; + this.bindDocumentClickListener(); + } + + onEditableInputFocus(event) { + this.focus = true; + this.hide(); + } + + onEditableInputChange(event) { + this.value = event.target.value; + this.updateSelectedOption(this.value); + this.onModelChange(this.value); + this.onChange.emit({ + originalEvent: event, + value: this.value + }); + } + + onShow() { + if(this.options && this.options.length) { + this.alignPanel(); + this.bindDocumentClickListener(); + } + } + + show() { + if(this.appendTo) { + this.panel.style.minWidth = this.domHandler.getWidth(this.container) + 'px'; + } + + this.panel.style.zIndex = String(++DomHandler.zindex); + this.panelVisible = true; + this.shown = true; + } + + hide() { + this.panelVisible = false; + } + + alignPanel() { + if(this.appendTo) + this.domHandler.absolutePosition(this.panel, this.container); + else + this.domHandler.relativePosition(this.panel, this.container); + } + + onInputFocus(event) { + this.focus = true; + this.onFocus.emit(event); + } + + onInputBlur(event) { + this.focus = false; + this.onModelTouched(); + this.onBlur.emit(event); + } + + onKeydown(event) { + if(this.readonly) { + return; + } + + let selectedItemIndex = this.selectedOption ? this.findOptionIndex(this.selectedOption.value, this.optionsToDisplay) : -1; + + switch(event.which) { + //down + case 40: + if(!this.panelVisible && event.altKey) { + this.show(); + } + else { + if(selectedItemIndex != -1) { + let nextItemIndex = selectedItemIndex + 1; + if(nextItemIndex != (this.optionsToDisplay.length)) { + this.selectedOption = this.optionsToDisplay[nextItemIndex]; + this.selectedOptionUpdated = true; + this.selectItem(event, this.selectedOption); + } + } + else if(this.optionsToDisplay) { + this.selectedOption = this.optionsToDisplay[0]; + } + } + + event.preventDefault(); + + break; + + //up + case 38: + if(selectedItemIndex > 0) { + let prevItemIndex = selectedItemIndex - 1; + this.selectedOption = this.optionsToDisplay[prevItemIndex]; + this.selectedOptionUpdated = true; + this.selectItem(event, this.selectedOption); + } + + event.preventDefault(); + break; + + //space + case 32: + this.panelVisible = !this.panelVisible; + + event.preventDefault(); + break; + + //enter + case 13: + this.hide(); + + event.preventDefault(); + break; + + //escape and tab + case 27: + case 9: + this.panelVisible = false; + break; + } + } + + findOptionIndex(val: any, opts: SelectItem[]): number { + let index: number = -1; + if(opts) { + for(let i = 0; i < opts.length; i++) { + if((val == null && opts[i].value == null) || this.objectUtils.equals(val, opts[i].value, this.dataKey)) { + index = i; + break; + } + } + } + + return index; + } + + findOption(val: any, opts: SelectItem[]): SelectItem { + let index: number = this.findOptionIndex(val, opts); + return (index != -1) ? opts[index] : null; + } + + onFilter(event): void { + if(this.options && this.options.length) { + let val = event.target.value.toLowerCase(); + this.optionsToDisplay = []; + for(let i = 0; i < this.options.length; i++) { + let option = this.options[i]; + if(option.label.toLowerCase().indexOf(val) > -1) { + this.optionsToDisplay.push(option); + } + } + this.optionsChanged = true; + } + + } + + applyFocus(): void { + if(this.editable) + this.domHandler.findSingle(this.el.nativeElement, '.ui-dropdown-label.ui-inputtext').focus(); + else + this.domHandler.findSingle(this.el.nativeElement, 'input[readonly]').focus(); + } + + bindDocumentClickListener() { + if(!this.documentClickListener) { + this.documentClickListener = this.renderer.listen('document', 'click', () => { + if(!this.selfClick&&!this.itemClick) { + this.panelVisible = false; + this.unbindDocumentClickListener(); + } + + this.selfClick = false; + this.itemClick = false; + this.cd.markForCheck(); + }); + } + } + + unbindDocumentClickListener() { + if(this.documentClickListener) { + this.documentClickListener(); + this.documentClickListener = null; + } + } + + ngOnDestroy() { + this.initialized = false; + + this.unbindDocumentClickListener(); + + if(this.appendTo) { + this.el.nativeElement.appendChild(this.panel); + } + } +} + +@NgModule({ + imports: [CommonModule,SharedModule], + exports: [Dropdown,SharedModule], + declarations: [Dropdown] +}) +export class DropdownModule { } diff --git a/src/app/components/editor/editor.ts b/src/app/components/editor/editor.ts new file mode 100644 index 00000000000..279fa351393 --- /dev/null +++ b/src/app/components/editor/editor.ts @@ -0,0 +1,179 @@ +import {NgModule,Component,ElementRef,AfterViewInit,Input,Output,EventEmitter,ContentChild,OnChanges,forwardRef} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {SharedModule,Header} from '../common/shared' +import {DomHandler} from '../dom/domhandler'; +import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; + +declare var Quill: any; + +export const EDITOR_VALUE_ACCESSOR: any = { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => Editor), + multi: true +}; + +@Component({ + selector: 'p-editor', + template: ` +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ `, + providers: [DomHandler,EDITOR_VALUE_ACCESSOR] +}) +export class Editor implements AfterViewInit,ControlValueAccessor { + + @Output() onTextChange: EventEmitter = new EventEmitter(); + + @Output() onSelectionChange: EventEmitter = new EventEmitter(); + + @ContentChild(Header) toolbar; + + @Input() style: any; + + @Input() styleClass: string; + + @Input() placeholder: string; + + @Input() readonly: boolean; + + @Input() formats: string[]; + + @Output() onInit: EventEmitter = new EventEmitter(); + + value: string; + + onModelChange: Function = () => {}; + + onModelTouched: Function = () => {}; + + quill: any; + + constructor(public el: ElementRef, public domHandler: DomHandler) {} + + ngAfterViewInit() { + let editorElement = this.domHandler.findSingle(this.el.nativeElement ,'div.ui-editor-content'); + let toolbarElement = this.domHandler.findSingle(this.el.nativeElement ,'div.ui-editor-toolbar'); + + this.quill = new Quill(editorElement, { + modules: { + toolbar: toolbarElement + }, + placeholder: this.placeholder, + readOnly: this.readonly, + theme: 'snow', + formats: this.formats + }); + + if(this.value) { + this.quill.pasteHTML(this.value); + } + + this.quill.on('text-change', (delta, oldContents, source) => { + let html = editorElement.children[0].innerHTML; + let text = this.quill.getText(); + if(html == '


') { + html = null; + } + + this.onTextChange.emit({ + htmlValue: html, + textValue: text, + delta: delta, + source: source + }); + + this.onModelChange(html); + + if(source === 'user') { + this.onModelTouched(); + } + }); + + this.quill.on('selection-change', (range, oldRange, source) => { + this.onSelectionChange.emit({ + range: range, + oldRange: oldRange, + source: source + }); + }); + + this.onInit.emit({ + editor: this.quill + }); + } + + writeValue(value: any) : void { + this.value = value; + + if(this.quill) { + if(value) + this.quill.pasteHTML(value); + else + this.quill.setText(''); + } + } + + registerOnChange(fn: Function): void { + this.onModelChange = fn; + } + + registerOnTouched(fn: Function): void { + this.onModelTouched = fn; + } + + getQuill() { + return this.quill; + } +} + +@NgModule({ + imports: [CommonModule], + exports: [Editor,SharedModule], + declarations: [Editor] +}) +export class EditorModule { } \ No newline at end of file diff --git a/src/app/components/fieldset/fieldset.css b/src/app/components/fieldset/fieldset.css new file mode 100644 index 00000000000..6eb6def80a3 --- /dev/null +++ b/src/app/components/fieldset/fieldset.css @@ -0,0 +1,19 @@ +.ui-fieldset, .ui-fieldset .ui-fieldset-legend { + padding: 0.6em 1em; +} + +.ui-fieldset-toggleable .ui-fieldset-legend { + padding: 0.5em 1em 0.5em 0.5em; + cursor:pointer; + white-space: nowrap; +} + +.ui-fieldset .ui-fieldset-toggler { + margin-right: .1em; + display: inline-block; + vertical-align: middle; +} + +.ui-fieldset .ui-fieldset-content-wrapper-overflown { + overflow: hidden; +} \ No newline at end of file diff --git a/src/app/components/fieldset/fieldset.ts b/src/app/components/fieldset/fieldset.ts new file mode 100644 index 00000000000..5ed8697d172 --- /dev/null +++ b/src/app/components/fieldset/fieldset.ts @@ -0,0 +1,95 @@ +import {NgModule,Component,Input,Output,EventEmitter,ElementRef} from '@angular/core'; +import {trigger,state,style,transition,animate} from '@angular/animations'; +import {CommonModule} from '@angular/common'; +import {SharedModule} from '../common/shared'; +import {BlockableUI} from '../common/blockableui'; + +@Component({ + selector: 'p-fieldset', + template: ` +
+ + + {{legend}} + + +
+
+ +
+
+
+ `, + animations: [ + trigger('fieldsetContent', [ + state('hidden', style({ + height: '0px' + })), + state('visible', style({ + height: '*' + })), + transition('visible => hidden', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)')), + transition('hidden => visible', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)')) + ]) + ] +}) +export class Fieldset implements BlockableUI { + + @Input() legend: string; + + @Input() toggleable: boolean; + + @Input() collapsed: boolean = false; + + @Output() onBeforeToggle: EventEmitter = new EventEmitter(); + + @Output() onAfterToggle: EventEmitter = new EventEmitter(); + + @Input() style: any; + + @Input() styleClass: string + + public animating: boolean; + + constructor(private el: ElementRef) {} + + toggle(event) { + if(this.toggleable) { + this.animating = true; + this.onBeforeToggle.emit({originalEvent: event, collapsed: this.collapsed}); + + if(this.collapsed) + this.expand(event); + else + this.collapse(event); + + this.onAfterToggle.emit({originalEvent: event, collapsed: this.collapsed}); + + //TODO: Use onDone of animate callback instead with RC6 + setTimeout(() => { + this.animating = false; + }, 400); + } + } + + expand(event) { + this.collapsed = false; + } + + collapse(event) { + this.collapsed = true; + } + + getBlockableElement(): HTMLElement { + return this.el.nativeElement.children[0]; + } + +} + +@NgModule({ + imports: [CommonModule], + exports: [Fieldset,SharedModule], + declarations: [Fieldset] +}) +export class FieldsetModule { } \ No newline at end of file diff --git a/src/app/components/fileupload/fileupload.css b/src/app/components/fileupload/fileupload.css new file mode 100644 index 00000000000..8ff9f7b6e38 --- /dev/null +++ b/src/app/components/fileupload/fileupload.css @@ -0,0 +1,81 @@ +/* + * FileUpload + */ +.ui-fileupload-buttonbar .ui-fileupload-choose input { + display: none; +} + +.ui-fileupload-buttonbar .ui-fileupload-choose.ui-state-disabled input { + cursor: default; +} + +.ui-fileupload-choose { + position: relative; + overflow: hidden; +} + +.ui-fileupload-buttonbar { + padding: .5em; + border-bottom: 0 none; +} + +.ui-fileupload-buttonbar .ui-button { + vertical-align: middle; + margin-right: .25em; +} + +.ui-fileupload-content { + padding: 1em; + position: relative; + transition: border-color .3s; +} + +.ui-fileupload-content.ui-fileupload-highlight { + border-color: #156090; +} + +.ui-fileupload-files img { + border: none; +} + +.ui-fileupload-files { + display: table; +} + +.ui-fileupload-row { + display: table-row; +} + +.ui-fileupload-row > div { + display: table-cell; + padding: .5em 1em; + vertical-align: middle; +} + +.ui-fileupload-content .ui-progressbar { + width: 100%; + position: absolute; + top: 1px; + left: 0; + height: .25em; + border: 0 none; +} + +.ui-fileupload-content .ui-progressbar-value { + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; + border: 0 none; +} + +/* ui-fluid */ +.ui-fluid .ui-fileupload .ui-button { + width: auto; +} + +.ui-fluid .ui-fileupload-content .ui-button-icon-only { + width: 2em; +} + + + diff --git a/src/app/components/fileupload/fileupload.ts b/src/app/components/fileupload/fileupload.ts new file mode 100644 index 00000000000..2c63ef72c01 --- /dev/null +++ b/src/app/components/fileupload/fileupload.ts @@ -0,0 +1,341 @@ +import {NgModule,Component,OnInit,Input,Output,EventEmitter,TemplateRef,AfterContentInit,ContentChildren,QueryList} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {DomSanitizer} from '@angular/platform-browser'; +import {ButtonModule} from '../button/button'; +import {MessagesModule} from '../messages/messages'; +import {ProgressBarModule} from '../progressbar/progressbar'; +import {Message} from '../common/message'; +import {PrimeTemplate,SharedModule} from '../common/shared'; + +@Component({ + selector: 'p-fileUpload', + template: ` +
+
+ + + + + + +
+
+ + + + +
+
+
+
+
{{file.name}}
+
{{formatSize(file.size)}}
+
+
+
+
+ +
+
+ + +
+
+ ` +}) +export class FileUpload implements OnInit,AfterContentInit { + + @Input() name: string; + + @Input() url: string; + + @Input() method: string = 'POST'; + + @Input() multiple: boolean; + + @Input() accept: string; + + @Input() disabled: boolean; + + @Input() auto: boolean; + + @Input() withCredentials: boolean; + + @Input() maxFileSize: number; + + @Input() invalidFileSizeMessageSummary: string = '{0}: Invalid file size, '; + + @Input() invalidFileSizeMessageDetail: string = 'maximum upload size is {0}.'; + + @Input() invalidFileTypeMessageSummary: string = '{0}: Invalid file type, '; + + @Input() invalidFileTypeMessageDetail: string = 'allowed file types: {0}.'; + + @Input() style: string; + + @Input() styleClass: string; + + @Input() previewWidth: number = 50; + + @Input() chooseLabel: string = 'Choose'; + + @Input() uploadLabel: string = 'Upload'; + + @Input() cancelLabel: string = 'Cancel'; + + @Output() onBeforeUpload: EventEmitter = new EventEmitter(); + + @Output() onBeforeSend: EventEmitter = new EventEmitter(); + + @Output() onUpload: EventEmitter = new EventEmitter(); + + @Output() onError: EventEmitter = new EventEmitter(); + + @Output() onClear: EventEmitter = new EventEmitter(); + + @Output() onRemove: EventEmitter = new EventEmitter(); + + @Output() onSelect: EventEmitter = new EventEmitter(); + + @ContentChildren(PrimeTemplate) templates: QueryList; + + public files: File[]; + + public progress: number = 0; + + public dragHighlight: boolean; + + public msgs: Message[]; + + public fileTemplate: TemplateRef; + + public contentTemplate: TemplateRef; + + public toolbarTemplate: TemplateRef; + + constructor(private sanitizer: DomSanitizer){} + + ngOnInit() { + this.files = []; + } + + ngAfterContentInit():void { + this.templates.forEach((item) => { + switch(item.getType()) { + case 'file': + this.fileTemplate = item.template; + break; + + case 'content': + this.contentTemplate = item.template; + break; + + case 'toolbar': + this.toolbarTemplate = item.template; + break; + + default: + this.fileTemplate = item.template; + break; + } + }); + } + + onChooseClick(event, fileInput) { + fileInput.value = null; + fileInput.click(); + } + + onFileSelect(event) { + this.msgs = []; + if(!this.multiple) { + this.files = []; + } + + let files = event.dataTransfer ? event.dataTransfer.files : event.target.files; + for(let i = 0; i < files.length; i++) { + let file = files[i]; + if(this.validate(file)) { + if(this.isImage(file)) { + file.objectURL = this.sanitizer.bypassSecurityTrustUrl((window.URL.createObjectURL(files[i]))); + } + + this.files.push(files[i]); + } + } + + this.onSelect.emit({originalEvent: event, files: files}); + + if(this.hasFiles() && this.auto) { + this.upload(); + } + } + + validate(file: File): boolean { + if(this.accept && !this.isFileTypeValid(file)) { + this.msgs.push({ + severity: 'error', + summary: this.invalidFileTypeMessageSummary.replace('{0}', file.name), + detail: this.invalidFileTypeMessageDetail.replace('{0}', this.accept) + }); + return false; + } + + if(this.maxFileSize && file.size > this.maxFileSize) { + this.msgs.push({ + severity: 'error', + summary: this.invalidFileSizeMessageSummary.replace('{0}', file.name), + detail: this.invalidFileSizeMessageDetail.replace('{0}', this.formatSize(this.maxFileSize)) + }); + return false; + } + + return true; + } + + private isFileTypeValid(file: File): boolean { + let acceptableTypes = this.accept.split(','); + for(let type of acceptableTypes) { + let acceptable = this.isWildcard(type) ? this.getTypeClass(file.type) === this.getTypeClass(type) + : file.type == type || this.getFileExtension(file) === type; + + if(acceptable) { + return true; + } + } + + return false; + } + + getTypeClass(fileType: string): string { + return fileType.substring(0, fileType.indexOf('/')); + } + + isWildcard(fileType: string): boolean { + return fileType.indexOf('*') !== -1; + } + + getFileExtension(file: File): string { + return '.' + file.name.split('.').pop(); + } + + isImage(file: File): boolean { + return /^image\//.test(file.type); + } + + onImageLoad(img: any) { + window.URL.revokeObjectURL(img.src); + } + + upload() { + this.msgs = []; + let xhr = new XMLHttpRequest(), + formData = new FormData(); + + this.onBeforeUpload.emit({ + 'xhr': xhr, + 'formData': formData + }); + + for(let i = 0; i < this.files.length; i++) { + formData.append(this.name, this.files[i], this.files[i].name); + } + + xhr.upload.addEventListener('progress', (e: ProgressEvent) => { + if(e.lengthComputable) { + this.progress = Math.round((e.loaded * 100) / e.total); + } + }, false); + + xhr.onreadystatechange = () => { + if(xhr.readyState == 4) { + this.progress = 0; + + if(xhr.status >= 200 && xhr.status < 300) + this.onUpload.emit({xhr: xhr, files: this.files}); + else + this.onError.emit({xhr: xhr, files: this.files}); + + this.clear(); + } + }; + + xhr.open(this.method, this.url, true); + + this.onBeforeSend.emit({ + 'xhr': xhr, + 'formData': formData + }); + + xhr.withCredentials = this.withCredentials; + + xhr.send(formData); + } + + clear() { + this.files = []; + this.onClear.emit(); + } + + remove(index: number) { + this.onRemove.emit({originalEvent: event, file: this.files[index]}); + this.files.splice(index, 1); + } + + hasFiles(): boolean { + return this.files && this.files.length > 0; + } + + onDragEnter(e) { + if(!this.disabled) { + e.stopPropagation(); + e.preventDefault(); + } + } + + onDragOver(e) { + if(!this.disabled) { + this.dragHighlight = true; + e.stopPropagation(); + e.preventDefault(); + } + } + + onDragLeave(e) { + if(!this.disabled) { + this.dragHighlight = false; + } + } + + onDrop(e) { + if(!this.disabled) { + this.dragHighlight = false; + e.stopPropagation(); + e.preventDefault(); + + this.onFileSelect(e); + } + } + + formatSize(bytes) { + if(bytes == 0) { + return '0 B'; + } + let k = 1000, + dm = 3, + sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], + i = Math.floor(Math.log(bytes) / Math.log(k)); + + return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]; + } +} + +@NgModule({ + imports: [CommonModule,SharedModule,ButtonModule,ProgressBarModule,MessagesModule], + exports: [FileUpload,SharedModule,ButtonModule,ProgressBarModule,MessagesModule], + declarations: [FileUpload] +}) +export class FileUploadModule { } \ No newline at end of file diff --git a/src/app/components/galleria/galleria.css b/src/app/components/galleria/galleria.css new file mode 100644 index 00000000000..8226a610b85 --- /dev/null +++ b/src/app/components/galleria/galleria.css @@ -0,0 +1,81 @@ +.ui-galleria { + overflow: hidden; + visibility: hidden; + position: relative; +} + +.ui-galleria-panel-wrapper { + position: relative; + padding: 0; + margin: 0; +} + +.ui-galleria-panel { + filter: inherit; + position: absolute; + top: 0; + left: 0; + list-style-type: none; +} + +.ui-galleria-filmstrip-wrapper { + overflow: hidden; + margin: .25em auto; + position: relative; +} + +.ui-galleria-filmstrip { + list-style: none outside none; + margin: 0; + padding: 0; + width: 2340px; + z-index: 900; + position: absolute; + top: 0; + left: 0; +} + +.ui-galleria-frame { + float:left; + margin-right: 5px; + opacity: 0.3; + cursor: pointer; +} + +.ui-galleria-frame-active { + opacity: 1; +} + +.ui-galleria-frame-content { + overflow: hidden; +} + +.ui-galleria-nav-next, .ui-galleria-nav-prev { + cursor: pointer; + position: absolute; +} + +.ui-galleria-nav-prev { + left: 5px; +} + +.ui-galleria-nav-next { + right: 5px; +} + +.ui-galleria-caption { + position: absolute; + left:1px; + background-color: rgba(0,0,0,0.5); + display: none; + color: #ededed; + padding: 0.2em 1em; +} + +.ui-galleria-caption h4 { + color: #ededed; +} + +.ui-galleria-panel-content { + padding: 1em 1.4em; +} \ No newline at end of file diff --git a/src/app/components/galleria/galleria.ts b/src/app/components/galleria/galleria.ts new file mode 100644 index 00000000000..cda4fb5c8cf --- /dev/null +++ b/src/app/components/galleria/galleria.ts @@ -0,0 +1,242 @@ +import {NgModule,Component,ElementRef,AfterViewChecked,AfterViewInit,OnDestroy,Input,Output,EventEmitter} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {DomHandler} from '../dom/domhandler'; + +@Component({ + selector: 'p-galleria', + template: ` +
+
    +
  • + +
  • +
+
+
    +
  • +
    + +
    +
  • +
+
+
+
+
+

{{images[activeIndex]?.title}}

{{images[activeIndex]?.alt}}

+
+
+ `, + providers: [DomHandler] +}) +export class Galleria implements AfterViewChecked,AfterViewInit,OnDestroy { + + @Input() style: any; + + @Input() styleClass: string; + + @Input() panelWidth: number = 600; + + @Input() panelHeight: number = 400; + + @Input() frameWidth: number = 60; + + @Input() frameHeight: number = 40; + + @Input() activeIndex: number = 0; + + @Input() showFilmstrip: boolean = true; + + @Input() autoPlay: boolean = true; + + @Input() transitionInterval: number = 4000; + + @Input() showCaption: boolean = true; + + @Output() onImageClicked = new EventEmitter(); + + _images: any[]; + + slideshowActive: boolean; + + public container: any; + + public panelWrapper: any; + + public panels: any; + + public caption: any; + + public stripWrapper: any; + + public strip: any; + + public frames: any; + + public interval: any; + + public stripLeft: number = 0; + + public imagesChanged: boolean; + + public initialized: boolean; + + constructor(public el: ElementRef, public domHandler: DomHandler) {} + + ngAfterViewChecked() { + if(this.imagesChanged) { + this.stopSlideshow(); + this.render(); + this.imagesChanged = false; + } + } + + @Input() get images(): any[] { + return this._images; + } + + set images(value:any[]) { + this._images = value; + this.activeIndex = 0; + this.imagesChanged = true; + } + + ngAfterViewInit() { + this.container = this.el.nativeElement.children[0]; + this.panelWrapper = this.domHandler.findSingle(this.el.nativeElement, 'ul.ui-galleria-panel-wrapper'); + this.initialized = true; + + if(this.showFilmstrip) { + this.stripWrapper = this.domHandler.findSingle(this.container,'div.ui-galleria-filmstrip-wrapper'); + this.strip = this.domHandler.findSingle(this.stripWrapper,'ul.ui-galleria-filmstrip'); + } + + if(this.images && this.images.length) { + this.render(); + } + } + + render() { + this.panels = this.domHandler.find(this.panelWrapper, 'li.ui-galleria-panel'); + + if(this.showFilmstrip) { + this.frames = this.domHandler.find(this.strip,'li.ui-galleria-frame'); + this.stripWrapper.style.width = this.domHandler.width(this.panelWrapper) - 50 + 'px'; + this.stripWrapper.style.height = this.frameHeight + 'px'; + } + + if(this.showCaption) { + this.caption = this.domHandler.findSingle(this.container,'div.ui-galleria-caption'); + this.caption.style.bottom = this.showFilmstrip ? this.domHandler.getOuterHeight(this.stripWrapper,true) + 'px' : 0 + 'px'; + this.caption.style.width = this.domHandler.width(this.panelWrapper) + 'px'; + } + + if(this.autoPlay) { + this.startSlideshow(); + } + + this.container.style.visibility = 'visible'; + } + + startSlideshow() { + this.interval = setInterval(() => { + this.next(); + }, this.transitionInterval); + + this.slideshowActive = true; + } + + stopSlideshow() { + if(this.interval) { + clearInterval(this.interval); + } + + this.slideshowActive = false; + } + + clickNavRight() { + if(this.slideshowActive) { + this.stopSlideshow(); + } + this.next(); + } + + clickNavLeft() { + if(this.slideshowActive) { + this.stopSlideshow(); + } + this.prev(); + } + + frameClick(frame) { + if(this.slideshowActive) { + this.stopSlideshow(); + } + + this.select(this.domHandler.index(frame), false); + } + + prev() { + if(this.activeIndex !== 0) { + this.select(this.activeIndex - 1, true); + } + } + + next() { + if(this.activeIndex !== (this.panels.length-1)) { + this.select(this.activeIndex + 1, true); + } + else { + this.select(0, false); + this.stripLeft = 0; + } + } + + select(index, reposition) { + if(index !== this.activeIndex) { + let oldPanel = this.panels[this.activeIndex], + newPanel = this.panels[index]; + + this.domHandler.fadeIn(newPanel, 500); + + if(this.showFilmstrip) { + let oldFrame = this.frames[this.activeIndex], + newFrame = this.frames[index]; + + if(reposition === undefined || reposition === true) { + let frameLeft = newFrame.offsetLeft, + stepFactor = this.frameWidth + parseInt(getComputedStyle(newFrame)['margin-right'], 10), + stripLeft = this.strip.offsetLeft, + frameViewportLeft = frameLeft + stripLeft, + frameViewportRight = frameViewportLeft + this.frameWidth; + + if(frameViewportRight > this.domHandler.width(this.stripWrapper)) + this.stripLeft -= stepFactor; + else if(frameViewportLeft < 0) + this.stripLeft += stepFactor; + } + } + + this.activeIndex = index; + } + } + + clickImage(event, image, i) { + this.onImageClicked.emit({originalEvent: event, image: image, index: i}) + } + + ngOnDestroy() { + this.stopSlideshow(); + } + +} + +@NgModule({ + imports: [CommonModule], + exports: [Galleria], + declarations: [Galleria] +}) +export class GalleriaModule { } \ No newline at end of file diff --git a/src/app/components/gmap/gmap.ts b/src/app/components/gmap/gmap.ts new file mode 100644 index 00000000000..88d3dae32b6 --- /dev/null +++ b/src/app/components/gmap/gmap.ts @@ -0,0 +1,143 @@ +import {NgModule,Component,ElementRef,OnInit,AfterViewInit,DoCheck,OnDestroy,Input,Output,EventEmitter,IterableDiffers,ChangeDetectorRef,NgZone} from '@angular/core'; +import {CommonModule} from '@angular/common'; + +declare var google: any; + +@Component({ + selector: 'p-gmap', + template: `
` +}) +export class GMap implements AfterViewInit,DoCheck { + + @Input() style: any; + + @Input() styleClass: string; + + @Input() options: any; + + @Input() overlays: any[]; + + @Output() onMapClick: EventEmitter = new EventEmitter(); + + @Output() onOverlayClick: EventEmitter = new EventEmitter(); + + @Output() onOverlayDragStart: EventEmitter = new EventEmitter(); + + @Output() onOverlayDrag: EventEmitter = new EventEmitter(); + + @Output() onOverlayDragEnd: EventEmitter = new EventEmitter(); + + @Output() onMapReady: EventEmitter = new EventEmitter(); + + differ: any; + + map: any; + + constructor(public el: ElementRef,differs: IterableDiffers, public cd: ChangeDetectorRef, public zone:NgZone) { + this.differ = differs.find([]).create(null); + } + + ngAfterViewInit() { + this.map = new google.maps.Map(this.el.nativeElement.children[0], this.options); + this.onMapReady.emit({ + map: this.map + }); + + if(this.overlays) { + for(let overlay of this.overlays) { + overlay.setMap(this.map); + this.bindOverlayEvents(overlay); + } + } + + this.map.addListener('click', (event) => { + this.zone.run(() => { + this.onMapClick.emit(event); + }); + }); + } + + bindOverlayEvents(overlay: any) { + overlay.addListener('click', (event) => { + this.zone.run(() => { + this.onOverlayClick.emit({ + originalEvent: event, + 'overlay': overlay, + map: this.map + }); + }); + }); + + if(overlay.getDraggable()) { + this.bindDragEvents(overlay); + } + } + + ngDoCheck() { + let changes = this.differ.diff(this.overlays); + + if(changes && this.map) { + changes.forEachRemovedItem((record) => {record.item.setMap(null)}); + changes.forEachAddedItem((record) => { + record.item.setMap(this.map); + record.item.addListener('click', (event) => { + this.zone.run(() => { + this.onOverlayClick.emit({ + originalEvent: event, + overlay: record.item, + map: this.map + }); + }); + }); + + if(record.item.getDraggable()) { + this.bindDragEvents(record.item); + } + }); + } + } + + bindDragEvents(overlay) { + overlay.addListener('dragstart', (event) => { + this.zone.run(() => { + this.onOverlayDragStart.emit({ + originalEvent: event, + overlay: overlay, + map: this.map + }); + }); + }); + + overlay.addListener('drag', (event) => { + this.zone.run(() => { + this.onOverlayDrag.emit({ + originalEvent: event, + overlay: overlay, + map: this.map + }); + }); + }); + + overlay.addListener('dragend', (event) => { + this.zone.run(() => { + this.onOverlayDragEnd.emit({ + originalEvent: event, + overlay: overlay, + map: this.map + }); + }); + + }); + } + + getMap() { + return this.map; + } +} + +@NgModule({ + imports: [CommonModule], + exports: [GMap], + declarations: [GMap] +}) +export class GMapModule { } \ No newline at end of file diff --git a/src/app/components/grid/grid.css b/src/app/components/grid/grid.css new file mode 100644 index 00000000000..0106d227f9c --- /dev/null +++ b/src/app/components/grid/grid.css @@ -0,0 +1,514 @@ +/* Deprecated Grid CSS */ +.ui-grid { + clear: both; + padding: 0; + margin: 0; +} + +.ui-grid:before, +.ui-grid:after { + content:""; + display:table; +} + +.ui-grid:after { + clear:both; +} + +.ui-grid .ui-grid-row { + display: -webkit-box; + display: -moz-box; + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + clear:both; +} + +.ui-grid-row:after { + clear: both; + content: ""; + display: table; +} + +.ui-grid-col-1, +.ui-grid-col-2, +.ui-grid-col-3, +.ui-grid-col-4, +.ui-grid-col-5, +.ui-grid-col-6, +.ui-grid-col-7, +.ui-grid-col-8, +.ui-grid-col-9, +.ui-grid-col-10, +.ui-grid-col-11, +.ui-grid-col-12 { + float: left; + box-sizing: border-box; +} + +.ui-grid-col-1 { + width: 8.33333%; +} + +.ui-grid-col-2 { + width: 16.66666%; +} + +.ui-grid-col-3 { + width: 25%; +} + +.ui-grid-col-4 { + width: 33.33333%; +} + +.ui-grid-col-5 { + width: 41.66666%; +} + +.ui-grid-col-6 { + width: 50%; +} + +.ui-grid-col-7 { + width: 58.33333%; +} + +.ui-grid-col-8 { + width: 66.66666%; +} + +.ui-grid-col-9 { + width: 75%; +} + +.ui-grid-col-10 { + width: 83.33333%; +} + +.ui-grid-col-11 { + width: 91.66666%; +} + +.ui-grid-col-12 { + width: 100%; +} + +@media (min-width: 480px) { + .ui-grid-fixed { + width: 480px; + } +} + +@media (min-width: 768px) { + .ui-grid-fixed { + width: 768px; + } +} + +@media (min-width: 960px) { + .ui-grid-fixed { + width: 960px; + } +} + +@media (min-width: 1024px) { + .ui-grid-fixed { + width: 1024px; + } +} + +/* Responsive */ +@media (max-width: 640px) { + .ui-grid-responsive .ui-grid-row { + display: block; + } + + .ui-grid-responsive .ui-grid-col-1, + .ui-grid-responsive .ui-grid-col-2, + .ui-grid-responsive .ui-grid-col-3, + .ui-grid-responsive .ui-grid-col-4, + .ui-grid-responsive .ui-grid-col-5, + .ui-grid-responsive .ui-grid-col-6, + .ui-grid-responsive .ui-grid-col-7, + .ui-grid-responsive .ui-grid-col-8, + .ui-grid-responsive .ui-grid-col-9, + .ui-grid-responsive .ui-grid-col-10, + .ui-grid-responsive .ui-grid-col-11, + .ui-grid-responsive .ui-grid-col-12 { + width: 100%; + float: none; + } +} + +.ui-grid.ui-grid-pad > .ui-grid-row > div { + padding: .25em .5em; +} + +/* Responsive */ +@media (max-width: 640px) { + .ui-grid-responsive .ui-grid-row { + display: block; + } + + .ui-grid-responsive .ui-grid-col-1, + .ui-grid-responsive .ui-grid-col-2, + .ui-grid-responsive .ui-grid-col-3, + .ui-grid-responsive .ui-grid-col-4, + .ui-grid-responsive .ui-grid-col-5, + .ui-grid-responsive .ui-grid-col-6, + .ui-grid-responsive .ui-grid-col-7, + .ui-grid-responsive .ui-grid-col-8, + .ui-grid-responsive .ui-grid-col-9, + .ui-grid-responsive .ui-grid-col-10, + .ui-grid-responsive .ui-grid-col-11, + .ui-grid-responsive .ui-grid-col-12 { + width: 100%; + float: none; + } +} + +/* New Grid CSS */ +.ui-g { + display: -webkit-box; + display: -moz-box; + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + flex-wrap: wrap; +} + +.ui-g:after { + clear: both; + content: ""; + display: table; +} + +.ui-g-1, +.ui-g-2, +.ui-g-3, +.ui-g-4, +.ui-g-5, +.ui-g-6, +.ui-g-7, +.ui-g-8, +.ui-g-9, +.ui-g-10, +.ui-g-11, +.ui-g-12 { + float: left; + box-sizing: border-box; + padding: 0.5em; +} + +.ui-g-1 { + width: 8.3333%; +} + +.ui-g-2 { + width: 16.6667%; +} + +.ui-g-3 { + width: 25%; +} + +.ui-g-4 { + width: 33.3333%; +} + +.ui-g-5 { + width: 41.6667%; +} + +.ui-g-6 { + width: 50%; +} + +.ui-g-7 { + width: 58.3333%; +} + +.ui-g-8 { + width: 66.6667%; +} + +.ui-g-9 { + width: 75%; +} + +.ui-g-10 { + width: 83.3333%; +} + +.ui-g-11 { + width: 91.6667%; +} + +.ui-g-12 { + width: 100%; +} + +@media screen and (max-width: 40em) { + .ui-sm-1, + .ui-sm-2, + .ui-sm-3, + .ui-sm-4, + .ui-sm-5, + .ui-sm-6, + .ui-sm-7, + .ui-sm-8, + .ui-sm-9, + .ui-sm-10, + .ui-sm-11, + .ui-sm-12 { + padding: 0.5em; + } + + .ui-sm-1 { + width: 8.3333%; + } + + .ui-sm-2 { + width: 16.6667%; + } + + .ui-sm-3 { + width: 25%; + } + + .ui-sm-4 { + width: 33.3333%; + } + + .ui-sm-5 { + width: 41.6667%; + } + + .ui-sm-6 { + width: 50%; + } + + .ui-sm-7 { + width: 58.3333%; + } + + .ui-sm-8 { + width: 66.6667%; + } + + .ui-sm-9 { + width: 75%; + } + + .ui-sm-10 { + width: 83.3333%; + } + + .ui-sm-11 { + width: 91.6667%; + } + + .ui-sm-12 { + width: 100%; + } +} + +@media screen and (min-width: 40.063em) { + .ui-md-1, + .ui-md-2, + .ui-md-3, + .ui-md-4, + .ui-md-5, + .ui-md-6, + .ui-md-7, + .ui-md-8, + .ui-md-9, + .ui-md-10, + .ui-md-11, + .ui-md-12 { + padding: 0.5em; + } + + .ui-md-1 { + width: 8.3333%; + } + + .ui-md-2 { + width: 16.6667%; + } + + .ui-md-3 { + width: 25%; + } + + .ui-md-4 { + width: 33.3333%; + } + + .ui-md-5 { + width: 41.6667%; + } + + .ui-md-6 { + width: 50%; + } + + .ui-md-7 { + width: 58.3333%; + } + + .ui-md-8 { + width: 66.6667%; + } + + .ui-md-9 { + width: 75%; + } + + .ui-md-10 { + width: 83.3333%; + } + + .ui-md-11 { + width: 91.6667%; + } + + .ui-md-12 { + width: 100%; + } +} + +@media screen and (min-width: 64.063em) { + .ui-lg-1, + .ui-lg-2, + .ui-lg-3, + .ui-lg-4, + .ui-lg-5, + .ui-lg-6, + .ui-lg-7, + .ui-lg-8, + .ui-lg-9, + .ui-lg-10, + .ui-lg-11, + .ui-lg-12 { + padding: 0.5em; + } + + .ui-lg-1 { + width: 8.3333%; + } + + .ui-lg-2 { + width: 16.6667%; + } + + .ui-lg-3 { + width: 25%; + } + + .ui-lg-4 { + width: 33.3333%; + } + + .ui-lg-5 { + width: 41.6667%; + } + + .ui-lg-6 { + width: 50%; + } + + .ui-lg-7 { + width: 58.3333%; + } + + .ui-lg-8 { + width: 66.6667%; + } + + .ui-lg-9 { + width: 75%; + } + + .ui-lg-10 { + width: 83.3333%; + } + + .ui-lg-11 { + width: 91.6667%; + } + + .ui-lg-12 { + width: 100%; + } +} + +@media screen and (min-width: 90.063em) { + .ui-xl-1, + .ui-xl-2, + .ui-xl-3, + .ui-xl-4, + .ui-xl-5, + .ui-xl-6, + .ui-xl-7, + .ui-xl-8, + .ui-xl-9, + .ui-xl-10, + .ui-xl-11, + .ui-xl-12 { + padding: 0.5em; + } + + .ui-xl-1 { + width: 8.3333%; + } + + .ui-xl-2 { + width: 16.6667%; + } + + .ui-xl-3 { + width: 25%; + } + + .ui-xl-4 { + width: 33.3333%; + } + + .ui-xl-5 { + width: 41.6667%; + } + + .ui-xl-6 { + width: 50%; + } + + .ui-xl-7 { + width: 58.3333%; + } + + .ui-xl-8 { + width: 66.6667%; + } + + .ui-xl-9 { + width: 75%; + } + + .ui-xl-10 { + width: 83.3333%; + } + + .ui-xl-11 { + width: 91.6667%; + } + + .ui-xl-12 { + width: 100%; + } +} + +.ui-g-nopad { + padding: 0; +} diff --git a/src/app/components/growl/growl.css b/src/app/components/growl/growl.css new file mode 100644 index 00000000000..228b722bd97 --- /dev/null +++ b/src/app/components/growl/growl.css @@ -0,0 +1,54 @@ +.ui-growl { + position:fixed; + top: 20px; + right: 20px; + width: 20em; +} + +.ui-growl-item-container { + position:relative; + margin:0 0 10px 0; + opacity:0.95; + filter:alpha(opacity=95); +} + +.ui-growl-item { + position: relative; + display: block; + padding: .5em 1em; +} + +.ui-growl-item p { + padding: 0; + margin: 0; +} + +.ui-growl-icon-close { + position: absolute; + top: 4px; + right: 4px; + cursor: pointer; +} + +.ui-growl-title { + font-weight: bold; + padding: 0 0 .5em 0; + display: block; +} + +.ui-growl-image { + position: absolute; + display: inline-block; + left: .5em; + top: .25em; + padding: 0; +} + +.ui-growl-message { + padding: 0 0 .25em 0; + margin-left: 2.5em; +} + +.ui-growl-message p { + font-weight: normal; +} \ No newline at end of file diff --git a/src/app/components/growl/growl.ts b/src/app/components/growl/growl.ts new file mode 100644 index 00000000000..3bcf7679375 --- /dev/null +++ b/src/app/components/growl/growl.ts @@ -0,0 +1,129 @@ +import {NgModule,Component,ElementRef,AfterViewInit,OnDestroy,Input,Output,ViewChild,EventEmitter} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {Message} from '../common/message'; +import {DomHandler} from '../dom/domhandler'; + +@Component({ + selector: 'p-growl', + template: ` +
+
+
+
+ +
+ {{msg.summary}} +

+
+
+
+
+
+ `, + providers: [DomHandler] +}) +export class Growl implements AfterViewInit,OnDestroy { + + @Input() sticky: boolean = false; + + @Input() life: number = 3000; + + @Input() style: any; + + @Input() styleClass: string; + + @Output() onClose: EventEmitter = new EventEmitter(); + + @Output() valueChange: EventEmitter = new EventEmitter(); + + @ViewChild('container') containerViewChild: ElementRef; + + _value: Message[]; + + zIndex: number; + + container: HTMLDivElement; + + timeout: any; + + preventRerender: boolean; + + constructor(public el: ElementRef, public domHandler: DomHandler) { + this.zIndex = DomHandler.zindex; + } + + ngAfterViewInit() { + this.container = this.containerViewChild.nativeElement; + } + + @Input() get value(): Message[] { + return this._value; + } + + set value(val:Message[]) { + this._value = val; + if(this.container) { + this.handleValueChange(); + } + } + + handleValueChange() { + if(this.preventRerender) { + this.preventRerender = false; + return; + } + + this.zIndex = ++DomHandler.zindex; + this.domHandler.fadeIn(this.container, 250); + + if(!this.sticky) { + if(this.timeout) { + clearTimeout(this.timeout); + } + this.timeout = setTimeout(() => { + this.removeAll(); + }, this.life); + } + } + + remove(index: number, msgel: any) { + this.domHandler.fadeOut(msgel, 250); + + setTimeout(() => { + this.preventRerender = true; + this.onClose.emit({message:this.value[index]}); + this._value = this.value.filter((val,i) => i!=index); + this.valueChange.emit(this._value); + }, 250); + } + + removeAll() { + if(this.value && this.value.length) { + this.domHandler.fadeOut(this.container, 250); + + setTimeout(() => { + this.value.forEach((msg,index) => this.onClose.emit({message:this.value[index]})); + this.value = []; + this.valueChange.emit(this.value); + }, 250); + } + } + + ngOnDestroy() { + if(!this.sticky) { + clearTimeout(this.timeout); + } + } + +} + +@NgModule({ + imports: [CommonModule], + exports: [Growl], + declarations: [Growl] +}) +export class GrowlModule { } \ No newline at end of file diff --git a/src/app/components/inplace/inplace.css b/src/app/components/inplace/inplace.css new file mode 100644 index 00000000000..05ed40149f6 --- /dev/null +++ b/src/app/components/inplace/inplace.css @@ -0,0 +1,11 @@ +.ui-inplace .ui-inplace-display { + display: inline; + cursor: pointer; + border: 0 none; + padding: .25em; + font-weight: normal; +} + +.ui-inplace .ui-inplace-content { + display: inline; +} \ No newline at end of file diff --git a/src/app/components/inplace/inplace.ts b/src/app/components/inplace/inplace.ts new file mode 100644 index 00000000000..8270f3e1800 --- /dev/null +++ b/src/app/components/inplace/inplace.ts @@ -0,0 +1,71 @@ +import {NgModule,Component,Input,Output,EventEmitter} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {ButtonModule} from '../button/button'; + +@Component({ + selector: 'p-inplaceDisplay', + template: '' +}) +export class InplaceDisplay {} + +@Component({ + selector: 'p-inplaceContent', + template: '' +}) +export class InplaceContent {} + +@Component({ + selector: 'p-inplace', + template: ` +
+
+ +
+
+ + +
+
+ ` +}) +export class Inplace { + + @Input() active: boolean; + + @Input() closable: boolean; + + @Input() disabled: boolean; + + @Input() style: any; + + @Input() styleClass: string; + + @Output() onActivate: EventEmitter = new EventEmitter(); + + @Output() onDeactivate: EventEmitter = new EventEmitter(); + + hover: boolean; + + activate(event) { + if(!this.disabled) { + this.active = true; + this.onActivate.emit(event); + } + } + + deactivate(event) { + if(!this.disabled) { + this.active = false; + this.hover = false; + this.onDeactivate.emit(event); + } + } +} + +@NgModule({ + imports: [CommonModule,ButtonModule], + exports: [Inplace,InplaceDisplay,InplaceContent,ButtonModule], + declarations: [Inplace,InplaceDisplay,InplaceContent] +}) +export class InplaceModule { } \ No newline at end of file diff --git a/src/app/components/inputmask/inputmask.ts b/src/app/components/inputmask/inputmask.ts new file mode 100644 index 00000000000..a86a3e09853 --- /dev/null +++ b/src/app/components/inputmask/inputmask.ts @@ -0,0 +1,590 @@ +/* + Port of jQuery MaskedInput by DigitalBush as a Native Angular2 Component in Typescript without jQuery + https://github.com/digitalBush/jquery.maskedinput/ + + Copyright (c) 2007-2014 Josh Bush (digitalbush.com) + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +*/ +import {NgModule,Component,ElementRef,OnInit,OnDestroy,HostBinding,HostListener,Input,forwardRef,Output,EventEmitter,ViewChild} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {DomHandler} from '../dom/domhandler'; +import {InputTextModule} from '../inputtext/inputtext'; +import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; + +export const INPUTMASK_VALUE_ACCESSOR: any = { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => InputMask), + multi: true +}; + +@Component({ + selector: 'p-inputMask', + template: ``, + host: { + '[class.ui-inputwrapper-filled]': 'filled', + '[class.ui-inputwrapper-focus]': 'focus' + }, + providers: [INPUTMASK_VALUE_ACCESSOR,DomHandler] +}) +export class InputMask implements OnInit,OnDestroy,ControlValueAccessor { + + @Input() mask: string; + + @Input() type: string = 'text'; + + @Input() slotChar: string = '_'; + + @Input() autoClear: boolean = true; + + @Input() style: string; + + @Input() inputId: string; + + @Input() styleClass: string; + + @Input() placeholder: string; + + @Input() size: number; + + @Input() maxlength: number; + + @Input() tabindex: string; + + @Input() disabled: boolean; + + @Input() readonly: boolean; + + @Input() unmask: boolean; + + @Input() name: string; + + @ViewChild('input') inputViewChild: ElementRef; + + @Output() onComplete: EventEmitter = new EventEmitter(); + + @Output() onBlur: EventEmitter = new EventEmitter(); + + value: any; + + onModelChange: Function = () => {}; + + onModelTouched: Function = () => {}; + + input: HTMLInputElement; + + filled: boolean; + + defs: any; + + tests: any[]; + + partialPosition: any; + + firstNonMaskPos: number; + + lastRequiredNonMaskPos: any; + + len: number; + + oldVal: string; + + buffer: any; + + defaultBuffer: string; + + focusText: string; + + caretTimeoutId: any; + + androidChrome: boolean; + + focus: boolean; + + constructor(public el: ElementRef, public domHandler: DomHandler) {} + + ngOnInit() { + this.tests = []; + this.partialPosition = this.mask.length; + this.len = this.mask.length; + this.firstNonMaskPos = null; + this.defs = { + '9': '[0-9]', + 'a': '[A-Za-z]', + '*': '[A-Za-z0-9]' + }; + + let ua = this.domHandler.getUserAgent(); + this.androidChrome = /chrome/i.test(ua) && /android/i.test(ua); + + let maskTokens = this.mask.split(''); + for(let i = 0; i < maskTokens.length; i++) { + let c = maskTokens[i]; + if (c == '?') { + this.len--; + this.partialPosition = i; + } + else if (this.defs[c]) { + this.tests.push(new RegExp(this.defs[c])); + if(this.firstNonMaskPos === null) { + this.firstNonMaskPos = this.tests.length - 1; + } + if(i < this.partialPosition){ + this.lastRequiredNonMaskPos = this.tests.length - 1; + } + } + else { + this.tests.push(null); + } + } + + this.buffer = []; + for(let i = 0; i < maskTokens.length; i++) { + let c = maskTokens[i]; + if(c != '?') { + if(this.defs[c]) + this.buffer.push(this.getPlaceholder(i)); + else + this.buffer.push(c); + } + } + this.defaultBuffer = this.buffer.join(''); + } + + writeValue(value: any) : void { + this.value = value; + + if(this.inputViewChild.nativeElement) { + if(this.value == undefined || this.value == null) + this.inputViewChild.nativeElement.value = ''; + else + this.inputViewChild.nativeElement.value = this.value; + + this.checkVal(); + this.focusText = this.inputViewChild.nativeElement.value; + this.updateFilledState(); + } + } + + registerOnChange(fn: Function): void { + this.onModelChange = fn; + } + + registerOnTouched(fn: Function): void { + this.onModelTouched = fn; + } + + setDisabledState(val: boolean): void { + this.disabled = val; + } + + caret(first?: number, last?: number) { + let range, begin, end; + + if(!this.inputViewChild.nativeElement.offsetParent||this.inputViewChild.nativeElement !== document.activeElement) { + return; + } + + if(typeof first == 'number') { + begin = first; + end = (typeof last === 'number') ? last : begin; + if(this.inputViewChild.nativeElement.setSelectionRange) { + this.inputViewChild.nativeElement.setSelectionRange(begin, end); + } + else if(this.inputViewChild.nativeElement['createTextRange']) { + range = this.inputViewChild.nativeElement['createTextRange'](); + range.collapse(true); + range.moveEnd('character', end); + range.moveStart('character', begin); + range.select(); + } + } + else { + if (this.inputViewChild.nativeElement.setSelectionRange) { + begin = this.inputViewChild.nativeElement.selectionStart; + end = this.inputViewChild.nativeElement.selectionEnd; + } + else if (document['selection'] && document['selection'].createRange) { + range = document['selection'].createRange(); + begin = 0 - range.duplicate().moveStart('character', -100000); + end = begin + range.text.length; + } + + return {begin: begin, end: end}; + } + } + + isCompleted(): boolean { + let completed: boolean; + for (let i = this.firstNonMaskPos; i <= this.lastRequiredNonMaskPos; i++) { + if (this.tests[i] && this.buffer[i] === this.getPlaceholder(i)) { + return false; + } + } + + return true; + } + + getPlaceholder(i: number) { + if(i < this.slotChar.length) { + return this.slotChar.charAt(i); + } + return this.slotChar.charAt(0); + } + + seekNext(pos) { + while (++pos < this.len && !this.tests[pos]); + return pos; + } + + seekPrev(pos) { + while (--pos >= 0 && !this.tests[pos]); + return pos; + } + + shiftL(begin:number,end:number) { + let i, j; + + if (begin<0) { + return; + } + + for (i = begin, j = this.seekNext(end); i < this.len; i++) { + if (this.tests[i]) { + if (j < this.len && this.tests[i].test(this.buffer[j])) { + this.buffer[i] = this.buffer[j]; + this.buffer[j] = this.getPlaceholder(j); + } else { + break; + } + + j = this.seekNext(j); + } + } + this.writeBuffer(); + this.caret(Math.max(this.firstNonMaskPos, begin)); + } + + shiftR(pos) { + let i, c, j, t; + + for (i = pos, c = this.getPlaceholder(pos); i < this.len; i++) { + if (this.tests[i]) { + j = this.seekNext(i); + t = this.buffer[i]; + this.buffer[i] = c; + if (j < this.len && this.tests[j].test(t)) { + c = t; + } else { + break; + } + } + } + } + + handleAndroidInput(e) { + var curVal = this.inputViewChild.nativeElement.value; + var pos = this.caret(); + if (this.oldVal && this.oldVal.length && this.oldVal.length > curVal.length ) { + // a deletion or backspace happened + this.checkVal(true); + while (pos.begin > 0 && !this.tests[pos.begin-1]) + pos.begin--; + if (pos.begin === 0) + { + while (pos.begin < this.firstNonMaskPos && !this.tests[pos.begin]) + pos.begin++; + } + this.caret(pos.begin,pos.begin); + } else { + this.checkVal(true); + while (pos.begin < this.len && !this.tests[pos.begin - 1]) + pos.begin++; + + setTimeout(() => this.caret(pos.begin, pos.begin)); + } + + if(this.isCompleted()) { + this.onComplete.emit(); + } + } + + onInputBlur(e) { + this.focus = false; + this.onModelTouched(); + this.checkVal(); + this.updateModel(e); + this.updateFilledState(); + this.onBlur.emit(e); + + if (this.inputViewChild.nativeElement.value != this.focusText) { + let event = document.createEvent('HTMLEvents'); + event.initEvent('change', true, false); + this.inputViewChild.nativeElement.dispatchEvent(event); + } + } + + onKeyDown(e) { + if (this.readonly) { + return; + } + + let k = e.which||e.keyCode, + pos, + begin, + end; + let iPhone = /iphone/i.test(this.domHandler.getUserAgent()); + this.oldVal = this.inputViewChild.nativeElement.value; + + //backspace, delete, and escape get special treatment + if (k === 8 || k === 46 || (iPhone && k === 127)) { + pos = this.caret(); + begin = pos.begin; + end = pos.end; + + + if (end - begin === 0) { + begin=k!==46?this.seekPrev(begin):(end=this.seekNext(begin-1)); + end=k===46?this.seekNext(end):end; + } + + this.clearBuffer(begin, end); + this.shiftL(begin, end - 1); + this.updateModel(e); + + e.preventDefault(); + } else if( k === 13 ) { // enter + this.onInputBlur(e); + this.updateModel(e); + } else if (k === 27) { // escape + this.inputViewChild.nativeElement.value = this.focusText; + this.caret(0, this.checkVal()); + this.updateModel(e); + e.preventDefault(); + } + } + + onKeyPress(e) { + if (this.readonly){ + return; + } + + var k = e.which || e.keyCode, + pos = this.caret(), + p, + c, + next, + completed; + + if (e.ctrlKey || e.altKey || e.metaKey || k < 32) {//Ignore + return; + } else if ( k && k !== 13 ) { + if (pos.end - pos.begin !== 0){ + this.clearBuffer(pos.begin, pos.end); + this.shiftL(pos.begin, pos.end-1); + } + + p = this.seekNext(pos.begin - 1); + if (p < this.len) { + c = String.fromCharCode(k); + if (this.tests[p].test(c)) { + this.shiftR(p); + + this.buffer[p] = c; + this.writeBuffer(); + next = this.seekNext(p); + + if(/android/i.test(this.domHandler.getUserAgent())){ + //Path for CSP Violation on FireFox OS 1.1 + let proxy = () => { + this.caret(next); + }; + + setTimeout(proxy,0); + }else{ + this.caret(next); + } + if(pos.begin <= this.lastRequiredNonMaskPos){ + completed = this.isCompleted(); + } + } + } + e.preventDefault(); + } + + this.updateModel(e); + + this.updateFilledState(); + + if(completed) { + this.onComplete.emit(); + } + } + + clearBuffer(start, end) { + let i; + for (i = start; i < end && i < this.len; i++) { + if (this.tests[i]) { + this.buffer[i] = this.getPlaceholder(i); + } + } + } + + writeBuffer() { + this.inputViewChild.nativeElement.value = this.buffer.join(''); + } + + checkVal(allow?: boolean) { + //try to place characters where they belong + let test = this.inputViewChild.nativeElement.value, + lastMatch = -1, + i, + c, + pos; + + for (i = 0, pos = 0; i < this.len; i++) { + if (this.tests[i]) { + this.buffer[i] = this.getPlaceholder(i); + while (pos++ < test.length) { + c = test.charAt(pos - 1); + if (this.tests[i].test(c)) { + this.buffer[i] = c; + lastMatch = i; + break; + } + } + if (pos > test.length) { + this.clearBuffer(i + 1, this.len); + break; + } + } else { + if (this.buffer[i] === test.charAt(pos)) { + pos++; + } + if( i < this.partialPosition){ + lastMatch = i; + } + } + } + if (allow) { + this.writeBuffer(); + } else if (lastMatch + 1 < this.partialPosition) { + if (this.autoClear || this.buffer.join('') === this.defaultBuffer) { + // Invalid value. Remove it and replace it with the + // mask, which is the default behavior. + if(this.inputViewChild.nativeElement.value) this.inputViewChild.nativeElement.value = ''; + this.clearBuffer(0, this.len); + } else { + // Invalid value, but we opt to show the value to the + // user and allow them to correct their mistake. + this.writeBuffer(); + } + } else { + this.writeBuffer(); + this.inputViewChild.nativeElement.value = this.inputViewChild.nativeElement.value.substring(0, lastMatch + 1); + } + return (this.partialPosition ? i : this.firstNonMaskPos); + } + + onFocus(event) { + if (this.readonly){ + return; + } + + this.focus = true; + + clearTimeout(this.caretTimeoutId); + let pos; + + this.focusText = this.inputViewChild.nativeElement.value; + + pos = this.checkVal(); + + this.caretTimeoutId = setTimeout(() => { + if(this.inputViewChild.nativeElement !== document.activeElement){ + return; + } + this.writeBuffer(); + if (pos == this.mask.replace("?","").length) { + this.caret(0, pos); + } else { + this.caret(pos); + } + }, 10); + } + + onInput(event) { + if (this.androidChrome) + this.handleAndroidInput(event); + else + this.handleInputChange(event); + } + + handleInputChange(event) { + if (this.readonly){ + return; + } + + setTimeout(() => { + var pos = this.checkVal(true); + this.caret(pos); + this.updateModel(event); + if(this.isCompleted()) { + this.onComplete.emit(); + } + }, 0); + } + + getUnmaskedValue() { + let unmaskedBuffer = []; + for(let i = 0; i < this.buffer.length; i++) { + let c = this.buffer[i]; + if(this.tests[i] && c != this.getPlaceholder(i)) { + unmaskedBuffer.push(c); + } + } + + return unmaskedBuffer.join(''); + } + + updateModel(e) { + this.onModelChange(this.unmask ? this.getUnmaskedValue() : e.target.value); + } + + updateFilledState() { + this.filled = this.inputViewChild.nativeElement && this.inputViewChild.nativeElement.value != ''; + } + + ngOnDestroy() { + + } +} + +@NgModule({ + imports: [CommonModule,InputTextModule], + exports: [InputMask], + declarations: [InputMask] +}) +export class InputMaskModule { } \ No newline at end of file diff --git a/src/app/components/inputswitch/inputswitch.css b/src/app/components/inputswitch/inputswitch.css new file mode 100644 index 00000000000..da01d4378cc --- /dev/null +++ b/src/app/components/inputswitch/inputswitch.css @@ -0,0 +1,58 @@ +.ui-inputswitch { + display: inline-block; + padding: 0; + position: relative; + overflow: hidden; + cursor: pointer; + user-select: none; + -moz-user-select: none; + -khtml-user-select: none; + -webkit-user-select: none; + height: 1.5em; +} + +.ui-inputswitch .ui-inputswitch-on, +.ui-inputswitch .ui-inputswitch-off { + white-space: nowrap; + display: inline-block; + position: absolute; + top: 0; + width: auto; + overflow: hidden; + user-select: none; + -moz-user-select: none; + -khtml-user-select: none; + -webkit-user-select: none; + font-weight: bold; + height: 100%; + line-height: 1.5em; +} + +.ui-inputswitch .ui-inputswitch-on { + left: 0; + border: 0 none; +} + +.ui-inputswitch .ui-inputswitch-off { + right: 0; + text-align: right; +} + +.ui-inputswitch .ui-inputswitch-on span, +.ui-inputswitch .ui-inputswitch-off span { + display: inline-block; + text-align: center; + height: 100%; + line-height: inherit; +} + +.ui-inputswitch .ui-inputswitch-handle { + display: block; + width: 0; + position: absolute; + top: 0; + left: 0; + height: 100%; + border-top: 0 none; + border-bottom: 0 none; +} \ No newline at end of file diff --git a/src/app/components/inputswitch/inputswitch.ts b/src/app/components/inputswitch/inputswitch.ts new file mode 100644 index 00000000000..52ab91305ee --- /dev/null +++ b/src/app/components/inputswitch/inputswitch.ts @@ -0,0 +1,200 @@ +import {NgModule,Component,ElementRef,AfterViewInit,AfterViewChecked,OnChanges,Input,forwardRef,EventEmitter,Output} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {NG_VALUE_ACCESSOR,ControlValueAccessor} from '@angular/forms'; +import {DomHandler} from '../dom/domhandler'; + +export const INPUTSWITCH_VALUE_ACCESSOR: any = { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => InputSwitch), + multi: true +}; + +@Component({ + selector: 'p-inputSwitch', + template: ` +
+
+ {{offLabel}} +
+
+ {{onLabel}} +
+
+
+ +
+
+ `, + providers: [INPUTSWITCH_VALUE_ACCESSOR,DomHandler] +}) +export class InputSwitch implements ControlValueAccessor,AfterViewInit,AfterViewChecked { + + @Input() onLabel: string = 'On'; + + @Input() offLabel: string = 'Off'; + + @Input() disabled: boolean; + + @Input() style: any; + + @Input() styleClass: string; + + @Input() tabindex: number; + + @Input() inputId: string; + + @Output() onChange: EventEmitter = new EventEmitter(); + + checked: boolean = false; + + focused: boolean = false; + + onModelChange: Function = () => {}; + + onModelTouched: Function = () => {}; + + public container: any; + + public handle: any; + + public onContainer: any; + + public offContainer: any; + + public onLabelChild: any; + + public offLabelChild: any; + + public offset: any; + + initialized: boolean = false; + + constructor(public el: ElementRef, public domHandler: DomHandler) {} + + ngAfterViewInit() { + this.container = this.el.nativeElement.children[0]; + this.handle = this.domHandler.findSingle(this.el.nativeElement, 'div.ui-inputswitch-handle'); + this.onContainer = this.domHandler.findSingle(this.container,'div.ui-inputswitch-on'); + this.offContainer = this.domHandler.findSingle(this.container,'div.ui-inputswitch-off'); + this.onLabelChild = this.domHandler.findSingle(this.onContainer,'span.ui-inputswitch-onlabel'); + this.offLabelChild = this.domHandler.findSingle(this.offContainer,'span.ui-inputswitch-offlabel'); + } + + ngAfterViewChecked() { + if(this.container.offsetParent && !this.initialized) { + this.render(); + } + } + + render() { + let onContainerWidth = this.domHandler.width(this.onContainer), + offContainerWidth = this.domHandler.width(this.offContainer), + spanPadding = this.domHandler.innerWidth(this.offLabelChild) - this.domHandler.width(this.offLabelChild), + handleMargins = this.domHandler.getOuterWidth(this.handle) - this.domHandler.innerWidth(this.handle); + + var containerWidth = (onContainerWidth > offContainerWidth) ? onContainerWidth : offContainerWidth, + handleWidth = containerWidth; + + this.handle.style.width = handleWidth + 'px'; + handleWidth = this.domHandler.width(this.handle); + containerWidth = containerWidth + handleWidth + 6; + + var labelWidth = containerWidth - handleWidth - spanPadding - handleMargins; + + this.container.style.width = containerWidth + 'px'; + this.onLabelChild.style.width = labelWidth + 'px'; + this.offLabelChild.style.width = labelWidth + 'px'; + + //position + this.offContainer.style.width = (this.domHandler.width(this.container) - 5) + 'px'; + this.offset = this.domHandler.width(this.container) - this.domHandler.getOuterWidth(this.handle); + + //default value + if(this.checked) { + this.handle.style.left = this.offset + 'px'; + this.onContainer.style.width = this.offset + 'px'; + this.offLabelChild.style.marginRight = -this.offset + 'px'; + } + else { + this.onContainer.style.width = 0 + 'px'; + this.onLabelChild.style.marginLeft = -this.offset + 'px'; + } + + this.initialized = true; + } + + toggle(event,checkbox) { + if(!this.disabled) { + if(this.checked) { + this.checked = false; + this.uncheckUI() + } + else { + this.checked = true; + this.checkUI(); + } + + this.onModelChange(this.checked); + this.onChange.emit({ + originalEvent: event, + checked: this.checked + }); + checkbox.focus(); + } + } + + checkUI() { + this.onContainer.style.width = this.offset + 'px'; + this.onLabelChild.style.marginLeft = 0 + 'px'; + this.offLabelChild.style.marginRight = -this.offset + 'px'; + this.handle.style.left = this.offset + 'px'; + } + + uncheckUI() { + this.onContainer.style.width = 0 + 'px'; + this.onLabelChild.style.marginLeft = -this.offset + 'px'; + this.offLabelChild.style.marginRight = 0 + 'px'; + this.handle.style.left = 0 + 'px'; + } + + onFocus(event) { + this.focused = true; + } + + onBlur(event) { + this.focused = false; + this.onModelTouched(); + } + + writeValue(checked: any) : void { + this.checked = checked; + + if(this.initialized) { + if(this.checked === true) + this.checkUI(); + else + this.uncheckUI(); + } + } + + registerOnChange(fn: Function): void { + this.onModelChange = fn; + } + + registerOnTouched(fn: Function): void { + this.onModelTouched = fn; + } + + setDisabledState(val: boolean): void { + this.disabled = val; + } +} + +@NgModule({ + imports: [CommonModule], + exports: [InputSwitch], + declarations: [InputSwitch] +}) +export class InputSwitchModule { } diff --git a/src/app/components/inputtext/inputtext.css b/src/app/components/inputtext/inputtext.css new file mode 100644 index 00000000000..1163fe103eb --- /dev/null +++ b/src/app/components/inputtext/inputtext.css @@ -0,0 +1,18 @@ +.ui-inputtext { + margin: 0; + outline: medium none; + padding: .25em; + font-weight: normal; +} + +.ui-widget-header .ui-inputtext, +.ui-widget-content .ui-inputtext { + font-weight: normal; +} + +.ui-fluid .ui-inputtext { + width: 100%; + box-sizing: border-box; + -webkit-box-sizing:border-box; + -moz-box-sizing: border-box; +} \ No newline at end of file diff --git a/src/app/components/inputtext/inputtext.ts b/src/app/components/inputtext/inputtext.ts new file mode 100644 index 00000000000..6acba8eefb7 --- /dev/null +++ b/src/app/components/inputtext/inputtext.ts @@ -0,0 +1,40 @@ +import {NgModule,Directive,ElementRef,HostListener,Input,DoCheck} from '@angular/core'; +import {CommonModule} from '@angular/common'; + +@Directive({ + selector: '[pInputText]', + host: { + '[class.ui-inputtext]': 'true', + '[class.ui-corner-all]': 'true', + '[class.ui-state-default]': 'true', + '[class.ui-widget]': 'true', + '[class.ui-state-filled]': 'filled' + } +}) +export class InputText implements DoCheck { + + filled: boolean; + + constructor(public el: ElementRef) {} + + ngDoCheck() { + this.updateFilledState(); + } + + //To trigger change detection to manage ui-state-filled for material labels when there is no value binding + @HostListener('input', ['$event']) + onInput(e) { + this.updateFilledState(); + } + + updateFilledState() { + this.filled = this.el.nativeElement.value && this.el.nativeElement.value.length; + } +} + +@NgModule({ + imports: [CommonModule], + exports: [InputText], + declarations: [InputText] +}) +export class InputTextModule { } \ No newline at end of file diff --git a/src/app/components/inputtextarea/inputtextarea.css b/src/app/components/inputtextarea/inputtextarea.css new file mode 100644 index 00000000000..f7ee7d87e0a --- /dev/null +++ b/src/app/components/inputtextarea/inputtextarea.css @@ -0,0 +1,8 @@ +.ui-inputtextarea-resizable { + overflow: hidden; + resize:none; +} + +.ui-fluid .ui-inputtextarea { + width: 100%; +} \ No newline at end of file diff --git a/src/app/components/inputtextarea/inputtextarea.ts b/src/app/components/inputtextarea/inputtextarea.ts new file mode 100644 index 00000000000..28c8b0ae92b --- /dev/null +++ b/src/app/components/inputtextarea/inputtextarea.ts @@ -0,0 +1,89 @@ +import {NgModule,Directive,ElementRef,HostListener,Input,OnInit,DoCheck} from '@angular/core'; +import {CommonModule} from '@angular/common'; + +@Directive({ + selector: '[pInputTextarea]', + host: { + '[class.ui-inputtext]': 'true', + '[class.ui-corner-all]': 'true', + '[class.ui-state-default]': 'true', + '[class.ui-widget]': 'true', + '[class.ui-state-filled]': 'filled', + '[attr.rows]': 'rows', + '[attr.cols]': 'cols' + } +}) +export class InputTextarea implements OnInit,DoCheck { + + @Input() autoResize: boolean; + + @Input() rows: number; + + @Input() cols: number; + + rowsDefault: number; + + colsDefault: number; + + filled: boolean; + + constructor(public el: ElementRef) {} + + ngOnInit() { + this.rowsDefault = this.rows; + this.colsDefault = this.cols; + } + + ngDoCheck() { + this.updateFilledState(); + } + + //To trigger change detection to manage ui-state-filled for material labels when there is no value binding + @HostListener('input', ['$event']) + onInput(e) { + this.updateFilledState(); + } + + updateFilledState() { + this.filled = this.el.nativeElement.value && this.el.nativeElement.value.length; + } + + @HostListener('focus', ['$event']) + onFocus(e) { + if(this.autoResize) { + this.resize(); + } + } + + @HostListener('blur', ['$event']) + onBlur(e) { + if(this.autoResize) { + this.resize(); + } + } + + @HostListener('keyup', ['$event']) + onKeyup(e) { + if(this.autoResize) { + this.resize(); + } + } + + resize () { + let linesCount = 0, + lines = this.el.nativeElement.value.split('\n'); + + for(let i = lines.length-1; i >= 0 ; --i) { + linesCount += Math.floor((lines[i].length / this.colsDefault) + 1); + } + + this.rows = (linesCount >= this.rowsDefault) ? (linesCount + 1) : this.rowsDefault; + } +} + +@NgModule({ + imports: [CommonModule], + exports: [InputTextarea], + declarations: [InputTextarea] +}) +export class InputTextareaModule { } \ No newline at end of file diff --git a/src/app/components/lightbox/images/loading.gif b/src/app/components/lightbox/images/loading.gif new file mode 100644 index 00000000000..19c67bbd040 Binary files /dev/null and b/src/app/components/lightbox/images/loading.gif differ diff --git a/src/app/components/lightbox/lightbox.css b/src/app/components/lightbox/lightbox.css new file mode 100644 index 00000000000..6e53a3c74d9 --- /dev/null +++ b/src/app/components/lightbox/lightbox.css @@ -0,0 +1,60 @@ +.ui-lightbox { + position: fixed; +} + +.ui-lightbox-content-wrapper { + position: relative; +} + +.ui-lightbox-content { + position: relative; + margin: 0; + padding: 0; + background-color: #000000; +} + +.ui-lightbox-nav-right, .ui-lightbox-nav-left { + position: absolute; + top: 50%; + cursor: pointer; +} + +.ui-lightbox-nav-left { + left: 0; +} + +.ui-lightbox-nav-right { + right: 0; +} + +.ui-lightbox-loading { + background: url("./images/loading.gif") #000000 center center no-repeat; +} + +.ui-lightbox-caption { + padding: 0.2em 0.4em; + display: none; +} + +.ui-lightbox-caption-text { + margin: 0.3em 0 0.1em 0; + float:left; +} + +.ui-lightbox-close { + float:right; + margin: 0; + padding: .125em; +} + +.ui-lightbox-close.ui-state-hover { + padding: 0; +} + +.ui-lightbox-nav-left, .ui-lightbox-nav-right { + opacity: .5; +} + +.ui-lightbox-nav-left:hover, .ui-lightbox-nav-right:hover{ + opacity: 1; +} \ No newline at end of file diff --git a/src/app/components/lightbox/lightbox.ts b/src/app/components/lightbox/lightbox.ts new file mode 100644 index 00000000000..afdd1422792 --- /dev/null +++ b/src/app/components/lightbox/lightbox.ts @@ -0,0 +1,229 @@ +import {NgModule,Component,ElementRef,Input,Output,Renderer2,AfterViewInit,OnDestroy} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {DomHandler} from '../dom/domhandler'; + +@Component({ + selector: 'p-lightbox', + template: ` +
+ + + +
+ + + +
+
+ +
+ + +
+ +
+
+ {{captionText}} +
+
+
+ `, + providers: [DomHandler] +}) +export class Lightbox implements AfterViewInit,OnDestroy{ + + @Input() images: any[]; + + @Input() type: string = 'image'; + + @Input() style: any; + + @Input() styleClass: string; + + @Input() appendTo: any; + + @Input() easing: 'ease-out'; + + @Input() effectDuration: any = '500ms'; + + public visible: boolean; + + public loading: boolean; + + public currentImage: any; + + public captionText: string; + + public zindex: any; + + public panel: any; + + public index: number; + + public mask: any; + + public preventDocumentClickListener: boolean; + + public documentClickListener: any; + + constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2) {} + + onImageClick(event,image,i,content) { + this.index = i; + this.loading = true; + content.style.width = 32 + 'px'; + content.style.height = 32 + 'px'; + this.show(); + this.displayImage(image); + + this.preventDocumentClickListener = true; + event.preventDefault(); + } + + ngAfterViewInit() { + this.panel = this.domHandler.findSingle(this.el.nativeElement, '.ui-lightbox '); + + if(this.appendTo) { + if(this.appendTo === 'body') + document.body.appendChild(this.panel); + else + this.domHandler.appendChild(this.panel, this.appendTo); + } + + this.documentClickListener = this.renderer.listen('document', 'click', (event) => { + if(!this.preventDocumentClickListener&&this.visible) { + this.hide(event); + } + this.preventDocumentClickListener = false; + }); + } + + onLinkClick(event,content) { + this.show(); + this.preventDocumentClickListener = true; + event.preventDefault(); + } + + displayImage(image) { + setTimeout(() => { + this.currentImage = image; + this.captionText = image.title; + }, 1000); + } + + show() { + this.mask = document.createElement('div'); + this.mask.style.zIndex = ++DomHandler.zindex; + this.domHandler.addMultipleClasses(this.mask, 'ui-widget-overlay ui-dialog-mask'); + document.body.appendChild(this.mask); + + this.zindex = ++DomHandler.zindex; + this.center(); + this.visible = true; + } + + hide(event) { + this.captionText = null; + this.index = null; + this.currentImage = null; + this.visible = false; + this.panel.style.left = 'auto'; + this.panel.style.top = 'auto'; + + if(this.mask) { + document.body.removeChild(this.mask); + this.mask = null; + } + + event.preventDefault(); + } + + center() { + let elementWidth = this.domHandler.getOuterWidth(this.panel); + let elementHeight = this.domHandler.getOuterHeight(this.panel); + if(elementWidth == 0 && elementHeight == 0) { + this.panel.style.visibility = 'hidden'; + this.panel.style.display = 'block'; + elementWidth = this.domHandler.getOuterWidth(this.panel); + elementHeight = this.domHandler.getOuterHeight(this.panel); + this.panel.style.display = 'none'; + this.panel.style.visibility = 'visible'; + } + let viewport = this.domHandler.getViewport(); + let x = (viewport.width - elementWidth) / 2; + let y = (viewport.height - elementHeight) / 2; + + this.panel.style.left = x + 'px'; + this.panel.style.top = y + 'px'; + } + + onImageLoad(event,content) { + let image = event.target; + image.style.visibility = 'hidden'; + image.style.display = 'block'; + let imageWidth = this.domHandler.getOuterWidth(image); + let imageHeight = this.domHandler.getOuterHeight(image); + image.style.display = 'none'; + image.style.visibility = 'visible'; + + content.style.width = imageWidth + 'px'; + content.style.height = imageHeight + 'px'; + this.panel.style.left = parseInt(this.panel.style.left) + (this.domHandler.getOuterWidth(this.panel) - imageWidth) / 2 + 'px'; + this.panel.style.top = parseInt(this.panel.style.top) + (this.domHandler.getOuterHeight(this.panel) - imageHeight) / 2 + 'px'; + + setTimeout(() => { + this.domHandler.fadeIn(image, 500); + image.style.display = 'block'; + //this.captionText = this.currentImage.title; + this.loading = false; + }, parseInt(this.effectDuration)); + } + + prev(placeholder: any) { + this.captionText = null; + this.loading = true; + placeholder.style.display = 'none'; + if(this.index > 0) { + this.displayImage(this.images[--this.index]); + } + } + + next(placeholder: any) { + this.captionText = null; + this.loading = true; + placeholder.style.display = 'none'; + if(this.index <= (this.images.length - 1)) { + this.displayImage(this.images[++this.index]); + } + } + + get leftVisible():boolean { + return this.images && this.images.length && this.index != 0 && !this.loading; + } + + get rightVisible():boolean { + return this.images && this.images.length && this.index < (this.images.length - 1) && !this.loading; + } + + ngOnDestroy() { + if(this.documentClickListener) { + this.documentClickListener(); + } + + if(this.appendTo) { + this.el.nativeElement.appendChild(this.panel); + } + } + +} + +@NgModule({ + imports: [CommonModule], + exports: [Lightbox], + declarations: [Lightbox] +}) +export class LightboxModule { } diff --git a/src/app/components/listbox/listbox.css b/src/app/components/listbox/listbox.css new file mode 100644 index 00000000000..cda0cd5a501 --- /dev/null +++ b/src/app/components/listbox/listbox.css @@ -0,0 +1,67 @@ +.ui-listbox { + overflow:auto; + padding: .25em; + width: 10em; +} + +.ui-listbox .ui-listbox-list { + list-style-type: none; + margin: 0; + padding: 0; +} + +.ui-listbox .ui-listbox-item { + padding: .25em; + border: 0 none; + cursor: pointer; + font-weight: normal; + margin-bottom: 1px; +} + +.ui-listbox .ui-listbox-item > span { + vertical-align: middle; +} + +.ui-listbox .ui-listbox-item:last-child { + margin-bottom: 0; +} + +.ui-listbox.ui-state-disabled .ui-listbox-item { + cursor: default; +} + +.ui-listbox-header { + margin-bottom: 0.3em; + padding: .125em .2em; + position: relative; +} + +.ui-listbox-header .ui-chkbox { + display: inline-block; + vertical-align: middle; + cursor: pointer; +} + +.ui-listbox-header .ui-listbox-filter-container { + display: inline-block; + vertical-align: middle; + position: relative; + width: 7em; +} + +.ui-listbox-header .ui-listbox-filter-container .fa { + position: absolute; + top: .25em; + left: .25em; +} + +.ui-listbox-header .ui-inputtext { + padding: .125em .125em .125em 1.25em; + width: 100%; +} + +/* Fluid */ +.ui-fluid .ui-listbox .ui-listbox-filter-container, +.ui-fluid .ui-listbox .ui-listbox-filter-container input { + width: calc(100% - 32px); +} \ No newline at end of file diff --git a/src/app/components/listbox/listbox.ts b/src/app/components/listbox/listbox.ts new file mode 100644 index 00000000000..c15598fee5d --- /dev/null +++ b/src/app/components/listbox/listbox.ts @@ -0,0 +1,371 @@ +import {NgModule,Component,ElementRef,Input,Output,EventEmitter,AfterContentInit,ContentChildren,QueryList,TemplateRef,IterableDiffers,forwardRef} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {SelectItem} from '../common/selectitem'; +import {SharedModule,PrimeTemplate} from '../common/shared'; +import {DomHandler} from '../dom/domhandler'; +import {ObjectUtils} from '../utils/ObjectUtils'; +import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; + +export const LISTBOX_VALUE_ACCESSOR: any = { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => Listbox), + multi: true +}; + +@Component({ + selector: 'p-listbox', + template: ` +
+
+
+
+ +
+
+ +
+
+
+ + +
+
+
    +
  • +
    +
    + +
    +
    + +
    +
    + {{option.label}} + +
  • +
+
+ `, + providers: [DomHandler,ObjectUtils,LISTBOX_VALUE_ACCESSOR] +}) +export class Listbox implements AfterContentInit,ControlValueAccessor { + + @Input() options: SelectItem[]; + + @Input() multiple: boolean; + + @Input() style: any; + + @Input() styleClass: string; + + @Input() disabled: boolean; + + @Input() checkbox: boolean = false; + + @Input() filter: boolean = false; + + @Input() metaKeySelection: boolean = true; + + @Input() dataKey: string; + + @Output() onChange: EventEmitter = new EventEmitter(); + + @Output() onDblClick: EventEmitter = new EventEmitter(); + + @ContentChildren(PrimeTemplate) templates: QueryList; + + public itemTemplate: TemplateRef; + + public filterValue: string; + + public visibleOptions: SelectItem[]; + + public filtered: boolean; + + public value: any; + + public onModelChange: Function = () => { }; + + public onModelTouched: Function = () => { }; + + public checkboxClick: boolean; + + public optionTouched: boolean; + + constructor(public el: ElementRef, public domHandler: DomHandler, public objectUtils: ObjectUtils) {} + + ngAfterContentInit() { + this.templates.forEach((item) => { + switch(item.getType()) { + case 'item': + this.itemTemplate = item.template; + break; + + default: + this.itemTemplate = item.template; + break; + } + }); + } + + writeValue(value: any): void { + this.value = value; + } + + registerOnChange(fn: Function): void { + this.onModelChange = fn; + } + + registerOnTouched(fn: Function): void { + this.onModelTouched = fn; + } + + setDisabledState(val: boolean): void { + this.disabled = val; + } + + onOptionClick(event, option) { + if(this.disabled) { + return; + } + + if(!this.checkboxClick) { + if(this.multiple) + this.onOptionClickMultiple(event, option); + else + this.onOptionClickSingle(event, option); + } + else { + this.checkboxClick = false; + } + + this.optionTouched = false; + } + + onOptionTouchEnd(event, option) { + if(this.disabled) { + return; + } + + this.optionTouched = true; + } + + onOptionClickSingle(event, option) { + let selected = this.isSelected(option); + let valueChanged = false; + let metaSelection = this.optionTouched ? false : this.metaKeySelection; + + if(metaSelection) { + let metaKey = (event.metaKey || event.ctrlKey); + + if(selected) { + if(metaKey) { + this.value = null; + valueChanged = true; + } + } + else { + this.value = option.value; + valueChanged = true; + } + } + else { + this.value = selected ? null : option.value; + valueChanged = true; + } + + if(valueChanged) { + this.onModelChange(this.value); + this.onChange.emit({ + originalEvent: event, + value: this.value + }); + } + } + + onOptionClickMultiple(event, option) { + let selected = this.isSelected(option); + let valueChanged = false; + let metaSelection = this.optionTouched ? false : this.metaKeySelection; + + if(metaSelection) { + let metaKey = (event.metaKey || event.ctrlKey); + + if(selected) { + if(metaKey) { + this.removeOption(option); + } + else { + this.value = [option.value]; + } + valueChanged = true; + } + else { + this.value = (metaKey) ? this.value || [] : []; + this.value = [...this.value, option.value]; + valueChanged = true; + } + } + else { + if(selected) { + this.removeOption(option); + } + else { + this.value = [...this.value||[],option.value]; + } + + valueChanged = true; + } + + if (valueChanged) { + this.onModelChange(this.value); + this.onChange.emit({ + originalEvent: event, + value: this.value + }); + } + } + + removeOption(option: any): void { + this.value = this.value.filter(val => !this.objectUtils.equals(val, option.value, this.dataKey)); + } + + isSelected(option: SelectItem) { + let selected = false; + + if(this.multiple) { + if(this.value) { + for(let val of this.value) { + if(this.objectUtils.equals(val, option.value, this.dataKey)) { + selected = true; + break; + } + } + } + } + else { + selected = this.objectUtils.equals(this.value, option.value, this.dataKey); + } + + return selected; + } + + get allChecked(): boolean { + if(this.filterValue && this.filterValue.trim().length) + return this.allFilteredSelected(); + else + return this.value&&this.options&&(this.value.length == this.options.length); + } + + allFilteredSelected(): boolean { + let allSelected: boolean; + if(this.value && this.visibleOptions && this.visibleOptions.length) { + allSelected = true; + for(let opt of this.visibleOptions) { + let selected: boolean; + for(let val of this.value) { + if(this.objectUtils.equals(val, opt.value, this.dataKey)) { + selected = true; + } + } + + if(!selected) { + allSelected = false; + break; + } + } + } + + return allSelected; + } + + onFilter(event) { + this.filterValue = event.target.value.trim().toLowerCase(); + this.visibleOptions = []; + for(let i = 0; i < this.options.length; i++) { + let option = this.options[i]; + if(option.label.toLowerCase().indexOf(this.filterValue.toLowerCase()) > -1) { + this.visibleOptions.push(option); + } + } + this.filtered = true; + } + + toggleAll(event, checkbox) { + if(this.disabled || (this.filterValue && this.filterValue.trim().length && (!this.visibleOptions || this.visibleOptions.length === 0))) { + return; + } + + if(checkbox.checked) { + this.value = []; + } + else { + let opts = (this.visibleOptions&&this.visibleOptions.length) ? this.visibleOptions : this.options; + if(opts) { + this.value = []; + for(let i = 0; i < opts.length; i++) { + this.value.push(opts[i].value); + } + } + } + checkbox.checked = !checkbox.checked; + this.onModelChange(this.value); + this.onChange.emit({originalEvent: event, value: this.value}); + } + + isItemVisible(option: SelectItem): boolean { + if(this.filterValue && this.filterValue.trim().length) { + for(let i = 0; i < this.visibleOptions.length; i++) { + if(this.visibleOptions[i].value == option.value) { + return true; + } + } + } + else { + return true; + } + } + + onDoubleClick(event: Event, option: SelectItem): any { + if(this.disabled) { + return; + } + + this.onDblClick.emit({ + originalEvent: event, + value: this.value + }) + } + + onCheckboxClick(event: Event, option: SelectItem) { + if(this.disabled) { + return; + } + + this.checkboxClick = true; + let selected = this.isSelected(option); + + if(selected) { + this.removeOption(option); + } + else { + this.value = this.value ? this.value : []; + this.value = [...this.value,option.value]; + } + + this.onModelChange(this.value); + this.onChange.emit({ + originalEvent: event, + value: this.value + }); + } +} + +@NgModule({ + imports: [CommonModule, SharedModule], + exports: [Listbox, SharedModule], + declarations: [Listbox] +}) +export class ListboxModule { } diff --git a/src/app/components/megamenu/megamenu.ts b/src/app/components/megamenu/megamenu.ts new file mode 100644 index 00000000000..6d8b0b7a168 --- /dev/null +++ b/src/app/components/megamenu/megamenu.ts @@ -0,0 +1,172 @@ +import {NgModule,Component,ElementRef,AfterViewInit,OnDestroy,Input,Output,Renderer2,EventEmitter} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {DomHandler} from '../dom/domhandler'; +import {MenuItem} from '../common/menuitem'; +import {Location} from '@angular/common'; +import {RouterModule} from '@angular/router'; + +@Component({ + selector: 'p-megaMenu', + template: ` +
+ +
+ `, + providers: [DomHandler] +}) +export class MegaMenu implements OnDestroy { + + @Input() model: MenuItem[]; + + @Input() style: any; + + @Input() styleClass: string; + + @Input() orientation: string = 'horizontal'; + + activeItem: any; + + constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2) {} + + onItemMouseEnter(event, item, menuitem: MenuItem) { + if(menuitem.disabled) { + return; + } + + this.activeItem = item; + let submenu = item.children[0].nextElementSibling; + if(submenu) { + submenu.style.zIndex = ++DomHandler.zindex; + + if(this.orientation === 'horizontal') { + submenu.style.top = this.domHandler.getOuterHeight(item.children[0]) + 'px'; + submenu.style.left = '0px'; + } + else if(this.orientation === 'vertical') { + submenu.style.top = '0px'; + submenu.style.left = this.domHandler.getOuterWidth(item.children[0]) + 'px'; + } + } + } + + onItemMouseLeave(event, link) { + this.activeItem = null; + } + + itemClick(event, item: MenuItem) { + if(item.disabled) { + event.preventDefault(); + return; + } + + if(!item.url) { + event.preventDefault(); + } + + if(item.command) { + if(!item.eventEmitter) { + item.eventEmitter = new EventEmitter(); + item.eventEmitter.subscribe(item.command); + } + + item.eventEmitter.emit({ + originalEvent: event, + item: item + }); + } + + this.activeItem = null; + } + + unsubscribe(item: any) { + if(item.eventEmitter) { + item.eventEmitter.unsubscribe(); + } + + if(item.items) { + for(let childItem of item.items) { + this.unsubscribe(childItem); + } + } + } + + ngOnDestroy() { + if(this.model) { + for(let item of this.model) { + this.unsubscribe(item); + } + } + } + + getColumnClass(menuitem: MenuItem) { + let length = menuitem.items ? menuitem.items.length: 0; + let columnClass; + switch(length) { + case 2: + columnClass= 'ui-g-6'; + break; + + case 3: + columnClass= 'ui-g-4'; + break; + + case 4: + columnClass= 'ui-g-3'; + break; + + case 6: + columnClass= 'ui-g-2'; + break; + + default: + columnClass= 'ui-g-12'; + break; + } + + return columnClass; + } +} + +@NgModule({ + imports: [CommonModule,RouterModule], + exports: [MegaMenu,RouterModule], + declarations: [MegaMenu] +}) +export class MegaMenuModule { } \ No newline at end of file diff --git a/src/app/components/menu/menu.css b/src/app/components/menu/menu.css new file mode 100644 index 00000000000..e7a74dbc9f4 --- /dev/null +++ b/src/app/components/menu/menu.css @@ -0,0 +1,302 @@ +.ui-menu { + width: 12.5em; + padding: .25em; + position:relative; +} + +.ui-menu.ui-menu-dynamic { + position: absolute; + display: none; + z-index: 100000; +} + +.ui-menu-list { + position: static; +} + +.ui-menu .ui-menu-list .ui-menuitem { + border: none; +} + +.ui-menu .ui-menu-list .ui-widget-header { + clear:both; + float:left; + width: 100%; + margin: .125em 0; + padding: .25em .5em; +} + +.ui-menu .ui-menuitem-parent, +.ui-menu .ui-menuitem { + width: 100%; + clear: both; + margin: .125em 0; + padding: 0; +} + +.ui-menu .ui-menuitem-link { + display: block; + width: 100%; + outline: none; + text-decoration: none; + font-weight: normal; + border: 1px solid transparent; + line-height: 1em; + padding: .25em; + cursor: pointer; +} + +.ui-menu .ui-menuitem-link .ui-menuitem-icon { + display: inline-block; + vertical-align: middle; +} + +.ui-menu .ui-menuitem-text { + vertical-align: middle; +} + +.ui-menu .ui-widget-header h1, +.ui-menu .ui-widget-header h2, +.ui-menu .ui-widget-header h3, +.ui-menu .ui-widget-header h4, +.ui-menu .ui-widget-header h5, +.ui-menu .ui-widget-header h6 { + font-size: 1em; + margin: 0 auto; +} + +/* Tiered Menu */ +.ui-menu .ui-menu-parent .ui-menu-child { + display: none; + width: 12.5em; + padding: .25em; + position:absolute; + margin: 0; + outline: 0; + text-decoration:none; + list-style:none; +} + +.ui-menu .ui-menu-parent { + position: relative; +} + +.ui-menu .ui-menu-parent .ui-submenu-icon { + float: right; + margin-right: -.25em; +} + +/** MenuButton **/ +.ui-menubutton { + padding: 0; +} + +.ui-menubutton .ui-button { + margin: 0; +} + +/** Menubar **/ +.ui-menu.ui-menubar .ui-menubar-root-list > li > a > .ui-submenu-icon { + float: none; +} + +.ui-menubar { + width:auto; +} + +.ui-menubar .ui-menubar-root-list { + list-style: none; + padding: 0; + margin: 0; +} + +.ui-menubar .ui-menubar-root-list > .ui-menuitem { + display: inline-block; + width: auto; +} + +.ui-menubar .ui-menu-child .ui-menuitem { + width: 100%; +} + +.ui-menubar .ui-menubar-options { + float: right; +} + +/** SlideMenu **/ +.ui-slidemenu .ui-slidemenu-wrapper { + position: relative; +} + +.ui-slidemenu .ui-slidemenu-content { + overflow-x: hidden; + overflow-y: auto; + position: relative; +} + +.ui-slidemenu .ui-menu-list { + position: absolute; + top: 0; +} + +.ui-slidemenu .ui-menu-parent { + position: static; +} + +.ui-slidemenu .ui-menu-child { + box-shadow : none; + border: 0 none; + background: none repeat scroll 0 0 transparent; +} + +.ui-slidemenu-backward { + position: absolute; + bottom: 0; + width: 100%; + padding: 0.2em; + cursor: pointer; + display: none; +} + +.ui-slidemenu-backward .fa { + vertical-align: middle; +} + +.ui-slidemenu-backward span { + vertical-align: middle; +} + +.ui-slidemenu .ui-slidemenuitem-active > .ui-submenu > ul { + display: block !important; +} + +/** MegaMenu **/ +.ui-megamenu .ui-g { + flex-wrap: nowrap; +} + +.ui-megamenu .ui-megamenu-panel.ui-menu-child { + width: auto; +} + +.ui-megamenu .ui-megamenu-panel .ui-menu-list { + width: 12.5em; +} + +.ui-megamenu-vertical { + width: 12.5em; +} + +.ui-megamenu-vertical .ui-menuitem-link, +.ui-megamenu-vertical .ui-menu-list .ui-menuitem { + width: 100%; + box-sizing: border-box; +} + +.ui-megamenu-vertical > .ui-menubar-root-list > .ui-menuitem > .ui-menuitem-link > .ui-submenu-icon { + float: right; +} + +/** PanelMenu **/ +.ui-panelmenu { + width: auto; +} + +.ui-panelmenu .ui-panelmenu-panel { + padding: 0; + margin: 0; +} + +.ui-panelmenu .ui-panelmenu-header { + cursor: pointer; + position: relative; + margin: -1px 0 0 0; + zoom: 1; +} + +.ui-panelmenu .ui-panelmenu-header a { + display: block; + padding: .25em .5em; +} + +.ui-panelmenu span { + vertical-align: middle; +} + +.ui-panelmenu .fa { + width: 1em; + text-align: center; + vertical-align: middle; + margin-right: .25em; +} + +.ui-panelmenu .ui-menuitem-text { + margin-left: .125em; +} + +.ui-panelmenu span { + vertical-align: middle; +} + +.ui-panelmenu .ui-panelmenu-content { + padding: 0.2em 0; + border-top: 0; + overflow: auto; + zoom: 1; + outline: none; + margin-bottom: 1px; +} + +.ui-panelmenu .ui-panelmenu-content-wrapper { + box-sizing: border-box; +} + +.ui-panelmenu .ui-panelmenu-content-wrapper-overflown { + overflow: hidden; +} + +.ui-panelmenu .ui-panelmenu-header.ui-state-disabled, +.ui-panelmenu .ui-panelmenu-header.ui-state-disabled a { + cursor: default; +} + +.ui-panelmenu .ui-menu-list { + position: static; +} + +.ui-panelmenu .ui-menuitem { + margin: 1px 0; + padding: 0; +} + +.ui-panelmenu .ui-menuitem-link { + display: block; + outline: none; + text-decoration: none; + font-weight: normal; + border: 1px solid transparent; + line-height: 1em; + cursor: pointer; + position: relative; + padding: .25em .5em; +} + +.ui-panelmenu .ui-menu-parent .ui-menu-list { + margin-left: 1.5em; +} + +/** MegaMenu and TieredMenus **/ +.ui-menuitem-active > .ui-submenu > ul, +.ui-menuitem-active > .ui-megamenu-panel { + display: block !important; +} + +.ui-menuitem-outline { + outline: 1px dotted; + z-index: 1; +} + +/** Fluid **/ +.ui-fluid .ui-menu { + width: 100%; +} \ No newline at end of file diff --git a/src/app/components/menu/menu.ts b/src/app/components/menu/menu.ts new file mode 100644 index 00000000000..268115e0f92 --- /dev/null +++ b/src/app/components/menu/menu.ts @@ -0,0 +1,194 @@ +import {NgModule,Component,ElementRef,AfterViewInit,OnDestroy,Input,Output,Renderer2,HostListener,EventEmitter,ViewChild} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {DomHandler} from '../dom/domhandler'; +import {MenuItem} from '../common/menuitem'; +import {RouterModule} from '@angular/router'; + +@Component({ + selector: 'p-menu', + template: ` + + `, + providers: [DomHandler], + host: {'(window:resize)': 'onResize($event)'} +}) +export class Menu implements AfterViewInit,OnDestroy { + + @Input() model: MenuItem[]; + + @Input() popup: boolean; + + @Input() style: any; + + @Input() styleClass: string; + + @Input() appendTo: any; + + @ViewChild('container') containerViewChild: ElementRef; + + container: HTMLDivElement; + + documentClickListener: any; + + preventDocumentDefault: any; + + onResizeTarget: any; + + constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2) {} + + ngAfterViewInit() { + this.container = this.containerViewChild.nativeElement; + + if(this.popup) { + if(this.appendTo) { + if(this.appendTo === 'body') + document.body.appendChild(this.container); + else + this.domHandler.appendChild(this.container, this.appendTo); + } + + this.documentClickListener = this.renderer.listen('document', 'click', () => { + if(!this.preventDocumentDefault) { + this.hide(); + } + this.preventDocumentDefault = false; + }); + } + } + + toggle(event) { + if(this.container.offsetParent) + this.hide(); + else + this.show(event); + + this.preventDocumentDefault = true; + } + + onResize(event) { + if(this.onResizeTarget && this.container.offsetParent) { + this.domHandler.absolutePosition(this.container, this.onResizeTarget); + } + } + + show(event) { + let target = event.currentTarget; + this.onResizeTarget = event.currentTarget; + this.container.style.display = 'block'; + this.domHandler.absolutePosition(this.container, target); + this.domHandler.fadeIn(this.container, 250); + this.preventDocumentDefault = true; + } + + hide() { + this.container.style.display = 'none'; + } + + itemClick(event, item: MenuItem) { + if(item.disabled) { + event.preventDefault(); + return; + } + + if(!item.url) { + event.preventDefault(); + } + + if(item.command) { + if(!item.eventEmitter) { + item.eventEmitter = new EventEmitter(); + item.eventEmitter.subscribe(item.command); + } + + item.eventEmitter.emit({ + originalEvent: event, + item: item + }); + } + + if(this.popup) { + this.hide(); + } + } + + ngOnDestroy() { + if(this.popup) { + if(this.documentClickListener) { + this.documentClickListener(); + } + + if(this.appendTo) { + this.el.nativeElement.appendChild(this.container); + } + } + + if(this.model) { + for(let item of this.model) { + this.unsubscribe(item); + } + } + } + + hasSubMenu(): boolean { + if(this.model) { + for(var item of this.model) { + if(item.items) { + return true; + } + } + } + return false; + } + + unsubscribe(item: any) { + if(item.eventEmitter) { + item.eventEmitter.unsubscribe(); + } + + if(item.items) { + for(let childItem of item.items) { + this.unsubscribe(childItem); + } + } + } +} + +@NgModule({ + imports: [CommonModule,RouterModule], + exports: [Menu,RouterModule], + declarations: [Menu] +}) +export class MenuModule { } \ No newline at end of file diff --git a/src/app/components/menubar/menubar.ts b/src/app/components/menubar/menubar.ts new file mode 100644 index 00000000000..f41ece4e3e3 --- /dev/null +++ b/src/app/components/menubar/menubar.ts @@ -0,0 +1,149 @@ +import {NgModule,Component,ElementRef,AfterViewInit,OnDestroy,Input,Output,Renderer2,EventEmitter} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {DomHandler} from '../dom/domhandler'; +import {MenuItem} from '../common/menuitem'; +import {Location} from '@angular/common'; +import {RouterModule} from '@angular/router'; + +@Component({ + selector: 'p-menubarSub', + template: ` + + `, + providers: [DomHandler] +}) +export class MenubarSub { + + @Input() item: MenuItem; + + @Input() root: boolean; + + constructor(public domHandler: DomHandler) {} + + activeItem: any; + + onItemMouseEnter(event: Event, item: HTMLLIElement, menuitem: MenuItem) { + if(menuitem.disabled) { + return; + } + + this.activeItem = item; + let nextElement = item.children[0].nextElementSibling; + if(nextElement) { + let sublist = nextElement.children[0]; + sublist.style.zIndex = String(++DomHandler.zindex); + + if(this.root) { + sublist.style.top = this.domHandler.getOuterHeight(item.children[0]) + 'px'; + sublist.style.left = '0px' + } + else { + sublist.style.top = '0px'; + sublist.style.left = this.domHandler.getOuterWidth(item.children[0]) + 'px'; + } + } + } + + onItemMouseLeave(event: Event) { + this.activeItem = null; + } + + itemClick(event, item: MenuItem) { + if(item.disabled) { + event.preventDefault(); + return; + } + + if(!item.url) { + event.preventDefault(); + } + + if(item.command) { + if(!item.eventEmitter) { + item.eventEmitter = new EventEmitter(); + item.eventEmitter.subscribe(item.command); + } + + item.eventEmitter.emit({ + originalEvent: event, + item: item + }); + } + + this.activeItem = null; + } + + listClick(event) { + this.activeItem = null; + } + +} + +@Component({ + selector: 'p-menubar', + template: ` +
+ +
+ `, + providers: [DomHandler] +}) +export class Menubar implements OnDestroy { + + @Input() model: MenuItem[]; + + @Input() style: any; + + @Input() styleClass: string; + + constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2) {} + + unsubscribe(item: any) { + if(item.eventEmitter) { + item.eventEmitter.unsubscribe(); + } + + if(item.items) { + for(let childItem of item.items) { + this.unsubscribe(childItem); + } + } + } + + ngOnDestroy() { + if(this.model) { + for(let item of this.model) { + this.unsubscribe(item); + } + } + } + +} + +@NgModule({ + imports: [CommonModule,RouterModule], + exports: [Menubar,RouterModule], + declarations: [Menubar,MenubarSub] +}) +export class MenubarModule { } \ No newline at end of file diff --git a/src/app/components/messages/messages.css b/src/app/components/messages/messages.css new file mode 100644 index 00000000000..d1b03b80f38 --- /dev/null +++ b/src/app/components/messages/messages.css @@ -0,0 +1,73 @@ +.ui-messages { + border: 1px solid; + margin: .5em 0; + padding: 1em 1em 1em .5em; + display: none; + position: relative; +} + +.ui-messages-icon { + display:inline-block; + padding: 0; + vertical-align: middle; +} + +.ui-messages-summary { + font-weight: bold; + margin-left: .25em; +} + +.ui-messages-detail { + margin-left: .25em; +} + +.ui-messages-success { + color: #ffffff; + background-color: #4CAF50; + border-color: #4CAF50; +} + +.ui-messages-info { + color: #ffffff; + background-color: #2196f3; + border-color: #2196f3; +} + +.ui-messages-warn { + color: #ffffff; + background-color: #FFB300; + border-color: #FFB300; +} + +.ui-messages-error { + color: #ffffff; + background-color: #f44336; + border-color: #f44336; +} + +.ui-messages ul { + margin: 0; + padding: 0; + list-style-type: none; + display: inline-block; + vertical-align: middle; +} + +.ui-messages.ui-messages-noicon ul { + margin: 0 1.5em 0 0; +} + +.ui-messages .ui-messages-close { + color: #ffffff; + cursor: pointer; + position: absolute; + top: 5px; + right: 5px; +} + +/* Message */ +.ui-message { + border: 1px solid; + margin: 0px .25em; + padding: .125em .25em; +} \ No newline at end of file diff --git a/src/app/components/messages/messages.ts b/src/app/components/messages/messages.ts new file mode 100644 index 00000000000..2f01b9909f2 --- /dev/null +++ b/src/app/components/messages/messages.ts @@ -0,0 +1,89 @@ +import {NgModule,Component,Input,Output,EventEmitter} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {Message} from '../common/message'; + +@Component({ + selector: 'p-messages', + template: ` +
+ + + + +
    +
  • + {{msg.summary}} + {{msg.detail}} +
  • +
+
+ ` +}) +export class Messages { + + @Input() value: Message[]; + + @Input() closable: boolean = true; + + @Output() valueChange: EventEmitter = new EventEmitter(); + + hasMessages() { + return this.value && this.value.length > 0; + } + + getSeverityClass() { + return this.value[0].severity; + } + + clear(event) { + this.value = []; + this.valueChange.emit(this.value); + + event.preventDefault(); + } + + get icon(): string { + let icon: string = null; + if(this.hasMessages()) { + let msg = this.value[0]; + switch(msg.severity) { + case 'success': + icon = 'fa-check'; + break; + + case 'info': + icon = 'fa-info-circle'; + break; + + case 'error': + icon = 'fa-close'; + break; + + case 'warn': + icon = 'fa-warning'; + break; + + case 'success': + icon = 'fa-check'; + break; + + default: + icon = 'fa-info-circle'; + break; + } + } + + return icon; + } +} + +@NgModule({ + imports: [CommonModule], + exports: [Messages], + declarations: [Messages] +}) +export class MessagesModule { } \ No newline at end of file diff --git a/src/app/components/multiselect/multiselect.css b/src/app/components/multiselect/multiselect.css new file mode 100644 index 00000000000..9742b18f40d --- /dev/null +++ b/src/app/components/multiselect/multiselect.css @@ -0,0 +1,138 @@ +/** MultiSelect **/ +.ui-multiselect { + display: inline-block; + position: relative; + width: auto; + cursor: pointer; +} + +.ui-multiselect .ui-multiselect-trigger { + border-right: none; + border-top: none; + border-bottom: none; + cursor: pointer; + width: 1.5em; + height: 100%; + position: absolute; + right: 0; + top: 0; + padding: 0 .25em; +} + +.ui-multiselect .ui-multiselect-trigger .fa { + margin-top: .4em; + margin-left: -.125em; +} + +.ui-multiselect .ui-multiselect-label-container { + overflow: hidden; +} + +.ui-multiselect .ui-multiselect-label { + display: block; + padding: .25em 2em .25em .25em; + width: auto; + border: none; + cursor: pointer; + text-overflow: ellipsis; + overflow: hidden; +} + +.ui-multiselect.ui-state-disabled .ui-multiselect-trigger, +.ui-multiselect.ui-state-disabled .ui-multiselect-label { + cursor: auto +} + +.ui-multiselect-panel { + padding: 0.2em; + position: absolute; + min-width: 10em; +} + +.ui-multiselect-panel .ui-multiselect-items-wrapper { + overflow: auto; + position: relative; + padding: 0.2em 0; +} + +.ui-multiselect-panel .ui-multiselect-list { + border: 0 none; +} + +.ui-multiselect-panel .ui-multiselect-item { + border: 0 none; + cursor: pointer; + font-weight: normal; + margin: 1px 0; + padding: .125em .25em; + text-align: left; + white-space: nowrap; + display: block; + position: relative; +} + +.ui-multiselect-panel .ui-multiselect-item .ui-chkbox { + display: inline-block; + vertical-align: middle; +} + +.ui-multiselect-panel .ui-multiselect-item label { + display: inline-block; + vertical-align: middle; +} + +.ui-multiselect-header { + margin-bottom: 0.3em; + padding: .25em; + position: relative; + text-align: left; +} + +.ui-multiselect-header .ui-chkbox { + display: inline-block; + vertical-align: middle; + cursor:pointer; +} + +.ui-multiselect-header .ui-multiselect-filter-container { + position: relative; + display: inline-block; + vertical-align: middle; + width: 65%; +} + +.ui-multiselect-header .ui-multiselect-filter-container .fa { + position: absolute; + top: .25em; + left: .125em; +} + +.ui-multiselect-header .ui-inputtext { + padding: .125em .125em .125em 1.25em; + width: 100%; +} + +.ui-multiselect-header .ui-multiselect-close { + position: absolute; + right: .375em; + top: .375em; + display: block; + font-size: 1em; + border: 0 none; +} + +.ui-multiselect-header a.ui-multiselect-all, +.ui-multiselect-header a.ui-multiselect-none { + float:left; + margin-right: 10px; + display: block; +} + +.ui-multiselect-header .ui-multiselect-close.ui-state-hover { + padding:0px; +} + +.ui-fluid .ui-multiselect { + width: 100%; + box-sizing: border-box; +} diff --git a/src/app/components/multiselect/multiselect.ts b/src/app/components/multiselect/multiselect.ts new file mode 100644 index 00000000000..175692f75dd --- /dev/null +++ b/src/app/components/multiselect/multiselect.ts @@ -0,0 +1,408 @@ +import {NgModule,Component,ElementRef,OnInit,AfterViewInit,AfterViewChecked,DoCheck,OnDestroy,Input,Output,Renderer2,EventEmitter,IterableDiffers,forwardRef,ViewChild} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {SelectItem} from '../common/selectitem'; +import {DomHandler} from '../dom/domhandler'; +import {ObjectUtils} from '../utils/ObjectUtils'; +import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; + +export const MULTISELECT_VALUE_ACCESSOR: any = { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MultiSelect), + multi: true +}; + +@Component({ + selector: 'p-multiSelect', + template: ` +
+
+ +
+
+ +
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+ + +
+ + + +
+
+
    +
  • +
    +
    + +
    +
    + +
    +
    + +
  • +
+
+
+
+ `, + providers: [DomHandler,ObjectUtils,MULTISELECT_VALUE_ACCESSOR] +}) +export class MultiSelect implements OnInit,AfterViewInit,AfterViewChecked,DoCheck,OnDestroy,ControlValueAccessor { + + @Input() options: SelectItem[]; + + @Output() onChange: EventEmitter = new EventEmitter(); + + @Output() onBlur: EventEmitter = new EventEmitter(); + + @Input() scrollHeight: string = '200px'; + + @Input() defaultLabel: string = 'Choose'; + + @Input() style: any; + + @Input() styleClass: string; + + @Input() inputId: string; + + @Input() disabled: boolean; + + @Input() filter: boolean = true; + + @Input() overlayVisible: boolean; + + @Input() tabindex: number; + + @Input() appendTo: any; + + @Input() dataKey: string; + + @Input() displaySelectedLabel: boolean = true; + + @Input() maxSelectedLabels: number = 3; + + @Input() selectedItemsLabel: string = '{0} items selected'; + + @ViewChild('container') containerViewChild: ElementRef; + + @ViewChild('panel') panelViewChild: ElementRef; + + public value: any[]; + + public onModelChange: Function = () => {}; + + public onModelTouched: Function = () => {}; + + public valuesAsString: string; + + public focus: boolean; + + public documentClickListener: any; + + public container: HTMLDivElement; + + public panel: HTMLDivElement; + + public selfClick: boolean; + + public panelClick: boolean; + + public filterValue: string; + + public visibleOptions: SelectItem[]; + + public filtered: boolean; + + public valueDiffer: any; + + public optionsDiffer: any; + + constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2, differs: IterableDiffers, public objectUtils: ObjectUtils) { + this.valueDiffer = differs.find([]).create(null); + this.optionsDiffer = differs.find([]).create(null); + } + + ngOnInit() { + this.updateLabel(); + + this.documentClickListener = this.renderer.listen('document', 'click', () => { + if(!this.selfClick && !this.panelClick && this.overlayVisible) { + this.hide(); + } + + this.selfClick = false; + this.panelClick = false; + }); + } + + ngAfterViewInit() { + this.container = this.containerViewChild.nativeElement; + this.panel = this.panelViewChild.nativeElement; + + if(this.appendTo) { + if(this.appendTo === 'body') + document.body.appendChild(this.panel); + else + this.domHandler.appendChild(this.panel, this.appendTo); + } + + if(this.overlayVisible) { + this.show(); + } + } + + ngAfterViewChecked() { + if(this.filtered) { + if(this.appendTo) + this.domHandler.absolutePosition(this.panel, this.container); + else + this.domHandler.relativePosition(this.panel, this.container); + + this.filtered = false; + } + } + + ngDoCheck() { + let valueChanges = this.valueDiffer.diff(this.value); + let optionChanges = this.optionsDiffer.diff(this.options); + + if(valueChanges||optionChanges) { + this.updateLabel(); + } + } + + writeValue(value: any) : void { + this.value = value; + this.updateLabel(); + } + + registerOnChange(fn: Function): void { + this.onModelChange = fn; + } + + registerOnTouched(fn: Function): void { + this.onModelTouched = fn; + } + + setDisabledState(val: boolean): void { + this.disabled = val; + } + + onItemClick(event, value) { + let selectionIndex = this.findSelectionIndex(value); + if(selectionIndex != -1) + this.value = this.value.filter((val,i) => i!=selectionIndex); + else + this.value = [...this.value||[],value]; + + this.onModelChange(this.value); + this.onChange.emit({originalEvent: event, value: this.value}); + } + + isSelected(value) { + return this.findSelectionIndex(value) != -1; + } + + findSelectionIndex(val: any): number { + let index = -1; + + if(this.value) { + for(let i = 0; i < this.value.length; i++) { + if(this.objectUtils.equals(this.value[i], val, this.dataKey)) { + index = i; + break; + } + } + } + + return index; + } + + toggleAll(event, checkbox) { + if(checkbox.checked) { + this.value = []; + } + else { + let opts = this.getVisibleOptions(); + if(opts) { + this.value = []; + for(let i = 0; i < opts.length; i++) { + this.value.push(opts[i].value); + } + } + } + checkbox.checked = !checkbox.checked; + this.onModelChange(this.value); + this.onChange.emit({originalEvent: event, value: this.value}); + } + + isAllChecked() { + if(this.filterValue && this.filterValue.trim().length) + return this.value&&this.visibleOptions&&this.visibleOptions.length&&(this.value.length == this.visibleOptions.length); + else + return this.value&&this.options&&(this.value.length == this.options.length); + } + + show() { + this.overlayVisible = true; + this.panel.style.zIndex = String(++DomHandler.zindex); + + if(this.appendTo) + this.domHandler.absolutePosition(this.panel, this.container); + else + this.domHandler.relativePosition(this.panel, this.container); + + this.domHandler.fadeIn(this.panel, 250); + } + + hide() { + this.overlayVisible = false; + } + + close(event) { + this.hide(); + event.preventDefault(); + event.stopPropagation(); + } + + onMouseclick(event,input) { + if(this.disabled) { + return; + } + + if(!this.panelClick) { + if(this.overlayVisible) { + this.hide(); + } + else { + input.focus(); + this.show(); + } + } + + this.selfClick = true; + } + + onFocus(event) { + this.focus = true; + } + + onInputBlur(event) { + this.focus = false; + this.onBlur.emit({originalEvent: event}); + this.onModelTouched(); + } + + updateLabel() { + if(this.value && this.options && this.value.length && this.displaySelectedLabel) { + let label = ''; + for(let i = 0; i < this.value.length; i++) { + if(i != 0) { + label = label + ', '; + } + label = label + this.findLabelByValue(this.value[i]); + } + + if(this.value.length <= this.maxSelectedLabels) { + this.valuesAsString = label; + } + else { + let pattern = /{(.*?)}/, + newSelectedItemsLabel = this.selectedItemsLabel.replace(this.selectedItemsLabel.match(pattern)[0], this.value.length + ''); + this.valuesAsString = newSelectedItemsLabel; + } + } + else { + this.valuesAsString = this.defaultLabel; + } + } + + findLabelByValue(val: any): string { + let label = null; + for(let i = 0; i < this.options.length; i++) { + let option = this.options[i]; + if(option.value == val) { + label = option.label; + break; + } + } + return label; + } + + onFilter(event) { + this.filterValue = event.target.value.trim().toLowerCase(); + this.visibleOptions = []; + for(let i = 0; i < this.options.length; i++) { + let option = this.options[i]; + if(option.label.toLowerCase().indexOf(this.filterValue.toLowerCase()) > -1) { + this.visibleOptions.push(option); + } + } + this.filtered = true; + } + + isItemVisible(option: SelectItem): boolean { + if(this.filterValue && this.filterValue.trim().length) { + for(let i = 0; i < this.visibleOptions.length; i++) { + if(this.visibleOptions[i].value == option.value) { + return true; + } + } + } + else { + return true; + } + } + + getVisibleOptions(): SelectItem[] { + if(this.filterValue && this.filterValue.trim().length) { + let items = []; + for(let i = 0; i < this.options.length; i++) { + let option = this.options[i]; + if(option.label.toLowerCase().includes(this.filterValue.toLowerCase())) { + items.push(option); + } + } + return items; + } + else { + return this.options; + } + } + + ngOnDestroy() { + if(this.documentClickListener) { + this.documentClickListener(); + } + + if(this.appendTo) { + this.container.appendChild(this.panel); + } + } + +} + +@NgModule({ + imports: [CommonModule], + exports: [MultiSelect], + declarations: [MultiSelect] +}) +export class MultiSelectModule { } diff --git a/src/app/components/orderlist/orderlist.css b/src/app/components/orderlist/orderlist.css new file mode 100644 index 00000000000..e223d039018 --- /dev/null +++ b/src/app/components/orderlist/orderlist.css @@ -0,0 +1,86 @@ +.ui-orderlist { + display: table; +} + +.ui-orderlist .ui-orderlist-caption { + width: 12.5em; +} + +.ui-orderlist .ui-orderlist-list { + list-style-type: none; + margin: 0; + padding: 0; + overflow: auto; + height: 12.5em; + width: 12.5em; +} + +.ui-orderlist .ui-orderlist-list li { + margin: 1px; + padding: .125em; +} + +.ui-orderlist .ui-button { + display: block; + margin-bottom: 0.3em; +} + +.ui-orderlist .ui-orderlist-button.ui-button-text-icon-primary { + width: 100%; +} + +.ui-orderlist .ui-orderlist-item { + cursor: pointer; + border: 0 none; + font-weight: inherit; +} + +.ui-orderlist .ui-orderlist-caption { + text-align: center; + padding: .5em .75em; + border-bottom: 0 none; +} + +.ui-orderlist table { + width: 100%; + border-collapse: collapse; +} + +.ui-orderlist.ui-state-disabled .ui-orderlist-item, +.ui-orderlist.ui-state-disabled .ui-button { + cursor: default; +} + +.ui-orderlist.ui-state-disabled .ui-orderlist-list { + overflow:hidden; +} + +/* Responsive */ +.ui-orderlist.ui-grid-responsive { + display: block; + width: 100%; +} + +.ui-orderlist.ui-grid-responsive .ui-orderlist-controls { + margin-right: .5em; +} + +.ui-orderlist.ui-grid-responsive .ui-orderlist-list, +.ui-orderlist.ui-grid-responsive .ui-orderlist-caption { + width: 100%; +} + +.ui-orderlist.ui-grid-responsive .ui-orderlist-controls .ui-button { + width: 100%; +} + +@media (max-width: 40em) { + .ui-orderlist.ui-grid-responsive .ui-orderlist-controls { + text-align: center; + } + + .ui-orderlist.ui-grid-responsive .ui-orderlist-controls .ui-button { + display: inline; + width: 20%; + } +} \ No newline at end of file diff --git a/src/app/components/orderlist/orderlist.ts b/src/app/components/orderlist/orderlist.ts new file mode 100644 index 00000000000..e28044eed17 --- /dev/null +++ b/src/app/components/orderlist/orderlist.ts @@ -0,0 +1,247 @@ +import {NgModule,Component,ElementRef,AfterViewChecked,AfterContentInit,Input,Output,ContentChildren,QueryList,TemplateRef,EventEmitter} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {ButtonModule} from '../button/button'; +import {SharedModule,PrimeTemplate} from '../common/shared'; +import {DomHandler} from '../dom/domhandler'; + +@Component({ + selector: 'p-orderList', + template: ` +
+
+
+ + + + +
+
+
{{header}}
+
    +
  • + +
  • +
+
+
+
+ `, + providers: [DomHandler] +}) +export class OrderList implements AfterViewChecked,AfterContentInit { + + @Input() value: any[]; + + @Input() header: string; + + @Input() style: any; + + @Input() styleClass: string; + + @Input() listStyle: any; + + @Input() responsive: boolean; + + @Input() metaKeySelection: boolean = true; + + @Output() onReorder: EventEmitter = new EventEmitter(); + + @Output() onSelectionChange: EventEmitter = new EventEmitter(); + + @ContentChildren(PrimeTemplate) templates: QueryList; + + public itemTemplate: TemplateRef; + + selectedItems: any[]; + + movedUp: boolean; + + movedDown: boolean; + + listContainer: any; + + itemTouched: boolean; + + constructor(public el: ElementRef, public domHandler: DomHandler) {} + + ngAfterViewInit() { + this.listContainer = this.domHandler.findSingle(this.el.nativeElement, 'ul.ui-orderlist-list'); + } + + ngAfterContentInit() { + this.templates.forEach((item) => { + switch(item.getType()) { + case 'item': + this.itemTemplate = item.template; + break; + + default: + this.itemTemplate = item.template; + break; + } + }); + } + + ngAfterViewChecked() { + if(this.movedUp||this.movedDown) { + let listItems = this.domHandler.find(this.listContainer, 'li.ui-state-highlight'); + let listItem; + + if(this.movedUp) + listItem = listItems[0]; + else + listItem = listItems[listItems.length - 1]; + + this.domHandler.scrollInView(this.listContainer, listItem); + this.movedUp = false; + this.movedDown = false; + } + } + + onItemClick(event, item) { + let index = this.findIndexInList(item, this.selectedItems); + let selected = (index != -1); + let metaSelection = this.itemTouched ? false : this.metaKeySelection; + + if(metaSelection) { + let metaKey = (event.metaKey||event.ctrlKey); + + if(selected && metaKey) { + this.selectedItems.splice(index, 1); + } + else { + this.selectedItems = (metaKey) ? this.selectedItems||[] : []; + this.selectedItems.push(item); + } + } + else { + if(selected) { + this.selectedItems.splice(index, 1); + } + else { + this.selectedItems = this.selectedItems||[]; + this.selectedItems.push(item); + } + } + + this.onSelectionChange.emit({originalEvent:event, value:this.selectedItems}); + this.itemTouched = false; + } + + onItemTouchEnd(event) { + this.itemTouched = true; + } + + isSelected(item: any) { + return this.findIndexInList(item, this.selectedItems) != -1; + } + + findIndexInList(item: any, list: any): number { + let index: number = -1; + + if(list) { + for(let i = 0; i < list.length; i++) { + if(list[i] == item) { + index = i; + break; + } + } + } + + return index; + } + + moveUp(event,listElement) { + if(this.selectedItems) { + for(let i = 0; i < this.selectedItems.length; i++) { + let selectedItem = this.selectedItems[i]; + let selectedItemIndex: number = this.findIndexInList(selectedItem, this.value); + + if(selectedItemIndex != 0) { + let movedItem = this.value[selectedItemIndex]; + let temp = this.value[selectedItemIndex-1]; + this.value[selectedItemIndex-1] = movedItem; + this.value[selectedItemIndex] = temp; + } + else { + break; + } + } + + this.movedUp = true; + this.onReorder.emit(event); + } + } + + moveTop(event,listElement) { + if(this.selectedItems) { + for(let i = 0; i < this.selectedItems.length; i++) { + let selectedItem = this.selectedItems[i]; + let selectedItemIndex: number = this.findIndexInList(selectedItem, this.value); + + if(selectedItemIndex != 0) { + let movedItem = this.value.splice(selectedItemIndex,1)[0]; + this.value.unshift(movedItem); + listElement.scrollTop = 0; + } + else { + break; + } + } + + this.onReorder.emit(event); + listElement.scrollTop = 0; + } + } + + moveDown(event,listElement) { + if(this.selectedItems) { + for(let i = this.selectedItems.length - 1; i >= 0; i--) { + let selectedItem = this.selectedItems[i]; + let selectedItemIndex: number = this.findIndexInList(selectedItem, this.value); + + if(selectedItemIndex != (this.value.length - 1)) { + let movedItem = this.value[selectedItemIndex]; + let temp = this.value[selectedItemIndex+1]; + this.value[selectedItemIndex+1] = movedItem; + this.value[selectedItemIndex] = temp; + } + else { + break; + } + } + + this.movedDown = true; + this.onReorder.emit(event); + } + } + + moveBottom(event,listElement) { + if(this.selectedItems) { + for(let i = this.selectedItems.length - 1; i >= 0; i--) { + let selectedItem = this.selectedItems[i]; + let selectedItemIndex: number = this.findIndexInList(selectedItem, this.value); + + if(selectedItemIndex != (this.value.length - 1)) { + let movedItem = this.value.splice(selectedItemIndex,1)[0]; + this.value.push(movedItem); + } + else { + break; + } + } + + this.onReorder.emit(event); + listElement.scrollTop = listElement.scrollHeight; + } + } +} + +@NgModule({ + imports: [CommonModule,ButtonModule,SharedModule], + exports: [OrderList,SharedModule], + declarations: [OrderList] +}) +export class OrderListModule { } \ No newline at end of file diff --git a/src/app/components/overlaypanel/overlaypanel.css b/src/app/components/overlaypanel/overlaypanel.css new file mode 100644 index 00000000000..b4955daf115 --- /dev/null +++ b/src/app/components/overlaypanel/overlaypanel.css @@ -0,0 +1,18 @@ +.ui-overlaypanel { + padding: 0; + margin: 0; + position: absolute; +} + +.ui-overlaypanel-content { + padding: 0.5em 1em; +} + +.ui-overlaypanel-close { + position: absolute; + top: -.5em; + right: -.5em; + -moz-border-radius: 100%; + -webkit-border-radius: 100%; + border-radius: 100%; +} \ No newline at end of file diff --git a/src/app/components/overlaypanel/overlaypanel.ts b/src/app/components/overlaypanel/overlaypanel.ts new file mode 100644 index 00000000000..0c742ffbca0 --- /dev/null +++ b/src/app/components/overlaypanel/overlaypanel.ts @@ -0,0 +1,159 @@ +import {NgModule,Component,Input,Output,OnInit,AfterViewInit,OnDestroy,EventEmitter,Renderer2,ElementRef,ChangeDetectorRef} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {DomHandler} from '../dom/domhandler'; + +@Component({ + selector: 'p-overlayPanel', + template: ` +
+
+ +
+ + + +
+ `, + providers: [DomHandler] +}) +export class OverlayPanel implements OnInit,AfterViewInit,OnDestroy { + + @Input() dismissable: boolean = true; + + @Input() showCloseIcon: boolean; + + @Input() style: any; + + @Input() styleClass: string; + + @Input() appendTo: any; + + @Output() onBeforeShow: EventEmitter = new EventEmitter(); + + @Output() onAfterShow: EventEmitter = new EventEmitter(); + + @Output() onBeforeHide: EventEmitter = new EventEmitter(); + + @Output() onAfterHide: EventEmitter = new EventEmitter(); + + container: any; + + visible: boolean = false; + + documentClickListener: any; + + selfClick: boolean; + + targetEvent: boolean; + + target: any; + + constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2, private cd: ChangeDetectorRef) {} + + ngOnInit() { + if(this.dismissable) { + this.documentClickListener = this.renderer.listen('document', 'click', () => { + if(!this.selfClick&&!this.targetEvent) { + this.hide(); + } + this.selfClick = false; + this.targetEvent = false; + this.cd.markForCheck(); + }); + } + } + + ngAfterViewInit() { + this.container = this.el.nativeElement.children[0]; + if(this.appendTo) { + if(this.appendTo === 'body') + document.body.appendChild(this.container); + else + this.domHandler.appendChild(this.container, this.appendTo); + } + } + + toggle(event,target?) { + let currentTarget = (target||event.currentTarget||event.target); + + if(!this.target||this.target == currentTarget) { + if(this.visible) + this.hide(); + else + this.show(event, target); + } + else { + this.show(event, target); + } + + if(this.dismissable) { + this.targetEvent = true; + } + + this.target = currentTarget; + } + + show(event,target?) { + if(this.dismissable) { + this.targetEvent = true; + } + + this.onBeforeShow.emit(null); + let elementTarget = target||event.currentTarget||event.target; + this.container.style.zIndex = ++DomHandler.zindex; + + if(this.visible) { + this.domHandler.absolutePosition(this.container, elementTarget); + } + else { + this.visible = true; + this.domHandler.absolutePosition(this.container, elementTarget); + this.domHandler.fadeIn(this.container, 250); + } + this.onAfterShow.emit(null); + } + + hide() { + if(this.visible) { + this.onBeforeHide.emit(null); + this.visible = false; + this.onAfterHide.emit(null); + } + } + + onPanelClick() { + if(this.dismissable) { + this.selfClick = true; + } + } + + onCloseClick(event) { + this.hide(); + + if(this.dismissable) { + this.selfClick = true; + } + + event.preventDefault(); + } + + ngOnDestroy() { + if(this.documentClickListener) { + this.documentClickListener(); + } + + if(this.appendTo) { + this.el.nativeElement.appendChild(this.container); + } + + this.target = null; + } +} + +@NgModule({ + imports: [CommonModule], + exports: [OverlayPanel], + declarations: [OverlayPanel] +}) +export class OverlayPanelModule { } diff --git a/src/app/components/paginator/paginator.css b/src/app/components/paginator/paginator.css new file mode 100644 index 00000000000..6d8573bfbf9 --- /dev/null +++ b/src/app/components/paginator/paginator.css @@ -0,0 +1,56 @@ +.ui-paginator { + margin: 0; + text-align: center; + padding: .125em; +} + +.ui-paginator .ui-paginator-top { + border-bottom: 0 none; +} + +.ui-paginator .ui-paginator-bottom { + border-top:0 none; +} + +.ui-paginator .ui-paginator-page, +.ui-paginator .ui-paginator-pages, +.ui-paginator .ui-paginator-next, +.ui-paginator .ui-paginator-last, +.ui-paginator .ui-paginator-first, +.ui-paginator .ui-paginator-prev, +.ui-paginator .ui-paginator-current { + display: inline-block; + padding: .125em .375em; + zoom: 1; + margin-left: .063em; + margin-right: .063em; + text-decoration: none; +} + +.ui-paginator .ui-paginator-page, +.ui-paginator .ui-paginator-next, +.ui-paginator .ui-paginator-last, +.ui-paginator .ui-paginator-first, +.ui-paginator .ui-paginator-prev{ + cursor: pointer; +} + +.ui-paginator .ui-paginator-current, +.ui-paginator .ui-paginator-rpp-options { + margin-left: 1em; + margin-right: 1em; + background-image: none; +} + +.ui-paginator .ui-paginator-jtp-select option, +.ui-paginator .ui-paginator-rpp-options option { + background-image: none; + border: 0 none; + box-shadow: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; +} + +.ui-paginator a.ui-state-disabled { + outline: 0 none; +} \ No newline at end of file diff --git a/src/app/components/paginator/paginator.ts b/src/app/components/paginator/paginator.ts new file mode 100644 index 00000000000..e88862980b0 --- /dev/null +++ b/src/app/components/paginator/paginator.ts @@ -0,0 +1,174 @@ +import {NgModule,Component,ElementRef,Input,Output,SimpleChange,EventEmitter} from '@angular/core'; +import {CommonModule} from '@angular/common'; + +@Component({ + selector: 'p-paginator', + template: ` +
+ + + + + + + + {{pageLink}} + + + + + + + + +
+ ` +}) +export class Paginator { + + @Input() pageLinkSize: number = 5; + + @Output() onPageChange: EventEmitter = new EventEmitter(); + + @Input() style: any; + + @Input() styleClass: string; + + @Input() rowsPerPageOptions: number[]; + + @Input() alwaysShow: boolean = true; + + public pageLinks: number[]; + + public _totalRecords: number = 0; + + public _first: number = 0; + + public _rows: number = 0; + + @Input() get totalRecords(): number { + return this._totalRecords; + } + + set totalRecords(val:number) { + this._totalRecords = val; + this.updatePageLinks(); + } + + @Input() get first(): number { + return this._first; + } + + set first(val:number) { + this._first = val; + this.updatePageLinks(); + } + + @Input() get rows(): number { + return this._rows; + } + + set rows(val:number) { + this._rows = val; + this.updatePageLinks(); + } + + isFirstPage() { + return this.getPage() === 0; + } + + isLastPage() { + return this.getPage() === this.getPageCount() - 1; + } + + getPageCount() { + return Math.ceil(this.totalRecords/this.rows)||1; + } + + calculatePageLinkBoundaries() { + let numberOfPages = this.getPageCount(), + visiblePages = Math.min(this.pageLinkSize, numberOfPages); + + //calculate range, keep current in middle if necessary + let start = Math.max(0, Math.ceil(this.getPage() - ((visiblePages) / 2))), + end = Math.min(numberOfPages - 1, start + visiblePages - 1); + + //check when approaching to last page + var delta = this.pageLinkSize - (end - start + 1); + start = Math.max(0, start - delta); + + return [start, end]; + } + + updatePageLinks() { + this.pageLinks = []; + let boundaries = this.calculatePageLinkBoundaries(), + start = boundaries[0], + end = boundaries[1]; + + for(let i = start; i <= end; i++) { + this.pageLinks.push(i + 1); + } + } + + changePage(p :number, event) { + var pc = this.getPageCount(); + + if(p >= 0 && p < pc) { + this.first = this.rows * p; + var state = { + page: p, + first: this.first, + rows: this.rows, + pageCount: pc + }; + this.updatePageLinks(); + + this.onPageChange.emit(state); + } + + if(event) { + event.preventDefault(); + } + } + + getPage(): number { + return Math.floor(this.first / this.rows); + } + + changePageToFirst(event) { + this.changePage(0, event); + } + + changePageToPrev(event) { + this.changePage(this.getPage() - 1, event); + } + + changePageToNext(event) { + this.changePage(this.getPage() + 1, event); + } + + changePageToLast(event) { + this.changePage(this.getPageCount() - 1, event); + } + + onRppChange(event) { + this.rows = this.rowsPerPageOptions[event.target.selectedIndex]; + this.changePageToFirst(event); + } +} + +@NgModule({ + imports: [CommonModule], + exports: [Paginator], + declarations: [Paginator] +}) +export class PaginatorModule { } diff --git a/src/app/components/panel/panel.css b/src/app/components/panel/panel.css new file mode 100644 index 00000000000..d295228671d --- /dev/null +++ b/src/app/components/panel/panel.css @@ -0,0 +1,33 @@ +.ui-panel { + padding: 0.2em; +} + +.ui-panel .ui-panel-titlebar { + padding: .5em .75em; +} + +.ui-panel .ui-panel-titlebar-icon { + float: right; + cursor: pointer; +} + +.ui-panel .ui-panel-titlebar-icon { + margin-left: 0.2em; + margin-top: -0.1em; +} + +.ui-panel .ui-panel-content { + border: 0; + background: none; + padding: .5em .75em; +} + +.ui-panel .ui-panel-footer { + border-width: 1px 0 0; + padding: .25em .5em; + text-align:left; +} + +.ui-panel-content-wrapper-overflown { + overflow: hidden; +} \ No newline at end of file diff --git a/src/app/components/panel/panel.ts b/src/app/components/panel/panel.ts new file mode 100644 index 00000000000..8c61febff4a --- /dev/null +++ b/src/app/components/panel/panel.ts @@ -0,0 +1,110 @@ +import {NgModule,Component,Input,Output,EventEmitter,ElementRef} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {SharedModule} from '../common/shared'; +import {BlockableUI} from '../common/blockableui'; +import {trigger,state,style,transition,animate} from '@angular/animations'; + +@Component({ + selector: 'p-panel', + template: ` +
+
+ {{header}} + + + + +
+
+
+ +
+
+
+ `, + animations: [ + trigger('panelContent', [ + state('hidden', style({ + height: '0' + })), + state('visible', style({ + height: '*' + })), + transition('visible <=> hidden', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)')) + ]) + ] +}) +export class Panel implements BlockableUI { + + @Input() toggleable: boolean; + + @Input() header: string; + + @Input() collapsed: boolean = false; + + @Input() style: any; + + @Input() styleClass: string; + + @Input() expandIcon: string = 'fa-plus'; + + @Input() collapseIcon: string = 'fa-minus'; + + @Output() collapsedChange: EventEmitter = new EventEmitter(); + + @Output() onBeforeToggle: EventEmitter = new EventEmitter(); + + @Output() onAfterToggle: EventEmitter = new EventEmitter(); + + public animating: boolean; + + constructor(private el: ElementRef) {} + + toggle(event) { + if(this.animating) { + return false; + } + + this.animating = true; + this.onBeforeToggle.emit({originalEvent: event, collapsed: this.collapsed}); + + if(this.toggleable) { + if(this.collapsed) + this.expand(event); + else + this.collapse(event); + } + + this.onAfterToggle.emit({originalEvent: event, collapsed: this.collapsed}); + + event.preventDefault(); + } + + expand(event) { + this.collapsed = false; + this.collapsedChange.emit(this.collapsed); + } + + collapse(event) { + this.collapsed = true; + this.collapsedChange.emit(this.collapsed); + } + + getBlockableElement(): HTMLElement { + return this.el.nativeElement.children[0]; + } + + onToggleDone(event: Event) { + this.animating = false; + } + +} + +@NgModule({ + imports: [CommonModule], + exports: [Panel,SharedModule], + declarations: [Panel] +}) +export class PanelModule { } \ No newline at end of file diff --git a/src/app/components/panelmenu/panelmenu.ts b/src/app/components/panelmenu/panelmenu.ts new file mode 100644 index 00000000000..4c17b069a14 --- /dev/null +++ b/src/app/components/panelmenu/panelmenu.ts @@ -0,0 +1,154 @@ +import {NgModule,Component,ElementRef,OnDestroy,Input,EventEmitter} from '@angular/core'; +import {trigger,state,style,transition,animate} from '@angular/animations'; +import {CommonModule} from '@angular/common'; +import {MenuItem} from '../common/menuitem'; +import {RouterModule} from '@angular/router'; + +export class BasePanelMenuItem { + + handleClick(event, item) { + if(item.disabled) { + event.preventDefault(); + return; + } + + item.expanded = !item.expanded; + + if(!item.url) { + event.preventDefault(); + } + + if(item.command) { + if(!item.eventEmitter) { + item.eventEmitter = new EventEmitter(); + item.eventEmitter.subscribe(item.command); + } + + item.eventEmitter.emit({ + originalEvent: event, + item: item + }); + } + } +} + +@Component({ + selector: 'p-panelMenuSub', + template: ` + + ` +}) +export class PanelMenuSub extends BasePanelMenuItem { + + @Input() item: MenuItem; + + @Input() expanded: boolean; +} + +@Component({ + selector: 'p-panelMenu', + template: ` + + `, + animations: [ + trigger('rootItem', [ + state('hidden', style({ + height: '0px' + })), + state('visible', style({ + height: '*' + })), + transition('visible => hidden', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)')), + transition('hidden => visible', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)')) + ]) + ] +}) +export class PanelMenu extends BasePanelMenuItem { + + @Input() model: MenuItem[]; + + @Input() style: any; + + @Input() styleClass: string; + + public animating: boolean; + + unsubscribe(item: any) { + if(item.eventEmitter) { + item.eventEmitter.unsubscribe(); + } + + if(item.items) { + for(let childItem of item.items) { + this.unsubscribe(childItem); + } + } + } + + ngOnDestroy() { + if(this.model) { + for(let item of this.model) { + this.unsubscribe(item); + } + } + } + + handleClick(event, item) { + this.animating = true; + super.handleClick(event, item); + //TODO: Use onDone of animate callback instead with RC6 + setTimeout(() => { + this.animating = false; + }, 400); + } + +} + +@NgModule({ + imports: [CommonModule,RouterModule], + exports: [PanelMenu,RouterModule], + declarations: [PanelMenu,PanelMenuSub] +}) +export class PanelMenuModule { } diff --git a/src/app/components/password/images/password-meter.png b/src/app/components/password/images/password-meter.png new file mode 100644 index 00000000000..eec05cfb434 Binary files /dev/null and b/src/app/components/password/images/password-meter.png differ diff --git a/src/app/components/password/password.css b/src/app/components/password/password.css new file mode 100644 index 00000000000..f72f179a337 --- /dev/null +++ b/src/app/components/password/password.css @@ -0,0 +1,20 @@ +.ui-password-panel { + padding: .25em .5em; + width: 10em; + margin-top: 2px; +} + +.ui-password-panel .ui-password-meter { + height: 10px; + background:transparent url("./images/password-meter.png") no-repeat left top; + padding: 0; + margin: 0; +} + +.ui-password-info { + margin-top: .25em; +} + +.ui-password-panel-overlay { + position: absolute; +} \ No newline at end of file diff --git a/src/app/components/password/password.ts b/src/app/components/password/password.ts new file mode 100644 index 00000000000..5a1bcbc7c6f --- /dev/null +++ b/src/app/components/password/password.ts @@ -0,0 +1,164 @@ +import {NgModule,Directive,ElementRef,HostListener,Input,AfterViewInit,OnDestroy,DoCheck} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {DomHandler} from '../dom/domhandler'; + +@Directive({ + selector: '[pPassword]', + host: { + '[class.ui-inputtext]': 'true', + '[class.ui-corner-all]': 'true', + '[class.ui-state-default]': 'true', + '[class.ui-widget]': 'true', + '[class.ui-state-filled]': 'filled' + }, + providers: [DomHandler] +}) +export class Password implements AfterViewInit,OnDestroy,DoCheck { + + @Input() promptLabel: string = 'Please enter a password'; + + @Input() weakLabel: string = 'Weak'; + + @Input() mediumLabel: string = 'Medium'; + + @Input() strongLabel: string = 'Strong'; + + @Input() feedback: boolean = true; + + panel: any; + + meter: any; + + info: any; + + filled: boolean; + + constructor(public el: ElementRef, public domHandler: DomHandler) {} + + ngAfterViewInit() { + this.panel = document.createElement('div'); + this.panel.className = 'ui-password-panel ui-widget ui-state-highlight ui-corner-all ui-helper-hidden ui-password-panel-overlay'; + this.meter = document.createElement('div'); + this.meter.className = 'ui-password-meter'; + this.info = document.createElement('div'); + this.info.className = 'ui-password-info'; + this.info.textContent = this.promptLabel; + + if(this.feedback) { + this.panel.appendChild(this.meter); + this.panel.appendChild(this.info); + document.body.appendChild(this.panel); + } + } + + ngDoCheck() { + this.updateFilledState(); + } + + //To trigger change detection to manage ui-state-filled for material labels when there is no value binding + @HostListener('input', ['$event']) + onInput(e) { + this.updateFilledState(); + } + + updateFilledState() { + this.filled = this.el.nativeElement.value && this.el.nativeElement.value.length; + } + + @HostListener('focus', ['$event']) + onFocus(e) { + this.panel.style.zIndex = String(++DomHandler.zindex); + this.domHandler.removeClass(this.panel, 'ui-helper-hidden'); + this.domHandler.absolutePosition(this.panel, this.el.nativeElement); + this.domHandler.fadeIn(this.panel, 250); + } + + @HostListener('blur', ['$event']) + onBlur(e) { + this.domHandler.addClass(this.panel, 'ui-helper-hidden'); + } + + @HostListener('keyup', ['$event']) + onKeyup(e) { + let value = e.target.value, + label = null, + meterPos = null; + + if(value.length === 0) { + label = this.promptLabel; + meterPos = '0px 0px'; + } + else { + var score = this.testStrength(value); + + if(score < 30) { + label = this.weakLabel; + meterPos = '0px -10px'; + } + else if(score >= 30 && score < 80) { + label = this.mediumLabel; + meterPos = '0px -20px'; + } + else if(score >= 80) { + label = this.strongLabel; + meterPos = '0px -30px'; + } + } + + this.meter.style.backgroundPosition = meterPos; + this.info.textContent = label; + } + + testStrength(str: string) { + let grade: number = 0; + let val; + + val = str.match('[0-9]'); + grade += this.normalize(val ? val.length : 1/4, 1) * 25; + + val = str.match('[a-zA-Z]'); + grade += this.normalize(val ? val.length : 1/2, 3) * 10; + + val = str.match('[!@#$%^&*?_~.,;=]'); + grade += this.normalize(val ? val.length : 1/6, 1) * 35; + + val = str.match('[A-Z]'); + grade += this.normalize(val ? val.length : 1/6, 1) * 30; + + grade *= str.length / 8; + + return grade > 100 ? 100 : grade; + } + + normalize(x, y) { + let diff = x - y; + + if(diff <= 0) + return x / y; + else + return 1 + 0.5 * (x / (x + y/4)); + } + + get disabled(): boolean { + return this.el.nativeElement.disabled; + } + + ngOnDestroy() { + if (!this.feedback) + return; + + this.panel.removeChild(this.meter); + this.panel.removeChild(this.info); + document.body.removeChild(this.panel); + this.panel = null; + this.meter = null; + this.info = null; + } +} + +@NgModule({ + imports: [CommonModule], + exports: [Password], + declarations: [Password] +}) +export class PasswordModule { } diff --git a/src/app/components/picklist/picklist.css b/src/app/components/picklist/picklist.css new file mode 100644 index 00000000000..c6a12aaf38f --- /dev/null +++ b/src/app/components/picklist/picklist.css @@ -0,0 +1,191 @@ +.ui-picklist > div { + float: left; +} + +.ui-picklist .ui-picklist-buttons { + height: 12.5em; + padding: 0 .25em; +} + +.ui-picklist .ui-picklist-list { + list-style-type: none; + margin: 0; + padding: 0; + overflow:auto; + height: 12.5em; + width: 12.5em; +} + +.ui-picklist .ui-picklist-list li { + margin: 1px; + padding: .125em; +} + +.ui-picklist .ui-button { + display:block; + margin-bottom: 0.25em; +} + +.ui-picklist .ui-button-text-icon-left { + width: 100%; +} + +.ui-picklist .ui-picklist-item { + cursor: pointer; + border: 0 none; + font-weight: inherit; +} + +.ui-picklist .ui-picklist-caption { + text-align: center; + padding: .5em .75em; + border-bottom:0 none; +} + +.ui-picklist table { + width: 100%; + border-collapse:collapse; +} + +.ui-picklist .ui-picklist-filter { + padding-right: 1em; + width: 100%; + box-sizing: border-box; +} + +.ui-picklist .ui-picklist-filter-container { + position: relative; + margin: 0; + padding: 0; +} + +.ui-picklist .ui-picklist-filter-container .fa { + position: absolute; + top: .25em; + right: .125em; +} + +.ui-picklist { + display: table; +} + +.ui-picklist > div { + float: none; + display: table-cell; + vertical-align: top; +} + +.ui-picklist .ui-picklist-buttons { + vertical-align: middle; +} + +/* Vertical */ +.ui-picklist.ui-picklist-vertical { + display: table; +} + +.ui-picklist.ui-picklist-vertical > div { + float: none; + display: table-row; + vertical-align: top; +} + +.ui-picklist.ui-picklist-vertical .ui-picklist-buttons { + text-align:center; + height: auto; +} + +.ui-picklist.ui-picklist-vertical .ui-picklist-buttons .ui-button { + display: inline-block; +} + +.ui-picklist.ui-picklist-vertical .ui-button { + margin-top: 0.25em; +} + +.ui-picklist-outline { + outline: 1px dotted black; + z-index: 1; +} + +.ui-picklist-list.ui-picklist-source, +.ui-picklist-list.ui-picklist-target { + outline: none; +} + +/* Responsive */ +.ui-picklist.ui-picklist-responsive * { + box-sizing: border-box; +} + +.ui-picklist.ui-picklist-responsive { + width: 100%; +} + +.ui-picklist.ui-picklist-responsive .ui-picklist-listwrapper { + width: 35%; +} + +.ui-picklist.ui-picklist-responsive .ui-picklist-listwrapper.ui-picklist-listwrapper-nocontrols { + width: 45%; +} + +.ui-picklist.ui-picklist-responsive .ui-picklist-buttons { + width: 10%; +} + +.ui-picklist.ui-picklist-responsive .ui-picklist-buttons button { + width: 100%; +} + +.ui-picklist.ui-picklist-responsive .ui-picklist-list { + width: auto; +} + +/* Responsive */ +@media (max-width: 40em) { + .ui-picklist.ui-picklist-responsive { + display: block; + } + + .ui-picklist.ui-picklist-responsive > div { + display: block; + width: 100% !important; + } + + .ui-picklist.ui-picklist-responsive .ui-picklist-buttons { + text-align: center; + height: auto; + padding: .4em 0; + } + + .ui-picklist.ui-picklist-responsive .ui-picklist-buttons button { + display: inline; + width: 20%; + margin-bottom: 0; + } + + .ui-picklist.ui-picklist-responsive .ui-picklist-source-controls.ui-picklist-buttons { + padding-bottom: .4em; + } + + .ui-picklist.ui-picklist-responsive .ui-picklist-target-controls.ui-picklist-buttons { + padding-top: .4em; + } + + .ui-picklist.ui-picklist-responsive .ui-picklist-buttons .fa-angle-right:before { + content: "\f107"; + } + + .ui-picklist.ui-picklist-responsive .ui-picklist-buttons .fa-angle-double-right:before { + content: "\f103"; + } + + .ui-picklist.ui-picklist-responsive .ui-picklist-buttons .fa-angle-left:before { + content: "\f106"; + } + + .ui-picklist.ui-picklist-responsive .ui-picklist-buttons .fa-angle-double-left:before { + content: "\f102"; + } +} diff --git a/src/app/components/picklist/picklist.ts b/src/app/components/picklist/picklist.ts new file mode 100644 index 00000000000..ff21e600edd --- /dev/null +++ b/src/app/components/picklist/picklist.ts @@ -0,0 +1,348 @@ +import {NgModule,Component,ElementRef,OnDestroy,AfterViewInit,AfterContentInit,AfterViewChecked,DoCheck,Input,Output,ContentChildren,QueryList,TemplateRef,EventEmitter} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {ButtonModule} from '../button/button'; +import {SharedModule,PrimeTemplate} from '../common/shared'; +import {DomHandler} from '../dom/domhandler'; + +@Component({ + selector: 'p-pickList', + template: ` +
+
+
+ + + + +
+
+
+
{{sourceHeader}}
+
    +
  • + +
  • +
+
+
+
+ + + + +
+
+
+
{{targetHeader}}
+
    +
  • + +
  • +
+
+
+
+ + + + +
+
+
+ `, + providers: [DomHandler] +}) +export class PickList implements OnDestroy,AfterViewChecked,AfterContentInit { + + @Input() source: any[]; + + @Input() target: any[]; + + @Input() sourceHeader: string; + + @Input() targetHeader: string; + + @Input() responsive: boolean; + + @Input() metaKeySelection: boolean = true; + + @Input() style: any; + + @Input() styleClass: string; + + @Input() sourceStyle: any; + + @Input() targetStyle: any; + + @Input() showSourceControls: boolean = true; + + @Input() showTargetControls: boolean = true; + + @Output() onMoveToSource: EventEmitter = new EventEmitter(); + + @Output() onMoveToTarget: EventEmitter = new EventEmitter(); + + @Output() onSourceReorder: EventEmitter = new EventEmitter(); + + @Output() onTargetReorder: EventEmitter = new EventEmitter(); + + @ContentChildren(PrimeTemplate) templates: QueryList; + + public itemTemplate: TemplateRef; + + selectedItemsSource: any[] = []; + + selectedItemsTarget: any[] = []; + + reorderedListElement: any; + + movedUp: boolean; + + movedDown: boolean; + + itemTouched: boolean; + + constructor(public el: ElementRef, public domHandler: DomHandler) {} + + ngAfterContentInit() { + this.templates.forEach((item) => { + switch(item.getType()) { + case 'item': + this.itemTemplate = item.template; + break; + + default: + this.itemTemplate = item.template; + break; + } + }); + } + + ngAfterViewChecked() { + if(this.movedUp||this.movedDown) { + let listItems = this.domHandler.find(this.reorderedListElement, 'li.ui-state-highlight'); + let listItem; + + if(this.movedUp) + listItem = listItems[0]; + else + listItem = listItems[listItems.length - 1]; + + this.domHandler.scrollInView(this.reorderedListElement, listItem); + this.movedUp = false; + this.movedDown = false; + this.reorderedListElement = null; + } + } + + onItemClick(event, item: any, selectedItems: any[]) { + let index = this.findIndexInSelection(item,selectedItems); + let selected = (index != -1); + let metaSelection = this.itemTouched ? false : this.metaKeySelection; + + if(metaSelection) { + let metaKey = (event.metaKey||event.ctrlKey); + + if(selected && metaKey) { + selectedItems.splice(index, 1); + } + else { + if(!metaKey) { + selectedItems.length = 0; + } + selectedItems.push(item); + } + } + else { + if(selected) + selectedItems.splice(index, 1); + else + selectedItems.push(item); + } + + + this.itemTouched = false; + } + + onItemTouchEnd(event) { + this.itemTouched = true; + } + + moveUp(listElement, list, selectedItems, callback) { + if(selectedItems && selectedItems.length) { + for(let i = 0; i < selectedItems.length; i++) { + let selectedItem = selectedItems[i]; + let selectedItemIndex: number = this.findIndexInList(selectedItem, list); + + if(selectedItemIndex != 0) { + let movedItem = list[selectedItemIndex]; + let temp = list[selectedItemIndex-1]; + list[selectedItemIndex-1] = movedItem; + list[selectedItemIndex] = temp; + } + else { + break; + } + } + + this.movedUp = true; + this.reorderedListElement = listElement; + callback.emit({items: selectedItems}); + } + } + + moveTop(listElement, list, selectedItems, callback) { + if(selectedItems && selectedItems.length) { + for(let i = 0; i < selectedItems.length; i++) { + let selectedItem = selectedItems[i]; + let selectedItemIndex: number = this.findIndexInList(selectedItem, list); + + if(selectedItemIndex != 0) { + let movedItem = list.splice(selectedItemIndex,1)[0]; + list.unshift(movedItem); + } + else { + break; + } + } + + listElement.scrollTop = 0; + callback.emit({items: selectedItems}); + } + } + + moveDown(listElement, list, selectedItems, callback) { + if(selectedItems && selectedItems.length) { + for(let i = selectedItems.length - 1; i >= 0; i--) { + let selectedItem = selectedItems[i]; + let selectedItemIndex: number = this.findIndexInList(selectedItem, list); + + if(selectedItemIndex != (list.length - 1)) { + let movedItem = list[selectedItemIndex]; + let temp = list[selectedItemIndex+1]; + list[selectedItemIndex+1] = movedItem; + list[selectedItemIndex] = temp; + } + else { + break; + } + } + + this.movedDown = true; + this.reorderedListElement = listElement; + callback.emit({items: selectedItems}); + } + } + + moveBottom(listElement, list, selectedItems, callback) { + if(selectedItems && selectedItems.length) { + for(let i = selectedItems.length - 1; i >= 0; i--) { + let selectedItem = selectedItems[i]; + let selectedItemIndex: number = this.findIndexInList(selectedItem, list); + + if(selectedItemIndex != (list.length - 1)) { + let movedItem = list.splice(selectedItemIndex,1)[0]; + list.push(movedItem); + } + else { + break; + } + } + + listElement.scrollTop = listElement.scrollHeight; + callback.emit({items: selectedItems}); + } + } + + moveRight(targetListElement) { + if(this.selectedItemsSource && this.selectedItemsSource.length) { + for(let i = 0; i < this.selectedItemsSource.length; i++) { + let selectedItem = this.selectedItemsSource[i]; + if(this.findIndexInList(selectedItem, this.target) == -1) { + this.target.push(this.source.splice(this.findIndexInList(selectedItem, this.source),1)[0]); + } + } + this.onMoveToTarget.emit({ + items: this.selectedItemsSource + }); + this.selectedItemsSource = []; + } + } + + moveAllRight() { + if(this.source) { + for(let i = 0; i < this.source.length; i++) { + this.target.push(this.source[i]); + } + this.onMoveToTarget.emit({ + items: this.source + }); + this.source.splice(0, this.source.length); + this.selectedItemsSource = []; + } + } + + moveLeft(sourceListElement) { + if(this.selectedItemsTarget && this.selectedItemsTarget.length) { + for(let i = 0; i < this.selectedItemsTarget.length; i++) { + let selectedItem = this.selectedItemsTarget[i]; + if(this.findIndexInList(selectedItem, this.source) == -1) { + this.source.push(this.target.splice(this.findIndexInList(selectedItem, this.target),1)[0]); + } + } + this.onMoveToSource.emit({ + items: this.selectedItemsTarget + }); + this.selectedItemsTarget = []; + } + } + + moveAllLeft() { + if(this.target) { + for(let i = 0; i < this.target.length; i++) { + this.source.push(this.target[i]); + } + this.onMoveToSource.emit({ + items: this.target + }); + this.target.splice(0, this.target.length); + this.selectedItemsTarget = []; + } + } + + isSelected(item: any, selectedItems: any[]) { + return this.findIndexInSelection(item, selectedItems) != -1; + } + + findIndexInSelection(item: any, selectedItems: any[]): number { + return this.findIndexInList(item, selectedItems); + } + + findIndexInList(item: any, list: any): number { + let index: number = -1; + + if(list) { + for(let i = 0; i < list.length; i++) { + if(list[i] == item) { + index = i; + break; + } + } + } + + return index; + } + + ngOnDestroy() { + + } +} + +@NgModule({ + imports: [CommonModule,ButtonModule,SharedModule], + exports: [PickList,SharedModule], + declarations: [PickList] +}) +export class PickListModule { } diff --git a/src/app/components/progressbar/progressbar.css b/src/app/components/progressbar/progressbar.css new file mode 100644 index 00000000000..017bb5c94e6 --- /dev/null +++ b/src/app/components/progressbar/progressbar.css @@ -0,0 +1,29 @@ +.ui-progressbar { + height: 1.2em; + text-align: left; + position: relative; +} + +.ui-progressbar .ui-progressbar-value { + height: 100%; + width: 0%; + position: absolute; + display: none; + border: 0 none; +} + +.ui-progressbar .ui-progressbar-value-animate { + -webkit-transition: width 1s ease-in-out; + -moz-transition: width 1s ease-in-out; + -o-transition: width 1s ease-in-out; + transition: width 1s ease-in-out; +} + +.ui-progressbar .ui-progressbar-label { + text-align: center; + height: 100%; + width: 100%; + position: absolute; + display: none; + font-weight: bold; +} \ No newline at end of file diff --git a/src/app/components/progressbar/progressbar.ts b/src/app/components/progressbar/progressbar.ts new file mode 100644 index 00000000000..a9b533716cb --- /dev/null +++ b/src/app/components/progressbar/progressbar.ts @@ -0,0 +1,28 @@ +import {NgModule,Component,Input} from '@angular/core'; +import {CommonModule} from '@angular/common'; + +@Component({ + selector: 'p-progressBar', + template: ` +
+
+
{{value}}{{unit}}
+
+ ` +}) +export class ProgressBar { + + @Input() value: any; + + @Input() showValue: boolean = true; + + @Input() unit: string = '%'; + +} + +@NgModule({ + imports: [CommonModule], + exports: [ProgressBar], + declarations: [ProgressBar] +}) +export class ProgressBarModule { } \ No newline at end of file diff --git a/src/app/components/radiobutton/radiobutton.css b/src/app/components/radiobutton/radiobutton.css new file mode 100644 index 00000000000..0a2480bafdd --- /dev/null +++ b/src/app/components/radiobutton/radiobutton.css @@ -0,0 +1,27 @@ +.ui-radiobutton { + display:inline-block; + cursor: pointer; + vertical-align: middle; + margin-right: .25em; +} + +.ui-radiobutton-box { + width: 1.125em; + height: 1.125em; + line-height: 1.125em; + -moz-border-radius: 100%; + -webkit-border-radius: 100%; + border-radius: 100%; + text-align: center; +} + +.ui-radiobutton-icon { + display: block; + font-size: .6em; + line-height: inherit; +} + +.ui-radiobutton, .ui-radiobutton-label { + vertical-align: middle; + display: inline-block; +} \ No newline at end of file diff --git a/src/app/components/radiobutton/radiobutton.ts b/src/app/components/radiobutton/radiobutton.ts new file mode 100644 index 00000000000..ece45c2cc6c --- /dev/null +++ b/src/app/components/radiobutton/radiobutton.ts @@ -0,0 +1,123 @@ +import {NgModule,Component,Input,Output,AfterViewInit,ElementRef,EventEmitter,forwardRef,ViewChild,ChangeDetectorRef} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; + +export const RADIO_VALUE_ACCESSOR: any = { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => RadioButton), + multi: true +}; + +@Component({ + selector: 'p-radioButton', + template: ` +
+
+ +
+
+ +
+
+ + `, + providers: [RADIO_VALUE_ACCESSOR] +}) +export class RadioButton implements ControlValueAccessor,AfterViewInit { + + @Input() value: any; + + @Input() name: string; + + @Input() disabled: boolean; + + @Input() label: string; + + @Input() tabindex: number; + + @Input() inputId: string; + + @Input() style: any; + + @Input() styleClass: string; + + @Output() onClick: EventEmitter = new EventEmitter(); + + @ViewChild('rb') inputViewChild: ElementRef; + + public input: HTMLInputElement; + + public onModelChange: Function = () => {}; + + public onModelTouched: Function = () => {}; + + public checked: boolean; + + public focused: boolean; + + constructor(private cd: ChangeDetectorRef) {} + + ngAfterViewInit() { + this.input = this.inputViewChild.nativeElement; + } + + handleClick() { + if(!this.disabled) { + this.onClick.emit(null); + this.select(); + } + } + + select() { + if(!this.disabled) { + this.input.checked = true; + this.checked = true; + this.onModelChange(this.value); + } + } + + writeValue(value: any) : void { + this.checked = (value == this.value); + + if(this.input) { + this.input.checked = this.checked; + } + + this.cd.markForCheck(); + } + + registerOnChange(fn: Function): void { + this.onModelChange = fn; + } + + registerOnTouched(fn: Function): void { + this.onModelTouched = fn; + } + + setDisabledState(val: boolean): void { + this.disabled = val; + } + + onFocus(event) { + this.focused = true; + } + + onBlur(event) { + this.focused = false; + this.onModelTouched(); + } + + onChange(event) { + this.select(); + } +} + +@NgModule({ + imports: [CommonModule], + exports: [RadioButton], + declarations: [RadioButton] +}) +export class RadioButtonModule { } \ No newline at end of file diff --git a/src/app/components/rating/rating.ts b/src/app/components/rating/rating.ts new file mode 100644 index 00000000000..44692c967d0 --- /dev/null +++ b/src/app/components/rating/rating.ts @@ -0,0 +1,99 @@ +import {NgModule,Component,ElementRef,OnInit,Input,Output,EventEmitter,forwardRef} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; + +export const RATING_VALUE_ACCESSOR: any = { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => Rating), + multi: true +}; + +@Component({ + selector: 'p-rating', + template: ` + + `, + providers: [RATING_VALUE_ACCESSOR] +}) +export class Rating implements ControlValueAccessor { + + @Input() disabled: boolean; + + @Input() readonly: boolean; + + @Input() stars: number = 5; + + @Input() cancel: boolean = true; + + @Output() onRate: EventEmitter = new EventEmitter(); + + @Output() onCancel: EventEmitter = new EventEmitter(); + + value: number; + + onModelChange: Function = () => {}; + + onModelTouched: Function = () => {}; + + public starsArray: number[]; + + ngOnInit() { + this.starsArray = []; + for(let i = 0; i < this.stars; i++) { + this.starsArray[i] = i; + } + } + + rate(event, i: number): void { + if(!this.readonly&&!this.disabled) { + this.value = (i + 1); + this.onModelChange(this.value); + this.onModelTouched(); + this.onRate.emit({ + originalEvent: event, + value: (i+1) + }); + } + event.preventDefault(); + } + + clear(event): void { + if(!this.readonly&&!this.disabled) { + this.value = null; + this.onModelChange(this.value); + this.onModelTouched(); + this.onCancel.emit(event); + } + event.preventDefault(); + } + + writeValue(value: any) : void { + this.value = value; + } + + registerOnChange(fn: Function): void { + this.onModelChange = fn; + } + + registerOnTouched(fn: Function): void { + this.onModelTouched = fn; + } + + setDisabledState(val: boolean): void { + this.disabled = val; + } +} + +@NgModule({ + imports: [CommonModule], + exports: [Rating], + declarations: [Rating] +}) +export class RatingModule { } \ No newline at end of file diff --git a/src/app/components/schedule/schedule.css b/src/app/components/schedule/schedule.css new file mode 100644 index 00000000000..838a51d449d --- /dev/null +++ b/src/app/components/schedule/schedule.css @@ -0,0 +1,3 @@ +.ui-fluid .fc .ui-button { + width: auto; +} \ No newline at end of file diff --git a/src/app/components/schedule/schedule.ts b/src/app/components/schedule/schedule.ts new file mode 100644 index 00000000000..ec4bd4e99c6 --- /dev/null +++ b/src/app/components/schedule/schedule.ts @@ -0,0 +1,382 @@ +import {NgModule,Component,ElementRef,OnDestroy,DoCheck,OnChanges,Input,Output,EventEmitter,IterableDiffers,OnInit,AfterViewChecked,SimpleChanges} from '@angular/core'; +import {CommonModule} from '@angular/common'; + +declare var jQuery: any; + +@Component({ + selector: 'p-schedule', + template: '
' +}) +export class Schedule implements DoCheck,OnDestroy,OnInit,OnChanges,AfterViewChecked { + + @Input() events: any[]; + + @Input() header: any; + + @Input() style: any; + + @Input() styleClass: string; + + @Input() rtl: boolean; + + @Input() weekends: boolean; + + @Input() hiddenDays: number[]; + + @Input() fixedWeekCount: boolean; + + @Input() weekNumbers: boolean; + + @Input() businessHours: any; + + @Input() height: any; + + @Input() contentHeight: any; + + @Input() aspectRatio: number = 1.35; + + @Input() eventLimit: any; + + @Input() defaultDate: any; + + @Input() editable: boolean; + + @Input() droppable: boolean; + + @Input() eventStartEditable: boolean; + + @Input() eventDurationEditable: boolean; + + @Input() defaultView: string = 'month'; + + @Input() allDaySlot: boolean = true; + + @Input() allDayText: string = 'all-day'; + + @Input() slotDuration: any = '00:30:00'; + + @Input() slotLabelInterval: any; + + @Input() snapDuration: any; + + @Input() scrollTime: any = '06:00:00'; + + @Input() minTime: any = '00:00:00'; + + @Input() maxTime: any = '24:00:00'; + + @Input() slotEventOverlap: boolean = true; + + @Input() nowIndicator: boolean; + + @Input() dragRevertDuration: number = 500; + + @Input() dragOpacity: number = .75; + + @Input() dragScroll: boolean = true; + + @Input() eventOverlap: any; + + @Input() eventConstraint: any; + + @Input() locale: string; + + @Input() timezone: boolean | string = false; + + @Input() timeFormat:string | null = null; + + @Input() eventRender: Function; + + @Input() dayRender: Function; + + @Input() options: any; + + @Output() onDayClick: EventEmitter = new EventEmitter(); + + @Output() onDrop: EventEmitter = new EventEmitter(); + + @Output() onEventClick: EventEmitter = new EventEmitter(); + + @Output() onEventMouseover: EventEmitter = new EventEmitter(); + + @Output() onEventMouseout: EventEmitter = new EventEmitter(); + + @Output() onEventDragStart: EventEmitter = new EventEmitter(); + + @Output() onEventDragStop: EventEmitter = new EventEmitter(); + + @Output() onEventDrop: EventEmitter = new EventEmitter(); + + @Output() onEventResizeStart: EventEmitter = new EventEmitter(); + + @Output() onEventResizeStop: EventEmitter = new EventEmitter(); + + @Output() onEventResize: EventEmitter = new EventEmitter(); + + @Output() onViewRender: EventEmitter = new EventEmitter(); + + initialized: boolean; + + stopNgOnChangesPropagation: boolean; + + differ: any; + + schedule: any; + + config: any; + + constructor(public el: ElementRef, differs: IterableDiffers) { + this.differ = differs.find([]).create(null); + this.initialized = false; + } + + ngOnInit() { + this.config = { + theme: true, + header: this.header, + isRTL: this.rtl, + weekends: this.weekends, + hiddenDays: this.hiddenDays, + fixedWeekCount: this.fixedWeekCount, + weekNumbers: this.weekNumbers, + businessHours: this.businessHours, + height: this.height, + contentHeight: this.contentHeight, + aspectRatio: this.aspectRatio, + eventLimit: this.eventLimit, + defaultDate: this.defaultDate, + locale: this.locale, + timezone: this.timezone, + timeFormat: this.timeFormat, + editable: this.editable, + droppable: this.droppable, + eventStartEditable: this.eventStartEditable, + eventDurationEditable: this.eventDurationEditable, + defaultView: this.defaultView, + allDaySlot: this.allDaySlot, + allDayText: this.allDayText, + slotDuration: this.slotDuration, + slotLabelInterval: this.slotLabelInterval, + snapDuration: this.snapDuration, + scrollTime: this.scrollTime, + minTime: this.minTime, + maxTime: this.maxTime, + slotEventOverlap: this.slotEventOverlap, + nowIndicator: this.nowIndicator, + dragRevertDuration: this.dragRevertDuration, + dragOpacity: this.dragOpacity, + dragScroll: this.dragScroll, + eventOverlap: this.eventOverlap, + eventConstraint: this.eventConstraint, + eventRender: this.eventRender, + dayRender: this.dayRender, + dayClick: (date, jsEvent, view) => { + this.onDayClick.emit({ + 'date': date, + 'jsEvent': jsEvent, + 'view': view + }); + }, + drop: (date, jsEvent, ui, resourceId) => { + this.onDrop.emit({ + 'date': date, + 'jsEvent': jsEvent, + 'ui': ui, + 'resourceId': resourceId + }); + }, + eventClick: (calEvent, jsEvent, view) => { + this.onEventClick.emit({ + 'calEvent': calEvent, + 'jsEvent': jsEvent, + 'view': view + }); + }, + eventMouseover: (calEvent, jsEvent, view) => { + this.onEventMouseover.emit({ + 'calEvent': calEvent, + 'jsEvent': jsEvent, + 'view': view + }); + }, + eventMouseout: (calEvent, jsEvent, view) => { + this.onEventMouseout.emit({ + 'calEvent': calEvent, + 'jsEvent': jsEvent, + 'view': view + }); + }, + eventDragStart: (event, jsEvent, ui, view) => { + this.onEventDragStart.emit({ + 'event': event, + 'jsEvent': jsEvent, + 'view': view + }); + }, + eventDragStop: (event, jsEvent, ui, view) => { + this.onEventDragStop.emit({ + 'event': event, + 'jsEvent': jsEvent, + 'view': view + }); + }, + eventDrop: (event, delta, revertFunc, jsEvent, ui, view) => { + this.updateEvent(event); + + this.onEventDrop.emit({ + 'event': event, + 'delta': delta, + 'revertFunc': revertFunc, + 'jsEvent': jsEvent, + 'view': view + }); + }, + eventResizeStart: (event, jsEvent, ui, view) => { + this.onEventResizeStart.emit({ + 'event': event, + 'jsEvent': jsEvent, + 'view': view + }); + }, + eventResizeStop: (event, jsEvent, ui, view) => { + this.onEventResizeStop.emit({ + 'event': event, + 'jsEvent': jsEvent, + 'view': view + }); + }, + eventResize: (event, delta, revertFunc, jsEvent, ui, view) => { + this.updateEvent(event); + + this.onEventResize.emit({ + 'event': event, + 'delta': delta, + 'revertFunc': revertFunc, + 'jsEvent': jsEvent, + 'view': view + }); + }, + viewRender: (view, element) => { + this.onViewRender.emit({ + 'view': view, + 'element': element + }); + } + }; + + if(this.options) { + for(let prop in this.options) { + this.config[prop] = this.options[prop]; + } + } + } + + ngAfterViewChecked() { + if(!this.initialized && this.el.nativeElement.offsetParent) { + this.initialize(); + } + } + + ngOnChanges(changes: SimpleChanges) { + if(this.schedule) { + let options = {}; + for(let change in changes) { + if(change !== 'events') { + options[change] = changes[change].currentValue; + } + } + + if(Object.keys(options).length) { + this.schedule.fullCalendar('option', options); + } + } + } + + initialize() { + this.schedule = jQuery(this.el.nativeElement.children[0]); + this.schedule.fullCalendar(this.config); + this.schedule.fullCalendar('addEventSource', this.events); + this.initialized = true; + } + + ngDoCheck() { + let changes = this.differ.diff(this.events); + + if(this.schedule && changes) { + this.schedule.fullCalendar('removeEventSources'); + this.schedule.fullCalendar('addEventSource', this.events); + } + } + + ngOnDestroy() { + jQuery(this.el.nativeElement.children[0]).fullCalendar('destroy'); + this.initialized = false; + this.schedule = null; + } + + gotoDate(date: any) { + this.schedule.fullCalendar('gotoDate', date); + } + + prev() { + this.schedule.fullCalendar('prev'); + } + + next() { + this.schedule.fullCalendar('next'); + } + + prevYear() { + this.schedule.fullCalendar('prevYear'); + } + + nextYear() { + this.schedule.fullCalendar('nextYear'); + } + + today() { + this.schedule.fullCalendar('today'); + } + + incrementDate(duration: any) { + this.schedule.fullCalendar('incrementDate', duration); + } + + changeView(viewName: string) { + this.schedule.fullCalendar('changeView', viewName); + } + + getDate() { + return this.schedule.fullCalendar('getDate'); + } + + findEvent(id: string) { + let event; + if(this.events) { + for(let e of this.events) { + if(e.id === id) { + event = e; + break; + } + } + } + return event; + } + + updateEvent(event: any) { + let sourceEvent = this.findEvent(event.id); + if(sourceEvent) { + sourceEvent.start = event.start.format(); + if(event.end) { + sourceEvent.end = event.end.format(); + } + } + } +} + +@NgModule({ + imports: [CommonModule], + exports: [Schedule], + declarations: [Schedule] +}) +export class ScheduleModule { } diff --git a/src/app/components/selectbutton/selectbutton.css b/src/app/components/selectbutton/selectbutton.css new file mode 100644 index 00000000000..b2b6650d3bf --- /dev/null +++ b/src/app/components/selectbutton/selectbutton.css @@ -0,0 +1,11 @@ +.ui-selectbutton{ + display: inline-block; +} + +.ui-selectbutton.ui-state-error { + padding: 0; +} + +.ui-selectbutton .ui-button.ui-state-focus{ + outline: none; +} \ No newline at end of file diff --git a/src/app/components/selectbutton/selectbutton.ts b/src/app/components/selectbutton/selectbutton.ts new file mode 100644 index 00000000000..dd101e27434 --- /dev/null +++ b/src/app/components/selectbutton/selectbutton.ts @@ -0,0 +1,128 @@ +import {NgModule,Component,Input,Output,EventEmitter,forwardRef} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {SelectItem} from '../common/selectitem'; +import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; + +export const SELECTBUTTON_VALUE_ACCESSOR: any = { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => SelectButton), + multi: true +}; + +@Component({ + selector: 'p-selectButton', + template: ` +
+
+ {{option.label}} +
+ +
+
+
+ `, + providers: [SELECTBUTTON_VALUE_ACCESSOR] +}) +export class SelectButton implements ControlValueAccessor { + + @Input() options: SelectItem[]; + + @Input() tabindex: number; + + @Input() multiple: boolean; + + @Input() style: any; + + @Input() styleClass: string; + + @Input() disabled: boolean; + + @Output() onChange: EventEmitter = new EventEmitter(); + + value: any; + + focusedItem: HTMLInputElement; + + onModelChange: Function = () => {}; + + onModelTouched: Function = () => {}; + + writeValue(value: any) : void { + this.value = value; + } + + registerOnChange(fn: Function): void { + this.onModelChange = fn; + } + + registerOnTouched(fn: Function): void { + this.onModelTouched = fn; + } + + setDisabledState(val: boolean): void { + this.disabled = val; + } + + onItemClick(event, option: SelectItem, checkbox: HTMLInputElement) { + if(this.disabled) { + return; + } + + checkbox.focus(); + + if(this.multiple) { + let itemIndex = this.findItemIndex(option); + if(itemIndex != -1) + this.value = this.value.filter((val,i) => i!=itemIndex); + else + this.value = [...this.value||[], option.value]; + } + else { + this.value = option.value; + } + + this.onModelChange(this.value); + + this.onChange.emit({ + originalEvent: event, + value: this.value + }); + } + + onFocus(event: Event) { + this.focusedItem = event.target; + } + + onBlur(event) { + this.focusedItem = null; + this.onModelTouched(); + } + + isSelected(option: SelectItem) { + if(this.multiple) + return this.findItemIndex(option) != -1; + else + return option.value == this.value; + } + + findItemIndex(option: SelectItem) { + let index = -1; + if(this.value) { + for(let i = 0; i < this.value.length; i++) { + if(this.value[i] == option.value) { + index = i; + break; + } + } + } + return index; + } +} + +@NgModule({ + imports: [CommonModule], + exports: [SelectButton], + declarations: [SelectButton] +}) +export class SelectButtonModule { } diff --git a/src/app/components/slidemenu/slidemenu.ts b/src/app/components/slidemenu/slidemenu.ts new file mode 100644 index 00000000000..6ec0f22d85e --- /dev/null +++ b/src/app/components/slidemenu/slidemenu.ts @@ -0,0 +1,221 @@ +import {NgModule,Component,ElementRef,AfterViewInit,OnDestroy,Input,Output,Renderer2,EventEmitter,Inject,forwardRef,ViewChild} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {DomHandler} from '../dom/domhandler'; +import {MenuItem} from '../common/menuitem'; +import {Location} from '@angular/common'; +import {RouterModule} from '@angular/router'; + +@Component({ + selector: 'p-slideMenuSub', + template: ` + + ` +}) +export class SlideMenuSub implements OnDestroy { + + @Input() item: MenuItem; + + @Input() root: boolean; + + @Input() backLabel: string = 'Back'; + + @Input() menuWidth: string; + + @Input() effectDuration: any; + + @Input() easing: string = 'ease-out'; + + constructor(@Inject(forwardRef(() => SlideMenu)) public slideMenu: SlideMenu) {} + + activeItem: any; + + itemClick(event, item: MenuItem, listitem: any) { + if(item.disabled) { + event.preventDefault(); + return; + } + + if(!item.url) { + event.preventDefault(); + } + + if(item.command) { + if(!item.eventEmitter && item.command) { + item.eventEmitter = new EventEmitter(); + item.eventEmitter.subscribe(item.command); + } + + item.eventEmitter.emit({ + originalEvent: event, + item: item + }); + } + + if(item.items && !this.slideMenu.animating) { + this.slideMenu.left -= this.slideMenu.menuWidth; + this.activeItem = listitem; + this.slideMenu.animating = true; + setTimeout(() => this.slideMenu.animating = false, this.effectDuration); + } + } + + ngOnDestroy() { + this.activeItem = null; + } +} + +@Component({ + selector: 'p-slideMenu', + template: ` +
+
+
+ +
+
+ {{backLabel}} +
+
+
+ `, + providers: [DomHandler] +}) +export class SlideMenu implements AfterViewInit,OnDestroy { + + @Input() model: MenuItem[]; + + @Input() popup: boolean; + + @Input() style: any; + + @Input() styleClass: string; + + @Input() menuWidth: number = 190; + + @Input() viewportHeight: number = 175; + + @Input() effectDuration: any = 500; + + @Input() easing: string = 'ease-out'; + + @Input() backLabel: string = 'Back'; + + @ViewChild('container') containerViewChild: ElementRef; + + @ViewChild('backward') backwardViewChild: ElementRef; + + @ViewChild('slideMenuContent') slideMenuContentViewChild: ElementRef; + + public container: HTMLDivElement; + + public backwardElement: HTMLDivElement; + + public slideMenuContentElement: HTMLDivElement; + + public documentClickListener: any; + + public preventDocumentDefault: any; + + public left: number = 0; + + public animating: boolean = false; + + constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2) {} + + ngAfterViewInit() { + this.container = this.containerViewChild.nativeElement; + this.backwardElement = this.backwardViewChild.nativeElement; + this.slideMenuContentElement = this.slideMenuContentViewChild.nativeElement; + this.slideMenuContentElement.style.height = this.viewportHeight - this.domHandler.getHiddenElementOuterHeight(this.backwardElement) + 'px'; + + if(this.popup) { + this.documentClickListener = this.renderer.listen('document', 'click', () => { + if(!this.preventDocumentDefault) { + this.hide(); + } + this.preventDocumentDefault = false; + }); + } + } + + toggle(event) { + if(this.container.offsetParent) + this.hide(); + else + this.show(event); + } + + show(event) { + this.preventDocumentDefault = true; + this.container.style.display = 'block'; + this.domHandler.absolutePosition(this.container, event.target); + this.domHandler.fadeIn(this.container, 250); + } + + hide() { + this.container.style.display = 'none'; + } + + unsubscribe(item: any) { + if(item.eventEmitter) { + item.eventEmitter.unsubscribe(); + } + + if(item.items) { + for(let childItem of item.items) { + this.unsubscribe(childItem); + } + } + } + + onClick(event) { + this.preventDocumentDefault = true; + } + + goBack() { + this.left += this.menuWidth; + } + + ngOnDestroy() { + if(this.documentClickListener) { + this.documentClickListener(); + } + + if(this.model) { + for(let item of this.model) { + this.unsubscribe(item); + } + } + } + +} + +@NgModule({ + imports: [CommonModule,RouterModule], + exports: [SlideMenu,RouterModule], + declarations: [SlideMenu,SlideMenuSub] +}) +export class SlideMenuModule { } diff --git a/src/app/components/slider/slider.css b/src/app/components/slider/slider.css new file mode 100644 index 00000000000..00dafd7306a --- /dev/null +++ b/src/app/components/slider/slider.css @@ -0,0 +1,65 @@ +.ui-slider { + position: relative; + text-align: left; +} +.ui-slider .ui-slider-handle { + position: absolute; + width: 1.2em; + height: 1.2em; + cursor: default; + -ms-touch-action: none; + touch-action: none; + z-index: 1; +} +.ui-slider .ui-slider-handle.ui-slider-handle-active { + z-index: 2; +} +.ui-slider .ui-slider-range { + position: absolute; + font-size: .7em; + display: block; + border: 0; + background-position: 0 0; +} + +.ui-slider-horizontal { + height: .8em; +} +.ui-slider-horizontal .ui-slider-handle { + top: -.25em; + margin-left: -.6em; +} +.ui-slider-horizontal .ui-slider-range { + top: 0; + height: 100%; +} +.ui-slider-horizontal .ui-slider-range-min { + left: 0; +} +.ui-slider-horizontal .ui-slider-range-max { + right: 0; +} + +.ui-slider-vertical { + width: .8em; + height: 100px; +} +.ui-slider-vertical .ui-slider-handle { + left: -.25em; + margin-left: 0; + margin-bottom: -.6em; +} +.ui-slider-vertical .ui-slider-range { + left: 0; + width: 100%; +} +.ui-slider-vertical .ui-slider-range-min { + bottom: 0; +} +.ui-slider-vertical .ui-slider-range-max { + top: 0; +} + +.ui-slider-animate .ui-slider-handle { + transition: left .3s; +} \ No newline at end of file diff --git a/src/app/components/slider/slider.ts b/src/app/components/slider/slider.ts new file mode 100644 index 00000000000..82d24aa7236 --- /dev/null +++ b/src/app/components/slider/slider.ts @@ -0,0 +1,332 @@ +import {NgModule,Component, ElementRef,AfterViewInit,OnDestroy,Input,Output,SimpleChange,EventEmitter,forwardRef,Renderer2} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {DomHandler} from '../dom/domhandler'; +import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; + +export const SLIDER_VALUE_ACCESSOR: any = { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => Slider), + multi: true +}; + +@Component({ + selector: 'p-slider', + template: ` +
+ + + + + +
+ `, + providers: [SLIDER_VALUE_ACCESSOR,DomHandler] +}) +export class Slider implements AfterViewInit,OnDestroy,ControlValueAccessor { + + @Input() animate: boolean; + + @Input() disabled: boolean; + + @Input() min: number = 0; + + @Input() max: number = 100; + + @Input() orientation: string = 'horizontal'; + + @Input() step: number; + + @Input() range: boolean; + + @Input() style: any; + + @Input() styleClass: string; + + @Output() onChange: EventEmitter = new EventEmitter(); + + @Output() onSlideEnd: EventEmitter = new EventEmitter(); + + public value: number; + + public values: number; + + public handleValue: number; + + public handleValues: number[] = []; + + public onModelChange: Function = () => {}; + + public onModelTouched: Function = () => {}; + + public dragging: boolean; + + public dragListener: any; + + public mouseupListener: any; + + public initX: number; + + public initY: number; + + public barWidth: number; + + public barHeight: number; + + public sliderHandleClick: boolean; + + public handleIndex: number; + + public startHandleValue: any; + + public startx: number; + + public starty: number; + + constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2) {} + + onMouseDown(event:Event,index?:number) { + if(this.disabled) { + return; + } + + this.dragging = true; + this.updateDomData(); + this.sliderHandleClick = true; + this.handleIndex = index; + } + + onTouchStart(event, index?:number) { + var touchobj = event.changedTouches[0]; + this.startHandleValue = (this.range) ? this.handleValues[index] : this.handleValue; + this.dragging = true; + this.handleIndex = index; + + if (this.orientation === 'horizontal') { + this.startx = parseInt(touchobj.clientX, 10); + this.barWidth = this.el.nativeElement.children[0].offsetWidth; + } + else { + this.starty = parseInt(touchobj.clientY, 10); + this.barHeight = this.el.nativeElement.children[0].offsetHeight; + } + + event.preventDefault(); + } + + onTouchMove(event, index?:number) { + var touchobj = event.changedTouches[0], + handleValue = 0; + + if (this.orientation === 'horizontal') { + handleValue = Math.floor(((parseInt(touchobj.clientX, 10) - this.startx) * 100) / (this.barWidth)) + this.startHandleValue; + } + else { + handleValue = Math.floor(((this.starty - parseInt(touchobj.clientY, 10)) * 100) / (this.barHeight)) + this.startHandleValue; + } + + this.setValueFromHandle(event, handleValue); + + event.preventDefault(); + } + + onBarClick(event) { + if(this.disabled) { + return; + } + + if(!this.sliderHandleClick) { + this.updateDomData(); + this.handleChange(event); + } + + this.sliderHandleClick = false; + } + + ngAfterViewInit() { + if(this.disabled) { + return; + } + + this.dragListener = this.renderer.listen('document', 'mousemove', (event) => { + if(this.dragging) { + this.handleChange(event); + } + }); + + this.mouseupListener = this.renderer.listen('document', 'mouseup', (event) => { + if(this.dragging) { + this.dragging = false; + if(this.range) { + this.onSlideEnd.emit({originalEvent: event, values: this.values}); + } else { + this.onSlideEnd.emit({originalEvent: event, value: this.value}); + } + } + }); + } + + handleChange(event: Event) { + let handleValue = this.calculateHandleValue(event); + this.setValueFromHandle(event, handleValue); + } + + setValueFromHandle(event: Event, handleValue: any) { + let newValue = this.getValueFromHandle(handleValue); + + if(this.range) { + if(this.step) { + this.handleStepChange(newValue, this.values[this.handleIndex]); + } + else { + this.handleValues[this.handleIndex] = handleValue; + this.updateValue(newValue, event); + } + } + else { + if(this.step) { + this.handleStepChange(newValue, this.value); + } + else { + this.handleValue = handleValue; + this.updateValue(newValue, event); + } + } + } + + handleStepChange(newValue: number, oldValue: number) { + let diff = (newValue - oldValue); + + if(diff < 0 && (-1 * diff) >= this.step / 2) { + newValue = oldValue - this.step; + this.updateValue(newValue); + this.updateHandleValue(); + } + else if(diff > 0 && diff >= this.step / 2) { + newValue = oldValue + this.step; + this.updateValue(newValue); + this.updateHandleValue(); + } + } + + writeValue(value: any) : void { + if(this.range) + this.values = value||[0,0]; + else + this.value = value||0; + + this.updateHandleValue(); + } + + registerOnChange(fn: Function): void { + this.onModelChange = fn; + } + + registerOnTouched(fn: Function): void { + this.onModelTouched = fn; + } + + setDisabledState(val: boolean): void { + this.disabled = val; + } + + updateDomData(): void { + let rect = this.el.nativeElement.children[0].getBoundingClientRect(); + this.initX = rect.left + this.domHandler.getWindowScrollLeft(); + this.initY = rect.top + this.domHandler.getWindowScrollTop(); + this.barWidth = this.el.nativeElement.children[0].offsetWidth; + this.barHeight = this.el.nativeElement.children[0].offsetHeight; + } + + calculateHandleValue(event): number { + if(this.orientation === 'horizontal') + return Math.floor(((event.pageX - this.initX) * 100) / (this.barWidth)); + else + return Math.floor((((this.initY + this.barHeight) - event.pageY) * 100) / (this.barHeight)); + } + + updateHandleValue(): void { + if(this.range) { + this.handleValues[0] = (this.values[0] < this.min ? 0 : this.values[0] - this.min) * 100 / (this.max - this.min); + this.handleValues[1] = (this.values[1] > this.max ? 100 : this.values[1] - this.min) * 100 / (this.max - this.min); + } + else { + if(this.value < this.min) + this.handleValue = 0; + else if(this.value > this.max) + this.handleValue = 100; + else + this.handleValue = (this.value - this.min) * 100 / (this.max - this.min); + } + } + + updateValue(val: number, event?: Event): void { + if(this.range) { + let value = val; + + if(this.handleIndex == 0) { + if(value < this.min) { + value = this.min; + this.handleValues[0] = 0; + } + else if (value > this.values[1]) { + value = this.values[1]; + this.handleValues[0] = this.handleValues[1]; + } + } + else { + if(value > this.max) { + value = this.max; + this.handleValues[1] = 100; + } + else if (value < this.values[0]) { + value = this.values[0]; + this.handleValues[1] = this.handleValues[0]; + } + } + + this.values[this.handleIndex] = Math.floor(value); + this.onModelChange(this.values); + this.onChange.emit({event: event, values: this.values}); + } + else { + if(val < this.min) { + val = this.min; + this.handleValue = 0; + } + else if (val > this.max) { + val = this.max; + this.handleValue = 100; + } + + this.value = Math.floor(val); + this.onModelChange(this.value); + this.onChange.emit({event: event, value: this.value}); + } + } + + getValueFromHandle(handleValue: number): number { + return (this.max - this.min) * (handleValue / 100) + this.min; + } + + ngOnDestroy() { + if(this.dragListener) { + this.dragListener(); + } + + if(this.mouseupListener) { + this.mouseupListener(); + } + } +} + +@NgModule({ + imports: [CommonModule], + exports: [Slider], + declarations: [Slider] +}) +export class SliderModule { } diff --git a/src/app/components/spinner/spinner.css b/src/app/components/spinner/spinner.css new file mode 100644 index 00000000000..9b25a7170e4 --- /dev/null +++ b/src/app/components/spinner/spinner.css @@ -0,0 +1,61 @@ +.ui-spinner { + display: inline-block; + overflow: visible; + padding: 0; + position: relative; + vertical-align: middle; +} + +.ui-spinner-input { + vertical-align: middle; + padding-right: 1.5em; +} + +.ui-spinner-button { + cursor: default; + display: block; + height: 50%; + margin: 0; + overflow: hidden; + padding: 0; + position: absolute; + right: 0; + text-align: center; + vertical-align: middle; + width: 1.5em; +} + +.ui-spinner .fa { + position: absolute; + top: 50%; + left: 50%; + margin-top: -.5em; + margin-left: -.5em; + width: 1em; +} + +.ui-spinner-up { + top: 0; +} + +.ui-spinner-down { + bottom: 0; +} + +/* Fluid */ +.ui-fluid .ui-spinner { + width: 100%; +} + +.ui-fluid .ui-spinner .ui-spinner-input { + padding-right: 2em; + width: 100%; +} + +.ui-fluid .ui-spinner .ui-spinner-button { + width: 1.5em; +} + +.ui-fluid .ui-spinner .ui-spinner-button .fa { + left: .7em; +} \ No newline at end of file diff --git a/src/app/components/spinner/spinner.ts b/src/app/components/spinner/spinner.ts new file mode 100644 index 00000000000..65eb5748549 --- /dev/null +++ b/src/app/components/spinner/spinner.ts @@ -0,0 +1,300 @@ +import {NgModule,Component,ElementRef,OnInit,Input,Output,EventEmitter,forwardRef} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {InputTextModule} from '../inputtext/inputtext'; +import {DomHandler} from '../dom/domhandler'; +import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; + +export const SPINNER_VALUE_ACCESSOR: any = { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => Spinner), + multi: true +}; + +@Component({ + selector: 'p-spinner', + template: ` + + + + + + `, + host: { + '[class.ui-inputwrapper-filled]': 'filled', + '[class.ui-inputwrapper-focus]': 'focus' + }, + providers: [DomHandler,SPINNER_VALUE_ACCESSOR], +}) +export class Spinner implements OnInit,ControlValueAccessor { + + @Output() onChange: EventEmitter = new EventEmitter(); + + @Output() onBlur: EventEmitter = new EventEmitter(); + + @Input() step: number = 1; + + @Input() min: number; + + @Input() max: number; + + @Input() maxlength: number; + + @Input() size: number; + + @Input() placeholder: string; + + @Input() inputId: string; + + @Input() disabled: boolean; + + @Input() readonly: boolean; + + @Input() decimalSeparator: string = '.'; + + @Input() thousandSeparator: string = ','; + + @Input() tabindex: number; + + @Input() formatInput: boolean = true; + + value: number; + + valueAsString: string = ''; + + onModelChange: Function = () => {}; + + onModelTouched: Function = () => {}; + + keyPattern: RegExp = /[0-9\+\-]/; + + public precision: number; + + public timer: any; + + public focus: boolean; + + public filled: boolean; + + constructor(public el: ElementRef, public domHandler: DomHandler) {} + + ngOnInit() { + if(Math.floor(this.step) === 0) { + this.precision = this.step.toString().split(/[,]|[.]/)[1].length; + } + } + + repeat(interval: number, dir: number) { + let i = interval||500; + + this.clearTimer(); + this.timer = setTimeout(() => { + this.repeat(40, dir); + }, i); + + this.spin(dir); + } + + spin(dir: number) { + let step = this.step * dir; + let currentValue = this.value||0; + let newValue: number = null; + + if(this.precision) + this.value = parseFloat(this.toFixed(currentValue + step, this.precision)); + else + this.value = currentValue + step; + + if(this.maxlength !== undefined && this.value.toString().length > this.maxlength) { + this.value = currentValue; + } + + if(this.min !== undefined && this.value < this.min) { + this.value = this.min; + } + + if(this.max !== undefined && this.value > this.max) { + this.value = this.max; + } + + this.formatValue(); + this.onModelChange(this.value); + this.onChange.emit(); + } + + toFixed(value: number, precision: number) { + let power = Math.pow(10, precision||0); + return String(Math.round(value * power) / power); + } + + onUpButtonMousedown(event: Event,input: HTMLInputElement) { + if(!this.disabled) { + input.focus(); + this.repeat(null, 1); + this.updateFilledState(); + } + } + + onUpButtonMouseup(event: Event) { + if(!this.disabled) { + this.clearTimer(); + } + } + + onUpButtonMouseleave(event: Event) { + if(!this.disabled) { + this.clearTimer(); + } + } + + onDownButtonMousedown(event: Event, input: HTMLInputElement) { + if(!this.disabled) { + input.focus(); + this.repeat(null, -1); + this.updateFilledState(); + } + } + + onDownButtonMouseup(event: Event) { + if(!this.disabled) { + this.clearTimer(); + } + } + + onDownButtonMouseleave(event: Event) { + if(!this.disabled) { + this.clearTimer(); + } + } + + onInputKeydown(event: KeyboardEvent) { + if(event.which == 38) { + this.spin(1); + event.preventDefault(); + } + else if(event.which == 40) { + this.spin(-1); + event.preventDefault(); + } + } + + onInputKeyPress(event: KeyboardEvent) { + let inputChar = String.fromCharCode(event.charCode); + if(!this.keyPattern.test(inputChar) && inputChar != this.decimalSeparator && event.keyCode != 9 && event.keyCode != 8 && event.keyCode != 37 && event.keyCode != 39 && event.keyCode != 46) { + event.preventDefault(); + } + } + + onInput(event: Event, inputValue: string) { + this.value = this.parseValue(inputValue); + this.formatValue(); + this.onModelChange(this.value); + this.updateFilledState(); + } + + onInputBlur(event) { + this.focus = false; + this.onModelTouched(); + this.onBlur.emit(event); + } + + onFocus() { + this.focus = true; + } + + parseValue(val: string): number { + let value: number; + + if(this.formatInput) { + val = val.split(this.thousandSeparator).join(''); + } + + if(val.trim() === '') { + value= this.min !== undefined ? this.min : null; + } + else { + if(this.precision) { + value = parseFloat(val.replace(',','.')); + } + else { + value = parseInt(val); + } + + if(!isNaN(value)) { + if(this.max !== undefined && value > this.max) { + value = this.max; + } + + if(this.min !== undefined && value < this.min) { + value = this.min; + } + } + else { + value = null; + } + } + + return value; + } + + formatValue(): void { + if(this.value !== null && this.value !== undefined) { + let textValue = String(this.value).replace('.', this.decimalSeparator); + + if(this.formatInput) { + textValue = textValue.replace(/\B(?=(\d{3})+(?!\d))/g, this.thousandSeparator); + } + this.valueAsString = textValue; + } + else { + this.valueAsString = ''; + } + } + + handleChange(event: Event) { + this.onChange.emit(event); + } + + clearTimer() { + if(this.timer) { + clearInterval(this.timer); + } + } + + writeValue(value: any) : void { + this.value = value; + this.formatValue(); + this.updateFilledState(); + } + + registerOnChange(fn: Function): void { + this.onModelChange = fn; + } + + registerOnTouched(fn: Function): void { + this.onModelTouched = fn; + } + + setDisabledState(val: boolean): void { + this.disabled = val; + } + + updateFilledState() { + this.filled = (this.value !== undefined && this.value != null); + } +} + + +@NgModule({ + imports: [CommonModule,InputTextModule], + exports: [Spinner], + declarations: [Spinner] +}) +export class SpinnerModule { } diff --git a/src/app/components/splitbutton/splitbutton.css b/src/app/components/splitbutton/splitbutton.css new file mode 100644 index 00000000000..3ccc9c24926 --- /dev/null +++ b/src/app/components/splitbutton/splitbutton.css @@ -0,0 +1,31 @@ +.ui-splitbutton { + position: relative; + display: inline-block; + zoom: 1; +} + +.ui-splitbutton .ui-button.ui-splitbutton-menubutton { + width: 2em; +} + +.ui-splitbutton.ui-state-disabled button { + cursor: default; +} + +.ui-fluid .ui-splitbutton { + width: 100%; + box-sizing: border-box; + -webkit-box-sizing:border-box; + -moz-box-sizing: border-box; +} + +.ui-fluid .ui-splitbutton .ui-button:first-child { + width: calc(100% - 2em); +} + +.ui-fluid .ui-splitbutton .ui-button.ui-splitbutton-menubutton { + width: 2em; + box-sizing: border-box; + -webkit-box-sizing:border-box; + -moz-box-sizing: border-box; +} \ No newline at end of file diff --git a/src/app/components/splitbutton/splitbutton.ts b/src/app/components/splitbutton/splitbutton.ts new file mode 100644 index 00000000000..4a7690f45c4 --- /dev/null +++ b/src/app/components/splitbutton/splitbutton.ts @@ -0,0 +1,125 @@ +import {NgModule,Component,ElementRef,OnInit,OnDestroy,Input,Output,EventEmitter,ContentChildren,QueryList,Renderer2,ChangeDetectorRef} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {DomHandler} from '../dom/domhandler'; +import {MenuItem} from '../common/menuitem'; +import {ButtonModule} from '../button/button'; +import {Router} from '@angular/router'; +import {RouterModule} from '@angular/router'; + +@Component({ + selector: 'p-splitButton', + template: ` + + `, + providers: [DomHandler] +}) +export class SplitButton implements OnInit,OnDestroy { + + @Input() model: MenuItem[]; + + @Input() icon: string; + + @Input() iconPos: string = 'left'; + + @Input() label: string; + + @Output() onClick: EventEmitter = new EventEmitter(); + + @Output() onDropdownClick: EventEmitter = new EventEmitter(); + + @Input() style: any; + + @Input() styleClass: string; + + @Input() menuStyle: any; + + @Input() menuStyleClass: string; + + @Input() disabled: boolean; + + @Input() tabindex: number; + + public menuVisible: boolean = false; + + public documentClickListener: any; + + constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2, public router: Router, public cd: ChangeDetectorRef) {} + + ngOnInit() { + this.documentClickListener = this.renderer.listen('document', 'click', () => { + this.menuVisible = false; + this.cd.markForCheck(); + }); + } + + onDefaultButtonClick(event: Event) { + this.onClick.emit(event); + } + + itemClick(event: Event, item: MenuItem) { + if(item.disabled) { + event.preventDefault(); + return; + } + + if(!item.url) { + event.preventDefault(); + } + + if(item.command) { + if(!item.eventEmitter) { + item.eventEmitter = new EventEmitter(); + item.eventEmitter.subscribe(item.command); + } + + item.eventEmitter.emit({ + originalEvent: event, + item: item + }); + } + + this.menuVisible = false; + } + + onDropdownButtonClick(event: Event, menu: HTMLDivElement, container: Element) { + this.menuVisible= !this.menuVisible; + this.domHandler.relativePosition(menu, container); + this.domHandler.fadeIn(menu,25); + menu.style.zIndex = String(++DomHandler.zindex); + this.onDropdownClick.emit(event); + event.stopPropagation(); + } + + ngOnDestroy() { + if(this.documentClickListener) { + this.documentClickListener(); + } + } +} + +@NgModule({ + imports: [CommonModule,ButtonModule,RouterModule], + exports: [SplitButton,ButtonModule,RouterModule], + declarations: [SplitButton] +}) +export class SplitButtonModule { } diff --git a/src/app/components/steps/steps.css b/src/app/components/steps/steps.css new file mode 100644 index 00000000000..0c6039c87b4 --- /dev/null +++ b/src/app/components/steps/steps.css @@ -0,0 +1,49 @@ +.ui-steps ul { + list-style-type: none; + padding: 0; + margin: 0; +} + +.ui-steps .ui-steps-item { + float: left; + box-sizing: border-box; + cursor: pointer; +} + +.ui-steps.ui-steps-readonly .ui-steps-item { + cursor: auto; +} + +.ui-steps .ui-steps-item .ui-menuitem-link { + text-decoration: none; + display: block; + padding: 1em; + position: relative; + text-align: center; +} + +.ui-steps .ui-steps-item.ui-state-highlight .ui-menuitem-link, +.ui-steps .ui-steps-item.ui-state-disabled .ui-menuitem-link { + cursor: default; +} + +.ui-steps .ui-steps-number { + font-size: 200%; + display: block; +} + +.ui-steps .ui-steps-title { + display: block; + white-space: nowrap; +} + +/* Responsive */ +@media (max-width: 40em) { + .ui-steps .ui-steps-item .ui-menuitem-link { + padding: 0.5em; + } + + .ui-steps .ui-steps-item .ui-steps-title { + display: none; + } +} \ No newline at end of file diff --git a/src/app/components/steps/steps.ts b/src/app/components/steps/steps.ts new file mode 100644 index 00000000000..65d04ae75e2 --- /dev/null +++ b/src/app/components/steps/steps.ts @@ -0,0 +1,74 @@ +import {NgModule,Component,Input,Output,EventEmitter} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {MenuItem} from '../common/menuitem'; +import {RouterModule} from '@angular/router'; + +@Component({ + selector: 'p-steps', + template: ` + + ` +}) +export class Steps { + + @Input() activeIndex: number = 0; + + @Input() model: MenuItem[]; + + @Input() readonly: boolean = true; + + @Input() style: any; + + @Input() styleClass: string; + + @Output() activeIndexChange: EventEmitter = new EventEmitter(); + + itemClick(event: Event, item: MenuItem, i: number) { + if(this.readonly || item.disabled) { + event.preventDefault(); + return; + } + + this.activeIndexChange.emit(i); + + if(!item.url) { + event.preventDefault(); + } + + if(item.command) { + if(!item.eventEmitter) { + item.eventEmitter = new EventEmitter(); + item.eventEmitter.subscribe(item.command); + } + + item.eventEmitter.emit({ + originalEvent: event, + item: item, + index: i + }); + } + } + +} + +@NgModule({ + imports: [CommonModule,RouterModule], + exports: [Steps,RouterModule], + declarations: [Steps] +}) +export class StepsModule { } \ No newline at end of file diff --git a/src/app/components/tabmenu/tabmenu.css b/src/app/components/tabmenu/tabmenu.css new file mode 100644 index 00000000000..1ccd8c4603e --- /dev/null +++ b/src/app/components/tabmenu/tabmenu.css @@ -0,0 +1,39 @@ +/** TabMenu **/ +.ui-tabmenu { + +} + +.ui-tabmenu .ui-tabmenu-nav { + margin: 0; + padding: .25em .5em 0 .25em; +} + +.ui-tabmenu .ui-tabmenu-nav .ui-tabmenuitem { + list-style: none; + float: left; + position: relative; + margin: 0 .2em 1px 0; + padding: 0; + white-space: nowrap; + display: block; + border-bottom: 0; + top: 1px; +} + +.ui-tabmenu .ui-tabmenu-nav .ui-tabmenuitem a { + float: left; + padding: 0.5em 1em; + text-decoration: none; +} + +.ui-tabmenu .ui-tabmenu-nav a { + padding: 0.5em 1em; +} + +.ui-tabmenu .ui-tabmenu-nav .ui-tabmenuitem .ui-icon { + float: left; +} + +.ui-tabmenu .ui-tabmenu-nav .ui-tabmenuitem.ui-state-disabled a { + cursor: default; +} \ No newline at end of file diff --git a/src/app/components/tabmenu/tabmenu.ts b/src/app/components/tabmenu/tabmenu.ts new file mode 100644 index 00000000000..a9b72347506 --- /dev/null +++ b/src/app/components/tabmenu/tabmenu.ts @@ -0,0 +1,102 @@ +import {NgModule,Component,ElementRef,OnDestroy,Input,Output,EventEmitter} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {DomHandler} from '../dom/domhandler'; +import {MenuItem} from '../common/menuitem'; +import {Location} from '@angular/common'; +import {RouterModule} from '@angular/router'; + +@Component({ + selector: 'p-tabMenu', + template: ` + + `, + providers: [DomHandler] +}) +export class TabMenu implements OnDestroy { + + @Input() model: MenuItem[]; + + @Input() activeItem: MenuItem; + + @Input() popup: boolean; + + @Input() style: any; + + @Input() styleClass: string; + + ngOnInit() { + if(!this.activeItem && this.model && this.model.length) { + this.activeItem = this.model[0]; + } + } + + itemClick(event: Event, item: MenuItem) { + if(item.disabled) { + event.preventDefault(); + return; + } + + if(!item.url) { + event.preventDefault(); + } + + if(item.command) { + if(!item.eventEmitter) { + item.eventEmitter = new EventEmitter(); + item.eventEmitter.subscribe(item.command); + } + + item.eventEmitter.emit({ + originalEvent: event, + item: item + }); + } + + this.activeItem = item; + } + + ngOnDestroy() { + if(this.model) { + for(let item of this.model) { + this.unsubscribe(item); + } + } + } + + unsubscribe(item: any) { + if(item.eventEmitter) { + item.eventEmitter.unsubscribe(); + } + + if(item.items) { + for(let childItem of item.items) { + this.unsubscribe(childItem); + } + } + } + +} + +@NgModule({ + imports: [CommonModule,RouterModule], + exports: [TabMenu,RouterModule], + declarations: [TabMenu] +}) +export class TabMenuModule { } \ No newline at end of file diff --git a/src/app/components/tabview/tabview.css b/src/app/components/tabview/tabview.css new file mode 100644 index 00000000000..0e94ce0f54c --- /dev/null +++ b/src/app/components/tabview/tabview.css @@ -0,0 +1,132 @@ +.ui-tabview { + padding: .25em; +} + +.ui-tabview .ui-tabview-nav { + margin: 0; +} + +.ui-tabview .ui-tabview-nav li { + list-style: none; + float: left; + position: relative; + margin: 0 .125em 1px 0; + padding: 0; + white-space: nowrap; +} + +.ui-tabview .ui-tabview-nav li a { + float: left; + padding: .5em 1em; + text-decoration: none; +} + +.ui-tabview .ui-tabview-nav li.ui-tabview-selected a, +.ui-tabview .ui-tabview-nav li.ui-state-disabled a, +.ui-tabview .ui-tabview-nav li.ui-state-processing a { + cursor: text; +} + +.ui-tabview .ui-tabview-nav li a, +.ui-tabview.ui-tabview-collapsible .ui-tabview-nav li.ui-tabview-selected a { + cursor: pointer; +} + +.ui-tabview .ui-tabview-panel { + border-width: 0; + padding: 1em; + background: none; +} + +.ui-tabview .ui-tabview-nav li { + display: block; +} + +.ui-tabview .ui-tabview-nav li .ui-tabview-left-icon, +.ui-tabview .ui-tabview-nav li .ui-tabview-right-icon, +.ui-tabview .ui-tabview-nav li .ui-tabview-title { + vertical-align: middle; +} + +.ui-tabview .ui-tabview-nav li .ui-tabview-close { + margin: 0.5em 0.3em 0 0; + cursor: pointer; +} + +/* per orientation settings */ +/* top and bottom */ +.ui-tabview.ui-tabview-top > .ui-tabview-nav li { + border-bottom: 0; + top: 1px; +} + +.ui-tabview.ui-tabview-top > .ui-tabview-nav { + padding: .2em .2em 0; +} + +.ui-tabview.ui-tabview-bottom > .ui-tabview-nav { + padding: 0 .2em .2em; +} + +.ui-tabview.ui-tabview-bottom > .ui-tabview-nav li { + border-top: 0; +} + +/* left and right*/ +.ui-tabview-left:after, +.ui-tabview-right:after { + clear:both; + content: "."; + display: block; + height: 0; + visibility: hidden; +} + +.ui-tabview-left > .ui-tabview-nav { + float:left; + width: 25%; + height: 300px; + background-image: none; + padding-top: 1px; +} + +.ui-tabview-left > .ui-tabview-panels { + float:right; + width: 75%; +} + +.ui-tabview.ui-tabview-left > .ui-tabview-nav li, +.ui-tabview.ui-tabview-right > .ui-tabview-nav li{ + display: block; + float: right; + white-space: normal; + width: 99%; +} + +.ui-tabview.ui-tabview-left > .ui-tabview-nav li { + margin: 0 0 1px 0; + border-right:0 none; +} + +.ui-tabview.ui-tabview-right > .ui-tabview-nav { + float:right; + width: 25%; + height: 300px; + background-image: none; + padding-top: 1px; +} + +.ui-tabview.ui-tabview-right > .ui-tabview-panels { + float:left; + width: 75%; +} + +.ui-tabview.ui-tabview-right > .ui-tabview-nav li { + margin: 0 0 1px 0; + border-left:0 none; +} + +/* RTL */ +.ui-rtl .ui-tabview .ui-tabview-nav li { + float: right; +} diff --git a/src/app/components/tabview/tabview.ts b/src/app/components/tabview/tabview.ts new file mode 100644 index 00000000000..b8222b5229b --- /dev/null +++ b/src/app/components/tabview/tabview.ts @@ -0,0 +1,260 @@ +import {NgModule,Component,ElementRef,Input,Output,EventEmitter,HostListener,AfterContentInit,ContentChildren,QueryList} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {BlockableUI} from '../common/blockableui'; + +@Component({ + selector: '[p-tabViewNav]', + host:{ + '[class.ui-tabview-nav]': 'true', + '[class.ui-helper-reset]': 'true', + '[class.ui-helper-clearfix]': 'true', + '[class.ui-widget-header]': 'true', + '[class.ui-corner-all]': 'true' + }, + template: ` + +
  • + + + {{tab.header}} + + + +
  • +
    + `, +}) +export class TabViewNav { + + @Input() tabs: TabPanel[]; + + @Input() orientation: string = 'top'; + + @Output() onTabClick: EventEmitter = new EventEmitter(); + + @Output() onTabCloseClick: EventEmitter = new EventEmitter(); + + getDefaultHeaderClass(tab:TabPanel) { + let styleClass = 'ui-state-default ui-corner-' + this.orientation; + if(tab.headerStyleClass) { + styleClass = styleClass + " " + tab.headerStyleClass; + } + return styleClass; + } + + clickTab(event, tab: TabPanel) { + this.onTabClick.emit({ + originalEvent: event, + tab: tab + }) + } + + clickClose(event, tab: TabPanel) { + this.onTabCloseClick.emit({ + originalEvent: event, + tab: tab + }) + } +} + +@Component({ + selector: 'p-tabPanel', + template: ` +
    + +
    + ` +}) +export class TabPanel { + + @Input() header: string; + + @Input() selected: boolean; + + @Input() disabled: boolean; + + @Input() closable: boolean; + + @Input() headerStyle: any; + + @Input() headerStyleClass: string; + + @Input() leftIcon: string; + + @Input() rightIcon: string; + + public closed: boolean; + + public lazy: boolean; +} + +@Component({ + selector: 'p-tabView', + template: ` +
    +
      +
      + +
      +
        +
        + `, +}) +export class TabView implements AfterContentInit,BlockableUI { + + @Input() orientation: string = 'top'; + + @Input() style: any; + + @Input() styleClass: string; + + @Input() controlClose: boolean; + + @Input() lazy: boolean; + + @ContentChildren(TabPanel) tabPanels: QueryList; + + @Output() onChange: EventEmitter = new EventEmitter(); + + @Output() onClose: EventEmitter = new EventEmitter(); + + initialized: boolean; + + tabs: TabPanel[]; + + private _activeIndex: number; + + constructor(public el: ElementRef) {} + + ngAfterContentInit() { + this.initTabs(); + + this.tabPanels.changes.subscribe(_ => { + this.initTabs(); + }); + } + + initTabs(): void { + this.tabs = this.tabPanels.toArray(); + for(let tab of this.tabs) { + tab.lazy = this.lazy; + } + + let selectedTab: TabPanel = this.findSelectedTab(); + if(!selectedTab && this.tabs.length) { + if(this.activeIndex != null && this.tabs.length > this.activeIndex) + this.tabs[this.activeIndex].selected = true; + else + this.tabs[0].selected = true; + } + } + + open(event: Event, tab: TabPanel) { + if(tab.disabled) { + if(event) { + event.preventDefault(); + } + return; + } + + if(!tab.selected) { + let selectedTab: TabPanel = this.findSelectedTab(); + if(selectedTab) { + selectedTab.selected = false + } + tab.selected = true; + this.onChange.emit({originalEvent: event, index: this.findTabIndex(tab)}); + } + + if(event) { + event.preventDefault(); + } + } + + close(event: Event, tab: TabPanel) { + if(this.controlClose) { + this.onClose.emit({ + originalEvent: event, + index: this.findTabIndex(tab), + close: () => { + this.closeTab(tab); + }} + ); + } + else { + this.closeTab(tab); + this.onClose.emit({ + originalEvent: event, + index: this.findTabIndex(tab) + }); + } + + event.stopPropagation(); + } + + closeTab(tab: TabPanel) { + if(tab.selected) { + tab.selected = false; + for(let i = 0; i < this.tabs.length; i++) { + let tabPanel = this.tabs[i]; + if(!tabPanel.closed&&!tab.disabled) { + tabPanel.selected = true; + break; + } + } + } + + tab.closed = true; + } + + findSelectedTab() { + for(let i = 0; i < this.tabs.length; i++) { + if(this.tabs[i].selected) { + return this.tabs[i]; + } + } + return null; + } + + findTabIndex(tab: TabPanel) { + let index = -1; + for(let i = 0; i < this.tabs.length; i++) { + if(this.tabs[i] == tab) { + index = i; + break; + } + } + return index; + } + + getBlockableElement(): HTMLElement { + return this.el.nativeElement.children[0]; + } + + @Input() get activeIndex(): number { + return this._activeIndex; + } + + set activeIndex(val:number) { + this._activeIndex = val; + + if(this.tabs && this.tabs.length && this._activeIndex != null) { + this.findSelectedTab().selected = false; + this.tabs[this._activeIndex].selected = true; + } + } +} + + +@NgModule({ + imports: [CommonModule], + exports: [TabView,TabPanel,TabViewNav], + declarations: [TabView,TabPanel,TabViewNav] +}) +export class TabViewModule { } \ No newline at end of file diff --git a/src/app/components/terminal/terminal.css b/src/app/components/terminal/terminal.css new file mode 100644 index 00000000000..86fe6028e06 --- /dev/null +++ b/src/app/components/terminal/terminal.css @@ -0,0 +1,25 @@ +.ui-terminal { + height: 18em; + overflow: auto; + padding: .25em; +} + +.ui-terminal-input { + border: 0 none; + background-color: transparent; + color: inherit; + padding: 0; + margin: 0 0 0 .125em; + width: 75%; + outline: none; + vertical-align: baseline; +} + +.ui-terminal-command { + margin-left: .125em; + -moz-margin-start: .125em; +} + +.ui-terminal-input::-ms-clear { + display: none; +} \ No newline at end of file diff --git a/src/app/components/terminal/terminal.ts b/src/app/components/terminal/terminal.ts new file mode 100644 index 00000000000..4c2dacea5bd --- /dev/null +++ b/src/app/components/terminal/terminal.ts @@ -0,0 +1,88 @@ +import {NgModule,Component,AfterViewInit,AfterViewChecked,Input,Output,EventEmitter,ElementRef} from '@angular/core'; +import {FormsModule} from '@angular/forms'; +import {CommonModule} from '@angular/common'; +import {DomHandler} from '../dom/domhandler'; + +@Component({ + selector: 'p-terminal', + template: ` +
        +
        {{welcomeMessage}}
        +
        +
        + {{prompt}} + {{command.text}} +
        {{command.response}}
        +
        +
        +
        + {{prompt}} + +
        +
        + `, + providers: [DomHandler] +}) +export class Terminal implements AfterViewInit,AfterViewChecked { + + @Input() welcomeMessage: string; + + @Input() prompt: string; + + @Input() style: any; + + @Input() styleClass: string; + + @Output() responseChange: EventEmitter = new EventEmitter(); + + @Output() handler: EventEmitter = new EventEmitter(); + + commands: any[] = []; + + command: string; + + container: Element; + + commandProcessed: boolean; + + constructor(public el: ElementRef, public domHandler: DomHandler) {} + + ngAfterViewInit() { + this.container = this.domHandler.find(this.el.nativeElement, '.ui-terminal')[0]; + } + + ngAfterViewChecked() { + if(this.commandProcessed) { + this.container.scrollTop = this.container.scrollHeight; + this.commandProcessed = false; + } + } + + @Input() + set response(value: string) { + if(value) { + this.commands[this.commands.length - 1].response = value; + this.commandProcessed = true; + } + } + + handleCommand(event: KeyboardEvent) { + if(event.keyCode == 13) { + this.commands.push({text: this.command}); + this.handler.emit({originalEvent: event, command: this.command}); + this.command = ''; + } + } + + focus(element: HTMLElement) { + element.focus(); + } + +} + +@NgModule({ + imports: [CommonModule,FormsModule], + exports: [Terminal], + declarations: [Terminal] +}) +export class TerminalModule { } \ No newline at end of file diff --git a/src/app/components/tieredmenu/tieredmenu.ts b/src/app/components/tieredmenu/tieredmenu.ts new file mode 100644 index 00000000000..f3125671498 --- /dev/null +++ b/src/app/components/tieredmenu/tieredmenu.ts @@ -0,0 +1,182 @@ +import {NgModule,Component,ElementRef,AfterViewInit,OnDestroy,Input,Output,Renderer2,EventEmitter} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {DomHandler} from '../dom/domhandler'; +import {MenuItem} from '../common/menuitem'; +import {RouterModule} from '@angular/router'; + +@Component({ + selector: 'p-tieredMenuSub', + template: ` + + `, + providers: [DomHandler] +}) +export class TieredMenuSub { + + @Input() item: MenuItem; + + @Input() root: boolean; + + constructor(public domHandler: DomHandler) {} + + activeItem: HTMLLIElement; + + onItemMouseEnter(event: Event, item: HTMLLIElement, menuitem: MenuItem) { + if(menuitem.disabled) { + return; + } + + this.activeItem = item; + let nextElement: HTMLElement = item.children[0].nextElementSibling; + if(nextElement) { + let sublist: HTMLElement = nextElement.children[0]; + sublist.style.zIndex = String(++DomHandler.zindex); + + sublist.style.top = '0px'; + sublist.style.left = this.domHandler.getOuterWidth(item.children[0]) + 'px'; + } + } + + onItemMouseLeave(event: Event) { + this.activeItem = null; + } + + itemClick(event: Event, item: MenuItem) { + if(item.disabled) { + event.preventDefault(); + return true; + } + + if(!item.url) { + event.preventDefault(); + } + + if(item.command) { + if(!item.eventEmitter) { + item.eventEmitter = new EventEmitter(); + item.eventEmitter.subscribe(item.command); + } + + item.eventEmitter.emit({ + originalEvent: event, + item: item + }); + } + } + + listClick(event: Event) { + this.activeItem = null; + } +} + +@Component({ + selector: 'p-tieredMenu', + template: ` +
        + +
        + `, + providers: [DomHandler] +}) +export class TieredMenu implements AfterViewInit,OnDestroy { + + @Input() model: MenuItem[]; + + @Input() popup: boolean; + + @Input() style: any; + + @Input() styleClass: string; + + container: any; + + documentClickListener: any; + + preventDocumentDefault: any; + + constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2) {} + + ngAfterViewInit() { + this.container = this.el.nativeElement.children[0]; + + if(this.popup) { + this.documentClickListener = this.renderer.listen('document', 'click', () => { + if(!this.preventDocumentDefault) { + this.hide(); + } + this.preventDocumentDefault = false; + }); + } + } + + toggle(event: Event) { + if(this.container.offsetParent) + this.hide(); + else + this.show(event); + } + + show(event: Event) { + this.preventDocumentDefault = true; + this.container.style.display = 'block'; + this.domHandler.absolutePosition(this.container, event.target); + this.domHandler.fadeIn(this.container, 250); + } + + hide() { + this.container.style.display = 'none'; + } + + unsubscribe(item: any) { + if(item.eventEmitter) { + item.eventEmitter.unsubscribe(); + } + + if(item.items) { + for(let childItem of item.items) { + this.unsubscribe(childItem); + } + } + } + + ngOnDestroy() { + if(this.popup && this.documentClickListener) { + this.documentClickListener(); + } + + if(this.model) { + for(let item of this.model) { + this.unsubscribe(item); + } + } + } + +} + +@NgModule({ + imports: [CommonModule,RouterModule], + exports: [TieredMenu,RouterModule], + declarations: [TieredMenu,TieredMenuSub] +}) +export class TieredMenuModule { } diff --git a/src/app/components/togglebutton/togglebutton.ts b/src/app/components/togglebutton/togglebutton.ts new file mode 100644 index 00000000000..0909cf7d19e --- /dev/null +++ b/src/app/components/togglebutton/togglebutton.ts @@ -0,0 +1,122 @@ +import {NgModule,Component,Input,Output,EventEmitter,forwardRef,AfterViewInit,ViewChild,ElementRef} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; + +export const TOGGLEBUTTON_VALUE_ACCESSOR: any = { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ToggleButton), + multi: true +}; + +@Component({ + selector: 'p-toggleButton', + template: ` +
        +
        + +
        + + {{checked ? hasOnLabel ? onLabel : 'ui-btn' : hasOffLabel ? offLabel : 'ui-btn'}} +
        + `, + providers: [TOGGLEBUTTON_VALUE_ACCESSOR] +}) +export class ToggleButton implements ControlValueAccessor,AfterViewInit { + + @Input() onLabel: string = 'Yes'; + + @Input() offLabel: string = 'No'; + + @Input() onIcon: string; + + @Input() offIcon: string; + + @Input() disabled: boolean; + + @Input() style: any; + + @Input() styleClass: string; + + @Input() inputId: string; + + @Input() tabindex: number; + + @Output() onChange: EventEmitter = new EventEmitter(); + + @ViewChild('checkbox') checkboxViewChild: ElementRef; + + checkbox: HTMLInputElement; + + checked: boolean = false; + + focus: boolean = false; + + onModelChange: Function = () => {}; + + onModelTouched: Function = () => {}; + + ngAfterViewInit() { + this.checkbox = this.checkboxViewChild.nativeElement; + } + + getIconClass() { + let baseClass = 'ui-button-icon-left fa fa-fw'; + return baseClass + ' ' + (this.checked ? this.onIcon : this.offIcon); + } + + toggle(event: Event) { + if(!this.disabled) { + this.checked = !this.checked; + this.onModelChange(this.checked); + this.onModelTouched(); + this.onChange.emit({ + originalEvent: event, + checked: this.checked + }); + this.checkbox.focus(); + } + } + + onFocus() { + this.focus = true; + } + + onBlur() { + this.focus = false; + this.onModelTouched(); + } + + writeValue(value: any) : void { + this.checked = value; + } + + registerOnChange(fn: Function): void { + this.onModelChange = fn; + } + + registerOnTouched(fn: Function): void { + this.onModelTouched = fn; + } + + setDisabledState(val: boolean): void { + this.disabled = val; + } + + get hasOnLabel():boolean { + return this.onLabel && this.onLabel.length > 0; + } + + get hasOffLabel():boolean { + return this.onLabel && this.onLabel.length > 0; + } +} + +@NgModule({ + imports: [CommonModule], + exports: [ToggleButton], + declarations: [ToggleButton] +}) +export class ToggleButtonModule { } diff --git a/src/app/components/toolbar/toolbar.css b/src/app/components/toolbar/toolbar.css new file mode 100644 index 00000000000..0c48db8f5f8 --- /dev/null +++ b/src/app/components/toolbar/toolbar.css @@ -0,0 +1,11 @@ +.ui-toolbar { + padding: .25em .5em; +} + +.ui-toolbar-group-left { + float:left +} + +.ui-toolbar-group-right { + float:right +} \ No newline at end of file diff --git a/src/app/components/toolbar/toolbar.ts b/src/app/components/toolbar/toolbar.ts new file mode 100644 index 00000000000..881896855bc --- /dev/null +++ b/src/app/components/toolbar/toolbar.ts @@ -0,0 +1,25 @@ +import {NgModule,Component,Input,Output,EventEmitter} from '@angular/core'; +import {CommonModule} from '@angular/common'; + +@Component({ + selector: 'p-toolbar', + template: ` +
        + +
        + ` +}) +export class Toolbar { + + @Input() style: any; + + @Input() styleClass: string; + +} + +@NgModule({ + imports: [CommonModule], + exports: [Toolbar], + declarations: [Toolbar] +}) +export class ToolbarModule { } \ No newline at end of file diff --git a/src/app/components/tooltip/tooltip.css b/src/app/components/tooltip/tooltip.css new file mode 100644 index 00000000000..e726b45048d --- /dev/null +++ b/src/app/components/tooltip/tooltip.css @@ -0,0 +1,66 @@ +.ui-tooltip { + position:absolute; + display:none; + padding: .25em .5em; +} + +.ui-tooltip.ui-tooltip-right, +.ui-tooltip.ui-tooltip-left { + padding: 0 .25em; +} + +.ui-tooltip.ui-tooltip-top, +.ui-tooltip.ui-tooltip-bottom { + padding:.25em 0; +} + +.ui-tooltip .ui-tooltip-text { + padding: .125em .5em; + background-color: rgb(76, 76, 76); + color: #ffffff; + white-space: nowrap; +} + +.ui-tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} + +.ui-tooltip-right .ui-tooltip-arrow { + top: 50%; + left: 0; + margin-top: -.25em; + border-width: .25em .25em .25em 0; + border-right-color: rgb(76, 76, 76); +} + +.ui-tooltip-left .ui-tooltip-arrow { + top: 50%; + right: 0; + margin-top: -.25em; + border-width: .25em 0 .25em .25em; + border-left-color: rgb(76, 76, 76); +} + +.ui-tooltip.ui-tooltip-top { + padding: .25em 0; +} + +.ui-tooltip-top .ui-tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -.25em; + border-width: .25em .25em 0; + border-top-color: rgb(76, 76, 76); +} + +.ui-tooltip-bottom .ui-tooltip-arrow { + top: 0; + left: 50%; + margin-left: -.25em; + border-width: 0 .25em .25em; + border-bottom-color: rgb(76, 76, 76); +} \ No newline at end of file diff --git a/src/app/components/tooltip/tooltip.ts b/src/app/components/tooltip/tooltip.ts new file mode 100644 index 00000000000..da2035d7aef --- /dev/null +++ b/src/app/components/tooltip/tooltip.ts @@ -0,0 +1,160 @@ +import {NgModule,Directive,ElementRef,OnDestroy,HostBinding,HostListener,Input} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {DomHandler} from '../dom/domhandler'; + +@Directive({ + selector: '[pTooltip]', + host: { + }, + providers: [DomHandler] +}) +export class Tooltip implements OnDestroy { + + @Input('pTooltip') text: string; + + @Input() tooltipPosition: string = 'right'; + + @Input() tooltipEvent: string = 'hover'; + + @Input() appendTo: any = 'body'; + + @Input() positionStyle: string; + + @Input() tooltipStyleClass: string; + + @Input("tooltipDisabled") disabled: boolean; + + @Input() escape: boolean = true; + + container: any; + + constructor(public el: ElementRef, public domHandler: DomHandler) {} + + @HostListener('mouseenter', ['$event']) + onMouseEnter(e: Event) { + if(this.tooltipEvent === 'hover') { + this.show(); + } + } + + @HostListener('mouseleave', ['$event']) + onMouseLeave(e: Event) { + if(this.tooltipEvent === 'hover') { + this.hide(); + } + } + + @HostListener('focus', ['$event']) + onFocus(e: Event) { + if(this.tooltipEvent === 'focus') { + this.show(); + } + } + + @HostListener('blur', ['$event']) + onBlur(e: Event) { + if(this.tooltipEvent === 'focus') { + this.hide(); + } + } + + show() { + if(!this.text || this.disabled) { + return; + } + + this.create(); + let offset = this.el.nativeElement.getBoundingClientRect(); + let targetTop = offset.top + this.domHandler.getWindowScrollTop(); + let targetLeft = offset.left + this.domHandler.getWindowScrollLeft(); + let left: number; + let top: number; + + this.container.style.display = 'block'; + + switch(this.tooltipPosition) { + case 'right': + left = targetLeft + this.domHandler.getOuterWidth(this.el.nativeElement); + top = targetTop + (this.domHandler.getOuterHeight(this.el.nativeElement) - this.domHandler.getOuterHeight(this.container)) / 2; + break; + + case 'left': + left = targetLeft - this.domHandler.getOuterWidth(this.container); + top = targetTop + (this.domHandler.getOuterHeight(this.el.nativeElement) - this.domHandler.getOuterHeight(this.container)) / 2; + break; + + case 'top': + left = targetLeft + (this.domHandler.getOuterWidth(this.el.nativeElement) - this.domHandler.getOuterWidth(this.container)) / 2; + top = targetTop - this.domHandler.getOuterHeight(this.container); + break; + + case 'bottom': + left = targetLeft + (this.domHandler.getOuterWidth(this.el.nativeElement) - this.domHandler.getOuterWidth(this.container)) / 2; + top = targetTop + this.domHandler.getOuterHeight(this.el.nativeElement); + break; + } + + this.container.style.left = left + 'px'; + this.container.style.top = top + 'px'; + this.domHandler.fadeIn(this.container, 250); + this.container.style.zIndex = ++DomHandler.zindex; + } + + hide() { + this.ngOnDestroy(); + } + + create() { + let styleClass = 'ui-widget ui-tooltip ui-tooltip-' + this.tooltipPosition; + this.container = document.createElement('div'); + if(this.tooltipStyleClass) { + styleClass += ' ' + this.tooltipStyleClass; + } + + this.container.className = styleClass; + + let tooltipArrow = document.createElement('div'); + tooltipArrow.className = 'ui-tooltip-arrow'; + this.container.appendChild(tooltipArrow); + + let tooltipText = document.createElement('div'); + tooltipText.className = 'ui-tooltip-text ui-shadow ui-corner-all'; + + if(this.escape) + tooltipText.appendChild(document.createTextNode(this.text)); + else + tooltipText.innerHTML = this.text; + + if(this.positionStyle) { + this.container.style.position = this.positionStyle; + } + + this.container.appendChild(tooltipText); + + if(this.appendTo === 'body') + document.body.appendChild(this.container); + else if(this.appendTo === 'target') + this.domHandler.appendChild(this.container, this.el.nativeElement); + else + this.domHandler.appendChild(this.container, this.appendTo); + } + + ngOnDestroy() { + if(this.container && this.container.parentElement) { + if(this.appendTo === 'body') + document.body.removeChild(this.container); + else if(this.appendTo === 'target') + this.el.nativeElement.removeChild(this.container); + else + this.domHandler.removeChild(this.container, this.appendTo); + } + this.container = null; + } +} + +@NgModule({ + imports: [CommonModule], + exports: [Tooltip], + declarations: [Tooltip] +}) +export class TooltipModule { } \ No newline at end of file diff --git a/src/app/components/tree/images/line.gif b/src/app/components/tree/images/line.gif new file mode 100755 index 00000000000..64e2280ec55 Binary files /dev/null and b/src/app/components/tree/images/line.gif differ diff --git a/src/app/components/tree/tree.css b/src/app/components/tree/tree.css new file mode 100644 index 00000000000..27617575fc5 --- /dev/null +++ b/src/app/components/tree/tree.css @@ -0,0 +1,158 @@ +.ui-tree { + width: 18em; +} + +.ui-tree .ui-treenode-selectable.ui-treenode-content { + cursor: pointer; +} + +.ui-tree .ui-tree-container { + height: 100%; + margin: 0; + overflow: auto; + padding: .25em; + white-space: nowrap; +} + +.ui-tree .ui-treenode-children { + margin: 0; + padding: 0 0 0 1em; +} + +.ui-tree .ui-treenode { + background-attachment: scroll; + background-color: transparent; + background-image: none; + background-position: 0 0; + background-repeat: repeat-y; + list-style: none outside none; + margin: 0; + padding: .125em 0 0 0; +} + +.ui-tree .ui-treenode-droppoint { + height: 4px; + list-style-type: none; +} + +.ui-tree .ui-treenode-droppoint-active { + border: 0 none; +} + +.ui-tree .ui-tree-toggler { + cursor: pointer; + display: inline-block; + vertical-align: middle; +} + +.ui-tree .ui-treenode-icon { + display: inline-block; + vertical-align: middle; +} + +.ui-tree .ui-treenode-label { + display: inline-block; + padding: 0 .25em; + vertical-align: middle; +} + +.ui-tree .ui-treenode-label.ui-state-hover, +.ui-tree .ui-treenode-label.ui-state-highlight { + font-weight: normal; + border: 0 none; +} + +.ui-tree .ui-treenode.ui-treenode-leaf > .ui-treenode-content > .ui-tree-toggler { + visibility: hidden; +} + +.ui-tree .ui-chkbox-box { + cursor: pointer; +} + +.ui-tree .ui-chkbox { + display: inline-block; + vertical-align: middle; +} + +.ui-tree .ui-chkbox .ui-chkbox-icon { + margin-left: 1px; +} + +/** Fluid **/ +.ui-fluid .ui-tree { + width: 100%; +} + +/** Horizontal Tree **/ +.ui-tree-horizontal { + width:auto; + padding: .5em 0; + overflow:auto; +} + +.ui-tree.ui-tree-horizontal table, +.ui-tree.ui-tree-horizontal tr, +.ui-tree.ui-tree-horizontal td { + border-collapse: collapse; + margin: 0; + padding: 0; + vertical-align: middle; +} + +.ui-tree.ui-tree-horizontal .ui-tree-toggler { + vertical-align: middle; + margin: 0; +} + +.ui-tree-horizontal .ui-treenode-content { + font-weight: normal; + padding: 0.4em 1em 0.4em 0.2em; +} + +.ui-tree.ui-tree-horizontal .ui-tree-node-label { + margin: 0; +} + +.ui-tree-horizontal .ui-treenode-parent .ui-treenode-content { + font-weight: normal; + white-space: nowrap; +} + +.ui-tree.ui-tree-horizontal .ui-treenode { + background: url("./images/line.gif") repeat-x scroll center center transparent; + padding: .25em 2.5em; +} + +.ui-tree.ui-tree-horizontal .ui-treenode.ui-treenode-leaf, +.ui-tree.ui-tree-horizontal .ui-treenode.ui-treenode-collapsed { + padding-right: 0; +} + +.ui-tree.ui-tree-horizontal .ui-treenode-children { + padding: 0; + margin: 0; +} + +.ui-tree.ui-tree-horizontal .ui-treenode-connector { + width: 1px; +} + +.ui-tree.ui-tree-horizontal .ui-treenode-connector-table { + height: 100%; + width: 1px; +} + +.ui-tree.ui-tree-horizontal .ui-treenode-connector-line { + background: url("./images/line.gif") repeat-y scroll 0 0 transparent; + width: 1px; +} + +.ui-tree.ui-tree-horizontal table { + height: 0; +} + +.ui-tree.ui-tree-horizontal .ui-chkbox { + vertical-align: bottom; + margin-right: .25em; +} diff --git a/src/app/components/tree/tree.ts b/src/app/components/tree/tree.ts new file mode 100644 index 00000000000..109e8a08181 --- /dev/null +++ b/src/app/components/tree/tree.ts @@ -0,0 +1,770 @@ +import {NgModule,Component,Input,AfterContentInit,OnDestroy,Output,EventEmitter,OnInit,EmbeddedViewRef,ViewContainerRef, + ContentChildren,QueryList,TemplateRef,Inject,forwardRef,Host} from '@angular/core'; +import {Optional} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {TreeNode} from '../common/treenode'; +import {SharedModule} from '../common/shared'; +import {PrimeTemplate} from '../common/shared'; +import {TreeDragDropService} from '../common/treedragdropservice'; +import {Subscription} from 'rxjs/Subscription'; + +@Component({ + selector: 'p-treeNodeTemplateLoader', + template: `` +}) +export class TreeNodeTemplateLoader implements OnInit, OnDestroy { + + @Input() node: any; + + @Input() template: TemplateRef; + + view: EmbeddedViewRef; + + constructor(public viewContainer: ViewContainerRef) {} + + ngOnInit() { + this.view = this.viewContainer.createEmbeddedView(this.template, { + '\$implicit': this.node + }); + } + + ngOnDestroy() { + this.view.destroy(); + } +} + +@Component({ + selector: 'p-treeNode', + template: ` + +
      • +
      • +
        +
        +
        + {{node.label}} + + + + +
        + +
      • +
      • + + + + + + + + +
        + + + + + + + + + +
        +
        +
        + + {{node.label}} + + + + +
        +
        +
        + +
        +
        +
        + ` +}) +export class UITreeNode implements OnInit { + + static ICON_CLASS: string = 'ui-treenode-icon fa fa-fw'; + + @Input() node: TreeNode; + + @Input() parentNode: TreeNode; + + @Input() root: boolean; + + @Input() index: number; + + @Input() firstChild: boolean; + + @Input() lastChild: boolean; + + constructor(@Inject(forwardRef(() => Tree)) public tree:Tree) {} + + draghoverPrev: boolean; + + draghoverNext: boolean; + + draghoverNode: boolean + + ngOnInit() { + this.node.parent = this.parentNode; + } + + getIcon() { + let icon: string; + + if(this.node.icon) + icon = this.node.icon; + else + icon = this.node.expanded && this.node.children && this.node.children.length ? this.node.expandedIcon : this.node.collapsedIcon; + + return UITreeNode.ICON_CLASS + ' ' + icon; + } + + isLeaf() { + return this.node.leaf == false ? false : !(this.node.children&&this.node.children.length); + } + + toggle(event: Event) { + if(this.node.expanded) + this.tree.onNodeCollapse.emit({originalEvent: event, node: this.node}); + else + this.tree.onNodeExpand.emit({originalEvent: event, node: this.node}); + + this.node.expanded = !this.node.expanded + } + + onNodeClick(event: MouseEvent) { + this.tree.onNodeClick(event, this.node); + } + + onNodeTouchEnd() { + this.tree.onNodeTouchEnd(); + } + + onNodeRightClick(event: MouseEvent) { + this.tree.onNodeRightClick(event, this.node); + } + + isSelected() { + return this.tree.isSelected(this.node); + } + + onDropPoint(event: Event, position: number) { + event.preventDefault(); + let dragNode = this.tree.dragNode; + let dragNodeIndex = this.tree.dragNodeIndex; + let dragNodeScope = this.tree.dragNodeScope; + let isValidDropPointIndex = this.tree.dragNodeTree === this.tree ? (position === 1 || dragNodeIndex !== this.index - 1) : true; + + if(this.tree.allowDrop(dragNode, this.node, dragNodeScope) && isValidDropPointIndex) { + let newNodeList = this.node.parent ? this.node.parent.children : this.tree.value; + this.tree.dragNodeSubNodes.splice(dragNodeIndex, 1); + if(position < 0) + newNodeList.splice(this.index, 0, dragNode); + else + newNodeList.push(dragNode); + + this.tree.dragDropService.stopDrag({ + node: dragNode, + subNodes: this.node.parent ? this.node.parent.children : this.tree.value, + index: dragNodeIndex + }); + + this.tree.onNodeDrop.emit({ + originalEvent: event, + dragNode: dragNode + }); + } + + this.draghoverPrev = false; + this.draghoverNext = false; + } + + onDropPointDragOver(event) { + event.dataTransfer.dropEffect = 'move'; + event.preventDefault(); + } + + onDropPointDragEnter(event: Event, position: number) { + if(this.tree.allowDrop(this.tree.dragNode, this.node, this.tree.dragNodeScope)) { + if(position < 0) + this.draghoverPrev = true; + else + this.draghoverNext = true; + } + } + + onDropPointDragLeave(event: Event) { + this.draghoverPrev = false; + this.draghoverNext = false; + } + + onDragStart(event) { + if(this.tree.draggableNodes && this.node.draggable !== false) { + event.dataTransfer.setData("text", "data"); + + this.tree.dragDropService.startDrag({ + tree: this, + node: this.node, + subNodes: this.node.parent ? this.node.parent.children : this.tree.value, + index: this.index, + scope: this.tree.draggableScope + }); + } + else { + event.preventDefault(); + } + } + + onDragStop(event) { + this.tree.dragDropService.stopDrag({ + node: this.node, + subNodes: this.node.parent ? this.node.parent.children : this.tree.value, + index: this.index + }); + } + + onDropNodeDragOver(event) { + event.dataTransfer.dropEffect = 'move'; + if(this.tree.droppableNodes) { + event.preventDefault(); + event.stopPropagation(); + } + } + + onDropNode(event) { + if(this.tree.droppableNodes && this.node.droppable !== false) { + event.preventDefault(); + event.stopPropagation(); + let dragNode = this.tree.dragNode; + if(this.tree.allowDrop(dragNode, this.node, this.tree.dragNodeScope)) { + let dragNodeIndex = this.tree.dragNodeIndex; + this.tree.dragNodeSubNodes.splice(dragNodeIndex, 1); + + if(this.node.children) + this.node.children.push(dragNode); + else + this.node.children = [dragNode]; + + this.tree.dragDropService.stopDrag({ + node: dragNode, + subNodes: this.node.parent ? this.node.parent.children : this.tree.value, + index: this.tree.dragNodeIndex + }); + + this.tree.onNodeDrop.emit({ + originalEvent: event, + dragNode: dragNode, + dropNode: this.node + }); + } + } + + this.draghoverNode = false; + } + + onDropNodeDragEnter(event) { + if(this.tree.droppableNodes && this.node.droppable !== false && this.tree.allowDrop(this.tree.dragNode, this.node, this.tree.dragNodeScope)) { + this.draghoverNode = true; + } + } + + onDropNodeDragLeave(event) { + if(this.tree.droppableNodes) { + let rect = event.currentTarget.getBoundingClientRect(); + if(event.x > rect.left + rect.width || event.x < rect.left || event.y >= Math.floor(rect.top + rect.height) || event.y < rect.top) { + this.draghoverNode = false; + } + } + } +} + +@Component({ + selector: 'p-tree', + template: ` +
        +
          + +
        +
        +
        + + +
        +
        + ` +}) +export class Tree implements OnInit,AfterContentInit,OnDestroy { + + @Input() value: TreeNode[]; + + @Input() selectionMode: string; + + @Input() selection: any; + + @Output() selectionChange: EventEmitter = new EventEmitter(); + + @Output() onNodeSelect: EventEmitter = new EventEmitter(); + + @Output() onNodeUnselect: EventEmitter = new EventEmitter(); + + @Output() onNodeExpand: EventEmitter = new EventEmitter(); + + @Output() onNodeCollapse: EventEmitter = new EventEmitter(); + + @Output() onNodeContextMenuSelect: EventEmitter = new EventEmitter(); + + @Output() onNodeDrop: EventEmitter = new EventEmitter(); + + @Input() style: any; + + @Input() styleClass: string; + + @Input() contextMenu: any; + + @Input() layout: string = 'vertical'; + + @Input() draggableScope: any; + + @Input() droppableScope: any; + + @Input() draggableNodes: boolean; + + @Input() droppableNodes: boolean; + + @Input() metaKeySelection: boolean = true; + + @Input() propagateSelectionUp: boolean = true; + + @Input() propagateSelectionDown: boolean = true; + + @ContentChildren(PrimeTemplate) templates: QueryList; + + public templateMap: any; + + public nodeTouched: boolean; + + public dragNodeTree: Tree; + + public dragNode: TreeNode; + + public dragNodeSubNodes: TreeNode[]; + + public dragNodeIndex: number; + + public dragNodeScope: any; + + public dragHover: boolean; + + public dragStartSubscription: Subscription; + + public dragStopSubscription: Subscription; + + constructor(@Optional() public dragDropService: TreeDragDropService) {} + + ngOnInit() { + if(this.droppableNodes) { + this.dragStartSubscription = this.dragDropService.dragStart$.subscribe( + event => { + this.dragNodeTree = event.tree; + this.dragNode = event.node; + this.dragNodeSubNodes = event.subNodes; + this.dragNodeIndex = event.index; + this.dragNodeScope = event.scope; + }); + + this.dragStopSubscription = this.dragDropService.dragStop$.subscribe( + event => { + this.dragNodeTree = null; + this.dragNode = null; + this.dragNodeSubNodes = null; + this.dragNodeIndex = null; + this.dragNodeScope = null; + this.dragHover = false; + }); + } + } + + get horizontal(): boolean { + return this.layout == 'horizontal'; + } + + ngAfterContentInit() { + if(this.templates.length) { + this.templateMap = {}; + } + + this.templates.forEach((item) => { + this.templateMap[item.getType()] = item.template; + }); + } + + onNodeClick(event: MouseEvent, node: TreeNode) { + let eventTarget = ( event.target); + + if(eventTarget.className && eventTarget.className.indexOf('ui-tree-toggler') === 0) { + return; + } + else if(this.selectionMode) { + if(node.selectable === false) { + return; + } + + let index = this.findIndexInSelection(node); + let selected = (index >= 0); + + if(this.isCheckboxSelectionMode()) { + if(selected) { + if(this.propagateSelectionDown) + this.propagateDown(node, false); + else + this.selection = this.selection.filter((val,i) => i!=index); + + if(this.propagateSelectionUp && node.parent) { + this.propagateUp(node.parent, false); + } + + this.selectionChange.emit(this.selection); + this.onNodeUnselect.emit({originalEvent: event, node: node}); + } + else { + if(this.propagateSelectionDown) + this.propagateDown(node, true); + else + this.selection = [...this.selection||[],node]; + + if(this.propagateSelectionUp && node.parent) { + this.propagateUp(node.parent, true); + } + + this.selectionChange.emit(this.selection); + this.onNodeSelect.emit({originalEvent: event, node: node}); + } + } + else { + let metaSelection = this.nodeTouched ? false : this.metaKeySelection; + + if(metaSelection) { + let metaKey = (event.metaKey||event.ctrlKey); + + if(selected && metaKey) { + if(this.isSingleSelectionMode()) { + this.selectionChange.emit(null); + } + else { + this.selection = this.selection.filter((val,i) => i!=index); + this.selectionChange.emit(this.selection); + } + + this.onNodeUnselect.emit({originalEvent: event, node: node}); + } + else { + if(this.isSingleSelectionMode()) { + this.selectionChange.emit(node); + } + else if(this.isMultipleSelectionMode()) { + this.selection = (!metaKey) ? [] : this.selection||[]; + this.selection = [...this.selection,node]; + this.selectionChange.emit(this.selection); + } + + this.onNodeSelect.emit({originalEvent: event, node: node}); + } + } + else { + if(this.isSingleSelectionMode()) { + if(selected) { + this.selection = null; + this.onNodeUnselect.emit({originalEvent: event, node: node}); + } + else { + this.selection = node; + this.onNodeSelect.emit({originalEvent: event, node: node}); + } + } + else { + if(selected) { + this.selection = this.selection.filter((val,i) => i!=index); + this.onNodeUnselect.emit({originalEvent: event, node: node}); + } + else { + this.selection = [...this.selection||[],node]; + this.onNodeSelect.emit({originalEvent: event, node: node}); + } + } + + this.selectionChange.emit(this.selection); + } + } + } + + this.nodeTouched = false; + } + + onNodeTouchEnd() { + this.nodeTouched = true; + } + + onNodeRightClick(event: MouseEvent, node: TreeNode) { + if(this.contextMenu) { + let eventTarget = ( event.target); + + if(eventTarget.className && eventTarget.className.indexOf('ui-tree-toggler') === 0) { + return; + } + else { + let index = this.findIndexInSelection(node); + let selected = (index >= 0); + + if(!selected) { + if(this.isSingleSelectionMode()) + this.selectionChange.emit(node); + else + this.selectionChange.emit([node]); + } + + this.contextMenu.show(event); + this.onNodeContextMenuSelect.emit({originalEvent: event, node: node}); + } + } + } + + findIndexInSelection(node: TreeNode) { + let index: number = -1; + + if(this.selectionMode && this.selection) { + if(this.isSingleSelectionMode()) { + index = (this.selection == node) ? 0 : - 1; + } + else { + for(let i = 0; i < this.selection.length; i++) { + if(this.selection[i] == node) { + index = i; + break; + } + } + } + } + + return index; + } + + propagateUp(node: TreeNode, select: boolean) { + if(node.children && node.children.length) { + let selectedCount: number = 0; + let childPartialSelected: boolean = false; + for(let child of node.children) { + if(this.isSelected(child)) { + selectedCount++; + } + else if(child.partialSelected) { + childPartialSelected = true; + } + } + + if(select && selectedCount == node.children.length) { + this.selection = [...this.selection||[],node]; + node.partialSelected = false; + } + else { + if(!select) { + let index = this.findIndexInSelection(node); + if(index >= 0) { + this.selection = this.selection.filter((val,i) => i!=index); + } + } + + if(childPartialSelected || selectedCount > 0 && selectedCount != node.children.length) + node.partialSelected = true; + else + node.partialSelected = false; + } + } + + let parent = node.parent; + if(parent) { + this.propagateUp(parent, select); + } + } + + propagateDown(node: TreeNode, select: boolean) { + let index = this.findIndexInSelection(node); + + if(select && index == -1) { + this.selection = [...this.selection||[],node]; + } + else if(!select && index > -1) { + this.selection = this.selection.filter((val,i) => i!=index); + } + + node.partialSelected = false; + + if(node.children && node.children.length) { + for(let child of node.children) { + this.propagateDown(child, select); + } + } + } + + isSelected(node: TreeNode) { + return this.findIndexInSelection(node) != -1; + } + + isSingleSelectionMode() { + return this.selectionMode && this.selectionMode == 'single'; + } + + isMultipleSelectionMode() { + return this.selectionMode && this.selectionMode == 'multiple'; + } + + isCheckboxSelectionMode() { + return this.selectionMode && this.selectionMode == 'checkbox'; + } + + getTemplateForNode(node: TreeNode): TemplateRef { + if(this.templateMap) + return node.type ? this.templateMap[node.type] : this.templateMap['default']; + else + return null; + } + + onDragOver(event) { + if(this.droppableNodes && (!this.value || this.value.length === 0)) { + event.dataTransfer.dropEffect = 'move'; + event.preventDefault(); + } + } + + onDrop(event) { + if(this.droppableNodes && (!this.value || this.value.length === 0)) { + event.preventDefault(); + let dragNode = this.dragNode; + if(this.allowDrop(dragNode, null, this.dragNodeScope)) { + let dragNodeIndex = this.dragNodeIndex; + this.dragNodeSubNodes.splice(dragNodeIndex, 1); + this.value = this.value||[]; + this.value.push(dragNode); + + this.dragDropService.stopDrag({ + node: dragNode + }); + } + } + } + + onDragEnter(event) { + if(this.droppableNodes && this.allowDrop(this.dragNode, null, this.dragNodeScope)) { + this.dragHover = true; + } + } + + onDragLeave(event) { + if(this.droppableNodes) { + let rect = event.currentTarget.getBoundingClientRect(); + if(event.x > rect.left + rect.width || event.x < rect.left || event.y > rect.top + rect.height || event.y < rect.top) { + this.dragHover = false; + } + } + } + + allowDrop(dragNode: TreeNode, dropNode: TreeNode, dragNodeScope: any): boolean { + if(this.isValidDragScope(dragNodeScope)) { + let allow: boolean = true; + if(dropNode) { + if(dragNode === dropNode) { + allow = false; + } + else { + let parent = dropNode.parent; + while(parent != null) { + if(parent === dragNode) { + allow = false; + break; + } + parent = parent.parent; + } + } + } + + return allow; + } + else { + return false; + } + } + + isValidDragScope(dragScope: any): boolean { + let dropScope = this.droppableScope; + + if(dropScope) { + if(typeof dropScope === 'string') { + if(typeof dragScope === 'string') + return dropScope === dragScope; + else if(dragScope instanceof Array) + return (>dragScope).indexOf(dropScope) != -1; + } + else if(dropScope instanceof Array) { + if(typeof dragScope === 'string') { + return (>dropScope).indexOf(dragScope) != -1; + } + else if(dragScope instanceof Array) { + for(let s of dropScope) { + for(let ds of dragScope) { + if(s === ds) { + return true; + } + } + } + } + } + return false; + } + else { + return true; + } + } + + ngOnDestroy() { + if(this.dragStartSubscription) { + this.dragStartSubscription.unsubscribe(); + } + + if(this.dragStopSubscription) { + this.dragStopSubscription.unsubscribe(); + } + } +} +@NgModule({ + imports: [CommonModule], + exports: [Tree,SharedModule], + declarations: [Tree,UITreeNode,TreeNodeTemplateLoader] +}) +export class TreeModule { } diff --git a/src/app/components/treetable/treetable.css b/src/app/components/treetable/treetable.css new file mode 100644 index 00000000000..bfdf1fcdcd1 --- /dev/null +++ b/src/app/components/treetable/treetable.css @@ -0,0 +1,93 @@ +.ui-treetable table { + border-collapse:collapse; + width: 100%; + table-layout: fixed; +} + +.ui-treetable .ui-treetable-header, +.ui-treetable .ui-treetable-footer { + text-align:center; + padding: .5em .75em; +} + +.ui-treetable .ui-treetable-header { + border-bottom: 0 none; +} + +.ui-treetable .ui-treetable-footer { + border-top: 0 none; +} + +.ui-treetable th, .ui-treetable tfoot td { + text-align: center; +} + +.ui-treetable thead th, +.ui-treetable tbody td, +.ui-treetable tfoot td { + padding: .25em .5em; + overflow: hidden; + white-space: nowrap; + border-width: 1px; + border-style: solid; +} + +.ui-treetable tbody td { + border-color: inherit; +} + +.ui-treetable tbody td:first-child span { + vertical-align: middle; +} + +.ui-treetable .ui-treetable-toggler { + vertical-align: middle; + cursor: pointer; + text-decoration: none; +} + +.ui-treetable .ui-treetable-checkbox { + margin-right: .5em; +} + +.ui-treetable .ui-treetable-checkbox .ui-chkbox-icon { + margin-left: 1px; +} + +.ui-treetable .ui-treetable-row.ui-treetable-row-selectable { + cursor: pointer; +} + +.ui-treetable .ui-treetable-row.ui-state-highlight { + border: 0 none; +} + +.ui-treetable tr.ui-state-hover { + border-color: inherit; + font-weight: inherit; +} + +.ui-treetable .ui-treetable-indent { + width: 1em; + height: 1em; + float: left; +} + +/* PrimeNG */ +.ui-treetable td.ui-treetable-child-table-container { + padding: 0; + border: 0 none; +} + +.ui-treetable .ui-treetable-row { + display: table-row; + border-bottom: 0 transparent +} + +.ui-treetable tbody .ui-treetable-row td { + border: 0 none; +} + +.ui-treetable tbody .ui-treetable-row td input { + outline: 0 none; +} \ No newline at end of file diff --git a/src/app/components/treetable/treetable.ts b/src/app/components/treetable/treetable.ts new file mode 100644 index 00000000000..ef4c611bf1d --- /dev/null +++ b/src/app/components/treetable/treetable.ts @@ -0,0 +1,409 @@ +import {NgModule,Component,Input,Output,EventEmitter,ElementRef,ContentChild,IterableDiffers,ContentChildren,QueryList,Inject,forwardRef,OnInit} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {TreeNode} from '../common/treenode'; +import {Header,Footer,Column} from '../common/shared'; +import {SharedModule} from '../common/shared'; +import {DomHandler} from '../dom/domhandler'; + +@Component({ + selector: '[pTreeRow]', + template: ` +
        + + + +
        +
        {{resolveFieldData(node.data,col.field)}} + + +
        +
        + + + +
        + +
        + ` +}) +export class UITreeRow implements OnInit { + + @Input() node: TreeNode; + + @Input() parentNode: TreeNode; + + @Input() level: number = 0; + + @Input() labelExpand: string = "Expand"; + + @Input() labelCollapse: string = "Collapse"; + + constructor(@Inject(forwardRef(() => TreeTable)) public treeTable:TreeTable) {} + + ngOnInit() { + this.node.parent = this.parentNode; + } + + toggle(event: Event) { + if(this.node.expanded) + this.treeTable.onNodeCollapse.emit({originalEvent: event, node: this.node}); + else + this.treeTable.onNodeExpand.emit({originalEvent: event, node: this.node}); + + this.node.expanded = !this.node.expanded; + + event.preventDefault(); + } + + isLeaf() { + return this.node.leaf == false ? false : !(this.node.children&&this.node.children.length); + } + + isSelected() { + return this.treeTable.isSelected(this.node); + } + + onRowClick(event: MouseEvent) { + this.treeTable.onRowClick(event, this.node); + } + + onRowRightClick(event: MouseEvent) { + this.treeTable.onRowRightClick(event, this.node); + } + + onRowTouchEnd() { + this.treeTable.onRowTouchEnd(); + } + + resolveFieldData(data: any, field: string): any { + if(data && field) { + if(field.indexOf('.') == -1) { + return data[field]; + } + else { + let fields: string[] = field.split('.'); + let value = data; + for(var i = 0, len = fields.length; i < len; ++i) { + value = value[fields[i]]; + } + return value; + } + } + else { + return null; + } + } +} + +@Component({ + selector: 'p-treeTable', + template: ` +
        +
        + +
        +
        + + + + + + + + + + + + +
        + {{col.header}} + + + +
        + {{col.footer}} + + + +
        +
        + +
        + ` +}) +export class TreeTable { + + @Input() value: TreeNode[]; + + @Input() selectionMode: string; + + @Input() selection: any; + + @Input() style: any; + + @Input() styleClass: string; + + @Input() labelExpand: string = "Expand"; + + @Input() labelCollapse: string = "Collapse"; + + @Input() metaKeySelection: boolean = true; + + @Input() contextMenu: any; + + @Output() selectionChange: EventEmitter = new EventEmitter(); + + @Output() onNodeSelect: EventEmitter = new EventEmitter(); + + @Output() onNodeUnselect: EventEmitter = new EventEmitter(); + + @Output() onNodeExpand: EventEmitter = new EventEmitter(); + + @Output() onNodeCollapse: EventEmitter = new EventEmitter(); + + @Output() onContextMenuSelect: EventEmitter = new EventEmitter(); + + @ContentChild(Header) header: Header; + + @ContentChild(Footer) footer: Footer; + + @ContentChildren(Column) columns: QueryList; + + public rowTouched: boolean; + + onRowClick(event: MouseEvent, node: TreeNode) { + let eventTarget = ( event.target); + if(eventTarget.className && eventTarget.className.indexOf('ui-treetable-toggler') === 0) { + return; + } + else if(this.selectionMode) { + if(node.selectable === false) { + return; + } + + let metaSelection = this.rowTouched ? false : this.metaKeySelection; + let index = this.findIndexInSelection(node); + let selected = (index >= 0); + + if(this.isCheckboxSelectionMode()) { + if(selected) { + this.propagateSelectionDown(node, false); + if(node.parent) { + this.propagateSelectionUp(node.parent, false); + } + this.selectionChange.emit(this.selection); + this.onNodeUnselect.emit({originalEvent: event, node: node}); + } + else { + this.propagateSelectionDown(node, true); + if(node.parent) { + this.propagateSelectionUp(node.parent, true); + } + this.selectionChange.emit(this.selection); + this.onNodeSelect.emit({originalEvent: event, node: node}); + } + } + else { + if(metaSelection) { + let metaKey = (event.metaKey||event.ctrlKey); + + if(selected && metaKey) { + if(this.isSingleSelectionMode()) { + this.selectionChange.emit(null); + } + else { + this.selection = this.selection.filter((val,i) => i!=index); + this.selectionChange.emit(this.selection); + } + + this.onNodeUnselect.emit({originalEvent: event, node: node}); + } + else { + if(this.isSingleSelectionMode()) { + this.selectionChange.emit(node); + } + else if(this.isMultipleSelectionMode()) { + this.selection = (!metaKey) ? [] : this.selection||[]; + this.selection = [...this.selection,node]; + this.selectionChange.emit(this.selection); + } + + this.onNodeSelect.emit({originalEvent: event, node: node}); + } + } + else { + if(this.isSingleSelectionMode()) { + if(selected) { + this.selection = null; + this.onNodeUnselect.emit({originalEvent: event, node: node}); + } + else { + this.selection = node; + this.onNodeSelect.emit({originalEvent: event, node: node}); + } + } + else { + if(selected) { + this.selection = this.selection.filter((val,i) => i!=index); + this.onNodeUnselect.emit({originalEvent: event, node: node}); + } + else { + this.selection = [...this.selection||[],node]; + this.onNodeSelect.emit({originalEvent: event, node: node}); + } + } + + this.selectionChange.emit(this.selection); + } + } + } + + this.rowTouched = false; + } + + onRowTouchEnd() { + this.rowTouched = true; + } + + onRowRightClick(event: MouseEvent, node: TreeNode) { + if(this.contextMenu) { + let index = this.findIndexInSelection(node); + let selected = (index >= 0); + + if(!selected) { + if(this.isSingleSelectionMode()) { + this.selection = node; + } + else if(this.isMultipleSelectionMode()) { + this.selection = [node]; + this.selectionChange.emit(this.selection); + } + + this.selectionChange.emit(this.selection); + } + + this.contextMenu.show(event); + this.onContextMenuSelect.emit({originalEvent: event, node: node}); + } + } + + findIndexInSelection(node: TreeNode) { + let index: number = -1; + + if(this.selectionMode && this.selection) { + if(this.isSingleSelectionMode()) { + index = (this.selection == node) ? 0 : - 1; + } + else { + for(let i = 0; i < this.selection.length; i++) { + if(this.selection[i] == node) { + index = i; + break; + } + } + } + } + + return index; + } + + propagateSelectionUp(node: TreeNode, select: boolean) { + if(node.children && node.children.length) { + let selectedCount: number = 0; + let childPartialSelected: boolean = false; + for(let child of node.children) { + if(this.isSelected(child)) { + selectedCount++; + } + else if(child.partialSelected) { + childPartialSelected = true; + } + } + + if(select && selectedCount == node.children.length) { + this.selection = [...this.selection||[],node]; + node.partialSelected = false; + } + else { + if(!select) { + let index = this.findIndexInSelection(node); + if(index >= 0) { + this.selection = this.selection.filter((val,i) => i!=index); + } + } + + if(childPartialSelected || selectedCount > 0 && selectedCount != node.children.length) + node.partialSelected = true; + else + node.partialSelected = false; + } + } + + let parent = node.parent; + if(parent) { + this.propagateSelectionUp(parent, select); + } + } + + propagateSelectionDown(node: TreeNode, select: boolean) { + let index = this.findIndexInSelection(node); + + if(select && index == -1) { + this.selection = [...this.selection||[],node]; + } + else if(!select && index > -1) { + this.selection = this.selection.filter((val,i) => i!=index); + } + + node.partialSelected = false; + + if(node.children && node.children.length) { + for(let child of node.children) { + this.propagateSelectionDown(child, select); + } + } + } + + isSelected(node: TreeNode) { + return this.findIndexInSelection(node) != -1; + } + + isSingleSelectionMode() { + return this.selectionMode && this.selectionMode == 'single'; + } + + isMultipleSelectionMode() { + return this.selectionMode && this.selectionMode == 'multiple'; + } + + isCheckboxSelectionMode() { + return this.selectionMode && this.selectionMode == 'checkbox'; + } + + hasFooter() { + if(this.columns) { + let columnsArr = this.columns.toArray(); + for(let i = 0; i < columnsArr.length; i++) { + if(columnsArr[i].footer) { + return true; + } + } + } + return false; + } +} + +@NgModule({ + imports: [CommonModule,SharedModule], + exports: [TreeTable,SharedModule], + declarations: [TreeTable,UITreeRow] +}) +export class TreeTableModule { } \ No newline at end of file diff --git a/src/app/components/tristatecheckbox/tristatecheckbox.ts b/src/app/components/tristatecheckbox/tristatecheckbox.ts new file mode 100644 index 00000000000..0f36d2dadff --- /dev/null +++ b/src/app/components/tristatecheckbox/tristatecheckbox.ts @@ -0,0 +1,120 @@ +import {NgModule,Component,Input,Output,EventEmitter,forwardRef,ChangeDetectorRef} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; + +export const TRISTATECHECKBOX_VALUE_ACCESSOR: any = { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TriStateCheckbox), + multi: true +}; + +@Component({ + selector: 'p-triStateCheckbox', + template: ` +
        +
        + +
        +
        + +
        +
        + `, + providers: [TRISTATECHECKBOX_VALUE_ACCESSOR] +}) +export class TriStateCheckbox implements ControlValueAccessor { + + constructor(private cd: ChangeDetectorRef) {} + + @Input() disabled: boolean; + + @Input() name: string; + + @Input() tabindex: number; + + @Input() inputId: string; + + @Input() style: any; + + @Input() styleClass: string; + + @Output() onChange: EventEmitter = new EventEmitter(); + + focus: boolean; + + value: any; + + onModelChange: Function = () => {}; + + onModelTouched: Function = () => {}; + + onClick(event: Event, input: HTMLInputElement) { + if(!this.disabled) { + this.toggle(event); + this.focus = true; + input.focus(); + } + } + + onKeydown(event: KeyboardEvent) { + if(event.keyCode == 32) { + event.preventDefault(); + } + } + + onKeyup(event: KeyboardEvent) { + if(event.keyCode == 32) { + this.toggle(event); + event.preventDefault(); + } + } + + toggle(event: Event) { + if(this.value == null || this.value == undefined) + this.value = true; + else if(this.value == true) + this.value = false; + else if(this.value == false) + this.value = null; + + this.onModelChange(this.value); + this.onChange.emit({ + originalEvent: event, + value: this.value + }) + } + + onFocus() { + this.focus = true; + } + + onBlur() { + this.focus = false; + this.onModelTouched(); + } + + registerOnChange(fn: Function): void { + this.onModelChange = fn; + } + + registerOnTouched(fn: Function): void { + this.onModelTouched = fn; + } + + writeValue(value: any) : void { + this.value = value; + this.cd.markForCheck(); + } + + setDisabledState(disabled: boolean): void { + this.disabled = disabled; + } +} + +@NgModule({ + imports: [CommonModule], + exports: [TriStateCheckbox], + declarations: [TriStateCheckbox] +}) +export class TriStateCheckboxModule { } diff --git a/src/app/components/utils/ObjectUtils.ts b/src/app/components/utils/ObjectUtils.ts new file mode 100644 index 00000000000..60c93ddc3e3 --- /dev/null +++ b/src/app/components/utils/ObjectUtils.ts @@ -0,0 +1,81 @@ +import {Injectable} from '@angular/core'; + +@Injectable() +export class ObjectUtils { + + public equals(obj1: any, obj2: any, field?: string): boolean { + if(field) + return (this.resolveFieldData(obj1, field) === this.resolveFieldData(obj2, field)); + else + return this.equalsByValue(obj1, obj2); + } + + public equalsByValue(obj1: any, obj2: any): boolean { + if (obj1 == null && obj2 == null) { + return true; + } + if (obj1 == null || obj2 == null) { + return false; + } + + if (obj1 == obj2) { + delete obj1._$visited; + return true; + } + + if (typeof obj1 == 'object' && typeof obj2 == 'object') { + obj1._$visited = true; + for (var p in obj1) { + if (p === "_$visited") continue; + if (obj1.hasOwnProperty(p) !== obj2.hasOwnProperty(p)) { + return false; + } + + switch (typeof (obj1[p])) { + case 'object': + if (obj1[p] && obj1[p]._$visited || !this.equals(obj1[p], obj2[p])) return false; + break; + + case 'function': + if (typeof (obj2[p]) == 'undefined' || (p != 'compare' && obj1[p].toString() != obj2[p].toString())) return false; + break; + + default: + if (obj1[p] != obj2[p]) return false; + break; + } + } + + for (var p in obj2) { + if (typeof (obj1[p]) == 'undefined') return false; + } + + delete obj1._$visited; + return true; + } + + return false; + } + + resolveFieldData(data: any, field: string): any { + if(data && field) { + if(field.indexOf('.') == -1) { + return data[field]; + } + else { + let fields: string[] = field.split('.'); + let value = data; + for(var i = 0, len = fields.length; i < len; ++i) { + if (value == null) { + return null; + } + value = value[fields[i]]; + } + return value; + } + } + else { + return null; + } + } +} \ No newline at end of file diff --git a/src/app/showcase/app-routing.module.ts b/src/app/showcase/app-routing.module.ts new file mode 100644 index 00000000000..3b901aa7d4c --- /dev/null +++ b/src/app/showcase/app-routing.module.ts @@ -0,0 +1,87 @@ +import { Routes,RouterModule } from '@angular/router'; +import { NgModule } from '@angular/core'; +import { HomeComponent } from './components/home/home.component'; + +@NgModule({ + imports: [ + RouterModule.forRoot([ + {path: '', component: HomeComponent}, + {path: 'setup', loadChildren: './components/setup/setup.module#SetupModule'}, + {path: 'theming', loadChildren: './components/theming/theming.module#ThemingModule'}, + {path: 'accordion', loadChildren: './components/accordion/accordiondemo.module#AccordionDemoModule'}, + {path: 'autocomplete', loadChildren: './components/autocomplete/autocompletedemo.module#AutoCompleteDemoModule'}, + {path: 'blockui', loadChildren: './components/blockui/blockuidemo.module#BlockUIDemoModule'}, + {path: 'breadcrumb', loadChildren: './components/breadcrumb/breadcrumbdemo.module#BreadcrumbDemoModule'}, + {path: 'button', loadChildren: './components/button/buttondemo.module#ButtonDemoModule'}, + {path: 'calendar', loadChildren: './components/calendar/calendardemo.module#CalendarDemoModule'}, + {path: 'captcha', loadChildren: './components/captcha/captchademo.module#CaptchaDemoModule'}, + {path: 'carousel', loadChildren: './components/carousel/carouseldemo.module#CarouselDemoModule'}, + {path: 'chart', loadChildren: './components/chart/chartdemo.module#ChartDemoModule'}, + {path: 'checkbox', loadChildren: './components/checkbox/checkboxdemo.module#CheckboxDemoModule'}, + {path: 'chips', loadChildren: './components/chips/chipsdemo.module#ChipsDemoModule'}, + {path: 'codehighlighter', loadChildren: './components/codehighlighter/codehighlighterdemo.module#CodeHighlighterDemoModule'}, + {path: 'confirmdialog', loadChildren: './components/confirmdialog/confirmdialogdemo.module#ConfirmDialogDemoModule'}, + {path: 'contextmenu', loadChildren: './components/contextmenu/contextmenudemo.module#ContextMenuDemoModule'}, + {path: 'datagrid', loadChildren: './components/datagrid/datagriddemo.module#DataGridDemoModule'}, + {path: 'datalist', loadChildren: './components/datalist/datalistdemo.module#DataListDemoModule'}, + {path: 'datascroller', loadChildren: './components/datascroller/datascrollerdemo.module#DataScrollerDemoModule'}, + {path: 'datatable', loadChildren: './components/datatable/datatabledemo.module#DataTableDemoModule'}, + {path: 'defer', loadChildren: './components/defer/deferdemo.module#DeferDemoModule'}, + {path: 'dialog', loadChildren: './components/dialog/dialogdemo.module#DialogDemoModule'}, + {path: 'dragdrop', loadChildren: './components/dragdrop/dragdropdemo.module#DragDropDemoModule'}, + {path: 'dropdown', loadChildren: './components/dropdown/dropdowndemo.module#DropdownDemoModule'}, + {path: 'editor', loadChildren: './components/editor/editordemo.module#EditorDemoModule'}, + {path: 'fieldset', loadChildren: './components/fieldset/fieldsetdemo.module#FieldsetDemoModule'}, + {path: 'fileupload', loadChildren: './components/fileupload/fileuploaddemo.module#FileUploadDemoModule'}, + {path: 'galleria', loadChildren: './components/galleria/galleriademo.module#GalleriaDemoModule'}, + {path: 'gmap', loadChildren: './components/gmap/gmapdemo.module#GMapDemoModule'}, + {path: 'grid', loadChildren: './components/grid/griddemo.module#GridDemoModule'}, + {path: 'growl', loadChildren: './components/growl/growldemo.module#GrowlDemoModule'}, + {path: 'inplace', loadChildren: './components/inplace/inplacedemo.module#InplaceDemoModule'}, + {path: 'inputmask', loadChildren: './components/inputmask/inputmaskdemo.module#InputMaskDemoModule'}, + {path: 'inputswitch', loadChildren: './components/inputswitch/inputswitchdemo.module#InputSwitchDemoModule'}, + {path: 'inputtext', loadChildren: './components/inputtext/inputtextdemo.module#InputTextDemoModule'}, + {path: 'inputtextarea', loadChildren: './components/inputtextarea/inputtextareademo.module#InputTextareaDemoModule'}, + {path: 'lightbox', loadChildren: './components/lightbox/lightboxdemo.module#LightboxDemoModule'}, + {path: 'listbox', loadChildren: './components/listbox/listboxdemo.module#ListboxDemoModule'}, + {path: 'megamenu', loadChildren: './components/megamenu/megamenudemo.module#MegaMenuDemoModule'}, + {path: 'menu', loadChildren: './components/menu/menudemo.module#MenuDemoModule'}, + {path: 'menubar', loadChildren: './components/menubar/menubardemo.module#MenubarDemoModule'}, + {path: 'menumodel', loadChildren: './components/menumodel/menumodeldemo.module#MenuModelDemoModule'}, + {path: 'messages', loadChildren: './components/messages/messagesdemo.module#MessagesDemoModule'}, + {path: 'multiselect', loadChildren: './components/multiselect/multiselectdemo.module#MultiSelectDemoModule'}, + {path: 'orderlist', loadChildren: './components/orderlist/orderlistdemo.module#OrderListDemoModule'}, + {path: 'overlaypanel', loadChildren: './components/overlaypanel/overlaypaneldemo.module#OverlayPanelDemoModule'}, + {path: 'paginator', loadChildren: './components/paginator/paginatordemo.module#PaginatorDemoModule'}, + {path: 'panel', loadChildren: './components/panel/paneldemo.module#PanelDemoModule'}, + {path: 'panelmenu', loadChildren: './components/panelmenu/panelmenudemo.module#PanelMenuDemoModule'}, + {path: 'password', loadChildren: './components/password/passworddemo.module#PasswordDemoModule'}, + {path: 'picklist', loadChildren: './components/picklist/picklistdemo.module#PickListDemoModule'}, + {path: 'progressbar', loadChildren: './components/progressbar/progressbardemo.module#ProgressBarDemoModule'}, + {path: 'radiobutton', loadChildren: './components/radiobutton/radiobuttondemo.module#RadioButtonDemoModule'}, + {path: 'rating', loadChildren: './components/rating/ratingdemo.module#RatingDemoModule'}, + {path: 'responsive', loadChildren: './components/responsive/responsivedemo.module#ResponsiveDemoModule'}, + {path: 'rtl', loadChildren: './components/rtl/rtldemo.module#RTLDemoModule'}, + {path: 'schedule', loadChildren: './components/schedule/scheduledemo.module#ScheduleDemoModule'}, + {path: 'selectbutton', loadChildren: './components/selectbutton/selectbuttondemo.module#SelectButtonDemoModule'}, + {path: 'slidemenu', loadChildren: './components/slidemenu/slidemenudemo.module#SlideMenuDemoModule'}, + {path: 'slider', loadChildren: './components/slider/sliderdemo.module#SliderDemoModule'}, + {path: 'spinner', loadChildren: './components/spinner/spinnerdemo.module#SpinnerDemoModule'}, + {path: 'splitbutton', loadChildren: './components/splitbutton/splitbuttondemo.module#SplitButtonDemoModule'}, + {path: 'steps', loadChildren: './components/steps/stepsdemo.module#StepsDemoModule'}, + {path: 'tabmenu', loadChildren: './components/tabmenu/tabmenudemo.module#TabMenuDemoModule'}, + {path: 'tabview', loadChildren: './components/tabview/tabviewdemo.module#TabViewDemoModule'}, + {path: 'terminal', loadChildren: './components/terminal/terminaldemo.module#TerminalDemoModule'}, + {path: 'tieredmenu', loadChildren: './components/tieredmenu/tieredmenudemo.module#TieredMenuDemoModule'}, + {path: 'togglebutton', loadChildren: './components/togglebutton/togglebuttondemo.module#ToggleButtonDemoModule'}, + {path: 'toolbar', loadChildren: './components/toolbar/toolbardemo.module#ToolbarDemoModule'}, + {path: 'tooltip', loadChildren: './components/tooltip/tooltipdemo.module#TooltipDemoModule'}, + {path: 'tree', loadChildren: './components/tree/treedemo.module#TreeDemoModule'}, + {path: 'treetable', loadChildren: './components/treetable/treetabledemo.module#TreeTableDemoModule'}, + {path: 'tristatecheckbox', loadChildren: './components/tristatecheckbox/tristatecheckboxdemo.module#TriStateCheckboxDemoModule'}, + {path: 'validation', loadChildren: './components/validation/validationdemo.module#ValidationDemoModule'} + ]) + ], + exports: [RouterModule] +}) +export class AppRoutingModule {} diff --git a/src/app/showcase/app.component.css b/src/app/showcase/app.component.css new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/app/showcase/app.component.html b/src/app/showcase/app.component.html new file mode 100644 index 00000000000..9cc9559ab80 --- /dev/null +++ b/src/app/showcase/app.component.html @@ -0,0 +1,243 @@ +
        + + +
        +
        + + logo + + + + mockosx + Forum + + + + + Themes + + + + + mockosx + Setup + + + +
        + +
        + +
        + + +
        + +
        \ No newline at end of file diff --git a/src/app/showcase/app.component.spec.ts b/src/app/showcase/app.component.spec.ts new file mode 100644 index 00000000000..7d2799ceb66 --- /dev/null +++ b/src/app/showcase/app.component.spec.ts @@ -0,0 +1,32 @@ +import { TestBed, async } from '@angular/core/testing'; + +import { AppComponent } from './app.component'; + +describe('AppComponent', () => { + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ + AppComponent + ], + }).compileComponents(); + })); + + it('should create the app', async(() => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.debugElement.componentInstance; + expect(app).toBeTruthy(); + })); + + it(`should have as title 'app'`, async(() => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.debugElement.componentInstance; + expect(app.title).toEqual('app'); + })); + + it('should render title in a h1 tag', async(() => { + const fixture = TestBed.createComponent(AppComponent); + fixture.detectChanges(); + const compiled = fixture.debugElement.nativeElement; + expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!!'); + })); +}); diff --git a/src/app/showcase/app.component.ts b/src/app/showcase/app.component.ts new file mode 100644 index 00000000000..a7234c52816 --- /dev/null +++ b/src/app/showcase/app.component.ts @@ -0,0 +1,15 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.css'] +}) +export class AppComponent { + + changeTheme(event: Event, theme: string) { + let themeLink: HTMLLinkElement = document.getElementById('theme-css'); + themeLink.href = 'assets/components/themes/' + theme + '/theme.css'; + event.preventDefault(); + } +} diff --git a/src/app/showcase/app.module.ts b/src/app/showcase/app.module.ts new file mode 100644 index 00000000000..863dbe14b6c --- /dev/null +++ b/src/app/showcase/app.module.ts @@ -0,0 +1,36 @@ +import { BrowserModule } from '@angular/platform-browser'; +import { NgModule } from '@angular/core'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { HttpModule } from '@angular/http'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { LocationStrategy, HashLocationStrategy } from '@angular/common'; +import { AppRoutingModule } from './app-routing.module'; + +import { AppComponent } from './app.component'; +import { HomeComponent } from './components/home/home.component'; + +import { CarService } from './service/carservice'; +import { CountryService } from './service/countryservice'; +import { EventService } from './service/eventservice'; +import { NodeService } from './service/nodeservice'; + +@NgModule({ + declarations: [ + AppComponent, + HomeComponent + ], + imports: [ + BrowserModule, + FormsModule, + ReactiveFormsModule, + AppRoutingModule, + HttpModule, + BrowserAnimationsModule + ], + providers: [ + { provide: LocationStrategy, useClass: HashLocationStrategy }, + CarService,CountryService,EventService,NodeService + ], + bootstrap: [AppComponent] +}) +export class AppModule { } \ No newline at end of file diff --git a/src/app/showcase/components/accordion/accordiondemo-routing.module.ts b/src/app/showcase/components/accordion/accordiondemo-routing.module.ts new file mode 100644 index 00000000000..72ae144c573 --- /dev/null +++ b/src/app/showcase/components/accordion/accordiondemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {AccordionDemo} from './accordiondemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: AccordionDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class AccordionDemoRoutingModule {} diff --git a/src/app/showcase/components/accordion/accordiondemo.html b/src/app/showcase/components/accordion/accordiondemo.html new file mode 100644 index 00000000000..ddbbc52e134 --- /dev/null +++ b/src/app/showcase/components/accordion/accordiondemo.html @@ -0,0 +1,342 @@ +
        +
        + Accordion + Accordion groups a collection of contents in tabs. +
        +
        + +
        + + +

        Default

        + + + The story begins as Don Vito Corleone, the head of a New York Mafia family, overseeshis daughter's wedding. His beloved son ichael has just come home from the war, but does not intend to become part of his father's business. T hrough Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, kind and benevolent to those who give respect, but given to ruthless violence whenever anything stands against the good of the family. + + + Francis Ford Coppola's legendary continuation and sequel to his landmark 1972 film, The_Godfather parallels the young Vito Corleone's rise with his son Michael's spiritual fall, deepening The_Godfather's depiction of the dark side of the American dream. In the early 1900s, the child Vito flees his Sicilian village for America after the local Mafia kills his family. Vito struggles to make a living, legally or illegally, for his wife and growing brood in Little Italy, killing the local Black Hand Fanucci after he demands his customary cut of the tyro's business. With Fanucci gone, Vito's communal stature grows. + + + After a break of more than 15 years, director Francis Ford Coppola and writer Mario Puzo returned to the well for this third and final story of the fictional Corleone crime family. Two decades have passed, and crime kingpin Michael Corleone, now divorced from his wife Kay has nearly succeeded in keeping his promise that his family would one day be completely legitimate. + + + +

        Multiple

        + + + The story begins as Don Vito Corleone, the head of a New York Mafia family, overseeshis daughter's wedding. His beloved son ichael has just come home from the war, but does not intend to become part of his father's business. T hrough Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, kind and benevolent to those who give respect, but given to ruthless violence whenever anything stands against the good of the family. + + + Francis Ford Coppola's legendary continuation and sequel to his landmark 1972 film, The_Godfather parallels the young Vito Corleone's rise with his son Michael's spiritual fall, deepening The_Godfather's depiction of the dark side of the American dream. In the early 1900s, the child Vito flees his Sicilian village for America after the local Mafia kills his family. Vito struggles to make a living, legally or illegally, for his wife and growing brood in Little Italy, killing the local Black Hand Fanucci after he demands his customary cut of the tyro's business. With Fanucci gone, Vito's communal stature grows. + + + After a break of more than 15 years, director Francis Ford Coppola and writer Mario Puzo returned to the well for this third and final story of the fictional Corleone crime family. Two decades have passed, and crime kingpin Michael Corleone, now divorced from his wife Kay has nearly succeeded in keeping his promise that his family would one day be completely legitimate. + + + +

        Tab Change Event

        + + + The story begins as Don Vito Corleone, the head of a New York Mafia family, overseeshis daughter's wedding. His beloved son ichael has just come home from the war, but does not intend to become part of his father's business. T hrough Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, kind and benevolent to those who give respect, but given to ruthless violence whenever anything stands against the good of the family. + + + Francis Ford Coppola's legendary continuation and sequel to his landmark 1972 film, The_Godfather parallels the young Vito Corleone's rise with his son Michael's spiritual fall, deepening The_Godfather's depiction of the dark side of the American dream. In the early 1900s, the child Vito flees his Sicilian village for America after the local Mafia kills his family. Vito struggles to make a living, legally or illegally, for his wife and growing brood in Little Italy, killing the local Black Hand Fanucci after he demands his customary cut of the tyro's business. With Fanucci gone, Vito's communal stature grows. + + + After a break of more than 15 years, director Francis Ford Coppola and writer Mario Puzo returned to the well for this third and final story of the fictional Corleone crime family. Two decades have passed, and crime kingpin Michael Corleone, now divorced from his wife Kay has nearly succeeded in keeping his promise that his family would one day be completely legitimate. + + + After a break of more than 15 years, director Francis Ford Coppola and writer Mario Puzo returned to the well for this third and final story of the fictional Corleone crime family. Two decades have passed, and crime kingpin Michael Corleone, now divorced from his wife Kay has nearly succeeded in keeping his promise that his family would one day be completely legitimate. + + +
        + +
        + + +

        Import

        +
        +
        +import {AccordionModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Accordion element consists of one or more p-accordionTab elements. Title of the tab is defined using header attribute.

        +
        +
        +<p-accordion>
        +    <p-accordionTab header="Header 1">
        +       Content 1
        +    </p-accordionTab>
        +    <p-accordionTab header="Header 2">
        +        Content 2
        +    </p-accordionTab>
        +    <p-accordionTab header="Header 3">
        +        Content 3    
        +    </p-accordionTab>
        +</p-accordion>
        +
        +
        + +

        Selected

        +

        Visibility of the content is specified with the selected property that supports one or two-way binding.

        +
        +
        +<p-accordion>
        +    <p-accordionTab header="Header 1" [selected]="true">
        +       Content 1
        +    </p-accordionTab>
        +    <p-accordionTab header="Header 2">
        +        Content 2
        +    </p-accordionTab>
        +    <p-accordionTab header="Header 3">
        +        Content 3    
        +    </p-accordionTab>
        +</p-accordion>
        +
        +
        + +

        Multiple

        +

        By default only one tab at a time can be active, enabling multiple property changes this behavior to allow multiple + tabs be active at the same time.

        +
        +
        +<p-accordion [multiple]="true">
        +    <p-accordionTab header="Header 1">
        +        Content 1
        +    </p-accordionTab>
        +    <p-accordionTab header="Header 2">
        +        Content 2
        +    </p-accordionTab>
        +    <p-accordionTab header="Header 3">
        +        Content 3    
        +    </p-accordionTab>
        +</p-accordion>
        +
        +
        + +

        Disabled

        +

        A tab can be disabled by setting the disabled property to true.

        + +
        +
        +<p-accordion>
        +    <p-accordionTab header="Header 1" [disabled]="true">
        +       Content 1
        +    </p-accordionTab>
        +    <p-accordionTab header="Header 2">
        +        Content 2
        +    </p-accordionTab>
        +    <p-accordionTab header="Header 3">
        +        Content 3    
        +    </p-accordionTab>
        +</p-accordion>
        +
        +
        + +

        Custom Content at Headers

        +

        Custom content can be placed at an accordion header with header element.

        +
        +
        +import {SharedModule} from 'primeng/primeng';
        +
        +
        + +
        +
        +<p-accordionTab>
        +    <p-header>
        +        Header Content
        +    </p-header>
        +    Body Content
        +</p-accordionTab>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        multiplebooleanfalseWhen enabled, multiple tabs can be activated at the same time.
        stylestringnullInline style of the component.
        styleClassstringfalseStyle class of the component.
        lazybooleanfalseDefines whether the elements of an inactive panel are created on load or on demand when the panel gets selected.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onClose + event.originalEvent: Click object
        + event.index: Index of the tab +
        Callback to invoke when an active tab is collapsed by clicking on the header.
        onOpen + event.originalEvent: Click object
        + event.index: Index of the tab +
        Callback to invoke when a tab gets expanded.
        +
        +
        +
        +<p-accordion (onOpen)="onTabOpen($event)">
        +
        +
        +
        +
        +onTabOpen(e) {
        +    var index = e.index;
        +}
        +
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        + +
        + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-accordionContainer element
        ui-accordion-headerHeader of a tab.
        ui-accordion-contentContent of a tab.
        +
        + +

        Dependencies

        +

        None.

        + +
        + + +
        +
        +<p-growl [value]="msgs"></p-growl>
        +
        +<h3 class="first">Default</h3>
        +<p-accordion>
        +    <p-accordionTab header="Godfather I" [selected]="true">
        +        The story begins as Don Vito Corleone, the head of a New York Mafia family, overseeshis daughter's wedding. His beloved son ichael has just come home from the war, but does not intend to become part of his father's business. T hrough Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, kind and benevolent to those who give respect, but given to ruthless violence whenever anything stands against the good of the family.
        +    </p-accordionTab>
        +    <p-accordionTab header="Godfather II">
        +        Francis Ford Coppola's legendary continuation and sequel to his landmark 1972 film, The_Godfather parallels the young Vito Corleone's rise with his son Michael's spiritual fall, deepening The_Godfather's depiction of the dark side of the American dream. In the early 1900s, the child Vito flees his Sicilian village for America after the local Mafia kills his family. Vito struggles to make a living, legally or illegally, for his wife and growing brood in Little Italy, killing the local Black Hand Fanucci after he demands his customary cut of the tyro's business. With Fanucci gone, Vito's communal stature grows.
        +    </p-accordionTab>
        +    <p-accordionTab header="Godfather III">
        +        After a break of more than  15 years, director Francis Ford Coppola and writer Mario Puzo returned to the well for this third and final story of the fictional Corleone crime family. Two decades have passed, and crime kingpin Michael Corleone, now divorced from his wife Kay has nearly succeeded in keeping his promise that his family would one day be completely legitimate.
        +    </p-accordionTab>
        +</p-accordion>
        +
        +<h3>Multiple</h3>
        +<p-accordion [multiple]="true">
        +    <p-accordionTab header="Godfather I">
        +        The story begins  as Don Vito Corleone, the head of a New York Mafia family, overseeshis daughter's wedding. His beloved son ichael has just come home from the war, but does not intend to become part of his father's business. T hrough Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, kind and benevolent to those who give respect, but given to ruthless violence whenever anything stands against the good of the family.
        +    </p-accordionTab>
        +    <p-accordionTab header="Godfather II">
        +        Francis Ford Coppola's legendary continuation and sequel to his landmark 1972 film, The_Godfather parallels the young Vito Corleone's rise with his son Michael's spiritual fall, deepening The_Godfather's depiction of the dark side of the American dream. In the early 1900s, the child Vito flees his Sicilian village for America after the local Mafia kills his family. Vito struggles to make a living, legally or illegally, for his wife and growing brood in Little Italy, killing the local Black Hand Fanucci after he demands his customary cut of the tyro's business. With Fanucci gone, Vito's communal stature grows.
        +   </p-accordionTab>
        +    <p-accordionTab header="Godfather III">
        +        After a break of more than  15 years, director Francis Ford Coppola and writer Mario Puzo returned to the well for this third and final story of the fictional Corleone crime family. Two decades have passed, and crime kingpin Michael Corleone, now divorced from his wife Kay has nearly succeeded in keeping his promise that his family would one day be completely legitimate.
        +    </p-accordionTab>
        +</p-accordion>
        +
        +<h3>Tab Change Event</h3>
        +<p-accordion (onClose)="onTabClose($event)" (onOpen)="onTabOpen($event)">
        +    <p-accordionTab header="Godfather I">
        +        The story begins as Don Vito Corleone, the head of a New York Mafia family, overseeshis daughter's wedding. His beloved son ichael has just come home from the war, but does not intend to become part of his father's business. T hrough Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, kind and benevolent to those who give respect, but given to ruthless violence whenever anything stands against the good of the family.
        +    </p-accordionTab>
        +    <p-accordionTab header="Godfather II">
        +        Francis Ford Coppola's legendary continuation and sequel to his landmark 1972 film, The_Godfather parallels the young Vito Corleone's rise with his son Michael's spiritual fall, deepening The_Godfather's depiction of the dark side of the American dream. In the early 1900s, the child Vito flees his Sicilian village for America after the local Mafia kills his family. Vito struggles to make a living, legally or illegally, for his wife and growing brood in Little Italy, killing the local Black Hand Fanucci after he demands his customary cut of the tyro's business. With Fanucci gone, Vito's communal stature grows.
        +    </p-accordionTab>
        +    <p-accordionTab header="Godfather III">
        +        After a break of more than  15 years, director Francis Ford Coppola and writer Mario Puzo returned to the well for this third and final story of the fictional Corleone crime family. Two decades have passed, and crime kingpin Michael Corleone, now divorced from his wife Kay has nearly succeeded in keeping his promise that his family would one day be completely legitimate.
        +    </p-accordionTab>
        +    <p-accordionTab header="Godfather IV" [disabled]="true">
        +        After a break of more than  15 years, director Francis Ford Coppola and writer Mario Puzo returned to the well for this third and final story of the fictional Corleone crime family. Two decades have passed, and crime kingpin Michael Corleone, now divorced from his wife Kay has nearly succeeded in keeping his promise that his family would one day be completely legitimate.
        +    </p-accordionTab>
        +</p-accordion>
        +
        +
        + +
        +
        +export class AccordionDemo {
        +
        +    msgs: Message[];
        +
        +    onTabClose(event) {
        +        this.msgs = [];
        +        this.msgs.push({severity:'info', summary:'Tab Closed', detail: 'Index: ' + event.index});
        +    }
        +    
        +    onTabOpen(event) {
        +        this.msgs = [];
        +        this.msgs.push({severity:'info', summary:'Tab Expanded', detail: 'Index: ' + event.index});
        +    }
        +}
        +
        +
        +
        +
        +
        diff --git a/src/app/showcase/components/accordion/accordiondemo.module.ts b/src/app/showcase/components/accordion/accordiondemo.module.ts new file mode 100644 index 00000000000..5a6e0e19f06 --- /dev/null +++ b/src/app/showcase/components/accordion/accordiondemo.module.ts @@ -0,0 +1,23 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {AccordionDemo} from './accordiondemo'; +import {AccordionDemoRoutingModule} from './accordiondemo-routing.module'; +import {AccordionModule} from '../../../components/accordion/accordion'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {GrowlModule} from '../../../components/growl/growl'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + AccordionDemoRoutingModule, + AccordionModule, + TabViewModule, + GrowlModule, + CodeHighlighterModule + ], + declarations: [ + AccordionDemo + ] +}) +export class AccordionDemoModule {} diff --git a/src/app/showcase/components/accordion/accordiondemo.ts b/src/app/showcase/components/accordion/accordiondemo.ts new file mode 100644 index 00000000000..3a4b6cb7000 --- /dev/null +++ b/src/app/showcase/components/accordion/accordiondemo.ts @@ -0,0 +1,20 @@ +import {Component} from '@angular/core'; +import {Message} from '../../../components/common/api'; + +@Component({ + templateUrl: './accordiondemo.html' +}) +export class AccordionDemo { + + msgs: Message[]; + + onTabClose(event) { + this.msgs = []; + this.msgs.push({severity:'info', summary:'Tab Closed', detail: 'Index: ' + event.index}); + } + + onTabOpen(event) { + this.msgs = []; + this.msgs.push({severity:'info', summary:'Tab Expanded', detail: 'Index: ' + event.index}); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/autocomplete/autocompletedemo-routing.module.ts b/src/app/showcase/components/autocomplete/autocompletedemo-routing.module.ts new file mode 100644 index 00000000000..ce25721ddd8 --- /dev/null +++ b/src/app/showcase/components/autocomplete/autocompletedemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {AutoCompleteDemo} from './autocompletedemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: AutoCompleteDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class AutoCompleteDemoRoutingModule {} diff --git a/src/app/showcase/components/autocomplete/autocompletedemo.html b/src/app/showcase/components/autocomplete/autocompletedemo.html new file mode 100644 index 00000000000..3edf16667fe --- /dev/null +++ b/src/app/showcase/components/autocomplete/autocompletedemo.html @@ -0,0 +1,563 @@ +
        +
        + AutoComplete + AutoComplete is an input component that provides real-time suggestions when being typed. +
        +
        + +
        +

        Basic

        + + Country: {{country ? country.name||country : 'none'}} + +

        Advanced

        + + +
        + +
        {{brand}}
        +
        +
        +
        + Brand: {{brand||'none'}} + +

        Multiple

        + + +
          +
        • {{c.name}}
        • +
        +
        + +
        + + +

        Import

        +
        +
        +import {AutoCompleteModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        AutoComplete uses ngModel for two-way binding, requires a list of suggestions and a completeMethod to query for the results. The completeMethod + gets the query text as event.query property and should update the suggestions with the search results.

        +
        +
        +<p-autoComplete [(ngModel)]="text" [suggestions]="results" (completeMethod)="search($event)"></p-autoComplete>
        +
        +
        + +
        +
        +export class AutoCompleteDemo {
        +    
        +    text: string;
        +    
        +    results: string[];
        +    
        +    search(event) {
        +        this.mylookupservice.getResults(event.query).then(data => {
        +            this.results = data;
        +        });
        +    }
        +    
        +}
        +
        +
        + +

        Model Driven Forms

        +

        AutoComplete can be used in a model driven form as well.

        +
        +
        +<p-autoComplete formControlName="city" [suggestions]="results" (completeMethod)="search($event)"></p-autoComplete>
        +
        +
        + +

        Dropdown

        +

        Enabling dropdown property displays a button next to the input field, implementation by default does nothing and you can use + the dropdown for cases like displaying all results. onDropdownClick is triggered when the button is clicked.

        +
        +
        +<p-autoComplete [(ngModel)]="text" [suggestions]="results" (completeMethod)="search($event)" 
        +            [dropdown]="true" (onDropdownClick)="handleDropdown(event)"></p-autoComplete>
        +
        +
        + +
        +
        +export class AutoCompleteDemo {
        +    
        +    text: string;
        +    
        +    results: string[];
        +    
        +    search(event) {
        +        this.mylookupservice.getResults(event.query).then(data => {
        +            this.results = data;
        +        });
        +    }
        +    
        +    handleDropdown(event) {
        +        //event.query = current value in input field
        +    }
        +    
        +}
        +
        +
        + +

        Multiple Selection

        +

        Multiple mode is used to select more than one value from the autocomplete. In this case, model reference should be an array.

        +
        +
        +<p-autoComplete [(ngModel)]="texts" [suggestions]="results" (completeMethod)="search($event)" [multiple]="true"></p-autoComplete>
        +
        +
        + +
        +
        +export class AutoCompleteDemo {
        +    
        +    texts: string[];
        +    
        +    results: string[];
        +    
        +    search(event) {
        +        this.mylookupservice.getResults(event.query).then(data => {
        +            this.results = data;
        +        });
        +    }
        +    
        +}
        +
        +
        + +

        Objects

        +

        AutoComplete can also work with objects using the field property that defines the label to display as a suggestion. The value passed to the model would still be the + object instance of a suggestion. Here is an example with a Country object that has name and code fields such as {name:"United States",code:"USA"}.

        +
        +
        +<p-autoComplete [(ngModel)]="val" [suggestions]="results" (completeMethod)="search($event)" field="name"></p-autoComplete>
        +
        +
        + +
        +
        +export class AutoCompleteDemo {
        +    
        +    val: country;
        +    
        +    results: country[];
        +    
        +    search(event) {
        +        this.countrylookupservice.getResults(event.query).then(data => {
        +            this.results = data;
        +        });
        +    }
        +    
        +}
        +
        +
        + +

        Templating

        +

        Item ng-template allows displaying custom content inside the suggestions panel. The local ng-template variable passed to the ng-template is an object in the suggestions array.

        +
        +
        +<p-autoComplete [(ngModel)]="brand" [suggestions]="filteredBrands" (completeMethod)="filterBrands($event)">
        +    <ng-template let-brand pTemplate="item">
        +        <div class="ui-helper-clearfix" style="border-bottom:1px solid #D5D5D5">
        +            <img src="showcase/resources/demo/images/car/{{brand}}.gif" style="width:32px;display:inline-block;margin:5px 0 2px 5px"/>
        +            <div style="font-size:18px;float:right;margin:10px 10px 0 0">{{brand}}</div>
        +        </div>
        +    </ng-template>
        +</p-autoComplete>
        +
        +
        + +

        In multiple mode, selected item can be customized using selectedItem ng-template.

        +
        +
        +<p-autoComplete [(ngModel)]="texts" [suggestions]="results" (completeMethod)="search($event)" [multiple]="true">
        +    <ng-template let-value pTemplate="selectedItem">
        +        <span style="font-size:18px">>{{value}}<</span>
        +    </ng-template>
        +</p-autoComplete>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        suggestionsarraynullAn array of suggestions to display.
        fieldanynullField of a suggested object to resolve and display.
        scrollHeightstring200pxMaximum height of the suggestions panel.
        dropdownbooleanfalseDisplays a button next to the input field when enabled.
        multiplebooleanfalseSpecifies if multiple values can be selected.
        minLengthnumber1Minimum number of characters to initiate a search.
        delaynumber300Delay between keystrokes to wait before sending a query.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        inputStylestringnullInline style of the input field.
        inputStyleClassstringnullInline style of the input field.
        inputIdstringnullIdentifier of the focus input to match a label defined for the component.
        placeholderstringnullHint text for the input field.
        readonlybooleanfalseWhen present, it specifies that the input cannot be typed.
        disabledbooleanfalseWhen present, it specifies that the component should be disabled.
        maxlengthnumbernullMaximum number of character allows in the input field.
        sizenumbernullSize of the input field.
        appendToanynullTarget element to attach the overlay, valid values are "body" or a local ng-template variable of another element.
        tabindexnumbernullIndex of the element in tabbing order.
        dataKeystringnullA property to uniquely identify a value in options.
        autoHighlightbooleanfalseWhen enabled, highlights the first item in the list by default.
        typestringtextType of the input, defaults to "text".
        emptyMessagestringnullMessage to display when there are no results for a query.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        completeMethod + event.originalEvent: browser event
        + event.query: Value to search with +
        Callback to invoke to search for suggestions.
        onFocusevent: Browser eventCallback to invoke when autocomplete gets focus.
        onBlurevent: Browser eventCallback to invoke when autocomplete loses focus.
        onSelect + value: Selected value + Callback to invoke when a suggestion is selected.
        onUnselect + value: Unselected value in multiple mode + Callback to invoke when a selected value is removed.
        onDropdownClick + event.originalEvent: browser event
        + event.query: Current value of the input field +
        Callback to invoke to when dropdown button is clicked.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-autocompleteContainer element
        ui-autocomplete-panelOverlay panel of suggestions.
        ui-autocomplete-itemsList container of suggestions.
        ui-autocomplete-itemList item of a suggestion.
        ui-autocomplete-tokenElement of a selected item in multiple mode.
        ui-autocomplete-token-iconClose icon element of a selected item in multiple mode.
        ui-autocomplete-token-labelLabel of a selected item in multiple mode.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<h3 class="first">Basic</h3>
        +<p-autoComplete [(ngModel)]="country" [suggestions]="filteredCountriesSingle" (completeMethod)="filterCountrySingle($event)" field="name" [size]="30"
        +    placeholder="Countries" [minLength]="1"></p-autoComplete>
        +<span style="margin-left:10px">Country: {{country ? country.name||country : 'none'}}</span>
        +
        +<h3>Advanced</h3>
        +<p-autoComplete [(ngModel)]="brand" [suggestions]="filteredBrands" (completeMethod)="filterBrands($event)" [size]="30"
        +    [minLength]="1" placeholder="Hint: type 'v' or 'f'" [dropdown]="true" (onDropdownClick)="handleDropdownClick($event)">
        +    <ng-template let-brand pTemplate="item">
        +        <div class="ui-helper-clearfix" style="border-bottom:1px solid #D5D5D5">
        +            <img src="showcase/resources/demo/images/car/{{brand}}.gif" style="width:32px;display:inline-block;margin:5px 0 2px 5px"/>
        +            <div style="font-size:18px;float:right;margin:10px 10px 0 0">{{brand}}</div>
        +        </div>
        +    </ng-template>
        +</p-autoComplete>
        +<span style="margin-left:50px">Brand: {{brand||'none'}}</span>
        +
        +<h3>Multiple</h3>
        +<p-autoComplete [(ngModel)]="countries" [suggestions]="filteredCountriesMultiple" (completeMethod)="filterCountryMultiple($event)" styleClass="wid100"
        +    [minLength]="1" placeholder="Countries" field="name" [multiple]="true">
        +</p-autoComplete>
        +<ul>
        +    <li *ngFor="let c of countries">{{c.name}}</li>
        +</ul>
        +
        +
        + +
        +
        +export class AutoCompleteDemo {
        +
        +    country: any;
        +    
        +    countries: any[];
        +        
        +    filteredCountriesSingle: any[];
        +    
        +    filteredCountriesMultiple: any[];
        +    
        +    brands: string[] = ['Audi','BMW','Fiat','Ford','Honda','Jaguar','Mercedes','Renault','Volvo','VW'];
        +    
        +    filteredBrands: any[];
        +    
        +    brand: string;
        +    
        +    constructor(private countryService: CountryService) { }
        +    
        +    filterCountrySingle(event) {
        +        let query = event.query;        
        +        this.countryService.getCountries().then(countries => {
        +            this.filteredCountriesSingle = this.filterCountry(query, countries);
        +        });
        +    }
        +    
        +    filterCountryMultiple(event) {
        +        let query = event.query;
        +        this.countryService.getCountries().then(countries => {
        +            this.filteredCountriesMultiple = this.filterCountry(query, countries);
        +        });
        +    }
        +    
        +    filterCountry(query, countries: any[]):any[] {
        +        //in a real application, make a request to a remote url with the query and return filtered results, for demo we filter at client side
        +        let filtered : any[] = [];
        +        for(let i = 0; i < countries.length; i++) {
        +            let country = countries[i];
        +            if(country.name.toLowerCase().indexOf(query.toLowerCase()) == 0) {
        +                filtered.push(country);
        +            }
        +        }
        +        return filtered;
        +    }
        +        
        +    filterBrands(event) {
        +        this.filteredBrands = [];
        +        for(let i = 0; i < this.brands.length; i++) {
        +            let brand = this.brands[i];
        +            if(brand.toLowerCase().indexOf(event.query.toLowerCase()) == 0) {
        +                this.filteredBrands.push(brand);
        +            }
        +        }
        +    }
        +    
        +    handleDropdownClick() {
        +        this.filteredBrands = [];
        +        
        +        //mimic remote call
        +        setTimeout(() => {
        +            this.filteredBrands = this.brands;
        +        }, 100)
        +    }
        +}
        +
        +
        + +
        +
        +@Injectable()
        +export class CountryService {
        +    
        +    constructor(private http: Http) {}
        +
        +    getCountries() {
        +        return this.http.get('showcase/resources/data/countries.json')
        +                    .toPromise()
        +                    .then(res => <any[]> res.json().data)
        +                    .then(data => { return data; });
        +    }
        +}
        +
        +
        +
        +
        +
        diff --git a/src/app/showcase/components/autocomplete/autocompletedemo.module.ts b/src/app/showcase/components/autocomplete/autocompletedemo.module.ts new file mode 100644 index 00000000000..14ed028591c --- /dev/null +++ b/src/app/showcase/components/autocomplete/autocompletedemo.module.ts @@ -0,0 +1,23 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms' +import {AutoCompleteDemo} from './autocompletedemo'; +import {AutoCompleteDemoRoutingModule} from './autocompletedemo-routing.module'; +import {AutoCompleteModule} from '../../../components/autocomplete/autocomplete'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + AutoCompleteDemoRoutingModule, + AutoCompleteModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + AutoCompleteDemo + ] +}) +export class AutoCompleteDemoModule {} diff --git a/src/app/showcase/components/autocomplete/autocompletedemo.ts b/src/app/showcase/components/autocomplete/autocompletedemo.ts new file mode 100644 index 00000000000..95ec4e52d08 --- /dev/null +++ b/src/app/showcase/components/autocomplete/autocompletedemo.ts @@ -0,0 +1,69 @@ +import {Component} from '@angular/core'; +import {CountryService} from '../../service/countryservice'; + +@Component({ + templateUrl: './autocompletedemo.html' +}) +export class AutoCompleteDemo { + + country: any; + + countries: any[]; + + filteredCountriesSingle: any[]; + + filteredCountriesMultiple: any[]; + + brands: string[] = ['Audi','BMW','Fiat','Ford','Honda','Jaguar','Mercedes','Renault','Volvo','VW']; + + filteredBrands: any[]; + + brand: string; + + constructor(private countryService: CountryService) { } + + filterCountrySingle(event) { + let query = event.query; + this.countryService.getCountries().then(countries => { + this.filteredCountriesSingle = this.filterCountry(query, countries); + }); + } + + filterCountryMultiple(event) { + let query = event.query; + this.countryService.getCountries().then(countries => { + this.filteredCountriesMultiple = this.filterCountry(query, countries); + }); + } + + filterCountry(query, countries: any[]):any[] { + //in a real application, make a request to a remote url with the query and return filtered results, for demo we filter at client side + let filtered : any[] = []; + for(let i = 0; i < countries.length; i++) { + let country = countries[i]; + if(country.name.toLowerCase().indexOf(query.toLowerCase()) == 0) { + filtered.push(country); + } + } + return filtered; + } + + filterBrands(event) { + this.filteredBrands = []; + for(let i = 0; i < this.brands.length; i++) { + let brand = this.brands[i]; + if(brand.toLowerCase().indexOf(event.query.toLowerCase()) == 0) { + this.filteredBrands.push(brand); + } + } + } + + handleDropdownClick() { + this.filteredBrands = []; + + //mimic remote call + setTimeout(() => { + this.filteredBrands = this.brands; + }, 100) + } +} \ No newline at end of file diff --git a/src/app/showcase/components/blockui/blockuidemo-routing.module.ts b/src/app/showcase/components/blockui/blockuidemo-routing.module.ts new file mode 100644 index 00000000000..673220e00a5 --- /dev/null +++ b/src/app/showcase/components/blockui/blockuidemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {BlockUIDemo} from './blockuidemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: BlockUIDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class BlockUIDemoRoutingModule {} diff --git a/src/app/showcase/components/blockui/blockuidemo.html b/src/app/showcase/components/blockui/blockuidemo.html new file mode 100644 index 00000000000..b58ff551ad8 --- /dev/null +++ b/src/app/showcase/components/blockui/blockuidemo.html @@ -0,0 +1,180 @@ +
        +
        + BlockUI + BlockUI can either block other components or the whole page. +
        +
        + +
        +

        Document

        + + + + +

        Panel

        + + + + + + + + The story begins as Don Vito Corleone, the head of a New York Mafia family, oversees his daughter's wedding. + His beloved son Michael has just come home from the war, but does not intend to become part of his father's business. + Through Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, + kind and benevolent to those who give respect, but given to ruthless violence whenever anything stands against the good of the family. + +
        + +
        + + +

        Import

        +
        +
        +import {BlockUIModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        BlockUI is controlled using the blocked property and component to block is defined as target. If target is not provided, document + itself is selected as the block target.

        + +
        +
        +export class BlockUIDemo {
        +
        +    blocked: boolean;
        +    
        +}
        +
        +
        + +
        +
        +<p-blockUI [blocked]="blocked"></p-blockUI>
        +
        +
        + +

        To block a certain component, define a local ng-template variable and bind it to the target option. The target component must implement the + BlockableUI interface, otherwise an exception is thrown.

        +
        +
        +<p-blockUI [blocked]="blockedDocument" [target]="pnl"></p-blockUI>
        +
        +<p-panel #pnl header="Panel Header">
        +    Content of Panel
        +</p-panel>
        +
        +
        + +

        Custom Content

        +

        Blocker mask is customized by simply adding the content inside the component

        +

        +
        +<p-blockUI [target]="pnl" [blocked]="blockedPanel">
        +    <i class="fa fa-lock fa-5x" style="position:absolute;top:25%;left:50%"></i>
        +</p-blockUI>
        +
        +<p-panel #pnl header="Panel Header">
        +    Content of Panel
        +</p-panel>
        +
        +
        + + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        blockedbooleanfalseControls the blocked state.
        targetanydocumentName of the local ng-template variable referring to another component.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + +
        NameElement
        ui-blockuiContainer element.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +export class BlockUIDemo {
        +
        +    blockedPanel: boolean = false;
        +    
        +    blockedDocument: boolean = false;
        +        
        +    blockDocument() {
        +        this.blockedDocument = true;
        +        setTimeout(() => {
        +            this.blockedDocument = false;
        +        }, 3000);
        +    }
        +}
        +
        +
        + +
        +
        +<h3 class="first">Document</h3>
        +<p-blockUI [blocked]="blockedDocument"></p-blockUI>
        +
        +<button type="button" pButton label="Block" (click)="blockDocument()"></button>
        +
        +<h3>Panel</h3>
        +<button type="button" pButton label="Block" (click)="blockedPanel=true"></button>
        +<button type="button" pButton label="Unblock" (click)="blockedPanel=false"></button>
        +
        +<p-blockUI [target]="pnl" [blocked]="blockedPanel">
        +    <i class="fa fa-lock fa-5x" style="position:absolute;top:25%;left:50%"></i>
        +</p-blockUI>
        +<p-panel #pnl header="Godfather I" [style]="{'margin-top':'20px'}">
        +    The story begins as Don Vito Corleone, the head of a New York Mafia family, oversees his daughter's wedding. 
        +    His beloved son Michael has just come home from the war, but does not intend to become part of his father's business. 
        +    Through Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, 
        +    kind and benevolent to those who give respect, but given to ruthless violence whenever anything stands against the good of the family.
        +</p-panel>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/blockui/blockuidemo.module.ts b/src/app/showcase/components/blockui/blockuidemo.module.ts new file mode 100644 index 00000000000..55110848cc6 --- /dev/null +++ b/src/app/showcase/components/blockui/blockuidemo.module.ts @@ -0,0 +1,25 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {BlockUIDemo} from './blockuidemo'; +import {BlockUIDemoRoutingModule} from './blockuidemo-routing.module'; +import {BlockUIModule} from '../../../components/blockui/blockui'; +import {ButtonModule} from '../../../components/button/button'; +import {PanelModule} from '../../../components/panel/panel'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + BlockUIDemoRoutingModule, + BlockUIModule, + ButtonModule, + PanelModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + BlockUIDemo + ] +}) +export class BlockUIDemoModule {} diff --git a/src/app/showcase/components/blockui/blockuidemo.ts b/src/app/showcase/components/blockui/blockuidemo.ts new file mode 100644 index 00000000000..20bbf1b634e --- /dev/null +++ b/src/app/showcase/components/blockui/blockuidemo.ts @@ -0,0 +1,18 @@ +import {Component,OnInit,EventEmitter} from '@angular/core'; + +@Component({ + templateUrl: './blockuidemo.html' +}) +export class BlockUIDemo { + + blockedPanel: boolean = false; + + blockedDocument: boolean = false; + + blockDocument() { + this.blockedDocument = true; + setTimeout(() => { + this.blockedDocument = false; + }, 3000); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/breadcrumb/breadcrumbdemo-routing.module.ts b/src/app/showcase/components/breadcrumb/breadcrumbdemo-routing.module.ts new file mode 100644 index 00000000000..ef57e809215 --- /dev/null +++ b/src/app/showcase/components/breadcrumb/breadcrumbdemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {BreadcrumbDemo} from './breadcrumbdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: BreadcrumbDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class BreadcrumbDemoRoutingModule {} diff --git a/src/app/showcase/components/breadcrumb/breadcrumbdemo.html b/src/app/showcase/components/breadcrumb/breadcrumbdemo.html new file mode 100644 index 00000000000..85cbf566527 --- /dev/null +++ b/src/app/showcase/components/breadcrumb/breadcrumbdemo.html @@ -0,0 +1,159 @@ +
        +
        + Breadcrumb + Breadcrumb provides contextual information about page hierarchy. +
        +
        + +
        + +
        + +
        + + +

        Import

        +
        +
        +import {BreadcrumbModule,MenuItem} from 'primeng/primeng';
        +
        +
        + +

        MenuModel API

        +

        Breadcrumb uses the common menumodel api to define its items, visit MenuModel API for details.

        + +

        Getting Started

        +

        Breadcrumb requires a collection of menuitems connected to its model property.

        + +
        +
        +export class BreadcrumbDemo implements OnInit {
        +
        +    private items: MenuItem[];
        +    
        +    ngOnInit() {
        +        this.items = [];
        +        this.items.push({label:'Categories'});
        +        this.items.push({label:'Sports'});
        +        this.items.push({label:'Football'});
        +        this.items.push({label:'Countries'});
        +        this.items.push({label:'Spain'});
        +        this.items.push({label:'F.C. Barcelona'});
        +        this.items.push({label:'Squad'});
        +        this.items.push({label:'Lionel Messi', url: 'https://en.wikipedia.org/wiki/Lionel_Messi'});
        +    }
        +}
        +
        +
        + +
        +
        +<p-breadcrumb [model]="items"></p-breadcrumb>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        modelarraynullAn array of menuitems.
        homeMenuItemnullMenuItem configuration for the home icon.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-breadcrumbContainer element.
        ui-menuitemMenuitem element.
        ui-menuitem-textLabel of a menuitem.
        ui-breadcrumb-chevronChevron element.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +export class BreadcrumbDemo implements OnInit {
        +
        +    private items: MenuItem[];
        +    
        +    ngOnInit() {
        +        this.items = [];
        +        this.items.push({label:'Categories'});
        +        this.items.push({label:'Sports'});
        +        this.items.push({label:'Football'});
        +        this.items.push({label:'Countries'});
        +        this.items.push({label:'Spain'});
        +        this.items.push({label:'F.C. Barcelona'});
        +        this.items.push({label:'Squad'});
        +        this.items.push({label:'Lionel Messi', url: 'https://en.wikipedia.org/wiki/Lionel_Messi'});
        +    }
        +}
        +
        +
        + +
        +
        +<p-breadcrumb [model]="items"></p-breadcrumb>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/breadcrumb/breadcrumbdemo.module.ts b/src/app/showcase/components/breadcrumb/breadcrumbdemo.module.ts new file mode 100644 index 00000000000..924ec67465c --- /dev/null +++ b/src/app/showcase/components/breadcrumb/breadcrumbdemo.module.ts @@ -0,0 +1,21 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {BreadcrumbDemo} from './breadcrumbdemo'; +import {BreadcrumbDemoRoutingModule} from './breadcrumbdemo-routing.module'; +import {BreadcrumbModule} from '../../../components/breadcrumb/breadcrumb'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + BreadcrumbDemoRoutingModule, + BreadcrumbModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + BreadcrumbDemo + ] +}) +export class BreadcrumbDemoModule {} diff --git a/src/app/showcase/components/breadcrumb/breadcrumbdemo.ts b/src/app/showcase/components/breadcrumb/breadcrumbdemo.ts new file mode 100644 index 00000000000..bae7db0806d --- /dev/null +++ b/src/app/showcase/components/breadcrumb/breadcrumbdemo.ts @@ -0,0 +1,22 @@ +import {Component,OnInit,EventEmitter} from '@angular/core'; +import {MenuItem} from '../../../components/common/api'; + +@Component({ + templateUrl: './breadcrumbdemo.html' +}) +export class BreadcrumbDemo implements OnInit { + + private items: MenuItem[]; + + ngOnInit() { + this.items = []; + this.items.push({label:'Categories'}); + this.items.push({label:'Sports'}); + this.items.push({label:'Football'}); + this.items.push({label:'Countries'}); + this.items.push({label:'Spain'}); + this.items.push({label:'F.C. Barcelona'}); + this.items.push({label:'Squad'}); + this.items.push({label:'Lionel Messi', url: 'https://en.wikipedia.org/wiki/Lionel_Messi'}); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/button/buttondemo-routing.module.ts b/src/app/showcase/components/button/buttondemo-routing.module.ts new file mode 100644 index 00000000000..d30f6b2bbca --- /dev/null +++ b/src/app/showcase/components/button/buttondemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {ButtonDemo} from './buttondemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: ButtonDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class ButtonDemoRoutingModule {} diff --git a/src/app/showcase/components/button/buttondemo.html b/src/app/showcase/components/button/buttondemo.html new file mode 100644 index 00000000000..b91df55448b --- /dev/null +++ b/src/app/showcase/components/button/buttondemo.html @@ -0,0 +1,196 @@ +
        +
        + Button + Button is an extension to standard input element with icons and theming. +
        +
        + +
        + + + + + + + + + + +

        Severity Buttons

        + + + + + + + + + + + + + +

        + Number of clicks: {{clicks}} +
        + +
        + + +

        Import

        +
        +
        +import {ButtonModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Button is applied to a button element with pButton directive. Text of the button is defined using label property.

        + +
        +
        +<button pButton type="button" label="Click"></button>
        +
        +
        + +

        Events

        +

        Events are defined using standard notation.

        + +
        +
        +<button pButton type="button" (click)="onclick()" label="Click"></button>
        +
        +
        + +
        +
        +export class Model {
        +
        +    onclick() {
        +        //execute action
        +    }
        +
        +}
        +
        +
        + +

        Icons

        +

        Icon on a button is specified with icon attribute and position is customized using iconPos attribute. Default + icon position is left. To display only an icon, leave label as undefined.

        +
        +
        +<button pButton type="button" icon="fa-check" iconPos="left"></button>
        +
        +
        + +

        Severity

        +

        Different color options are available to define severity levels.

        + +
          +
        • .ui-button-secondary
        • +
        • .ui-button-success
        • +
        • .ui-button-info
        • +
        • .ui-button-warning
        • +
        • .ui-button-danger
        • +
        +
        +
        +<button pButton type="button" class="ui-button-info"></button>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        labelstringnullText of the button.
        iconstringnullName of the icon.
        iconPosstringleftPosition of the icon, valid values are "left" and "right".
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-buttonButton element
        ui-button-iconIcon element
        ui-button-textLabel element of the button
        +
        + +

        Dependencies

        +

        None.

        +
        + +
        +
        +<button pButton type="button" (click)="count()" label="Click"></button>
        +
        +<button pButton type="button" (click)="count()" icon="fa-check" label="Click"></button>
        +
        +<button pButton type="button" (click)="count()" icon="fa-check" iconPos="right" label="Click"></button>
        +
        +<button pButton type="button" (click)="count()" icon="fa-check"></button>
        +
        +<button pButton type="button" (click)="count()" icon="fa-check" [disabled]="true" label="Disabled"></button>
        +
        +Number of clicks: {{clicks}}
        +
        +
        +
        +
        +export class ButtonDemo {
        +
        +    clicks: number = 0;
        +
        +    count() {
        +        this.clicks++;
        +    }
        +}
        +
        +
        + +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/button/buttondemo.module.ts b/src/app/showcase/components/button/buttondemo.module.ts new file mode 100644 index 00000000000..958a51a68db --- /dev/null +++ b/src/app/showcase/components/button/buttondemo.module.ts @@ -0,0 +1,21 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {ButtonDemo} from './buttondemo'; +import {ButtonDemoRoutingModule} from './buttondemo-routing.module'; +import {ButtonModule} from '../../../components/button/button'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + ButtonDemoRoutingModule, + ButtonModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + ButtonDemo + ] +}) +export class ButtonDemoModule {} diff --git a/src/app/showcase/components/button/buttondemo.ts b/src/app/showcase/components/button/buttondemo.ts new file mode 100644 index 00000000000..7ac909ce617 --- /dev/null +++ b/src/app/showcase/components/button/buttondemo.ts @@ -0,0 +1,13 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './buttondemo.html' +}) +export class ButtonDemo { + + clicks: number = 0; + + count() { + this.clicks++; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/calendar/calendardemo-routing.module.ts b/src/app/showcase/components/calendar/calendardemo-routing.module.ts new file mode 100644 index 00000000000..224e0981712 --- /dev/null +++ b/src/app/showcase/components/calendar/calendardemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {CalendarDemo} from './calendardemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: CalendarDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class CalendarDemoRoutingModule {} diff --git a/src/app/showcase/components/calendar/calendardemo.html b/src/app/showcase/components/calendar/calendardemo.html new file mode 100644 index 00000000000..b13c1910375 --- /dev/null +++ b/src/app/showcase/components/calendar/calendardemo.html @@ -0,0 +1,616 @@ +
        +
        + Calendar + Calendar is an input component to select a date. +
        +
        + +
        +
        +
        +

        Basic

        + {{date1|date}} +
        + +
        +

        Spanish

        + {{date2|date}} +
        + +
        +

        Icon

        + {{date3|date}} +
        + +
        +

        Min-Max

        + {{date4|date}} +
        + +
        +

        Disable Days

        + {{date5|date}} +
        + +
        +

        Navigators

        + {{date6|date}} +
        + +
        +

        Time

        + {{date7}} +
        + +
        +

        Time Only

        + +
        +
        + +

        Inline {{date9|date}}

        + +
        + +
        + + +

        Import

        +
        +
        +import {CalendarModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Two-way value binding is defined using the standard ngModel directive referencing to a Date property.

        + +
        +
        +<p-calendar [(ngModel)]="value"></p-calendar>
        +
        +
        + +
        +
        +export class MyModel {
        +
        +    value: Date;
        +    
        +}
        +
        +
        + +

        Model Driven Forms

        +

        Calendar can be used in a model driven form as well.

        +
        +
        +<p-calendar formControlName="date"></p-calendar>
        +
        +
        + +

        Popup and Inline

        +

        Calendar is displayed in a popup by default and inline property needs to be enabled for inline mode.

        +
        +
        +<p-calendar [(ngModel)]="value" [inline]="true"></p-calendar>
        +
        +
        + +

        DateFormat

        +

        Default date format is mm/dd/yy, to customize this use dateFormat property.

        +
        +
        +<p-calendar [(ngModel)]="dateValue" dateFormat="dd.mm.yy"></p-calendar>
        +
        +
        + +

        Following options can be a part of the format.

        +
          +
        • d - day of month (no leading zero)
        • +
        • dd - day of month (two digit)
        • +
        • o - day of the year (no leading zeros)
        • +
        • oo - day of the year (three digit)
        • +
        • D - day name short
        • +
        • DD - day name long
        • +
        • m - month of year (no leading zero)
        • +
        • mm - month of year (two digit)
        • +
        • M - month name short
        • +
        • MM - month name long
        • +
        • y - year (two digit)
        • +
        • yy - year (four digit)
        • +
        • @ - Unix timestamp (ms since 01/01/1970)
        • +
        • ! - Windows ticks (100ns since 01/01/0001)
        • +
        • '...' - literal text
        • +
        • '' - single quote
        • +
        • anything else - literal text
        • +
        + +

        Time

        +

        TimePicker is enabled with showTime property and 24 (default) or 12 hour mode is configured using hourFormat option.

        +
        +
        +<p-calendar [(ngModel)]="value" showTime="showTime" hourFormat="12"></p-calendar>
        +<p-calendar [(ngModel)]="value" showTime="showTime" hourFormat="24"></p-calendar>
        +
        +
        + +

        Date Restriction

        +

        To disable entering dates manually, set readonlyInput to true and to restrict selectable dates use minDate + and maxDate options.

        +
        +
        +<p-calendar [(ngModel)]="dateValue" [minDate]="minDateValue" [maxDate]="maxDateValue" readonlyInput="readonlyInput">></p-calendar>
        +
        +
        + +

        Disable specific dates and/or days

        +

        To disable specific dates or days, set readonlyInput to true and to restrict selectable dates use disabledDates and/or disabledDays options.

        +
        +
        +<p-calendar [(ngModel)]="dateValue" [disabledDates]="invalidDates" [disabledDays]="[0,6}" readonlyInput="readonlyInput">></p-calendar>
        +
        +
        + +

        Localization

        +

        Localization for different languages and formats is defined by binding the locale settings object to the locale property. Following is the default values for English. +

        +
        +
        +<p-calendar [(ngModel)]="dateValue" [locale]="en"></p-calendar>
        +
        +
        + +
        +
        +export class MyModel {
        +    
        +    en: any;
        +    
        +    ngOnInit() {
        +        this.en = {
        +            firstDayOfWeek: 0,
        +            dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
        +            dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
        +            dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"],
        +            monthNames: [ "January","February","March","April","May","June","July","August","September","October","November","December" ],
        +            monthNamesShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun","Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ]
        +        };
        +    }
        +}
        +
        +
        + +

        Custom Content

        +

        Calendar UI accepts custom content using p-header and p-footer components.

        +
        +
        +<p-calendar [(ngModel)]="dateValue">
        +    <p-header>Header</p-header>
        +    <p-footer>Footer</p-footer>
        +</p-calendar>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        defaultDateDatenullSet the date to highlight on first opening if the field is blank.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        inputStylestringnullInline style of the input field.
        inputStyleClassstringnullStyle class of the input field.
        inputIdstringnullIdentifier of the focus input to match a label defined for the component.
        placeholderstringnullPlaceholder text for the input.
        disabledbooleanfalseWhen specified, disables the component.
        dateFormatstringmm/dd/yyFormat of the date.
        inlinebooleanfalseWhen enabled, displays the calendar as inline. Default is false for popup mode.
        showOtherMonthsbooleantrueWhether to display dates in other months (non-selectable) at the start or end of the current month. To make these days selectable use the selectOtherMonths option.
        selectOtherMonthsbooleanfalseWhether days in other months shown before or after the current month are selectable. This only applies if the showOtherMonths option is set to true.
        showIconbooleanfalseWhen enabled, displays a button with icon next to input.
        showOnFocusbooleantrueWhen disabled, datepicker will not be visible with input focus.
        iconstringfa-calendarIcon of the calendar button.
        appendToanynullTarget element to attach the overlay, valid values are "body" or a local ng-template variable of another element.
        readonlyInputbooleannullWhen specified, prevents entering the date manually with keyboard.
        shortYearCutoffstring+10The cutoff year for determining the century for a date.
        minDateDatenullThe minimum selectable date.
        maxDateDatenullThe maximum selectable date.
        disabledDatesArray<Date>nullArray with dates that should be disabled (not selectable).
        disabledDaysArray<number>nullArray with weekday numbers that should be disabled (not selectable).
        monthNavigatorbooleanfalseWhether the month should be rendered as a dropdown instead of text.
        yearNavigatorbooleanfalseWhether the year should be rendered as a dropdown instead of text.
        yearRangestringnullThe range of years displayed in the year drop-down in (nnnn:nnnn) format such as (2000:2020).
        showTimebooleanfalseWhether to display timepicker.
        hourFormatstring24Specifies 12 or 24 hour format.
        localeobjectnullAn object having regional configuration properties for the calendar.
        timeOnlybooleanfalseWhether to display timepicker only.
        dataTypestringdateType of the value to write back to ngModel, default is date and alternative is string.
        requiredbooleanfalseWhen present, it specifies that an input field must be filled out before submitting the form.
        tabindexnumbernullIndex of the element in tabbing order.
        showSecondsbooleanfalseWhether to show the seconds in time picker.
        stepHournumber1Hours to change per step.
        stepMinutenumber1Minutes to change per step.
        stepSecondnumber1Seconds to change per step.
        utcbooleanfalseWhether to convert date to UTC on selection.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onSelectvalue: Selected value + Callback to invoke when a date is selected.
        onBlurevent: Blur event + Callback to invoke on blur of input field.
        onFocusevent: Focus event + Callback to invoke on focus of input field.
        onInputevent: Input event + Callback to invoke when input field is being typed.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + +
        NameElement
        ui-calendarWrapper of input element
        ui-inputtextInput element
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<div class="ui-g">
        +    <div class="ui-g-12 ui-md-4">
        +        <h3>Basic</h3>
        +        <p-calendar [(ngModel)]="date1"></p-calendar> {{date1|date}}
        +    </div>
        +    
        +    <div class="ui-g-12 ui-md-4">
        +        <h3>Spanish</h3>
        +        <p-calendar [(ngModel)]="date2" [locale]="es" dateFormat="dd/mm/yy"></p-calendar> {{date2|date}}
        +    </div>
        +    
        +    <div class="ui-g-12 ui-md-4">
        +        <h3>Icon</h3>
        +        <p-calendar [(ngModel)]="date3" [showIcon]="true"></p-calendar> <span style="margin-left:35px">{{date3|date}}</span>
        +    </div>
        +    
        +    <div class="ui-g-12 ui-md-4">
        +        <h3>Min-Max</h3>
        +        <p-calendar [(ngModel)]="date4" [minDate]="minDate" [maxDate]="maxDate" [readonlyInput]="true"></p-calendar> {{date4|date}}
        +    </div>
        +    
        +    <div class="ui-g-12 ui-md-4">
        +        <h3>Disable Days</h3>
        +        <p-calendar [(ngModel)]="date5" tabindex="0" [disabledDates]="invalidDates" [disabledDays]="[0,6]" readonlyInput="readonlyInput"></p-calendar> {{date5|date}}
        +    </div>
        +    
        +    <div class="ui-g-12 ui-md-4">
        +        <h3>Navigators</h3>
        +        <p-calendar [(ngModel)]="date6" [monthNavigator]="true" [yearNavigator]="true" yearRange="2000:2030"></p-calendar> {{date6|date}}
        +    </div>
        +    
        +    <div class="ui-g-12 ui-md-4">
        +        <h3>Time</h3>
        +        <p-calendar [(ngModel)]="date7" [showTime]="true"></p-calendar> {{date7}}
        +    </div>
        +    
        +    <div class="ui-g-12 ui-md-4">
        +        <h3>Time Only </h3>
        +        <p-calendar [(ngModel)]="date8" [timeOnly]="true"></p-calendar>
        +    </div>
        +</div>
        +
        +<h3>Inline {{date8|date}}</h3>
        +<p-calendar [(ngModel)]="date9" [inline]="true"></p-calendar> 
        +
        +
        + +
        +
        +export class CalendarDemo {
        +
        +    date1: Date;
        +
        +    date2: Date;
        +
        +    date3: Date;
        +
        +    date4: Date;
        +
        +    date5: Date;
        +
        +    date6: Date;
        +    
        +    date7: Date;
        +    
        +    date8: Date;
        +    
        +    date9: Date;
        +    
        +    minDate: Date;
        +    
        +    maxDate: Date;
        +    
        +    es: any;
        +    
        +    invalidDates: Array<Date>
        +        
        +    ngOnInit() {
        +        this.es = {
        +            firstDayOfWeek: 1,
        +            dayNames: [ "domingo","lunes","martes","miércoles","jueves","viernes","sábado" ],
        +            dayNamesShort: [ "dom","lun","mar","mié","jue","vie","sáb" ],
        +            dayNamesMin: [ "D","L","M","X","J","V","S" ],
        +            monthNames: [ "enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre" ],
        +            monthNamesShort: [ "ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic" ]
        +        }
        +        
        +        this.tr = {
        +            firstDayOfWeek : 1
        +        }
        +        
        +        let today = new Date();
        +        let month = today.getMonth();
        +        let year = today.getFullYear();
        +        let prevMonth = (month === 0) ? 11 : month -1;
        +        let prevYear = (prevMonth === 11) ? year - 1 : year;
        +        let nextMonth = (month === 11) ? 0 : month + 1;
        +        let nextYear = (nextMonth === 0) ? year + 1 : year;
        +        this.minDate = new Date();
        +        this.minDate.setMonth(prevMonth);
        +        this.minDate.setFullYear(prevYear);
        +        this.maxDate = new Date();
        +        this.maxDate.setMonth(nextMonth);
        +        this.maxDate.setFullYear(nextYear);
        +        
        +        let invalidDate = new Date();
        +        invalidDate.setDate(today.getDate() - 1);
        +        this.invalidDates = [today,invalidDate];
        +    }
        +}
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/calendar/calendardemo.module.ts b/src/app/showcase/components/calendar/calendardemo.module.ts new file mode 100644 index 00000000000..6ef70086f3a --- /dev/null +++ b/src/app/showcase/components/calendar/calendardemo.module.ts @@ -0,0 +1,23 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms' +import {CalendarDemo} from './calendardemo'; +import {CalendarDemoRoutingModule} from './calendardemo-routing.module'; +import {CalendarModule} from '../../../components/calendar/calendar'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + CalendarDemoRoutingModule, + CalendarModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + CalendarDemo + ] +}) +export class CalendarDemoModule {} diff --git a/src/app/showcase/components/calendar/calendardemo.ts b/src/app/showcase/components/calendar/calendardemo.ts new file mode 100644 index 00000000000..ee8f4419171 --- /dev/null +++ b/src/app/showcase/components/calendar/calendardemo.ts @@ -0,0 +1,62 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './calendardemo.html' +}) +export class CalendarDemo { + + date1: Date; + + date2: Date; + + date3: Date; + + date4: Date; + + date5: Date; + + date6: Date; + + date7: Date; + + date8: Date; + + date9: Date; + + minDate: Date; + + maxDate: Date; + + invalidDates: Array; + + es: any; + + ngOnInit() { + this.es = { + firstDayOfWeek: 1, + dayNames: [ "domingo","lunes","martes","miércoles","jueves","viernes","sábado" ], + dayNamesShort: [ "dom","lun","mar","mié","jue","vie","sáb" ], + dayNamesMin: [ "D","L","M","X","J","V","S" ], + monthNames: [ "enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre" ], + monthNamesShort: [ "ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic" ] + }; + + let today = new Date(); + let month = today.getMonth(); + let year = today.getFullYear(); + let prevMonth = (month === 0) ? 11 : month -1; + let prevYear = (prevMonth === 11) ? year - 1 : year; + let nextMonth = (month === 11) ? 0 : month + 1; + let nextYear = (nextMonth === 0) ? year + 1 : year; + this.minDate = new Date(); + this.minDate.setMonth(prevMonth); + this.minDate.setFullYear(prevYear); + this.maxDate = new Date(); + this.maxDate.setMonth(nextMonth); + this.maxDate.setFullYear(nextYear); + + let invalidDate = new Date(); + invalidDate.setDate(today.getDate() - 1); + this.invalidDates = [today,invalidDate]; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/captcha/captchademo-routing.module.ts b/src/app/showcase/components/captcha/captchademo-routing.module.ts new file mode 100644 index 00000000000..d422fd498ab --- /dev/null +++ b/src/app/showcase/components/captcha/captchademo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {CaptchaDemo} from './captchademo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: CaptchaDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class CaptchaDemoRoutingModule {} diff --git a/src/app/showcase/components/captcha/captchademo.html b/src/app/showcase/components/captcha/captchademo.html new file mode 100644 index 00000000000..d055ce0e74b --- /dev/null +++ b/src/app/showcase/components/captcha/captchademo.html @@ -0,0 +1,207 @@ +
        +
        + Captcha + Captcha is a form validation component based on Recaptcha. +
        +
        + +
        + + + +
        + +
        + + +

        Import

        +
        +
        +import {CaptchaModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Captcha is used with a siteKey and a callback to verify the response.

        + +
        +
        +<p-captcha siteKey="YOUR_SITE_KEY" (onResponse)="showResponse($event)"></p-captcha>
        +
        +
        + +

        In addition include the captcha widget resource to your page.

        +
        +
        +<script src="https://www.google.com/recaptcha/api.js?render=explicit&onload=initRecaptcha" async defer></script>
        +
        +
        + +

        Global callback name is initRecaptcha by default and it can be changed using initCallback property .

        +
        +
        +<script src="https://www.google.com/recaptcha/api.js?render=explicit&onload=loadCaptcha" async defer></script>
        +
        +
        + +
        +
        +<p-captcha siteKey="YOUR_SITE_KEY" (onResponse)="showResponse($event)" initCallback="loadCaptcha"></p-captcha>
        +
        +
        + + +

        Verification

        +

        In order to ensure if a response token is valid, verification against recaptcha api needs to be done at backend. Read more at + official documentation.

        +
        +
        +showResponse(response) {
        +    //call to a backend to verify against recaptcha with private key
        +}
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        sitekeystringnullPublic sitekey.
        themestringlightThe color scheme of the widget.
        typestringimageThe type of CAPTCHA to serve.
        sizestringnormalThe size of the widget.
        tabindexnumber0The tabindex of the widget and challenge. + If other elements in your page use tabindex, + it should be set to make user navigation easier. +
        languagestringenLanguage of the widget.
        initCallbackstringinitRecaptchaName of global callback to initialize recaptcha.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onResponseevent.response: The user response token.The callback function to be executed when the user submits a successful CAPTCHA response.
        onExpire-The callback function to be executed when the recaptcha response expires and the user needs to solve a new CAPTCHA.
        +
        + +

        Methods

        +
        + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        reset-Resets the reCAPTCHA widget.
        getResponse-Gets the response for the reCAPTCHA widget.
        +
        + +

        Official Documentation

        + Here + +

        Dependencies

        +

        Google Recaptcha V2

        +
        + + +
        +
        +<p-growl [value]="msgs" sticky="sticky"></p-growl>
        +
        +<p-captcha siteKey="6Lf2XQkTAAAAANcvOwYqPxWL4iZDksFqHpS39GDA" (onResponse)="showResponse($event)"></p-captcha>
        +
        +
        + +
        +
        +export class CaptchaDemo {
        +    
        +    msgs: Message[] = [];
        +    
        +    showResponse(event) {
        +        this.msgs = [];
        +        this.msgs.push({severity:'info', summary:'Succees', detail: 'User Responded'});
        +    }
        +}
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/captcha/captchademo.module.ts b/src/app/showcase/components/captcha/captchademo.module.ts new file mode 100644 index 00000000000..8f48e47e82d --- /dev/null +++ b/src/app/showcase/components/captcha/captchademo.module.ts @@ -0,0 +1,23 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {CaptchaDemo} from './captchademo'; +import {CaptchaDemoRoutingModule} from './captchademo-routing.module'; +import {CaptchaModule} from '../../../components/captcha/captcha'; +import {GrowlModule} from '../../../components/growl/growl'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + CaptchaDemoRoutingModule, + CaptchaModule, + TabViewModule, + GrowlModule, + CodeHighlighterModule + ], + declarations: [ + CaptchaDemo + ] +}) +export class CaptchaDemoModule {} diff --git a/src/app/showcase/components/captcha/captchademo.ts b/src/app/showcase/components/captcha/captchademo.ts new file mode 100644 index 00000000000..bb35ad43df3 --- /dev/null +++ b/src/app/showcase/components/captcha/captchademo.ts @@ -0,0 +1,15 @@ +import {Component} from '@angular/core'; +import {Message} from '../../../components/common/api'; + +@Component({ + templateUrl: './captchademo.html' +}) +export class CaptchaDemo { + + msgs: Message[] = []; + + showResponse(event) { + this.msgs = []; + this.msgs.push({severity:'info', summary:'Success', detail: 'User Responsed'}); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/carousel/carouseldemo-routing.module.ts b/src/app/showcase/components/carousel/carouseldemo-routing.module.ts new file mode 100644 index 00000000000..a7692ca3e9b --- /dev/null +++ b/src/app/showcase/components/carousel/carouseldemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {CarouselDemo} from './carouseldemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: CarouselDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class CarouselDemoRoutingModule {} diff --git a/src/app/showcase/components/carousel/carouseldemo.html b/src/app/showcase/components/carousel/carouseldemo.html new file mode 100644 index 00000000000..43062ba2406 --- /dev/null +++ b/src/app/showcase/components/carousel/carouseldemo.html @@ -0,0 +1,339 @@ +
        +
        + Carousel + Carousel displays content using a slide effect featuring responsive mode, swipe support for touch enabled devices and various customization options. +
        +
        + +
        + + + + + +
        +
        +
        +
        +
        +
        Vin
        +
        {{car.vin}}
        +
        +
        +
        Year
        +
        {{car.year}}
        +
        +
        +
        Color
        +
        {{car.color}}
        +
        +
        +
        + +
        +
        +
        +
        +
        +
        + +
        + + +

        Import

        +
        +
        +import {CarouselModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Carousel requires a collection of items as its value and a ng-template content to display + where each item can be accessed using the implicit variable.

        +
        +
        +<p-carousel [value]="items">
        +    <ng-template let-item pTemplate="item">
        +        Content to display
        +    </ul>
        +</p-carousel>
        +
        +
        + +

        Managing Data

        +

        DataTable uses setter based checking to realize if the underlying data has changed to update the UI so your data changes such as adding or removing a record + should always create a new array reference instead of manipulating an existing array. For example, use slice instead of splice when removing an item + or use spread operator instead of push method when adding an item.

        + +

        Limiting Visible Items

        +

        Default number of visible items is 3, use numVisible option to customize this.

        +
        +
        +<p-carousel numVisible="1">
        +
        +
        + +

        Effects

        +

        The easing function to use is "ease-out" by default and this can be customized using easing property. + See here for possible alternative values.

        +
        +
        +<p-carousel easing="easeOutStrong">
        +
        +
        + +

        SlideShow

        +

        Carousel can display the contents in a slideshow, for this purpose autoPlayInterval and circular attributes are used.

        +
        +
        +<p-carousel circular="circular" autoplayInterval="3000">
        +
        +
        + +

        Responsive

        +

        Responsive mode is enabled by default causing carousel to switch between small and large viewport depending on the breakpoint value which is 560 initially.

        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        valuearraynullArray of data to display.
        numVisiblenumber3Number of visible items per page.
        firstVisiblenumber0Index of the first visible item.
        headerTextstringnullText of the header section.
        effectDurationany500Duration of the scrolling animation in milliseconds or a predefined value like "slow", "normal" and "fast".
        circularbooleanfalseDefines continuous scrolling.
        breakpointnumber560Breakpoint value in pixels to switch between small and large viewport.
        responsivebooleantrueWhen defined, causes carousel to adjust its width based on screen size.
        autoplayIntervalnumber0Time in milliseconds to have carousel start scrolling automatically.
        easingstringease-outEasing animation to use for scrolling.
        pageLinksnumber3Number of maximum page links to display. If total page count exceeds this value a dropdown is displayed instead.
        stylestringnullInline style of the element.
        styleClassstringnullInline style of the element.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + +
        NameParametersDescription
        onPageevent.page: New page indexCallback to invoke on page change.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-carouselContainer element.
        ui-carousel-headerHeader element.
        ui-carousel-header-titleHeader text.
        ui-carousel-viewportViewport containing the items.
        ui-carousel-buttonNavigator button at header.
        ui-carousel-next-buttonNext page button at header.
        ui-carousel-prev-buttonPrevious page button at header.
        ui-carousel-page-linksPage links container.
        ui-carousel-page-linkA page link.
        ui-carousel-mobiledropdownCancel icon.
        ui-carousel-itemCancel icon.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<p-growl [value]="msgs"></p-growl>
        +
        +<p-carousel headerText="Cars" [value]="cars">
        +    <ng-template let-car pTemplate="item">
        +        <div class="ui-grid ui-grid-responsive">
        +            <div class="ui-grid-row">
        +                <div class="ui-grid-col-12"><img src="showcase/resources/demo/images/car/{{car.brand}}.gif" /></div>
        +            </div>
        +            <div class="ui-grid-row">
        +                <div class="ui-grid-col-6">Vin</div>
        +                <div class="ui-grid-col-6">{{car.vin}}</div>
        +            </div>
        +            <div class="ui-grid-row">
        +                <div class="ui-grid-col-6">Year</div>
        +                <div class="ui-grid-col-6">{{car.year}}</div>
        +            </div>
        +            <div class="ui-grid-row">
        +                <div class="ui-grid-col-6">Color</div>
        +                <div class="ui-grid-col-6">{{car.color}}</div>
        +            </div>
        +            <div class="ui-grid-row">
        +                <div class="ui-grid-col-12">
        +                    <button type="button" pButton icon="fa-search" (click)="selectCar(car)"></button>
        +                </div>
        +            </div>
        +        </div>
        +    </ng-template>
        +</p-carousel>
        +
        +
        + +
        +
        +export class CarouselDemo {
        +
        +    cars: Car[];
        +
        +    msgs: Message[];
        +
        +    constructor() {
        +        this.msgs = [];
        +        this.cars = [
        +            {vin: 'r3278r2', year: 2010, brand: 'Audi', color: 'Black'},
        +            {vin: 'jhto2g2', year: 2015, brand: 'BMW', color: 'White'},
        +            {vin: 'h453w54', year: 2012, brand: 'Honda', color: 'Blue'},
        +            {vin: 'g43gwwg', year: 1998, brand: 'Renault', color: 'White'},
        +            {vin: 'gf45wg5', year: 2011, brand: 'VW', color: 'Red'},
        +            {vin: 'bhv5y5w', year: 2015, brand: 'Jaguar', color: 'Blue'},
        +            {vin: 'ybw5fsd', year: 2012, brand: 'Ford', color: 'Yellow'},
        +            {vin: '45665e5', year: 2011, brand: 'Mercedes', color: 'Brown'},
        +            {vin: 'he6sb5v', year: 2015, brand: 'Ford', color: 'Black'}
        +        ];
        +    }
        +
        +    selectCar(car: Car) {
        +        this.msgs = [];
        +        this.msgs.push({severity: 'info', summary: 'Car Selected', detail: 'Vin:' + car.vin});
        +    }
        +}
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/carousel/carouseldemo.module.ts b/src/app/showcase/components/carousel/carouseldemo.module.ts new file mode 100644 index 00000000000..6295f7af161 --- /dev/null +++ b/src/app/showcase/components/carousel/carouseldemo.module.ts @@ -0,0 +1,25 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {CarouselDemo} from './carouseldemo'; +import {CarouselDemoRoutingModule} from './carouseldemo-routing.module'; +import {CarouselModule} from '../../../components/carousel/carousel'; +import {ButtonModule} from '../../../components/button/button'; +import {GrowlModule} from '../../../components/growl/growl'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + CarouselDemoRoutingModule, + CarouselModule, + ButtonModule, + GrowlModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + CarouselDemo + ] +}) +export class CarouselDemoModule {} diff --git a/src/app/showcase/components/carousel/carouseldemo.ts b/src/app/showcase/components/carousel/carouseldemo.ts new file mode 100644 index 00000000000..6e26314c04a --- /dev/null +++ b/src/app/showcase/components/carousel/carouseldemo.ts @@ -0,0 +1,46 @@ +import {Component} from '@angular/core'; +import {Message} from '../../../components/common/api'; +import {Car} from '../../components/domain/car'; + +@Component({ + templateUrl: './carouseldemo.html', + styles: [` + .ui-grid-row { + text-align: center; + } + + .ui-grid { + margin: 10px 0px; + } + + .ui-grid-row > div { + padding: 4px 10px; + } + `] +}) +export class CarouselDemo { + + cars: Car[]; + + msgs: Message[]; + + constructor() { + this.msgs = []; + this.cars = [ + {vin: 'r3278r2', year: 2010, brand: 'Audi', color: 'Black'}, + {vin: 'jhto2g2', year: 2015, brand: 'BMW', color: 'White'}, + {vin: 'h453w54', year: 2012, brand: 'Honda', color: 'Blue'}, + {vin: 'g43gwwg', year: 1998, brand: 'Renault', color: 'White'}, + {vin: 'gf45wg5', year: 2011, brand: 'VW', color: 'Red'}, + {vin: 'bhv5y5w', year: 2015, brand: 'Jaguar', color: 'Blue'}, + {vin: 'ybw5fsd', year: 2012, brand: 'Ford', color: 'Yellow'}, + {vin: '45665e5', year: 2011, brand: 'Mercedes', color: 'Brown'}, + {vin: 'he6sb5v', year: 2015, brand: 'Ford', color: 'Black'} + ]; + } + + selectCar(car: Car) { + this.msgs = []; + this.msgs.push({severity: 'info', summary: 'Car Selected', detail: 'Vin:' + car.vin}); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/chart/barchart/barchartdemo.html b/src/app/showcase/components/chart/barchart/barchartdemo.html new file mode 100644 index 00000000000..8d235b1c621 --- /dev/null +++ b/src/app/showcase/components/chart/barchart/barchartdemo.html @@ -0,0 +1,53 @@ +
        +
        + BarChart + A bar chart or bar graph is a chart that presents Grouped data with rectangular bars with lengths proportional to the values that they represent. +
        +
        + +
        + +
        + +
        + + +
        +
        +export class BarChartDemo {
        +
        +    data: any;
        +
        +    constructor() {
        +        this.data = {
        +            labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
        +            datasets: [
        +                {
        +                    label: 'My First dataset',
        +                    backgroundColor: '#42A5F5',
        +                    borderColor: '#1E88E5',
        +                    data: [65, 59, 80, 81, 56, 55, 40]
        +                },
        +                {
        +                    label: 'My Second dataset',
        +                    backgroundColor: '#9CCC65',
        +                    borderColor: '#7CB342',
        +                    data: [28, 48, 40, 19, 86, 27, 90]
        +                }
        +            ]
        +        }
        +    }
        +}
        +
        +
        +
        + + +
        +
        +<p-chart type="bar" [data]="data"></p-chart>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/chart/barchart/barchartdemo.ts b/src/app/showcase/components/chart/barchart/barchartdemo.ts new file mode 100644 index 00000000000..bbe45328043 --- /dev/null +++ b/src/app/showcase/components/chart/barchart/barchartdemo.ts @@ -0,0 +1,29 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './barchartdemo.html' +}) +export class BarChartDemo { + + data: any; + + constructor() { + this.data = { + labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], + datasets: [ + { + label: 'My First dataset', + backgroundColor: '#42A5F5', + borderColor: '#1E88E5', + data: [65, 59, 80, 81, 56, 55, 40] + }, + { + label: 'My Second dataset', + backgroundColor: '#9CCC65', + borderColor: '#7CB342', + data: [28, 48, 40, 19, 86, 27, 90] + } + ] + } + } +} \ No newline at end of file diff --git a/src/app/showcase/components/chart/chartdemo-routing.module.ts b/src/app/showcase/components/chart/chartdemo-routing.module.ts new file mode 100644 index 00000000000..8cc57611db1 --- /dev/null +++ b/src/app/showcase/components/chart/chartdemo-routing.module.ts @@ -0,0 +1,27 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {ChartDemo} from './chartdemo'; +import {PieChartDemo} from './piechart/piechartdemo'; +import {DoughnutChartDemo} from './doughnutchart/doughnutchartdemo'; +import {BarChartDemo} from './barchart/barchartdemo'; +import {LineChartDemo} from './linechart/linechartdemo'; +import {PolarAreaChartDemo} from './polarareachart/polarareachartdemo'; +import {RadarChartDemo} from './radarchart/radarchartdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'', component: ChartDemo}, + {path:'pie', component: PieChartDemo}, + {path:'doughnut', component: DoughnutChartDemo}, + {path:'bar', component: BarChartDemo}, + {path:'line', component: LineChartDemo}, + {path:'polararea',component: PolarAreaChartDemo}, + {path:'radar', component: RadarChartDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class ChartDemoRoutingModule {} diff --git a/src/app/showcase/components/chart/chartdemo.html b/src/app/showcase/components/chart/chartdemo.html new file mode 100644 index 00000000000..1c8dc6505fd --- /dev/null +++ b/src/app/showcase/components/chart/chartdemo.html @@ -0,0 +1,236 @@ +
        +
        + Charts + Chart components are based on Charts.js 2.1.x, an open source HTML5 based charting library. +
        +
        + +
        +

        Chart Component

        +

        Chart component is used to display a chart on page. The classname is UIChart and element tag is p-chart.

        + +

        Import

        +
        +
        +import {ChartModule} from 'primeng/primeng';
        +
        +
        + +

        Charts.js

        +

        In order for chart component to work, include charts.js to your project. An example with CLI would be;

        +
        +
        +"scripts": [
        +  "../node_modules/chart.js/dist/Chart.js",
        +  //..others
        +],
        +
        +
        + + +

        Change Detection

        +

        In order to chart to redraw itself, a new data object needs to be created. Changing the array contents without creating a new + array instance does not trigger change detection.

        +
        +
        +<p-chart type="pie" [data]="data"></p-chart>
        +<button type="button" pButton (click)="update($event)"></button>
        +
        +
        + +
        +
        +update(event: Event) {
        +    this.data = //create new data
        +}
        +
        +
        + +

        Attributes of Chart Component.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        typestringnullType of the chart.
        dataanynullData to display.
        optionsanynullOptions to customize the chart.
        widthstringnullWidth of the chart in non-responsive mode.
        heightstringnullHeight of the chart in non-responsive mode.
        onDataSelectfunctionnullCallback to execute when an element on chart is clicked.
        +
        + +

        Methods

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        refresh-Redraws the graph with new data.
        reinit-Destroys the graph first and then creates it again.
        generateLegend-Returns an HTML string of a legend for that chart. The legend is generated from the legendCallback in the options.
        +
        + +

        Chart Types

        +

        Chart type is defined using the type property. Currently there are 6 options available; pie, doughtnut, line, bar, radar and polarArea.

        + +

        Data

        +

        Data of a chart is provided using a binding to the data property, each type has its own format of data. Here is an example of a line chart.

        + +
        +
        +<p-chart type="line" [data]="data"></p-chart>
        +
        +
        + +
        +
        +export class LineChartDemo {
        +
        +    data: any;
        +    
        +    constructor() {
        +        this.data = {
        +            labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
        +            datasets: [
        +                {
        +                    label: 'First Dataset',
        +                    data: [65, 59, 80, 81, 56, 55, 40]
        +                },
        +                {
        +                    label: 'Second Dataset',
        +                    data: [28, 48, 40, 19, 86, 27, 90]
        +                }
        +            ]
        +        }
        +    }
        +}
        +
        +
        + +

        Options

        +

        While a series can be customized per dataset, general chart options are defined with options property. + Example below adds a title and customizes the legend position of the chart. For all available options refer to the charts.js documentation.

        + +
        +
        +<p-chart type="line" [data]="data" [options]="options"></p-chart>
        +
        +
        + +
        +
        +export class LineChartDemo {
        +
        +    data: any;
        +    
        +    options: any;
        +    
        +    constructor() {
        +        this.data = {
        +            labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
        +            datasets: [
        +                {
        +                    label: 'First Dataset',
        +                    data: [65, 59, 80, 81, 56, 55, 40]
        +                },
        +                {
        +                    label: 'Second Dataset',
        +                    data: [28, 48, 40, 19, 86, 27, 90]
        +                }
        +            ]
        +        }
        +        
        +        this.options = {
        +            title: {
        +                display: true,
        +                text: 'My Title',
        +                fontSize: 16
        +            },
        +            legend: {
        +                position: 'bottom'
        +            }
        +        };
        +    }
        +}
        +
        +
        + +

        Events

        +

        When data is selected with click event, chart component provides onDataSelect callback to process the selected data.

        +
        +
        +<p-chart type="line" [data]="data" (onDataSelect)="selectData($event)"></p-chart>
        +
        +
        + +
        +
        +selectData(event) {
        +    //event.dataset = Selected dataset
        +    //event.element = Selected element
        +    //event.element._datasetIndex = Index of the dataset in data
        +    //event.element._index = Index of the data in dataset
        +}
        +
        +
        + + +
        diff --git a/src/app/showcase/components/chart/chartdemo.module.ts b/src/app/showcase/components/chart/chartdemo.module.ts new file mode 100644 index 00000000000..c20f4a52783 --- /dev/null +++ b/src/app/showcase/components/chart/chartdemo.module.ts @@ -0,0 +1,35 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {ChartDemoRoutingModule} from './chartdemo-routing.module'; +import {ChartDemo} from './chartdemo'; +import {PieChartDemo} from './piechart/piechartdemo'; +import {DoughnutChartDemo} from './doughnutchart/doughnutchartdemo'; +import {BarChartDemo} from './barchart/barchartdemo'; +import {LineChartDemo} from './linechart/linechartdemo'; +import {PolarAreaChartDemo} from './polarareachart/polarareachartdemo'; +import {RadarChartDemo} from './radarchart/radarchartdemo'; +import {ChartModule} from '../../../components/chart/chart'; +import {GrowlModule} from '../../../components/growl/growl'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + ChartDemoRoutingModule, + ChartModule, + GrowlModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + ChartDemo, + PieChartDemo, + DoughnutChartDemo, + BarChartDemo, + LineChartDemo, + PolarAreaChartDemo, + RadarChartDemo + ] +}) +export class ChartDemoModule {} diff --git a/src/app/showcase/components/chart/chartdemo.ts b/src/app/showcase/components/chart/chartdemo.ts new file mode 100644 index 00000000000..584d8929e8a --- /dev/null +++ b/src/app/showcase/components/chart/chartdemo.ts @@ -0,0 +1,8 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './chartdemo.html' +}) +export class ChartDemo { + +} \ No newline at end of file diff --git a/src/app/showcase/components/chart/doughnutchart/doughnutchartdemo.html b/src/app/showcase/components/chart/doughnutchart/doughnutchartdemo.html new file mode 100644 index 00000000000..6c5c335cfe4 --- /dev/null +++ b/src/app/showcase/components/chart/doughnutchart/doughnutchartdemo.html @@ -0,0 +1,53 @@ +
        +
        + DoughnutChart + A doughnut chart is a variant of the pie chart, with a blank center allowing for additional information about the data as a whole to be included. +
        +
        + +
        + +
        + +
        + + +
        +
        +export class DoughnutChartDemo {
        +
        +    data: any;
        +
        +    constructor() {
        +        this.data = {
        +            labels: ['A','B','C'],
        +            datasets: [
        +                {
        +                    data: [300, 50, 100],
        +                    backgroundColor: [
        +                        "#FF6384",
        +                        "#36A2EB",
        +                        "#FFCE56"
        +                    ],
        +                    hoverBackgroundColor: [
        +                        "#FF6384",
        +                        "#36A2EB",
        +                        "#FFCE56"
        +                    ]
        +                }]    
        +            };
        +    }
        +}
        +
        +
        +
        + + +
        +
        +<p-chart type="doughnut" [data]="data"></p-chart>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/chart/doughnutchart/doughnutchartdemo.ts b/src/app/showcase/components/chart/doughnutchart/doughnutchartdemo.ts new file mode 100644 index 00000000000..9e3e3739b46 --- /dev/null +++ b/src/app/showcase/components/chart/doughnutchart/doughnutchartdemo.ts @@ -0,0 +1,29 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './doughnutchartdemo.html' +}) +export class DoughnutChartDemo { + + data: any; + + constructor() { + this.data = { + labels: ['A','B','C'], + datasets: [ + { + data: [300, 50, 100], + backgroundColor: [ + "#FF6384", + "#36A2EB", + "#FFCE56" + ], + hoverBackgroundColor: [ + "#FF6384", + "#36A2EB", + "#FFCE56" + ] + }] + }; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/chart/linechart/linechartdemo.html b/src/app/showcase/components/chart/linechart/linechartdemo.html new file mode 100644 index 00000000000..1fe5ca840ee --- /dev/null +++ b/src/app/showcase/components/chart/linechart/linechartdemo.html @@ -0,0 +1,64 @@ +
        +
        + LineChart + A line chart or line graph is a type of chart which displays information as a series of data points called 'markers' connected by straight line segments. +
        +
        + +
        + + + +
        + +
        + + +
        +
        +export class LineChartDemo {
        +
        +    data: any;
        +    
        +    msgs: Message[];
        +
        +    constructor() {
        +        this.data = {
        +            labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
        +            datasets: [
        +                {
        +                    label: 'First Dataset',
        +                    data: [65, 59, 80, 81, 56, 55, 40],
        +                    fill: false,
        +                    borderColor: '#4bc0c0'
        +                },
        +                {
        +                    label: 'Second Dataset',
        +                    data: [28, 48, 40, 19, 86, 27, 90],
        +                    fill: false,
        +                    borderColor: '#565656'
        +                }
        +            ]
        +        }
        +    }
        +
        +    selectData(event) {
        +        this.msgs = [];
        +        this.msgs.push({severity: 'info', summary: 'Data Selected', 'detail': this.data.datasets[event.element._datasetIndex].data[event.element._index]});
        +    }
        +}
        +
        +
        +
        + + +
        +
        +<p-growl [value]="msgs"></p-growl>
        +
        +<p-chart type="line" [data]="data" (onDataSelect)="selectData($event)"></p-chart>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/chart/linechart/linechartdemo.ts b/src/app/showcase/components/chart/linechart/linechartdemo.ts new file mode 100644 index 00000000000..61e758697a4 --- /dev/null +++ b/src/app/showcase/components/chart/linechart/linechartdemo.ts @@ -0,0 +1,37 @@ +import {Component} from '@angular/core'; +import {Message} from '../../../../components/common/api'; + +@Component({ + templateUrl: './linechartdemo.html' +}) +export class LineChartDemo { + + data: any; + + msgs: Message[]; + + constructor() { + this.data = { + labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], + datasets: [ + { + label: 'First Dataset', + data: [65, 59, 80, 81, 56, 55, 40], + fill: false, + borderColor: '#4bc0c0' + }, + { + label: 'Second Dataset', + data: [28, 48, 40, 19, 86, 27, 90], + fill: false, + borderColor: '#565656' + } + ] + } + } + + selectData(event) { + this.msgs = []; + this.msgs.push({severity: 'info', summary: 'Data Selected', 'detail': this.data.datasets[event.element._datasetIndex].data[event.element._index]}); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/chart/piechart/piechartdemo.html b/src/app/showcase/components/chart/piechart/piechartdemo.html new file mode 100644 index 00000000000..38f170f37db --- /dev/null +++ b/src/app/showcase/components/chart/piechart/piechartdemo.html @@ -0,0 +1,53 @@ +
        +
        + PieChart + A pie chart is a circular statistical graphic, which is divided into slices to illustrate numerical proportion. +
        +
        + +
        + +
        + +
        + + +
        +
        +export class PieChartDemo {
        +
        +    data: any;
        +
        +    constructor() {
        +        this.data = {
        +            labels: ['A','B','C'],
        +            datasets: [
        +                {
        +                    data: [300, 50, 100],
        +                    backgroundColor: [
        +                        "#FF6384",
        +                        "#36A2EB",
        +                        "#FFCE56"
        +                    ],
        +                    hoverBackgroundColor: [
        +                        "#FF6384",
        +                        "#36A2EB",
        +                        "#FFCE56"
        +                    ]
        +                }]    
        +            };
        +    }
        +}
        +
        +
        +
        + + +
        +
        +<p-chart type="pie" [data]="data"></p-chart>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/chart/piechart/piechartdemo.ts b/src/app/showcase/components/chart/piechart/piechartdemo.ts new file mode 100644 index 00000000000..71edcc25a99 --- /dev/null +++ b/src/app/showcase/components/chart/piechart/piechartdemo.ts @@ -0,0 +1,29 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './piechartdemo.html' +}) +export class PieChartDemo { + + data: any; + + constructor() { + this.data = { + labels: ['A','B','C'], + datasets: [ + { + data: [300, 50, 100], + backgroundColor: [ + "#FF6384", + "#36A2EB", + "#FFCE56" + ], + hoverBackgroundColor: [ + "#FF6384", + "#36A2EB", + "#FFCE56" + ] + }] + }; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/chart/polarareachart/polarareachartdemo.html b/src/app/showcase/components/chart/polarareachart/polarareachartdemo.html new file mode 100644 index 00000000000..55819b4531e --- /dev/null +++ b/src/app/showcase/components/chart/polarareachart/polarareachartdemo.html @@ -0,0 +1,62 @@ +
        +
        + PolarAreaChart + Polar area charts are similar to pie charts, but each segment has the same angle - the radius of the segment differs depending on the value. +
        +
        + +
        + +
        + +
        + + +
        +
        +export class PolarAreaChartDemo {
        +
        +    data: any;
        +
        +    constructor() {
        +        this.data = {
        +            datasets: [{
        +                data: [
        +                    11,
        +                    16,
        +                    7,
        +                    3,
        +                    14
        +                ],
        +                backgroundColor: [
        +                    "#FF6384",
        +                    "#4BC0C0",
        +                    "#FFCE56",
        +                    "#E7E9ED",
        +                    "#36A2EB"
        +                ],
        +                label: 'My dataset'
        +            }],
        +            labels: [
        +                "Red",
        +                "Green",
        +                "Yellow",
        +                "Grey",
        +                "Blue"
        +            ]
        +        }
        +    }
        +}
        +
        +
        +
        + + +
        +
        +<p-chart type="polarArea" [data]="data"></p-chart>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/chart/polarareachart/polarareachartdemo.ts b/src/app/showcase/components/chart/polarareachart/polarareachartdemo.ts new file mode 100644 index 00000000000..f9c837a8809 --- /dev/null +++ b/src/app/showcase/components/chart/polarareachart/polarareachartdemo.ts @@ -0,0 +1,38 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './polarareachartdemo.html' +}) +export class PolarAreaChartDemo { + + data: any; + + constructor() { + this.data = { + datasets: [{ + data: [ + 11, + 16, + 7, + 3, + 14 + ], + backgroundColor: [ + "#FF6384", + "#4BC0C0", + "#FFCE56", + "#E7E9ED", + "#36A2EB" + ], + label: 'My dataset' + }], + labels: [ + "Red", + "Green", + "Yellow", + "Grey", + "Blue" + ] + } + } +} \ No newline at end of file diff --git a/src/app/showcase/components/chart/radarchart/radarchartdemo.html b/src/app/showcase/components/chart/radarchart/radarchartdemo.html new file mode 100644 index 00000000000..094e3762b0a --- /dev/null +++ b/src/app/showcase/components/chart/radarchart/radarchartdemo.html @@ -0,0 +1,61 @@ +
        +
        + RadarChart + A radar chart is a graphical method of displaying multivariate data in the form of a two-dimensional chart of three or more quantitative variables represented on axes starting from the same point. +
        +
        + +
        + +
        + +
        + + +
        +
        +export class RadarChartDemo {
        +
        +    data: any;
        +
        +    constructor() {
        +        this.data = {
        +            labels: ['Eating', 'Drinking', 'Sleeping', 'Designing', 'Coding', 'Cycling', 'Running'],
        +            datasets: [
        +                {
        +                    label: 'My First dataset',
        +                    backgroundColor: 'rgba(179,181,198,0.2)',
        +                    borderColor: 'rgba(179,181,198,1)',
        +                    pointBackgroundColor: 'rgba(179,181,198,1)',
        +                    pointBorderColor: '#fff',
        +                    pointHoverBackgroundColor: '#fff',
        +                    pointHoverBorderColor: 'rgba(179,181,198,1)',
        +                    data: [65, 59, 90, 81, 56, 55, 40]
        +                },
        +                {
        +                    label: 'My Second dataset',
        +                    backgroundColor: 'rgba(255,99,132,0.2)',
        +                    borderColor: 'rgba(255,99,132,1)',
        +                    pointBackgroundColor: 'rgba(255,99,132,1)',
        +                    pointBorderColor: '#fff',
        +                    pointHoverBackgroundColor: '#fff',
        +                    pointHoverBorderColor: 'rgba(255,99,132,1)',
        +                    data: [28, 48, 40, 19, 96, 27, 100]
        +                }
        +            ]
        +        };
        +    }
        +}
        +
        +
        +
        + + +
        +
        +<p-chart type="radar" [data]="data"></p-chart>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/chart/radarchart/radarchartdemo.ts b/src/app/showcase/components/chart/radarchart/radarchartdemo.ts new file mode 100644 index 00000000000..0e57b34fd3c --- /dev/null +++ b/src/app/showcase/components/chart/radarchart/radarchartdemo.ts @@ -0,0 +1,38 @@ +import {Component} from '@angular/core'; +import {Message} from '../../../../components/common/api'; + +@Component({ + templateUrl: './radarchartdemo.html' +}) +export class RadarChartDemo { + + data: any; + + constructor() { + this.data = { + labels: ['Eating', 'Drinking', 'Sleeping', 'Designing', 'Coding', 'Cycling', 'Running'], + datasets: [ + { + label: 'My First dataset', + backgroundColor: 'rgba(179,181,198,0.2)', + borderColor: 'rgba(179,181,198,1)', + pointBackgroundColor: 'rgba(179,181,198,1)', + pointBorderColor: '#fff', + pointHoverBackgroundColor: '#fff', + pointHoverBorderColor: 'rgba(179,181,198,1)', + data: [65, 59, 90, 81, 56, 55, 40] + }, + { + label: 'My Second dataset', + backgroundColor: 'rgba(255,99,132,0.2)', + borderColor: 'rgba(255,99,132,1)', + pointBackgroundColor: 'rgba(255,99,132,1)', + pointBorderColor: '#fff', + pointHoverBackgroundColor: '#fff', + pointHoverBorderColor: 'rgba(255,99,132,1)', + data: [28, 48, 40, 19, 96, 27, 100] + } + ] + }; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/checkbox/checkboxdemo-routing.module.ts b/src/app/showcase/components/checkbox/checkboxdemo-routing.module.ts new file mode 100644 index 00000000000..2ea281955e4 --- /dev/null +++ b/src/app/showcase/components/checkbox/checkboxdemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {CheckboxDemo} from './checkboxdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: CheckboxDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class CheckboxDemoRoutingModule {} diff --git a/src/app/showcase/components/checkbox/checkboxdemo.html b/src/app/showcase/components/checkbox/checkboxdemo.html new file mode 100644 index 00000000000..12b6a4807bb --- /dev/null +++ b/src/app/showcase/components/checkbox/checkboxdemo.html @@ -0,0 +1,276 @@ +
        +
        + Checkbox + Checkbox is an extension to standard checkbox element with skinning capabilities. +
        +
        + +
        +

        Basic

        +
        +
        +
        +
        +
        + + Selected Cities: {{city}} + +

        Preselection

        +
        +
        +
        +
        +
        +
        + + Selected Categories: {{cat}} + +

        Boolean - {{checked}}

        + +
        + +
        + + +

        Import

        +
        +
        +import {CheckboxModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Checkbox can either be used in multiple selection with other checkboxes or as a single checkbox to provide a boolean value.

        + +

        Multiple Values

        +

        Multiple mode is enabled by default, ngModel property refers to an array to bind the selected values.

        +
        +
        +<p-checkbox name="groupname" value="val1" [(ngModel)]="selectedValues"></p-checkbox>
        +<p-checkbox name="groupname" value="val2" [(ngModel)]="selectedValues"></p-checkbox>
        +
        +
        + +
        +
        +export class ModelComponent {
        +
        +    selectedValues: string[] = [];
        +
        +}
        +
        +
        + +

        As ngModel is two-way binding enabled, prepopulating the model array with values is enough to display the related + checkboxes as checked by default.

        +
        +
        +export class ModelComponent {
        +
        +    selectedValues: string[] = ['val1','val2'];
        +
        +}
        +
        +
        + +

        Label

        +

        The label attribute provides a label text for the checkbox. This label is also clickable and toggles the checked state.

        +
        +
        +<p-checkbox name="groupname" value="val1" label="Value 1" [(ngModel)]="selectedValues"></p-checkbox>
        +<p-checkbox name="groupname" value="val2" label="Value 2" [(ngModel)]="selectedValues"></p-checkbox>
        +
        +
        + +

        Boolean Value

        +

        A single boolean value can be bound using the ngModel property as well by enabling the binary option.

        +
        +
        +export class ModelComponent {
        +
        +    value: boolean;
        +
        +}
        +
        +
        + +
        +
        +<p-checkbox [(ngModel)]="value" binary="true"></p-checkbox>
        +
        +
        + +

        Model Driven Forms

        +

        Checkbox can be used in a model driven form as well.

        +
        +
        +<p-checkbox formControlName="agreed"></p-checkbox>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        namestringnullName of the checkbox group.
        valueanynullValue of the checkbox.
        labelstringnullLabel of the checkbox.
        disabledbooleanfalseWhen present, it specifies that the element should be disabled.
        binarybooleanfalseAllows to select a boolean value instead of multiple values.
        tabindexnumbernullIndex of the element in tabbing order.
        inputIdstringnullIdentifier of the focus input to match a label defined for the component.
        styleobjectnullInline style of the component.
        styleClassstringnullStyle class of the component.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + +
        NameParametersDescription
        onChangechecked: Boolean value to represent new state of checkbox.Callback to invoke on checkbox click.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-chkboxContainer element
        ui-chkbox-boxContainer of icon.
        ui-chkbox-iconIcon element.
        ui-chkbox-labelLabel element.
        +
        + +

        Dependencies

        +

        None.

        +
        + +
        +
        +<h3 class="first">Basic</h3>
        +<div class="ui-g" style="width:250px;margin-bottom:10px">
        +    <div class="ui-g-12"><p-checkbox name="group1" value="New York" label="New York" [(ngModel)]="selectedCities"></p-checkbox></div>
        +    <div class="ui-g-12"><p-checkbox name="group1" value="San Francisco" label="San Francisco" [(ngModel)]="selectedCities"></p-checkbox></div>
        +    <div class="ui-g-12"><p-checkbox name="group1" value="Los Angeles" label="Los Angeles" [(ngModel)]="selectedCities"></p-checkbox></div>
        +</div>
        +
        +Selected Cities: <span *ngFor="let city of selectedCities" style="margin-right:10px">{{city}}</span>
        +
        +<h3>Preselection</h3>
        +<div class="ui-g" style="width:250px;margin-bottom:10px">
        +    <div class="ui-g-12"><p-checkbox name="group2" value="Technology" label="Technology" [(ngModel)]="selectedCategories"></p-checkbox></div>
        +    <div class="ui-g-12"><p-checkbox name="group2" value="Finance" label="Finance" [(ngModel)]="selectedCategories"></p-checkbox></div>
        +    <div class="ui-g-12"><p-checkbox name="group2" value="Sports" label="Sports" [(ngModel)]="selectedCategories"></p-checkbox></div>
        +    <div class="ui-g-12"><p-checkbox name="group2" value="Entertainment" label="Entertainment" [(ngModel)]="selectedCategories"></p-checkbox></div>
        +</div>
        +
        +Selected Categories: <span *ngFor="let cat of selectedCategories" style="margin-right:10px">{{cat}} </span>
        +
        +<h3>Boolean - {{checked}}</h3>
        +<p-checkbox [(ngModel)]="checked" binary="true"></p-checkbox>
        +
        +
        + +
        +
        +export class CheckboxDemo {
        +
        +    selectedCities: string[] = [];
        +
        +    selectedCategories: string[] = ['Technology', 'Sports'];
        +
        +    checked: boolean = false;
        +}
        +
        +
        +
        +
        +
        diff --git a/src/app/showcase/components/checkbox/checkboxdemo.module.ts b/src/app/showcase/components/checkbox/checkboxdemo.module.ts new file mode 100644 index 00000000000..149d34ee6c3 --- /dev/null +++ b/src/app/showcase/components/checkbox/checkboxdemo.module.ts @@ -0,0 +1,23 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {CheckboxDemo} from './checkboxdemo'; +import {CheckboxDemoRoutingModule} from './checkboxdemo-routing.module'; +import {CheckboxModule} from '../../../components/checkbox/checkbox'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + CheckboxDemoRoutingModule, + CheckboxModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + CheckboxDemo + ] +}) +export class CheckboxDemoModule {} diff --git a/src/app/showcase/components/checkbox/checkboxdemo.ts b/src/app/showcase/components/checkbox/checkboxdemo.ts new file mode 100644 index 00000000000..35e3715e8ae --- /dev/null +++ b/src/app/showcase/components/checkbox/checkboxdemo.ts @@ -0,0 +1,24 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './checkboxdemo.html', + styles: [` + .ui-grid .ui-grid-col-1, + .ui-grid .ui-grid-col-11 { + padding: 4px 10px; + } + + .ui-grid label { + display: block; + margin: 2px 0 0 4px; + } + `] +}) +export class CheckboxDemo { + + selectedCities: string[] = []; + + selectedCategories: string[] = ['Technology', 'Sports']; + + checked: boolean = false; +} \ No newline at end of file diff --git a/src/app/showcase/components/chips/chipsdemo-routing.module.ts b/src/app/showcase/components/chips/chipsdemo-routing.module.ts new file mode 100644 index 00000000000..be9ef482643 --- /dev/null +++ b/src/app/showcase/components/chips/chipsdemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {ChipsDemo} from './chipsdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: ChipsDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class ChipsDemoRoutingModule {} diff --git a/src/app/showcase/components/chips/chipsdemo.html b/src/app/showcase/components/chips/chipsdemo.html new file mode 100644 index 00000000000..029152bd195 --- /dev/null +++ b/src/app/showcase/components/chips/chipsdemo.html @@ -0,0 +1,225 @@ +
        +
        + Chips + Chips is used to enter multiple values on an inputfield. +
        +
        + +
        +

        Basic

        + + +

        Template

        + + + {{item}} - (active) + + +
        + +
        + + +

        Import

        +
        +
        +import {ChipsModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Chips requires an array as its model.

        +
        +
        +<p-chips [(ngModel)]="values"></p-chips>
        +
        +
        + +
        +
        +export class MyModel {
        +
        +    values: string[];
        +
        +}
        +
        +
        +

        Model Driven Forms

        +

        Chips can be used in a model driven form as well.

        +
        +
        +<p-chips formControlName="cities"></p-chips>
        +
        +
        + +

        Custom Content

        +

        A chip is customized using a ng-template element where the value is passed as the implicit variable.

        +
        +
        +<p-chips [(ngModel)]="values">
        +    <ng-template let-item pTemplate="item">
        +        {{item}} - (active) <i class="fa fa-user"></i>
        +    </ng-template>
        +</p-chips>
        +
        +
        +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        fieldstringnullName of the property to display on a chip.
        maxnumbernullMaximum number of entries allowed.
        disabledbooleanfalseWhen present, it specifies that the element should be disabled.
        stylestringnullInline style of the element.
        styleClassstringnullStyle class of the element.
        placeholderstringnullAdvisory information to display on input.
        tabindexnumbernullIndex of the element in tabbing order.
        inputIdstringnullIdentifier of the focus input to match a label defined for the component.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onAddoriginalEvent: Browser event
        + value: Added item value +
        Callback to invoke when a value is added.
        onRemoveoriginalEvent: Browser event
        + value: Added item value +
        Callback to invoke when a value is removed.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-chipsContainer element.
        ui-chips-tokenChip element container.
        ui-chips-token-iconIcon of a chip.
        ui-chips-token-labelLabel of a chip.
        ui-chips-input-tokenContainer of input element.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<h3 class="first">Basic</h3>
        +<p-chips [(ngModel)]="values1" ></p-chips>
        +
        +<h3>ng-template</h3>
        +<p-chips [(ngModel)]="values2">
        +    <ng-template let-item pTemplate="item">
        +        {{item}} - (active) <i class="fa fa-user" style="margin-right:2em"></i>
        +    </ng-template>
        +</p-chips>
        +
        +
        + +
        +
        +export class ChipsDemo {
        +
        +    values1: string[];
        +    
        +    values2: string[];
        +}
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/chips/chipsdemo.module.ts b/src/app/showcase/components/chips/chipsdemo.module.ts new file mode 100644 index 00000000000..9541beb8ae4 --- /dev/null +++ b/src/app/showcase/components/chips/chipsdemo.module.ts @@ -0,0 +1,25 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {ChipsDemo} from './chipsdemo'; +import {ChipsDemoRoutingModule} from './chipsdemo-routing.module'; +import {ChipsModule} from '../../../components/chips/chips'; +import {ButtonModule} from '../../../components/button/button'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + ChipsDemoRoutingModule, + ChipsModule, + ButtonModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + ChipsDemo + ] +}) +export class ChipsDemoModule {} diff --git a/src/app/showcase/components/chips/chipsdemo.ts b/src/app/showcase/components/chips/chipsdemo.ts new file mode 100644 index 00000000000..ffe9f2a75c6 --- /dev/null +++ b/src/app/showcase/components/chips/chipsdemo.ts @@ -0,0 +1,11 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './chipsdemo.html' +}) +export class ChipsDemo { + + values1: string[]; + + values2: string[]; +} \ No newline at end of file diff --git a/src/app/showcase/components/codehighlighter/codehighlighterdemo-routing.module.ts b/src/app/showcase/components/codehighlighter/codehighlighterdemo-routing.module.ts new file mode 100644 index 00000000000..5bf9a4b502d --- /dev/null +++ b/src/app/showcase/components/codehighlighter/codehighlighterdemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {CodeHighlighterDemo} from './codehighlighterdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: CodeHighlighterDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class CodeHighlighterDemoRoutingModule {} diff --git a/src/app/showcase/components/codehighlighter/codehighlighterdemo.html b/src/app/showcase/components/codehighlighter/codehighlighterdemo.html new file mode 100644 index 00000000000..0561e34744e --- /dev/null +++ b/src/app/showcase/components/codehighlighter/codehighlighterdemo.html @@ -0,0 +1,110 @@ +
        +
        + CodeHighlighter + CodeHighlighter is an attribute directive to highlight code blocks using PrismJS +
        +
        + +
        +

        CSS

        +
        +
        +.ui-datatable table {
        +    border-collapse:collapse;
        +    width: 100%;
        +    table-layout: fixed;
        +}
        +
        +
        + +

        HTML

        +
        +
        +<div id="pm" style="width:300px">
        +<div>
        +<div><a data-icon="fa-file-o">File</a></div>
        +<div>
        +    <ul>
        +        <li><a data-icon="fa-plus">New</a>
        +            <ul>
        +                <li><a>Project</a></li>
        +                <li><a>Other</a></li>
        +            </ul>
        +        </li>
        +        <li><a>Open</a></li>
        +        <li><a>Quit</a></li>
        +    </ul>
        +</div>
        +</div>
        +</div>
        +
        +
        + +

        Javascript

        +
        +
        +var map;
        +    function initMap() {
        +        map = new google.maps.Map(document.getElementById('map'), {
        +        center: {lat: -34.397, lng: 150.644},
        +        zoom: 8
        +    });
        +}
        +
        +
        + +

        Typescript

        +
        +
        +import {Directive, ElementRef, OnInit} from '@angular/core';
        +
        +declare var Prism: any;
        +
        +@Directive({
        +    selector: '[pCode]'
        +})
        +export class CodeHighlighter implements OnInit {
        +
        +    constructor(private el: ElementRef) {}
        +
        +    ngOnInit() {
        +        Prism.highlightElement(this.el.nativeElement);
        +    }
        +}
        +
        +
        +
        + +
        + + +

        Import

        +
        +
        +import {CodeHighlighterModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        CodeHighlighter is applied to a code element with [pCode] directive. The <code> should have + a style class having language- prefix to specify the language to highlight. See Prismjs docs for the list of available languages. + An example block with css code would be as follows.

        + +
        +
        +<pre>
        +<code class="language-css" pCode>
        +    .ui-datatable table {
        +    border-collapse:collapse;
        +    width: 100%;
        +    table-layout: fixed;
        +}
        +</code>
        +</pre>
        +
        +
        +

        Dependencies

        +

        Prismjs

        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/codehighlighter/codehighlighterdemo.module.ts b/src/app/showcase/components/codehighlighter/codehighlighterdemo.module.ts new file mode 100644 index 00000000000..d1ca07737a1 --- /dev/null +++ b/src/app/showcase/components/codehighlighter/codehighlighterdemo.module.ts @@ -0,0 +1,19 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {CodeHighlighterDemo} from './codehighlighterdemo'; +import {CodeHighlighterDemoRoutingModule} from './codehighlighterdemo-routing.module'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; +import {TabViewModule} from '../../../components/tabview/tabview'; + +@NgModule({ + imports: [ + CommonModule, + CodeHighlighterDemoRoutingModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + CodeHighlighterDemo + ] +}) +export class CodeHighlighterDemoModule {} diff --git a/src/app/showcase/components/codehighlighter/codehighlighterdemo.ts b/src/app/showcase/components/codehighlighter/codehighlighterdemo.ts new file mode 100644 index 00000000000..96f6e657247 --- /dev/null +++ b/src/app/showcase/components/codehighlighter/codehighlighterdemo.ts @@ -0,0 +1,8 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './codehighlighterdemo.html' +}) +export class CodeHighlighterDemo { + +} \ No newline at end of file diff --git a/src/app/showcase/components/confirmdialog/confirmdialogdemo-routing.module.ts b/src/app/showcase/components/confirmdialog/confirmdialogdemo-routing.module.ts new file mode 100644 index 00000000000..f755cc35fc6 --- /dev/null +++ b/src/app/showcase/components/confirmdialog/confirmdialogdemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {ConfirmDialogDemo} from './confirmdialogdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: ConfirmDialogDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class ConfirmDialogDemoRoutingModule {} diff --git a/src/app/showcase/components/confirmdialog/confirmdialogdemo.html b/src/app/showcase/components/confirmdialog/confirmdialogdemo.html new file mode 100644 index 00000000000..8ae47a478bd --- /dev/null +++ b/src/app/showcase/components/confirmdialog/confirmdialogdemo.html @@ -0,0 +1,346 @@ +
        +
        + ConfirmDialog + ConfirmDialog is backed by a service utilizing Observables to display confirmation windows + easily that can be shared by multiple actions on the same component. +
        +
        + +
        + + + + + + + +
        + +
        + + +

        Import

        +
        +
        +import {ConfirmDialogModule,ConfirmationService} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        ConfirmDialog is defined using p-confirmDialog tag and an instance of ConfirmationService is required to display it by + calling confirm method.

        + +
        +
        +<p-confirmDialog header="Confirmation" icon="fa fa-question-circle" width="425"></p-confirmDialog>
        +
        +<button type="text" (click)="confirm()" pButton icon="fa-check" label="Confirm"></button>
        +
        +
        + +
        +
        +export class ConfirmDialogDemo { 
        +           
        +    constructor(private confirmationService: ConfirmationService) {}
        +
        +    confirm() {
        +        this.confirmationService.confirm({
        +            message: 'Are you sure that you want to perform this action?',
        +            accept: () => {
        +                //Actual logic to perform a confirmation
        +            }
        +        });
        +    }
        +}
        +
        +
        + +

        Confirm method takes a confirmation instance used to customize the dialog UI along with accept and reject actions.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        messagestringnullMessage of the confirmation.
        keystringnullOptional key to match the key of the confirm dialog, necessary to use when component tree has multiple confirm dialogs.
        headerstringnullHeader text of the dialog.
        iconstringnullIcon to display next to the message.
        acceptFunctionnullCallback to execute when action is confirmed.
        rejectFunctionnullCallback to execute when action is rejected.
        +
        + +

        Customization

        +

        Properties of the dialog are defined in two ways, message, icon and header properties can either + be defined using confirm method or declaratively on p-confirmDialog ng-template. If these values are unlikely to change then + declarative approach would be useful, still properties defined in a ng-template can be overriden with confirm method call.

        + +

        In addition, buttons at footer section can be customized by passing your own UI, important note to make confirmation work with + a custom UI is defining a local ng-template variable for the dialog and assign accept()-reject() methods to your own buttons.

        + +
        +
        +<p-confirmDialog header="Confirmation" icon="fa fa-question-circle" width="425" #cd>
        +    <p-footer>
        +        <button type="button" pButton icon="fa-close" label="No" (click)="cd.reject()"></button>
        +        <button type="button" pButton icon="fa-check" label="Yes" (click)="cd.accept()"></button>
        +    </p-footer>
        +</p-confirmDialog>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        headerstringnullTitle text of the dialog.
        messagestringnullMessage of the confirmation.
        keystringnullOptional key to match the key of confirm object, necessary to use when component tree has multiple confirm dialogs.
        iconstringnullIcon to display next to message.
        acceptLabelstringYesLabel of the accept button.
        acceptIconstringfa-checkIcon of the accept button.
        acceptVisiblebooleantrueVisibility of the accept button.
        rejectLabelstringNoLabel of the reject button.
        rejectIconstringfa-closeIcon of the reject button.
        rejectVisiblebooleantrueVisibility of the reject button.
        widthint300Width of the dialog.
        heightintautoHeight of the dialog.
        closeOnEscapebooleantrueSpecifices if pressing escape key should hide the dialog.
        rtlbooleanfalseWhen enabled dialog is displayed in RTL direction.
        closablebooleantrueAdds a close icon to the header to hide the dialog.
        responsivebooleantrueIn responsive mode, dialog adjusts itself to screen width.
        appendToanynullTarget element to attach the dialog, valid values are "body" or a local ng-template variable of another element.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-dialogContainer element
        ui-confirmdialogContainer element
        ui-dialog-titlebarContainer of header.
        ui-dialog-titleHeader element.
        ui-dialog-titlebar-iconIcon container inside header.
        ui-dialog-titlebar-closeClose icon element.
        ui-dialog-contentContent element.
        +
        + +

        Dependencies

        +

        ConfirmationService

        +
        + + +
        +
        +<p-growl [value]="msgs"></p-growl>
        +    
        +<p-confirmDialog width="425"></p-confirmDialog>
        +
        +<button type="button" (click)="confirm1()" pButton icon="fa-check" label="Confirm"></button>
        +
        +<button type="button" (click)="confirm2()" pButton icon="fa-trash" label="Delete"></button>
        +
        +
        + +
        +
        +@Component({
        +    templateUrl: 'showcase/demo/confirmdialog/confirmdialogdemo.html',
        +    providers: [ConfirmationService]
        +})
        +export class ConfirmDialogDemo {
        +    
        +    msgs: Message[] = [];
        +    
        +    constructor(private confirmationService: ConfirmationService) {}
        +
        +    confirm1() {
        +        this.confirmationService.confirm({
        +            message: 'Are you sure that you want to perform this action?',
        +            accept: () => {
        +                this.msgs = [];
        +                this.msgs.push({severity:'info', summary:'Confirmed', detail:'You have accepted'});
        +            }
        +        });
        +    }
        +    
        +    confirm2() {
        +        this.confirmationService.confirm({
        +            message: 'Do you want to delete this record?',
        +            header: 'Delete Confirmation',
        +            icon: 'fa fa-trash',
        +            accept: () => {
        +                this.msgs = [];
        +                this.msgs.push({severity:'info', summary:'Confirmed', detail:'Record deleted'});
        +            }
        +        });
        +    }
        +}
        +
        +
        +
        +
        +
        diff --git a/src/app/showcase/components/confirmdialog/confirmdialogdemo.module.ts b/src/app/showcase/components/confirmdialog/confirmdialogdemo.module.ts new file mode 100644 index 00000000000..a2e4a37a8e0 --- /dev/null +++ b/src/app/showcase/components/confirmdialog/confirmdialogdemo.module.ts @@ -0,0 +1,25 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {ConfirmDialogDemo} from './confirmdialogdemo'; +import {ConfirmDialogDemoRoutingModule} from './confirmdialogdemo-routing.module'; +import {ConfirmDialogModule} from '../../../components/confirmdialog/confirmdialog'; +import {ButtonModule} from '../../../components/button/button'; +import {GrowlModule} from '../../../components/growl/growl'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + ConfirmDialogDemoRoutingModule, + ConfirmDialogModule, + ButtonModule, + GrowlModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + ConfirmDialogDemo + ] +}) +export class ConfirmDialogDemoModule {} diff --git a/src/app/showcase/components/confirmdialog/confirmdialogdemo.ts b/src/app/showcase/components/confirmdialog/confirmdialogdemo.ts new file mode 100644 index 00000000000..fc9a7c6273f --- /dev/null +++ b/src/app/showcase/components/confirmdialog/confirmdialogdemo.ts @@ -0,0 +1,38 @@ +import {Component} from '@angular/core'; +import {ConfirmationService} from '../../../components/common/api'; +import {Message} from '../../../components/common/api'; + +@Component({ + templateUrl: './confirmdialogdemo.html', + providers: [ConfirmationService] +}) +export class ConfirmDialogDemo { + + msgs: Message[] = []; + + constructor(private confirmationService: ConfirmationService) {} + + confirm1() { + this.confirmationService.confirm({ + message: 'Are you sure that you want to perform this action?', + header: 'Confirmation', + icon: 'fa fa-question-circle', + accept: () => { + this.msgs = []; + this.msgs.push({severity:'info', summary:'Confirmed', detail:'You have accepted'}); + } + }); + } + + confirm2() { + this.confirmationService.confirm({ + message: 'Do you want to delete this record?', + header: 'Delete Confirmation', + icon: 'fa fa-trash', + accept: () => { + this.msgs = []; + this.msgs.push({severity:'info', summary:'Confirmed', detail:'Record deleted'}); + } + }); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/contextmenu/contextmenudemo-routing.module.ts b/src/app/showcase/components/contextmenu/contextmenudemo-routing.module.ts new file mode 100644 index 00000000000..3acfc335fb0 --- /dev/null +++ b/src/app/showcase/components/contextmenu/contextmenudemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {ContextMenuDemo} from './contextmenudemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: ContextMenuDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class ContextMenuDemoRoutingModule {} diff --git a/src/app/showcase/components/contextmenu/contextmenudemo.html b/src/app/showcase/components/contextmenu/contextmenudemo.html new file mode 100644 index 00000000000..16ab2fd9886 --- /dev/null +++ b/src/app/showcase/components/contextmenu/contextmenudemo.html @@ -0,0 +1,324 @@ +
        +
        + ContextMenu + ContextMenu displays an overlay menu on right click of its target. This page has two menus, one for the document and one for the image. Note that + components like DataTable has special integration with ContextMenu. Refer to documentation of the individual documentation of the components having a special integration. +
        +
        + +
        + + + + + Logo +
        + +
        + + +

        Import

        +
        +
        +import {ContextMenuModule,MenuItem} from 'primeng/primeng';
        +
        +
        + +

        MenuModel API

        +

        ContextMenu uses the common menumodel api to define its items, visit MenuModel API for details.

        + +

        Getting Started

        +

        ContextMenu requires nested menuitems as its model and in its simplest form ContextMenu is attached to the document with global setting. .

        +
        +
        +<p-contextMenu [global]="true" [model]="items"></p-contextMenu>
        +
        +
        + +

        Target

        +

        ContextMenu can be attached to a particular element whose local template variable name is defined using the target property.

        +
        +
        +<p-contextMenu [target]="img" [model]="items2" ></p-contextMenu>
        +
        +<img #img src="/showcase/resources/images/primeng.svg" alt="Logo">
        +
        +
        + +

        Exclusive Integrations

        +

        Some components like DataTable require special attention so they provide a different method to attach a context menu. Refer to + individual documentation of components with special integration like DataTable.

        + +
        +
        +export class ContextMenuDemo {
        +
        +    private items: MenuItem[];
        +
        +    ngOnInit() {
        +        this.items = [
        +            {
        +                label: 'File',
        +                items: [{
        +                        label: 'New', 
        +                        icon: 'fa-plus',
        +                        items: [
        +                            {label: 'Project'},
        +                            {label: 'Other'},
        +                        ]
        +                    },
        +                    {label: 'Open'},
        +                    {label: 'Quit'}
        +                ]
        +            },
        +            {
        +                label: 'Edit',
        +                icon: 'fa-edit',
        +                items: [
        +                    {label: 'Undo', icon: 'fa-mail-forward'},
        +                    {label: 'Redo', icon: 'fa-mail-reply'}
        +                ]
        +            }
        +        ];
        +    }
        +}
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        modelarraynullAn array of menuitems.
        globalbooleanfalseAttaches the menu to document instead of a particular item.
        targetstringnullLocal template variable name of the element to attach the context menu.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        appendToanynullTarget element to attach the overlay, valid values are "body" or a local ng-template variable of another element.
        +
        + +

        Methods

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        toggleevent (optional): mouse eventToggles the visibility of the popup menu.
        showevent: browser eventDisplays the popup menu.
        hide-Hides the popup menu.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-contextmenuContainer element.
        ui-menu-listList element.
        ui-menuitemMenuitem element.
        ui-menuitem-textLabel of a menuitem.
        ui-menuitem-iconIcon of a menuitem.
        ui-submenu-iconArrow icon of a submenu.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<p-contextMenu [global]="true" [model]="items1"></p-contextMenu>
        +
        +<p-contextMenu [target]="img" [model]="items2" ></p-contextMenu>
        +
        +<img #img src="/showcase/resources/images/primeng.svg" alt="Logo">
        +
        +
        + +
        +
        +export class ContextMenuDemo {
        +
        +    private items: MenuItem[];
        +    
        +    private items2: MenuItem[];
        +
        +    ngOnInit() {
        +        this.items = [
        +            {
        +                label: 'File',
        +                icon: 'fa-file-o',
        +                items: [{
        +                        label: 'New', 
        +                        icon: 'fa-plus',
        +                        items: [
        +                            {label: 'Project'},
        +                            {label: 'Other'},
        +                        ]
        +                    },
        +                    {label: 'Open'},
        +                    {label: 'Quit'}
        +                ]
        +            },
        +            {
        +                label: 'Edit',
        +                icon: 'fa-edit',
        +                items: [
        +                    {label: 'Undo', icon: 'fa-mail-forward'},
        +                    {label: 'Redo', icon: 'fa-mail-reply'}
        +                ]
        +            },
        +            {
        +                label: 'Help',
        +                icon: 'fa-question',
        +                items: [
        +                    {
        +                        label: 'Contents'
        +                    },
        +                    {
        +                        label: 'Search', 
        +                        icon: 'fa-search', 
        +                        items: [
        +                            {
        +                                label: 'Text', 
        +                                items: [
        +                                    {
        +                                        label: 'Workspace'
        +                                    }
        +                                ]
        +                            },
        +                            {
        +                                label: 'File'
        +                            }
        +                    ]}
        +                ]
        +            },
        +            {
        +                label: 'Actions',
        +                icon: 'fa-gear',
        +                items: [
        +                    {
        +                        label: 'Edit',
        +                        icon: 'fa-refresh',
        +                        items: [
        +                            {label: 'Save', icon: 'fa-save'},
        +                            {label: 'Update', icon: 'fa-save'},
        +                        ]
        +                    },
        +                    {
        +                        label: 'Other',
        +                        icon: 'fa-phone',
        +                        items: [
        +                            {label: 'Delete', icon: 'fa-minus'}
        +                        ]
        +                    }
        +                ]
        +            },
        +            {
        +                label: 'Quit', icon: 'fa-minus'
        +            }
        +        ];
        +        
        +        this.items2 = [
        +            {
        +                label: 'Next',
        +                icon: 'fa-chevron-right'
        +            },
        +            {
        +                label: 'Prev',
        +                icon: 'fa-chevron-left'
        +            }
        +        ];
        +    }
        +}
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/contextmenu/contextmenudemo.module.ts b/src/app/showcase/components/contextmenu/contextmenudemo.module.ts new file mode 100644 index 00000000000..c70f76a6fd4 --- /dev/null +++ b/src/app/showcase/components/contextmenu/contextmenudemo.module.ts @@ -0,0 +1,21 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {ContextMenuDemo} from './contextmenudemo'; +import {ContextMenuDemoRoutingModule} from './contextmenudemo-routing.module'; +import {ContextMenuModule} from '../../../components/contextmenu/contextmenu'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + ContextMenuDemoRoutingModule, + ContextMenuModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + ContextMenuDemo + ] +}) +export class ContextMenuDemoModule {} diff --git a/src/app/showcase/components/contextmenu/contextmenudemo.ts b/src/app/showcase/components/contextmenu/contextmenudemo.ts new file mode 100644 index 00000000000..4986cc39f55 --- /dev/null +++ b/src/app/showcase/components/contextmenu/contextmenudemo.ts @@ -0,0 +1,100 @@ +import {Component} from '@angular/core'; +import {MenuItem} from '../../../components/common/api'; + +@Component({ + templateUrl: './contextmenudemo.html' +}) +export class ContextMenuDemo { + + private items1: MenuItem[]; + + private items2: MenuItem[]; + + ngOnInit() { + this.items1 = [ + { + label: 'File', + icon: 'fa-file-o', + items: [{ + label: 'New', + icon: 'fa-plus', + items: [ + {label: 'Project'}, + {label: 'Other'}, + ] + }, + {label: 'Open'}, + {label: 'Quit'} + ] + }, + { + label: 'Edit', + icon: 'fa-edit', + items: [ + {label: 'Undo', icon: 'fa-mail-forward'}, + {label: 'Redo', icon: 'fa-mail-reply'} + ] + }, + { + label: 'Help', + icon: 'fa-question', + items: [ + { + label: 'Contents' + }, + { + label: 'Search', + icon: 'fa-search', + items: [ + { + label: 'Text', + items: [ + { + label: 'Workspace' + } + ] + }, + { + label: 'File' + } + ]} + ] + }, + { + label: 'Actions', + icon: 'fa-gear', + items: [ + { + label: 'Edit', + icon: 'fa-refresh', + items: [ + {label: 'Save', icon: 'fa-save'}, + {label: 'Update', icon: 'fa-save'}, + ] + }, + { + label: 'Other', + icon: 'fa-phone', + items: [ + {label: 'Delete', icon: 'fa-minus'} + ] + } + ] + }, + { + label: 'Quit', icon: 'fa-minus' + } + ]; + + this.items2 = [ + { + label: 'Next', + icon: 'fa-chevron-right' + }, + { + label: 'Prev', + icon: 'fa-chevron-left' + } + ]; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/datagrid/datagriddemo-routing.module.ts b/src/app/showcase/components/datagrid/datagriddemo-routing.module.ts new file mode 100644 index 00000000000..35396d993bf --- /dev/null +++ b/src/app/showcase/components/datagrid/datagriddemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {DataGridDemo} from './datagriddemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: DataGridDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class DataGridDemoRoutingModule {} diff --git a/src/app/showcase/components/datagrid/datagriddemo.html b/src/app/showcase/components/datagrid/datagriddemo.html new file mode 100644 index 00000000000..5ce7f1a9ad5 --- /dev/null +++ b/src/app/showcase/components/datagrid/datagriddemo.html @@ -0,0 +1,441 @@ +
        +
        + DataGrid + DataGrid displays data in grid format. +
        +
        + +
        + + + List of Cars + + +
        + + +
        {{car.year}} - {{car.color}}
        +
        + +
        +
        +
        +
        + + +
        +
        +
        +
        +
        +
        Vin:
        +
        {{selectedCar.vin}}
        +
        +
        +
        Year:
        +
        {{selectedCar.year}}
        +
        +
        +
        Brand:
        +
        {{selectedCar.brand}}
        +
        +
        +
        Color:
        +
        {{selectedCar.color}}
        +
        +
        +
        +
        + +
        + + +

        Import

        +
        +
        +import {DataGridModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        DataGrid requires a collection of items as its value and a ng-template to display each item. ng-template should contain a div element as a wrapper with Grid CSS style class of your choice to + define the grid layout. +

        Throughout the samples, a car interface having vin, brand, year and color properties are used to define an object to be displayed by the datagrid. Cars are loaded by a CarService that connects to a server to fetch the cars with a Promise.

        +
        +
        +export interface Car {
        +    vin;
        +    year;
        +    brand;
        +    color;
        +}
        +
        +
        + +
        +
        +import {Injectable} from 'angular2/core';
        +import {Http, Response} from 'angular2/http';
        +import {Car} from '../domain/car';
        +    
        +@Injectable()
        +export class CarService {
        +    
        +    constructor(private http: Http) {}
        +
        +    getCarsLarge() {
        +        return this.http.get('/showcase/resources/data/cars-large.json')
        +                    .toPromise()
        +                    .then(res => <Car[]> res.json().data)
        +                    .then(data => { return data; });
        +    }
        +}
        +
        +
        + +

        Here is a sample DataGrid that displays a list of cars where each row contains 3 cars.

        +
        +
        +export class DataGridDemo implements OnInit {
        +
        +    cars: Car[];
        +
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsLarge().then(cars => this.cars = cars);
        +    }
        +}
        +
        +
        + +
        +
        +<p-dataGrid [value]="cars">
        +    <ng-template let-car pTemplate="item">
        +        <div class="ui-g-12 ui-md-3">
        +            Car content
        +        </div>
        +    </ng-template>
        +</p-dataGrid>
        +
        +
        + +

        Index of the row is available at the ng-template.

        +
        +
        +<p-dataGrid [value]="cars">
        +    <ng-template let-car let-i="index" pTemplate="item">
        +        <div class="ui-g-12 ui-md-3">
        +            Car content for {{i}}
        +        </div>
        +    </ng-template>
        +</p-dataGrid>
        +
        +
        + + +

        Managing Data

        +

        DataTable uses setter based checking to realize if the underlying data has changed to update the UI so your data changes such as adding or removing a record + should always create a new array reference instead of manipulating an existing array. For example, use slice instead of splice when removing an item + or use spread operator instead of push method when adding an item.

        + +

        Facets

        +

        Header and Footer are the two sections aka facets that are capable of displaying custom content.

        +
        +
        +import {Header} from 'primeng/primeng';
        +import {Footer} from 'primeng/primeng';
        +
        +
        +
        +
        +<p-dataGrid [value]="cars">
        +    <p-header>List of Cars</p-header>
        +    <p-footer>Choose from the list.</p-footer>
        +    <ng-template let-car pTemplate="item">
        +        <div class="ui-g-12 ui-md-3">
        +            Car content
        +        </div>
        +    </ng-template>
        +</p-dataGrid>
        +
        +
        + +

        Paginator

        +

        Pagination is enabled by setting paginator property to true, rows attribute defines the number of rows per page and pageLinks specify the the number + of page links to display.

        +
        +
        +<p-dataGrid [value]="cars" [paginator]="true" [rows]="9">
        +    <ng-template let-car pTemplate="item">
        +        <div class="ui-g-12 ui-md-3">
        +            Car content
        +        </div>
        +    </ng-template>
        +</p-dataGrid>
        +
        +
        + +

        Lazy Loading

        +

        Lazy mode is handy to deal with large datasets, instead of loading the entire data, small chunks of data is loaded by invoking + onLazyLoad callback everytime paging happens. To implement lazy loading, + enable lazy attribute and provide a method callback using onLazyLoad that actually loads the data from a remote datasource. onLazyLoad gets an event object + that contains information about what to load. It is also important to assign the logical number of rows to totalRecords by doing a projection query for paginator configuration so that paginator + displays the UI assuming there are actually records of totalRecords size although in reality they aren't as in lazy mode, only the records that are displayed on the current page exist.

        +
        +
        +<p-dataGrid [value]="cars" [paginator]="true" [rows]="9" [lazy]="true" (onLazyLoad)="loadData($event)" [totalRecords]="totalRecords">
        +    <ng-template let-car pTemplate="item">
        +        <div class="ui-g-12 ui-md-3">
        +            Car content
        +        </div>
        +    </ng-template>
        +</p-dataGrid>
        +
        +
        + +
        +
        +loadData(event) {
        +    //event.first = First row offset
        +    //event.rows = Number of rows per page
        +}
        +
        +
        + +

        Responsive

        +

        DataGrid is responsive by default, when the screen gets smaller than a certain value, items are displayed as stacked.

        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        valuearraynullAn array of objects to display.
        rowsnumbernullNumber of rows to display per page.
        paginatorbooleanfalseWhen specified as true, enables the pagination.
        totalRecordsnumbernullNumber of total records, defaults to length of value when not defined.
        pageLinksnumber5Number of page links to display in paginator.
        rowsPerPageOptionsarraynullArray of integer values to display inside rows per page dropdown of paginator
        alwaysShowPaginatorbooleantrueWhether to show it even there is only one page.
        lazybooleanfalseDefines if data is loaded and interacted with in lazy manner.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        paginatorPositionstringbottomPosition of the paginator, options are "top","bottom" or "both".
        emptyMessagestringNo records found.Text to display when there is no data.
        trackByFunctionnullFunction to optimize the dom operations by delegating to ngForTrackBy, default algoritm checks for object identity.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onLazyLoadevent.first = First row offset
        + event.rows = Number of rows per page
        Callback to invoke when paging, sorting or filtering happens in lazy mode.
        onPageevent.first: Index of first record in page
        + event.rows: Number of rows on the page
        Callback to invoke when pagination occurs.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-datagridContainer element.
        ui-datagrid-headerHeader section.
        ui-datagrid-footerFooter section.
        ui-datagrid-contentContainer of items.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<p-dataGrid [value]="cars" [paginator]="true" [rows]="20">
        +    <p-header>
        +        List of Cars
        +    </p-header>
        +    <ng-template let-car pTemplate="item">
        +        <div style="padding:3px" class="ui-g-12 ui-md-3">
        +            <p-panel [header]="car.vin" [style]="{'text-align':'center'}">
        +                <img src="showcase/resources/demo/images/car/{{car.brand}}.gif">
        +                <div class="car-detail">{{car.year}} - {{car.color}}</div>
        +                <hr class="ui-widget-content" style="border-top:0">
        +                <i class="fa fa-search" (click)="selectCar(car)" style="cursor:pointer"></i>
        +            </p-panel>
        +        </div>
        +    </ng-template>
        +</p-dataGrid>
        +
        +<p-dialog header="Car Details" [(visible)]="displayDialog" [responsive]="true" showEffect="fade" [modal]="true" width="225" (onAfterHide)="onDialogHide()">
        +    <div class="ui-grid ui-grid-responsive ui-grid-pad" *ngIf="selectedCar" style="font-size:16px;text-align:center;padding:20px">
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-12" style="text-align:center"><img src="showcase/resources/demo/images/car/{{selectedCar.brand}}-big.gif"></div>
        +        </div>
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4">Vin: </div>
        +            <div class="ui-grid-col-8">{{selectedCar.vin}}</div>
        +        </div>
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4">Year: </div>
        +            <div class="ui-grid-col-8">{{selectedCar.year}}</div>
        +        </div>
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4">Brand: </div>
        +            <div class="ui-grid-col-8">{{selectedCar.brand}}</div>
        +        </div>
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4">Color: </div>
        +            <div class="ui-grid-col-8">{{selectedCar.color}}</div>
        +        </div>
        +    </div>
        +</p-dialog>
        +
        +
        +
        +
        +export class DataGridDemo implements OnInit {
        +
        +    cars: Car[];
        +    
        +    selectedCar: Car;
        +    
        +    displayDialog: boolean;
        +
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsLarge().then(cars => this.cars = cars);
        +    }
        +    
        +    selectCar(car: Car) {
        +        this.selectedCar = car;
        +        this.displayDialog = true;
        +    }
        +    
        +    onDialogHide() {
        +        this.selectedCar = null;
        +    }
        +}
        +
        +
        + + +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/datagrid/datagriddemo.module.ts b/src/app/showcase/components/datagrid/datagriddemo.module.ts new file mode 100644 index 00000000000..270292bb439 --- /dev/null +++ b/src/app/showcase/components/datagrid/datagriddemo.module.ts @@ -0,0 +1,25 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {DataGridDemo} from './datagriddemo'; +import {DataGridDemoRoutingModule} from './datagriddemo-routing.module'; +import {DataGridModule} from '../../../components/datagrid/datagrid'; +import {PanelModule} from '../../../components/panel/panel'; +import {DialogModule} from '../../../components/dialog/dialog'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + DataGridDemoRoutingModule, + DataGridModule, + PanelModule, + DialogModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + DataGridDemo + ] +}) +export class DataGridDemoModule {} diff --git a/src/app/showcase/components/datagrid/datagriddemo.ts b/src/app/showcase/components/datagrid/datagriddemo.ts new file mode 100644 index 00000000000..929737caef9 --- /dev/null +++ b/src/app/showcase/components/datagrid/datagriddemo.ts @@ -0,0 +1,30 @@ +import {Component,OnInit} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; + +@Component({ + templateUrl: './datagriddemo.html' +}) +export class DataGridDemo implements OnInit { + + cars: Car[]; + + selectedCar: Car; + + displayDialog: boolean; + + constructor(private carService: CarService) { } + + ngOnInit() { + this.carService.getCarsLarge().then(cars => this.cars = cars); + } + + selectCar(car: Car) { + this.selectedCar = car; + this.displayDialog = true; + } + + onDialogHide() { + this.selectedCar = null; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/datalist/datalistdemo-routing.module.ts b/src/app/showcase/components/datalist/datalistdemo-routing.module.ts new file mode 100644 index 00000000000..c5fb00691f5 --- /dev/null +++ b/src/app/showcase/components/datalist/datalistdemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {DataListDemo} from './datalistdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: DataListDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class DataListDemoRoutingModule {} diff --git a/src/app/showcase/components/datalist/datalistdemo.html b/src/app/showcase/components/datalist/datalistdemo.html new file mode 100644 index 00000000000..d455b1627ca --- /dev/null +++ b/src/app/showcase/components/datalist/datalistdemo.html @@ -0,0 +1,472 @@ +
        +
        + DataList + DataList displays data in list layout. +
        +
        + +
        + + + List of Cars + + +
        +
        +
        +
        +
        +
        +
        Vin:
        +
        {{car.vin}}
        +
        +
        +
        Year:
        +
        {{car.year}}
        +
        +
        +
        Brand:
        +
        {{car.brand}}
        +
        +
        +
        Color:
        +
        {{car.color}}
        +
        +
        +
        +
        +
        +
        +
        + + +
        +
        +
        +
        +
        +
        Vin:
        +
        {{selectedCar.vin}}
        +
        +
        +
        Year:
        +
        {{selectedCar.year}}
        +
        +
        +
        Brand:
        +
        {{selectedCar.brand}}
        +
        +
        +
        Color:
        +
        {{selectedCar.color}}
        +
        +
        +
        +
        + +
        + + +

        Import

        +
        +
        +import {DataListModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        DataList requires a collection of items as its value and a ng-template content to display + where each item can be accessed using the implicit variable.

        + +

        Throughout the samples, a car interface having vin, brand, year and color properties are + used to define an object to be displayed by the datalist. Cars are loaded by a CarService that + connects to a server to fetch the cars with a Promise.

        +
        +
        +export interface Car {
        +    vin;
        +    year;
        +    brand;
        +    color;
        +}
        +
        +
        + +
        +
        +import {Injectable} from 'angular2/core';
        +import {Http, Response} from 'angular2/http';
        +import {Car} from '../domain/car';
        +    
        +@Injectable()
        +export class CarService {
        +    
        +    constructor(private http: Http) {}
        +
        +    getCarsLarge() {
        +        return this.http.get('/showcase/resources/data/cars-large.json')
        +                    .toPromise()
        +                    .then(res => <Car[]> res.json().data)
        +                    .then(data => { return data; });
        +    }
        +}
        +
        +
        + +

        Here is a sample DataList that displays a list of cars.

        +
        +
        +export class DataListDemo implements OnInit {
        +
        +    cars: Car[];
        +
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsLarge().then(cars => this.cars = cars);
        +    }
        +}
        +
        +
        + +
        +
        +<p-dataList [value]="cars">
        +    <ng-template let-car pTemplate="item">
        +        Car content
        +    </ng-template>
        +</p-dataList>
        +
        +
        + +

        Index of the row is available at the ng-template.

        +
        +
        +<p-dataList [value]="cars">
        +    <ng-template let-car let-i="index" pTemplate="item">
        +        Car content for {{i}}
        +    </ng-template>
        +</p-dataList>
        +
        +
        + +

        Managing Data

        +

        DataTable uses setter based checking to realize if the underlying data has changed to update the UI so your data changes such as adding or removing a record + should always create a new array reference instead of manipulating an existing array. For example, use slice instead of splice when removing an item + or use spread operator instead of push method when adding an item.

        + +

        Facets

        +

        Header and Footer are the two sections aka facets that are capable of displaying custom content.

        +
        +
        +import {Header} from 'primeng/primeng';
        +import {Footer} from 'primeng/primeng';
        +
        +
        +
        +
        +<p-dataList [value]="cars">
        +    <p-header>List of Cars</p-header>
        +    <p-footer>Choose from the list.</p-footer>
        +    <ng-template let-car pTemplate="item">
        +        Car content
        +    </ng-template>
        +</p-dataList>
        +
        +
        + +

        Paginator

        +

        Pagination is enabled by setting paginator property to true, rows attribute defines the number of rows per page and pageLinks specify the the number + of page links to display.

        +
        +
        +<p-dataList [value]="cars" [paginator]="true" [rows]="10">
        +    <ng-template let-car pTemplate="item">
        +        Car content
        +    </ng-template>
        +</p-dataList>
        +
        +
        + +

        Lazy Loading

        +

        Lazy mode is handy to deal with large datasets, instead of loading the entire data, small chunks of data is loaded by invoking + onLazyLoad callback everytime paging happens. To implement lazy loading, + enable lazy attribute and provide a method callback using onLazyLoad that actually loads the data from a remote datasource. onLazyLoad gets an event object + that contains information about what to load. It is also important to assign the logical number of rows to totalRecords by doing a projection query for paginator configuration so that paginator + displays the UI assuming there are actually records of totalRecords size although in reality they aren't as in lazy mode, only the records that are displayed on the current page exist.

        +
        +
        +<p-dataList [value]="cars" [paginator]="true" [rows]="9" [lazy]="true" (onLazyLoad)="loadData($event)" [totalRecords]="totalRecords">
        +    <ng-template let-car pTemplate="item">
        +        Car content
        +    </ng-template>
        +</p-dataList>
        +
        +
        + +
        +
        +loadData(event) {
        +    //event.first = First row offset
        +    //event.rows = Number of rows per page
        +}
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        valuearraynullAn array of objects to display.
        rowsnumbernullNumber of rows to display per page.
        paginatorbooleanfalseWhen specified as true, enables the pagination.
        totalRecordsnumbernullNumber of total records, defaults to length of value when not defined.
        pageLinksnumber5Number of page links to display in paginator.
        rowsPerPageOptionsarraynullArray of integer values to display inside rows per page dropdown of paginator
        alwaysShowPaginatorbooleantrueWhether to show it even there is only one page.
        lazybooleanfalseDefines if data is loaded and interacted with in lazy manner.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        paginatorPositionstringbottomPosition of the paginator, options are "top","bottom" or "both".
        emptyMessagestringNo records found.Text to display when there is no data.
        trackByFunctionnullFunction to optimize the dom operations by delegating to ngForTrackBy, default algoritm checks for object identity.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onLazyLoadevent.first = First row offset
        + event.rows = Number of rows per page
        Callback to invoke when paging, sorting or filtering happens in lazy mode.
        onPageevent.first: Index of first record in page
        + event.rows: Number of rows on the page
        Callback to invoke when pagination occurs.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-datalistContainer element.
        ui-datalist-headerHeader section.
        ui-datalist-footerFooter section.
        ui-datalist-contentWrapper of item container.
        ui-datalist-dataItem container element.
        ui-datalist-emptymessageElement containing the empty message.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<p-dataList [value]="cars" [paginator]="true" [rows]="5">
        +    <p-header>
        +        List of Cars
        +    </p-header>
        +    <ng-template let-car pTemplate="item">
        +        <div class="ui-grid ui-grid-responsive ui-fluid" style="font-size:16px;padding:20px;border-bottom:1px solid #D5D5D5;">
        +            <div class="ui-grid-row">
        +                <div class="ui-grid-col-3" style="text-align:center"><i class="fa fa-search" (click)="selectCar(car)" style="cursor:pointer;float:left;margin-top:40px"></i><img src="showcase/resources/demo/images/car/{{car.brand}}-big.gif"></div>
        +                <div class="ui-grid-col-9">
        +                    <div class="ui-grid ui-grid-responsive ui-fluid">
        +                        <div class="ui-grid-row">
        +                            <div class="ui-grid-col-2">Vin: </div>
        +                            <div class="ui-grid-col-10">{{car.vin}}</div>
        +                        </div>
        +                        <div class="ui-grid-row">
        +                            <div class="ui-grid-col-2">Year: </div>
        +                            <div class="ui-grid-col-10">{{car.year}}</div>
        +                        </div>
        +                        <div class="ui-grid-row">
        +                            <div class="ui-grid-col-2">Brand: </div>
        +                            <div class="ui-grid-col-10">{{car.brand}}</div>
        +                        </div>
        +                        <div class="ui-grid-row">
        +                            <div class="ui-grid-col-2">Color: </div>
        +                            <div class="ui-grid-col-10">{{car.color}}</div>
        +                        </div>
        +                    </div>
        +                </div>
        +            </div>
        +        </div>
        +    </ng-template>
        +</p-dataList>
        +    
        +<p-dialog header="Car Details" [(visible)]="displayDialog" [responsive]="true" showEffect="fade" [modal]="true" width="225" (onAfterHide)="onDialogHide()">
        +    <div class="ui-grid ui-grid-responsive ui-fluid" *ngIf="selectedCar" style="font-size:16px;text-align:center;padding:20px">
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-12" style="text-align:center"><img src="showcase/resources/demo/images/car/{{selectedCar.brand}}-big.gif"></div>
        +        </div>
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4">Vin: </div>
        +            <div class="ui-grid-col-8">{{selectedCar.vin}}</div>
        +        </div>
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4">Year: </div>
        +            <div class="ui-grid-col-8">{{selectedCar.year}}</div>
        +        </div>
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4">Brand: </div>
        +            <div class="ui-grid-col-8">{{selectedCar.brand}}</div>
        +        </div>
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4">Color: </div>
        +            <div class="ui-grid-col-8">{{selectedCar.color}}</div>
        +        </div>
        +    </div>
        +</p-dialog>
        +
        +
        +
        +
        +export class DataListDemo implements OnInit {
        +
        +    cars: Car[];
        +    
        +    selectedCar: Car;
        +    
        +    displayDialog: boolean;
        +
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsLarge().then(cars => this.cars = cars);
        +    }
        +    
        +    selectCar(car: Car) {
        +        this.selectedCar = car;
        +        this.displayDialog = true;
        +    }
        +    
        +    onDialogHide() {
        +        this.selectedCar = null;
        +    }
        +}
        +
        +
        + + +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/datalist/datalistdemo.module.ts b/src/app/showcase/components/datalist/datalistdemo.module.ts new file mode 100644 index 00000000000..af1538f547b --- /dev/null +++ b/src/app/showcase/components/datalist/datalistdemo.module.ts @@ -0,0 +1,23 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {DataListDemo} from './datalistdemo'; +import {DataListDemoRoutingModule} from './datalistdemo-routing.module'; +import {DataListModule} from '../../../components/datalist/datalist'; +import {DialogModule} from '../../../components/dialog/dialog'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + DataListDemoRoutingModule, + DataListModule, + DialogModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + DataListDemo + ] +}) +export class DataListDemoModule {} diff --git a/src/app/showcase/components/datalist/datalistdemo.ts b/src/app/showcase/components/datalist/datalistdemo.ts new file mode 100644 index 00000000000..32541d7d05f --- /dev/null +++ b/src/app/showcase/components/datalist/datalistdemo.ts @@ -0,0 +1,40 @@ +import {Component,OnInit} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; + +@Component({ + templateUrl: './datalistdemo.html', + styles: [` + .ui-grid-row > div { + padding: 4px 10px; + font-size: 16px; + } + + .ui-grid-row .ui-grid-row > div:last-child { + font-weight: bold; + } + `] +}) +export class DataListDemo implements OnInit { + + cars: Car[]; + + selectedCar: Car; + + displayDialog: boolean; + + constructor(private carService: CarService) { } + + ngOnInit() { + this.carService.getCarsLarge().then(cars => this.cars = cars); + } + + selectCar(car: Car) { + this.selectedCar = car; + this.displayDialog = true; + } + + onDialogHide() { + this.selectedCar = null; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/datascroller/datascrollerdemo-routing.module.ts b/src/app/showcase/components/datascroller/datascrollerdemo-routing.module.ts new file mode 100644 index 00000000000..d3b47277b67 --- /dev/null +++ b/src/app/showcase/components/datascroller/datascrollerdemo-routing.module.ts @@ -0,0 +1,21 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {DataScrollerDemo} from './datascrollerdemo'; +import {DataScrollerInfiniteDemo} from './datascrollerinfinitedemo'; +import {DataScrollerInlineDemo} from './datascrollerinlinedemo'; +import {DataScrollerLoaderDemo} from './datascrollerloaderdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path: '',component: DataScrollerDemo}, + {path: 'inline', component: DataScrollerInlineDemo}, + {path: 'loader', component: DataScrollerLoaderDemo}, + {path: 'infinite', component: DataScrollerInfiniteDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class DatascrollerDemoRoutingModule {} diff --git a/src/app/showcase/components/datascroller/datascrollerdemo.html b/src/app/showcase/components/datascroller/datascrollerdemo.html new file mode 100644 index 00000000000..a639bf98e6c --- /dev/null +++ b/src/app/showcase/components/datascroller/datascrollerdemo.html @@ -0,0 +1,438 @@ + + +
        +
        + DataScroller + DataScroller displays data with on demand loading using scroll. +
        +
        + +
        + + + Scroll Down to to Load More + + +
      • +
        +
        +
        +
        +
        +
        +
        Vin:
        +
        {{car.vin}}
        +
        +
        +
        Year:
        +
        {{car.year}}
        +
        +
        +
        Brand:
        +
        {{car.brand}}
        +
        +
        +
        Color:
        +
        {{car.color}}
        +
        +
        +
        +
        +
        +
      • +
        +
        + + +
        +
        +
        +
        +
        +
        Vin:
        +
        {{selectedCar.vin}}
        +
        +
        +
        Year:
        +
        {{selectedCar.year}}
        +
        +
        +
        Brand:
        +
        {{selectedCar.brand}}
        +
        +
        +
        Color:
        +
        {{selectedCar.color}}
        +
        +
        +
        +
        + +
        + + +

        Import

        +
        +
        +import {DataScrollerModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        DataScroller requires a collection of items as its value, number of rows to load and a ng-template content to display + where each item can be accessed using the implicit variable.

        + +

        Throughout the samples, a car interface having vin, brand, year and color properties are used + to define an object to be displayed by the datascroller. Cars are loaded by a CarService that + connects to a server to fetch the cars with a Promise.

        +
        +
        +export interface Car {
        +    vin;
        +    year;
        +    brand;
        +    color;
        +}
        +
        +
        + +
        +
        +import {Injectable} from 'angular2/core';
        +import {Http, Response} from 'angular2/http';
        +import {Car} from '../domain/car';
        +
        +@Injectable()
        +export class CarService {
        +
        +    constructor(private http: Http) {}
        +
        +    getCarsLarge() {
        +        return this.http.get('/showcase/resources/data/cars-large.json')
        +                    .toPromise()
        +                    .then(res => <Car[]> res.json().data)
        +                    .then(data => { return data; });
        +    }
        +}
        +
        +
        + +

        Here is a sample DataScroller that displays a list of cars where each load event adds 10 more rows if available.

        +
        +
        +export class DataScrollertDemo implements OnInit {
        +
        +    cars: Car[];
        +
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsLarge().then(cars => this.cars = cars);
        +    }
        +}
        +
        +
        + +
        +
        +<p-dataScroller [value]="cars" [rows]="10">
        +    <ng-template let-car pTemplate="item">
        +        Car content
        +    </ng-template>
        +</p-dataScroller>
        +
        +
        + +

        Managing Data

        +

        DataTable uses setter based checking to realize if the underlying data has changed to update the UI so your data changes such as adding or removing a record + should always create a new array reference instead of manipulating an existing array. For example, use slice instead of splice when removing an item + or use spread operator instead of push method when adding an item.

        + +

        Facets

        +

        Header and Footer are the two sections aka facets that are capable of displaying custom content.

        +
        +
        +import {Header} from 'primeng/primeng';
        +import {Footer} from 'primeng/primeng';
        +
        +
        +
        +
        +<p-dataScroller [value]="cars" [rows]="10">
        +    <p-header>List of Cars</p-header>
        +    <p-footer>Choose from the list.</p-footer>
        +    <ng-template let-car pTemplate="item">
        +        Car content
        +    </ng-template>
        +</p-dataScroller>
        +
        +
        + +

        Inline

        +

        By default DataScroller listens to the scroll event of window, the alternative is the inline mode where container of the DataScroller element itself is used as the event target. Set inline option to true to enable this mode.

        +
        +
        +<p-dataScroller [value]="cars" [inline]="true" [rows]="10">
        +    <ng-template let-car pTemplate="item">
        +        Car content
        +    </ng-template>
        +</p-dataScroller>
        +
        +
        + +

        Lazy Loading

        +

        Lazy mode is handy to deal with large datasets, instead of loading the entire data, small chunks of data is loaded by invoking + onLazyLoad callback everytime paging happens. To implement lazy loading, + enable lazy attribute and provide a method callback using onLazyLoad that actually loads the data from a remote datasource. onLazyLoad gets an event object + that contains information about what to load.

        +
        +
        +<p-dataScroller [value]="cars" [rows]="10" [lazy]="true" (onLazyLoad)="loadData($event)">
        +    <ng-template let-car pTemplate="item">
        +        Car content
        +    </ng-template>
        +</p-dataScroller>
        +
        +
        + +
        +
        +loadData(event) {
        +    //event.first = First row offset
        +    //event.rows = Number of rows per page
        +    //add more records to the cars array
        +}
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        valuearraynullAn array of objects to display.
        rowsnumbernullNumber of rows to fetch in a load event.
        inlinebooleanfalseDefines if the event target to listen the scroll event is the element itself.
        scrollHeightanynullMax height of the content area in inline mode.
        loaderanynullReference of the target element whose click event loads the data instead of scrolling.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + +
        NameParametersDescription
        onLazyLoadevent.first = First row offset
        + event.rows = Number of rows per page
        Callback to invoke in lazy mode to load new data.
        +
        + +

        Methods

        +
        + + + + + + + + + + + + + + + +
        NameParametersDescription
        reset-Resets data.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-datascrollerContainer element.
        ui-datascroller-headerHeader section.
        ui-datascroller-footerFooter section.
        ui-datascroller-contentWrapper of item container.
        ui-datascroller-listItem container element.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<p-dataScroller [value]="cars" [rows]="10" [buffer]="0.4">
        +    <p-header>
        +        Scroll Down to to Load More
        +    </p-header>
        +    <ng-template let-car pTemplate="item">
        +        <div class="ui-grid ui-grid-responsive ui-fluid" style="font-size:16px;padding:20px;border-bottom:1px solid #D5D5D5;">
        +            <div class="ui-grid-row">
        +                <div class="ui-grid-col-3" style="text-align:center"><i class="fa fa-search" (click)="selectCar(car)" style="cursor:pointer;float:left;margin-top:40px"></i><img src="showcase/resources/demo/images/car/{{car.brand}}-big.gif"></div>
        +                <div class="ui-grid-col-9">
        +                    <div class="ui-grid ui-grid-responsive ui-fluid">
        +                        <div class="ui-grid-row">
        +                            <div class="ui-grid-col-2">Vin: </div>
        +                            <div class="ui-grid-col-10">{{car.vin}}</div>
        +                        </div>
        +                        <div class="ui-grid-row">
        +                            <div class="ui-grid-col-2">Year: </div>
        +                            <div class="ui-grid-col-10">{{car.year}}</div>
        +                        </div>
        +                        <div class="ui-grid-row">
        +                            <div class="ui-grid-col-2">Brand: </div>
        +                            <div class="ui-grid-col-10">{{car.brand}}</div>
        +                        </div>
        +                        <div class="ui-grid-row">
        +                            <div class="ui-grid-col-2">Color: </div>
        +                            <div class="ui-grid-col-10">{{car.color}}</div>
        +                        </div>
        +                    </div>
        +                </div>
        +            </div>
        +        </div>
        +    </ng-template>
        +</p-dataScroller>
        +
        +<p-dialog header="Car Details" [(visible)]="displayDialog" [responsive]="true" showEffect="fade" [modal]="true" width="225" (onAfterHide)="onDialogHide()">
        +    <div class="ui-grid ui-grid-responsive ui-fluid" *ngIf="selectedCar" style="font-size:16px;text-align:center;padding:20px">
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-12" style="text-align:center"><img src="showcase/resources/demo/images/car/{{selectedCar.brand}}-big.gif"></div>
        +        </div>
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4">Vin: </div>
        +            <div class="ui-grid-col-8">{{selectedCar.vin}}</div>
        +        </div>
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4">Year: </div>
        +            <div class="ui-grid-col-8">{{selectedCar.year}}</div>
        +        </div>
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4">Brand: </div>
        +            <div class="ui-grid-col-8">{{selectedCar.brand}}</div>
        +        </div>
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4">Color: </div>
        +            <div class="ui-grid-col-8">{{selectedCar.color}}</div>
        +        </div>
        +    </div>
        +</p-dialog>
        +
        +
        +
        +
        +export class DataScrollerDemo implements OnInit {
        +
        +    cars: Car[];
        +
        +    selectedCar: Car;
        +
        +    displayDialog: boolean;
        +
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsMedium().then(cars => this.cars = cars);
        +    }
        +
        +    selectCar(car: Car) {
        +        this.selectedCar = car;
        +        this.displayDialog = true;
        +    }
        +
        +    onDialogHide() {
        +        this.selectedCar = null;
        +    }
        +}
        +
        +
        + + +
        +
        +
        diff --git a/src/app/showcase/components/datascroller/datascrollerdemo.module.ts b/src/app/showcase/components/datascroller/datascrollerdemo.module.ts new file mode 100644 index 00000000000..7376c40f9c3 --- /dev/null +++ b/src/app/showcase/components/datascroller/datascrollerdemo.module.ts @@ -0,0 +1,35 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {DataScrollerDemo} from './datascrollerdemo'; +import {DataScrollerSubMenu} from './datascrollersubmenu'; +import {DataScrollerInfiniteDemo} from './datascrollerinfinitedemo'; +import {DataScrollerInlineDemo} from './datascrollerinlinedemo'; +import {DataScrollerLoaderDemo} from './datascrollerloaderdemo'; +import {DatascrollerDemoRoutingModule} from './datascrollerdemo-routing.module'; +import {DataScrollerModule} from '../../../components/datascroller/datascroller'; +import {DialogModule} from '../../../components/dialog/dialog'; +import {ButtonModule} from '../../../components/button/button'; +import {GrowlModule} from '../../../components/growl/growl'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + DatascrollerDemoRoutingModule, + DataScrollerModule, + DialogModule, + ButtonModule, + GrowlModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + DataScrollerDemo, + DataScrollerInfiniteDemo, + DataScrollerInlineDemo, + DataScrollerLoaderDemo, + DataScrollerSubMenu + ] +}) +export class DataScrollerDemoModule {} diff --git a/src/app/showcase/components/datascroller/datascrollerdemo.ts b/src/app/showcase/components/datascroller/datascrollerdemo.ts new file mode 100644 index 00000000000..da255083c9c --- /dev/null +++ b/src/app/showcase/components/datascroller/datascrollerdemo.ts @@ -0,0 +1,40 @@ +import {Component,OnInit} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; + +@Component({ + templateUrl: './datascrollerdemo.html', + styles: [` + .ui-grid-row > div { + padding: 4px 10px; + font-size: 20px; + } + + .ui-grid-row .ui-grid-row > div:last-child { + font-weight: bold; + } + `] +}) +export class DataScrollerDemo implements OnInit { + + cars: Car[]; + + selectedCar: Car; + + displayDialog: boolean; + + constructor(private carService: CarService) { } + + ngOnInit() { + this.carService.getCarsMedium().then(cars => this.cars = cars); + } + + selectCar(car: Car) { + this.selectedCar = car; + this.displayDialog = true; + } + + onDialogHide() { + this.selectedCar = null; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/datascroller/datascrollerinfinitedemo.html b/src/app/showcase/components/datascroller/datascrollerinfinitedemo.html new file mode 100644 index 00000000000..ac80a971f90 --- /dev/null +++ b/src/app/showcase/components/datascroller/datascrollerinfinitedemo.html @@ -0,0 +1,122 @@ + + +
        +
        + DataScroller - Infinite + DataScroller supports lazy loading so that each scroll event fetches new chunk of data from a remote datasource. This example generates + the new records on-the-fly and scrolling is infinite.
        Scroll to the bottom of this page to see the demo. +
        +
        + +
        + + +
        +
        +export class DataScrollerInfiniteDemo {
        +
        +    cars: Car[];
        +    
        +    msgs: Message[] = [];
        +    
        +    constructor(private carService: CarService) { }
        +    
        +    loadData(event) {
        +        //initialize
        +        if(!this.cars) {
        +            this.carService.getCarsSmall().then(cars => this.cars = cars);
        +        }
        +        //in real application, newArray should be loaded from a remote datasource
        +        else {
        +            let newArray = this.cars.slice(0);
        +            for(let i = 0; i < newArray.length; i++) {
        +                this.cars.push(newArray[i]);
        +            }
        +            this.msgs = [];
        +            this.msgs.push({severity:'info', summary:'Data Loaded', detail:'Between ' + event.first + ' and ' + (event.first + event.rows)});
        +        }        
        +    }
        +}
        +
        +
        +
        + + +
        +
        +<p-growl [value]="msgs"></p-growl>
        +
        +<p-dataScroller [value]="cars" [rows]="10" (onLazyLoad)="loadData($event)" [lazy]="true">
        +    <p-header>
        +        Scroll Down to to Load More
        +    </p-header>
        +    <ng-template let-car pTemplate="item">
        +        <div class="ui-grid ui-grid-responsive ui-fluid" style="font-size:16px;padding:20px;border-bottom:1px solid #D5D5D5">
        +            <div class="ui-grid-row">
        +                <div class="ui-grid-col-3" style="text-align:center"><img src="showcase/resources/demo/images/car/{{car.brand}}-big.gif"></div>
        +                <div class="ui-grid-col-9">
        +                    <div class="ui-grid ui-grid-responsive ui-fluid">
        +                        <div class="ui-grid-row">
        +                            <div class="ui-grid-col-2">Vin: </div>
        +                            <div class="ui-grid-col-10">{{car.vin}}</div>
        +                        </div>
        +                        <div class="ui-grid-row">
        +                            <div class="ui-grid-col-2">Year: </div>
        +                            <div class="ui-grid-col-10">{{car.year}}</div>
        +                        </div>
        +                        <div class="ui-grid-row">
        +                            <div class="ui-grid-col-2">Brand: </div>
        +                            <div class="ui-grid-col-10">{{car.brand}}</div>
        +                        </div>
        +                        <div class="ui-grid-row">
        +                            <div class="ui-grid-col-2">Color: </div>
        +                            <div class="ui-grid-col-10">{{car.color}}</div>
        +                        </div>
        +                    </div>
        +                </div>
        +            </div>
        +        </div>
        +    </ng-template>
        +</p-dataScroller>
        +
        +
        +
        +
        +
        + +
        + + + + + Scroll Down to to Load More + + +
        +
        +
        +
        +
        +
        +
        Vin:
        +
        {{car.vin}}
        +
        +
        +
        Year:
        +
        {{car.year}}
        +
        +
        +
        Brand:
        +
        {{car.brand}}
        +
        +
        +
        Color:
        +
        {{car.color}}
        +
        +
        +
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/datascroller/datascrollerinfinitedemo.ts b/src/app/showcase/components/datascroller/datascrollerinfinitedemo.ts new file mode 100644 index 00000000000..e6881b251cd --- /dev/null +++ b/src/app/showcase/components/datascroller/datascrollerinfinitedemo.ts @@ -0,0 +1,42 @@ +import {Component,OnInit} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; +import {Message} from '../../../components/common/api'; + +@Component({ + templateUrl: './datascrollerinfinitedemo.html', + styles: [` + .ui-grid-row > div { + padding: 4px 10px; + font-size: 20px; + } + + .ui-grid-row .ui-grid-row > div:last-child { + font-weight: bold; + } + `] +}) +export class DataScrollerInfiniteDemo { + + cars: Car[]; + + msgs: Message[] = []; + + constructor(private carService: CarService) { } + + loadData(event) { + //initialize + if(!this.cars) { + this.carService.getCarsSmall().then(cars => this.cars = cars); + } + //in real application, newArray should be loaded from a remote datasource + else { + let newArray = this.cars.slice(0); + for(let i = 0; i < newArray.length; i++) { + this.cars.push(newArray[i]); + } + this.msgs = []; + this.msgs.push({severity:'info', summary:'Data Loaded', detail:'Between ' + event.first + ' and ' + (event.first + event.rows)}); + } + } +} \ No newline at end of file diff --git a/src/app/showcase/components/datascroller/datascrollerinlinedemo.html b/src/app/showcase/components/datascroller/datascrollerinlinedemo.html new file mode 100644 index 00000000000..607e68246be --- /dev/null +++ b/src/app/showcase/components/datascroller/datascrollerinlinedemo.html @@ -0,0 +1,164 @@ + + +
        +
        + DataScroller - Inline + DataScroller can listen scroll event of itself rather than document in inline mode. +
        +
        + +
        + + + Scroll Down to to Load More + + +
        +
        +
        +
        +
        +
        +
        Vin:
        +
        {{car.vin}}
        +
        +
        +
        Year:
        +
        {{car.year}}
        +
        +
        +
        Brand:
        +
        {{car.brand}}
        +
        +
        +
        Color:
        +
        {{car.color}}
        +
        +
        +
        +
        +
        +
        +
        + + +
        +
        +
        +
        +
        +
        Vin:
        +
        {{selectedCar.vin}}
        +
        +
        +
        Year:
        +
        {{selectedCar.year}}
        +
        +
        +
        Brand:
        +
        {{selectedCar.brand}}
        +
        +
        +
        Color:
        +
        {{selectedCar.color}}
        +
        +
        +
        +
        + +
        + + +
        +
        +export class DataScrollerInlineDemo implements OnInit {
        +
        +    cars: Car[];
        +    
        +    selectedCar: Car;
        +    
        +    displayDialog: boolean;
        +
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsMedium().then(cars => this.cars = cars);
        +    }
        +    
        +    selectCar(car: Car) {
        +        this.selectedCar = car;
        +        this.displayDialog = true;
        +    }
        +    
        +    onDialogHide() {
        +        this.selectedCar = null;
        +    }
        +}
        +
        +
        +
        + + +
        +
        +<p-dataScroller [value]="cars" [rows]="10" [inline]="true" scrollHeight="500px">
        +    <p-header>
        +        Scroll Down to to Load More
        +    </p-header>
        +    <ng-template let-car pTemplate="item">
        +        <div class="ui-grid ui-grid-responsive ui-fluid" style="font-size:16px;padding:20px;border-bottom:1px solid #D5D5D5">
        +            <div class="ui-grid-row">
        +                <div class="ui-grid-col-3" style="text-align:center"><i class="fa fa-search" (click)="selectCar(car)" style="cursor:pointer;float:left;margin-top:40px"></i><img src="showcase/resources/demo/images/car/{{car.brand}}-big.gif"></div>
        +                <div class="ui-grid-col-9">
        +                    <div class="ui-grid ui-grid-responsive ui-fluid">
        +                        <div class="ui-grid-row">
        +                            <div class="ui-grid-col-2">Vin: </div>
        +                            <div class="ui-grid-col-10">{{car.vin}}</div>
        +                        </div>
        +                        <div class="ui-grid-row">
        +                            <div class="ui-grid-col-2">Year: </div>
        +                            <div class="ui-grid-col-10">{{car.year}}</div>
        +                        </div>
        +                        <div class="ui-grid-row">
        +                            <div class="ui-grid-col-2">Brand: </div>
        +                            <div class="ui-grid-col-10">{{car.brand}}</div>
        +                        </div>
        +                        <div class="ui-grid-row">
        +                            <div class="ui-grid-col-2">Color: </div>
        +                            <div class="ui-grid-col-10">{{car.color}}</div>
        +                        </div>
        +                    </div>
        +                </div>
        +            </div>
        +        </div>
        +    </ng-template>
        +</p-dataScroller>
        +    
        +<p-dialog header="Car Details" [(visible)]="displayDialog" [responsive]="true" showEffect="fade" [modal]="true" width="225" (onAfterHide)="onDialogHide()">
        +    <div class="ui-grid ui-grid-responsive ui-fluid" *ngIf="selectedCar" style="font-size:16px;text-align:center;padding:20px">
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-12" style="text-align:center"><img src="showcase/resources/demo/images/car/{{selectedCar.brand}}-big.gif"></div>
        +        </div>
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4">Vin: </div>
        +            <div class="ui-grid-col-8">{{selectedCar.vin}}</div>
        +        </div>
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4">Year: </div>
        +            <div class="ui-grid-col-8">{{selectedCar.year}}</div>
        +        </div>
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4">Brand: </div>
        +            <div class="ui-grid-col-8">{{selectedCar.brand}}</div>
        +        </div>
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4">Color: </div>
        +            <div class="ui-grid-col-8">{{selectedCar.color}}</div>
        +        </div>
        +    </div>
        +</p-dialog>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/datascroller/datascrollerinlinedemo.ts b/src/app/showcase/components/datascroller/datascrollerinlinedemo.ts new file mode 100644 index 00000000000..62c757a0ff8 --- /dev/null +++ b/src/app/showcase/components/datascroller/datascrollerinlinedemo.ts @@ -0,0 +1,40 @@ +import {Component,OnInit} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; + +@Component({ + templateUrl: './datascrollerinlinedemo.html', + styles: [` + .ui-grid-row > div { + padding: 4px 10px; + font-size: 20px; + } + + .ui-grid-row .ui-grid-row > div:last-child { + font-weight: bold; + } + `] +}) +export class DataScrollerInlineDemo implements OnInit { + + cars: Car[]; + + selectedCar: Car; + + displayDialog: boolean; + + constructor(private carService: CarService) { } + + ngOnInit() { + this.carService.getCarsMedium().then(cars => this.cars = cars); + } + + selectCar(car: Car) { + this.selectedCar = car; + this.displayDialog = true; + } + + onDialogHide() { + this.selectedCar = null; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/datascroller/datascrollerloaderdemo.html b/src/app/showcase/components/datascroller/datascrollerloaderdemo.html new file mode 100644 index 00000000000..5a2ab19d6ba --- /dev/null +++ b/src/app/showcase/components/datascroller/datascrollerloaderdemo.html @@ -0,0 +1,170 @@ + + +
        +
        + DataScroller - Loader + Instead of scrolling, click event of an element can be used to load data. +
        +
        + +
        + + + Click Load Button at Footer to Load More + + +
        +
        +
        +
        +
        +
        +
        Vin:
        +
        {{car.vin}}
        +
        +
        +
        Year:
        +
        {{car.year}}
        +
        +
        +
        Brand:
        +
        {{car.brand}}
        +
        +
        +
        Color:
        +
        {{car.color}}
        +
        +
        +
        +
        +
        +
        + + + +
        + + +
        +
        +
        +
        +
        +
        Vin:
        +
        {{selectedCar.vin}}
        +
        +
        +
        Year:
        +
        {{selectedCar.year}}
        +
        +
        +
        Brand:
        +
        {{selectedCar.brand}}
        +
        +
        +
        Color:
        +
        {{selectedCar.color}}
        +
        +
        +
        +
        + +
        + + +
        +
        +export class DataScrollerLoaderDemo implements OnInit {
        +
        +    cars: Car[];
        +    
        +    selectedCar: Car;
        +    
        +    displayDialog: boolean;
        +
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsMedium().then(cars => this.cars = cars);
        +    }
        +    
        +    selectCar(car: Car) {
        +        this.selectedCar = car;
        +        this.displayDialog = true;
        +    }
        +    
        +    onDialogHide() {
        +        this.selectedCar = null;
        +    }
        +}
        +
        +
        +
        + + +
        +
        +<p-dataScroller [value]="cars" [rows]="5" [loader]="loadButton">
        +    <p-header>
        +        Click Load Button at Footer to Load More
        +    </p-header>
        +    <ng-template let-car pTemplate="item">
        +        <div class="ui-grid ui-grid-responsive ui-fluid" style="font-size:16px;padding:20px;border-bottom:1px solid #D5D5D5">
        +            <div class="ui-grid-row">
        +                <div class="ui-grid-col-3" style="text-align:center"><i class="fa fa-search" (click)="selectCar(car)" style="cursor:pointer;float:left;margin-top:40px"></i><img src="showcase/resources/demo/images/car/{{car.brand}}-big.gif"></div>
        +                <div class="ui-grid-col-9">
        +                    <div class="ui-grid ui-grid-responsive ui-fluid">
        +                        <div class="ui-grid-row">
        +                            <div class="ui-grid-col-2">Vin: </div>
        +                            <div class="ui-grid-col-10">{{car.vin}}</div>
        +                        </div>
        +                        <div class="ui-grid-row">
        +                            <div class="ui-grid-col-2">Year: </div>
        +                            <div class="ui-grid-col-10">{{car.year}}</div>
        +                        </div>
        +                        <div class="ui-grid-row">
        +                            <div class="ui-grid-col-2">Brand: </div>
        +                            <div class="ui-grid-col-10">{{car.brand}}</div>
        +                        </div>
        +                        <div class="ui-grid-row">
        +                            <div class="ui-grid-col-2">Color: </div>
        +                            <div class="ui-grid-col-10">{{car.color}}</div>
        +                        </div>
        +                    </div>
        +                </div>
        +            </div>
        +        </div>
        +    </ng-template>
        +    <p-footer>
        +        <button #loadButton type="text" icon="fa-refresh" pButton label="Load"></button>
        +    </p-footer>
        +</p-dataScroller>
        +    
        +<p-dialog header="Car Details" [(visible)]="displayDialog" [responsive]="true" showEffect="fade" [modal]="true" width="225" (onAfterHide)="onDialogHide()">
        +    <div class="ui-grid ui-grid-responsive ui-fluid" *ngIf="selectedCar" style="font-size:16px;text-align:center;padding:20px">
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-12" style="text-align:center"><img src="showcase/resources/demo/images/car/{{selectedCar.brand}}-big.gif"></div>
        +        </div>
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4">Vin: </div>
        +            <div class="ui-grid-col-8">{{selectedCar.vin}}</div>
        +        </div>
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4">Year: </div>
        +            <div class="ui-grid-col-8">{{selectedCar.year}}</div>
        +        </div>
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4">Brand: </div>
        +            <div class="ui-grid-col-8">{{selectedCar.brand}}</div>
        +        </div>
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4">Color: </div>
        +            <div class="ui-grid-col-8">{{selectedCar.color}}</div>
        +        </div>
        +    </div>
        +</p-dialog>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/datascroller/datascrollerloaderdemo.ts b/src/app/showcase/components/datascroller/datascrollerloaderdemo.ts new file mode 100644 index 00000000000..66603e727af --- /dev/null +++ b/src/app/showcase/components/datascroller/datascrollerloaderdemo.ts @@ -0,0 +1,40 @@ +import {Component,OnInit} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; + +@Component({ + templateUrl: './datascrollerloaderdemo.html', + styles: [` + .ui-grid-row > div { + padding: 4px 10px; + font-size: 20px; + } + + .ui-grid-row .ui-grid-row > div:last-child { + font-weight: bold; + } + `] +}) +export class DataScrollerLoaderDemo implements OnInit { + + cars: Car[]; + + selectedCar: Car; + + displayDialog: boolean; + + constructor(private carService: CarService) { } + + ngOnInit() { + this.carService.getCarsMedium().then(cars => this.cars = cars); + } + + selectCar(car: Car) { + this.selectedCar = car; + this.displayDialog = true; + } + + onDialogHide() { + this.selectedCar = null; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/datascroller/datascrollersubmenu.ts b/src/app/showcase/components/datascroller/datascrollersubmenu.ts new file mode 100644 index 00000000000..3ee03ffe9be --- /dev/null +++ b/src/app/showcase/components/datascroller/datascrollersubmenu.ts @@ -0,0 +1,17 @@ +import {Component} from '@angular/core'; + +@Component({ + selector: 'datascroller-demos', + template: ` + + ` +}) +export class DataScrollerSubMenu { +} diff --git a/src/app/showcase/components/datatable/datatablecmdemo.html b/src/app/showcase/components/datatable/datatablecmdemo.html new file mode 100644 index 00000000000..c108aa161e8 --- /dev/null +++ b/src/app/showcase/components/datatable/datatablecmdemo.html @@ -0,0 +1,91 @@ + + +
        +
        + DataTable - ContextMenu + DataTable has exclusive integration with ContextMenu. +
        +
        + +
        + + + + Right Click on Rows for ContextMenu + + + + + + + +
        + +
        + + +
        +
        +export class DataTableCMDemo implements OnInit {
        +
        +    msgs: Message[];
        +
        +    cars: Car[];
        +
        +    selectedCar: Car;
        +    
        +    items: MenuItem[];
        +
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsSmall().then(cars => this.cars = cars);
        +        
        +        this.items = [
        +            {label: 'View', icon: 'fa-search', command: (event) => this.viewCar(this.selectedCar)},
        +            {label: 'Delete', icon: 'fa-close', command: (event) => this.deleteCar(this.selectedCar)}
        +        ];
        +    }
        +
        +    viewCar(car: Car) {
        +        this.msgs = [];
        +        this.msgs.push({severity: 'info', summary: 'Car Selected', detail: car.vin + ' - ' + car.brand});
        +    }
        +
        +    deleteCar(car: Car) {
        +        let index = -1;
        +        for(let i = 0; i < this.cars.length; i++) {
        +            if(this.cars[i].vin == car.vin) {
        +                index = i;
        +                break;
        +            }
        +        }
        +        this.cars.splice(index, 1);
        +        
        +        this.msgs = [];
        +        this.msgs.push({severity: 'info', summary: 'Car Deleted', detail: car.vin + ' - ' + car.brand});
        +    }
        +}
        +
        +
        +
        + + +
        +
        +<p-growl [value]="msgs"></p-growl>
        +
        +<p-dataTable [value]="cars" selectionMode="single" [(selection)]="selectedCar" [contextMenu]="cm">
        +    <p-header>Right Click on Rows for ContextMenu</p-header>
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +<p-contextMenu #cm [model]="items"></p-contextMenu>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatablecmdemo.ts b/src/app/showcase/components/datatable/datatablecmdemo.ts new file mode 100644 index 00000000000..a946075aba6 --- /dev/null +++ b/src/app/showcase/components/datatable/datatablecmdemo.ts @@ -0,0 +1,48 @@ +import {Component,OnInit} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; +import {Message,MenuItem} from '../../../components/common/api'; + +@Component({ + templateUrl: './datatablecmdemo.html' +}) +export class DataTableCMDemo implements OnInit { + + msgs: Message[]; + + cars: Car[]; + + selectedCar: Car; + + items: MenuItem[]; + + constructor(private carService: CarService) { } + + ngOnInit() { + this.carService.getCarsSmall().then(cars => this.cars = cars); + + this.items = [ + {label: 'View', icon: 'fa-search', command: (event) => this.viewCar(this.selectedCar)}, + {label: 'Delete', icon: 'fa-close', command: (event) => this.deleteCar(this.selectedCar)} + ]; + } + + viewCar(car: Car) { + this.msgs = []; + this.msgs.push({severity: 'info', summary: 'Car Selected', detail: car.vin + ' - ' + car.brand}); + } + + deleteCar(car: Car) { + let index = -1; + for(let i = 0; i < this.cars.length; i++) { + if(this.cars[i].vin == car.vin) { + index = i; + break; + } + } + this.cars.splice(index, 1); + + this.msgs = []; + this.msgs.push({severity: 'info', summary: 'Car Deleted', detail: car.vin + ' - ' + car.brand}); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatablecolgroupdemo.html b/src/app/showcase/components/datatable/datatablecolgroupdemo.html new file mode 100644 index 00000000000..3e9c0b2ad00 --- /dev/null +++ b/src/app/showcase/components/datatable/datatablecolgroupdemo.html @@ -0,0 +1,113 @@ + + +
        +
        + DataTable - Column Grouping + Columns can be grouped at header and footer using headerColumnGroup and footerColumnGroup components that both define an array + of columns each having colspan and rowspan. +
        +
        + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + +
        + + +
        +
        +export class DataTableGroupDemo implements OnInit {
        +
        +    sales: any[];
        +
        +    ngOnInit() {
        +        this.sales = [
        +            {brand: 'Apple', lastYearSale: '51%', thisYearSale: '40%', lastYearProfit: '$54,406.00', thisYearProfit: '$43,342'},
        +            {brand: 'Samsung', lastYearSale: '83%', thisYearSale: '96%', lastYearProfit: '$423,132', thisYearProfit: '$312,122'},
        +            {brand: 'Microsoft', lastYearSale: '38%', thisYearSale: '5%', lastYearProfit: '$12,321', thisYearProfit: '$8,500'},
        +            {brand: 'Philips', lastYearSale: '49%', thisYearSale: '22%', lastYearProfit: '$745,232', thisYearProfit: '$650,323,'},
        +            {brand: 'Song', lastYearSale: '17%', thisYearSale: '79%', lastYearProfit: '$643,242', thisYearProfit: '500,332'},
        +            {brand: 'LG', lastYearSale: '52%', thisYearSale: ' 65%', lastYearProfit: '$421,132', thisYearProfit: '$150,005'},
        +            {brand: 'Sharp', lastYearSale: '82%', thisYearSale: '12%', lastYearProfit: '$131,211', thisYearProfit: '$100,214'},
        +            {brand: 'Panasonic', lastYearSale: '44%', thisYearSale: '45%', lastYearProfit: '$66,442', thisYearProfit: '$53,322'},
        +            {brand: 'HTC', lastYearSale: '90%', thisYearSale: '56%', lastYearProfit: '$765,442', thisYearProfit: '$296,232'},
        +            {brand: 'Toshiba', lastYearSale: '75%', thisYearSale: '54%', lastYearProfit: '$21,212', thisYearProfit: '$12,533'}
        +        ];
        +    }
        +}
        +
        +
        +
        + + +
        +
        +<p-dataTable [value]="sales">
        +    <p-headerColumnGroup>
        +        <p-row>
        +            <p-column header="Brand" rowspan="3"></p-column>
        +            <p-column header="Sale Rate" colspan="4"></p-column>
        +        </p-row>
        +        <p-row>
        +            <p-column header="Sales" colspan="2"></p-column>
        +            <p-column header="Profits" colspan="2"></p-column>
        +        </p-row>
        +        <p-row>
        +            <p-column header="Last Year"></p-column>
        +            <p-column header="This Year"></p-column>
        +            <p-column header="Last Year"></p-column>
        +            <p-column header="This Year"></p-column>
        +        </p-row>
        +    </p-headerColumnGroup>
        +    
        +    <p-column field="brand"></p-column>
        +    <p-column field="lastYearSale"></p-column>
        +    <p-column field="thisYearSale"></p-column>
        +    <p-column field="lastYearProfit"></p-column>
        +    <p-column field="thisYearProfit"></p-column>
        +    
        +    <p-footerColumnGroup>
        +        <p-row>
        +            <p-column footer="Totals:" colspan="3"></p-column>
        +            <p-column footer="$506,202"></p-column>
        +            <p-column footer="$531,020"></p-column>
        +        </p-row>
        +    </p-footerColumnGroup>
        +</p-dataTable>
        +
        +
        +
        +
        +
        diff --git a/src/app/showcase/components/datatable/datatablecolgroupdemo.ts b/src/app/showcase/components/datatable/datatablecolgroupdemo.ts new file mode 100644 index 00000000000..222a6647ca4 --- /dev/null +++ b/src/app/showcase/components/datatable/datatablecolgroupdemo.ts @@ -0,0 +1,24 @@ +import {Component,OnInit} from '@angular/core'; + +@Component({ + templateUrl: './datatablecolgroupdemo.html' +}) +export class DataTableColGroupDemo implements OnInit { + + sales: any[]; + + ngOnInit() { + this.sales = [ + {brand: 'Apple', lastYearSale: '51%', thisYearSale: '40%', lastYearProfit: '$54,406.00', thisYearProfit: '$43,342'}, + {brand: 'Samsung', lastYearSale: '83%', thisYearSale: '96%', lastYearProfit: '$423,132', thisYearProfit: '$312,122'}, + {brand: 'Microsoft', lastYearSale: '38%', thisYearSale: '5%', lastYearProfit: '$12,321', thisYearProfit: '$8,500'}, + {brand: 'Philips', lastYearSale: '49%', thisYearSale: '22%', lastYearProfit: '$745,232', thisYearProfit: '$650,323,'}, + {brand: 'Song', lastYearSale: '17%', thisYearSale: '79%', lastYearProfit: '$643,242', thisYearProfit: '500,332'}, + {brand: 'LG', lastYearSale: '52%', thisYearSale: ' 65%', lastYearProfit: '$421,132', thisYearProfit: '$150,005'}, + {brand: 'Sharp', lastYearSale: '82%', thisYearSale: '12%', lastYearProfit: '$131,211', thisYearProfit: '$100,214'}, + {brand: 'Panasonic', lastYearSale: '44%', thisYearSale: '45%', lastYearProfit: '$66,442', thisYearProfit: '$53,322'}, + {brand: 'HTC', lastYearSale: '90%', thisYearSale: '56%', lastYearProfit: '$765,442', thisYearProfit: '$296,232'}, + {brand: 'Toshiba', lastYearSale: '75%', thisYearSale: '54%', lastYearProfit: '$21,212', thisYearProfit: '$12,533'} + ]; + } +} diff --git a/src/app/showcase/components/datatable/datatablecolreorderdemo.html b/src/app/showcase/components/datatable/datatablecolreorderdemo.html new file mode 100644 index 00000000000..2c084bf1980 --- /dev/null +++ b/src/app/showcase/components/datatable/datatablecolreorderdemo.html @@ -0,0 +1,51 @@ + + +
        +
        + DataTable + Columns can be reordered using drag drop by setting the reorderableColumns to true. onColReorder is a callback that is invoked when a column is reordered. +
        +
        + +
        + + + + + + +
        + +
        + + +
        +
        +export class DataTableColReorderDemo implements OnInit {
        +
        +    cars: Car[];
        +
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsSmall().then(cars => this.cars = cars);
        +    }
        +}
        +
        +
        +
        + + +
        +
        +<p-dataTable [value]="cars" reorderableColumns="true">
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatablecolreorderdemo.ts b/src/app/showcase/components/datatable/datatablecolreorderdemo.ts new file mode 100644 index 00000000000..805025f2cf1 --- /dev/null +++ b/src/app/showcase/components/datatable/datatablecolreorderdemo.ts @@ -0,0 +1,17 @@ +import {Component,OnInit} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; + +@Component({ + templateUrl: './datatablecolreorderdemo.html' +}) +export class DataTableColReorderDemo implements OnInit { + + cars: Car[]; + + constructor(private carService: CarService) { } + + ngOnInit() { + this.carService.getCarsSmall().then(cars => this.cars = cars); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatablecolresizedemo.html b/src/app/showcase/components/datatable/datatablecolresizedemo.html new file mode 100644 index 00000000000..7196788d712 --- /dev/null +++ b/src/app/showcase/components/datatable/datatablecolresizedemo.html @@ -0,0 +1,71 @@ + + +
        +
        + DataTable + Columns can be resized using drag drop by setting the resizableColumns to true. There are two resize modes; "fit" and "expand". Fit is the default one and + the overall table width does not change when a column is resized. In "expand" mode, table width also changes along with the column width. onColumnResize + is a callback that passes the resized column header as a parameter. +
        +
        + +
        +

        Fit Mode

        + + + + + + + +

        Expand Mode

        + + + + + + +
        + +
        + + +
        +
        +export class DataTableColResizeDemo implements OnInit {
        +
        +    cars: Car[];
        +
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsSmall().then(cars => this.cars = cars);
        +    }
        +}
        +
        +
        +
        + + +
        +
        +<h3 class="first">Fit Mode</h3>
        +<p-dataTable [value]="cars" resizableColumns="true">
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +<h3>Expand Mode</h3>
        +<p-dataTable [value]="cars" resizableColumns="true" columnResizeMode="expand">
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatablecolresizedemo.ts b/src/app/showcase/components/datatable/datatablecolresizedemo.ts new file mode 100644 index 00000000000..cfb1755b473 --- /dev/null +++ b/src/app/showcase/components/datatable/datatablecolresizedemo.ts @@ -0,0 +1,17 @@ +import {Component,OnInit} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; + +@Component({ + templateUrl: './datatablecolresizedemo.html' +}) +export class DataTableColResizeDemo implements OnInit { + + cars: Car[]; + + constructor(private carService: CarService) { } + + ngOnInit() { + this.carService.getCarsSmall().then(cars => this.cars = cars); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatablecoltogglerdemo.html b/src/app/showcase/components/datatable/datatablecoltogglerdemo.html new file mode 100644 index 00000000000..cd149b9e7da --- /dev/null +++ b/src/app/showcase/components/datatable/datatablecoltogglerdemo.html @@ -0,0 +1,71 @@ + + +
        +
        + DataTable - Column Toggler + This demo uses a multiselect component to implement toggleable columns. +
        +
        + +
        + + +
        + +
        +
        + +
        +
        + +
        + + +
        +
        +export class DataTableColTogglerDemo implements OnInit {
        +
        +    cars: Car[];
        +    
        +    cols: any[];
        +    
        +    columnOptions: SelectItem[];
        +        
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsSmall().then(cars => this.cars = cars);
        +        
        +        this.cols = [
        +            {field: 'vin', header: 'Vin'},
        +            {field: 'year', header: 'Year'},
        +            {field: 'brand', header: 'Brand'},
        +            {field: 'color', header: 'Color'}
        +        ];
        +        
        +        this.columnOptions = [];
        +        for(let i = 0; i < this.cols.length; i++) {
        +            this.columnOptions.push({label: this.cols[i].header, value: this.cols[i]});
        +        }
        +    }
        +}
        +
        +
        +
        + + +
        +
        +<p-dataTable [value]="cars">
        +    <p-header>
        +        <div style="text-align:left">
        +            <p-multiSelect [options]="columnOptions" [(ngModel)]="cols"></p-multiSelect>
        +        </div>
        +    </p-header>
        +    <p-column *ngFor="let col of cols" [field]="col.field" [header]="col.header"></p-column>
        +</p-dataTable>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatablecoltogglerdemo.ts b/src/app/showcase/components/datatable/datatablecoltogglerdemo.ts new file mode 100644 index 00000000000..efa9d2ffe4d --- /dev/null +++ b/src/app/showcase/components/datatable/datatablecoltogglerdemo.ts @@ -0,0 +1,34 @@ +import {Component,OnInit} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; +import {SelectItem} from '../../../components/common/api'; + +@Component({ + templateUrl: './datatablecoltogglerdemo.html' +}) +export class DataTableColTogglerDemo implements OnInit { + + cars: Car[]; + + cols: any[]; + + columnOptions: SelectItem[]; + + constructor(private carService: CarService) { } + + ngOnInit() { + this.carService.getCarsSmall().then(cars => this.cars = cars); + + this.cols = [ + {field: 'vin', header: 'Vin'}, + {field: 'year', header: 'Year'}, + {field: 'brand', header: 'Brand'}, + {field: 'color', header: 'Color'} + ]; + + this.columnOptions = []; + for(let i = 0; i < this.cols.length; i++) { + this.columnOptions.push({label: this.cols[i].header, value: this.cols[i]}); + } + } +} \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatablecruddemo.html b/src/app/showcase/components/datatable/datatablecruddemo.html new file mode 100644 index 00000000000..a8ca5862269 --- /dev/null +++ b/src/app/showcase/components/datatable/datatablecruddemo.html @@ -0,0 +1,165 @@ + + +
        +
        + DataTable + This samples demonstrates a CRUD implementation using various PrimeNG components. +
        +
        + +
        + + CRUD for Cars + + + + +
        +
        + + +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        + +
        + + +
        +
        +
        +
        + +
        + + +
        +
        +export class DataTableCrudDemo implements OnInit {
        +
        +    displayDialog: boolean;
        +
        +    car: Car = new PrimeCar();
        +    
        +    selectedCar: Car;
        +    
        +    newCar: boolean;
        +
        +    cars: Car[];
        +
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsSmall().then(cars => this.cars = cars);
        +    }
        +    
        +    showDialogToAdd() {
        +        this.newCar = true;
        +        this.car = new PrimeCar();
        +        this.displayDialog = true;
        +    }
        +    
        +    save() {
        +        let cars = [...this.cars];
        +        if(this.newCar)
        +            cars.push(this.car);
        +        else
        +            cars[this.findSelectedCarIndex()] = this.car;
        +        
        +        this.cars = cars;
        +        this.car = null;
        +        this.displayDialog = false;
        +    }
        +    
        +    delete() {
        +        let index = this.findSelectedCarIndex();
        +        this.cars = this.cars.filter((val,i) => i!=index);
        +        this.car = null;
        +        this.displayDialog = false;
        +    }    
        +    
        +    onRowSelect(event) {
        +        this.newCar = false;
        +        this.car = this.cloneCar(event.data);
        +        this.displayDialog = true;
        +    }
        +    
        +    cloneCar(c: Car): Car {
        +        let car = new PrimeCar();
        +        for(let prop in c) {
        +            car[prop] = c[prop];
        +        }
        +        return car;
        +    }
        +    
        +    findSelectedCarIndex(): number {
        +        return this.cars.indexOf(this.selectedCar);
        +    }
        +}
        +
        +class PrimeCar implements Car {
        +    
        +    constructor(public vin?, public year?, public brand?, public color?) {}
        +}
        +
        +
        +
        + + +
        +
        +<p-dataTable [value]="cars" selectionMode="single" [(selection)]="selectedCar" (onRowSelect)="onRowSelect($event)" [paginator]="true" rows="15" [responsive]="true">
        +    <p-header>CRUD for Cars</p-header>
        +    <p-column field="vin" header="Vin" [sortable]="true"></p-column>
        +    <p-column field="year" header="Year" [sortable]="true"></p-column>
        +    <p-column field="brand" header="Brand" [sortable]="true"></p-column>
        +    <p-column field="color" header="Color" [sortable]="true"></p-column>
        +    <p-footer><div class="ui-helper-clearfix" style="width:100%"><button type="button" pButton icon="fa-plus" style="float:left" (click)="showDialogToAdd()" label="Add"></button></div></p-footer>
        +</p-dataTable>
        +
        +<p-dialog header="Car Details" [(visible)]="displayDialog" [responsive]="true" showEffect="fade" [modal]="true">
        +    <div class="ui-grid ui-grid-responsive ui-fluid" *ngIf="car">
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4"><label for="vin">Vin</label></div>
        +            <div class="ui-grid-col-8"><input pInputText id="vin" [(ngModel)]="car.vin" /></div>
        +        </div>
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4"><label for="year">Year</label></div>
        +            <div class="ui-grid-col-8"><input pInputText id="year" [(ngModel)]="car.year" /></div>
        +        </div>
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4"><label for="brand">Brand</label></div>
        +            <div class="ui-grid-col-8"><input pInputText id="brand" [(ngModel)]="car.brand" /></div>
        +        </div>
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4"><label for="color">Color</label></div>
        +            <div class="ui-grid-col-8"><input pInputText id="color" [(ngModel)]="car.color" /></div>
        +        </div>
        +    </div>
        +    <p-footer>
        +        <div class="ui-dialog-buttonpane ui-helper-clearfix">
        +            <button type="button" pButton icon="fa-close" (click)="delete()" label="Delete"></button>
        +            <button type="button" pButton icon="fa-check" (click)="save()" label="Save"></button>
        +        </div>
        +    </p-footer>
        +</p-dialog>
        +
        +
        +
        +
        +
        diff --git a/src/app/showcase/components/datatable/datatablecruddemo.ts b/src/app/showcase/components/datatable/datatablecruddemo.ts new file mode 100644 index 00000000000..3bacdd9c061 --- /dev/null +++ b/src/app/showcase/components/datatable/datatablecruddemo.ts @@ -0,0 +1,82 @@ +import {Component,OnInit} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; + +@Component({ + templateUrl: './datatablecruddemo.html', + styles: [` + .ui-grid-row div { + padding: 4px 10px + } + + .ui-grid-row div label { + font-weight: bold; + } + `] +}) +export class DataTableCrudDemo implements OnInit { + + displayDialog: boolean; + + car: Car = new PrimeCar(); + + selectedCar: Car; + + newCar: boolean; + + cars: Car[]; + + constructor(private carService: CarService) { } + + ngOnInit() { + this.carService.getCarsSmall().then(cars => this.cars = cars); + } + + showDialogToAdd() { + this.newCar = true; + this.car = new PrimeCar(); + this.displayDialog = true; + } + + save() { + let cars = [...this.cars]; + if(this.newCar) + cars.push(this.car); + else + cars[this.findSelectedCarIndex()] = this.car; + + this.cars = cars; + this.car = null; + this.displayDialog = false; + } + + delete() { + let index = this.findSelectedCarIndex(); + this.cars = this.cars.filter((val,i) => i!=index); + this.car = null; + this.displayDialog = false; + } + + onRowSelect(event) { + this.newCar = false; + this.car = this.cloneCar(event.data); + this.displayDialog = true; + } + + cloneCar(c: Car): Car { + let car = new PrimeCar(); + for(let prop in c) { + car[prop] = c[prop]; + } + return car; + } + + findSelectedCarIndex(): number { + return this.cars.indexOf(this.selectedCar); + } +} + +class PrimeCar implements Car { + + constructor(public vin?, public year?, public brand?, public color?) {} +} \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatabledemo-routing.module.ts b/src/app/showcase/components/datatable/datatabledemo-routing.module.ts new file mode 100644 index 00000000000..86b885c78f3 --- /dev/null +++ b/src/app/showcase/components/datatable/datatabledemo-routing.module.ts @@ -0,0 +1,53 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {DataTableDemo} from './datatabledemo'; +import {DataTableCMDemo} from './datatablecmdemo'; +import {DataTableColReorderDemo} from './datatablecolreorderdemo'; +import {DataTableColResizeDemo} from './datatablecolresizedemo'; +import {DataTableColTogglerDemo} from './datatablecoltogglerdemo'; +import {DataTableCrudDemo} from './datatablecruddemo'; +import {DataTableEditableDemo} from './datatableeditabledemo'; +import {DataTableExportDemo} from './datatableexportdemo'; +import {DataTableFacetsDemo} from './datatablefacetsdemo'; +import {DataTableFilterDemo} from './datatablefilterdemo'; +import {DataTableColGroupDemo} from './datatablecolgroupdemo'; +import {DataTableRowGroupDemo} from './datatablerowgroupdemo'; +import {DataTableLazyDemo} from './datatablelazydemo'; +import {DataTablePaginatorDemo} from './datatablepaginatordemo'; +import {DataTableResponsiveDemo} from './datatableresponsivedemo'; +import {DataTableRowExpansionDemo} from './datatablerowexpansiondemo'; +import {DataTableScrollDemo} from './datatablescrolldemo'; +import {DataTableSelectionDemo} from './datatableselectiondemo'; +import {DataTableSortDemo} from './datatablesortdemo'; +import {DataTableTemplatingDemo} from './datatabletemplatingdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path: '', component: DataTableDemo}, + {path: 'facets', component: DataTableFacetsDemo}, + {path: 'paginator', component: DataTablePaginatorDemo}, + {path: 'sort', component: DataTableSortDemo}, + {path: 'responsive', component: DataTableResponsiveDemo}, + {path: 'selection', component: DataTableSelectionDemo}, + {path: 'filter', component: DataTableFilterDemo}, + {path: 'editable', component: DataTableEditableDemo}, + {path: 'colresize', component: DataTableColResizeDemo}, + {path: 'colreorder', component: DataTableColReorderDemo}, + {path: 'scroll', component: DataTableScrollDemo}, + {path: 'colgroup', component: DataTableColGroupDemo}, + {path: 'rowgroup', component: DataTableRowGroupDemo}, + {path: 'lazy', component: DataTableLazyDemo}, + {path: 'crud', component: DataTableCrudDemo}, + {path: 'templating', component: DataTableTemplatingDemo}, + {path: 'contextmenu', component: DataTableCMDemo}, + {path: 'coltoggler', component: DataTableColTogglerDemo}, + {path: 'rowexpansion', component: DataTableRowExpansionDemo}, + {path: 'export', component: DataTableExportDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class DatatableDemoRoutingModule {} diff --git a/src/app/showcase/components/datatable/datatabledemo.html b/src/app/showcase/components/datatable/datatabledemo.html new file mode 100644 index 00000000000..22206da8e36 --- /dev/null +++ b/src/app/showcase/components/datatable/datatabledemo.html @@ -0,0 +1,1615 @@ + + +
        +
        + DataTable + DataTable displays data in tabular format. +
        +
        + +
        +

        Basic

        + + + + + + + +

        Dynamic Columns

        + + + +
        + +
        + + +

        Import

        +
        +
        +import {DataTableModule,SharedModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        DataTable requires a value as an array of objects and columns defined with p-column component. Throughout the samples, a car interface having + vin, brand, year and color properties is used to define an object to be displayed by the datatable. Cars are loaded by a CarService that + connects to a server to fetch the cars with a Promise. +

        +
        +
        +export interface Car {
        +    vin;
        +    year;
        +    brand;
        +    color;
        +}
        +
        +
        + +
        +
        +import {Injectable} from 'angular2/core';
        +import {Http, Response} from 'angular2/http';
        +import {Car} from '../domain/car';
        +    
        +@Injectable()
        +export class CarService {
        +    
        +    constructor(private http: Http) {}
        +
        +    getCarsSmall() {
        +        return this.http.get('/showcase/resources/data/cars-small.json')
        +                    .toPromise()
        +                    .then(res => <Car[]> res.json().data)
        +                    .then(data => { return data; });
        +    }
        +}
        +
        +
        +

        Following sample datatable has 4 columns and retrieves the data from a service on init.

        + +
        +
        +export class DataTableDemo implements OnInit {
        +
        +    cars: Car[];
        +
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsSmall().then(cars => this.cars = cars);
        +    }
        +}
        +
        +
        + +

        List of cars are bound to the value property and columns are defined using p-column component.

        +
        +
        +<p-dataTable [value]="cars">
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +
        + +

        Column Component

        +

        Column component defines various options to specify corresponding features.

        +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        fieldstringnullProperty of a row data.
        sortFieldstringnullProperty of a row data used for sorting, defaults to field.
        headerstringnullHeader text of a column.
        footerstringnullFooter text of a column.
        sortableanyfalseDefines if a column is sortable.
        sortFunctionfunctionnullSort function for custom sorting.
        editablebooleanfalseDefines if a column is editable.
        filterbooleanfalseDefines if a column can be filtered.
        filterMatchModestringnullDefines filterMatchMode; "startsWith", "contains", "endsWidth", "equals", "notEquals" and "in".
        filterTypestringtextType of the filter input field.
        filterPlaceholderstringnullDefines placeholder of the input fields.
        rowspanstringnullNumber of rows to span for grouping.
        colspanstringnullNumber of columns to span for grouping.
        styleobjectnullInline style of the column.
        styleClassstringnullStyle class of the column.
        tableStylestringnullInline style of the table element.
        tableStyleClassstringnullStyle class of the table element.
        hiddenbooleanfalseControls visiblity of the column.
        expanderbooleanfalseDisplays an icon to toggle row expansion.
        selectionModestringnullDefines column based selection mode, options are "single" and "multiple".
        frozenbooleanfalseWhether the column is fixed in horizontal scrolling or not.
        +
        + +
        +
        +<p-column field="vin" header="Vin" [sortable]="true"></p-column>
        +
        +
        + +

        Dynamic Colums

        +

        Columns can be instantiated using an array as well by iterating with ngFor.

        +
        +
        +export class DataTableDemo implements OnInit {
        +
        +    cars: Car[];
        +    
        +    cols: any[];
        +
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsSmall().then(cars => this.cars = cars);
        +        
        +        this.cols = [
        +            {field: 'vin', header: 'Vin'},
        +            {field: 'year', header: 'Year'},
        +            {field: 'brand', header: 'Brand'},
        +            {field: 'color', header: 'Color'}
        +        ];
        +    }
        +}
        +
        +
        + +
        +
        +<p-dataTable [value]="cars">
        +    <p-column *ngFor="let col of cols" [field]="col.field" [header]="col.header"></p-column>
        +</p-dataTable>
        +
        +
        + +

        Managing Data

        +

        DataTable uses setter based checking to realize if the underlying data has changed to update the UI so your data changes such as adding or removing a record + should always create a new array reference instead of manipulating an existing array. For example, use slice instead of splice when removing an item + or use spread operator instead of push method when adding an item.

        + +

        Templates

        +

        Field data of a corresponding row is displayed as the cell content by default, this can be customized using templating where the implicit variable passed to the ng-template + is the column definition and data of current row is the rowData property. In addition index of the current can be accessed using the optional rowIndex variable. + Similarly, custom content can be placed at the header and footer of a column with templating.

        + +

        A ng-template inside a column must be decorated with pTemplate directive along with the type to indicate where the ng-template belongs to. Possible values + are "header", "body" and "footer".

        +
        +
        +<p-column field="color" header="Color">
        +    <ng-template let-col let-car="rowData" let-ri="rowIndex" pTemplate="body">
        +        <span>{{car[col.field]}}</span>
        +    </ng-template>
        +</p-column>
        +<p-column>
        +    <ng-template pTemplate="header">
        +        <button type="button" pButton (click)="selectAllCars()" icon="fa-check"></button>
        +    </ng-template>
        +    <ng-template let-car="rowData" pTemplate="body">
        +        <button type="button" pButton (click)="selectCar(car)" icon="fa-search"></button>
        +    </ng-template>
        +</p-column>
        +
        +
        + +

        Index of the row is available at the ng-template.

        +
        +
        +    <p-column>
        +        <ng-template let-car="rowData" let-i="rowIndex" pTemplate="body">
        +            <button type="button" pButton (click)="selectCar(i)" icon="fa-search"></button>
        +        </ng-template>
        +    </p-column>
        +
        +
        + +

        See the live example.

        + +

        Facets

        +

        Header and Footer are the two sections aka facets that are capable of displaying custom content.

        +
        +
        +import {Header} from 'primeng/primeng';
        +import {Footer} from 'primeng/primeng';
        +
        +
        +
        +
        +<p-dataTable [value]="cars">
        +    <p-header>List of Cars</p-header>
        +    <p-footer>Choose from the list.</p-footer>
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +
        +

        See the live example.

        + +

        Column Grouping

        +

        Columns can be grouped at header and footer using headerColumnGroup and footerColumnGroup components containing rows with + columns. Templating is also supported inside grouped columns.

        +
        +
        +<p-dataTable [value]="sales">
        +    <p-headerColumnGroup>
        +        <p-row>
        +            <p-column header="Brand" rowspan="3"></p-column>
        +            <p-column header="Sale Rate" colspan="4"></p-column>
        +        </p-row>
        +        <p-row>
        +            <p-column header="Sales" colspan="2"></p-column>
        +            <p-column header="Profits" colspan="2"></p-column>
        +        </p-row>
        +        <p-row>
        +            <p-column header="Last Year"></p-column>
        +            <p-column header="This Year"></p-column>
        +            <p-column header="Last Year"></p-column>
        +            <p-column header="This Year"></p-column>
        +        </p-row>
        +    </p-headerColumnGroup>
        +    
        +    <p-column field="brand"></p-column>
        +    <p-column field="lastYearSale"></p-column>
        +    <p-column field="thisYearSale"></p-column>
        +    <p-column field="lastYearProfit"></p-column>
        +    <p-column field="thisYearProfit"></p-column>
        +    
        +    <p-footerColumnGroup>
        +        <p-row>
        +            <p-column footer="Totals:" colspan="3"></p-column>
        +            <p-column footer="$506,202"></p-column>
        +            <p-column footer="$531,020"></p-column>
        +        </p-row>
        +    </p-footerColumnGroup>
        +</p-dataTable>
        +
        +
        +

        See the live example.

        + +

        Row Grouping

        +

        Rows can either be grouped by a separate grouping row or using rowspan. In both cases, data has to be sorted by the grouping field initially.

        +
        +
        +<p-dataTable [value]="cars1" sortField="brand" rowGroupMode="subheader" groupField="brand">
        +    <p-header>Subheader</p-header>
        +    <ng-template pTemplate="rowgroupheader" let-rowData>{{rowData['brand']}}</ng-template>
        +    <p-column field="color" header="Color"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="vin" header="Vin"></p-column>
        +</p-dataTable>
        +
        +<p-dataTable [value]="cars2" sortField="brand" rowGroupMode="rowspan">
        +    <p-header>RowSpan</p-header>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="vin" header="Vin"></p-column>
        +</p-dataTable>
        +
        +
        + +

        Visibility of a group can be toggled using an icon placed next to the group name using expandableRowGroups property. + By default all groups are collapsed and expandadRowGroups property needs to be populated with the group field values + to show particular groups as expanded by default.

        +
        +
        +<p-dataTable [value]="cars" sortField="brand" rowGroupMode="subheader" groupField="brand" expandableRowGroups="true">
        +    <p-header>Subheader</p-header>
        +    <ng-template pTemplate="rowgroup" let-rowData>{{rowData['brand']}}</ng-template>
        +    <p-column field="color" header="Color"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="vin" header="Vin"></p-column>
        +</p-dataTable>
        +
        +
        + +

        A footer for a row can be defined using the rowgroupfooter ng-template.

        +
        +
        +<p-dataTable [value]="cars" sortField="brand" rowGroupMode="subheader" groupField="brand" expandableRowGroups="true"
        +        [sortableRowGroup]="false">
        +    <p-header>Toggleable Row Groups with Footers</p-header>
        +    <ng-template pTemplate="rowgroupheader" let-rowData>{{rowData['brand']}}</ng-template>
        +    <p-column field="color" header="Color"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="price" header="Price">
        +        <ng-template let-col let-car="rowData" pTemplate="body">
        +            <span>{{car[col.field] | currency:'USD':true:'.0-0'}}</span>
        +        </ng-template>
        +    </p-column>
        +    <ng-template pTemplate="rowgroupfooter" let-car>
        +        <td colspan="3" style="text-align:right">Total Price</td>
        +        <td>{{calculateGroupTotal(car['brand']) | currency:'USD':true:'.0-0' }}</td>
        +    </ng-template>
        +</p-dataTable>
        +
        +
        + +

        Clicking a row group sorts the data according to the group field, you can control this behavior using sortableRowGroup property.

        + +

        See the live example.

        + +

        Paginator

        +

        Pagination is enabled by setting paginator property to true, rows attribute defines the number of rows per page and pageLinks specify the the number + of page links to display. See paginator component for more information.

        +
        +
        +<p-dataTable [value]="cars" [rows]="10" [paginator]="true">
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +
        +

        See the live example.

        + +

        Sorting

        +

        Simply enabling sortable property at column object is enough to make a column sortable. The property to use when + sorting is field by default and this can be customized using sortField.

        +
        +
        +<p-column field="vin" header="Vin" sortable="true"></p-column>
        +
        +
        +

        By default sorting is executed on the clicked column. To do multiple field sorting, set sortMode property to "multiple" and use metakey + when clicking on another column.

        +
        +
        +<p-dataTable [value]="cars" [sortMode]="multiple">
        +
        +
        + +

        In case you'd like to display the table as sorted by default initially on load, use the sortField-sortOrder properties in single mode.

        +
        +
        +<p-dataTable [value]="cars" sortField="year" [sortOrder]="1">
        +    <p-column field="vin" header="Vin" sortable="true"></p-column>
        +    <p-column field="year" header="Year" sortable="true"></p-column>
        +    <p-column field="brand" header="Brand" sortable="true"></p-column>
        +    <p-column field="color" header="Color" sortable="true"></p-column>
        +</p-dataTable>
        +
        +
        +

        In multiple mode, use the multiSortMeta property and bind an array of SortMeta objects.

        +
        +
        +<p-dataTable [value]="cars" [multiSortMeta]="multiSortMeta">
        +    <p-column field="vin" header="Vin" sortable="true"></p-column>
        +    <p-column field="year" header="Year" sortable="true"></p-column>
        +    <p-column field="brand" header="Brand" sortable="true"></p-column>
        +    <p-column field="color" header="Color" sortable="true"></p-column>
        +</p-dataTable>
        +
        +
        + +
        +
        +this.multiSortMeta = [];
        +this.multiSortMeta.push({field: 'year', order: 1});
        +this.multiSortMeta.push({field: 'brand', order: -1});
        +
        +
        + +

        To customize sorting, set sortable option to custom and define a sortFunction that sorts the list.

        +
        +
        +<p-dataTable [value]="cars" [multiSortMeta]="multiSortMeta">
        +    <p-column field="vin" header="Vin" sortable="true"></p-column>
        +    <p-column field="year" header="Year" sortable="custom" (sortFunction)="mysort($event)"></p-column>
        +    <p-column field="brand" header="Brand" sortable="true"></p-column>
        +    <p-column field="color" header="Color" sortable="true"></p-column>
        +</p-dataTable>
        +
        +
        + +
        +
        +mysort(event) {
        +    //event.field = Field to sort
        +    //event.order = Sort order
        +}
        +
        +
        + +

        See the live example.

        + +

        Filtering

        +

        Filtering is enabled by setting the filter property as true on a column. Default match mode is "startsWith" and this can be configured + using filterMatchMode property that also accepts "contains", "endsWith", "equals" and "in".

        +
        +
        +<p-column field="vin" header="Vin (startsWith)" [filter]="true" filterPlaceholder="Search"></p-column>
        +<p-column field="year" header="Year (contains)" [filter]="true" filterMatchMode="contains"></p-column>
        +<p-column field="brand" header="Brand (startsWith)" [filter]="true"></p-column>
        +<p-column field="color" header="Color (endsWith)" [filter]="true" filterMatchMode="endsWith"></p-column>
        +
        +
        +

        An optional global filter feature is available to search all fields with the same keyword, to enable this place an input component whose keyup event would be + listened for filtering and bind the local ng-template variable name of it to the global filter property.

        +
        +
        +<input #gb type="text" placeholder="Global search">
        +<p-dataTable [value]="cars" [rows]="10" [globalFilter]="gb">
        +
        +
        + +

        By default, input fields are used as filter elements and this can be customized using templating. It is important to use the on change callback + of the filter component to call the filter method of datatable by passing the value, field and matchmode properties.

        +
        +
        +<p-column field="brand" header="Brand (Custom)" [filter]="true" [style]="{'overflow':'visible'}" filterMatchMode="equals">
        +    <ng-template pTemplate="filter" let-col>
        +        <p-dropdown [options]="brands" [style]="{'width':'100%'}" (onChange)="dt.filter($event.value,col.field,col.filterMatchMode)" styleClass="ui-column-filter"></p-dropdown>
        +    </ng-template>
        +</p-column>
        +
        +
        + +

        See the live example.

        + +

        Selection

        +

        DataTable provides single and multiple selection modes on click of a row. Selected rows are bound to the selection property and onRowSelect-onRowUnselect events + are provided as optional callbacks. Alternatively column based selection can be done using radio buttons or checkboxes using selectionMode of a particular column. + When comparing if a row is selected, DataTable traverses all properties of the object which affects performance as a result. It is suggested to define a dataKey property + that uniquely identifies a record to avoid deep object comparison and increase performance.

        +

        In single mode, selection binding is an object reference.

        +
        +
        +export class DataTableDemo implements OnInit {
        +
        +    cars: Car[];
        +    
        +    selectedCar: Car;
        +
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsSmall().then(cars => this.cars = cars);
        +    }
        +}
        +
        +
        +
        +
        +<p-dataTable [value]="cars" selectionMode="single" [(selection)]="selectedCar" dataKey="vin">
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +
        + +

        In multiple mode, selection binding should be an array and multiple items can either be selected + using metaKey or toggled individually depending on the value of metaKeySelection property value which is true by default. On touch enabled + devices metaKeySelection is turned off automatically.

        +
        +
        +export class DataTableDemo implements OnInit {
        +
        +    cars: Car[];
        +    
        +    selectedCars: Car[];
        +
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsSmall().then(cars => this.cars = cars);
        +    }
        +}
        +
        +
        +
        +
        +<p-dataTable [value]="cars" selectionMode="multiple" [(selection)]="selectedCars" dataKey="vin">
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +
        + +

        If you prefer a radioButton or a checkbox instead of a row click, use the selectionMode of a column instead. Following datatable + displays a checkbox at the first column of each row and automatically adds a header checkbox to toggle selection of all rows.

        +
        +
        +<p-dataTable [value]="cars" [(selection)]="selectedCars" dataKey="vin">
        +    <p-column selectionMode="multiple"></p-column>
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +
        + +

        See the live example.

        + +

        ContextMenu

        +

        DataTable has exclusive integration with contextmenu component. In order to attach a menu to a datatable, define a local template + variable for the menu and bind it to the contextMenu property of the datatable. This enables showing the menu whenever a row is right clicked.

        +
        +
        +<p-dataTable [value]="cars" selectionMode="single" [(selection)]="selectedCar" [contextMenu]="cm">
        +    <p-header>Right Click on Rows for ContextMenu</p-header>
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +<p-contextMenu #cm [model]="items"></p-contextMenu>
        +
        +
        + +

        See the live example.

        + +

        Editing

        +

        Incell editing is enabled by setting editable property true both on datatable and columns. Clicking a cell switches to edit mode + and hitting enter key or clicking another cell switches it back to view mode.

        +
        +
        +<p-dataTable [value]="cars" [editable]="true">
        +    <p-column field="vin" header="Vin" [editable]="true"></p-column>
        +    <p-column field="year" header="Year" [editable]="true"></p-column>
        +    <p-column field="brand" header="Brand" [editable]="true"></p-column>
        +    <p-column field="color" header="Color" [editable]="true"></p-column>
        +</p-dataTable>
        +
        +
        + +

        Simple input fields are used as the editor elements by default and this can be customized by adding a pTemplate named editor.

        +
        +
        +<p-dataTable [value]="cars" [editable]="true">
        +    <p-column field="vin" header="Vin" [editable]="true"></p-column>
        +    <p-column field="year" header="Year" [editable]="true"></p-column>
        +    <p-column field="brand" header="Brand" [editable]="true" [style]="{'overflow':'visible'}">
        +        <ng-template let-col let-car="rowData" pTemplate="editor">
        +            <p-dropdown [(ngModel)]="car[col.field]" [options]="brands" [autoWidth]="false" [style]="{'width':'100%'}" required="true"></p-dropdown>
        +        </ng-template>
        +    </p-column>
        +    <p-column field="color" header="Color" [editable]="true"></p-column>
        +    <p-column field="saleDate" header="Sale Date" [editable]="true" [style]=" {'overflow':'visible' }">
        +        <ng-template let-col let-car="rowData" pTemplate="body">
        +             {{car[col.field]|date }}
        +        </ng-template>
        +        <ng-template let-col let-car="rowData" pTemplate="editor">
        +            <p-calendar [(ngModel)]="car[col.field]"></p-calendar>
        +        </ng-template>
        +    </p-column>
        +</p-dataTable>
        +
        +
        + +

        See the live example.

        + +

        Expandable Rows

        +

        Row expansion allows displaying detailed content for a particular row. To use this feature, enable expandableRows property, add an expander column and + to declare the expanded content provide a pTemplate with "rowexpansion" as the value.

        +
        +
        +<p-dataTable [value]="cars" expandableRows="true">
        +    <p-column expander="true" [style]="{'width':'22px'}"></p-column>
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +    <ng-template let-car pTemplate="rowexpansion">
        +        <div class="ui-grid ui-grid-responsive ui-fluid" style="font-size:16px;padding:20px">
        +            <div class="ui-grid-row">
        +                <div class="ui-grid-col-3" style="text-align:center">
        +                    <img src="showcase/resources/demo/images/car/{{car.brand}}-big.gif">
        +                </div>
        +                <div class="ui-grid-col-9">
        +                    <div class="ui-grid ui-grid-responsive ui-grid-pad">
        +                        <div class="ui-grid-row">
        +                            <div class="ui-grid-col-2 label">Vin: </div>
        +                            <div class="ui-grid-col-10">{{car.vin}}</div>
        +                        </div>
        +                        <div class="ui-grid-row">
        +                            <div class="ui-grid-col-2 label">Year: </div>
        +                            <div class="ui-grid-col-10">{{car.year}}</div>
        +                        </div>
        +                        <div class="ui-grid-row">
        +                            <div class="ui-grid-col-2 label">Brand: </div>
        +                            <div class="ui-grid-col-10">{{car.brand}}</div>
        +                        </div>
        +                        <div class="ui-grid-row">
        +                            <div class="ui-grid-col-2 label">Color: </div>
        +                            <div class="ui-grid-col-10">{{car.color}}</div>
        +                        </div>
        +                    </div>
        +                </div>
        +            </div>
        +        </div>
        +    </ng-template>
        +</p-dataTable>
        +
        +
        +

        By default all rows are collapsed and expandadRows property needs to be populated + with the row data instances to show particular rows as expanded by default.

        +

        See the live example.

        + +

        Column Resize

        +

        Columns can be resized using drag drop by setting the resizableColumns to true. There are two resize modes; "fit" and "expand". Fit is the default one and + the overall table width does not change when a column is resized. In "expand" mode, table width also changes along with the column width. onColumnResize + is a callback that passes the resized column header as a parameter.

        + +
        +
        +<p-dataTable [value]="cars" [resizableColumns]="true">
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +
        + +

        It is important to note that when you need to change column widths, since table width is 100%, giving fixed pixel widths does not work well as browsers scale them, instead give percentage widths.

        +
        +
        +<p-dataTable [value]="cars" [resizableColumns]="true">
        +    <p-column field="vin" header="Vin" [style]="{'width':'20%'}"></p-column>
        +    <p-column field="year" header="Year" [style]="{'width':'30%'}"></p-column>
        +    <p-column field="brand" header="Brand" [style]="{'width':'15%'}"></p-column>
        +    <p-column field="color" header="Color" [style]="{'width':'35%'}"></p-column>
        +</p-dataTable>
        +
        +
        + +

        See the live example.

        + +

        Column Reordering

        +

        Columns can be reordered using drag drop by setting the reorderableColumns to true. onColReorder is a callback that is invoked when a column is reordered.

        +
        +
        +<p-dataTable [value]="cars" [reorderableColumns]="true">
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +
        +

        See the live example.

        + +

        Data Export

        +

        DataTable can export its data in CSV format using exportCSV() method.

        +
        +
        +<p-dataTable #dt [value]="cars">
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable> 
        +
        +<button type="button" pButton icon="fa-file-o" iconPos="left" label="CSV" (click)="dt.exportCSV()"></button>
        +
        +
        +

        See the live example.

        + +

        Scrolling

        +

        DataTable supports both horizontal and vertical scrolling by defining scrollWidth and scrollHeight options respectively. The properties can take + fixed pixels values or percentages to calculate scroll viewport relative to the parent of the datatable. Sample below uses vertical scrolling where + headers are fixed and data is scrollable. In horizontal scrolling, it is important to give fixed widths to columns.

        +
        +
        +<p-dataTable [value]="cars" [scrollable]="true" scrollHeight="200px">
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +
        +

        In horizontal scrolling, certain columns can be fixed as well by enabling the frozen property at column level .

        +
        +
        +<p-dataTable [value]="cars" [scrollable]="true" scrollHeight="200px" frozenWidth="100px" scrollWidth="600px">
        +    <p-column field="vin" header="Vin" frozen="true"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +
        + +

        In this case, if frozen and scrollable cells have content with varying height, misalignment might occur. To avoid a performance hit, DataTable avoid expensive calculations + to align the row heights as it can be easily done with CSS manually.

        +
        +
        +.ui-datatable .ui-datatable-frozen-view .ui-datatable-data > tr > td,
        +.ui-datatable .ui-datatable-unfrozen-view .ui-datatable-data > tr > td {
        +    height: 24px;
        +}
        +
        +
        + +

        Additionally, virtualScroll mode enables dealing with large datasets by loading data on demand during scrolling.

        + +

        See the live example.

        + +

        Lazy Loading

        +

        Lazy mode is handy to deal with large datasets, instead of loading the entire data, small chunks of data is loaded by invoking + onLazyLoad callback everytime paging, sorting and filtering happens. To implement lazy loading, + enable lazy attribute and provide a method callback using onLazyLoad that actually loads the data from a remote datasource. onLazyLoad gets an event object + that contains information about what to load. It is also important to assign the logical number of rows to totalRecords by doing a projection query for paginator configuration so that paginator + displays the UI assuming there are actually records of totalRecords size although in reality they aren't as in lazy mode, only the records that are displayed on the current page exist.

        +
        +
        +<p-dataTable [value]="cars" [scrollable]="true" [lazy]="true" (onLazyLoad)="loadData($event)" [totalRecords]="totalRecords">
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +
        + +
        +
        +loadData(event: LazyLoadEvent) {
        +    //event.first = First row offset
        +    //event.rows = Number of rows per page
        +    //event.sortField = Field name to sort in single sort mode
        +    //event.sortOrder = Sort order as number, 1 for asc and -1 for dec in single sort mode
        +    //multiSortMeta: An array of SortMeta objects used in multiple columns sorting. Each SortMeta has field and order properties.
        +    //filters: Filters object having field as key and filter value, filter matchMode as value
        +    //globalFilter: Value of the global filter if available
        +    this.cars = //do a request to a remote datasource using a service and return the cars that match the lazy load criteria
        +}
        +
        +
        +

        See the live example.

        + +

        Responsive

        +

        DataTable columns are displayed as stacked in responsive mode if the screen size becomes smaller than a certain breakpoint value. This feature is enabled + by setting responsive to true.

        +
        +
        +<p-dataTable [value]="cars" [responsive]="true">
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +
        +

        See the live example.

        + +

        Overlays in Cells

        +

        Cells of datatable hides the overflow by default, this prevents overlay of a component like dropdown to be displayed properly. In cases like these, + set the style of the column to allow overflow.

        +
        +
        +<p-column field="color" [style]="{'overflow':'visible'}">
        +    <ng-template let-col let-car="rowData">
        +        <p-dropdown></p-dropdown>
        +    </ng-template>
        +</p-column>
        +
        +
        + +

        Loading Status

        +

        DataTable has a loading property, when enabled a spinner icon is displayed to indicate data load.

        +
        +
        +<p-dataTable [value]="cars" [loading]="loading">
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +
        + +
        +
        +export class DataTableDemo implements OnInit {
        +
        +    loading: boolean;
        +
        +    cars: Car[];
        +
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.loading = true;
        +        setTimeout(() => {
        +            this.carService.getCarsSmall().then(cars => this.cars = cars);
        +            this.loading = false;
        +        }, 1000);
        +    }
        +}
        +
        +
        + +

        Performance Tips Status

        +
          +
        • When selection is enabled use dataKey to avoid deep checking when comparing objects.
        • +
        • Use rowTrackBy that internally uses ngForTrackBy to avoid unnecessary dom operations.
        • +
        • Prefer lazy loading for large datasets.
        • +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        valuearraynullAn array of objects to display.
        headerRowsarraynullAn array of column definitions for column grouping at header.
        footerRowsarraynullAn array of column definitions for column grouping at footer.
        rowsnumbernullNumber of rows to display per page.
        paginatorbooleanfalseWhen specified as true, enables the pagination.
        totalRecordsnumbernullNumber of total records, defaults to length of value when not defined.
        pageLinksnumbernullNumber of page links to display in paginator.
        rowsPerPageOptionsarraynullArray of integer values to display inside rows per page dropdown of paginator
        alwaysShowPaginatorbooleantrueWhether to show it even there is only one page.
        sortModestringsingleDefines whether sorting works on single column or on multiple columns.
        sortFieldstringnullName of the field to sort data by default.
        sortOrdernumbernullOrder to sort the data by default.
        multiSortMetaarraynullAn array of SortMeta objects to sort the data by default in multiple sort mode.
        rowGroupModestringnullType of the row grouping, valid values are "subheader" and "rowspan".
        groupFieldstringnullName of the field to group by in subheader row grouping mode.
        sortableGroupRowbooleantrueWhether to sort the data if the row group subheader is clicked.
        expandableRowGroupsbooleanfalseWhen enabled, adds a clickable icon at group header to expand or collapse the group.
        expandedRowGroupsarraynullCollection of group field values to show a group as expanded by default.
        responsivebooleanfalseDefines if the columns should be stacked in smaller screens.
        selectionModestringnullSpecifies the selection mode, valid values are "single" and "multiple".
        headerCheckboxToggleAllPagesbooleanfalse + When set to true, the header checkbox on paged DataTables with checkbox multiple + selection enabled will toggle the selection of items across all pages. See the + live example. +
        selectionanynullSelected row in single mode or an array of values in multiple mode.
        editablebooleanfalseActivates incell editing when enabled.
        expandableRowsbooleanfalseActivates expandable rows feature when true.
        expandedRowsarraynullCollection of rows to display as expanded.
        rowExpandModestringmultipleWhether multiple rows can be expanded at any time. Valid values are "multiple" and "single".
        globalFilteranynullReference of an input field to use as a global filter.
        filterDelaynumber300Delay in milliseconds before filtering the data.
        lazybooleanfalseDefines if data is loaded and interacted with in lazy manner.
        resizableColumnsbooleanfalseWhen enabled, columns can be resized using drag and drop.
        columnResizeModebooleanfalseDefines whether the overall table width should change on column resize, valid values are "fit" and "expand".
        reorderableColumnsbooleanfalseWhen enabled, columns can be reordered using drag and drop.
        scrollablebooleanfalseWhen specifies, enables horizontal and/or vertical scrolling.
        scrollHeightnumber/stringnullHeight of the scroll viewport, can be pixel as a number or a percentage.
        scrollWidthnumber/stringnullWidth of the scroll viewport, can be pixel as a number or a percentage.
        virtualScrollbooleanfalseWhether the data should be loaded on demand during scroll.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        contextMenuContextMenunullLocal ng-template varilable of a ContextMenu.
        csvSeparatorstring,Character to use as the csv separator.
        exportFilenamestringdownloadName of the exported file.
        emptyMessagestringNo records found.Text to display when there is no data.
        paginatorPositionstringbottomPosition of the paginator, options are "top","bottom" or "both".
        rowStyleClassfunctionnullFunction that gets the row data and row index as parameters and returns a style class for the row.
        rowHoverbooleanfalseAdds hover effect to rows without the need for selectionMode.
        filtersarraynullAn array of FilterMetadata objects to provide external filters.
        metaKeySelectionbooleantrueDefines whether metaKey is requred or not for the selection. When true metaKey needs to be pressed to select or unselect an item and when set to false selection of each item + can be toggled individually. On touch enabled devices, metaKeySelection is turned off automatically.
        dataKeystringnullA property to uniquely identify a record in data.
        loadingbooleanfalseDisplays a loader to indicate data load is in progress.
        rowTrackByFunctionnullFunction to optimize the dom operations by delegating to ngForTrackBy, default algoritm checks for object identity.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onRowClickevent.originalEvent: Browser event
        + event.data: Selected data
        Callback to invoke when a row is clicked.
        onRowSelectevent.originalEvent: Browser event
        + event.data: Selected data
        + event.type: Type of selection, valid values are "row", "radiobutton" and "checkbox" +
        Callback to invoke when a row is selected.
        onRowUnselectevent.originalEvent: Browser event
        + event.data: Unselected data
        + event.type: Type of unselection, valid values are "row" and "checkbox"
        Callback to invoke when a row is unselected with metakey.
        onRowDblclickevent.originalEvent: Browser event
        + event.data: Selected data
        Callback to invoke when a row is selected with double clicked.
        onHeaderCheckboxToggleevent.originalEvent: Browser event
        + event.checked: State of the header checkbox
        Callback to invoke when state of header checkbox changes.
        onContextMenuSelectevent.originalEvent: Browser event
        + event.data: Selected data
        Callback to invoke when a row is selected with right click.
        onColResizeevent.element: Resized column header
        + event.delta: Change of width in number of pixels
        Callback to invoke when a column is resized.
        onColReorderevent.dragIndex: Index of the dragged column
        + event.dropIndex: Index of the dropped column
        + event.columns: Columns array after reorder.
        Callback to invoke when a column is reordered.
        onLazyLoadevent.first = First row offset
        + event.rows = Number of rows per page
        + event.sortField = Field name to sort with
        + event.sortOrder = Sort order as number, 1 for asc and -1 for dec
        + filters: FilterMetadata object having field as key and filter value, filter matchMode as value
        Callback to invoke when paging, sorting or filtering happens in lazy mode.
        onEditInitevent.column: Column object of the cell
        + event.data: Row data
        Callback to invoke when a cell switches to edit mode.
        onEditevent.originalEvent: Browser event + event.column: Column object of the cell
        + event.data: Row data
        + event.index: Row index
        Callback to invoke when cell data is being edited.
        onEditCompleteevent.column: Column object of the cell
        + event.data: Row data
        + event.index: Row index
        Callback to invoke when cell edit is completed.
        onEditCancelevent.column: Column object of the cell
        + event.data: Row data
        + event.index: Row index
        Callback to invoke when cell edit is cancelled with escape key.
        onPageevent.first: Index of first record in page
        + event.rows: Number of rows on the page
        Callback to invoke when pagination occurs.
        onSortevent.field: Field name of the sorted column
        + event.order: Sort order as 1 or -1
        + event.multisortmeta: Sort metadata in multi sort mode. See multiple sorting section for the structure of this object.
        Callback to invoke when a column gets sorted.
        onFilterevent.filters: Filters object having a field as the property key and an object with value, matchMode as the property value.
        + event.filteredValue: Filtered data after running the filtering.
        Callback to invoke when data is filtered.
        onRowExpandevent.originalEvent: Browser event
        + data: Row data to expand.
        Callback to invoke when a row is expanded.
        onRowCollapseevent.originalEvent: Browser event
        + data: Row data to collapse.
        Callback to invoke when a row is collapsed.
        onRowGroupExpandevent.originalEvent: Browser event
        + group: Value of the group.
        Callback to invoke when a row group is expanded.
        onRowGroupCollapseevent.originalEvent: Browser event
        + group: Value of the group.
        Callback to invoke when a row group is collapsed.
        +
        + +
        +
        +<p-dataTable [value]="cars" selectionMode="single" [(selection)]="selectedCar" (onRowSelect)="handleRowSelect($event)">
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +
        + +
        +
        +handleRowSelect(event) {
        +    //event.data = Selected row data
        +}
        +
        +
        + +

        Methods

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        reset-Resets sort, filter and paginator state.
        exportCSV-Exports the data in csv format.
        toggleRowdataToggles row expansion for given row data.
        +
        + +
        +
        +<p-dataTable #dt [value]="cars">
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +<button type="button" pButton (click)="update(dt)" label="Reset"></button>
        +
        +
        + +
        +
        +update(dt: DataTable) {
        +    dt.reset();
        +}
        +
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-datatableContainer element.
        ui-datatable-headerHeader section.
        ui-datatable-footerFooter section.
        ui-column-titleTitle of a column.
        ui-sortable-columnSortable column header.
        ui-column-filterFilter element in header.
        ui-cell-dataData cell in body.
        ui-cell-editorInput element for incell editing.
        ui-datatable-scrollable-headerContainer of header in a scrollable table.
        ui-datatable-scrollable-headerContainer of body in a scrollable table.
        ui-datatable-scrollable-headerContainer of footer in a scrollable table.
        ui-datatable-responsiveContainer element of a responsive datatable.
        ui-datatable-emptymessageCell containing the empty message.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<h3 class="first">Basic</h3>
        +<p-dataTable [value]="cars">
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +<h3>Dynamic Columns</h3>
        +<p-dataTable [value]="cars">
        +    <p-column *ngFor="let col of cols" [field]="col.field" [header]="col.header"></p-column>
        +</p-dataTable>
        +
        +
        + +
        +
        +export class DataTableDemo implements OnInit {
        +
        +    cars: Car[];
        +    
        +    cols: any[];
        +    
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsSmall().then(cars => this.cars = cars);
        +        
        +        this.cols = [
        +            {field: 'vin', header: 'Vin'},
        +            {field: 'year', header: 'Year'},
        +            {field: 'brand', header: 'Brand'},
        +            {field: 'color', header: 'Color'}
        +        ];
        +    }
        +}
        +
        +
        + + +
        +
        +
        diff --git a/src/app/showcase/components/datatable/datatabledemo.module.ts b/src/app/showcase/components/datatable/datatabledemo.module.ts new file mode 100644 index 00000000000..d0eba53c5c6 --- /dev/null +++ b/src/app/showcase/components/datatable/datatabledemo.module.ts @@ -0,0 +1,81 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {DataTableDemo} from './datatabledemo'; +import {DataTableCMDemo} from './datatablecmdemo'; +import {DataTableColReorderDemo} from './datatablecolreorderdemo'; +import {DataTableColResizeDemo} from './datatablecolresizedemo'; +import {DataTableColTogglerDemo} from './datatablecoltogglerdemo'; +import {DataTableCrudDemo} from './datatablecruddemo'; +import {DataTableEditableDemo} from './datatableeditabledemo'; +import {DataTableExportDemo} from './datatableexportdemo'; +import {DataTableFacetsDemo} from './datatablefacetsdemo'; +import {DataTableFilterDemo} from './datatablefilterdemo'; +import {DataTableColGroupDemo} from './datatablecolgroupdemo'; +import {DataTableRowGroupDemo} from './datatablerowgroupdemo'; +import {DataTableLazyDemo} from './datatablelazydemo'; +import {DataTablePaginatorDemo} from './datatablepaginatordemo'; +import {DataTableResponsiveDemo} from './datatableresponsivedemo'; +import {DataTableRowExpansionDemo} from './datatablerowexpansiondemo'; +import {DataTableScrollDemo} from './datatablescrolldemo'; +import {DataTableSelectionDemo} from './datatableselectiondemo'; +import {DataTableSortDemo} from './datatablesortdemo'; +import {DataTableTemplatingDemo} from './datatabletemplatingdemo'; +import {DataTableSubmenu} from './datatablesubmenu'; +import {DatatableDemoRoutingModule} from './datatabledemo-routing.module'; +import {DataTableModule} from '../../../components/datatable/datatable'; +import {ButtonModule} from '../../../components/button/button'; +import {DropdownModule} from '../../../components/dropdown/dropdown'; +import {CalendarModule} from '../../../components/calendar/calendar'; +import {InputTextModule} from '../../../components/inputtext/inputtext'; +import {ContextMenuModule} from '../../../components/contextmenu/contextmenu'; +import {DialogModule} from '../../../components/dialog/dialog'; +import {SliderModule} from '../../../components/slider/slider'; +import {MultiSelectModule} from '../../../components/multiselect/multiselect'; +import {GrowlModule} from '../../../components/growl/growl'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + DatatableDemoRoutingModule, + DataTableModule, + CalendarModule, + ButtonModule, + InputTextModule, + ContextMenuModule, + DropdownModule, + DialogModule, + MultiSelectModule, + SliderModule, + GrowlModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + DataTableDemo, + DataTableCMDemo, + DataTableColReorderDemo, + DataTableColResizeDemo, + DataTableColTogglerDemo, + DataTableCrudDemo, + DataTableEditableDemo, + DataTableExportDemo, + DataTableFacetsDemo, + DataTableFilterDemo, + DataTableColGroupDemo, + DataTableRowGroupDemo, + DataTableLazyDemo, + DataTablePaginatorDemo, + DataTableResponsiveDemo, + DataTableRowExpansionDemo, + DataTableScrollDemo, + DataTableSelectionDemo, + DataTableSortDemo, + DataTableTemplatingDemo, + DataTableSubmenu + ] +}) +export class DataTableDemoModule {} diff --git a/src/app/showcase/components/datatable/datatabledemo.ts b/src/app/showcase/components/datatable/datatabledemo.ts new file mode 100644 index 00000000000..be078988de6 --- /dev/null +++ b/src/app/showcase/components/datatable/datatabledemo.ts @@ -0,0 +1,33 @@ +import {Component,OnInit} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; + + +@Component({ + templateUrl: './datatabledemo.html' +}) +export class DataTableDemo implements OnInit { + + loading: boolean; + + cars: Car[]; + + cols: any[]; + + constructor(private carService: CarService) { } + + ngOnInit() { + this.loading = true; + setTimeout(() => { + this.carService.getCarsSmall().then(cars => this.cars = cars); + this.loading = false; + }, 1000); + + this.cols = [ + {field: 'vin', header: 'Vin'}, + {field: 'year', header: 'Year'}, + {field: 'brand', header: 'Brand'}, + {field: 'color', header: 'Color'} + ]; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatableeditabledemo.html b/src/app/showcase/components/datatable/datatableeditabledemo.html new file mode 100644 index 00000000000..5658d41c1f1 --- /dev/null +++ b/src/app/showcase/components/datatable/datatableeditabledemo.html @@ -0,0 +1,76 @@ + + +
        +
        + DataTable + Incell editing is enabled by setting editable property true both on datatable and columns, when a cell is clicked edit mode is activated, clicking outside of cell or hitting the enter key + switches back to view mode after updating the value. +
        +
        + +
        + + + + + + + + + + + + {{car[col.field]|date}} + + + + + + +
        + +
        + + +
        +
        +export class DataTableEditableDemo implements OnInit {
        +
        +    cars: Car[];
        +
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsSmall().then(cars => this.cars = cars);
        +    }
        +}
        +
        +
        +
        + + +
        +
        +<p-dataTable [value]="cars" [editable]="true">
        +    <p-column field="vin" header="Vin" [editable]="true"></p-column>
        +    <p-column field="year" header="Year" [editable]="true"></p-column>
        +    <p-column field="brand" header="Brand" [editable]="true" [style]="{'overflow':'visible'}">
        +        <ng-template let-col let-car="rowData" pTemplate="editor">
        +            <p-dropdown [(ngModel)]="car[col.field]" [options]="brands" [autoWidth]="false" [style]="{'width':'100%'}" required="true"></p-dropdown>
        +        </ng-template>
        +    </p-column>
        +    <p-column field="color" header="Color" [editable]="true"></p-column>
        +    <p-column field="saleDate" header="Sale Date" [editable]="true" [style]=" {'overflow':'visible' }">
        +        <ng-template let-col let-car="rowData" pTemplate="body">
        +             {{car[col.field]|date }}
        +        </ng-template>
        +        <ng-template let-col let-car="rowData" pTemplate="editor">
        +            <p-calendar [(ngModel)]="car[col.field]"></p-calendar>
        +        </ng-template>
        +    </p-column>
        +</p-dataTable>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatableeditabledemo.ts b/src/app/showcase/components/datatable/datatableeditabledemo.ts new file mode 100644 index 00000000000..51163293be2 --- /dev/null +++ b/src/app/showcase/components/datatable/datatableeditabledemo.ts @@ -0,0 +1,34 @@ +import {Component,OnInit} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; +import {SelectItem} from '../../../components/common/api'; + +@Component({ + templateUrl: './datatableeditabledemo.html' +}) +export class DataTableEditableDemo implements OnInit { + + cars: Car[]; + + brands: SelectItem[]; + + constructor(private carService: CarService) { } + + ngOnInit() { + this.carService.getCarsSmall().then(cars => this.cars = cars); + + this.brands = [ + {label: 'Choose', value: null}, + {label: 'Audi', value: 'Audi'}, + {label: 'BMW', value: 'BMW'}, + {label: 'Fiat', value: 'Fiat'}, + {label: 'Ford', value: 'Ford'}, + {label: 'Honda', value: 'Honda'}, + {label: 'Jaguar', value: 'Jaguar'}, + {label: 'Mercedes', value: 'Mercedes'}, + {label: 'Renault', value: 'Renault'}, + {label: 'VW', value: 'VW'}, + {label: 'Volvo', value: 'Volvo'} + ]; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatableexportdemo.html b/src/app/showcase/components/datatable/datatableexportdemo.html new file mode 100644 index 00000000000..2a5b78f4315 --- /dev/null +++ b/src/app/showcase/components/datatable/datatableexportdemo.html @@ -0,0 +1,64 @@ + + +
        +
        + DataTable - Export + DataTable can export its data to CSV format. +
        +
        + +
        + + + +
        + +
        +
        + + + + +
        + +
        + +
        + + +
        +
        +export class DataTableExportDemo implements OnInit {
        +
        +    cars: Car[];
        +
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsSmall().then(cars => this.cars = cars);
        +    }
        +
        +}
        +
        +
        +
        + + +
        +
        +<p-dataTable #dt [value]="cars" exportFilename="cars">
        +    <p-header>
        +        <div class="ui-helper-clearfix">
        +            <button type="button" pButton icon="fa-file-o" iconPos="left" label="CSV" (click)="dt.exportCSV()" style="float:left"></button>
        +        </div>
        +    </p-header>
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>   
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatableexportdemo.ts b/src/app/showcase/components/datatable/datatableexportdemo.ts new file mode 100644 index 00000000000..4d29ed56789 --- /dev/null +++ b/src/app/showcase/components/datatable/datatableexportdemo.ts @@ -0,0 +1,18 @@ +import {Component,OnInit} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; + +@Component({ + templateUrl: './datatableexportdemo.html' +}) +export class DataTableExportDemo implements OnInit { + + cars: Car[]; + + constructor(private carService: CarService) { } + + ngOnInit() { + this.carService.getCarsSmall().then(cars => this.cars = cars); + } + +} \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatablefacetsdemo.html b/src/app/showcase/components/datatable/datatablefacetsdemo.html new file mode 100644 index 00000000000..45c7911b143 --- /dev/null +++ b/src/app/showcase/components/datatable/datatablefacetsdemo.html @@ -0,0 +1,55 @@ + + +
        +
        + DataTable - Facets + DataTable provides header and footer sections. +
        +
        + +
        + + List of Cars + There are 10 cars + + + + + +
        + +
        + + +
        +
        +export class DataTableFacetsDemo implements OnInit {
        +
        +    cars: Car[];
        +
        +    constructor(private carService:CarService) {}
        +
        +    ngOnInit() {
        +        this.carService.getCarsSmall().then(cars => this.cars = cars);
        +    }
        +}
        +
        +
        +
        + + +
        +
        +<p-dataTable [value]="cars">
        +    <p-header>List of Cars</p-header>
        +    <p-footer>There are 10 cars</p-footer>
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatablefacetsdemo.ts b/src/app/showcase/components/datatable/datatablefacetsdemo.ts new file mode 100644 index 00000000000..b285b72c281 --- /dev/null +++ b/src/app/showcase/components/datatable/datatablefacetsdemo.ts @@ -0,0 +1,17 @@ +import {Component,OnInit} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; + +@Component({ + templateUrl: './datatablefacetsdemo.html' +}) +export class DataTableFacetsDemo implements OnInit { + + cars: Car[]; + + constructor(private carService:CarService) {} + + ngOnInit() { + this.carService.getCarsSmall().then(cars => this.cars = cars); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatablefilterdemo.html b/src/app/showcase/components/datatable/datatablefilterdemo.html new file mode 100644 index 00000000000..5cf66142f4f --- /dev/null +++ b/src/app/showcase/components/datatable/datatablefilterdemo.html @@ -0,0 +1,117 @@ + + +
        +
        + DataTable - Filter + Filtering is enabled by setting the filter property as true in column object. Default match mode is "startsWith" and this can be configured + using filterMatchMode property of column object that also accepts "contains", "endsWith", "equals" and "in". An optional global filter feature is available to search all fields with a keyword. + By default input fields are generated as filter elements and using templating any component can be used as a filter. + +
        +
        + +
        +
        + + +
        + + List of Cars + + + + + + + + + + + + + + + + + + +
        + +
        + + +
        +
        +export class DataTableFilterDemo implements OnInit {
        +
        +    cars: Car[];
        +    
        +    brands: SelectItem[];
        +    
        +    colors: SelectItem[];
        +    
        +    constructor(private carService: CarService) {}
        +
        +    ngOnInit() {
        +        this.carService.getCarsMedium().then(cars => this.cars = cars);
        +        
        +        this.brands = [];
        +        this.brands.push({label: 'All Brands', value: null});
        +        this.brands.push({label: 'Audi', value: 'Audi'});
        +        this.brands.push({label: 'BMW', value: 'BMW'});
        +        this.brands.push({label: 'Fiat', value: 'Fiat'});
        +        this.brands.push({label: 'Honda', value: 'Honda'});
        +        this.brands.push({label: 'Jaguar', value: 'Jaguar'});
        +        this.brands.push({label: 'Mercedes', value: 'Mercedes'});
        +        this.brands.push({label: 'Renault', value: 'Renault'});
        +        this.brands.push({label: 'VW', value: 'VW'});
        +        this.brands.push({label: 'Volvo', value: 'Volvo'});
        +        
        +        this.colors = [];
        +        this.colors.push({label: 'White', value: 'White'});
        +        this.colors.push({label: 'Green', value: 'Green'});
        +        this.colors.push({label: 'Silver', value: 'Silver'});
        +        this.colors.push({label: 'Black', value: 'Black'});
        +        this.colors.push({label: 'Red', value: 'Red'});
        +        this.colors.push({label: 'Maroon', value: 'Maroon'});
        +        this.colors.push({label: 'Brown', value: 'Brown'});
        +        this.colors.push({label: 'Orange', value: 'Orange'});
        +        this.colors.push({label: 'Blue', value: 'Blue'});
        +    }
        +}
        +
        +
        +
        + + +
        +
        +<div class="ui-widget-header" style="padding:4px 10px;border-bottom: 0 none">
        +    <i class="fa fa-search" style="margin:4px 4px 0 0"></i>
        +    <input #gb type="text" pInputText size="50" placeholder="Global Filter">
        +</div>
        +<p-dataTable [value]="cars" [rows]="10" [paginator]="true" [globalFilter]="gb" #dt>
        +    <p-header>List of Cars</p-header>
        +    <p-column field="vin" header="Vin (startsWith)" [filter]="true" filterPlaceholder="Search"></p-column>
        +    <p-column field="year" header="Year ({{yearFilter||'No Filter'}})" [filter]="true" filterMatchMode="equals">
        +        <ng-template pTemplate="filter" let-col>
        +            <i class="fa fa-close" (click)="yearFilter=null;dt.filter(null,col.field,col.filterMatchMode)"></i>
        +            <p-slider [style]="{'width':'100%','margin-top':'8px'}" [(ngModel)]="yearFilter" [min]="1970" [max]="2010" (onSlideEnd)="dt.filter($event.value,col.field,col.filterMatchMode)"></p-slider>
        +        </ng-template>
        +    </p-column>
        +    <p-column field="brand" header="Brand (Custom)" [filter]="true" [style]="{'overflow':'visible'}" filterMatchMode="equals">
        +        <ng-template pTemplate="filter" let-col>
        +            <p-dropdown [options]="brands" [style]="{'width':'100%'}" (onChange)="dt.filter($event.value,col.field,col.filterMatchMode)" styleClass="ui-column-filter"></p-dropdown>
        +        </ng-template>
        +    </p-column>
        +    <p-column field="color" header="Color (Custom)" [filter]="true" filterMatchMode="in" [style]="{'overflow':'visible'}">
        +        <ng-template pTemplate="filter" let-col>
        +            <p-multiSelect [options]="colors" defaultLabel="All Colors" (onChange)="dt.filter($event.value,col.field,col.filterMatchMode)" styleClass="ui-column-filter"></p-multiSelect>
        +        </ng-template>
        +    </p-column>
        +</p-dataTable>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatablefilterdemo.ts b/src/app/showcase/components/datatable/datatablefilterdemo.ts new file mode 100644 index 00000000000..30b06fec631 --- /dev/null +++ b/src/app/showcase/components/datatable/datatablefilterdemo.ts @@ -0,0 +1,45 @@ +import {Component,OnInit} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; +import {SelectItem} from '../../../components/common/api'; + +@Component({ + templateUrl: './datatablefilterdemo.html' +}) +export class DataTableFilterDemo implements OnInit { + + cars: Car[]; + + brands: SelectItem[]; + + colors: SelectItem[]; + + constructor(private carService: CarService) {} + + ngOnInit() { + this.carService.getCarsMedium().then(cars => this.cars = cars); + + this.brands = []; + this.brands.push({label: 'All Brands', value: null}); + this.brands.push({label: 'Audi', value: 'Audi'}); + this.brands.push({label: 'BMW', value: 'BMW'}); + this.brands.push({label: 'Fiat', value: 'Fiat'}); + this.brands.push({label: 'Honda', value: 'Honda'}); + this.brands.push({label: 'Jaguar', value: 'Jaguar'}); + this.brands.push({label: 'Mercedes', value: 'Mercedes'}); + this.brands.push({label: 'Renault', value: 'Renault'}); + this.brands.push({label: 'VW', value: 'VW'}); + this.brands.push({label: 'Volvo', value: 'Volvo'}); + + this.colors = []; + this.colors.push({label: 'White', value: 'White'}); + this.colors.push({label: 'Green', value: 'Green'}); + this.colors.push({label: 'Silver', value: 'Silver'}); + this.colors.push({label: 'Black', value: 'Black'}); + this.colors.push({label: 'Red', value: 'Red'}); + this.colors.push({label: 'Maroon', value: 'Maroon'}); + this.colors.push({label: 'Brown', value: 'Brown'}); + this.colors.push({label: 'Orange', value: 'Orange'}); + this.colors.push({label: 'Blue', value: 'Blue'}); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatablelazydemo.html b/src/app/showcase/components/datatable/datatablelazydemo.html new file mode 100644 index 00000000000..4cdf6046ebe --- /dev/null +++ b/src/app/showcase/components/datatable/datatablelazydemo.html @@ -0,0 +1,83 @@ + + +
        +
        + DataTable - Lazy + Lazy mode is handy to deal with large datasets, instead of loading the entire data, small chunks of data is loaded by invoking + onLazyLoad callback everytime paging, sorting and filtering happens. Sample belows imitates lazy paging by using an in memory list. + It is also important to assign the logical number of rows to totalRecords by doing a projection query for paginator configuration so that paginator + displays the UI assuming there are actually records of totalRecords size although in reality they aren't as in lazy mode, only the records that are displayed on the current page exist. +
        +
        + +
        + + List of Cars + + + + + +
        + +
        + + +
        +
        +export class DataTableLazyDemo implements OnInit {
        +
        +    datasource: Car[];
        +    
        +    cars: Car[];
        +    
        +    totalRecords: number;
        +
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        //datasource imitation
        +        this.carService.getCarsLarge().then(cars => {
        +            this.datasource = cars; 
        +            this.totalRecords = this.datasource.length;
        +            this.cars = this.datasource.slice(0, 10);
        +        });
        +    }
        +    
        +    loadCarsLazy(event: LazyLoadEvent) {
        +        //in a real application, make a remote request to load data using state metadata from event
        +        //event.first = First row offset
        +        //event.rows = Number of rows per page
        +        //event.sortField = Field name to sort with
        +        //event.sortOrder = Sort order as number, 1 for asc and -1 for dec
        +        //filters: FilterMetadata object having field as key and filter value, filter matchMode as value
        +        
        +        //imitate db connection over a network
        +        setTimeout(() => {
        +            if(this.datasource) {
        +                this.cars = this.datasource.slice(event.first, (event.first + event.rows));
        +            }
        +        }, 250);
        +    }
        +}
        +
        +
        +
        + + +
        +
        +<p-dataTable [value]="cars" [lazy]="true" [rows]="10" [paginator]="true" 
        +            [totalRecords]="totalRecords" (onLazyLoad)="loadCarsLazy($event)">
        +    <p-header>List of Cars</p-header>
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatablelazydemo.ts b/src/app/showcase/components/datatable/datatablelazydemo.ts new file mode 100644 index 00000000000..e604b41d082 --- /dev/null +++ b/src/app/showcase/components/datatable/datatablelazydemo.ts @@ -0,0 +1,44 @@ +import {Component,OnInit} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; +import {LazyLoadEvent} from '../../../components/common/api'; +import {FilterMetadata} from '../../../components/common/api'; + +@Component({ + templateUrl: './datatablelazydemo.html', +}) +export class DataTableLazyDemo implements OnInit { + + datasource: Car[]; + + cars: Car[]; + + totalRecords: number; + + constructor(private carService: CarService) { } + + ngOnInit() { + //datasource imitation + this.carService.getCarsLarge().then(cars => { + this.datasource = cars; + this.totalRecords = this.datasource.length; + this.cars = this.datasource.slice(0, 10); + }); + } + + loadCarsLazy(event: LazyLoadEvent) { + //in a real application, make a remote request to load data using state metadata from event + //event.first = First row offset + //event.rows = Number of rows per page + //event.sortField = Field name to sort with + //event.sortOrder = Sort order as number, 1 for asc and -1 for dec + //filters: FilterMetadata object having field as key and filter value, filter matchMode as value + + //imitate db connection over a network + setTimeout(() => { + if(this.datasource) { + this.cars = this.datasource.slice(event.first, (event.first + event.rows)); + } + }, 250); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatablepaginatordemo.html b/src/app/showcase/components/datatable/datatablepaginatordemo.html new file mode 100644 index 00000000000..5863116dd88 --- /dev/null +++ b/src/app/showcase/components/datatable/datatablepaginatordemo.html @@ -0,0 +1,54 @@ + + +
        +
        + DataTable - Paginator + Pagination is enabled by setting paginator property to true, rows attribute defines the number of rows per page and pageLinks specify the the number + of page links to display. +
        +
        + +
        + + List of Cars + + + + + +
        + +
        + + +
        +
        +export class DataTablePaginatorDemo implements OnInit {
        +
        +    cars: Car[];
        +
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsMedium().then(cars => this.cars = cars);
        +    }
        +}
        +
        +
        +
        + + +
        +
        +<p-dataTable [value]="cars" [rows]="10" [paginator]="true" [pageLinks]="3" [rowsPerPageOptions]="[5,10,20]">
        +    <p-header>List of Cars</p-header>
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatablepaginatordemo.ts b/src/app/showcase/components/datatable/datatablepaginatordemo.ts new file mode 100644 index 00000000000..67c981470a6 --- /dev/null +++ b/src/app/showcase/components/datatable/datatablepaginatordemo.ts @@ -0,0 +1,17 @@ +import {Component,OnInit} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; + +@Component({ + templateUrl: './datatablepaginatordemo.html', +}) +export class DataTablePaginatorDemo implements OnInit { + + cars: Car[]; + + constructor(private carService: CarService) { } + + ngOnInit() { + this.carService.getCarsMedium().then(cars => this.cars = cars); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatableresponsivedemo.html b/src/app/showcase/components/datatable/datatableresponsivedemo.html new file mode 100644 index 00000000000..3fa031efa41 --- /dev/null +++ b/src/app/showcase/components/datatable/datatableresponsivedemo.html @@ -0,0 +1,65 @@ + + +
        +
        + DataTable - Responsive + DataTable columns are displayed as stacked in responsive mode if the screen size becomes smaller than a certain breakpoint value. + This feature is enabled by setting responsive to true. In case you'd like to control the stacked mode manually regardless of screen size, + use the stacked property. +
        +
        + +
        + + + + Responsive + + + + + +
        + +
        + + +
        +
        +export class DataTableResponsiveDemo implements OnInit {
        +
        +    cars: Car[];
        +    
        +    stacked: boolean;
        +
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsMedium().then(cars => this.cars = cars);
        +    }
        +    
        +    toggle() {
        +        this.stacked = !this.stacked;
        +    }
        +}
        +
        +
        +
        + + +
        +
        +<button pButton type="button" (click)="toggle()" style="margin-bottom:10px" label="Toggle" icon="fa-list"></button>
        +
        +<p-dataTable [value]="cars" [rows]="10" [paginator]="true" [pageLinks]="3" [responsive]="true" [stacked]="stacked">
        +    <p-header>Responsive</p-header>
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatableresponsivedemo.ts b/src/app/showcase/components/datatable/datatableresponsivedemo.ts new file mode 100644 index 00000000000..36d59a8320c --- /dev/null +++ b/src/app/showcase/components/datatable/datatableresponsivedemo.ts @@ -0,0 +1,23 @@ +import {Component,OnInit} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; + +@Component({ + templateUrl: './datatableresponsivedemo.html', +}) +export class DataTableResponsiveDemo implements OnInit { + + cars: Car[]; + + stacked: boolean; + + constructor(private carService: CarService) { } + + ngOnInit() { + this.carService.getCarsMedium().then(cars => this.cars = cars); + } + + toggle() { + this.stacked = !this.stacked; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatablerowexpansiondemo.html b/src/app/showcase/components/datatable/datatablerowexpansiondemo.html new file mode 100644 index 00000000000..5b890368cfa --- /dev/null +++ b/src/app/showcase/components/datatable/datatablerowexpansiondemo.html @@ -0,0 +1,173 @@ + + +
        +
        + DataTable - Row Expansion + A row can be expanded to display extra content by enabling expandableRows property and providing a row ng-template. +
        +
        + +
        + + + + + + + +
        +
        +
        + + +
        +
        +
        +
        +
        Vin:
        +
        {{car.vin}}
        +
        +
        +
        Year:
        +
        {{car.year}}
        +
        +
        +
        Brand:
        +
        {{car.brand}}
        +
        +
        +
        Color:
        +
        {{car.color}}
        +
        +
        +
        +
        +
        +
        +
        + + +
        +
        +
        +
        {{selectedCar.vin}}
        +
        +
        +
        +
        {{selectedCar.year}}
        +
        +
        +
        +
        {{selectedCar.brand}}
        +
        +
        +
        +
        {{selectedCar.color}}
        +
        +
        +
        +
        + +
        + + +
        +
        +export class DataTableRowExpansionDemo implements OnInit {
        +
        +    cars: Car[];
        +    
        +    cols: any[];
        +    
        +    selectedCar: Car;
        +    
        +    dialogVisible: boolean;
        +    
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsSmall().then(cars => this.cars = cars);
        +        
        +        this.cols = [
        +            {field: 'vin', header: 'Vin'},
        +            {field: 'year', header: 'Year'},
        +            {field: 'brand', header: 'Brand'},
        +            {field: 'color', header: 'Color'}
        +        ];
        +    }
        +    
        +    showCar(car: Car) {
        +        this.selectedCar = car;
        +        this.dialogVisible = true;
        +    }
        +}
        +
        +
        +
        + + +
        +
        +<p-dataTable [value]="cars" expandableRows="true">
        +    <p-column expander="true" styleClass="col-icon"></p-column>
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +    <ng-template let-car pTemplate="rowexpansion">
        +        <div class="ui-grid ui-grid-responsive ui-fluid" style="font-size:16px;padding:20px">
        +            <div class="ui-grid-row">
        +                <div class="ui-grid-col-3" style="text-align:center">
        +                    <i class="fa fa-search" (click)="showCar(car)" style="cursor:pointer;float:left;margin-top:40px"></i>
        +                    <img src="showcase/resources/demo/images/car/{{car.brand}}-big.gif">
        +                </div>
        +                <div class="ui-grid-col-9">
        +                    <div class="ui-grid ui-grid-responsive ui-grid-pad">
        +                        <div class="ui-grid-row">
        +                            <div class="ui-grid-col-2 label">Vin: </div>
        +                            <div class="ui-grid-col-10">{{car.vin}}</div>
        +                        </div>
        +                        <div class="ui-grid-row">
        +                            <div class="ui-grid-col-2 label">Year: </div>
        +                            <div class="ui-grid-col-10">{{car.year}}</div>
        +                        </div>
        +                        <div class="ui-grid-row">
        +                            <div class="ui-grid-col-2 label">Brand: </div>
        +                            <div class="ui-grid-col-10">{{car.brand}}</div>
        +                        </div>
        +                        <div class="ui-grid-row">
        +                            <div class="ui-grid-col-2 label">Color: </div>
        +                            <div class="ui-grid-col-10">{{car.color}}</div>
        +                        </div>
        +                    </div>
        +                </div>
        +            </div>
        +        </div>
        +    </ng-template>
        +</p-dataTable>
        +
        +<p-dialog header="Car Details" [(visible)]="dialogVisible" [responsive]="true" showEffect="fade" [modal]="true" width="250">
        +    <div class="ui-grid ui-grid-responsive ui-grid-pad" *ngIf="selectedCar">
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4"><label for="vin" class="label">Vin</label></div>
        +            <div class="ui-grid-col-8">{{selectedCar.vin}}</div>
        +        </div>
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4"><label for="brand" class="label">Year</label></div>
        +            <div class="ui-grid-col-8">{{selectedCar.year}}</div>
        +        </div>
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4"><label for="brand" class="label">Brand</label></div>
        +            <div class="ui-grid-col-8">{{selectedCar.brand}}</div>
        +        </div>
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4"><label for="color" class="label">Color</label></div>
        +            <div class="ui-grid-col-8">{{selectedCar.color}}</div>
        +        </div>
        +    </div>
        +</p-dialog>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatablerowexpansiondemo.ts b/src/app/showcase/components/datatable/datatablerowexpansiondemo.ts new file mode 100644 index 00000000000..8cc23606582 --- /dev/null +++ b/src/app/showcase/components/datatable/datatablerowexpansiondemo.ts @@ -0,0 +1,40 @@ +import {Component,OnInit} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; + +@Component({ + templateUrl: './datatablerowexpansiondemo.html', + styles: [` + .label { + font-weight: bold + } + `] +}) +export class DataTableRowExpansionDemo implements OnInit { + + cars: Car[]; + + cols: any[]; + + selectedCar: Car; + + dialogVisible: boolean; + + constructor(private carService: CarService) { } + + ngOnInit() { + this.carService.getCarsSmall().then(cars => this.cars = cars); + + this.cols = [ + {field: 'vin', header: 'Vin'}, + {field: 'year', header: 'Year'}, + {field: 'brand', header: 'Brand'}, + {field: 'color', header: 'Color'} + ]; + } + + showCar(car: Car) { + this.selectedCar = car; + this.dialogVisible = true; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatablerowgroupdemo.html b/src/app/showcase/components/datatable/datatablerowgroupdemo.html new file mode 100644 index 00000000000..91c688cdd84 --- /dev/null +++ b/src/app/showcase/components/datatable/datatablerowgroupdemo.html @@ -0,0 +1,126 @@ + + +
        +
        + DataTable - Row Grouping + Rows can either be grouped by a separate grouping row or using rowspan. Additional optional features + are toggleable groups and footer rows. +
        +
        + +
        + + Toggleable Row Groups with Footers + {{rowData['brand']}} + + + + + + {{car[col.field] | currency:'USD':true:'.0-0'}} + + + + Total Price + {{calculateGroupTotal(car['brand']) | currency:'USD':true:'.0-0' }} + + + + + Subheader + {{rowData['brand']}} + + + + + + + RowSpan + + + + + +
        + +
        + + +
        +
        +export class DataTableRowGroupDemo implements OnInit {
        +
        +    cars1: Car[];
        +    
        +    cars2: Car[];
        +    
        +    cars3: Car[];
        +    
        +    constructor(private carService: CarService) {}
        +
        +    ngOnInit() {
        +        this.carService.getCarsMedium().then(cars => this.cars1 = cars);
        +        this.carService.getCarsMedium().then(cars => this.cars2 = cars);
        +        this.carService.getCarsMedium().then(cars => this.cars3 = cars);
        +    }
        +    
        +    calculateGroupTotal(brand: string) {
        +        let total = 0;
        +        
        +        if(this.cars1) {
        +            for(let car of this.cars1) {
        +                if(car.brand === brand) {
        +                    total += car.price;
        +                }
        +            }
        +        }
        +
        +        return total;
        +    }
        +}
        +
        +
        +
        + + +
        +
        +<p-dataTable [value]="cars1" sortField="brand" rowGroupMode="subheader" groupField="brand" expandableRowGroups="true"
        +        [sortableRowGroup]="false">
        +    <p-header>Toggleable Row Groups with Footers</p-header>
        +    <ng-template pTemplate="rowgroupheader" let-rowData>{{rowData['brand']}}</ng-template>
        +    <p-column field="color" header="Color"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="price" header="Price">
        +        <ng-template let-col let-car="rowData" pTemplate="body">
        +            <span>{{car[col.field] | currency:'USD':true:'.0-0'}}</span>
        +        </ng-template>
        +    </p-column>
        +    <ng-template pTemplate="rowgroupfooter" let-car>
        +        <td colspan="3" style="text-align:right">Total Price</td>
        +        <td>{{calculateGroupTotal(car['brand']) | currency:'USD':true:'.0-0' }}</td>
        +    </ng-template>
        +</p-dataTable>
        +
        +<p-dataTable [value]="cars2" sortField="brand" rowGroupMode="subheader" groupField="brand" [style]="{'margin-top':'50px'}">
        +    <p-header>Subheader</p-header>
        +    <ng-template pTemplate="rowgroupheader" let-rowData>{{rowData['brand']}}</ng-template>
        +    <p-column field="color" header="Color" sortable="true"></p-column>
        +    <p-column field="year" header="Year" sortable="true"></p-column>
        +    <p-column field="vin" header="Vin" sortable="true"></p-column>
        +</p-dataTable>
        +
        +<p-dataTable [value]="cars3" sortField="brand" rowGroupMode="rowspan" [style]="{'margin-top':'50px'}">
        +    <p-header>RowSpan</p-header>
        +    <p-column field="brand" header="Brand" sortable="true"></p-column>
        +    <p-column field="color" header="Color" sortable="true"></p-column>
        +    <p-column field="year" header="Year" sortable="true"></p-column>
        +    <p-column field="vin" header="Vin" sortable="true"></p-column>
        +</p-dataTable>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatablerowgroupdemo.ts b/src/app/showcase/components/datatable/datatablerowgroupdemo.ts new file mode 100644 index 00000000000..ba4a68b3c16 --- /dev/null +++ b/src/app/showcase/components/datatable/datatablerowgroupdemo.ts @@ -0,0 +1,38 @@ +import {Component,OnInit} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; +import {SelectItem} from '../../../components/common/api'; + +@Component({ + templateUrl: './datatablerowgroupdemo.html' +}) +export class DataTableRowGroupDemo implements OnInit { + + cars1: Car[]; + + cars2: Car[]; + + cars3: Car[]; + + constructor(private carService: CarService) {} + + ngOnInit() { + this.carService.getCarsMedium().then(cars => this.cars1 = cars); + this.carService.getCarsMedium().then(cars => this.cars2 = cars); + this.carService.getCarsMedium().then(cars => this.cars3 = cars); + } + + calculateGroupTotal(brand: string) { + let total = 0; + + if(this.cars1) { + for(let car of this.cars1) { + if(car.brand === brand) { + total += car.price; + } + } + } + + return total; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatablescrolldemo.html b/src/app/showcase/components/datatable/datatablescrolldemo.html new file mode 100644 index 00000000000..5ddc78934e9 --- /dev/null +++ b/src/app/showcase/components/datatable/datatablescrolldemo.html @@ -0,0 +1,164 @@ + + +
        +
        + DataTable - Scroll + Data scrolling with fixed header is available horizontally, vertically or both. ScrollHeight and ScrollWidth values can either + be fixed pixels or percentages. Certain columns can be fixed as well. Virtual Scrolling mode is available to deal with large datasets by loading data on demand during scrolling. +
        +
        + +
        + + Vertical + + + + + + + + Virtual Scrolling - 500000 Rows + + + + + + + + Vertical and Horizontal + + + + + + + + Frozen Columns + + + + + + + + +
        + +
        + + +
        +
        +export class DataTableScrollDemo implements OnInit {
        +
        +    cars: Car[];
        +    
        +    carsLarge: Car[];
        +    
        +    totalRecords: number;
        +
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsMedium().then(cars => this.cars = cars);
        +        
        +        this.totalRecords = 500000;
        +    }
        +    
        +    loadCarsLazy(event: LazyLoadEvent) {
        +        //for demo purposes keep loading the same dataset 
        +        //in a real production application, this data should come from server by building the query with LazyLoadEvent options 
        +        this.carsLarge = [
        +            {"brand": "VW", "year": 2012, "color": "Orange", "vin": "dsad231ff"},
        +            {"brand": "Audi", "year": 2011, "color": "Black", "vin": "gwregre345"},
        +            {"brand": "Renault", "year": 2005, "color": "Gray", "vin": "h354htr"},
        +            {"brand": "BMW", "year": 2003, "color": "Blue", "vin": "j6w54qgh"},
        +            {"brand": "Mercedes", "year": 1995, "color": "Orange", "vin": "hrtwy34"},
        +            {"brand": "Volvo", "year": 2005, "color": "Black", "vin": "jejtyj"},
        +            {"brand": "Honda", "year": 2012, "color": "Yellow", "vin": "g43gr"},
        +            {"brand": "Jaguar", "year": 2013, "color": "Orange", "vin": "greg34"},
        +            {"brand": "Ford", "year": 2000, "color": "Black", "vin": "h54hw5"},
        +            {"brand": "Fiat", "year": 2013, "color": "Red", "vin": "245t2s"},
        +            {"brand": "VW", "year": 2012, "color": "Orange", "vin": "dsad231ff"},
        +            {"brand": "Audi", "year": 2011, "color": "Black", "vin": "gwregre345"},
        +            {"brand": "Renault", "year": 2005, "color": "Gray", "vin": "h354htr"},
        +            {"brand": "BMW", "year": 2003, "color": "Blue", "vin": "j6w54qgh"},
        +            {"brand": "Mercedes", "year": 1995, "color": "Orange", "vin": "hrtwy34"},
        +            {"brand": "Volvo", "year": 2005, "color": "Black", "vin": "jejtyj"},
        +            {"brand": "Honda", "year": 2012, "color": "Yellow", "vin": "g43gr"},
        +            {"brand": "Jaguar", "year": 2013, "color": "Orange", "vin": "greg34"},
        +            {"brand": "Ford", "year": 2000, "color": "Black", "vin": "h54hw5"},
        +            {"brand": "Fiat", "year": 2013, "color": "Red", "vin": "245t2s"},
        +            {"brand": "VW", "year": 2012, "color": "Orange", "vin": "dsad231ff"},
        +            {"brand": "Audi", "year": 2011, "color": "Black", "vin": "gwregre345"},
        +            {"brand": "Renault", "year": 2005, "color": "Gray", "vin": "h354htr"},
        +            {"brand": "BMW", "year": 2003, "color": "Blue", "vin": "j6w54qgh"},
        +            {"brand": "Mercedes", "year": 1995, "color": "Orange", "vin": "hrtwy34"},
        +            {"brand": "Volvo", "year": 2005, "color": "Black", "vin": "jejtyj"},
        +            {"brand": "Honda", "year": 2012, "color": "Yellow", "vin": "g43gr"},
        +            {"brand": "Jaguar", "year": 2013, "color": "Orange", "vin": "greg34"},
        +            {"brand": "Ford", "year": 2000, "color": "Black", "vin": "h54hw5"},
        +            {"brand": "Fiat", "year": 2013, "color": "Red", "vin": "245t2s"},
        +            {"brand": "VW", "year": 2012, "color": "Orange", "vin": "dsad231ff"},
        +            {"brand": "Audi", "year": 2011, "color": "Black", "vin": "gwregre345"},
        +            {"brand": "Renault", "year": 2005, "color": "Gray", "vin": "h354htr"},
        +            {"brand": "BMW", "year": 2003, "color": "Blue", "vin": "j6w54qgh"},
        +            {"brand": "Mercedes", "year": 1995, "color": "Orange", "vin": "hrtwy34"},
        +            {"brand": "Volvo", "year": 2005, "color": "Black", "vin": "jejtyj"},
        +            {"brand": "Honda", "year": 2012, "color": "Yellow", "vin": "g43gr"},
        +            {"brand": "Jaguar", "year": 2013, "color": "Orange", "vin": "greg34"},
        +            {"brand": "Ford", "year": 2000, "color": "Black", "vin": "h54hw5"},
        +            {"brand": "Fiat", "year": 2013, "color": "Red", "vin": "245t2s"}
        +        ];
        +        
        +    }
        +}
        +
        +
        +
        + + +
        +
        +<p-dataTable [value]="cars" scrollable="true" scrollHeight="200px">
        +    <p-header>Vertical</p-header>
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +<p-dataTable [value]="carsLarge" scrollable="true" scrollHeight="200px" [rows]="20" virtualScroll="virtualScroll" [style]="{'margin-top':'30px'}" 
        +    [lazy]="true" [totalRecords]="totalRecords" (onLazyLoad)="loadCarsLazy($event)">
        +    <p-header>Virtual Scrolling - 500000 Rows</p-header>
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +<p-dataTable [value]="cars" scrollable="true"  scrollHeight="200px" scrollWidth="600px" [style]="{'margin-top':'30px'}">
        +    <p-header>Vertical and Horizontal</p-header>
        +    <p-column field="vin" header="Vin" [style]="{'width':'250px'}"></p-column>
        +    <p-column field="year" header="Year" [style]="{'width':'250px'}"></p-column>
        +    <p-column field="brand" header="Brand" [style]="{'width':'250px'}"></p-column>
        +    <p-column field="color" header="Color" [style]="{'width':'250px'}"></p-column>
        +</p-dataTable>
        +
        +<p-dataTable [value]="cars" scrollable="true" scrollHeight="200px" frozenWidth="200px" unfrozenWidth="600px" [style]="{'margin-top':'30px'}">
        +    <p-header>Frozen Columns</p-header>
        +    <p-column field="vin" header="Vin" [style]="{'width':'250px'}" frozen="true"></p-column>
        +    <p-column field="year" header="Year" [style]="{'width':'250px'}"></p-column>
        +    <p-column field="brand" header="Brand" [style]="{'width':'250px'}"></p-column>
        +    <p-column field="color" header="Color" [style]="{'width':'250px'}"></p-column>
        +    <p-column field="year" header="Year" [style]="{'width':'250px'}"></p-column>
        +    <p-column field="brand" header="Brand" [style]="{'width':'250px'}"></p-column>
        +    <p-column field="color" header="Color" [style]="{'width':'250px'}"></p-column>
        +</p-dataTable>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatablescrolldemo.ts b/src/app/showcase/components/datatable/datatablescrolldemo.ts new file mode 100644 index 00000000000..c6ba64b2d41 --- /dev/null +++ b/src/app/showcase/components/datatable/datatablescrolldemo.ts @@ -0,0 +1,73 @@ +import {Component,OnInit} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; +import {LazyLoadEvent} from '../../../components/common/api'; +import {FilterMetadata} from '../../../components/common/api'; + +@Component({ + templateUrl: './datatablescrolldemo.html', +}) +export class DataTableScrollDemo implements OnInit { + + cars: Car[]; + + carsLarge: Car[]; + + totalRecords: number; + + constructor(private carService: CarService) { } + + ngOnInit() { + this.carService.getCarsMedium().then(cars => this.cars = cars); + + this.totalRecords = 500000; + } + + loadCarsLazy(event: LazyLoadEvent) { + //for demo purposes keep loading the same dataset + //in a real production application, this data should come from server by building the query with LazyLoadEvent options + this.carsLarge = [ + {"brand": "VW", "year": 2012, "color": "Orange", "vin": "dsad231ff"}, + {"brand": "Audi", "year": 2011, "color": "Black", "vin": "gwregre345"}, + {"brand": "Renault", "year": 2005, "color": "Gray", "vin": "h354htr"}, + {"brand": "BMW", "year": 2003, "color": "Blue", "vin": "j6w54qgh"}, + {"brand": "Mercedes", "year": 1995, "color": "Orange", "vin": "hrtwy34"}, + {"brand": "Volvo", "year": 2005, "color": "Black", "vin": "jejtyj"}, + {"brand": "Honda", "year": 2012, "color": "Yellow", "vin": "g43gr"}, + {"brand": "Jaguar", "year": 2013, "color": "Orange", "vin": "greg34"}, + {"brand": "Ford", "year": 2000, "color": "Black", "vin": "h54hw5"}, + {"brand": "Fiat", "year": 2013, "color": "Red", "vin": "245t2s"}, + {"brand": "VW", "year": 2012, "color": "Orange", "vin": "dsad231ff"}, + {"brand": "Audi", "year": 2011, "color": "Black", "vin": "gwregre345"}, + {"brand": "Renault", "year": 2005, "color": "Gray", "vin": "h354htr"}, + {"brand": "BMW", "year": 2003, "color": "Blue", "vin": "j6w54qgh"}, + {"brand": "Mercedes", "year": 1995, "color": "Orange", "vin": "hrtwy34"}, + {"brand": "Volvo", "year": 2005, "color": "Black", "vin": "jejtyj"}, + {"brand": "Honda", "year": 2012, "color": "Yellow", "vin": "g43gr"}, + {"brand": "Jaguar", "year": 2013, "color": "Orange", "vin": "greg34"}, + {"brand": "Ford", "year": 2000, "color": "Black", "vin": "h54hw5"}, + {"brand": "Fiat", "year": 2013, "color": "Red", "vin": "245t2s"}, + {"brand": "VW", "year": 2012, "color": "Orange", "vin": "dsad231ff"}, + {"brand": "Audi", "year": 2011, "color": "Black", "vin": "gwregre345"}, + {"brand": "Renault", "year": 2005, "color": "Gray", "vin": "h354htr"}, + {"brand": "BMW", "year": 2003, "color": "Blue", "vin": "j6w54qgh"}, + {"brand": "Mercedes", "year": 1995, "color": "Orange", "vin": "hrtwy34"}, + {"brand": "Volvo", "year": 2005, "color": "Black", "vin": "jejtyj"}, + {"brand": "Honda", "year": 2012, "color": "Yellow", "vin": "g43gr"}, + {"brand": "Jaguar", "year": 2013, "color": "Orange", "vin": "greg34"}, + {"brand": "Ford", "year": 2000, "color": "Black", "vin": "h54hw5"}, + {"brand": "Fiat", "year": 2013, "color": "Red", "vin": "245t2s"}, + {"brand": "VW", "year": 2012, "color": "Orange", "vin": "dsad231ff"}, + {"brand": "Audi", "year": 2011, "color": "Black", "vin": "gwregre345"}, + {"brand": "Renault", "year": 2005, "color": "Gray", "vin": "h354htr"}, + {"brand": "BMW", "year": 2003, "color": "Blue", "vin": "j6w54qgh"}, + {"brand": "Mercedes", "year": 1995, "color": "Orange", "vin": "hrtwy34"}, + {"brand": "Volvo", "year": 2005, "color": "Black", "vin": "jejtyj"}, + {"brand": "Honda", "year": 2012, "color": "Yellow", "vin": "g43gr"}, + {"brand": "Jaguar", "year": 2013, "color": "Orange", "vin": "greg34"}, + {"brand": "Ford", "year": 2000, "color": "Black", "vin": "h54hw5"}, + {"brand": "Fiat", "year": 2013, "color": "Red", "vin": "245t2s"} + ]; + + } +} \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatableselectiondemo.html b/src/app/showcase/components/datatable/datatableselectiondemo.html new file mode 100644 index 00000000000..e3abe35bc41 --- /dev/null +++ b/src/app/showcase/components/datatable/datatableselectiondemo.html @@ -0,0 +1,240 @@ + + +
        +
        + DataTable - Selection + DataTable provides single and multiple selection modes on click of a row. Selected rows are bound to the selection property + and onRowSelect-onRowUnselect events are provided as optional callbacks. In addition built-in radio button and checkbox based selections + are available as alternatives. +
        +
        + +
        + + +

        Single

        +

        In single mode, a row is selected on click event of a row. If the row is already selected then the row gets unselected.

        + + Single Selection +
        Selected Car: {{selectedCar1 ? selectedCar1.vin + ' - ' + selectedCar1.brand + ' - ' + selectedCar1.year + ' - ' + selectedCar1.color: 'none'}}
        + + + + +
        + +

        Multiple

        +

        In multiple mode, selection binding should be an array. For touch enabled devices, selection is managed by tapping and for other devices + metakey is required.

        + + Multiple Selection + + + + + +
          +
        • {{car.vin + ' - ' + car.brand + ' - ' + car.year + ' - ' + car.color}}
        • +
        +
        +
        + +

        Events

        +

        DataTable provides onRowSelect and onRowUnselect as optional callbacks.

        + + Selection with Events + + + + + + +

        RadioButton

        +

        Single selection can also be handled using radio buttons by enabling the selectionMode property of column as "single".

        + + Single Selection +
        Selected Car: {{selectedCar3 ? selectedCar3.vin + ' - ' + selectedCar3.brand + ' - ' + selectedCar3.year + ' - ' + selectedCar3.color: 'none'}}
        + + + + + +
        + +

        Checkbox

        +

        Multiple selection can also be handled using checkboxes by enabling the selectionMode property of column as "multiple".

        + + Checkbox Selection + + + + + + +
          +
        • {{car.vin + ' - ' + car.brand + ' - ' + car.year + ' - ' + car.color}}
        • +
        +
        +
        + +

        Checkbox with Paging

        +

        + When using checkboxes for multiple selection with paging and clicking the header checkbox, by default, items on + all other pages will be deselected and only the current page's items will be toggled. Often, the more desired + approach is to toggle all items across all pages. This can be accomplished by setting the + "headerCheckboxToggleAllPages" property to "true" on your paged DataTable. Notice how the header checkbox only + stays checked when all items across all pages are selected. +

        + + Checkbox Multiple Selection with Paging + + + + + + +
          +
        • {{car.vin + ' - ' + car.brand + ' - ' + car.year + ' - ' + car.color}}
        • +
        +
        +
        +
        + +
        + + +
        +
        +export class DataTableSelectionDemo implements OnInit {
        +
        +    msgs: Message[];
        +
        +    cars: Car[];
        +
        +    selectedCar1: Car;
        +
        +    selectedCar2: Car;
        +    
        +    selectedCar3: Car;
        +
        +    selectedCars1: Car[];
        +    
        +    selectedCars2: Car[];
        +    
        +    selectedCars3: Car[];
        +
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsSmall().then(cars => this.cars = cars);
        +    }
        +
        +    onRowSelect(event) {
        +        this.msgs = [];
        +        this.msgs.push({severity: 'info', summary: 'Car Selected', detail: event.data.vin + ' - ' + event.data.brand});
        +    }
        +
        +    onRowUnselect(event) {
        +        this.msgs = [];
        +        this.msgs.push({severity: 'info', summary: 'Car Unselected', detail: event.data.vin + ' - ' + event.data.brand});
        +    }
        +}
        +
        +
        +
        + + +
        +
        +<p-growl [value]="msgs"></p-growl>
        +
        +<h3 class="first">Single</h3>
        +<p>In single mode, a row is selected on click event of a row. If the row is already selected then the row gets unselected.</p>
        +<p-dataTable [value]="cars" selectionMode="single" [(selection)]="selectedCar1" dataKey="vin">
        +    <p-header>Single Selection</p-header>
        +    <p-footer><div style="text-align: left">Selected Car: {{selectedCar1 ? selectedCar1.vin + ' - ' + selectedCar1.brand + ' - ' + selectedCar1.year + ' - ' + selectedCar1.color: 'none'}}</div></p-footer>
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +<h3>Multiple</h3>
        +<p></p>
        +<p-dataTable [value]="cars" selectionMode="multiple" [(selection)]="selectedCars" dataKey="vin">
        +    <p-header>Multiple Selection</p-header>
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +    <p-footer>
        +        <ul>
        +            <li *ngFor="let car of selectedCars" style="text-align: left">{{car.vin + ' - ' + car.brand + ' - ' + car.year + ' - ' + car.color}}</li>
        +        </ul>
        +    </p-footer>
        +</p-dataTable>
        +
        +<h3>Events</h3>
        +<p>DataTable provides onRowSelect and onRowUnselect as optional callbacks.</p>
        +<p-dataTable [value]="cars" selectionMode="single" [(selection)]="selectedCar2" (onRowSelect)="onRowSelect($event)" (onRowUnselect)="onRowUnselect($event)" dataKey="vin">
        +    <p-header>Selection with Events</p-header>
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +<h3>RadioButton</h3>
        +<p>Single selection can also be handled using radio buttons by enabling the selectionMode property of column as "single".</p>
        +<p-dataTable [value]="cars" [(selection)]="selectedCar3" dataKey="vin">
        +    <p-header>Single Selection</p-header>
        +    <p-footer><div style="text-align: left">Selected Car: {{selectedCar3 ? selectedCar3.vin + ' - ' + selectedCar3.brand + ' - ' + selectedCar3.year + ' - ' + selectedCar3.color: 'none'}}</div></p-footer>
        +    <p-column [style]="{'width':'38px'}" selectionMode="single"></p-column>
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +<h3>Checkbox</h3>
        +<p>Multiple selection can also be handled using checkboxes by enabling the selectionMode property of column as "multiple".</p>
        +<p-dataTable [value]="cars" [(selection)]="selectedCars2" dataKey="vin">
        +    <p-header>Checkbox Selection</p-header>
        +    <p-column [style]="{'width':'38px'}" selectionMode="multiple"></p-column>
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +    <p-footer>
        +        <ul>
        +            <li *ngFor="let car of selectedCars2" style="text-align: left">{{car.vin + ' - ' + car.brand + ' - ' + car.year + ' - ' + car.color}}</li>
        +        </ul>
        +    </p-footer>
        +</p-dataTable>
        +    
        +<h3>Checkbox with Paging</h3>
        +<p> 
        +    When using checkboxes for multiple selection with paging and clicking the header checkbox, by default, items on all 
        +    other pages will be deselected and only the current page's items will be toggled. Often, the more desired approach
        +    is to toggle all items across all pages. This can be accomplished by setting the 
        +    "headerCheckboxToggleAllPages" property to "true" on your paged DataTable. Notice how the header
        +    checkbox only stays checked when all items across all pages are selected. 
        +</p>
        +<p-dataTable [value]="cars" [(selection)]="selectedCars3" dataKey="vin" [paginator]="true" [rows]="5" [headerCheckboxToggleAllPages]="true">
        +    <p-header>Checkbox Multiple Selection with Paging</p-header>
        +    <p-column [style]="{'width':'38px'}" selectionMode="multiple"></p-column>
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +    <p-footer>
        +        <ul>
        +            <li *ngFor="let car of selectedCars3" style="text-align: left">{{car.vin + ' - ' + car.brand + ' - ' + car.year + ' - ' + car.color}}</li>
        +        </ul>
        +    </p-footer>
        +</p-dataTable>
        +
        +
        +
        +
        +
        diff --git a/src/app/showcase/components/datatable/datatableselectiondemo.ts b/src/app/showcase/components/datatable/datatableselectiondemo.ts new file mode 100644 index 00000000000..b01b17a5871 --- /dev/null +++ b/src/app/showcase/components/datatable/datatableselectiondemo.ts @@ -0,0 +1,42 @@ +import {Component,OnInit} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; +import {Message} from '../../../components/common/api'; + +@Component({ + templateUrl: './datatableselectiondemo.html', +}) +export class DataTableSelectionDemo implements OnInit { + + msgs: Message[]; + + cars: Car[]; + + selectedCar1: Car; + + selectedCar2: Car; + + selectedCar3: Car; + + selectedCars1: Car[]; + + selectedCars2: Car[]; + + selectedCars3: Car[]; + + constructor(private carService: CarService) { } + + ngOnInit() { + this.carService.getCarsSmall().then(cars => this.cars = cars); + } + + onRowSelect(event) { + this.msgs = []; + this.msgs.push({severity: 'info', summary: 'Car Selected', detail: event.data.vin + ' - ' + event.data.brand}); + } + + onRowUnselect(event) { + this.msgs = []; + this.msgs.push({severity: 'info', summary: 'Car Unselected', detail: event.data.vin + ' - ' + event.data.brand}); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatablesortdemo.html b/src/app/showcase/components/datatable/datatablesortdemo.html new file mode 100644 index 00000000000..6329cada95d --- /dev/null +++ b/src/app/showcase/components/datatable/datatablesortdemo.html @@ -0,0 +1,73 @@ + + +
        +
        + DataTable - Sort + Simply enabling sortable property at column object is enough to make a column sortable. For multiple sorting + use metakey. +
        +
        + +
        +

        Single Column

        + + + + + + + +

        Multiple Columns

        + + + + + + +
        + +
        + + +
        +
        +export class DataTableSortDemo implements OnInit {
        +
        +    cars1: Car[];
        +    
        +    cars2: Car[];
        +
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsSmall().then(cars => this.cars1 = cars);
        +        this.carService.getCarsSmall().then(cars => this.cars2 = cars);
        +    }
        +}
        +
        +
        +
        + + +
        +
        +<h3 class="first">Single Column</h3>
        +<p-dataTable [value]="cars1">
        +    <p-column field="vin" header="Vin" [sortable]="true"></p-column>
        +    <p-column field="year" header="Year" [sortable]="true"></p-column>
        +    <p-column field="brand" header="Brand" [sortable]="true"></p-column>
        +    <p-column field="color" header="Color" [sortable]="true"></p-column>
        +</p-dataTable>
        +
        +<h3>Multiple Columns</h3>
        +<p-dataTable [value]="cars2" sortMode="multiple">
        +    <p-column field="vin" header="Vin" [sortable]="true"></p-column>
        +    <p-column field="year" header="Year" [sortable]="true"></p-column>
        +    <p-column field="brand" header="Brand" [sortable]="true"></p-column>
        +    <p-column field="color" header="Color" [sortable]="true"></p-column>
        +</p-dataTable>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatablesortdemo.ts b/src/app/showcase/components/datatable/datatablesortdemo.ts new file mode 100644 index 00000000000..6930f4421b9 --- /dev/null +++ b/src/app/showcase/components/datatable/datatablesortdemo.ts @@ -0,0 +1,20 @@ +import {Component,OnInit} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; + +@Component({ + templateUrl: './datatablesortdemo.html' +}) +export class DataTableSortDemo implements OnInit { + + cars1: Car[]; + + cars2: Car[]; + + constructor(private carService: CarService) { } + + ngOnInit() { + this.carService.getCarsSmall().then(cars => this.cars1 = cars); + this.carService.getCarsSmall().then(cars => this.cars2 = cars); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatablesubmenu.ts b/src/app/showcase/components/datatable/datatablesubmenu.ts new file mode 100644 index 00000000000..5a3bc99ebb9 --- /dev/null +++ b/src/app/showcase/components/datatable/datatablesubmenu.ts @@ -0,0 +1,32 @@ +import {Component} from '@angular/core'; + +@Component({ + selector: 'datatable-demos', + template: ` + + ` +}) +export class DataTableSubmenu {} diff --git a/src/app/showcase/components/datatable/datatabletemplatingdemo.html b/src/app/showcase/components/datatable/datatabletemplatingdemo.html new file mode 100644 index 00000000000..835780a085d --- /dev/null +++ b/src/app/showcase/components/datatable/datatabletemplatingdemo.html @@ -0,0 +1,87 @@ + + +
        +
        + DataTable - Templating + Field data of a corresponding row is displayed as the cell content by default, this can be customized using templating. Similarly, + custom content can be placed at the header and footer of a column with templating. +
        +
        + +
        + + + + + + + + + {{car[col.field]}} + + + + + + + + + + + +
        + +
        + + +
        +
        +export class DataTableTemplatingDemo implements OnInit {
        +
        +    cars: Car[];
        +    
        +    msgs: Message[] = [];
        +
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsSmall().then(cars => this.cars = cars);
        +    }
        +    
        +    selectCar(car: Car) {
        +        this.msgs = [];
        +        this.msgs.push({severity:'info', summary:'Car Select', detail:'Vin: ' + car.vin});
        +    }
        +}
        +
        +
        +
        + + +
        +
        +<p-growl [value]="msgs"></p-growl>
        +
        +<p-dataTable [value]="cars">
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color">
        +        <ng-template let-col let-car="rowData" pTemplate="body">
        +            <span [style.color]="car[col.field]">{{car[col.field]}}</span>
        +        </ng-template>
        +    </p-column>
        +    <p-column styleClass="col-button">
        +        <ng-template pTemplate="header">
        +            <button type="button" pButton icon="fa-refresh"></button>
        +        </ng-template>
        +        <ng-template let-car="rowData" pTemplate="body">
        +            <button type="button" pButton (click)="selectCar(car)" icon="fa-search"></button>
        +        </ng-template>
        +    </p-column>
        +</p-dataTable>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/datatable/datatabletemplatingdemo.ts b/src/app/showcase/components/datatable/datatabletemplatingdemo.ts new file mode 100644 index 00000000000..25726895bbc --- /dev/null +++ b/src/app/showcase/components/datatable/datatabletemplatingdemo.ts @@ -0,0 +1,25 @@ +import {Component,OnInit} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; +import {Message} from '../../../components/common/api'; + +@Component({ + templateUrl: './datatabletemplatingdemo.html', +}) +export class DataTableTemplatingDemo implements OnInit { + + cars: Car[]; + + msgs: Message[] = []; + + constructor(private carService: CarService) { } + + ngOnInit() { + this.carService.getCarsSmall().then(cars => this.cars = cars); + } + + selectCar(car: Car) { + this.msgs = []; + this.msgs.push({severity:'info', summary:'Car Select', detail:'Vin: ' + car.vin}); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/defer/deferdemo-routing.module.ts b/src/app/showcase/components/defer/deferdemo-routing.module.ts new file mode 100644 index 00000000000..97c1ef94b8d --- /dev/null +++ b/src/app/showcase/components/defer/deferdemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {DeferDemo} from './deferdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: DeferDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class DeferDemoRoutingModule {} diff --git a/src/app/showcase/components/defer/deferdemo.html b/src/app/showcase/components/defer/deferdemo.html new file mode 100644 index 00000000000..7cb293076e2 --- /dev/null +++ b/src/app/showcase/components/defer/deferdemo.html @@ -0,0 +1,143 @@ +
        +
        + Defer + Defer directive postpones the loading the content that is initially not in viewport until it becomes visible on scroll. Think of + pDefer as a smart ngIf that lazily loads content when it becomes visible after page scroll. Scroll down to load the DataTable + which initiates a query that is not executed on initial page load to speed up load performance. +
        +
        + +
        +
        + DataTable is not loaded, scroll down to initialize it. +
        + + + +
        + + + + + + + + +
        + +
        + +
        + + +

        Import

        +
        +
        +import {DeferModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Defer is applied to a container element with pDefer directive where content needs to be placed inside an ng-template.

        +
        +
        +<div pDefer>
        +    <ng-template>
        +       deferred content
        +   </ng-template>
        +</div>
        +
        +
        + +

        Callback

        +

        onLoad callback is useful to initialize the content when it becomes visible on scroll such as loading data.

        + +
        +
        +<div pDefer (onLoad)="initData()">
        +    <ng-template>
        +        <p-dataTable [value]="cars">
        +            <p-column field="vin" header="Vin"></p-column>
        +            <p-column field="year" header="Year"></p-column>
        +            <p-column field="brand" header="Brand"></p-column>
        +            <p-column field="color" header="Color"></p-column>
        +        </p-dataTable>
        +    </ng-template>
        +</div>
        +
        +
        + +
        +
        +this.cars = //initialize
        +
        +
        + +

        Properties

        +

        Directive has no attributes.

        + +

        Events

        +
        + + + + + + + + + + + + + + + +
        NameParametersDescription
        onLoad-Callback to invoke when deferred content is loaded.
        +
        + +

        Styling

        +

        Directive does not apply any styling to host.

        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<div pDefer (onLoad)="initData()">
        +    <ng-template>
        +        <p-dataTable [value]="cars">
        +            <p-column field="vin" header="Vin"></p-column>
        +            <p-column field="year" header="Year"></p-column>
        +            <p-column field="brand" header="Brand"></p-column>
        +            <p-column field="color" header="Color"></p-column>
        +        </p-dataTable>
        +    </ng-template>
        +</div>
        +
        +
        + + +
        +
        +export class DeferDemo {
        +
        +    cars: Car[];
        +    
        +    msgs: Message[] = [];
        +            
        +    constructor(private carService: CarService)  {}
        +    
        +    initData()  {
        +        this.msgs = [{severity:'success', summary:'Data Initialized', detail:'Render Completed'}];
        +        this.carService.getCarsSmall().then(cars => this.cars = cars);
        +     }
        + }
        +
        +
        + +
        +
        +
        diff --git a/src/app/showcase/components/defer/deferdemo.module.ts b/src/app/showcase/components/defer/deferdemo.module.ts new file mode 100644 index 00000000000..e3859c2925b --- /dev/null +++ b/src/app/showcase/components/defer/deferdemo.module.ts @@ -0,0 +1,25 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {DeferDemo} from './deferdemo'; +import {DeferDemoRoutingModule} from './deferdemo-routing.module'; +import {DeferModule} from '../../../components/defer/defer'; +import {DataTableModule} from '../../../components/datatable/datatable'; +import {GrowlModule} from '../../../components/growl/growl'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + DeferDemoRoutingModule, + DeferModule, + GrowlModule, + TabViewModule, + DataTableModule, + CodeHighlighterModule + ], + declarations: [ + DeferDemo + ] +}) +export class DeferDemoModule {} diff --git a/src/app/showcase/components/defer/deferdemo.ts b/src/app/showcase/components/defer/deferdemo.ts new file mode 100644 index 00000000000..270c6915070 --- /dev/null +++ b/src/app/showcase/components/defer/deferdemo.ts @@ -0,0 +1,21 @@ +import {Component} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; +import {Message} from '../../../components/common/api'; + +@Component({ + templateUrl: './deferdemo.html' +}) +export class DeferDemo { + + cars: Car[]; + + msgs: Message[] = []; + + constructor(private carService: CarService) { } + + initData() { + this.msgs = [{severity:'success', summary:'Data Initialized', detail:'Render Completed'}]; + this.carService.getCarsSmall().then(cars => this.cars = cars); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/dialog/dialogdemo-routing.module.ts b/src/app/showcase/components/dialog/dialogdemo-routing.module.ts new file mode 100644 index 00000000000..690ac9d3b8d --- /dev/null +++ b/src/app/showcase/components/dialog/dialogdemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {DialogDemo} from './dialogdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: DialogDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class DialogDemoRoutingModule {} diff --git a/src/app/showcase/components/dialog/dialogdemo.html b/src/app/showcase/components/dialog/dialogdemo.html new file mode 100644 index 00000000000..7068c2b691d --- /dev/null +++ b/src/app/showcase/components/dialog/dialogdemo.html @@ -0,0 +1,384 @@ +
        +
        + Dialog + Dialog is a container to display content in an overlay window. +
        +
        + +
        + + The story begins as Don Vito Corleone, the head of a New York Mafia family, oversees his daughter's wedding. + His beloved son Michael has just come home from the war, but does not intend to become part of his father's business. + Through Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, + kind and benevolent to those who give respect, + but given to ruthless violence whenever anything stands against the good of the family. + +
        + + +
        +
        +
        + + +
        + +
        + + +

        Import

        +
        +
        +import {DialogModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Dialog is used as a container and visibility is controlled with visible property.

        + +
        +
        +<p-dialog header="Title" [(visible)]="display">
        +    Content
        +</p-dialog>
        +
        +<button type="text" (click)="showDialog()" pButton icon="fa-external-link-square" label="Show"></button>
        +
        +
        + +
        +
        +export class ModelComponent {
        +
        +    display: boolean = false;
        +
        +    showDialog() {
        +        this.display = true;
        +    }
        +
        +}
        +
        +
        + +

        By default dialog is hidden and enabling the visible property displays the dialog. As visible supports + two-way binding, hiding the dialog with close button updates the visible state as false.

        + +

        Width

        +

        When the content of the dialog is fluid, dialog width may grow unexpectedly, in this case define a fixed width to the dialog + or the content.

        +
        +
        +<p-dialog header="Title" [(visible)]="display" [width]="300">
        +    Content
        +</p-dialog>
        +
        +
        + +

        Header and Footer

        +

        Header and Footer sections are useful to include custom content. Note that Header and Footer components should be imported and defined + at directives section of your component for this to work. If you have buttons at footer, it is suggested to use .ui-dialog-buttonpane class inside footer + as it includes built-in styling for buttons.

        +
        +
        +<p-dialog [(visible)]="display">
        +    <p-header>
        +        Header content here
        +    </p-header>
        +    Content
        +    <p-footer>
        +        <div class="ui-dialog-buttonpane ui-helper-clearfix">
        +            //buttons
        +        </div>
        +    </p-footer>
        +</p-dialog>
        +
        +
        + +

        Overlays Inside

        +

        When dialog contents include other components with overlays such as dropdown, it is suggested to turn off the overflow of dialog content + so that the overlays can be displayed outside of the dialog.

        +
        +
        +<p-dropdown [options]="cities" formControlName="selectedCity"></p-dropdown>
        +
        +
        + +

        RTL Support

        +

        RTL orientation is enabled by adding "ui-rtl" to an ancestor element of dialog in combination with standard dir="rtl" option.

        +
        +
        +<div class="ui-rtl" dir="rtl">
        +    <p-dialog [(visible)]="display">
        +        <p-header>
        +            Header content here
        +        </p-header>
        +        Content
        +        <p-footer>
        +            Footer content here
        +        </p-footer>
        +    </p-dialog>
        +</div>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        headerstringnullTitle text of the dialog.
        draggablebooleantrueEnables dragging to change the position using header.
        resizablebooleantrueEnables resizing of the content.
        minWidthnumber150Minimum width of a resizable dialog.
        minHeightnumber150Minimum width of a resizable dialog.
        widthint300Width of the dialog.
        heightintautoHeight of the dialog.
        contentStyleobjectnullStyle of the content section.
        visiblebooleanfalseSpecifies the visibility of the dialog.
        modalbooleanfalseDefines if background should be blocked when dialog is displayed.
        closeOnEscapebooleantrueSpecifices if pressing escape key should hide the dialog.
        dismissableMaskbooleanfalseSpecifices if clicking the modal background should hide the dialog.
        rtlbooleanfalseWhen enabled dialog is displayed in RTL direction.
        closablebooleantrueAdds a close icon to the header to hide the dialog.
        responsivebooleantrueIn responsive mode, dialog adjusts itself to screen width.
        breakpointnumber640Maximum screen width to display the dialog with 100% width in responsive mode.
        appendToanynullTarget element to attach the dialog, valid values are "body" or a local ng-template variable of another element.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        showHeaderbooleantrueWhether to show the header or not.
        positionLeftnumbernullLeft coordinate value of the dialog.
        positionTopnumbernullTop coordinate value of the dialog.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onShowevent: Event objectCallback to invoke when dialog is shown.
        onHideevent: Event objectCallback to invoke when dialog is hidden.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-dialogContainer element
        ui-dialog-titlebarContainer of header.
        ui-dialog-titleHeader element.
        ui-dialog-titlebar-iconIcon container inside header.
        ui-dialog-titlebar-closeClose icon element.
        ui-dialog-contentContent element.
        ui-dialog-footerFooter element.
        ui-dialog-buttonpaneOptional container for buttons at footer.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<p-dialog header="Godfather I" [(visible)]="display" modal="modal" width="300" [responsive]="true">
        +    <p>The story begins as Don Vito Corleone, the head of a New York Mafia family, oversees his daughter's wedding. 
        +       His beloved son Michael has just come home from the war, but does not intend to become part of his father's business. 
        +       Through Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, 
        +       kind and benevolent to those who give respect, 
        +       but given to ruthless violence whenever anything stands against the good of the family.</p>
        +        <p-footer>
        +            <div class="ui-dialog-buttonpane ui-widget-content ui-helper-clearfix">
        +                <button type="button" pButton icon="fa-close" (click)="display=false" label="No"></button>
        +                <button type="button" pButton icon="fa-check" (click)="display=false" label="Yes"></button>
        +            </div>
        +        </p-footer>
        +</p-dialog>
        +
        +<button type="button" (click)="showDialog()" pButton icon="fa-external-link-square" label="Show"></button>
        +
        +
        + +
        +
        +export class DialogDemo {
        +
        +    display: boolean = false;
        +
        +    showDialog() {
        +        this.display = true;
        +    }
        +
        +}
        +
        +
        +
        +
        +
        diff --git a/src/app/showcase/components/dialog/dialogdemo.module.ts b/src/app/showcase/components/dialog/dialogdemo.module.ts new file mode 100644 index 00000000000..b9755b67236 --- /dev/null +++ b/src/app/showcase/components/dialog/dialogdemo.module.ts @@ -0,0 +1,23 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {DialogDemo} from './dialogdemo'; +import {DialogDemoRoutingModule} from './dialogdemo-routing.module'; +import {DialogModule} from '../../../components/dialog/dialog'; +import {ButtonModule} from '../../../components/button/button'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + DialogDemoRoutingModule, + DialogModule, + ButtonModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + DialogDemo + ] +}) +export class DialogDemoModule {} diff --git a/src/app/showcase/components/dialog/dialogdemo.ts b/src/app/showcase/components/dialog/dialogdemo.ts new file mode 100644 index 00000000000..4aa9de699ad --- /dev/null +++ b/src/app/showcase/components/dialog/dialogdemo.ts @@ -0,0 +1,18 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './dialogdemo.html' +}) +export class DialogDemo { + + display: boolean = false; + + showDialog() { + this.display = true; + } + + hideDialog() { + this.display = false; + } + +} \ No newline at end of file diff --git a/src/app/showcase/components/domain/car.ts b/src/app/showcase/components/domain/car.ts new file mode 100644 index 00000000000..a728a44d11a --- /dev/null +++ b/src/app/showcase/components/domain/car.ts @@ -0,0 +1,8 @@ +export interface Car { + vin?; + year?; + brand?; + color?; + price?; + saleDate?; +} \ No newline at end of file diff --git a/src/app/showcase/components/dragdrop/dragdropdemo-routing.module.ts b/src/app/showcase/components/dragdrop/dragdropdemo-routing.module.ts new file mode 100644 index 00000000000..b96f8c195ea --- /dev/null +++ b/src/app/showcase/components/dragdrop/dragdropdemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {DragDropDemo} from './dragdropdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: DragDropDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class DragDropDemoRoutingModule {} diff --git a/src/app/showcase/components/dragdrop/dragdropdemo.html b/src/app/showcase/components/dragdrop/dragdropdemo.html new file mode 100644 index 00000000000..657b7c3834d --- /dev/null +++ b/src/app/showcase/components/dragdrop/dragdropdemo.html @@ -0,0 +1,309 @@ +
        +
        + Drag and Drop + pDraggable and pDroppable directives apply drag-drop behaviors to any element. +
        +
        + +
        +

        Drag Only

        +
        + + The story begins as Don Vito Corleone, the head of a New York Mafia family, oversees his daughter's wedding. + His beloved son Michael has just come home from the war, but does not intend to become part of his father's business. + Through Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, + kind and benevolent to those who give respect, but given to ruthless violence whenever anything stands against the good of the family. + +
        + +

        Drag and Drop to DataTable

        +
        +
        +
        +
          +
        • + + +
          {{car.vin}} - {{car.year}}
          +
        • +
        +
        +
        + + + + + + +
        +
        +
        +
        + +
        + + +

        Import

        +
        +
        +import {DragDropModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        pDraggable and pDroppable are attached to a target element to add drag-drop behavior. The value of a Directive attribute is required + and it defines the scope to match draggables with droppables. Droppable scope can also be an array to accept multiple droppables.

        + +
        +
        +<div pDraggable="dd">Draggable Div</div>
        +
        +<div pDroppable="dd">Droppable Div</div>
        +
        +
        + +

        Drag Handle

        +

        Drag handle is used to restrict dragging unless mousedown occurs on the specified element. Panel below can only be dragged using its header.

        + +
        +
        +<div pDraggable="pnl"  dragHandle=".ui-panel-titlebar">
        +    <p-panel header="Drag Header">
        +        The story begins as Don Vito Corleone, the head of a New York Mafia family, oversees his daughter's wedding. 
        +        His beloved son Michael has just come home from the war, but does not intend to become part of his father's business. 
        +        Through Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, 
        +        kind and benevolent to those who give respect, but given to ruthless violence whenever anything stands against the good of the family.
        +    </p-panel>
        +</div>
        +
        +
        + + +

        Draggable

        +

        Attributes

        +
        + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        dragEffectstringnullDefines the cursor style, valid values are none, copy, move, link, copyMove, copyLink, linkMove and all.
        dragHandlestringnullSelector to define the drag handle, by default anywhere on the target element is a drag handle to start dragging.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onDragStart + event: browser event + Callback to invoke when drag begins.
        onDrag + event: browser event + Callback to invoke on dragging.
        onDragEnd + event: browser event + Callback to invoke when drag ends.
        +
        + +

        Droppable

        +

        Attributes

        +
        + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        dropEffectstringnullDefines the cursor style on drag over, valid values are copy, move, link and move.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onDragEnter + event: browser event + Callback to invoke when a draggable enters drop area.
        onDragOver + event: browser event + Callback to invoke when an element or text selection is being dragged over a valid drop target (every few hundred milliseconds).
        onDrop + event: browser event + Callback to invoke when a draggable is dropped onto drop area.
        onDragLeave + event: browser event + Callback to invoke when a draggable leave drop area.
        +
        + + +

        Dependencies

        +

        Native HTML5 DragDrop.

        +
        + +
        +
        +<h3 class="first">Drag Only</h3>
        +<div pDraggable="pnl"  dragHandle=".ui-panel-titlebar">
        +    <p-panel header="Drag Header">
        +        The story begins as Don Vito Corleone, the head of a New York Mafia family, oversees his daughter's wedding. 
        +        His beloved son Michael has just come home from the war, but does not intend to become part of his father's business. 
        +        Through Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, 
        +        kind and benevolent to those who give respect, but given to ruthless violence whenever anything stands against the good of the family.
        +    </p-panel>
        +</div>
        +
        +<h3>Drag and Drop to DataTable</h3>
        +<div class="ui-grid ui-grid-pad ui-grid-responsive">
        +    <div class="ui-grid-row">
        +        <div class="ui-grid-col-6 ui-widget-content" style="border-right:0 none">
        +            <ul style="margin:0;padding:0">
        +                <li *ngFor="let car of availableCars" class="ui-state-default ui-helper-clearfix" pDraggable="cars"
        +                    (onDragStart)="dragStart($event,car)" (onDragEnd)="dragEnd($event)">
        +                    <i class="fa fa-arrows fa-2x" style="float:right;margin-top:8px"></i>
        +                    <img src="showcase/resources/demo/images/car/{{car.brand}}.gif" style="float:left" draggable="false">
        +                    <div style="margin:8px 0 0 8px;float:left">{{car.vin}} - {{car.year}}</div>
        +                </li>
        +            </ul>
        +        </div>
        +        <div class="ui-grid-col-6 ui-widget-content" pDroppable="cars" (onDrop)="drop($event)"
        +                [ngClass]="{'ui-state-highlight':draggedCar}">
        +            <p-dataTable [value]="selectedCars">
        +                <p-column field="vin" header="Vin"></p-column>
        +                <p-column field="year" header="Year"></p-column>
        +                <p-column field="brand" header="Brand"></p-column>
        +                <p-column field="color" header="Color"></p-column>
        +            </p-dataTable>
        +        </div>
        +    </div>
        +</div>
        +
        +
        + +
        +
        +export class DragDropDemo {
        +    
        +    availableCars: Car[];
        +    
        +    selectedCars: Car[];
        +    
        +    draggedCar: Car;
        +    
        +    constructor(private carService: CarService) { }
        +    
        +    ngOnInit() {
        +        this.selectedCars = [];
        +        this.carService.getCarsSmall().then(cars => this.availableCars = cars);
        +    }
        +    
        +    dragStart(event,car: Car) {
        +        this.draggedCar = car;
        +    }
        +    
        +    drop(event) {
        +        if(this.draggedCar) {
        +            let draggedCarIndex = this.findIndex(this.draggedCar);
        +            this.selectedCars = [...this.selectedCars, this.draggedCar];
        +            this.availableCars = this.availableCars.filter((val,i) => i!=draggedCarIndex);
        +            this.draggedCar = null;
        +        }
        +    }
        +    
        +    dragEnd(event) {
        +        this.draggedCar = null;
        +    }
        +    
        +    findIndex(car: Car) {
        +        let index = -1;
        +        for(let i = 0; i < this.availableCars.length; i++) {
        +            if(car.vin === this.availableCars[i].vin) {
        +                index = i;
        +                break;
        +            }
        +        }
        +        return index;
        +    }
        +
        +}
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/dragdrop/dragdropdemo.module.ts b/src/app/showcase/components/dragdrop/dragdropdemo.module.ts new file mode 100644 index 00000000000..545c0cc3f7f --- /dev/null +++ b/src/app/showcase/components/dragdrop/dragdropdemo.module.ts @@ -0,0 +1,26 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {DragDropDemo} from './dragdropdemo'; +import {DragDropDemoRoutingModule} from './dragdropdemo-routing.module'; +import {DragDropModule} from '../../../components/dragdrop/dragdrop'; +import {PanelModule} from '../../../components/panel/panel'; +import {DataTableModule} from '../../../components/datatable/datatable'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + + +@NgModule({ + imports: [ + CommonModule, + DragDropDemoRoutingModule, + DragDropModule, + PanelModule, + DataTableModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + DragDropDemo + ] +}) +export class DragDropDemoModule {} diff --git a/src/app/showcase/components/dragdrop/dragdropdemo.ts b/src/app/showcase/components/dragdrop/dragdropdemo.ts new file mode 100644 index 00000000000..ece1ca4a278 --- /dev/null +++ b/src/app/showcase/components/dragdrop/dragdropdemo.ts @@ -0,0 +1,58 @@ +import {Component} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; + +@Component({ + templateUrl: './dragdropdemo.html', + styles: [` + .ui-grid li { + list-style-type: none; + padding: 10px; + margin-bottom: 5px; + } + `] +}) +export class DragDropDemo { + + availableCars: Car[]; + + selectedCars: Car[]; + + draggedCar: Car; + + constructor(private carService: CarService) { } + + ngOnInit() { + this.selectedCars = []; + this.carService.getCarsSmall().then(cars => this.availableCars = cars); + } + + dragStart(event,car: Car) { + this.draggedCar = car; + } + + drop(event) { + if(this.draggedCar) { + let draggedCarIndex = this.findIndex(this.draggedCar); + this.selectedCars = [...this.selectedCars, this.draggedCar]; + this.availableCars = this.availableCars.filter((val,i) => i!=draggedCarIndex); + this.draggedCar = null; + } + } + + dragEnd(event) { + this.draggedCar = null; + } + + findIndex(car: Car) { + let index = -1; + for(let i = 0; i < this.availableCars.length; i++) { + if(car.vin === this.availableCars[i].vin) { + index = i; + break; + } + } + return index; + } + +} \ No newline at end of file diff --git a/src/app/showcase/components/dropdown/dropdown.html b/src/app/showcase/components/dropdown/dropdown.html new file mode 100644 index 00000000000..8e5140e004e --- /dev/null +++ b/src/app/showcase/components/dropdown/dropdown.html @@ -0,0 +1,401 @@ +
        +
        + Dropdown + Dropdown is used to select an item from a collection of options. Custom content support and filtering are the notable features. +
        +
        + +
        +

        Single

        + +

        Selected City: {{selectedCity ? selectedCity.name : 'none'}}

        + +

        Editable

        + +

        Selected Car: {{selectedCar||'none'}}

        + +

        Content with Filters

        + + +
        + +
        {{car.label}}
        +
        +
        +
        +

        Selected Car: {{selectedCar2||'none'}}

        +
        + +
        + + +

        Import

        +
        +
        +import {DropdownModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Two-way value binding is defined using ngModel and dropdown requires a collection of options + where each option should follow the SelectItem interface that defines label-value properties.

        +
        +
        +<p-dropdown [options]="cities" [(ngModel)]="selectedCity"></p-dropdown>
        +
        +
        + +
        +
        +import {SelectItem} from 'primeng/primeng';
        +
        +export class MyModel {
        +
        +    cities: SelectItem[];
        +
        +    selectedCity: string;
        +
        +    constructor() {
        +        this.cities = [];
        +        this.cities.push({label:'Select City', value:null});
        +        this.cities.push({label:'New York', value:{id:1, name: 'New York', code: 'NY'}});
        +        this.cities.push({label:'Rome', value:{id:2, name: 'Rome', code: 'RM'}});
        +        this.cities.push({label:'London', value:{id:3, name: 'London', code: 'LDN'}});
        +        this.cities.push({label:'Istanbul', value:{id:4, name: 'Istanbul', code: 'IST'}});
        +        this.cities.push({label:'Paris', value:{id:5, name: 'Paris', code: 'PRS'}});
        +    }
        +
        +}
        +
        +
        + +

        Model Driven Forms

        +

        Dropdown can be used in a model driven form as well.

        +
        +
        +<p-dropdown [options]="cities" formControlName="selectedCity"></p-dropdown>
        +
        +
        + +

        Filtering

        +

        Options can be filtered using an input field in the overlay by enabling the filter property.

        +
        +
        +<p-dropdown [options]="cities" [(ngModel)]="selectedCity" [filter]="true"></p-dropdown>
        +
        +
        + +

        Custom Content

        +

        Label of an option is used as the display text of an item by default, for custom content support define a ng-template that gets the SelectItem as the local ng-template variable.

        +
        +
        +<p-dropdown [options]="cars" [(ngModel)]="selectedCar" [style]="{'width':'150px'}">
        +    <ng-template let-car pTemplate="item">
        +        <div class="ui-helper-clearfix" style="position: relative;height: 25px;">
        +            <img src="showcase/resources/demo/images/car/{{car.label}}.gif" style="width:24px;position:absolute;top:1px;left:5px"/>
        +            <div style="font-size:14px;float:right;margin-top:4px">{{car.label}}</div>
        +        </div>
        +    </ng-template>
        +</p-dropdown>
        +
        +
        + +
        +
        +import {SelectItem} from 'primeng/primeng'
        +
        +export class MyModel {
        +
        +    cars: SelectItem[];
        +
        +    selectedCar: string;
        +
        +    constructor() {
        +        this.cars = [];
        +        this.cars.push({label: 'Audi', value: 'Audi'});
        +        this.cars.push({label: 'BMW', value: 'BMW'});
        +        this.cars.push({label: 'Fiat', value: 'Fiat'});
        +        this.cars.push({label: 'Ford', value: 'Ford'});
        +        this.cars.push({label: 'Honda', value: 'Honda'});
        +        this.cars.push({label: 'Jaguar', value: 'Jaguar'});
        +        this.cars.push({label: 'Mercedes', value: 'Mercedes'});
        +        this.cars.push({label: 'Renault', value: 'Renault'});
        +        this.cars.push({label: 'VW', value: 'VW'});
        +        this.cars.push({label: 'Volvo', value: 'Volvo'});
        +    }
        +}
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        optionsarraynullAn array of selectitems to display as the available options.
        scrollHeightstring200pxHeight of the viewport in pixels, a scrollbar is defined if height of list exceeds this value.
        stylestringnullInline style of the element.
        panelStylestringnullInline style of the overlay panel element.
        styleClassstringnullStyle class of the element.
        panelStyleClassstringnullStyle class of the overlay panel element.
        filterbooleanfalseWhen specified, displays an input field to filter the items on keyup.
        filterPlaceholderstringnullPlaceholder text to show when filter input is empty.
        autoWidthbooleantrueCalculates the width based on options width, set to false for custom width.
        requiredbooleanfalseWhen present, it specifies that an input field must be filled out before submitting the form.
        disabledbooleanfalseWhen present, it specifies that the component should be disabled.
        editablebooleanfalseWhen present, custom value instead of predefined options can be entered using the editable input field.
        appendToanynullTarget element to attach the overlay, valid values are "body" or a local ng-template variable of another element.
        tabindexnumbernullIndex of the element in tabbing order.
        placeholderstringnullDefault text to display when no option is selected.
        inputIdstringnullIdentifier of the focus input to match a label defined for the dropdown.
        dataKeystringnullA property to uniquely identify a value in options.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onChangeevent.originalEvent: Browser event
        + event.value: Selected option value +
        Callback to invoke when value of dropdown changes.
        onFocusevent: Browser eventCallback to invoke when dropdown gets focus.
        onBlurevent: Browser eventCallback to invoke when dropdown loses focus.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-dropdownContainer element.
        ui-dropdown-labelElement to display label of selected option.
        ui-dropdown-triggerIcon element.
        ui-dropdown-panelIcon element.
        ui-dropdown-items-wrapperWrapper element of items list.
        ui-dropdown-itemsList element of items.
        ui-dropdown-itemAn item in the list.
        ui-dropdown-filter-containerContainer of filter input.
        ui-dropdown-filterFilter element.
        ui-dropdown-openContainer element when overlay is visible.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<h3 class="first">Single</h3>
        +<p-dropdown [options]="cities" [(ngModel)]="selectedCity" placeholder="Select a City"></p-dropdown>
        +<p>Selected City: {{selectedCity ? selectedCity.name : 'none'}}</p>
        +
        +<h3>Editable</h3>
        +<p-dropdown [options]="cars" [(ngModel)]="selectedCar" [style]="{'width':'150px'}" editable="editable" placeholder="Select a Brand"></p-dropdown>
        +<p>Selected Car: {{selectedCar||'none'}}</p>
        +
        +<h3>Content with Filters</h3>
        +<p-dropdown [options]="cars" [(ngModel)]="selectedCar2" [style]="{'width':'150px'}" filter="filter">
        +    <ng-template let-car pTemplate="item">
        +        <div class="ui-helper-clearfix" style="position: relative;height: 25px;">
        +            <img src="showcase/resources/demo/images/car/{{car.label}}.gif" style="width:24px;position:absolute;top:1px;left:5px"/>
        +            <div style="font-size:14px;float:right;margin-top:4px">{{car.label}}</div>
        +        </div>
        +    </ng-template>
        +</p-dropdown>
        +<p>Selected Car: {{selectedCar2||'none'}}</p>
        +
        +
        + +
        +
        +export class DropdownDemo {
        +
        +    cities: SelectItem[];
        +
        +    selectedCity: string;
        +
        +    cars: SelectItem[];
        +
        +    selectedCar: string = 'BMW';
        +
        +    constructor() {
        +        this.cities = [];
        +        this.cities.push({label:'New York', value:{id:1, name: 'New York', code: 'NY'}});
        +        this.cities.push({label:'Rome', value:{id:2, name: 'Rome', code: 'RM'}});
        +        this.cities.push({label:'London', value:{id:3, name: 'London', code: 'LDN'}});
        +        this.cities.push({label:'Istanbul', value:{id:4, name: 'Istanbul', code: 'IST'}});
        +        this.cities.push({label:'Paris', value:{id:5, name: 'Paris', code: 'PRS'}});
        +
        +        this.cars = [];
        +        this.cars.push({label: 'Audi', value: 'Audi'});
        +        this.cars.push({label: 'BMW', value: 'BMW'});
        +        this.cars.push({label: 'Fiat', value: 'Fiat'});
        +        this.cars.push({label: 'Ford', value: 'Ford'});
        +        this.cars.push({label: 'Honda', value: 'Honda'});
        +        this.cars.push({label: 'Jaguar', value: 'Jaguar'});
        +        this.cars.push({label: 'Mercedes', value: 'Mercedes'});
        +        this.cars.push({label: 'Renault', value: 'Renault'});
        +        this.cars.push({label: 'VW', value: 'VW'});
        +        this.cars.push({label: 'Volvo', value: 'Volvo'});
        +    }
        +
        +}
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/dropdown/dropdowndemo-routing.module.ts b/src/app/showcase/components/dropdown/dropdowndemo-routing.module.ts new file mode 100644 index 00000000000..c15acef57cc --- /dev/null +++ b/src/app/showcase/components/dropdown/dropdowndemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {DropdownDemo} from './dropdowndemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: DropdownDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class DropdownDemoRoutingModule {} diff --git a/src/app/showcase/components/dropdown/dropdowndemo.module.ts b/src/app/showcase/components/dropdown/dropdowndemo.module.ts new file mode 100644 index 00000000000..2816cefc1cc --- /dev/null +++ b/src/app/showcase/components/dropdown/dropdowndemo.module.ts @@ -0,0 +1,23 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {DropdownDemo} from './dropdowndemo'; +import {DropdownDemoRoutingModule} from './dropdowndemo-routing.module'; +import {DropdownModule} from '../../../components/dropdown/dropdown'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + DropdownDemoRoutingModule, + DropdownModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + DropdownDemo + ] +}) +export class DropdownDemoModule {} diff --git a/src/app/showcase/components/dropdown/dropdowndemo.ts b/src/app/showcase/components/dropdown/dropdowndemo.ts new file mode 100644 index 00000000000..71aa94fd744 --- /dev/null +++ b/src/app/showcase/components/dropdown/dropdowndemo.ts @@ -0,0 +1,40 @@ +import {Component} from '@angular/core'; +import {SelectItem} from '../../../components/common/api'; + +@Component({ + templateUrl: './dropdown.html', +}) +export class DropdownDemo { + + cities: SelectItem[]; + + selectedCity: any; + + cars: SelectItem[]; + + selectedCar: string; + + selectedCar2: string = 'BMW'; + + constructor() { + this.cities = []; + this.cities.push({label:'New York', value:{id:1, name: 'New York', code: 'NY'}}); + this.cities.push({label:'Rome', value:{id:2, name: 'Rome', code: 'RM'}}); + this.cities.push({label:'London', value:{id:3, name: 'London', code: 'LDN'}}); + this.cities.push({label:'Istanbul', value:{id:4, name: 'Istanbul', code: 'IST'}}); + this.cities.push({label:'Paris', value:{id:5, name: 'Paris', code: 'PRS'}}); + + this.cars = []; + this.cars.push({label: 'Audi', value: 'Audi'}); + this.cars.push({label: 'BMW', value: 'BMW'}); + this.cars.push({label: 'Fiat', value: 'Fiat'}); + this.cars.push({label: 'Ford', value: 'Ford'}); + this.cars.push({label: 'Honda', value: 'Honda'}); + this.cars.push({label: 'Jaguar', value: 'Jaguar'}); + this.cars.push({label: 'Mercedes', value: 'Mercedes'}); + this.cars.push({label: 'Renault', value: 'Renault'}); + this.cars.push({label: 'VW', value: 'VW'}); + this.cars.push({label: 'Volvo', value: 'Volvo'}); + } + +} \ No newline at end of file diff --git a/src/app/showcase/components/editor/editordemo-routing.module.ts b/src/app/showcase/components/editor/editordemo-routing.module.ts new file mode 100644 index 00000000000..eebf3f3b4cc --- /dev/null +++ b/src/app/showcase/components/editor/editordemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {EditorDemo} from './editordemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: EditorDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class EditorDemoRoutingModule {} diff --git a/src/app/showcase/components/editor/editordemo.html b/src/app/showcase/components/editor/editordemo.html new file mode 100644 index 00000000000..6c0ac5f59d1 --- /dev/null +++ b/src/app/showcase/components/editor/editordemo.html @@ -0,0 +1,283 @@ +
        +
        + Editor + Editor is rich text editor component based on Quill. +
        +
        + +
        +

        Default

        + +

        Value: {{text1||'empty'}}

        + + + +
        + +

        Custom Toolbar

        + + + + + + + + + +

        Value: {{text2||'empty'}}

        + + +
        + +
        + + +

        Import

        +
        +
        +import {EditorModule,SharedModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Two-way value binding is defined with ngModel.

        + +
        +
        +<p-editor [(ngModel)]="text" [style]="{'height':'320px'}"></p-editor>
        +
        +
        + +
        +
        +export class EditorDemo {
        +    
        +    text: string;
        +        
        +}
        +
        +
        + +

        Model Driven Forms

        +

        Editor can be used in a model driven form as well.

        +
        +
        +<p-editor formControlName="description" [style]="{'height':'320px'}"></p-editor>
        +
        +
        + +

        Toolbar

        +

        Editor provides a default toolbar with common options, to customize it define your elements inside the header element. Refer to Quill documentation for available controls.

        +
        +
        +<p-editor [(ngModel)]="text2" [style]="{'height':'320px'}">
        +    <p-header>
        +        <span class="ql-format-group">
        +            <span title="Bold" class="ql-format-button ql-bold"></span>
        +            <span class="ql-format-separator"></span>
        +            <span title="Italic" class="ql-format-button ql-italic"></span>
        +            <span class="ql-format-separator"></span>
        +            <span title="Underline" class="ql-format-button ql-underline"></span>
        +            <span class="ql-format-separator"></span>
        +            <span title="Strikethrough" class="ql-format-button ql-strike"></span>
        +        </span>
        +    </p-header>
        +</p-editor>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        stylestringnullInline style of the container.
        styleClassstringnullStyle class of the container.
        placeholderstringnullPlaceholder text to show when editor is empty.
        readonlybooleanfalseWhether to instantiate the editor to read-only mode.
        formatsstring[]nullWhitelist of formats to display, see here for available options.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onTextChangeevent.delta: Representation of the change.
        + event.source: Source of change. Will be either "user" or "api".
        + event.htmlValue: Current value as html.
        + event.textValue: Current value as text.
        Callback to invoke when text of editor changes.
        onSelectionChangeevent.range: Object with index and length keys indicating where the selection exists.
        + event.oldRange: Object with index and length keys indicating where the previous selection was..
        + event.source: Source of change. Will be either "user" or "api".
        Callback to invoke when selected text of editor changes.
        onInitevent.editor: Quill editor instance.
        + event.oldRange: Object with index and length keys indicating where the previous selection was..
        + event.source: Source of change. Will be either "user" or "api".
        Callback to invoke after editor is initialized.
        +
        + +

        Refer to Quill documentation for more information.

        + +

        Methods

        +
        + + + + + + + + + + + + + + + +
        NameParametersDescription
        getQuill-Returns the underlying quill instance.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-editor-containerContainer element
        ui-editor-toolbarToolbar of the editor
        ui-editor-contentEditable area
        +
        + +

        Dependencies

        +

        Quill Editor 1.0.

        +

        Resources of quill needs to be added to your application. Example setup with CLI is as follows;

        +
        +
        +npm install quill --save
        +
        +
        +

        Add Quill to scripts in angular-cli.json

        +
        +
        +"scripts": [... "../node_modules/quill/dist/quill.js"],
        +
        +
        +

        Add Quill css to styles in angular-cli.json

        +
        +
        +"styles": [ ... "../node_modules/quill/dist/quill.core.css", "../node_modules/quill/dist/quill.snow.css"],
        + 
        +
        + +
        + +
        +
        +<h3 class="first">Default</h3>
        +<p-editor [(ngModel)]="text1" [style]="{'height':'320px'}"></p-editor>
        +<p>Value: {{text1||'empty'}}</p>
        +
        +<button pButton type="button" label="Clear" icon="fa-close" (click)="text1=null"></button>
        +
        +<hr style="border-top:0px;border-color:#dde3e6">
        +
        +<h3>Custom Toolbar</h3>
        +<p-editor [(ngModel)]="text2" [style]="{'height':'320px'}">
        +    <p-header>
        +        <span class="ql-formats">
        +            <button class="ql-bold"></button>
        +            <button class="ql-italic"></button>
        +            <button class="ql-underline"></button>
        +        </span>
        +    </p-header>
        +</p-editor>
        +<p>Value: {{text2||'empty'}}</p>
        +
        +<button pButton type="button" label="Clear" icon="fa-close" (click)="text2=null"></button>
        +
        +
        + +
        +
        +export class EditorDemo {
        +
        +    text1: string = '<div>Hello World!</div><div>PrimeNG <b>Editor</b> Rocks</div><div><br></div>';
        +    
        +    text2: string;
        +}
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/editor/editordemo.module.ts b/src/app/showcase/components/editor/editordemo.module.ts new file mode 100644 index 00000000000..2e8154e9f59 --- /dev/null +++ b/src/app/showcase/components/editor/editordemo.module.ts @@ -0,0 +1,25 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {EditorDemo} from './editordemo'; +import {EditorDemoRoutingModule} from './editordemo-routing.module'; +import {EditorModule} from '../../../components/editor/editor'; +import {ButtonModule} from '../../../components/button/button'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + EditorDemoRoutingModule, + EditorModule, + ButtonModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + EditorDemo + ] +}) +export class EditorDemoModule {} diff --git a/src/app/showcase/components/editor/editordemo.ts b/src/app/showcase/components/editor/editordemo.ts new file mode 100644 index 00000000000..c6a7f536bff --- /dev/null +++ b/src/app/showcase/components/editor/editordemo.ts @@ -0,0 +1,11 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './editordemo.html' +}) +export class EditorDemo { + + text1: string = '
        Hello World!
        PrimeNG Editor Rocks

        '; + + text2: string; +} \ No newline at end of file diff --git a/src/app/showcase/components/fieldset/fieldsetdemo-routing.module.ts b/src/app/showcase/components/fieldset/fieldsetdemo-routing.module.ts new file mode 100644 index 00000000000..d6db82a4497 --- /dev/null +++ b/src/app/showcase/components/fieldset/fieldsetdemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {FieldsetDemo} from './fieldsetdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: FieldsetDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class FieldsetDemoRoutingModule {} diff --git a/src/app/showcase/components/fieldset/fieldsetdemo.html b/src/app/showcase/components/fieldset/fieldsetdemo.html new file mode 100644 index 00000000000..e947b900bbc --- /dev/null +++ b/src/app/showcase/components/fieldset/fieldsetdemo.html @@ -0,0 +1,197 @@ +
        +
        + Fieldset + Fieldset is a grouping component with a content toggle feature. +
        +
        + +
        + + The story begins as Don Vito Corleone, the head of a New York Mafia family, oversees his daughter's wedding. + His beloved son Michael has just come home from the war, but does not intend to become part of his father's business. + Through Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, + kind and benevolent to those who give respect, + but given to ruthless violence whenever anything stands against the good of the family. + +
        + + The story begins as Don Vito Corleone, the head of a New York Mafia family, oversees his daughter's wedding. + His beloved son Michael has just come home from the war, but does not intend to become part of his father's business. + Through Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, + kind and benevolent to those who give respect, + but given to ruthless violence whenever anything stands against the good of the family. + +
        + +
        + + +

        Import

        +
        +
        +import {FieldsetModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Fieldset is defined with p-fieldset element.

        +
        +
        +<p-fieldset legend="Header">
        +    Content
        +</p-fieldset>
        +
        +
        + +

        Toggleable

        +

        Content of the fieldset can be expanded and collapsed using toggleable option, default state is defined with collapsed option.

        +
        +
        +<p-fieldset legend="Header" [toggleable]="true">
        +    Content
        +</p-fieldset>
        +
        +
        + +

        Custom Legend

        +

        Legend content can be customized with p-header component.

        +
        +
        +<p-fieldset>
        +    <p-header>Custom Legend Content</p-header>
        +    Content
        +</p-fieldset>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        legendstringnullHeader text of the fieldset.
        toggleablebooleanfalseWhen specified, content can toggled by clicking the legend.
        collapsedbooleanfalseDefines the default visibility state of the content.
        stylestringnullInline style of the fieldset.
        styleClassstringnullStyle class of the fieldset.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onBeforeToggleevent.originalEvent: browser event
        + event.collapsed: state as a boolean
        Callback to invoke before content toggle.
        onAfterToggleevent.originalEvent: browser event
        + event.collapsed: state as a boolean
        Callback to invoke after content toggle.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-fieldsetFieldset element
        ui-fieldset-toggleableToggleable fieldset element
        ui-fieldset-legendLegend element.
        ui-fieldset-contentContent element.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<p-fieldset legend="Godfather I">
        +    The story begins as Don Vito Corleone, the head of a New York Mafia family, oversees his daughter's wedding. 
        +    His beloved son Michael has just come home from the war, but does not intend to become part of his father's business. 
        +    Through Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, 
        +    kind and benevolent to those who give respect, 
        +    but given to ruthless violence whenever anything stands against the good of the family.
        +</p-fieldset>
        +
        +<p-fieldset legend="Toggleable" [toggleable]="true">
        +    The story begins as Don Vito Corleone, the head of a New York Mafia family, oversees his daughter's wedding. 
        +    His beloved son Michael has just come home from the war, but does not intend to become part of his father's business. 
        +    Through Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, 
        +    kind and benevolent to those who give respect, 
        +    but given to ruthless violence whenever anything stands against the good of the family.
        +</p-fieldset>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/fieldset/fieldsetdemo.module.ts b/src/app/showcase/components/fieldset/fieldsetdemo.module.ts new file mode 100644 index 00000000000..907b318008b --- /dev/null +++ b/src/app/showcase/components/fieldset/fieldsetdemo.module.ts @@ -0,0 +1,21 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FieldsetDemo} from './fieldsetdemo'; +import {FieldsetDemoRoutingModule} from './fieldsetdemo-routing.module'; +import {FieldsetModule} from '../../../components/fieldset/fieldset'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + FieldsetDemoRoutingModule, + FieldsetModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + FieldsetDemo + ] +}) +export class FieldsetDemoModule {} diff --git a/src/app/showcase/components/fieldset/fieldsetdemo.ts b/src/app/showcase/components/fieldset/fieldsetdemo.ts new file mode 100644 index 00000000000..33d8337e74d --- /dev/null +++ b/src/app/showcase/components/fieldset/fieldsetdemo.ts @@ -0,0 +1,8 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './fieldsetdemo.html' +}) +export class FieldsetDemo { + +} \ No newline at end of file diff --git a/src/app/showcase/components/fileupload/fileuploaddemo-routing.module.ts b/src/app/showcase/components/fileupload/fileuploaddemo-routing.module.ts new file mode 100644 index 00000000000..68ee64cd111 --- /dev/null +++ b/src/app/showcase/components/fileupload/fileuploaddemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {FileUploadDemo} from './fileuploaddemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: FileUploadDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class FileUploadDemoRoutingModule {} diff --git a/src/app/showcase/components/fileupload/fileuploaddemo.html b/src/app/showcase/components/fileupload/fileuploaddemo.html new file mode 100644 index 00000000000..3cb6a339c52 --- /dev/null +++ b/src/app/showcase/components/fileupload/fileuploaddemo.html @@ -0,0 +1,367 @@ +
        +
        + FileUpload + FileUpload is an advanced uploader with dragdrop support, multi file uploads, auto uploading, progress tracking and + validations. +
        +
        + +
        + + + + +
          +
        • {{file.name}} - {{file.size}} bytes
        • +
        +
        +
        +
        + +
        + + +

        Import

        +
        +
        +import {FileUploadModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        FileUpload requires a url property as the upload target and a name to identify the files at backend.

        +
        +
        +<p-fileUpload name="myfile[]" url="http://localhost:3000/upload"></p-fileUpload>
        +
        +
        + +

        Multiple Uploads

        +

        Only one file can be selected at a time, to allow selecting multiples enable multiple option.

        +
        +
        +<p-fileUpload name="myfile[]" url="http://localhost:3000/upload" multiple="multiple"></p-fileUpload>
        +
        +
        + +

        DragDrop

        +

        File selection can also be done by dragging and dropping one or more to the content section of the component.

        + +

        Auto Uploads

        +

        When auto property is enabled, upload begins as soon as file selection is completed or a file is dropped on the drop area.

        +
        +
        +<p-fileUpload name="myfile[]" url="http://localhost:3000/upload" multiple="multiple"
        +        accept="image/*" auto="auto"></p-fileUpload>
        +
        +
        + +

        File Types

        +

        Selectable file types can be restricted with accept property, example below only allows images to be uploaded. + Read more about other possible values here.

        +
        +
        +<p-fileUpload name="myfile[]" url="http://localhost:3000/upload" multiple="multiple"
        +        accept="image/*"></p-fileUpload>
        +
        +
        + +

        File Size

        +

        Maximium file size can be restricted using maxFileSize property defined in bytes.

        +
        +
        +<p-fileUpload name="myfile[]" url="http://localhost:3000/upload" multiple="multiple"
        +        accept="image/*" maxFileSize="1000000"></p-fileUpload>
        +
        +
        + +

        In order to customize the default messages use invalidFileSizeMessageSummary and invalidFileSizeMessageDetail options. + In summary {0} placeholder refers to the filename and in detail, file size.

        +
          +
        • invalidFileSizeMessageSummary: '{0}: Invalid file size, '
        • +
        • invalidFileSizeMessageDetail: string = 'maximum upload size is {0}.'
        • +
        + +

        Templating

        +

        File list UI is customizable using a ng-template called "file" that gets the File instance as the implicit variable. + Second ng-template named "content" can be used to place custom content inside the content section which would be useful to implement a user interface to manage the uploaded files such as removing them. + Third and final ng-template option is "toolbar" to display custom content at toolbar.

        +
        +
        +<p-fileUpload name="myfile[]" url="http://localhost:3000/upload" multiple="multiple"
        +        accept="image/*" maxFileSize="1000000">
        +        <ng-template pTemplate="toolbar">
        +            <div>Upload 3 Files</div>
        +        </ng-template>  
        +        <ng-template let-file pTemplate="file">
        +            <div>Custom UI to display a file</div>
        +        </ng-template> 
        +        <ng-template pTemplate="content">
        +            <div>Custom UI to manage uploaded files</div>
        +        </ng-template>  
        +</p-fileUpload>
        +
        +
        + +

        Request Customization

        +

        XHR request to upload the files can be customized using the onBeforeUpload callback that passes + the xhr instance and FormData object as event parameters.

        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        namestringnullName of the request parameter to identify the files at backend.
        urlstringnullRemote url to upload the files.
        methodstringPOSTHTTP method to send the files to the url.
        multiplebooleanfalseUsed to select multiple files at once from file dialog.
        acceptstringfalsePattern to restrict the allowed file types such as "image/*".
        disabledbooleanfalseDisables the upload functionality.
        autobooleanfalseWhen enabled, upload begins automatically after selection is completed.
        maxFileSizenumbernullMaximum file size allowed in bytes.
        invalidFileSizeMessageSummarystring"{0}: Invalid file size, "Summary message of the invalid fize size.
        invalidFileSizeMessageDetailstring"maximum upload size is {0}."Detail message of the invalid fize size.
        invalidFileTypeMessageSummarystring"{0}: Invalid file type, "Summary message of the invalid fize type.
        invalidFileTypeMessageDetailstring"allowed file types: {0}."Detail message of the invalid fize type.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        previewWidthnumber50Width of the image thumbnail in pixels.
        chooseLabelstringChooseLabel of the choose button.
        uploadLabelstringUploadLabel of the upload button.
        cancelLabelstringCancelLabel of the cancel button.
        withCredentialsbooleanfalseCross-site Access-Control requests should be made using credentials such as cookies, authorization headers or TLS client certificates.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onBeforeUploadevent.xhr: XmlHttpRequest instance.
        + event.formData: FormData object.
        Callback to invoke before file upload begins to customize the request + such as post parameters before the files.
        onBeforeSendevent.xhr: XmlHttpRequest instance.
        + event.formData: FormData object.
        Callback to invoke before file send begins to customize the request + such as adding headers.
        onUploadevent.xhr: XmlHttpRequest instance.
        + event.files: Uploaded files.
        Callback to invoke when file upload is complete.
        onErrorevent.xhr: XmlHttpRequest instance.
        + event.files: Files that are not uploaded.
        Callback to invoke if file upload fails.
        onClear-.Callback to invoke when files in queue are removed without uploading using clear all button.
        onRemoveevent.originalEvent: Original browser event.
        + event.file: Selected file.
        Callback to invoke when a file is removed without uploading using clear button of a file.
        onSelectevent.originalEvent: Original browser event.
        + event.files: List of selected files.
        Callback to invoke when files are selected.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-fileuploadContainer element
        ui-fileupload-buttonbarHeader containing the buttons
        ui-fileupload-contentContent section
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<p-growl [value]="msgs"></p-growl>
        +    
        +<p-fileUpload name="demo[]" url="http://localhost:3000/upload" (onUpload)="onUpload($event)" 
        +        multiple="multiple" accept="image/*" maxFileSize="1000000">
        +    <ng-template pTemplate type="content">
        +        <ul *ngIf="uploadedFiles.length">
        +            <li *ngFor="let file of uploadedFiles">{{file.name}} - {{file.size}} bytes</li>
        +        </ul>
        +    </ng-template>        
        +</p-fileUpload>
        +
        +
        + +
        +
        +export class FileUploadDemo {
        +
        +    msgs: Message[];
        +    
        +    uploadedFiles: any[] = [];
        +
        +    onUpload(event) {
        +        for(let file of event.files) {
        +            this.uploadedFiles.push(file);
        +        }
        +    
        +        this.msgs = [];
        +        this.msgs.push({severity: 'info', summary: 'File Uploaded', detail: ''});
        +    }
        +}
        +
        +
        +
        +
        +
        diff --git a/src/app/showcase/components/fileupload/fileuploaddemo.module.ts b/src/app/showcase/components/fileupload/fileuploaddemo.module.ts new file mode 100644 index 00000000000..485030b4bff --- /dev/null +++ b/src/app/showcase/components/fileupload/fileuploaddemo.module.ts @@ -0,0 +1,23 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FileUploadDemo} from './fileuploaddemo'; +import {FileUploadDemoRoutingModule} from './fileuploaddemo-routing.module'; +import {FileUploadModule} from '../../../components/fileupload/fileupload'; +import {GrowlModule} from '../../../components/growl/growl'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + FileUploadDemoRoutingModule, + FileUploadModule, + GrowlModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + FileUploadDemo + ] +}) +export class FileUploadDemoModule {} diff --git a/src/app/showcase/components/fileupload/fileuploaddemo.ts b/src/app/showcase/components/fileupload/fileuploaddemo.ts new file mode 100644 index 00000000000..8aae937a156 --- /dev/null +++ b/src/app/showcase/components/fileupload/fileuploaddemo.ts @@ -0,0 +1,21 @@ +import {Component} from '@angular/core'; +import {Message} from '../../../components/common/api'; + +@Component({ + templateUrl: './fileuploaddemo.html' +}) +export class FileUploadDemo { + + msgs: Message[]; + + uploadedFiles: any[] = []; + + onUpload(event) { + for(let file of event.files) { + this.uploadedFiles.push(file); + } + + this.msgs = []; + this.msgs.push({severity: 'info', summary: 'File Uploaded', detail: ''}); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/galleria/galleriademo-routing.module.ts b/src/app/showcase/components/galleria/galleriademo-routing.module.ts new file mode 100644 index 00000000000..d5de1b7db2c --- /dev/null +++ b/src/app/showcase/components/galleria/galleriademo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {GalleriaDemo} from './galleriademo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: GalleriaDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class GalleriaDemoRoutingModule {} diff --git a/src/app/showcase/components/galleria/galleriademo.html b/src/app/showcase/components/galleria/galleriademo.html new file mode 100644 index 00000000000..b09727fd0d8 --- /dev/null +++ b/src/app/showcase/components/galleria/galleriademo.html @@ -0,0 +1,247 @@ +
        +
        + Galleria + Galleria is a content gallery component. +
        +
        + +
        + +
        + +
        + + +

        Import

        +
        +
        +import {GalleriaModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Galleria requires a set of images to display. Source attribute defines the path of the image whereas title and alt attributes are used in the caption section + to display summary and description about an image.

        +
        +
        +<p-galleria [images]="images" panelWidth="500" panelHeight="313" [showCaption]="true"></p-galleria>
        +
        +
        + +
        +
        +export class GalleriaDemo implements OnInit {
        +    
        +    images: any[];
        +    
        +    ngOnInit() {
        +        this.images = [];
        +        this.images.push({source:'showcase/resources/demo/images/galleria/galleria1.jpg', alt:'Description for Image 1', title:'Title 1'});
        +        this.images.push({source:'showcase/resources/demo/images/galleria/galleria2.jpg', alt:'Description for Image 2', title:'Title 2'});
        +        this.images.push({source:'showcase/resources/demo/images/galleria/galleria3.jpg', alt:'Description for Image 3', title:'Title 3'});
        +        this.images.push({source:'showcase/resources/demo/images/galleria/galleria4.jpg', alt:'Description for Image 4', title:'Title 4'});
        +        this.images.push({source:'showcase/resources/demo/images/galleria/galleria5.jpg', alt:'Description for Image 5', title:'Title 5'});
        +        this.images.push({source:'showcase/resources/demo/images/galleria/galleria6.jpg', alt:'Description for Image 6', title:'Title 6'});
        +        this.images.push({source:'showcase/resources/demo/images/galleria/galleria7.jpg', alt:'Description for Image 7', title:'Title 7'});
        +        this.images.push({source:'showcase/resources/demo/images/galleria/galleria8.jpg', alt:'Description for Image 8', title:'Title 8'});
        +        this.images.push({source:'showcase/resources/demo/images/galleria/galleria9.jpg', alt:'Description for Image 9', title:'Title 9'});
        +        this.images.push({source:'showcase/resources/demo/images/galleria/galleria10.jpg', alt:'Description for Image 10', title:'Title 10'});
        +        this.images.push({source:'showcase/resources/demo/images/galleria/galleria11.jpg', alt:'Description for Image 11', title:'Title 11'});
        +        this.images.push({source:'showcase/resources/demo/images/galleria/galleria12.jpg', alt:'Description for Image 12', title:'Title 12'});
        +    }
        +}
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        panelWidthnumber600Width of the content panel.
        panelHeightnumber400Height of the content panel.
        frameWidthnumber60Width of the filmstrip frames.
        frameHeightnumber40Height of the filmstrip frames.
        showFilmstripbooleantrueDefines visibility of filmstrip.
        autoPlaybooleantrueImages are displayed with a slideshow in autoPlay mode.
        transitionIntervalnumber4000Time in milliseconds between each slide in autoPlay mode.
        effectstringfadeName of animation to use on transitions.
        effectDurationnumber250Duration of animation in milliseconds.
        showCaptionbooleantrueDisplays information retrieved from title and alt attributes of images in content caption.
        activeIndexnumber0Index of the current active image of galleria images.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + +
        NameParametersDescription
        onImageClicked + event.image: Image Object
        + event.originalEvent: Click Object
        + event.index: Index of the image +
        Callback to invoke when the displayed image is clicked.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-galleriaContainer element
        ui-galleria-panel-wrapperParent of item containers.
        ui-galleria-filmstrip-wrapperContainer of filmstrip.
        ui-galleria-filmstripFilmstrip element
        ui-galleria-frameFrame element of thumbnail
        ui-galleria-nav-nextIcon to navigate to next item
        ui-galleria-nav-prevIcon to navigate to previous item
        ui-galleria-captionCaption element that displays title and description of an item
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<p-galleria [images]="images" panelWidth="500" panelHeight="313" showCaption="true"></p-galleria>
        +
        +
        + +
        +
        +export class GalleriaDemo implements OnInit {
        +    
        +    images: any[];
        +    
        +    ngOnInit() {
        +        this.images = [];
        +        this.images.push({source:'showcase/resources/demo/images/galleria/galleria1.jpg', alt:'Description for Image 1', title:'Title 1'});
        +        this.images.push({source:'showcase/resources/demo/images/galleria/galleria2.jpg', alt:'Description for Image 2', title:'Title 2'});
        +        this.images.push({source:'showcase/resources/demo/images/galleria/galleria3.jpg', alt:'Description for Image 3', title:'Title 3'});
        +        this.images.push({source:'showcase/resources/demo/images/galleria/galleria4.jpg', alt:'Description for Image 4', title:'Title 4'});
        +        this.images.push({source:'showcase/resources/demo/images/galleria/galleria5.jpg', alt:'Description for Image 5', title:'Title 5'});
        +        this.images.push({source:'showcase/resources/demo/images/galleria/galleria6.jpg', alt:'Description for Image 6', title:'Title 6'});
        +        this.images.push({source:'showcase/resources/demo/images/galleria/galleria7.jpg', alt:'Description for Image 7', title:'Title 7'});
        +        this.images.push({source:'showcase/resources/demo/images/galleria/galleria8.jpg', alt:'Description for Image 8', title:'Title 8'});
        +        this.images.push({source:'showcase/resources/demo/images/galleria/galleria9.jpg', alt:'Description for Image 9', title:'Title 9'});
        +        this.images.push({source:'showcase/resources/demo/images/galleria/galleria10.jpg', alt:'Description for Image 10', title:'Title 10'});
        +        this.images.push({source:'showcase/resources/demo/images/galleria/galleria11.jpg', alt:'Description for Image 11', title:'Title 11'});
        +        this.images.push({source:'showcase/resources/demo/images/galleria/galleria12.jpg', alt:'Description for Image 12', title:'Title 12'});
        +    }
        +}
        +
        +
        +
        +
        +
        + diff --git a/src/app/showcase/components/galleria/galleriademo.module.ts b/src/app/showcase/components/galleria/galleriademo.module.ts new file mode 100644 index 00000000000..9b530760ae4 --- /dev/null +++ b/src/app/showcase/components/galleria/galleriademo.module.ts @@ -0,0 +1,21 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {GalleriaDemo} from './galleriademo'; +import {GalleriaDemoRoutingModule} from './galleriademo-routing.module'; +import {GalleriaModule} from '../../../components/galleria/galleria'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + GalleriaDemoRoutingModule, + GalleriaModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + GalleriaDemo + ] +}) +export class GalleriaDemoModule {} diff --git a/src/app/showcase/components/galleria/galleriademo.ts b/src/app/showcase/components/galleria/galleriademo.ts new file mode 100644 index 00000000000..8e0050409bc --- /dev/null +++ b/src/app/showcase/components/galleria/galleriademo.ts @@ -0,0 +1,25 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './galleriademo.html' +}) +export class GalleriaDemo { + + images: any[]; + + constructor() { + this.images = []; + this.images.push({source:'showcase/resources/demo/images/galleria/galleria1.jpg', alt:'Description for Image 1', title:'Title 1'}); + this.images.push({source:'showcase/resources/demo/images/galleria/galleria2.jpg', alt:'Description for Image 2', title:'Title 2'}); + this.images.push({source:'showcase/resources/demo/images/galleria/galleria3.jpg', alt:'Description for Image 3', title:'Title 3'}); + this.images.push({source:'showcase/resources/demo/images/galleria/galleria4.jpg', alt:'Description for Image 4', title:'Title 4'}); + this.images.push({source:'showcase/resources/demo/images/galleria/galleria5.jpg', alt:'Description for Image 5', title:'Title 5'}); + this.images.push({source:'showcase/resources/demo/images/galleria/galleria6.jpg', alt:'Description for Image 6', title:'Title 6'}); + this.images.push({source:'showcase/resources/demo/images/galleria/galleria7.jpg', alt:'Description for Image 7', title:'Title 7'}); + this.images.push({source:'showcase/resources/demo/images/galleria/galleria8.jpg', alt:'Description for Image 8', title:'Title 8'}); + this.images.push({source:'showcase/resources/demo/images/galleria/galleria9.jpg', alt:'Description for Image 9', title:'Title 9'}); + this.images.push({source:'showcase/resources/demo/images/galleria/galleria10.jpg', alt:'Description for Image 10', title:'Title 10'}); + this.images.push({source:'showcase/resources/demo/images/galleria/galleria11.jpg', alt:'Description for Image 11', title:'Title 11'}); + this.images.push({source:'showcase/resources/demo/images/galleria/galleria12.jpg', alt:'Description for Image 12', title:'Title 12'}); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/gmap/gmapdemo-routing.module.ts b/src/app/showcase/components/gmap/gmapdemo-routing.module.ts new file mode 100644 index 00000000000..045814da896 --- /dev/null +++ b/src/app/showcase/components/gmap/gmapdemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {GMapDemo} from './gmapdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: GMapDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class GMapDemoRoutingModule {} diff --git a/src/app/showcase/components/gmap/gmapdemo.html b/src/app/showcase/components/gmap/gmapdemo.html new file mode 100644 index 00000000000..3dcec94fe1f --- /dev/null +++ b/src/app/showcase/components/gmap/gmapdemo.html @@ -0,0 +1,466 @@ +
        +
        + GMap + GMap component provides integration with Google Maps API. This sample demontrates + various uses cases like binding, overlays and events. Click the map to add a new item. +
        +
        + +
        + + + + + + + + +
        +
        +
        + +
        +
        + +
        +
        + +
        +
        +
        + +
        + +
        +
        +
        +
        + +
        + + +

        Import

        +
        +
        +import {GMapModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        A map is initialized with options and dimensions. Refer to the google maps api for the list of available options.

        +
        +
        +<p-gmap [options]="options" [style]="{'width':'100%','height':'320px'}" ></p-gmap>
        +
        +
        + +
        +
        +export class MyModel {
        +
        +    options: any;
        +    
        +    overlays: any[];
        +    
        +    ngOnInit() {
        +        this.options = {
        +            center: {lat: 36.890257, lng: 30.707417},
        +            zoom: 12
        +        };
        +    }
        +
        +}
        +
        +
        + +

        Overlays

        +

        GMap can display any type of overlay such as markers, polygons and circles. Overlay instances are bound using the overlays property array. Overlays are aware + of one-way binding so whenever the array changes, gmap updates itself.

        +
        +
        +<p-gmap [options]="options" [overlays]="overlays" [style]="{'width':'100%','height':'320px'}" ></p-gmap>
        +
        +
        + +
        +
        +export class MyModel {
        +
        +    options: any;
        +    
        +    overlays: any[];
        +    
        +    ngOnInit() {
        +        this.options = {
        +            center: {lat: 36.890257, lng: 30.707417},
        +            zoom: 12
        +        };
        +        
        +        this.overlays = [
        +            new google.maps.Marker({position: {lat: 36.879466, lng: 30.667648}, title:"Konyaalti"}),
        +            new google.maps.Marker({position: {lat: 36.883707, lng: 30.689216}, title:"Ataturk Park"}),
        +            new google.maps.Marker({position: {lat: 36.885233, lng: 30.702323}, title:"Oldtown"}),
        +            new google.maps.Polygon({paths: [
        +                {lat: 36.9177, lng: 30.7854},{lat: 36.8851, lng: 30.7802},{lat: 36.8829, lng: 30.8111},{lat: 36.9177, lng: 30.8159}
        +            ], strokeOpacity: 0.5, strokeWeight: 1,fillColor: '#1976D2', fillOpacity: 0.35
        +            }),
        +            new google.maps.Circle({center: {lat: 36.90707, lng: 30.56533}, fillColor: '#1976D2', fillOpacity: 0.35, strokeWeight: 1, radius: 1500}),
        +            new google.maps.Polyline({path: [{lat: 36.86149, lng: 30.63743},{lat: 36.86341, lng: 30.72463}], geodesic: true, strokeColor: '#FF0000', strokeOpacity: 0.5, strokeWeight: 2})
        +        ];
        +    }
        +}
        +
        +
        + +

        Events

        +

        GMap provides common callbacks to hook into events including map click, overlay click and overlay dragging.

        +
        +
        +<p-gmap [options]="options" [overlays]="overlays" [style]="{'width':'100%','height':'320px'}"
        +            (onMapClick)="handleMapClick($event)" (onOverlayClick)="handleOverlayClick($event)"></p-gmap>
        +
        +
        + +
        +
        +export class MyModel {
        +
        +    options: any;
        +    
        +    overlays: any[];
        +    
        +    ngOnInit() {
        +        this.options = {
        +            center: {lat: 36.890257, lng: 30.707417},
        +            zoom: 12
        +        };
        +        
        +        this.overlays = [
        +            new google.maps.Marker({position: {lat: 36.879466, lng: 30.667648}, title:"Konyaalti"}),
        +            new google.maps.Marker({position: {lat: 36.883707, lng: 30.689216}, title:"Ataturk Park"}),
        +            new google.maps.Marker({position: {lat: 36.885233, lng: 30.702323}, title:"Oldtown"}),
        +            new google.maps.Polygon({paths: [
        +                {lat: 36.9177, lng: 30.7854},{lat: 36.8851, lng: 30.7802},{lat: 36.8829, lng: 30.8111},{lat: 36.9177, lng: 30.8159}
        +            ], strokeOpacity: 0.5, strokeWeight: 1,fillColor: '#1976D2', fillOpacity: 0.35
        +            }),
        +            new google.maps.Circle({center: {lat: 36.90707, lng: 30.56533}, fillColor: '#1976D2', fillOpacity: 0.35, strokeWeight: 1, radius: 1500}),
        +            new google.maps.Polyline({path: [{lat: 36.86149, lng: 30.63743},{lat: 36.86341, lng: 30.72463}], geodesic: true, strokeColor: '#FF0000', strokeOpacity: 0.5, strokeWeight: 2})
        +        ];
        +    }
        +    
        +    handleMapClick(event) {
        +        //event: MouseEvent of Google Maps api
        +    }
        +    
        +    handleOverlayClick(event) {
        +        //event.originalEvent: MouseEvent of Google Maps api
        +        //event.overlay: Clicked overlay     
        +        //event.map: Map instance   
        +    }
        +}
        +
        +
        + +

        Google Maps API

        +

        In case you need to access the map instance directly, use the getMap() method.

        +
        +
        +<p-gmap #gmap [options]="options"></p-gmap>
        +
        +<button type="button" pButton label="Zoom In" icon="fa-search-plus" (click)="zoomIn(gmap.getMap())"></button>
        +
        +
        + +
        +
        +export class MyModel {
        +
        +    options: any;
        +    
        +    overlays: any[];
        +    
        +    ngOnInit() {
        +        this.options = {
        +            center: {lat: 36.890257, lng: 30.707417},
        +            zoom: 12
        +        };
        +    }
        +    
        +    zoomIn(map) {
        +        map.setZoom(map.getZoom()+1);
        +    }
        +}
        +
        +
        +

        Another option is to to get the map object directly after init via (onMapReady) event. + In the example below, google.maps.Map is used for adjusting map bounds to markers.

        +
        +
        +<p-gmap #gmap [options]="options" [overlays]="overlays" [style]="mapStyle"
        +    (onMapReady)="setMap($event)"></p-gmap>
        +
        +
        +

        Then from your component you would write

        +
        +
        +export class MyModel {
        +
        +    options: any;
        +    
        +    overlays: any[];
        +    
        +    map: google.maps.Map;
        +    
        +    setMap(event) {
        +        this.map = event.map;
        +    }
        +    
        +    ngOnInit() {
        +        let bounds = new google.maps.LatLngBounds();
        +        this.overlays = [
        +            new google.maps.Marker({position: {lat: 36.879466, lng: 30.667648}, title:"Konyaalti"}),
        +            new google.maps.Marker({position: {lat: 36.883707, lng: 30.689216}, title:"Ataturk Park"}),
        +            new google.maps.Marker({position: {lat: 36.885233, lng: 30.702323}, title:"Oldtown"}),
        +        ]
        +        // ... extend bounds
        +        this.overlays.forEach(marker => {
        +            bounds.extend(marker.getPosition());
        +        });
        +        
        +        setTimeout(()=> { // map will need some time to load
        +            this.map.fitBounds(bounds); // Map object used directly
        +        }, 1000);
        +    }
        +}
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        optionsanynullGoogle Maps API configuration object.
        overlaysarraynullAn array of overlays to display.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onMapClickevent: Google Maps MouseEventCallback to invoke when map is clicked except markers.
        onOverlayClickoriginalEvent: Google Maps MouseEvent
        + overlay: Clicked overlay
        + map: Map instance
        Callback to invoke when an overlay is clicked.
        onOverlayDragStartoriginalEvent: Google Maps MouseEvent
        + overlay: Clicked overlay
        + map: Map instance
        Callback to invoke when an overlay drag starts.
        onOverlayDragoriginalEvent: Google Maps MouseEvent
        + overlay: Clicked overlay
        + map: Map instance
        Callback to invoke when an overlay is being dragged.
        onOverlayDragEndoriginalEvent: Google Maps MouseEvent
        + overlay: Clicked overlay
        + map: Map instance
        Callback to invoke when an overlay drag ends.
        onMapReadyevent.map: Google Maps InstanceCallback to invoke when the map is ready to be used.
        +
        + +

        Dependencies

        +

        Google Maps API.

        +
        + + +
        +
        +<p-growl [value]="msgs"></p-growl>
        +
        +<p-gmap #gmap [style]="{'width':'100%','height':'320px'}" [options]="options" [overlays]="overlays" 
        +    (onMapClick)="handleMapClick($event)" (onOverlayClick)="handleOverlayClick($event)" (onOverlayDragEnd)="handleDragEnd($event)"></p-gmap>
        +<button type="button" pButton label="Clear" icon="fa-close" (click)="clear()" style="margin-top:10px"></button>
        +<button type="button" pButton label="Zoom In" icon="fa-search-plus" (click)="zoomIn(gmap.getMap())" style="margin-top:10px"></button>
        +<button type="button" pButton label="Zoom Out" icon="fa-search-minus" (click)="zoomOut(gmap.getMap())" style="margin-top:10px"></button>
        +
        +<p-dialog showEffect="fade" [(visible)]="dialogVisible" header="New Location">
        +    <div class="ui-g ui-fluid" *ngIf="selectedPosition">
        +        <div class="ui-g-2"><label for="title">Label</label></div>
        +        <div class="ui-g-10"><input type="text" pInputText id="title" [(ngModel)]="markerTitle"></div>
        +        
        +        <div class="ui-g-2"><label for="lat">Lat</label></div>
        +        <div class="ui-g-10"><input id="lat" type="text" readonly pInputText [ngModel]="selectedPosition.lat()"></div>
        +        
        +        <div class="ui-g-2"><label for="lng">Lng</label></div>
        +        <div class="ui-g-10"><input id="lng" type="text" readonly pInputText [ngModel]="selectedPosition.lng()"></div>
        +        
        +        <div class="ui-g-2"><label for="drg">Drag</label></div>
        +        <div class="ui-g-10"><p-checkbox [(ngModel)]="draggable" binary="true" [style]="{'margin-top':'.25em'}"></p-checkbox></div>
        +    </div>
        +    <p-footer>
        +        <div class="ui-dialog-buttonpane ui-helper-clearfix">
        +            <button type="button" pButton label="Add Marker" icon="fa-plus" (click)="addMarker()"></button>
        +        </div>
        +    </p-footer>
        +</p-dialog>
        +
        +
        + +
        +
        +export class GMapDemo implements OnInit {
        +
        +    options: any;
        +    
        +    overlays: any[];
        +    
        +    dialogVisible: boolean;
        +    
        +    markerTitle: string;
        +    
        +    selectedPosition: any;
        +    
        +    infoWindow: any;
        +    
        +    draggable: boolean;
        +    
        +    msgs: Message[] = [];
        +
        +    ngOnInit() {
        +        this.options = {
        +            center: {lat: 36.890257, lng: 30.707417},
        +            zoom: 12
        +        };
        +        
        +        this.initOverlays();
        +        
        +        this.infoWindow = new google.maps.InfoWindow();
        +    }
        +    
        +    handleMapClick(event) {
        +        this.dialogVisible = true;
        +        this.selectedPosition = event.latLng;
        +    }
        +    
        +    handleOverlayClick(event) {
        +        this.msgs = [];
        +        let isMarker = event.overlay.getTitle != undefined;
        +        
        +        if(isMarker) {
        +            let title = event.overlay.getTitle();
        +            this.infoWindow.setContent('
        ' + title + '
        '); + this.infoWindow.open(event.map, event.overlay); + event.map.setCenter(event.overlay.getPosition()); + + this.msgs.push({severity:'info', summary:'Marker Selected', detail: title}); + } + else { + this.msgs.push({severity:'info', summary:'Shape Selected', detail: ''}); + } + } + + addMarker() { + this.overlays.push(new google.maps.Marker({position:{lat: this.selectedPosition.lat(), lng: this.selectedPosition.lng()}, title:this.markerTitle, draggable: this.draggable})); + this.markerTitle = null; + this.dialogVisible = false; + } + + handleDragEnd(event) { + this.msgs = []; + this.msgs.push({severity:'info', summary:'Marker Dragged', detail: event.overlay.getTitle()}); + } + + initOverlays() { + if(!this.overlays||!this.overlays.length) { + this.overlays = [ + new google.maps.Marker({position: {lat: 36.879466, lng: 30.667648}, title:"Konyaalti"}), + new google.maps.Marker({position: {lat: 36.883707, lng: 30.689216}, title:"Ataturk Park"}), + new google.maps.Marker({position: {lat: 36.885233, lng: 30.702323}, title:"Oldtown"}), + new google.maps.Polygon({paths: [ + {lat: 36.9177, lng: 30.7854},{lat: 36.8851, lng: 30.7802},{lat: 36.8829, lng: 30.8111},{lat: 36.9177, lng: 30.8159} + ], strokeOpacity: 0.5, strokeWeight: 1,fillColor: '#1976D2', fillOpacity: 0.35 + }), + new google.maps.Circle({center: {lat: 36.90707, lng: 30.56533}, fillColor: '#1976D2', fillOpacity: 0.35, strokeWeight: 1, radius: 1500}), + new google.maps.Polyline({path: [{lat: 36.86149, lng: 30.63743},{lat: 36.86341, lng: 30.72463}], geodesic: true, strokeColor: '#FF0000', strokeOpacity: 0.5, strokeWeight: 2}) + ]; + } + } + + zoomIn(map) { + map.setZoom(map.getZoom()+1); + } + + zoomOut(map) { + map.setZoom(map.getZoom()-1); + } + + clear() { + this.overlays = []; + } +} +
        +
        +
        +
        +
        diff --git a/src/app/showcase/components/gmap/gmapdemo.module.ts b/src/app/showcase/components/gmap/gmapdemo.module.ts new file mode 100644 index 00000000000..ddfed1a2446 --- /dev/null +++ b/src/app/showcase/components/gmap/gmapdemo.module.ts @@ -0,0 +1,33 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {GMapDemo} from './gmapdemo'; +import {GMapDemoRoutingModule} from './gmapdemo-routing.module'; +import {GMapModule} from '../../../components/gmap/gmap'; +import {GrowlModule} from '../../../components/growl/growl'; +import {CheckboxModule} from '../../../components/checkbox/checkbox'; +import {DialogModule} from '../../../components/dialog/dialog'; +import {InputTextModule} from '../../../components/inputtext/inputtext'; +import {ButtonModule} from '../../../components/button/button'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + GMapDemoRoutingModule, + GMapModule, + GrowlModule, + InputTextModule, + CheckboxModule, + DialogModule, + ButtonModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + GMapDemo + ] +}) +export class GMapDemoModule {} diff --git a/src/app/showcase/components/gmap/gmapdemo.ts b/src/app/showcase/components/gmap/gmapdemo.ts new file mode 100644 index 00000000000..78065e4aeca --- /dev/null +++ b/src/app/showcase/components/gmap/gmapdemo.ts @@ -0,0 +1,103 @@ +import {Component,OnInit} from '@angular/core'; +import {Message} from '../../../components/common/api'; + +declare var google: any; + +@Component({ + templateUrl: './gmapdemo.html', + styles: [` + .ui-g-2 { + padding-top: .75em; + } + `] +}) +export class GMapDemo implements OnInit { + + options: any; + + overlays: any[]; + + dialogVisible: boolean; + + markerTitle: string; + + selectedPosition: any; + + infoWindow: any; + + draggable: boolean; + + msgs: Message[] = []; + + ngOnInit() { + this.options = { + center: {lat: 36.890257, lng: 30.707417}, + zoom: 12 + }; + + this.initOverlays(); + + this.infoWindow = new google.maps.InfoWindow(); + } + + handleMapClick(event) { + this.dialogVisible = true; + this.selectedPosition = event.latLng; + } + + handleOverlayClick(event) { + this.msgs = []; + let isMarker = event.overlay.getTitle != undefined; + + if(isMarker) { + let title = event.overlay.getTitle(); + this.infoWindow.setContent('
        ' + title + '
        '); + this.infoWindow.open(event.map, event.overlay); + event.map.setCenter(event.overlay.getPosition()); + + this.msgs.push({severity:'info', summary:'Marker Selected', detail: title}); + } + else { + this.msgs.push({severity:'info', summary:'Shape Selected', detail: ''}); + } + } + + addMarker() { + this.overlays.push(new google.maps.Marker({position:{lat: this.selectedPosition.lat(), lng: this.selectedPosition.lng()}, title:this.markerTitle, draggable: this.draggable})); + this.markerTitle = null; + this.dialogVisible = false; + } + + handleDragEnd(event) { + this.msgs = []; + this.msgs.push({severity:'info', summary:'Marker Dragged', detail: event.overlay.getTitle()}); + } + + initOverlays() { + if(!this.overlays||!this.overlays.length) { + this.overlays = [ + new google.maps.Marker({position: {lat: 36.879466, lng: 30.667648}, title:"Konyaalti"}), + new google.maps.Marker({position: {lat: 36.883707, lng: 30.689216}, title:"Ataturk Park"}), + new google.maps.Marker({position: {lat: 36.885233, lng: 30.702323}, title:"Oldtown"}), + new google.maps.Polygon({paths: [ + {lat: 36.9177, lng: 30.7854},{lat: 36.8851, lng: 30.7802},{lat: 36.8829, lng: 30.8111},{lat: 36.9177, lng: 30.8159} + ], strokeOpacity: 0.5, strokeWeight: 1,fillColor: '#1976D2', fillOpacity: 0.35 + }), + new google.maps.Circle({center: {lat: 36.90707, lng: 30.56533}, fillColor: '#1976D2', fillOpacity: 0.35, strokeWeight: 1, radius: 1500}), + new google.maps.Polyline({path: [{lat: 36.86149, lng: 30.63743},{lat: 36.86341, lng: 30.72463}], geodesic: true, strokeColor: '#FF0000', strokeOpacity: 0.5, strokeWeight: 2}) + ]; + } + } + + zoomIn(map) { + map.setZoom(map.getZoom()+1); + } + + zoomOut(map) { + map.setZoom(map.getZoom()-1); + } + + clear() { + this.overlays = []; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/grid/griddemo-routing.module.ts b/src/app/showcase/components/grid/griddemo-routing.module.ts new file mode 100644 index 00000000000..a7223dccb62 --- /dev/null +++ b/src/app/showcase/components/grid/griddemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {GridDemo} from './griddemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: GridDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class GridDemoRoutingModule {} diff --git a/src/app/showcase/components/grid/griddemo.html b/src/app/showcase/components/grid/griddemo.html new file mode 100644 index 00000000000..8c05c602bd0 --- /dev/null +++ b/src/app/showcase/components/grid/griddemo.html @@ -0,0 +1,499 @@ +
        +
        + Grid CSS + Grid CSS is a lightweight responsive and fluid layout utility optimized for mobile devices, tablets and desktops. + Grid CSS is used internally in PrimeNG components and can be used as standalone as well. +
        +
        + +
        +

        Basic

        +
        +
        1
        +
        1
        +
        1
        +
        1
        +
        1
        +
        1
        +
        1
        +
        1
        +
        1
        +
        1
        +
        1
        +
        1
        +
        + +
        +
        2
        +
        2
        +
        2
        +
        2
        +
        2
        +
        2
        +
        + +
        +
        3
        +
        3
        +
        3
        +
        3
        +
        + +
        +
        4
        +
        4
        +
        4
        +
        + +
        +
        6
        +
        6
        +
        + +
        +
        12
        +
        + +
        +
        4
        +
        8
        +
        + +
        +
        3
        +
        9
        +
        + +
        +
        3
        +
        5
        +
        4
        +
        + +
        +
        4
        +
        2
        +
        2
        +
        3
        +
        1
        +
        + +

        Responsive

        +
        +
        ui-g-12 ui-md-6 ui-lg-3
        +
        ui-g-12 ui-md-6 ui-lg-3
        +
        ui-g-12 ui-md-6 ui-lg-3
        +
        ui-g-12 ui-md-6 ui-lg-3
        +
        + +
        +
        ui-g-12 ui-md-6 ui-lg-4
        +
        ui-g-12 ui-md-6 ui-lg-4
        +
        ui-g-12 ui-lg-4
        +
        + +

        Nested

        +
        +
        +
        6
        +
        6
        +
        12
        +
        +
        4
        +
        + +

        Sample Layout

        +
        +
        Menu
        +
        +
        + Bar +
        +
        +
        +
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed imperdiet, orci nec dictum convallis, ligula mauris vestibulum turpis, nec varius tortor quam at diam. Nullam a viverra nibh. In tincidunt tempor lectus quis vulputate. Pellentesque nec dui aliquam, lobortis est in, lobortis ante
        +
        Maecenas vel nisi aliquet, vulputate tortor id, laoreet massa. Maecenas mattis tristique bibendum. Suspendisse vel mi dictum, vestibulum lacus quis, pulvinar quam. Proin vulputate, nibh at finibus varius, leo eros lacinia elit, nec blandit odio tellus a justo. Donec nec ex auctor, tristique nulla nec, rutrum sapien.
        +
        Proin efficitur in leo eget ornare. Nam vestibulum neque sed velit sagittis sodales. Sed scelerisque hendrerit magna a hendrerit. Cras tempor sem at justo pharetra convallis. Curabitur vel sodales purus. Vestibulum interdum facilisis nulla imperdiet suscipit. Quisque lectus felis, condimentum eget hendrerit sit amet.
        +
        + +
        +
        +
        +
        +
        +
        + +
        +
        Phasellus faucibus purus volutpat mauris lacinia sodales. Ut sit amet sapien facilisis, commodo dui non, fringilla tellus. Quisque tempus facilisis nisi sodales finibus. Pellentesque neque orci, ullamcorper vitae ligula quis, dignissim euismod augue.
        +
        Fusce ullamcorper congue massa, eget ullamcorper nunc lobortis egestas. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque ultrices dui eget dolor feugiat dapibus. Aliquam pretium leo et egestas luctus. Nunc facilisis gravida tellus.
        +
        +
        +
        +
        + Footer +
        +
        +
        + +
        + + +

        Getting Started

        +

        Grid CSS is based on a 12 column layout. Columns are prefixed with ui-g-* and they should be a descendant of a container having ui-g class. + A simple 3 column layout can be defined as;

        +
        +
        +<div class="ui-g">
        +    <div class="ui-g-4">Col1</div>
        +    <div class="ui-g-4">Col2</div>
        +    <div class="ui-g-4">Col3</div>
        +</div>
        +
        +
        + +
        +
        Col1
        +
        Col2
        +
        Col3
        +
        + +

        Multi Line

        +

        When the number of columns exceed 12, columns wrap to a new line.

        +
        +
        +<div class="ui-g">
        +    <div class="ui-g-6">Col1</div>
        +    <div class="ui-g-6">Col2</div>
        +    <div class="ui-g-6">Col3</div>
        +    <div class="ui-g-6">Col4</div>
        +</div>
        +
        +
        + +
        +
        Col1
        +
        Col2
        +
        Col3
        +
        Col3
        +
        + +

        Same can also be achieved by having two ui-g containers to semantically define a row.

        +
        +
        +<div class="ui-g">
        +    <div class="ui-g-6">Col1</div>
        +    <div class="ui-g-6">Col2</div>
        +</div>
        +<div class="ui-g">
        +    <div class="ui-g-6">Col3</div>
        +    <div class="ui-g-6">Col4</div>
        +</div>
        +
        +
        + +
        +
        Col1
        +
        Col2
        +
        +
        +
        Col3
        +
        Col4
        +
        + +

        Nested

        +

        Columns can be nested to create more complex layouts.

        +
        +
        +<div class="ui-g">
        +    <div class="ui-g-8 ui-g-nopad">
        +        <div class="ui-g-6">6</div>
        +        <div class="ui-g-6">6</div>
        +        <div class="ui-g-12">12</div>
        +    </div>
        +    <div class="ui-g-4">4</div>
        +</div>
        +
        +
        + +
        +
        +
        6
        +
        6
        +
        12
        +
        +
        4
        +
        + +

        Direct children of ui-g has the same height automatically, in example above if the inside columns is likely to have different height with different content.

        +
        +
        +<div class="ui-g">
        +    <div class="ui-g-8 ui-g-nopad">
        +        <div class="ui-g-6">6 <br /><br /><br /> Content </div>
        +        <div class="ui-g-6">6</div>
        +        <div class="ui-g-12">12</div>
        +    </div>
        +    <div class="ui-g-4">4</div>
        +</div>
        +
        +
        +
        +
        +
        6


        Content
        +
        6
        +
        12
        +
        +
        4
        +
        + +

        Solution is wrapping the internal divs inside a ui-g as well.

        +
        +
        +<div class="ui-g">
        +    <div class="ui-g-8 ui-g-nopad">
        +        <div class="ui-g">
        +            <div class="ui-g-6">6 <br /><br /><br /> Content </div>
        +            <div class="ui-g-6">6</div>
        +            <div class="ui-g-12">12</div>
        +        </div>
        +    </div>
        +    <div class="ui-g-4">4</div>
        +</div>
        +
        +
        +
        +
        +
        +
        6


        Content
        +
        6
        +
        12
        +
        +
        +
        4
        +
        + +

        Responsive

        +

        Responsive layout is achieved by applying additional classes to the columns whereas ui-g-* define the default behavior. Four screen sizes are supported + with different breakpoints.

        + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        PrefixDevicesMedia QueryExample
        ui-sm-*Small devices like phonesmax-width: 40em (640px)ui-sm-6, ui-sm-4
        ui-md-*Medium sized devices such as tabletsmin-width: 40.063em (641px)ui-md-2, ui-sm-8
        ui-lg-*Devices with large screen like desktopsmin-width: 64.063em (1025px)ui-lg-6, ui-sm-12
        ui-xl-*Big screen monitorsmin-width: 90.063em (1441px)ui-xl-2, ui-sm-10
        +
        + +

        Most of the time, ui-md-* styles are used with default ui-g-* classes, to customize small or large screens apply ui-sm, ui-lg and ui-xl can be utilized.

        + +

        In example below, large screens display 4 columns, medium screens display 2 columns in 2 rows and default behavior gets only displayed in a mobile phone + where each column is rendered in a separate row.

        + +
        +
        +<div class="ui-g">
        +    <div class="ui-g-12 ui-md-6 ui-lg-3">ui-g-12 ui-md-6 ui-lg-3</div>
        +    <div class="ui-g-12 ui-md-6 ui-lg-3">ui-g-12 ui-md-6 ui-lg-3</div>
        +    <div class="ui-g-12 ui-md-6 ui-lg-3">ui-g-12 ui-md-6 ui-lg-3</div>
        +    <div class="ui-g-12 ui-md-6 ui-lg-3">ui-g-12 ui-md-6 ui-lg-3</div>
        +</div>
        +
        +
        +
        +
        ui-g-12 ui-md-6 ui-lg-3
        +
        ui-g-12 ui-md-6 ui-lg-3
        +
        ui-g-12 ui-md-6 ui-lg-3
        +
        ui-g-12 ui-md-6 ui-lg-3
        +
        + +

        In this second example below, 3 columns are displayed in large screens and in medium screens first two columns are placed side by side where the last column displayed + below them. In a mobile phone, they all get displayed in a separate row.

        +
        +
        +<div class="ui-g">
        +    <div class="ui-g-12 ui-md-6 ui-lg-4">ui-g-12 ui-md-6 ui-lg-4</div>
        +    <div class="ui-g-12 ui-md-6 ui-lg-4">ui-g-12 ui-md-6 ui-lg-4</div>
        +    <div class="ui-g-12 ui-lg-4">ui-g-12 ui-lg-4</div>
        +</div>
        +
        +
        + +
        +
        ui-g-12 ui-md-6 ui-lg-4
        +
        ui-g-12 ui-md-6 ui-lg-4
        +
        ui-g-12 ui-lg-4
        +
        + +

        Padding

        +

        A column has a default padding by default, to remove it you may apply ui-g-nopad style class.

        + +
        + + +
        +
        +<h3 class="first">Basic</h3>
        +<div class="ui-g">
        +    <div class="ui-g-1">1</div>
        +    <div class="ui-g-1">1</div>
        +    <div class="ui-g-1">1</div>
        +    <div class="ui-g-1">1</div>
        +    <div class="ui-g-1">1</div>
        +    <div class="ui-g-1">1</div>
        +    <div class="ui-g-1">1</div>
        +    <div class="ui-g-1">1</div>
        +    <div class="ui-g-1">1</div>
        +    <div class="ui-g-1">1</div>
        +    <div class="ui-g-1">1</div>
        +    <div class="ui-g-1">1</div>
        +</div>
        +
        +<div class="ui-g">
        +    <div class="ui-g-2">2</div>
        +    <div class="ui-g-2">2</div>
        +    <div class="ui-g-2">2</div>
        +    <div class="ui-g-2">2</div>
        +    <div class="ui-g-2">2</div>
        +    <div class="ui-g-2">2</div>
        +</div>
        +
        +<div class="ui-g">
        +    <div class="ui-g-3">3</div>
        +    <div class="ui-g-3">3</div>
        +    <div class="ui-g-3">3</div>
        +    <div class="ui-g-3">3</div>
        +</div>
        +
        +<div class="ui-g">
        +    <div class="ui-g-4">4</div>
        +    <div class="ui-g-4">4</div>
        +    <div class="ui-g-4">4</div>
        +</div>
        +
        +<div class="ui-g">
        +    <div class="ui-g-6">6</div>
        +    <div class="ui-g-6">6</div>
        +</div>
        +
        +<div class="ui-g">
        +    <div class="ui-g-12">12</div>
        +</div>
        +
        +<div class="ui-g">
        +    <div class="ui-g-4">4</div>
        +    <div class="ui-g-8">8</div>
        +</div>
        +
        +<div class="ui-g">
        +    <div class="ui-g-3">3</div>
        +    <div class="ui-g-9">9</div>
        +</div>
        +
        +<div class="ui-g">
        +    <div class="ui-g-3">3</div>
        +    <div class="ui-g-5">5</div>
        +    <div class="ui-g-4">4</div>
        +</div>
        +
        +<div class="ui-g">
        +    <div class="ui-g-4">4</div>
        +    <div class="ui-g-2">2</div>
        +    <div class="ui-g-2">2</div>
        +    <div class="ui-g-3">3</div>
        +    <div class="ui-g-1">1</div>
        +</div>
        +
        +<h3>Responsive</h3>
        +<div class="ui-g">
        +    <div class="ui-g-12 ui-md-6 ui-lg-3">ui-g-12 ui-md-6 ui-lg-3</div>
        +    <div class="ui-g-12 ui-md-6 ui-lg-3">ui-g-12 ui-md-6 ui-lg-3</div>
        +    <div class="ui-g-12 ui-md-6 ui-lg-3">ui-g-12 ui-md-6 ui-lg-3</div>
        +    <div class="ui-g-12 ui-md-6 ui-lg-3">ui-g-12 ui-md-6 ui-lg-3</div>
        +</div>
        +
        +<div class="ui-g">
        +    <div class="ui-g-12 ui-md-6 ui-lg-4">ui-g-12 ui-md-6 ui-lg-4</div>
        +    <div class="ui-g-12 ui-md-6 ui-lg-4">ui-g-12 ui-md-6 ui-lg-4</div>
        +    <div class="ui-g-12 ui-lg-4">ui-g-12 ui-lg-4</div>
        +</div>
        +
        +<h3>Nested</h3>
        +<div class="ui-g">
        +    <div class="ui-g-8 ui-g-nopad">
        +        <div class="ui-g-6">6</div>
        +        <div class="ui-g-6">6</div>
        +        <div class="ui-g-12">12</div>
        +    </div>
        +    <div class="ui-g-4">4</div>
        +</div>
        +
        +<h3>Sample Layout</h3>
        +<div class="ui-g">
        +    <div class="ui-g-12 ui-md-2">Menu</div>
        +    <div class="ui-g-12 ui-md-10 ui-g-nopad">
        +        <div class="ui-g-12">
        +            Bar
        +        </div>
        +        <div class="ui-g-12 ui-g-nopad">
        +            <div class="ui-g">
        +                <div class="ui-g-12 ui-md-4">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed imperdiet, orci nec dictum convallis, ligula mauris vestibulum turpis, nec varius tortor quam at diam. Nullam a viverra nibh. In tincidunt tempor lectus quis vulputate. Pellentesque nec dui aliquam, lobortis est in, lobortis ante</div>
        +                <div class="ui-g-12 ui-md-4">Maecenas vel nisi aliquet, vulputate tortor id, laoreet massa. Maecenas mattis tristique bibendum. Suspendisse vel mi dictum, vestibulum lacus quis, pulvinar quam. Proin vulputate, nibh at finibus varius, leo eros lacinia elit, nec blandit odio tellus a justo. Donec nec ex auctor, tristique nulla nec, rutrum sapien.</div>
        +                <div class="ui-g-12 ui-md-4">Proin efficitur in leo eget ornare. Nam vestibulum neque sed velit sagittis sodales. Sed scelerisque hendrerit magna a hendrerit. Cras tempor sem at justo pharetra convallis. Curabitur vel sodales purus. Vestibulum interdum facilisis nulla imperdiet suscipit. Quisque lectus felis, condimentum eget hendrerit sit amet.</div>
        +            </div>
        +            
        +            <div class="ui-g">
        +                <div class="ui-g-6 ui-md-3"><img src="showcase/resources/demo/images/galleria/galleria1.jpg" style="width:100%"></div>  
        +                <div class="ui-g-6 ui-md-3"><img src="showcase/resources/demo/images/galleria/galleria1.jpg" style="width:100%"></div> 
        +                <div class="ui-g-6 ui-md-3"><img src="showcase/resources/demo/images/galleria/galleria1.jpg" style="width:100%"></div>    
        +                <div class="ui-g-6 ui-md-3"><img src="showcase/resources/demo/images/galleria/galleria1.jpg" style="width:100%"></div>      
        +            </div>
        +            
        +            <div class="ui-g">
        +                <div class="ui-g-12 ui-md-6">Phasellus faucibus purus volutpat mauris lacinia sodales. Ut sit amet sapien facilisis, commodo dui non, fringilla tellus. Quisque tempus facilisis nisi sodales finibus. Pellentesque neque orci, ullamcorper vitae ligula quis, dignissim euismod augue.</div>
        +                <div class="ui-g-12 ui-md-6">Fusce ullamcorper congue massa, eget ullamcorper nunc lobortis egestas. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque ultrices dui eget dolor feugiat dapibus. Aliquam pretium leo et egestas luctus. Nunc facilisis gravida tellus.</div>
        +            </div>
        +        </div>
        +    </div>
        +    <div class="ui-g-12">
        +        Footer
        +    </div>
        +</div>
        +
        +
        +
        +
        +
        + + + diff --git a/src/app/showcase/components/grid/griddemo.module.ts b/src/app/showcase/components/grid/griddemo.module.ts new file mode 100644 index 00000000000..e404c1686a4 --- /dev/null +++ b/src/app/showcase/components/grid/griddemo.module.ts @@ -0,0 +1,19 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {GridDemo} from './griddemo'; +import {GridDemoRoutingModule} from './griddemo-routing.module'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + GridDemoRoutingModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + GridDemo + ] +}) +export class GridDemoModule {} diff --git a/src/app/showcase/components/grid/griddemo.ts b/src/app/showcase/components/grid/griddemo.ts new file mode 100644 index 00000000000..9d39cb37e28 --- /dev/null +++ b/src/app/showcase/components/grid/griddemo.ts @@ -0,0 +1,15 @@ +import {Component} from '@angular/core'; + +@Component ({ + styles:[` + .ui-g div { + background-color: #ededed; + text-align: center; + border: 1px solid #fafafa; + } + `], + templateUrl: './griddemo.html' +}) +export class GridDemo { + +} \ No newline at end of file diff --git a/src/app/showcase/components/growl/growldemo-routing.module.ts b/src/app/showcase/components/growl/growldemo-routing.module.ts new file mode 100644 index 00000000000..fc3779f03c2 --- /dev/null +++ b/src/app/showcase/components/growl/growldemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {GrowlDemo} from './growldemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: GrowlDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class GrowlDemoRoutingModule {} diff --git a/src/app/showcase/components/growl/growldemo.html b/src/app/showcase/components/growl/growldemo.html new file mode 100644 index 00000000000..dfba84d5436 --- /dev/null +++ b/src/app/showcase/components/growl/growldemo.html @@ -0,0 +1,252 @@ +
        +
        + Growl + Growl is used to display messages in an overlay. +
        +
        + +
        + + +
        + + + + + + +
        +
        + +
        + + +

        Import

        +
        +
        +import {GrowlModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        A single message is specified by Message interface in PrimeNG that defines the id, severity, summary and detail as properties. + Messages to display on growl are defined using the value property which should an array of Message instances.

        +
        +
        +<p-growl [(value)]="msgs"></p-growl>
        +
        +
        + +
        +
        +import {Message} from 'primeng/primeng';
        +
        +export class MyModel {
        +
        +    msgs: Message[] = [];
        +
        +}
        +
        +
        + +

        Severities

        +

        Here are the possible values for the severity of a message.

        +
          +
        • success
        • +
        • info
        • +
        • warn
        • +
        • error
        • +
        + +

        Showing Messages

        +

        Adding messages to the array is enough to display them via growl. Similary removing a message + from the array is also removed by growl.

        +
        +
        +<p-growl [(value)]="msgs"></p-growl>
        +    
        +<button type="button" (click)="show()">Show</button>
        +<button type="button" (click)="clear()">Hide</button>
        +
        +
        + +
        +
        +show() {
        +    this.msgs.push({severity:'info', summary:'Info Message', detail:'PrimeNG rocks'});
        +}
        +
        +hide() {
        +    this.msgs = [];
        +}
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        valuearraynullAn array of messages to display.
        stickybooleanfalseWhen defined, growl messages are not removed automatically after a period defined by life option.
        lifenumber3000Time to display a message in milliseconds before removing it.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + +
        NameParametersDescription
        onClosemessage: Removed messageCallback to invoke when a message is closed.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-growlMain container element.
        ui-growl-containerContainer of a message item.
        ui-growl-itemMessage element.
        ui-growl-icon-closeClose icon of a message.
        ui-growl-imageSeverity icon.
        ui-growl-messageContainer of message texts.
        ui-growl-titleSummary of the message.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<p-growl [(value)]="msgs" sticky="sticky"></p-growl>
        +
        +<div>
        +    <button type="button" pButton (click)="showSuccess()" label="Success" class="ui-button-success"></button>
        +    <button type="button" pButton (click)="showInfo()" label="Info" class="ui-button-info"></button>
        +    <button type="button" pButton (click)="showWarn()" label="Warn" class="ui-button-warning"></button>
        +    <button type="button" pButton (click)="showError()" label="Error" class="ui-button-error"></button>
        +    <button type="button" pButton (click)="showMultiple()" label="Multiple"></button>
        +    <button type="button" pButton (click)="clear()" icon="fa-close" style="float:right" label="Clear"></button>
        +</div>
        +
        +
        + +
        +
        +import {Message} from 'primeng/primeng';
        +
        +export class GrowlDemo {
        +
        +    msgs: Message[] = [];
        +
        +    showInfo() {
        +        this.msgs = [];
        +        this.msgs.push({severity:'info', summary:'Info Message', detail:'PrimeNG rocks'});
        +    }
        +
        +    showWarn() {
        +        this.msgs = [];
        +        this.msgs.push({severity:'warn', summary:'Warn Message', detail:'There are unsaved changes'});
        +    }
        +
        +    showError() {
        +        this.msgs = [];
        +        this.msgs.push({severity:'error', summary:'Error Message', detail:'Validation failed'});
        +    }
        +
        +    showMultiple() {
        +        this.msgs = [];
        +        this.msgs.push({severity:'info', summary:'Message 1', detail:'PrimeNG rocks'});
        +        this.msgs.push({severity:'info', summary:'Message 2', detail:'PrimeUI rocks'});
        +        this.msgs.push({severity:'info', summary:'Message 3', detail:'PrimeFaces rocks'});
        +    }
        +
        +    clear() {
        +        this.msgs = [];
        +    }
        +}
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/growl/growldemo.module.ts b/src/app/showcase/components/growl/growldemo.module.ts new file mode 100644 index 00000000000..587dc367c89 --- /dev/null +++ b/src/app/showcase/components/growl/growldemo.module.ts @@ -0,0 +1,23 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {GrowlDemo} from './growldemo'; +import {GrowlDemoRoutingModule} from './growldemo-routing.module'; +import {GrowlModule} from '../../../components/growl/growl'; +import {ButtonModule} from '../../../components/button/button'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + GrowlDemoRoutingModule, + GrowlModule, + ButtonModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + GrowlDemo + ] +}) +export class GrowlDemoModule {} diff --git a/src/app/showcase/components/growl/growldemo.ts b/src/app/showcase/components/growl/growldemo.ts new file mode 100644 index 00000000000..0ce5072504a --- /dev/null +++ b/src/app/showcase/components/growl/growldemo.ts @@ -0,0 +1,42 @@ +import {Component} from '@angular/core'; +import {SelectItem} from '../../../components/common/api'; +import {Message} from '../../../components/common/api'; + +@Component({ + templateUrl: './growldemo.html' +}) +export class GrowlDemo { + + msgs: Message[] = []; + + showSuccess() { + this.msgs = []; + this.msgs.push({severity:'success', summary:'Success Message', detail:'Order submitted'}); + } + + showInfo() { + this.msgs = []; + this.msgs.push({severity:'info', summary:'Info Message', detail:'PrimeNG rocks'}); + } + + showWarn() { + this.msgs = []; + this.msgs.push({severity:'warn', summary:'Warn Message', detail:'There are unsaved changes'}); + } + + showError() { + this.msgs = []; + this.msgs.push({severity:'error', summary:'Error Message', detail:'Validation failed'}); + } + + showMultiple() { + this.msgs = []; + this.msgs.push({severity:'info', summary:'Message 1', detail:'PrimeNG rocks'}); + this.msgs.push({severity:'info', summary:'Message 2', detail:'PrimeUI rocks'}); + this.msgs.push({severity:'info', summary:'Message 3', detail:'PrimeFaces rocks'}); + } + + clear() { + this.msgs = []; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/home/home.component.css b/src/app/showcase/components/home/home.component.css new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/app/showcase/components/home/home.component.html b/src/app/showcase/components/home/home.component.html new file mode 100644 index 00000000000..5d74d1f91ef --- /dev/null +++ b/src/app/showcase/components/home/home.component.html @@ -0,0 +1,186 @@ +
        +
        +
        + +

        +
        PrimeNG is a collection of rich UI components for Angular. PrimeNG is a sibling of the popular JavaServer Faces Component Suite, PrimeFaces.
        +
        +
        All widgets are open source and free to use under MIT License.
        +
        +
        PrimeNG is developed by PrimeTek Informatics, a company with years of expertise in developing open source UI components. + For project news and updates, follow us on twitter.
        +
        + +
        +
        + Download +
        +
        + GitHub +
        + +
        +
        + +
        +
        + + PRIMEFACES UI + Derived from the mighty PrimeFaces +
        +
        + + WIDGETS + 70+ Components
        Easy to Use
        Accessible
        +
        +
        + + PRODUCTIVITY + Simple
        Lightweight
        Powerful
        +
        +
        + + MOBILE + Responsive
        Cross Browser
        Touch Optimized
        +
        +
        + + COMMUNITY + Active
        Vibrant
        Open Source
        +
        +
        + + THEMES + 15+ Free Themes
        Premium Themes
        Bootstrap Theme
        +
        +
        +
        +
        + +
        +

        Key Users

        +

        Open source products of PrimeTek are used all around the world by 1M+ developers in corporations, government and educational + institutions.

        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        + +
        +

        Premium Application Templates for PrimeNG

        +

        Based on Angular CLI, create awesome applications in no time using the premium templates + of PrimeNG and impress your users.

        + +
        +
        + + Paradise + +
        +
        + + Ultima + +
        +
        + + Barcelona + +
        +
        + + Morpheus + +
        +
        + + Atlantis + +
        +
        + + Poseidon + +
        +
        + + Omega + +
        +
        +
        + +
        +

        News

        +
        +
        + + NGConf + +

        PrimeNG is a silver sponsor of NG-Conf 2017, 5th-7th April, Salt Lake City.

        +
        +
        + + AngularBeers + +

        PrimeTek will be at AngularBeers Community Days Event in Barcelona to present PrimeNG.

        +
        +
        + + Bootstrap + +

        A free bootstrap theme for PrimeNG is now available.

        +
        +
        + +
        + +
        +

        PrimeNG PRO Support

        +

        With PrimeNG PRO, it's easy to support, tune and add features to PrimeNG as if it were an in-house framework.

        +

        PrimeNG PRO is a term based commercial support service. With the exclusive services of Pro account, + you no longer need to post your questions in the community forum and your issues to community issue tracker.

        + +

        Standard PRO Services

        +
          +
        • Access to pro.primefaces.org
        • +
        • Response within 1 business day.
        • +
        • Defect patches.
        • +
        • Private branch management in case you need.
        • +
        • Customized builds.
        • +
        • Unlimited number of cases.
        • +
        • Remote desktop connection.
        • +
        • Conference calls for discussions.
        • +
        • High priority to your issues.
        • +
        + +

        New Features (Optional)

        + +

        New feature and enhancement requests are not available in core services and provided via an hour based model instead. When you have a feature request we provide an estimate, if you confirm we deliver your request within an estimated timeframe and deduct the amount of work from your hours. These requests can be;

        + +
          +
        • New components.
        • +
        • New functionality to existing components.
        • +
        • Changing the way a certain functionality is implemented.
        • +
        • Accessibility improvements.
        • +
        • Proof of Concept implementations of a use case.
        • +
        • Code reviews to offer best practices.
        • +
        + +

        You can purchase additional hours along with the subscription and also anytime during your subscription period. If your subscription term ends with unused hours, they will be added to your new subscription term in case you extend.

        + +
        Get a Quote
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/home/home.component.spec.ts b/src/app/showcase/components/home/home.component.spec.ts new file mode 100644 index 00000000000..86774ae217a --- /dev/null +++ b/src/app/showcase/components/home/home.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { HomeComponent } from './home.component'; + +describe('HomeComponent', () => { + let component: HomeComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ HomeComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(HomeComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should be created', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/showcase/components/home/home.component.ts b/src/app/showcase/components/home/home.component.ts new file mode 100644 index 00000000000..dd5ae2d8c2e --- /dev/null +++ b/src/app/showcase/components/home/home.component.ts @@ -0,0 +1,14 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + templateUrl: './home.component.html', + styleUrls: ['./home.component.css'] +}) +export class HomeComponent implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/src/app/showcase/components/inplace/inplacedemo-routing.module.ts b/src/app/showcase/components/inplace/inplacedemo-routing.module.ts new file mode 100644 index 00000000000..c5558592872 --- /dev/null +++ b/src/app/showcase/components/inplace/inplacedemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {InplaceDemo} from './inplacedemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: InplaceDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class InplaceDemoRoutingModule {} diff --git a/src/app/showcase/components/inplace/inplacedemo.html b/src/app/showcase/components/inplace/inplacedemo.html new file mode 100644 index 00000000000..273e7f8c4b1 --- /dev/null +++ b/src/app/showcase/components/inplace/inplacedemo.html @@ -0,0 +1,214 @@ +
        +
        + Inplace + Inplace provides an easy to do editing and display at the same time where clicking the output displays the actual content. +
        +
        + +
        +

        Basic

        + + + Click to Edit + + + + + + +

        Image

        + + + View Picture + + + Nature + + + +

        Data

        + + + View Data + + + + + + + + + + +
        + +
        + + +

        Import

        +
        +
        +import {InplaceModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Inplace requires two child components having pInplaceDisplay and pInplaceOutput attributes respectively to define.

        + +
        +
        +<p-inplace>
        +    <span pInplaceDisplay>
        +        Click to Edit
        +    </span>
        +    <span pInplaceContent>
        +        <input type="text" value="PrimeNG" pInputText>
        +    </span>
        +</p-inplace>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        activebooleanfalseWhether the content is displayed or not.
        disabledbooleanfalseWhen present, it specifies that the element should be disabled.
        closablebooleanfalseDisplays a button to switch back to display mode.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onActivateevent.originalEvent: Click eventActivates the content.
        onDeactivateevent.originalEvent: Click eventDeactivates the content.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-inplaceContainer element
        ui-inplace-displayDisplay container
        ui-inplace-contentContent container
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<h3 class="first">Basic</h3>
        +<p-inplace closable="closable">
        +    <span pInplaceDisplay>
        +        Click to Edit
        +    </span>
        +    <span pInplaceContent>
        +        <input type="text" value="PrimeNG" pInputText>
        +    </span>
        +</p-inplace>
        +
        +<h3>Image</h3>
        +<p-inplace>
        +    <span pInplaceDisplay>
        +        <span class="fa fa-picture-o"></span><span style="margin-left:8px">View Picture</span>
        +    </span>
        +    <span pInplaceContent>
        +        <img src="showcase/resources/demo/images/galleria/galleria5.jpg" alt="Nature">
        +    </span>
        +</p-inplace>
        +
        +<h3>Data</h3>
        +<p-inplace>
        +    <span pInplaceDisplay>
        +        <span class="fa fa-table"></span><span style="margin-left:8px">View Data</span>
        +    </span>
        +    <span pInplaceContent>
        +        <p-dataTable [value]="cars">
        +            <p-column field="vin" header="Vin"></p-column>
        +            <p-column field="year" header="Year"></p-column>
        +            <p-column field="brand" header="Brand"></p-column>
        +            <p-column field="color" header="Color"></p-column>
        +        </p-dataTable>
        +    </span>
        +</p-inplace>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/inplace/inplacedemo.module.ts b/src/app/showcase/components/inplace/inplacedemo.module.ts new file mode 100644 index 00000000000..b77792a809a --- /dev/null +++ b/src/app/showcase/components/inplace/inplacedemo.module.ts @@ -0,0 +1,25 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {InplaceDemo} from './inplacedemo'; +import {InplaceDemoRoutingModule} from './inplacedemo-routing.module'; +import {InplaceModule} from '../../../components/inplace/inplace'; +import {InputTextModule} from '../../../components/inputtext/inputtext'; +import {DataTableModule} from '../../../components/datatable/datatable'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + InplaceDemoRoutingModule, + InplaceModule, + InputTextModule, + DataTableModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + InplaceDemo + ] +}) +export class InplaceDemoModule {} diff --git a/src/app/showcase/components/inplace/inplacedemo.ts b/src/app/showcase/components/inplace/inplacedemo.ts new file mode 100644 index 00000000000..f7586cd43f3 --- /dev/null +++ b/src/app/showcase/components/inplace/inplacedemo.ts @@ -0,0 +1,17 @@ +import {Component,OnInit} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; + +@Component({ + templateUrl: './inplacedemo.html' +}) +export class InplaceDemo implements OnInit { + + cars: Car[]; + + constructor(private carService: CarService) { } + + ngOnInit() { + this.carService.getCarsSmall().then(cars => this.cars = cars); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/inputmask/inputmaskdemo-routing.module.ts b/src/app/showcase/components/inputmask/inputmaskdemo-routing.module.ts new file mode 100644 index 00000000000..a0e63eb8618 --- /dev/null +++ b/src/app/showcase/components/inputmask/inputmaskdemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {InputMaskDemo} from './inputmaskdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: InputMaskDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class InputMaskDemoRoutingModule {} diff --git a/src/app/showcase/components/inputmask/inputmaskdemo.html b/src/app/showcase/components/inputmask/inputmaskdemo.html new file mode 100644 index 00000000000..db8b0460999 --- /dev/null +++ b/src/app/showcase/components/inputmask/inputmaskdemo.html @@ -0,0 +1,291 @@ +
        +
        + InputMask + InputMask component is used to enter input in a certain format such as numeric, date, currency, email and phone. +
        +
        + +
        + +
        +
        + Basic + +
        + +
        + SSN + +
        + +
        + Date + +
        + +
        + Phone + +
        + +
        + Phone Ext + +
        + +
        + Serial Number + +
        +
        + +
        + +
        + + +

        Import

        +
        +
        +import {InputMaskModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Component is defined using p-inputMask element with a mask and two-way value binding is enabled with standard ngModel directive.

        +
        +
        +<p-inputMask [(ngModel)]="val" mask="99-9999"></p-inputMask>
        +
        +
        + +

        Mask

        +

        Mask format can be a combination of the the following built-in definitions.

        +
          +
        • a - Alpha character (A-Z,a-z)
        • +
        • 9 - Numeric character (0-9)
        • +
        • * - Alpha numberic character (A-Z,a-z,0-9)
        • +
        +
        +
        +<p-inputMask [(ngModel)]="val" mask="a*-999-a999"></p-inputMask>
        +
        +
        + +

        SlotChar

        +

        Underscore is the default placeholder for a mask and this can be customized using slotChart option.

        +
        +
        +<p-inputMask [(ngModel)]="val" mask="99-9999" slotChar=" "></p-inputMask>
        +
        +
        + +

        Optional Values

        +

        If the input does not complete the mask definition, it is cleared by default. Use autoClear property to control this behavior. In addition, + certain part of a mask can be made optional by using ? symbol where anything after the question mark becomes optional.

        + +

        Model Driven Forms

        +

        InputMask can be used in a model driven form as well.

        +
        +
        +<p-inputMask formControlName="username" mask="(999) 999-9999? x99999"></p-inputMask>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        typestringtextHTML5 input type
        maskstringnullMask pattern.
        slotCharstring_Placeholder character in mask, default is underscore.
        autoClearbooleantrueClears the incomplete value on blur.
        unmaskbooleanfalseDefines if ngModel sets the raw unmasked value to bound value or the formatted mask value.
        stylestringnullInline style of the input field.
        styleClassstringnullStyle class of the input field.
        placeholderstringnullAdvisory information to display on input.
        sizenumbernullSize of the input field.
        maxlengthnumbernullMaximum number of character allows in the input field.
        tabindexnumbernullSpecifies tab order of the element.
        disabledbooleanfalseWhen present, it specifies that the element value cannot be altered.
        readonlybooleanfalseWhen present, it specifies that an input field is read-only.
        namestringnullName of the input field.
        inputIdstringnullIdentifier of the focus input to match a label defined for the component.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onBlurevent: Browser eventCallback to invoke when input loses focus.
        onComplete-Callback to invoke on when user completes the mask pattern.
        +
        + +

        Styling

        +

        Styling is same as inputtext component, for theming classes visit theming page.

        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<div class="ui-g ui-fluid">
        +    <div class="ui-g-12 ui-md-6 ui-lg-4">
        +        <span>Basic</span>
        +        <p-inputMask mask="99-999999" [(ngModel)]="val1" placeholder="99-999999"></p-inputMask>
        +    </div>
        +    
        +    <div class="ui-g-12 ui-md-6 ui-lg-4">
        +        <span>SSN</span>
        +        <p-inputMask mask="999-99-9999" [(ngModel)]="val2" placeholder="999-99-9999"></p-inputMask>
        +    </div>
        +    
        +    <div class="ui-g-12 ui-md-6 ui-lg-4">
        +        <span>Date</span>
        +        <p-inputMask mask="99/99/9999" [(ngModel)]="val3" placeholder="99/99/9999" slotChar="mm/dd/yyyy"></p-inputMask>
        +    </div>
        +    
        +    <div class="ui-g-12 ui-md-6 ui-lg-4">
        +        <span>Phone</span>
        +        <p-inputMask mask="(999) 999-9999" [(ngModel)]="val4" placeholder="(999) 999-9999"></p-inputMask>
        +    </div>
        +    
        +    <div class="ui-g-12 ui-md-6 ui-lg-4">
        +        <span>Phone Ext</span>
        +        <p-inputMask mask="(999) 999-9999? x99999" [(ngModel)]="val5" placeholder="(999) 999-9999? x99999"></p-inputMask>
        +    </div>
        +    
        +    <div class="ui-g-12 ui-md-6 ui-lg-4">
        +        <span>Serial Number</span>
        +        <p-inputMask mask="a*-999-a999" [(ngModel)]="val6" placeholder="a*-999-a999"></p-inputMask>
        +    </div>
        +</div>
        +
        +
        + +
        +
        +export class InputMaskDemo {
        +
        +    val1: string;
        +
        +    val2: string;
        +
        +    val3: string;
        +
        +    val4: string;
        +
        +    val5: string;
        +    
        +    val6: string;
        +    
        +}
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/inputmask/inputmaskdemo.module.ts b/src/app/showcase/components/inputmask/inputmaskdemo.module.ts new file mode 100644 index 00000000000..b776000dbac --- /dev/null +++ b/src/app/showcase/components/inputmask/inputmaskdemo.module.ts @@ -0,0 +1,23 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {InputMaskDemo} from './inputmaskdemo'; +import {InputMaskDemoRoutingModule} from './inputmaskdemo-routing.module'; +import {InputMaskModule} from '../../../components/inputmask/inputmask'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + InputMaskDemoRoutingModule, + InputMaskModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + InputMaskDemo + ] +}) +export class InputMaskDemoModule {} diff --git a/src/app/showcase/components/inputmask/inputmaskdemo.ts b/src/app/showcase/components/inputmask/inputmaskdemo.ts new file mode 100644 index 00000000000..ceb398a2d95 --- /dev/null +++ b/src/app/showcase/components/inputmask/inputmaskdemo.ts @@ -0,0 +1,25 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './inputmaskdemo.html', + styles: [` + .ui-g-12 > span { + display: block; + margin-bottom: 4px; + } + `] +}) +export class InputMaskDemo { + + val1: string; + + val2: string; + + val3: string; + + val4: string; + + val5: string; + + val6: string; +} \ No newline at end of file diff --git a/src/app/showcase/components/inputswitch/inputswitch.html b/src/app/showcase/components/inputswitch/inputswitch.html new file mode 100644 index 00000000000..56d3ec7f375 --- /dev/null +++ b/src/app/showcase/components/inputswitch/inputswitch.html @@ -0,0 +1,214 @@ +
        +
        + InputSwitch + InputSwitch is used to select a boolean value. +
        +
        + +
        +

        Basic - {{checked1}}

        + + +

        Labels - {{checked2}}

        + +
        + +
        + + +

        Import

        +
        +
        +import {InputSwitchModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Two-way binding to a boolean property is defined using the standard ngModel directive.

        + +
        +
        +<p-inputSwitch [(ngModel)]="checked"></p-inputSwitch>
        +
        +
        + +
        +
        +export class ModelComponent {
        +
        +    checked: boolean;
        +
        +}
        +
        +
        + +

        As model is two-way binding enabled, setting the bound value as true displays the state as checked by default.

        +
        +
        +export class ModelComponent {
        +
        +   checked: boolean = true;
        +
        +}
        +
        +
        + +

        Model Driven Forms

        +

        InputSwitch can be used in a model driven form as well.

        +
        +
        +<p-inputSwitch formControlName="enabled"></p-inputSwitch>
        +
        +
        + +

        Customization

        +

        Labels can be customized using onLabel and offLabel properties.

        +
        +
        +<p-inputSwitch onLabel="I confirm" offLabel="I reject" [(ngModel)]="val"></p-inputSwitch>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        onLabelstringOnLabel for the on state.
        offLabelstringOffLabel for the off state.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        tabindexnumbernullIndex of the element in tabbing order.
        inputIdstringnullIdentifier of the focus input to match a label defined for the component.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + +
        NameParametersDescription
        onChangeevent.originalEvent: browser event
        + event.checked: checked state as a boolean
        Callback to invoke on state change.
        +
        +
        +
        +<p-inputSwitch (onChange)="handleChange($event)" [(ngModel)]="val">
        +
        +
        +
        +
        +export class ModelComponent {
        +
        +    handleChange(e) {
        +        var isChecked = e.checked;
        +    }
        +}
        +
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-inputswitchContainer element
        ui-inputswitch-onChecked state element.
        ui-inputswitch-offUnchecked state element.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<h3 class="first">Basic - {{checked1}}</h3>
        +<p-inputSwitch [(ngModel)]="checked1"></p-inputSwitch>
        +
        +<h3>Labels - <span> {{checked2}}</h3>
        +<p-inputSwitch onLabel="Yes" offLabel="No" [(ngModel)]="checked2"></p-inputSwitch>
        +
        +
        + +
        +
        +export class InputSwitchDemo {
        +
        +    checked1: boolean = false;
        +
        +    checked2: boolean = true;
        +}
        +
        +
        +
        +
        +
        diff --git a/src/app/showcase/components/inputswitch/inputswitchdemo-routing.module.ts b/src/app/showcase/components/inputswitch/inputswitchdemo-routing.module.ts new file mode 100644 index 00000000000..05d551d3bc7 --- /dev/null +++ b/src/app/showcase/components/inputswitch/inputswitchdemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {InputSwitchDemo} from './inputswitchdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: InputSwitchDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class InputSwitchDemoRoutingModule {} diff --git a/src/app/showcase/components/inputswitch/inputswitchdemo.module.ts b/src/app/showcase/components/inputswitch/inputswitchdemo.module.ts new file mode 100644 index 00000000000..8df2452b9f3 --- /dev/null +++ b/src/app/showcase/components/inputswitch/inputswitchdemo.module.ts @@ -0,0 +1,23 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {InputSwitchDemo} from './inputswitchdemo'; +import {InputSwitchDemoRoutingModule} from './inputswitchdemo-routing.module'; +import {InputSwitchModule} from '../../../components/inputswitch/inputswitch'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + InputSwitchDemoRoutingModule, + InputSwitchModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + InputSwitchDemo + ] +}) +export class InputSwitchDemoModule {} diff --git a/src/app/showcase/components/inputswitch/inputswitchdemo.ts b/src/app/showcase/components/inputswitch/inputswitchdemo.ts new file mode 100644 index 00000000000..4eb85f14297 --- /dev/null +++ b/src/app/showcase/components/inputswitch/inputswitchdemo.ts @@ -0,0 +1,11 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './inputswitch.html' +}) +export class InputSwitchDemo { + + checked1: boolean = false; + + checked2: boolean = true; +} \ No newline at end of file diff --git a/src/app/showcase/components/inputtext/inputtextdemo-routing.module.ts b/src/app/showcase/components/inputtext/inputtextdemo-routing.module.ts new file mode 100644 index 00000000000..b25cb23627f --- /dev/null +++ b/src/app/showcase/components/inputtext/inputtextdemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {InputTextDemo} from './inputtextdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: InputTextDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class InputTextDemoRoutingModule {} diff --git a/src/app/showcase/components/inputtext/inputtextdemo.html b/src/app/showcase/components/inputtext/inputtextdemo.html new file mode 100644 index 00000000000..9d2f332d3b7 --- /dev/null +++ b/src/app/showcase/components/inputtext/inputtextdemo.html @@ -0,0 +1,118 @@ +
        +
        + Inputtext + InputText is an extension to standard input element with theming. +
        +
        + +
        +

        Basic

        + {{text}} + +

        Disabled

        + + + +
        + +
        + + +

        Import

        +
        +
        +import {InputTextModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        InputText is applied to an input field with pInputText directive.

        + +
        +
        +<input type="text" pInputText />
        +
        +
        + +

        Model Binding

        +

        A model can be bound using standard ngModel directive.

        +
        +
        +<input type="text" pInputText [(ngModel)]="property"/>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        disabledbooleanfalseWhen present, it specifies that the element should be disabled.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + +
        NameElement
        ui-inputtextInput element
        +
        + +

        Dependencies

        +

        None.

        +
        + +
        +
        +<h3 class="first">Basic</h3>
        +<input id="in" type="text" size="30" pInputText [(ngModel)]="text">  {{text}}
        +
        +<h3>Disabled</h3>
        +<input id="in" type="text" size="30" pInputText [disabled]="disabled" />
        +
        +<button type="button" (click)="toggleDisabled()" pButton label="Toggle"></button>
        +
        +
        + +
        +
        +export class InputTextDemo {
        +
        +    text: string;
        +
        +    disabled: boolean = true;
        +
        +    toggleDisabled() {
        +        this.disabled = !this.disabled;
        +    }
        +}
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/inputtext/inputtextdemo.module.ts b/src/app/showcase/components/inputtext/inputtextdemo.module.ts new file mode 100644 index 00000000000..c89b880971c --- /dev/null +++ b/src/app/showcase/components/inputtext/inputtextdemo.module.ts @@ -0,0 +1,25 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {InputTextDemo} from './inputtextdemo'; +import {InputTextDemoRoutingModule} from './inputtextdemo-routing.module'; +import {InputTextModule} from '../../../components/inputtext/inputtext'; +import {ButtonModule} from '../../../components/button/button'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + InputTextDemoRoutingModule, + FormsModule, + InputTextModule, + ButtonModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + InputTextDemo + ] +}) +export class InputTextDemoModule {} diff --git a/src/app/showcase/components/inputtext/inputtextdemo.ts b/src/app/showcase/components/inputtext/inputtextdemo.ts new file mode 100644 index 00000000000..c38e69ac898 --- /dev/null +++ b/src/app/showcase/components/inputtext/inputtextdemo.ts @@ -0,0 +1,15 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './inputtextdemo.html' +}) +export class InputTextDemo { + + text: string; + + disabled: boolean = true; + + toggleDisabled() { + this.disabled = !this.disabled; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/inputtextarea/inputtextareademo-routing.module.ts b/src/app/showcase/components/inputtextarea/inputtextareademo-routing.module.ts new file mode 100644 index 00000000000..232d29f1c71 --- /dev/null +++ b/src/app/showcase/components/inputtextarea/inputtextareademo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {InputTextareaDemo} from './inputtextareademo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: InputTextareaDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class InputTextareaDemoRoutingModule {} diff --git a/src/app/showcase/components/inputtextarea/inputtextareademo.html b/src/app/showcase/components/inputtextarea/inputtextareademo.html new file mode 100644 index 00000000000..867aa102a81 --- /dev/null +++ b/src/app/showcase/components/inputtextarea/inputtextareademo.html @@ -0,0 +1,114 @@ +
        +
        + InputTextarea + Inputtextarea add styling and autoResize functionality to standard textare element. +
        +
        + +
        +

        Default

        + + +

        AutoResize

        + +
        + +
        + + +

        Import

        +
        +
        +import {InputTextareaModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        InputTextarea is applied to an input field with pInputTextarea directive.

        + +
        +
        +<textarea pInputTextarea></textarea>
        +
        +
        + +

        Model Binding

        +

        A model can be bound using the standard ngModel directive.

        +
        +
        +<textarea pInputTextarea [(ngModel)]="property"></textarea>
        +
        +
        + +

        AutoResize

        +

        In auto resize mode, textarea grows instead of displaying a scrollbar.

        +
        +
        +<textarea pInputTextarea autoResize="autoResize"></textarea>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        autoResizebooleanfalseWhen present, textarea size changes as being typed.
        disabledbooleanfalseWhen present, it specifies that the element should be disabled.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + +
        NameElement
        ui-inputtextareaTextarea element
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<h3 class="first">Default</h3>
        +<textarea rows="5" cols="30" pInputTextarea></textarea>
        +
        +<h3>AutoResize</h3>
        +<textarea rows="5" cols="30" pInputTextarea autoResize="autoResize"></textarea>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/inputtextarea/inputtextareademo.module.ts b/src/app/showcase/components/inputtextarea/inputtextareademo.module.ts new file mode 100644 index 00000000000..10596ad058f --- /dev/null +++ b/src/app/showcase/components/inputtextarea/inputtextareademo.module.ts @@ -0,0 +1,21 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {InputTextareaDemo} from './inputtextareademo'; +import {InputTextareaDemoRoutingModule} from './inputtextareademo-routing.module'; +import {InputTextareaModule} from '../../../components/inputtextarea/inputtextarea'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + InputTextareaDemoRoutingModule, + InputTextareaModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + InputTextareaDemo + ] +}) +export class InputTextareaDemoModule {} diff --git a/src/app/showcase/components/inputtextarea/inputtextareademo.ts b/src/app/showcase/components/inputtextarea/inputtextareademo.ts new file mode 100644 index 00000000000..49a101d05ae --- /dev/null +++ b/src/app/showcase/components/inputtextarea/inputtextareademo.ts @@ -0,0 +1,8 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './inputtextareademo.html' +}) +export class InputTextareaDemo { + +} \ No newline at end of file diff --git a/src/app/showcase/components/lightbox/lightboxdemo-routing.module.ts b/src/app/showcase/components/lightbox/lightboxdemo-routing.module.ts new file mode 100644 index 00000000000..4331566a7be --- /dev/null +++ b/src/app/showcase/components/lightbox/lightboxdemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {LightboxDemo} from './lightboxdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: LightboxDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class LightboxDemoRoutingModule {} diff --git a/src/app/showcase/components/lightbox/lightboxdemo.html b/src/app/showcase/components/lightbox/lightboxdemo.html new file mode 100644 index 00000000000..48f5a27355b --- /dev/null +++ b/src/app/showcase/components/lightbox/lightboxdemo.html @@ -0,0 +1,211 @@ +
        +
        + Lightbox + LightBox is a modal overlay component to display images, videos, inline html content and iframes. +
        +
        + +
        +

        Basic

        + + +

        Content

        + + + Watch Video + + + +
        + +
        + + +

        Import

        +
        +
        +import {LightboxModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Lightbox has two modes; image and custom content defined using type property. In image mode a collection of + images are required to display where an image object in the collection defines the source of the original image, thumbnail image and the title.

        +
        +
        +<p-lightbox [images]="images"></p-lightbox>
        +
        +
        + +
        +
        +export class LightboxDemo {
        +
        +    images: any[];
        +
        +    constructor() {
        +        this.images = [];
        +        this.images.push({source:'showcase/resources/demo/images/sopranos/sopranos1.jpg', thumbnail: 'showcase/resources/demo/images/sopranos/sopranos1_small.jpg', title:'Sopranos 1'});
        +        this.images.push({source:'showcase/resources/demo/images/sopranos/sopranos2.jpg', thumbnail: 'showcase/resources/demo/images/sopranos/sopranos2_small.jpg', title:'Sopranos 2'});
        +        this.images.push({source:'showcase/resources/demo/images/sopranos/sopranos3.jpg', thumbnail: 'showcase/resources/demo/images/sopranos/sopranos3_small.jpg', title:'Sopranos 3'});
        +        this.images.push({source:'showcase/resources/demo/images/sopranos/sopranos4.jpg', thumbnail: 'showcase/resources/demo/images/sopranos/sopranos4_small.jpg', title:'Sopranos 4'});
        +    }
        +}
        +
        +
        +

        Content mode is enabled by setting type property to "content", providing an anchor to open the lightbox and content to display inside lightbox.

        +
        +
        +<p-lightbox type="content">
        +    <a class="group" href="#">
        +        Watch Video
        +    </a>
        +    <iframe width="560" height="315" src="https://www.youtube.com/embed/9bZkp7q19f0" frameborder="0" allowfullscreen></iframe>
        +</p-lightbox>
        +
        +
        + +

        Effects

        +

        The easing function to use between image transitions is "ease-out" by default and this can be customized using easing property. + See here for possible alternative values. Duration + of the effect can be changed using effectDuration option.

        +
        +
        +<p-lightbox [images]="images" easing="ease-in" effectDuration="1500ms"></p-lightbox>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        imagesarraynullAn array of images to display.
        typestringimageType of the lightbox, valid values are "image" and "content".
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        easingstringease-outEasing to use for transition between images.
        effectDurationstring500msDuration of the transition between the images.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-lightboxContainer element
        ui-lightbox-contentContent element.
        ui-lightbox-nav-rightElement to navigate to next image.
        ui-lightbox-nav-leftElement to navigate to previous image.
        ui-lightbox-captionCaption element.
        ui-lightbox-caption-textText of caption.
        ui-lightbox-closeClose icon.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<h3 class="first">Basic</h3>
        +<p-lightbox [images]="images"></p-lightbox>
        +
        +<h3>Content</h3>
        +<p-lightbox type="content">
        +    <a class="group" href="#">
        +        Watch Video
        +    </a>
        +    <iframe width="560" height="315" src="https://www.youtube.com/embed/9bZkp7q19f0" frameborder="0" allowfullscreen></iframe>
        +</p-lightbox>
        +
        +
        + +
        +
        +export class LightboxDemo {
        +
        +    images: any[];
        +
        +    constructor() {
        +        this.images = [];
        +        this.images.push({source:'showcase/resources/demo/images/sopranos/sopranos1.jpg', thumbnail: 'showcase/resources/demo/images/sopranos/sopranos1_small.jpg', title:'Sopranos 1'});
        +        this.images.push({source:'showcase/resources/demo/images/sopranos/sopranos2.jpg', thumbnail: 'showcase/resources/demo/images/sopranos/sopranos2_small.jpg', title:'Sopranos 2'});
        +        this.images.push({source:'showcase/resources/demo/images/sopranos/sopranos3.jpg', thumbnail: 'showcase/resources/demo/images/sopranos/sopranos3_small.jpg', title:'Sopranos 3'});
        +        this.images.push({source:'showcase/resources/demo/images/sopranos/sopranos4.jpg', thumbnail: 'showcase/resources/demo/images/sopranos/sopranos4_small.jpg', title:'Sopranos 4'});
        +    }
        +}
        +
        +
        +
        +
        +
        diff --git a/src/app/showcase/components/lightbox/lightboxdemo.module.ts b/src/app/showcase/components/lightbox/lightboxdemo.module.ts new file mode 100644 index 00000000000..16db1db882e --- /dev/null +++ b/src/app/showcase/components/lightbox/lightboxdemo.module.ts @@ -0,0 +1,21 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {LightboxDemo} from './lightboxdemo'; +import {LightboxDemoRoutingModule} from './lightboxdemo-routing.module'; +import {LightboxModule} from '../../../components/lightbox/lightbox'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + LightboxDemoRoutingModule, + LightboxModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + LightboxDemo + ] +}) +export class LightboxDemoModule {} diff --git a/src/app/showcase/components/lightbox/lightboxdemo.ts b/src/app/showcase/components/lightbox/lightboxdemo.ts new file mode 100644 index 00000000000..35d4293ed7c --- /dev/null +++ b/src/app/showcase/components/lightbox/lightboxdemo.ts @@ -0,0 +1,17 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './lightboxdemo.html' +}) +export class LightboxDemo { + + images: any[]; + + constructor() { + this.images = []; + this.images.push({source:'showcase/resources/demo/images/sopranos/sopranos1.jpg', thumbnail: 'showcase/resources/demo/images/sopranos/sopranos1_small.jpg', title:'Sopranos 1'}); + this.images.push({source:'showcase/resources/demo/images/sopranos/sopranos2.jpg', thumbnail: 'showcase/resources/demo/images/sopranos/sopranos2_small.jpg', title:'Sopranos 2'}); + this.images.push({source:'showcase/resources/demo/images/sopranos/sopranos3.jpg', thumbnail: 'showcase/resources/demo/images/sopranos/sopranos3_small.jpg', title:'Sopranos 3'}); + this.images.push({source:'showcase/resources/demo/images/sopranos/sopranos4.jpg', thumbnail: 'showcase/resources/demo/images/sopranos/sopranos4_small.jpg', title:'Sopranos 4'}); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/listbox/listboxdemo-routing.module.ts b/src/app/showcase/components/listbox/listboxdemo-routing.module.ts new file mode 100644 index 00000000000..4b3d2f9f7c4 --- /dev/null +++ b/src/app/showcase/components/listbox/listboxdemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {ListboxDemo} from './listboxdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: ListboxDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class ListboxDemoRoutingModule {} diff --git a/src/app/showcase/components/listbox/listboxdemo.html b/src/app/showcase/components/listbox/listboxdemo.html new file mode 100644 index 00000000000..51ceb6fc63f --- /dev/null +++ b/src/app/showcase/components/listbox/listboxdemo.html @@ -0,0 +1,372 @@ +
        +
        + Listbox + Listbox is used to select one or more values from a list of items. +
        +
        + +
        +

        Basic

        + + +

        Selected City: {{selectedCity}}

        + +

        Advanced (Multiple, Checkbox and Filter)

        + +

        Selected Cities: {{c}}

        + +

        Content

        + + +
        + + {{car.value}} +
        +
        +
        +

        Selected Car: {{selectedCar}}

        + + +
        + +
        + + +

        Import

        +
        +
        +import {ListboxModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Two-way value binding is defined using ngModel and listbox requires a collection of options + where each option should follow the SelectItem interface that defines label-value properties.

        +
        +
        +<p-listbox [options]="cities" [(ngModel)]="selectedCity"></p-listbox>
        +
        +
        + +
        +
        +import {SelectItem} from 'primeng/primeng';
        +
        +export class MyModel {
        +
        +    cities: SelectItem[];
        +
        +    selectedCity: string;
        +
        +    constructor() {
        +        this.cities = [];
        +        this.cities.push({label:'New York', value:'New York'});
        +        this.cities.push({label:'Rome', value:'Rome'});
        +        this.cities.push({label:'London', value:'London'});
        +        this.cities.push({label:'Istanbul', value:'Istanbul'});
        +        this.cities.push({label:'Paris', value:'Paris'});
        +    }
        +
        +}
        +
        +
        + +

        Selection

        +

        Listbox allows selection of either single or multiple items whereas checkbox option displays a checkbox to indicate multiple selection. + In single case, model should be a single object reference whereas in multiple case should be an array. Multiple items can either be selected + using metaKey or toggled individually depending on the value of metaKeySelection property value which is true by default. On touch enabled + devices metaKeySelection is turned off automatically.

        +
        +
        +<p-listbox [options]="cities" [(ngModel)]="selectedCities"></p-listbox>
        +
        +
        + +
        +
        +import {SelectItem} from 'primeng/primeng';
        +
        +export class MyModel {
        +
        +    cities: SelectItem[];
        +
        +    selectedCities: string[];
        +
        +    constructor() {
        +        this.cities = [];
        +        this.cities.push({label:'New York', value:'New York'});
        +        this.cities.push({label:'Rome', value:'Rome'});
        +        this.cities.push({label:'London', value:'London'});
        +        this.cities.push({label:'Istanbul', value:'Istanbul'});
        +        this.cities.push({label:'Paris', value:'Paris'});
        +    }
        +
        +}
        +
        +
        + +

        Filter

        +

        Filtering allows searching items in the list using an input field at the header. In order to use filtering, enable filter property.

        +
        +
        +<p-listbox [options]="cities" [(ngModel)]="selectedCities" filter="filter"></p-listbox>
        +
        +
        + +

        Model Driven Forms

        +

        Listbox can be used in a model driven form as well.

        +
        +
        +<p-listbox [options]="cities" formControlName="cities"></p-listbox>
        +
        +
        + +

        Custom Content

        +

        Label of an option is used as the display text of an item by default, for custom content support define a ng-template where + the local ng-template variable refers to an option in the options collection.

        +
        +
        +<p-listbox [options]="cars" [(ngModel)]="selectedCar" style="width:190px">
        +    <ng-template let-car let-i="index" pTemplate="item">
        +        <div class="ui-helper-clearfix">
        +            <img src="showcase/resources/demo/images/car/{{car.label}}.gif" style="display:inline-block;margin:5px 0 0 5px"/>
        +            <span style="font-size:20px;float:right;margin:15px 10px 0 0">{{i}} - {{car.value}}</span>
        +        </div>
        +    </ng-template>
        +</p-listbox>
        +
        +
        + +
        +
        +import {SelectItem} from 'primeng/primeng'
        +
        +export class MyModel {
        +
        +    cars: SelectItem[];
        +
        +    selectedCar: string;
        +
        +    constructor() {
        +        this.cars = [];
        +        this.cars.push({label: 'Audi', value: 'Audi'});
        +        this.cars.push({label: 'BMW', value: 'BMW'});
        +        this.cars.push({label: 'Fiat', value: 'Fiat'});
        +        this.cars.push({label: 'Ford', value: 'Ford'});
        +        this.cars.push({label: 'Honda', value: 'Honda'});
        +        this.cars.push({label: 'Jaguar', value: 'Jaguar'});
        +        this.cars.push({label: 'Mercedes', value: 'Mercedes'});
        +        this.cars.push({label: 'Renault', value: 'Renault'});
        +        this.cars.push({label: 'VW', value: 'VW'});
        +        this.cars.push({label: 'Volvo', value: 'Volvo'});
        +    }
        +}
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        optionsarraynullAn array of selectitems to display as the available options.
        multiplebooleanfalseWhen specified, allows selecting multiple values.
        checkboxbooleanfalseWhen specified, allows selecting items with checkboxes.
        filterbooleanfalseWhen specified, displays a filter input at header.
        disabledbooleanfalseWhen present, it specifies that the element should be disabled.
        stylestringnullInline style of the element.
        styleClassstringnullStyle class of the element.
        metaKeySelectionbooleantrueDefines how multiple items can be selected, when true metaKey needs to be pressed to select or unselect an item and when set to false selection of each item + can be toggled individually. On touch enabled devices, metaKeySelection is turned off automatically.
        dataKeystringnullA property to uniquely identify a value in options.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onChangeevent.originalEvent: browser event
        + event.value: single value or an array of values that are selected +
        Callback to invoke when value of listbox changes.
        onDblClickevent.originalEvent: browser event
        + event.value: Clicked selecte item +
        Callback to invoke when an item is double clicked.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-listboxContainer element.
        ui-listbox-listList container.
        ui-listbox-itemAn item in the list.
        ui-listbox-headerHeader element.
        ui-listbox-filter-containerContainer of filter input in header.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<h3 class="first">Single</h3>
        +<p-listbox [options]="cities" [(ngModel)]="selectedCity"></p-listbox>
        +
        +<p>Selected City: {{selectedCity}}</p>
        +
        +<h3>Advanced (Multiple, Checkbox and Filter)</h3>
        +<p-listbox [options]="cities" [(ngModel)]="selectedCities" multiple="multiple" checkbox="checkbox" filter="filter"></p-listbox>
        +<p>Selected Cities: <span *ngFor="let c of selectedCities" style="margin-right: 10px">{{c}}</span></p>
        +
        +<h3>Content</h3>
        +<p-listbox [options]="cars" [(ngModel)]="selectedCar" [style]="{'width':'190px','max-height':'250px'}">
        +    <ng-template let-car pTemplate="item">
        +        <div class="ui-helper-clearfix">
        +            <img src="showcase/resources/demo/images/car/{{car.label}}.gif" style="display:inline-block;margin:5px 0 0 5px"/>
        +            <span style="font-size:20px;float:right;margin:15px 10px 0 0">{{car.value}}</span>
        +        </div>
        +    </ng-template>
        +</p-listbox>
        +<p>Selected Car: {{selectedCar}}</p>
        +
        +<button type="button" (click)="selectedCar=null" pButton icon="fa-close" label="Clear Selected Car"></button>
        +
        +
        + +
        +
        +export class ListboxDemo {
        +
        +    cities: SelectItem[];
        +
        +    selectedCity: string;
        +
        +    selectedCities: string[];
        +
        +    cars: SelectItem[];
        +
        +    selectedCar: string = 'BMW';
        +
        +    constructor() {
        +        this.cities = [];
        +        this.cities.push({label:'New York', value:'New York'});
        +        this.cities.push({label:'Rome', value:'Rome'});
        +        this.cities.push({label:'London', value:'London'});
        +        this.cities.push({label:'Istanbul', value:'Istanbul'});
        +        this.cities.push({label:'Paris', value:'Paris'});
        +
        +        this.cars = [];
        +        this.cars.push({label: 'Audi', value: 'Audi'});
        +        this.cars.push({label: 'BMW', value: 'BMW'});
        +        this.cars.push({label: 'Fiat', value: 'Fiat'});
        +        this.cars.push({label: 'Ford', value: 'Ford'});
        +        this.cars.push({label: 'Honda', value: 'Honda'});
        +        this.cars.push({label: 'Jaguar', value: 'Jaguar'});
        +        this.cars.push({label: 'Mercedes', value: 'Mercedes'});
        +        this.cars.push({label: 'Renault', value: 'Renault'});
        +        this.cars.push({label: 'VW', value: 'VW'});
        +        this.cars.push({label: 'Volvo', value: 'Volvo'});
        +    }
        +}
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/listbox/listboxdemo.module.ts b/src/app/showcase/components/listbox/listboxdemo.module.ts new file mode 100644 index 00000000000..8bc609f28ff --- /dev/null +++ b/src/app/showcase/components/listbox/listboxdemo.module.ts @@ -0,0 +1,25 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {ListboxDemo} from './listboxdemo'; +import {ListboxDemoRoutingModule} from './listboxdemo-routing.module'; +import {ListboxModule} from '../../../components/listbox/listbox'; +import {ButtonModule} from '../../../components/button/button'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + ListboxDemoRoutingModule, + ListboxModule, + ButtonModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + ListboxDemo + ] +}) +export class ListboxDemoModule {} diff --git a/src/app/showcase/components/listbox/listboxdemo.ts b/src/app/showcase/components/listbox/listboxdemo.ts new file mode 100644 index 00000000000..39e8573e061 --- /dev/null +++ b/src/app/showcase/components/listbox/listboxdemo.ts @@ -0,0 +1,39 @@ +import {Component} from '@angular/core'; +import {SelectItem} from '../../../components/common/api'; + +@Component({ + templateUrl: './listboxdemo.html' +}) +export class ListboxDemo { + + cities: SelectItem[]; + + selectedCity: string; + + selectedCities: string[]; + + cars: SelectItem[]; + + selectedCar: string = 'BMW'; + + constructor() { + this.cities = []; + this.cities.push({label:'New York', value:'New York'}); + this.cities.push({label:'Rome', value:'Rome'}); + this.cities.push({label:'London', value:'London'}); + this.cities.push({label:'Istanbul', value:'Istanbul'}); + this.cities.push({label:'Paris', value:'Paris'}); + + this.cars = []; + this.cars.push({label: 'Audi', value: 'Audi'}); + this.cars.push({label: 'BMW', value: 'BMW'}); + this.cars.push({label: 'Fiat', value: 'Fiat'}); + this.cars.push({label: 'Ford', value: 'Ford'}); + this.cars.push({label: 'Honda', value: 'Honda'}); + this.cars.push({label: 'Jaguar', value: 'Jaguar'}); + this.cars.push({label: 'Mercedes', value: 'Mercedes'}); + this.cars.push({label: 'Renault', value: 'Renault'}); + this.cars.push({label: 'VW', value: 'VW'}); + this.cars.push({label: 'Volvo', value: 'Volvo'}); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/megamenu/megamenudemo-routing.module.ts b/src/app/showcase/components/megamenu/megamenudemo-routing.module.ts new file mode 100644 index 00000000000..78953c623fb --- /dev/null +++ b/src/app/showcase/components/megamenu/megamenudemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {MegaMenuDemo} from './megamenudemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: MegaMenuDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class MegaMenuDemoRoutingModule {} diff --git a/src/app/showcase/components/megamenu/megamenudemo.html b/src/app/showcase/components/megamenu/megamenudemo.html new file mode 100644 index 00000000000..6069360e02c --- /dev/null +++ b/src/app/showcase/components/megamenu/megamenudemo.html @@ -0,0 +1,328 @@ +
        +
        + MegaMenu + MegaMenu displays submenus of root items together. +
        +
        + +
        +

        Default

        + + +

        Vertical

        + +
        + +
        + + +

        Import

        +
        +
        +import {MegaMenuModule} from 'primeng/primeng';
        +
        +
        + +

        MenuModel API

        +

        MegaMenu uses the common menumodel api to define its items, visit MenuModel API for details.

        + +

        Getting Started

        +

        MegaMenu requires nested menuitems as its model where the items of a root menuitem is a two dimensional array to define columns in an overlay submenu.

        +
        +
        +<p-megaMenu [model]="items"></p-megaMenu>
        +
        +
        + +
        +
        +    export class MegaMenuDemo {
        +
        +        private items: MenuItem[];
        +
        +        ngOnInit() {
        +            this.items = [
        +                {
        +                    label: 'TV', icon: 'fa-check',
        +                    items: [
        +                        [
        +                            {
        +                                label: 'TV 1',
        +                                items: [{label: 'TV 1.1'},{label: 'TV 1.2'}]
        +                            },
        +                            {
        +                                label: 'TV 2',
        +                                items: [{label: 'TV 2.1'},{label: 'TV 2.2'}]
        +                            }
        +                        ],
        +                        [
        +                            {
        +                                label: 'TV 3',
        +                                items: [{label: 'TV 3.1'},{label: 'TV 3.2'}]
        +                            },
        +                            {
        +                                label: 'TV 4',
        +                                items: [{label: 'TV 4.1'},{label: 'TV 4.2'}]
        +                            }    
        +                        ]
        +                    ]
        +                },
        +                {
        +                    label: 'Sports', icon: 'fa-soccer-ball-o',
        +                    items: [
        +                        [
        +                            {
        +                                label: 'Sports 1',
        +                                items: [{label: 'Sports 1.1'},{label: 'Sports 1.2'}]
        +                            },
        +                            {
        +                                label: 'Sports 2',
        +                                items: [{label: 'Sports 2.1'},{label: 'Sports 2.2'}]
        +                            },
        +
        +                        ],
        +                        [
        +                            {
        +                                label: 'Sports 3',
        +                                items: [{label: 'Sports 3.1'},{label: 'Sports 3.2'}]
        +                            },
        +                            {
        +                                label: 'Sports 4',
        +                                items: [{label: 'Sports 4.1'},{label: 'Sports 4.2'}]
        +                            }
        +                        ],
        +                        [
        +                            {
        +                                label: 'Sports 5',
        +                                items: [{label: 'Sports 5.1'},{label: 'Sports 5.2'}]
        +                            },
        +                            {
        +                                label: 'Sports 6',
        +                                items: [{label: 'Sports 6.1'},{label: 'Sports 6.2'}]
        +                            }
        +                        ]
        +                    ]
        +                }
        +            ];
        +        }
        +    }
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        modelarraynullAn array of menuitems.
        orientationstringhorizontalDefines the orientation, valid values are horizontal and vertical.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-megamenuContainer element.
        ui-menu-listList element.
        ui-menuitemMenuitem element.
        ui-menuitem-textLabel of a menuitem.
        ui-menuitem-iconIcon of a menuitem.
        ui-submenu-iconArrow icon of a submenu.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<p-megaMenu [model]="items"></p-megaMenu>
        +
        +
        + +
        +
        +export class MegaMenuDemo {
        +
        +    private items: MenuItem[];
        +
        +    ngOnInit() {
        +        this.items = [
        +            {
        +                label: 'TV', icon: 'fa-check',
        +                items: [
        +                    [
        +                        {
        +                            label: 'TV 1',
        +                            items: [{label: 'TV 1.1'},{label: 'TV 1.2'}]
        +                        },
        +                        {
        +                            label: 'TV 2',
        +                            items: [{label: 'TV 2.1'},{label: 'TV 2.2'}]
        +                        }
        +                    ],
        +                    [
        +                        {
        +                            label: 'TV 3',
        +                            items: [{label: 'TV 3.1'},{label: 'TV 3.2'}]
        +                        },
        +                        {
        +                            label: 'TV 4',
        +                            items: [{label: 'TV 4.1'},{label: 'TV 4.2'}]
        +                        }    
        +                    ]
        +                ]
        +            },
        +            {
        +                label: 'Sports', icon: 'fa-soccer-ball-o',
        +                items: [
        +                    [
        +                        {
        +                            label: 'Sports 1',
        +                            items: [{label: 'Sports 1.1'},{label: 'Sports 1.2'}]
        +                        },
        +                        {
        +                            label: 'Sports 2',
        +                            items: [{label: 'Sports 2.1'},{label: 'Sports 2.2'}]
        +                        },
        +
        +                    ],
        +                    [
        +                        {
        +                            label: 'Sports 3',
        +                            items: [{label: 'Sports 3.1'},{label: 'Sports 3.2'}]
        +                        },
        +                        {
        +                            label: 'Sports 4',
        +                            items: [{label: 'Sports 4.1'},{label: 'Sports 4.2'}]
        +                        }
        +                    ],
        +                    [
        +                        {
        +                            label: 'Sports 5',
        +                            items: [{label: 'Sports 5.1'},{label: 'Sports 5.2'}]
        +                        },
        +                        {
        +                            label: 'Sports 6',
        +                            items: [{label: 'Sports 6.1'},{label: 'Sports 6.2'}]
        +                        }
        +                    ]
        +                ]
        +            },
        +            {
        +                label: 'Entertainment', icon: 'fa-child',
        +                items: [
        +                    [
        +                        {
        +                            label: 'Entertainment 1',
        +                            items: [{label: 'Entertainment 1.1'},{label: 'Entertainment 1.2'}]
        +                        },
        +                        {
        +                            label: 'Entertainment 2',
        +                            items: [{label: 'Entertainment 2.1'},{label: 'Entertainment 2.2'}]
        +                        }
        +                    ],
        +                    [
        +                        {
        +                            label: 'Entertainment 3',
        +                            items: [{label: 'Entertainment 3.1'},{label: 'Entertainment 3.2'}]
        +                        },
        +                        {
        +                            label: 'Entertainment 4',
        +                            items: [{label: 'Entertainment 4.1'},{label: 'Entertainment 4.2'}]
        +                        }    
        +                    ]
        +                ]
        +            },
        +            {
        +                label: 'Technology', icon: 'fa-gears',
        +                items: [
        +                    [
        +                        {
        +                            label: 'Technology 1',
        +                            items: [{label: 'Technology 1.1'},{label: 'Technology 1.2'}]
        +                        },
        +                        {
        +                            label: 'Technology 2',
        +                            items: [{label: 'Technology 2.1'},{label: 'Technology 2.2'}]
        +                        },
        +                        {
        +                            label: 'Technology 3',
        +                            items: [{label: 'Technology 3.1'},{label: 'Technology 3.2'}]
        +                        }
        +                    ],
        +                    [
        +                        {
        +                            label: 'Technology 4',
        +                            items: [{label: 'Technology 4.1'},{label: 'Technology 4.2'}]
        +                        }  
        +                    ]
        +                ]
        +            }
        +        ];
        +    }
        +}
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/megamenu/megamenudemo.module.ts b/src/app/showcase/components/megamenu/megamenudemo.module.ts new file mode 100644 index 00000000000..6a1c2283366 --- /dev/null +++ b/src/app/showcase/components/megamenu/megamenudemo.module.ts @@ -0,0 +1,22 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {MegaMenuDemo} from './megamenudemo'; +import {MegaMenuDemoRoutingModule} from './megamenudemo-routing.module'; +import {MegaMenuModule} from '../../../components/megamenu/megamenu'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + + +@NgModule({ + imports: [ + CommonModule, + MegaMenuDemoRoutingModule, + MegaMenuModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + MegaMenuDemo + ] +}) +export class MegaMenuDemoModule {} diff --git a/src/app/showcase/components/megamenu/megamenudemo.ts b/src/app/showcase/components/megamenu/megamenudemo.ts new file mode 100644 index 00000000000..abc69dbe6bf --- /dev/null +++ b/src/app/showcase/components/megamenu/megamenudemo.ts @@ -0,0 +1,126 @@ +import {Component} from '@angular/core'; +import {MenuItem} from '../../../components/common/api'; + +@Component({ + templateUrl: './megamenudemo.html' +}) +export class MegaMenuDemo { + + private items: MenuItem[]; + + ngOnInit() { + this.items = [ + { + label: 'TV', icon: 'fa-check', + items: [ + [ + { + label: 'TV 1', + items: [{label: 'TV 1.1'},{label: 'TV 1.2'}] + }, + { + label: 'TV 2', + items: [{label: 'TV 2.1'},{label: 'TV 2.2'}] + } + ], + [ + { + label: 'TV 3', + items: [{label: 'TV 3.1'},{label: 'TV 3.2'}] + }, + { + label: 'TV 4', + items: [{label: 'TV 4.1'},{label: 'TV 4.2'}] + } + ] + ] + }, + { + label: 'Sports', icon: 'fa-soccer-ball-o', + items: [ + [ + { + label: 'Sports 1', + items: [{label: 'Sports 1.1'},{label: 'Sports 1.2'}] + }, + { + label: 'Sports 2', + items: [{label: 'Sports 2.1'},{label: 'Sports 2.2'}] + }, + + ], + [ + { + label: 'Sports 3', + items: [{label: 'Sports 3.1'},{label: 'Sports 3.2'}] + }, + { + label: 'Sports 4', + items: [{label: 'Sports 4.1'},{label: 'Sports 4.2'}] + } + ], + [ + { + label: 'Sports 5', + items: [{label: 'Sports 5.1'},{label: 'Sports 5.2'}] + }, + { + label: 'Sports 6', + items: [{label: 'Sports 6.1'},{label: 'Sports 6.2'}] + } + ] + ] + }, + { + label: 'Entertainment', icon: 'fa-child', + items: [ + [ + { + label: 'Entertainment 1', + items: [{label: 'Entertainment 1.1'},{label: 'Entertainment 1.2'}] + }, + { + label: 'Entertainment 2', + items: [{label: 'Entertainment 2.1'},{label: 'Entertainment 2.2'}] + } + ], + [ + { + label: 'Entertainment 3', + items: [{label: 'Entertainment 3.1'},{label: 'Entertainment 3.2'}] + }, + { + label: 'Entertainment 4', + items: [{label: 'Entertainment 4.1'},{label: 'Entertainment 4.2'}] + } + ] + ] + }, + { + label: 'Technology', icon: 'fa-gears', + items: [ + [ + { + label: 'Technology 1', + items: [{label: 'Technology 1.1'},{label: 'Technology 1.2'}] + }, + { + label: 'Technology 2', + items: [{label: 'Technology 2.1'},{label: 'Technology 2.2'}] + }, + { + label: 'Technology 3', + items: [{label: 'Technology 3.1'},{label: 'Technology 3.2'}] + } + ], + [ + { + label: 'Technology 4', + items: [{label: 'Technology 4.1'},{label: 'Technology 4.2'}] + } + ] + ] + } + ]; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/menu/menudemo-routing.module.ts b/src/app/showcase/components/menu/menudemo-routing.module.ts new file mode 100644 index 00000000000..51db9af5fc1 --- /dev/null +++ b/src/app/showcase/components/menu/menudemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {MenuDemo} from './menudemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: MenuDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class MenuDemoRoutingModule {} diff --git a/src/app/showcase/components/menu/menudemo.html b/src/app/showcase/components/menu/menudemo.html new file mode 100644 index 00000000000..8201a6f55a6 --- /dev/null +++ b/src/app/showcase/components/menu/menudemo.html @@ -0,0 +1,247 @@ +
        +
        + Menu + Menu is a navigation/command component that supports dynamic and static positioning. +
        +
        + +
        +

        Basic

        + + +

        Popup

        + + +
        + +
        + + +

        Import

        +
        +
        +import {MenuModule,MenuItem} from 'primeng/primeng';
        +
        +
        + +

        MenuModel API

        +

        Menu uses the common menumodel api to define its items, visit MenuModel API for details.

        + +

        Getting Started

        +

        Menu requires a collection of menuitems as its model.

        +
        +
        +<p-menu [model]="items"></p-menu>
        +
        +
        + +
        +
        +export class MenuDemo {
        +    
        +    private items: MenuItem[];
        +
        +    ngOnInit() {
        +        this.items = [
        +                    {label: 'New', icon: 'fa-plus'},
        +                    {label: 'Open', icon: 'fa-download'},
        +                    {label: 'Undo', icon: 'fa-refresh'}
        +                ];
        +    }
        +}
        +
        +
        + +

        SubMenus

        +

        Menu supports 1 level of nesting via subitems of an item.

        +
        +
        +export class MenuDemo {
        +    
        +    private items: MenuItem[];
        +
        +    ngOnInit() {
        +        this.items = [{
        +            label: 'File',
        +            items: [
        +                {label: 'New', icon: 'fa-plus'},
        +                {label: 'Open', icon: 'fa-download'}
        +            ]
        +        },
        +        {
        +            label: 'Edit',
        +            items: [
        +                {label: 'Undo', icon: 'fa-refresh'},
        +                {label: 'Redo', icon: 'fa-repeat'}
        +            ]
        +        }];
        +    }
        +}
        +
        +
        + +

        Popup Mode

        +

        Menu is inline by default, popup mode is also supported by enabling popup property and calling toggle method by passing the event + from the anchor element.

        +
        +
        +<p-menu #menu popup="popup" [model]="items"></p-menu>
        +<button type="button" pButton icon="fa fa-list" label="Show" (click)="menu.toggle($event)"></button>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        modelarraynullAn array of menuitems.
        popupbooleanfalseDefines if menu would displayed as a popup.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        appendToanynullTarget element to attach the overlay, valid values are "body" or a local ng-template variable of another element.
        +
        + +

        Methods

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        toggleevent: browser eventToggles the visibility of the popup menu.
        showevent: browser eventDisplays the popup menu.
        hide-Hides the popup menu.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-menuContainer element.
        ui-menu-listList element.
        ui-menuitemMenuitem element.
        ui-menuitem-textLabel of a menuitem.
        ui-menuitem-iconIcon of a menuitem.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<h3 class="first">Basic</h3>
        +<p-menu [model]="items"></p-menu>
        +
        +<h3>Popup</h3>
        +<p-menu #menu popup="popup" [model]="items"></p-menu>
        +<button type="button" pButton icon="fa fa-list" label="Show" (click)="menu.toggle($event)"></button>
        +
        +
        + +
        +
        +export class MenuDemo {
        +    
        +    private items: MenuItem[];
        +
        +    ngOnInit() {
        +        this.items = [{
        +            label: 'File',
        +            items: [
        +                {label: 'New', icon: 'fa-plus'},
        +                {label: 'Open', icon: 'fa-download'}
        +            ]
        +        },
        +        {
        +            label: 'Edit',
        +            items: [
        +                {label: 'Undo', icon: 'fa-refresh'},
        +                {label: 'Redo', icon: 'fa-repeat'}
        +            ]
        +        }];
        +    }
        +}
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/menu/menudemo.module.ts b/src/app/showcase/components/menu/menudemo.module.ts new file mode 100644 index 00000000000..5f72fa97028 --- /dev/null +++ b/src/app/showcase/components/menu/menudemo.module.ts @@ -0,0 +1,23 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {MenuDemo} from './menudemo'; +import {MenuDemoRoutingModule} from './menudemo-routing.module'; +import {MenuModule} from '../../../components/menu/menu' +import {ButtonModule} from '../../../components/button/button';; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + MenuDemoRoutingModule, + MenuModule, + ButtonModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + MenuDemo + ] +}) +export class MenuDemoModule {} diff --git a/src/app/showcase/components/menu/menudemo.ts b/src/app/showcase/components/menu/menudemo.ts new file mode 100644 index 00000000000..23ebef64a29 --- /dev/null +++ b/src/app/showcase/components/menu/menudemo.ts @@ -0,0 +1,27 @@ +import {Component} from '@angular/core'; +import {MenuItem} from '../../../components/common/api'; + +@Component({ + templateUrl: './menudemo.html' +}) +export class MenuDemo { + + private items: MenuItem[]; + + ngOnInit() { + this.items = [{ + label: 'File', + items: [ + {label: 'New', icon: 'fa-plus'}, + {label: 'Open', icon: 'fa-download'} + ] + }, + { + label: 'Edit', + items: [ + {label: 'Undo', icon: 'fa-refresh'}, + {label: 'Redo', icon: 'fa-repeat'} + ] + }]; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/menubar/menubardemo-routing.module.ts b/src/app/showcase/components/menubar/menubardemo-routing.module.ts new file mode 100644 index 00000000000..a2425cdce4f --- /dev/null +++ b/src/app/showcase/components/menubar/menubardemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {MenubarDemo} from './menubardemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: MenubarDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class MenubarDemoRoutingModule {} diff --git a/src/app/showcase/components/menubar/menubardemo.html b/src/app/showcase/components/menubar/menubardemo.html new file mode 100644 index 00000000000..96a37754870 --- /dev/null +++ b/src/app/showcase/components/menubar/menubardemo.html @@ -0,0 +1,240 @@ +
        +
        + Menubar + Menubar is an horizontal menu components with support for nested submenus. +
        +
        + +
        + +
        + +
        + + +

        Import

        +
        +
        +import {MenubarModule,MenuItem} from 'primeng/primeng';
        +
        +
        + +

        MenuModel API

        +

        Menubar uses the common menumodel api to define its items, visit MenuModel API for details.

        + +

        Getting Started

        +

        Menubar requires nested menuitems as its model.

        +
        +
        +<p-menubar [model]="items"></p-menubar>
        +
        +
        + +
        +
        +export class MenubarDemo {
        +
        +    private items: MenuItem[];
        +
        +    ngOnInit() {
        +        this.items = [
        +            {
        +                label: 'File',
        +                items: [{
        +                        label: 'New', 
        +                        icon: 'fa-plus',
        +                        items: [
        +                            {label: 'Project'},
        +                            {label: 'Other'},
        +                        ]
        +                    },
        +                    {label: 'Open'},
        +                    {label: 'Quit'}
        +                ]
        +            },
        +            {
        +                label: 'Edit',
        +                icon: 'fa-edit',
        +                items: [
        +                    {label: 'Undo', icon: 'fa-mail-forward'},
        +                    {label: 'Redo', icon: 'fa-mail-reply'}
        +                ]
        +            }
        +        ];
        +    }
        +}
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        modelarraynullAn array of menuitems.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-menubarContainer element.
        ui-menu-listList element.
        ui-menuitemMenuitem element.
        ui-menuitem-textLabel of a menuitem.
        ui-menuitem-iconIcon of a menuitem.
        ui-submenu-iconArrow icon of a submenu.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<p-menubar [model]="items"></p-menubar>
        +
        +
        + +
        +
        +export class MenubarDemo {
        +
        +    private items: MenuItem[];
        +
        +    ngOnInit() {
        +        this.items = [
        +            {
        +                label: 'File',
        +                icon: 'fa-file-o',
        +                items: [{
        +                        label: 'New', 
        +                        icon: 'fa-plus',
        +                        items: [
        +                            {label: 'Project'},
        +                            {label: 'Other'},
        +                        ]
        +                    },
        +                    {label: 'Open'},
        +                    {label: 'Quit'}
        +                ]
        +            },
        +            {
        +                label: 'Edit',
        +                icon: 'fa-edit',
        +                items: [
        +                    {label: 'Undo', icon: 'fa-mail-forward'},
        +                    {label: 'Redo', icon: 'fa-mail-reply'}
        +                ]
        +            },
        +            {
        +                label: 'Help',
        +                icon: 'fa-question',
        +                items: [
        +                    {
        +                        label: 'Contents'
        +                    },
        +                    {
        +                        label: 'Search', 
        +                        icon: 'fa-search', 
        +                        items: [
        +                            {
        +                                label: 'Text', 
        +                                items: [
        +                                    {
        +                                        label: 'Workspace'
        +                                    }
        +                                ]
        +                            },
        +                            {
        +                                label: 'File'
        +                            }
        +                    ]}
        +                ]
        +            },
        +            {
        +                label: 'Actions',
        +                icon: 'fa-gear',
        +                items: [
        +                    {
        +                        label: 'Edit',
        +                        icon: 'fa-refresh',
        +                        items: [
        +                            {label: 'Save', icon: 'fa-save'},
        +                            {label: 'Update', icon: 'fa-save'},
        +                        ]
        +                    },
        +                    {
        +                        label: 'Other',
        +                        icon: 'fa-phone',
        +                        items: [
        +                            {label: 'Delete', icon: 'fa-minus'}
        +                        ]
        +                    }
        +                ]
        +            },
        +            {
        +                label: 'Quit', icon: 'fa-minus'
        +            }
        +        ];
        +    }
        +}
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/menubar/menubardemo.module.ts b/src/app/showcase/components/menubar/menubardemo.module.ts new file mode 100644 index 00000000000..e689754901f --- /dev/null +++ b/src/app/showcase/components/menubar/menubardemo.module.ts @@ -0,0 +1,21 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {MenubarDemo} from './menubardemo'; +import {MenubarDemoRoutingModule} from './menubardemo-routing.module'; +import {MenubarModule} from '../../../components/menubar/menubar'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + MenubarDemoRoutingModule, + MenubarModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + MenubarDemo + ] +}) +export class MenubarDemoModule {} diff --git a/src/app/showcase/components/menubar/menubardemo.ts b/src/app/showcase/components/menubar/menubardemo.ts new file mode 100644 index 00000000000..78912aa7f49 --- /dev/null +++ b/src/app/showcase/components/menubar/menubardemo.ts @@ -0,0 +1,87 @@ +import {Component} from '@angular/core'; +import {MenuItem} from '../../../components/common/api'; + +@Component({ + templateUrl: './menubardemo.html' +}) +export class MenubarDemo { + + private items: MenuItem[]; + + ngOnInit() { + this.items = [ + { + label: 'File', + icon: 'fa-file-o', + items: [{ + label: 'New', + icon: 'fa-plus', + items: [ + {label: 'Project'}, + {label: 'Other'}, + ] + }, + {label: 'Open'}, + {label: 'Quit'} + ] + }, + { + label: 'Edit', + icon: 'fa-edit', + items: [ + {label: 'Undo', icon: 'fa-mail-forward'}, + {label: 'Redo', icon: 'fa-mail-reply'} + ] + }, + { + label: 'Help', + icon: 'fa-question', + items: [ + { + label: 'Contents' + }, + { + label: 'Search', + icon: 'fa-search', + items: [ + { + label: 'Text', + items: [ + { + label: 'Workspace' + } + ] + }, + { + label: 'File' + } + ]} + ] + }, + { + label: 'Actions', + icon: 'fa-gear', + items: [ + { + label: 'Edit', + icon: 'fa-refresh', + items: [ + {label: 'Save', icon: 'fa-save'}, + {label: 'Update', icon: 'fa-save'}, + ] + }, + { + label: 'Other', + icon: 'fa-phone', + items: [ + {label: 'Delete', icon: 'fa-minus'} + ] + } + ] + }, + { + label: 'Quit', icon: 'fa-minus' + } + ]; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/menumodel/menumodeldemo-routing.module.ts b/src/app/showcase/components/menumodel/menumodeldemo-routing.module.ts new file mode 100644 index 00000000000..7aadfcf8aa9 --- /dev/null +++ b/src/app/showcase/components/menumodel/menumodeldemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {MenuModelDemo} from './menumodeldemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: MenuModelDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class MenuModelDemoRoutingModule {} diff --git a/src/app/showcase/components/menumodel/menumodeldemo.html b/src/app/showcase/components/menumodel/menumodeldemo.html new file mode 100644 index 00000000000..224b06ed028 --- /dev/null +++ b/src/app/showcase/components/menumodel/menumodeldemo.html @@ -0,0 +1,178 @@ +
        +
        + MenuModel API + PrimeNG menus components share a common api to specify the menuitems and submenus. +
        +
        + +
        +

        MenuItem

        +

        Core of the api is MenuItem class that defines various options such as the label, icon and children of an item in a menu. Example below + is a sample configuration with Menu component.

        + +
        +
        +<p-menu [model]="items"></p-menu>
        +
        +
        + +
        +
        +import {MenuModule,MenuItem} from 'primeng/primeng';
        +
        +
        + +
        +
        +export class MenuDemo {
        +    
        +    private items: MenuItem[];
        +
        +    ngOnInit() {
        +        this.items = [{
        +            label: 'File',
        +            items: [
        +                {label: 'New', icon: 'fa-plus'},
        +                {label: 'Open', icon: 'fa-download'}
        +            ]
        +        },
        +        {
        +            label: 'Edit',
        +            items: [
        +                {label: 'Undo', icon: 'fa-refresh'},
        +                {label: 'Redo', icon: 'fa-repeat'}
        +            ]
        +        }];
        +    }
        +}
        +
        +
        + +

        MenuItem provides the following properties.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        labelstringnullText of the item.
        iconstringnullIcon of the item.
        commandfunctionnullCallback to execute when item is clicked.
        urlstringnullExternal link to navigate when item is clicked.
        routerLinkarraynullRouterLink definition for internal navigation.
        routerLinkActiveOptionsobjectnullConfiguration for active router link.
        itemsarraynullAn array of children menuitems.
        expandedbooleanfalseVisibility of submenu.
        disabledbooleanfalseWhen set as true, disables the menuitem.
        visiblebooleantrueWhether the dom element of menuitem is created or not.
        targetstringnullSpecifies where to open the linked document.
        +
        + +

        Command

        +

        The function to invoke when an item is clicked is defined using the command property.

        +
        +
        +export class MenuDemo {
        +    
        +    private items: MenuItem[];
        +
        +    ngOnInit() {
        +        this.items = [{
        +            label: 'File',
        +            items: [
        +                {label: 'New', icon: 'fa-plus': command: (event) => {
        +                    //event.originalEvent: Browser event
        +                    //event.item: menuitem metadata
        +                }}
        +            ]
        +        }
        +    }
        +}
        +
        +
        + +

        Navigation

        +

        Navigation is specified using url property for external links and with routerLink for internal ones. If a menuitem has an active route, ui-state-active style class is added as an indicator. Active route link can be + configured with routerLinkActiveOptions property of MenuItem API.

        +
        +
        +export class MenuDemo {
        +    
        +    private items: MenuItem[];
        +
        +    ngOnInit() {
        +        this.items = [{
        +            label: 'File',
        +            items: [
        +                {label: 'New', icon: 'fa-plus', url: 'http://www.primefaces.org/primeng'},
        +                {label: 'Open', icon: 'fa-download', routerLink: ['/pagename']}
        +            ]
        +        }
        +    }
        +}
        +
        +
        + +
        \ No newline at end of file diff --git a/src/app/showcase/components/menumodel/menumodeldemo.module.ts b/src/app/showcase/components/menumodel/menumodeldemo.module.ts new file mode 100644 index 00000000000..ad3fc3d57eb --- /dev/null +++ b/src/app/showcase/components/menumodel/menumodeldemo.module.ts @@ -0,0 +1,17 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {MenuModelDemo} from './menumodeldemo'; +import {MenuModelDemoRoutingModule} from './menumodeldemo-routing.module'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + MenuModelDemoRoutingModule, + CodeHighlighterModule + ], + declarations: [ + MenuModelDemo + ] +}) +export class MenuModelDemoModule {} diff --git a/src/app/showcase/components/menumodel/menumodeldemo.ts b/src/app/showcase/components/menumodel/menumodeldemo.ts new file mode 100644 index 00000000000..c94d0d14c01 --- /dev/null +++ b/src/app/showcase/components/menumodel/menumodeldemo.ts @@ -0,0 +1,8 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './menumodeldemo.html' +}) +export class MenuModelDemo { + +} \ No newline at end of file diff --git a/src/app/showcase/components/messages/messagesdemo-routing.module.ts b/src/app/showcase/components/messages/messagesdemo-routing.module.ts new file mode 100644 index 00000000000..f04e9d65108 --- /dev/null +++ b/src/app/showcase/components/messages/messagesdemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {MessagesDemo} from './messagesdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: MessagesDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class MessagesDemoRoutingModule {} diff --git a/src/app/showcase/components/messages/messagesdemo.html b/src/app/showcase/components/messages/messagesdemo.html new file mode 100644 index 00000000000..48a49f5fb47 --- /dev/null +++ b/src/app/showcase/components/messages/messagesdemo.html @@ -0,0 +1,223 @@ +
        +
        + Messages + Messages is used to display messages inline. +
        +
        + +
        + + +
        + + + + + + +
        +
        + +
        + + +

        Import

        +
        +
        +import {MessagesModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        A single message is specified by Message interface in PrimeNG that defines the id, severity, summary and detail as the properties. + Messages to display are defined using the value property which should an array of Message instances.

        +
        +
        +<p-messages [(value)]="msgs"></p-messages>
        +
        +
        + +

        Severities

        +

        Here are the possible values for the severity of a message.

        +
          +
        • success
        • +
        • info
        • +
        • warn
        • +
        • error
        • +
        + +

        Showing Messages

        +

        Adding messages to the array is enough to display them. Similarly removing a message from the array is also removed from the UI.

        +
        +
        +<p-messages [(value)]="msgs"></p-messages>
        +
        +<button type="button" (click)="show()">Show</button>
        +<button type="button" (click)="clear()">Hide</button>
        +
        +
        + +
        +
        +show() {
        +    this.msgs.push({severity:'info', summary:'Info Message', detail:'PrimeNG rocks'});
        +}
        +
        +hide() {
        +    this.msgs = [];
        +}
        +
        +
        + +

        Closable

        +

        Messages are closable by default resulting in a close icon being displayed on top right corner.

        +
        +
        +<p-messages [(value)]="msgs"></p-messages>
        +
        +
        + +

        In order to disable closable messages, set closable to false. Note that in this case two-way binding is not necessary as the component + does not need to update its value.

        +
        +
        +<p-messages [value]="msgs" [closable]="false"></p-messages>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        valuearraynullAn array of messages to display.
        closablebooleantrueDefines if message box can be closed by the click icon.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-messagesContainer element.
        ui-messages-infoContainer element when displaying info messages.
        ui-messages-warnContainer element when displaying warning messages.
        ui-messages-errorContainer element when displaying error messages.
        ui-messages-successContainer element when displaying success messages.
        ui-messages-closeClose icon.
        ui-messages-iconSeverity icon.
        ui-messages-summarySummary of a message.
        ui-messages-detailDetail of a message.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<p-messages [(value)]="msgs"></p-messages>
        +
        +<div>
        +    <button type="button" pButton (click)="showSuccess()" label="Success" class="ui-button-success"></button>
        +    <button type="button" pButton (click)="showInfo()" label="Info" class="ui-button-info"></button>
        +    <button type="button" pButton (click)="showWarn()" label="Warn" class="ui-button-warning"></button>
        +    <button type="button" pButton (click)="showError()" label="Error" class="ui-button-danger"></button>
        +    <button type="button" pButton (click)="showMultiple()" label="Multiple"></button>
        +    <button type="button" pButton (click)="clear()" icon="fa-close" style="float:right" label="Clear"></button>
        +</div>
        +
        +
        + +
        +
        +export class MessagesDemo {
        +
        +    msgs: Message[] = [];
        +
        +    showInfo() {
        +        this.msgs = [];
        +        this.msgs.push({severity:'info', summary:'Info Message', detail:'PrimeNG rocks'});
        +    }
        +
        +    showWarn() {
        +        this.msgs = [];
        +        this.msgs.push({severity:'warn', summary:'Warn Message', detail:'There are unsaved changes'});
        +    }
        +
        +    showError() {
        +        this.msgs = [];
        +        this.msgs.push({severity:'error', summary:'Error Message', detail:'Validation failed'});
        +    }
        +
        +    showMultiple() {
        +        this.msgs = [];
        +        this.msgs.push({severity:'info', summary:'Message 1', detail:'PrimeNG rocks'});
        +        this.msgs.push({severity:'info', summary:'Message 2', detail:'PrimeUI rocks'});
        +        this.msgs.push({severity:'info', summary:'Message 3', detail:'PrimeFaces rocks'});
        +    }
        +
        +    clear() {
        +        this.msgs = [];
        +    }
        +}
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/messages/messagesdemo.module.ts b/src/app/showcase/components/messages/messagesdemo.module.ts new file mode 100644 index 00000000000..a790636ed69 --- /dev/null +++ b/src/app/showcase/components/messages/messagesdemo.module.ts @@ -0,0 +1,23 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {MessagesDemo} from './messagesdemo'; +import {MessagesDemoRoutingModule} from './messagesdemo-routing.module'; +import {MessagesModule} from '../../../components/messages/messages'; +import {ButtonModule} from '../../../components/button/button'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + MessagesDemoRoutingModule, + MessagesModule, + ButtonModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + MessagesDemo + ] +}) +export class MessagesDemoModule {} diff --git a/src/app/showcase/components/messages/messagesdemo.ts b/src/app/showcase/components/messages/messagesdemo.ts new file mode 100644 index 00000000000..615f9227251 --- /dev/null +++ b/src/app/showcase/components/messages/messagesdemo.ts @@ -0,0 +1,41 @@ +import {Component} from '@angular/core'; +import {Message} from '../../../components/common/api'; + +@Component({ + templateUrl: './messagesdemo.html' +}) +export class MessagesDemo { + + msgs: Message[] = []; + + showSuccess() { + this.msgs = []; + this.msgs.push({severity:'success', summary:'Success Message', detail:'Order submitted'}); + } + + showInfo() { + this.msgs = []; + this.msgs.push({severity:'info', summary:'Info Message', detail:'PrimeNG rocks'}); + } + + showWarn() { + this.msgs = []; + this.msgs.push({severity:'warn', summary:'Warn Message', detail:'There are unsaved changes'}); + } + + showError() { + this.msgs = []; + this.msgs.push({severity:'error', summary:'Error Message', detail:'Validation failed'}); + } + + showMultiple() { + this.msgs = []; + this.msgs.push({severity:'info', summary:'Message 1', detail:'PrimeNG rocks'}); + this.msgs.push({severity:'info', summary:'Message 2', detail:'PrimeUI rocks'}); + this.msgs.push({severity:'info', summary:'Message 3', detail:'PrimeFaces rocks'}); + } + + clear() { + this.msgs = []; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/multiselect/multiselectdemo-routing.module.ts b/src/app/showcase/components/multiselect/multiselectdemo-routing.module.ts new file mode 100644 index 00000000000..fa0628c09ea --- /dev/null +++ b/src/app/showcase/components/multiselect/multiselectdemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {MultiSelectDemo} from './multiselectdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: MultiSelectDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class MultiSelectDemoRoutingModule {} diff --git a/src/app/showcase/components/multiselect/multiselectdemo.html b/src/app/showcase/components/multiselect/multiselectdemo.html new file mode 100644 index 00000000000..134ef22b8d1 --- /dev/null +++ b/src/app/showcase/components/multiselect/multiselectdemo.html @@ -0,0 +1,282 @@ +
        +
        + MultiSelect + MultiSelect is used to select multiple items from a collection. +
        +
        + +
        + +

        Selected Cars: {{selectedCars}}

        +
        + +
        + + +

        Import

        +
        +
        +import {MultiSelectModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Two-way value binding is defined using ngModel and multiselect requires a collection of options + where each option should follow the SelectItem interface that defines label-value properties.

        +
        +
        +<p-multiSelect [options]="cities" [(ngModel)]="selectedCities"></p-multiSelect>
        +
        +
        + +
        +
        +import {SelectItem} from 'primeng/primeng';
        +
        +export class MyModel {
        +
        +    cities: SelectItem[];
        +
        +    selectedCities: string[];
        +
        +    constructor() {
        +        this.cities = [];
        +        this.cities.push({label:'New York', value:'New York'});
        +        this.cities.push({label:'Rome', value:'Rome'});
        +        this.cities.push({label:'London', value:'London'});
        +        this.cities.push({label:'Istanbul', value:'Istanbul'});
        +        this.cities.push({label:'Paris', value:'Paris'});
        +    }
        +
        +}
        +
        +
        + +

        Model Driven Forms

        +

        MultiSelect can be used in a model driven form as well.

        +
        +
        +<p-multiSelect [options]="cities" formControlName="selectedCities"></p-multiSelect>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        optionsarraynullAn array of selectitems to display as the available options.
        disabledbooleanfalseWhen present, it specifies that the element should be disabled.
        filterbooleantrueWhen specified, displays an input field to filter the items on keyup.
        defaultLabelstringChooseLabel to display when there are no selections.
        appendToanynullTarget element to attach the overlay, valid values are "body" or a local ng-template variable of another element.
        stylestringnullInline style of the element.
        styleClassstringnullStyle class of the element.
        scrollHeightstring200pxHeight of the viewport in pixels, a scrollbar is defined if height of list exceeds this value.
        overlayVisiblebooleanfalseSpecifies the visibility of the options panel.
        tabindexnumbernullIndex of the element in tabbing order.
        dataKeystringnullA property to uniquely identify a value in options.
        inputIdstringnullIdentifier of the focus input to match a label defined for the component.
        displaySelectedLabelbooleantrueWhether to show labels of selected item labels or use default label.
        maxSelectedLabelsnumber3Decides how many selected item labels to show at most.
        selectedItemsLabelstring{0} items selectedLabel to display after exceeding max selected labels.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onChangeevent.originalEvent: browser event
        + event.value: Current selected values +
        Callback to invoke when value changes.
        onBlurevent.originalEvent: browser eventCallback to invoke when multiselect loses focus.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-multiselectContainer element.
        ui-multiselect-label-containerContainer of the label to display selected items.
        ui-multiselect-label-containerLabel to display selected items.
        ui-multiselect-triggerDropdown button.
        ui-multiselect-filter-containerContainer of filter input.
        ui-multiselect-panelOverlay panel for items.
        ui-multiselect-itemsList container of items.
        ui-multiselect-itemAn item in the list.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<p-multiSelect [options]="cars" [(ngModel)]="selectedCars"></p-multiSelect>
        +
        +<p>Selected Cars: {{selectedCars}}</p>
        +
        +
        + +
        +
        +export class MultiSelectDemo {
        +
        +    cars: SelectItem[];
        +
        +    selectedCars: string[] = [];
        +
        +    constructor() {
        +        this.cars = [];
        +        this.cars.push({label: 'Audi', value: 'Audi'});
        +        this.cars.push({label: 'BMW', value: 'BMW'});
        +        this.cars.push({label: 'Fiat', value: 'Fiat'});
        +        this.cars.push({label: 'Ford', value: 'Ford'});
        +        this.cars.push({label: 'Honda', value: 'Honda'});
        +        this.cars.push({label: 'Jaguar', value: 'Jaguar'});
        +        this.cars.push({label: 'Mercedes', value: 'Mercedes'});
        +        this.cars.push({label: 'Renault', value: 'Renault'});
        +        this.cars.push({label: 'VW', value: 'VW'});
        +        this.cars.push({label: 'Volvo', value: 'Volvo'});
        +    }
        +}
        +
        +
        +
        +
        +
        diff --git a/src/app/showcase/components/multiselect/multiselectdemo.module.ts b/src/app/showcase/components/multiselect/multiselectdemo.module.ts new file mode 100644 index 00000000000..17fd7b314df --- /dev/null +++ b/src/app/showcase/components/multiselect/multiselectdemo.module.ts @@ -0,0 +1,24 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {MultiSelectDemo} from './multiselectdemo'; +import {MultiSelectDemoRoutingModule} from './multiselectdemo-routing.module'; +import {MultiSelectModule} from '../../../components/multiselect/multiselect'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + MultiSelectDemoRoutingModule, + MultiSelectModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + MultiSelectDemo + ] +}) +export class MultiSelectDemoModule {} diff --git a/src/app/showcase/components/multiselect/multiselectdemo.ts b/src/app/showcase/components/multiselect/multiselectdemo.ts new file mode 100644 index 00000000000..6d15f966b96 --- /dev/null +++ b/src/app/showcase/components/multiselect/multiselectdemo.ts @@ -0,0 +1,26 @@ +import {Component} from '@angular/core'; +import {SelectItem} from '../../../components/common/api'; + +@Component({ + templateUrl: './multiselectdemo.html' +}) +export class MultiSelectDemo { + + cars: SelectItem[]; + + selectedCars: string[] = []; + + constructor() { + this.cars = []; + this.cars.push({label: 'Audi', value: 'Audi'}); + this.cars.push({label: 'BMW', value: 'BMW'}); + this.cars.push({label: 'Fiat', value: 'Fiat'}); + this.cars.push({label: 'Ford', value: 'Ford'}); + this.cars.push({label: 'Honda', value: 'Honda'}); + this.cars.push({label: 'Jaguar', value: 'Jaguar'}); + this.cars.push({label: 'Mercedes', value: 'Mercedes'}); + this.cars.push({label: 'Renault', value: 'Renault'}); + this.cars.push({label: 'VW', value: 'VW'}); + this.cars.push({label: 'Volvo', value: 'Volvo'}); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/orderlist/orderlistdemo-routing.module.ts b/src/app/showcase/components/orderlist/orderlistdemo-routing.module.ts new file mode 100644 index 00000000000..9f4ef320b1b --- /dev/null +++ b/src/app/showcase/components/orderlist/orderlistdemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {OrderListDemo} from './orderlistdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: OrderListDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class OrderListDemoRoutingModule {} diff --git a/src/app/showcase/components/orderlist/orderlistdemo.html b/src/app/showcase/components/orderlist/orderlistdemo.html new file mode 100644 index 00000000000..4f91f46b55e --- /dev/null +++ b/src/app/showcase/components/orderlist/orderlistdemo.html @@ -0,0 +1,236 @@ +
        +
        + OrderList + OrderList is used to sort a collection. When the position of an item changes, the backend array is updated as well. +
        +
        + +
        + +
        +
        + + +
        + +
        {{car.brand}} - {{car.year}} - {{car.color}}
        +
        +
        +
        +
        +
        +
          +
        • {{car.brand}} - {{car.year}} - {{car.color}}
        • +
        +
        +
        + +
        + +
        + + +

        Import

        +
        +
        +import {OrderListModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        OrderList requires an array as its value and a ng-template for its content where each item in the array + can be accessed inside the ng-template using a local ng-template variable.

        +
        +
        +<p-orderList [value]="cars">
        +    <ng-template let-car pTemplate="item">
        +        <div class="ui-helper-clearfix">
        +            <img src="showcase/resources/demo/images/car/{{car.brand}}.gif" style="display:inline-block;margin:2px 0 2px 2px" />
        +            <div style="font-size:14px;float:right;margin:15px 5px 0 0">{{car.brand}} - {{car.year}} - {{car.color}}</div>
        +        </div>
        +    </ng-template>
        +</p-orderList>
        +
        +
        + +
        +
        +export class MyComponent {
        +
        +    cars: Car[];
        +    
        +    ngOnInit() {
        +        this.cars = //initialize cars
        +    }
        +}
        +
        +
        + +

        Multiple Selection

        +

        Multiple items can either be selected using metaKey or toggled individually depending on the value of metaKeySelection property value which is true by default. On touch enabled + devices metaKeySelection is turned off automatically.

        + +

        Responsive

        +

        In responsive mode, orderlist adjusts its controls based on screen size. To activate this mode, set responsive as true.

        +
        +
        +<p-orderList [value]="cars" [responsive]="true">
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        valuearraynullAn array of objects to reorder.
        headerstringnullText for the caption
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        listStylestringnullInline style of the list element.
        responsivebooleanfalseWhen enabled orderlist adjusts its controls based on screen size.
        metaKeySelectionbooleantrueWhen true metaKey needs to be pressed to select or unselect an item and when set to false selection of each item + can be toggled individually. On touch enabled devices, metaKeySelection is turned off automatically.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onReorderevent: browser eventCallback to invoke when list is reordered.
        onSelectionChangeoriginalEvent: browser event
        + value: Current selection
        Callback to invoke when selection changes.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-orderlistContainer element.
        ui-orderlist-listList container.
        ui-orderlist-itemAn item in the list.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<div class="ui-g">
        +    <div class="ui-g-12 ui-md-6">
        +        <p-orderList [value]="cars" [listStyle]="{'height':'250px'}" [responsive]="true" header="Responsive Cars">
        +            <ng-template let-car pTemplate="item">
        +                <div class="ui-helper-clearfix">
        +                    <img src="showcase/resources/demo/images/car/{{car.brand}}.gif" style="display:inline-block;margin:2px 0 2px 2px" />
        +                    <div style="font-size:14px;float:right;margin:15px 5px 0 0">{{car.brand}} - {{car.year}} - {{car.color}}</div>
        +                </div>
        +            </ng-template>
        +        </p-orderList>
        +    </div>
        +    <div class="ui-g-12 ui-md-6">
        +        <ul>
        +            <li *ngFor="let car of cars" style="list-style-type:none">{{car.brand}} - {{car.year}} - {{car.color}}</li>
        +        </ul>
        +    </div>
        +</div>
        +
        +
        + +
        +
        +export class OrderListDemo {
        +
        +    cars: Car[];
        +    
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsSmall().then(cars => this.cars = cars);
        +    }
        +}
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/orderlist/orderlistdemo.module.ts b/src/app/showcase/components/orderlist/orderlistdemo.module.ts new file mode 100644 index 00000000000..0497b1ee87c --- /dev/null +++ b/src/app/showcase/components/orderlist/orderlistdemo.module.ts @@ -0,0 +1,21 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {OrderListDemo} from './orderlistdemo'; +import {OrderListDemoRoutingModule} from './orderlistdemo-routing.module'; +import {OrderListModule} from '../../../components/orderlist/orderlist'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + OrderListDemoRoutingModule, + OrderListModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + OrderListDemo + ] +}) +export class OrderListDemoModule {} diff --git a/src/app/showcase/components/orderlist/orderlistdemo.ts b/src/app/showcase/components/orderlist/orderlistdemo.ts new file mode 100644 index 00000000000..317372da645 --- /dev/null +++ b/src/app/showcase/components/orderlist/orderlistdemo.ts @@ -0,0 +1,17 @@ +import {Component} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; + +@Component({ + templateUrl: './orderlistdemo.html' +}) +export class OrderListDemo { + + cars: Car[]; + + constructor(private carService: CarService) { } + + ngOnInit() { + this.carService.getCarsSmall().then(cars => this.cars = cars); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/overlaypanel/overlaypaneldemo-routing.module.ts b/src/app/showcase/components/overlaypanel/overlaypaneldemo-routing.module.ts new file mode 100644 index 00000000000..c60f8dc4878 --- /dev/null +++ b/src/app/showcase/components/overlaypanel/overlaypaneldemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {OverlayPanelDemo} from './overlaypaneldemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: OverlayPanelDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class OverlayPanelDemoRoutingModule {} diff --git a/src/app/showcase/components/overlaypanel/overlaypaneldemo.html b/src/app/showcase/components/overlaypanel/overlaypaneldemo.html new file mode 100644 index 00000000000..1d381ca88dd --- /dev/null +++ b/src/app/showcase/components/overlaypanel/overlaypaneldemo.html @@ -0,0 +1,311 @@ +
        +
        + OverlayPanel + OverlayPanel is a container component that can overlay other components on page. +
        +
        + +
        +

        Basic

        +

        Click the button to show the panel.

        + + + + Galleria 1 + + +

        Customized

        +

        This OverlayPanel gets displayed on hover of the icon, is not dismissable and displays a close icon.

        + + + + + + + + + + + +

        DataTable Integration

        + + + + + + + + + + + + + + + +
        + +
        + + +

        Import

        +
        +
        +import {OverlayPanelModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        OverlayPanel is defined using p-overlayPanel element and is displayed using the show or toggle method of a local ng-template variable.

        +
        +
        +<p-overlayPanel #op>
        +    Content
        +</p-overlayPanel>
        +
        +<button type="text" pButton label="Basic" (click)="op.toggle($event)"></button>
        +
        +
        +

        Show and Hide

        +

        show method takes two parameters, first one is the event and it is mandatory. By default the target component to align the overlay is the event target, + if you'd like to align it to another element, provide it as the second parameter. Similarly calling hide() hides the overlay panel and the toggle method + toggles the visibility of the panel. In example below, clicking the button displays the overlayPanel aligned to the actualTarget div, not the button itself.

        +
        +
        +<p-overlayPanel #op>
        +    Content
        +</p-overlayPanel>
        +
        +<button type="text" pButton label="Custom Target" (click)="op.show($event, actualTarget)"></button>
        +<div #actualTarget></div>
        +
        +
        + + +

        Dismissable and CloseIcon

        +

        Clicking outside the overlay hides the panel, setting dismissable to false disables this behavior. Additionally enablign showCloseIcon property + displays a close icon at the top right corner to close the panel

        +
        +
        +<p-overlayPanel #op [dismissable]="true" [showCloseIcon]="true">
        +    Content
        +</p-overlayPanel>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        dismissablebooleantrueEnables to hide the overlay when outside is clicked.
        showCloseIconbooleanfalseWhen enabled, displays a close icon at top right corner.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        appendToanynullTarget element to attach the panel, valid values are "body" or a local ng-template variable of another element.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onBeforeShow-Callback to invoke before overlay is shown.
        onAfterShow-Callback to invoke after overlay is shown.
        onBeforeHide-Callback to invoke before overlay is hidden.
        onAfterHide-Callback to invoke after overlay is hidden.
        +
        + +

        Methods

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        toggleevent: browser event
        + target?: target element to align the panel, defaults to event.target +
        Toggles the visibility of the panel.
        showevent: browser event
        + target?: target element to align the panel to +
        Displays the panel.
        hide-Hides the panel.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-overlaypanelContainer element.
        ui-overlaypanel-contentContent of the panel.
        ui-overlaypanel-closeClose icon.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<h3 class="first">Basic</h3>
        +<p>Click the button to show the panel.</p>
        +<button type="text" pButton label="Basic" (click)="op1.toggle($event)"></button>
        +
        +<p-overlayPanel #op1>
        +    <img src="showcase/resources/demo/images/galleria/galleria1.jpg" alt="Galleria 1" />
        +</p-overlayPanel>
        +
        +<h3>Customized</h3>
        +<p>This OverlayPanel gets displayed on hover of the icon, is not dismissable and displays a close icon.</p>
        +<i class="fa fa-search" (mouseenter)="op2.show($event)" style="font-size:24px"></i>
        +
        +<p-overlayPanel #op2 [showCloseIcon]="true" [dismissable]="false">
        +    <p-dataTable [value]="cars1" [style]="{'width':'500px'}">
        +        <p-column field="vin" header="Vin" [sortable]="true"></p-column>
        +        <p-column field="year" header="Year" [sortable]="true"></p-column>
        +        <p-column field="brand" header="Brand" [sortable]="true"></p-column>
        +        <p-column field="color" header="Color" [sortable]="true"></p-column>
        +    </p-dataTable>
        +</p-overlayPanel>
        +
        +<h3>DataTable Integration</h3>
        +<p-dataTable [value]="cars2">
        +    <p-column [style]="{'width':'10%','text-align':'center'}" header="Logo">
        +        <ng-template let-car="rowData" pTemplate="body">
        +            <button type="button" pButton (click)="selectCar($event,car,op3);" icon="fa-search"></button>
        +        </ng-template>
        +    </p-column>
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +<p-overlayPanel #op3>
        +    <img src="showcase/resources/demo/images/car/{{selectedCar.brand}}-big.gif" *ngIf="selectedCar"/>
        +</p-overlayPanel>
        +
        +
        + +
        +
        +export class OverlayPanelDemo {
        +
        +    cars1: Car[];
        +    
        +    cars2: Car[];
        +    
        +    selectedCar: Car;
        +    
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsSmall().then(cars => this.cars1 = cars);
        +        this.carService.getCarsSmall().then(cars => this.cars2 = cars);
        +    }
        +    
        +    selectCar(event,car: Car, overlaypanel: OverlayPanel) {
        +        this.selectedCar = car;
        +        overlaypanel.toggle(event);
        +    }
        +}
        +
        +
        +
        +
        +
        diff --git a/src/app/showcase/components/overlaypanel/overlaypaneldemo.module.ts b/src/app/showcase/components/overlaypanel/overlaypaneldemo.module.ts new file mode 100644 index 00000000000..7fced54264a --- /dev/null +++ b/src/app/showcase/components/overlaypanel/overlaypaneldemo.module.ts @@ -0,0 +1,25 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {OverlayPanelDemo} from './overlaypaneldemo'; +import {OverlayPanelDemoRoutingModule} from './overlaypaneldemo-routing.module'; +import {OverlayPanelModule} from '../../../components/overlaypanel/overlaypanel'; +import {ButtonModule} from '../../../components/button/button'; +import {DataTableModule} from '../../../components/datatable/datatable'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + OverlayPanelDemoRoutingModule, + OverlayPanelModule, + ButtonModule, + DataTableModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + OverlayPanelDemo + ] +}) +export class OverlayPanelDemoModule {} diff --git a/src/app/showcase/components/overlaypanel/overlaypaneldemo.ts b/src/app/showcase/components/overlaypanel/overlaypaneldemo.ts new file mode 100644 index 00000000000..614b6309257 --- /dev/null +++ b/src/app/showcase/components/overlaypanel/overlaypaneldemo.ts @@ -0,0 +1,28 @@ +import {Component} from '@angular/core'; +import {OverlayPanel} from '../../../components/overlaypanel/overlaypanel'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; + +@Component({ + templateUrl: './overlaypaneldemo.html' +}) +export class OverlayPanelDemo { + + cars1: Car[]; + + cars2: Car[]; + + selectedCar: Car; + + constructor(private carService: CarService) { } + + ngOnInit() { + this.carService.getCarsSmall().then(cars => this.cars1 = cars); + this.carService.getCarsSmall().then(cars => this.cars2 = cars); + } + + selectCar(event,car: Car, overlaypanel: OverlayPanel) { + this.selectedCar = car; + overlaypanel.toggle(event); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/paginator/paginatordemo-routing.module.ts b/src/app/showcase/components/paginator/paginatordemo-routing.module.ts new file mode 100644 index 00000000000..c2fd63d166f --- /dev/null +++ b/src/app/showcase/components/paginator/paginatordemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {PaginatorDemo} from './paginatordemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: PaginatorDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class PaginatorDemoRoutingModule {} diff --git a/src/app/showcase/components/paginator/paginatordemo.html b/src/app/showcase/components/paginator/paginatordemo.html new file mode 100644 index 00000000000..9fd6cf4d25c --- /dev/null +++ b/src/app/showcase/components/paginator/paginatordemo.html @@ -0,0 +1,222 @@ +
        +
        + Paginator + Paginator is a generic widget to display content in paged format. +
        +
        + +
        + +
        + +
        + + +

        Import

        +
        +
        +import {PaginatorModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Paginator is defined using p-paginator element.

        +
        +
        +<p-paginator></p-paginator>
        +
        +
        +

        Rows and TotalRecords

        +

        Rows and TotalRecords define how many pages the paginator should display. Paginator below will have 10 pages.

        +
        +
        +<p-paginator rows="10" totalRecords="100"></p-paginator>
        +
        +
        + +

        PageLinks

        +

        PageLinks provide shortcuts to jump to a specific page, use pageLinkSize property to define the number of links to display. Default is 5.

        + +
        +
        +<p-paginator rows="10" totalRecords="100" pageLinkSize="3"></p-paginator>
        +
        +
        + +

        Rows Per Page

        +

        Number of items per page can be changed by the user using a dropdown if you define rowsPerPageOptions as an array of possible values.

        +
        +
        +<p-paginator rows="10" totalRecords="120" [rowsPerPageOptions]="[10,20,30]"></p-paginator>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        totalRecordsnumber0Number of total records.
        rowsnumber0Data count to display per page.
        firstnumber0Zero-relative number of the first row to be displayed.
        pageLinkSizenumber5Number of page links to display.
        rowsPerPageOptionsarraynullArray of integer values to display inside rows per page dropdown.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        alwaysShowbooleantrueWhether to show it even there is only one page.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + +
        NameParametersDescription
        onPageChangeevent.page: New page number
        + event.first: Index of first record
        + event.rows: Number of rows to display in new page
        + event.page: Index of the new page
        + event.pageCount: Total number of pages
        Callback to invoke when page changes, the event object contains information about the new state.
        +
        + +
        +
        +<p-paginator rows="10" totalRecords="100" (onPageChange)="paginate($event)"></p-paginator>
        +
        +
        + +
        +
        +export class MyComponent {
        +
        +    paginate(event) {
        +        //event.first = Index of the first record
        +        //event.rows = Number of rows to display in new page
        +        //event.page = Index of the new page
        +        //event.pageCount = Total number of pages
        +    }
        +
        +}
        +
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-paginatorContainer element.
        ui-paginator-firstFirst page element.
        ui-paginator-prevPrevious page element.
        ui-paginator-pagesContainer of page links.
        ui-paginator-pageA page link.
        ui-paginator-nextNext page element.
        ui-paginator-lastLast page element.
        ui-paginator-rpp-optionsRows per page dropdown.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<p-paginator rows="10" totalRecords="120" [rowsPerPageOptions]="[10,20,30]"></p-paginator>
        +
        +
        +
        +
        +
        diff --git a/src/app/showcase/components/paginator/paginatordemo.module.ts b/src/app/showcase/components/paginator/paginatordemo.module.ts new file mode 100644 index 00000000000..500dfb61559 --- /dev/null +++ b/src/app/showcase/components/paginator/paginatordemo.module.ts @@ -0,0 +1,21 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {PaginatorDemo} from './paginatordemo'; +import {PaginatorDemoRoutingModule} from './paginatordemo-routing.module'; +import {PaginatorModule} from '../../../components/paginator/paginator'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + PaginatorDemoRoutingModule, + PaginatorModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + PaginatorDemo + ] +}) +export class PaginatorDemoModule {} diff --git a/src/app/showcase/components/paginator/paginatordemo.ts b/src/app/showcase/components/paginator/paginatordemo.ts new file mode 100644 index 00000000000..8ebf022511c --- /dev/null +++ b/src/app/showcase/components/paginator/paginatordemo.ts @@ -0,0 +1,8 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './paginatordemo.html' +}) +export class PaginatorDemo { + +} \ No newline at end of file diff --git a/src/app/showcase/components/panel/paneldemo-routing.module.ts b/src/app/showcase/components/panel/paneldemo-routing.module.ts new file mode 100644 index 00000000000..fd5ae37107a --- /dev/null +++ b/src/app/showcase/components/panel/paneldemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {PanelDemo} from './paneldemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: PanelDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class PanelDemoRoutingModule {} diff --git a/src/app/showcase/components/panel/paneldemo.html b/src/app/showcase/components/panel/paneldemo.html new file mode 100644 index 00000000000..16aaf4c1a54 --- /dev/null +++ b/src/app/showcase/components/panel/paneldemo.html @@ -0,0 +1,228 @@ +
        +
        + Panel + Panel is a grouping component providing with content toggle feature. +
        +
        + +
        + + + + The story begins as Don Vito Corleone, the head of a New York Mafia family, oversees his daughter's wedding. + His beloved son Michael has just come home from the war, but does not intend to become part of his father's business. + Through Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, + kind and benevolent to those who give respect, but given to ruthless violence whenever anything stands against the good of the family. + + + + +
        + Custom Header + + +
        +
        + The story begins as Don Vito Corleone, the head of a New York Mafia family, oversees his daughter's wedding. + His beloved son Michael has just come home from the war, but does not intend to become part of his father's business. + Through Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, + kind and benevolent to those who give respect, but given to ruthless violence whenever anything stands against the good of the family. +
        +
        + +
        + + +

        Import

        +
        +
        +import {PanelModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Panel is defined with p-panel element.

        +
        +
        +<p-panel header="Title">
        +    Content
        +</p-panel>
        +
        +
        +

        Toggleable

        +

        Content of the panel can be expanded and collapsed using toggleable option, default state is defined with collapsed option.

        +
        +
        +<p-panel header="Title" [toggleable]="true">
        +    Content
        +</p-panel>
        +
        +
        + +

        Custom Header

        +

        Header section of the panel can be customized by defining a header element with content.

        +
        +
        +<p-panel >
        +    <p-header>
        +        Header content here
        +    </p-header>
        +    Body Content
        +</p-panel>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        headerstringnullHeader text of the panel.
        toggleablebooleanfalseDefines if content of panel can be expanded and collapsed.
        collapsedbooleanfalseDefines the initial state of panel content, supports one or two-way binding as well.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        expandIconstringfa-plusExpand icon of the toggle button.
        collapseIconstringfa-minusCollapsed icon of the toggle button.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onBeforeToggleevent.originalEvent: browser event
        + event.collapsed: state as a boolean
        Callback to invoke before content toggle.
        onAfterToggleevent.originalEvent: browser event
        + event.collapsed: state as a boolean
        Callback to invoke after content toggle.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-panelContainer element.
        ui-panel-titlebarHeader section.
        ui-panel-titleTitle text of panel.
        ui-panel-titlebar-togglerToggle icon.
        ui-panel-contentContent of panel.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<p-growl [value]="msgs"></p-growl>
        +
        +<p-panel header="Godfather I" [toggleable]="true" [style]="{'margin-bottom':'20px'}">
        +    The story begins as Don Vito Corleone, the head of a New York Mafia family, oversees his daughter's wedding. 
        +    His beloved son Michael has just come home from the war, but does not intend to become part of his father's business. 
        +    Through Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, 
        +    kind and benevolent to those who give respect, but given to ruthless violence whenever anything stands against the good of the family.
        +</p-panel>
        +
        +<p-panel>
        +    <p-header>
        +        <div class="ui-helper-clearfix">
        +            <span class="ui-panel-title" style="font-size:16px;display:inline-block;margin-top:2px">Custom Header</span>
        +            
        +            <p-splitButton [style]="{'float':'right'{" label="Save" icon="fa-check" (onClick)="save()" [model]="items"></p-splitButton>
        +        </div>
        +    </p-header>
        +    The story begins as Don Vito Corleone, the head of a New York Mafia family, oversees his daughter's wedding. 
        +    His beloved son Michael has just come home from the war, but does not intend to become part of his father's business. 
        +    Through Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, 
        +    kind and benevolent to those who give respect, but given to ruthless violence whenever anything stands against the good of the family.
        +</p-panel>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/panel/paneldemo.module.ts b/src/app/showcase/components/panel/paneldemo.module.ts new file mode 100644 index 00000000000..9b35c4930ba --- /dev/null +++ b/src/app/showcase/components/panel/paneldemo.module.ts @@ -0,0 +1,25 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {PanelDemo} from './paneldemo'; +import {PanelDemoRoutingModule} from './paneldemo-routing.module'; +import {PanelModule} from '../../../components/panel/panel'; +import {GrowlModule} from '../../../components/growl/growl'; +import {SplitButtonModule} from '../../../components/splitbutton/splitbutton'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + PanelDemoRoutingModule, + PanelModule, + GrowlModule, + SplitButtonModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + PanelDemo + ] +}) +export class PanelDemoModule {} diff --git a/src/app/showcase/components/panel/paneldemo.ts b/src/app/showcase/components/panel/paneldemo.ts new file mode 100644 index 00000000000..02cf943c210 --- /dev/null +++ b/src/app/showcase/components/panel/paneldemo.ts @@ -0,0 +1,41 @@ +import {Component,OnInit} from '@angular/core'; +import {Message} from '../../../components/common/api'; +import {MenuItem} from '../../../components/common/api'; + +@Component({ + templateUrl: './paneldemo.html' +}) +export class PanelDemo implements OnInit { + + msgs: Message[] = []; + + items: MenuItem[]; + + ngOnInit() { + this.items = [ + {label: 'Update', icon: 'fa-refresh', command: () => { + this.update(); + }}, + {label: 'Delete', icon: 'fa-close', command: () => { + this.delete(); + }}, + {label: 'Angular.io', icon: 'fa-link', url: 'http://angular.io'}, + {label: 'Theming', icon: 'fa-paint-brush', routerLink: ['/theming']} + ]; + } + + save() { + this.msgs = []; + this.msgs.push({severity:'info', summary:'Success', detail:'Data Saved'}); + } + + update() { + this.msgs = []; + this.msgs.push({severity:'info', summary:'Success', detail:'Data Updated'}); + } + + delete() { + this.msgs = []; + this.msgs.push({severity:'info', summary:'Success', detail:'Data Deleted'}); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/panelmenu/panelmenudemo-routing.module.ts b/src/app/showcase/components/panelmenu/panelmenudemo-routing.module.ts new file mode 100644 index 00000000000..66184e30ed5 --- /dev/null +++ b/src/app/showcase/components/panelmenu/panelmenudemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {PanelMenuDemo} from './panelmenudemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: PanelMenuDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class PanelMenuDemoRoutingModule {} diff --git a/src/app/showcase/components/panelmenu/panelmenudemo.html b/src/app/showcase/components/panelmenu/panelmenudemo.html new file mode 100644 index 00000000000..79e1bea1a3f --- /dev/null +++ b/src/app/showcase/components/panelmenu/panelmenudemo.html @@ -0,0 +1,295 @@ +
        +
        + Menu - PanelMenu + PanelMenu is a hybrid of accordion-tree components. +
        +
        + +
        + +
        + +
        + + +

        Import

        +
        +
        +import {PanelMenuModule,MenuItem} from 'primeng/primeng';
        +
        +
        + +

        MenuModel API

        +

        PanelMenu uses the common menumodel api to define its items, visit MenuModel API for details.

        + +

        Getting Started

        +

        PanelMenu requires nested menuitems as its model.

        +
        +
        +<p-panelMenu [model]="items" [style]="{'width':'300px'}"></p-panelMenu>
        +
        +
        + +
        +
        +export class PanelMenuDemo {
        +  
        +    private items: MenuItem[];
        +
        +    ngOnInit() {
        +        this.items = [
        +            {
        +                label: 'File',
        +                icon: 'fa-file-o',
        +                items: [{
        +                        label: 'New', 
        +                        icon: 'fa-plus',
        +                        items: [
        +                            {label: 'Project'},
        +                            {label: 'Other'},
        +                        ]
        +                    },
        +                    {label: 'Open'},
        +                    {label: 'Quit'}
        +                ]
        +            },
        +            {
        +                label: 'Edit',
        +                icon: 'fa-edit',
        +                items: [
        +                    {label: 'Undo', icon: 'fa-mail-forward'},
        +                    {label: 'Redo', icon: 'fa-mail-reply'}
        +                ]
        +            },
        +            {
        +                label: 'Help',
        +                icon: 'fa-question',
        +                items: [
        +                    {
        +                        label: 'Contents'
        +                    },
        +                    {
        +                        label: 'Search', 
        +                        icon: 'fa-search', 
        +                        items: [
        +                            {
        +                                label: 'Text', 
        +                                items: [
        +                                    {
        +                                        label: 'Workspace'
        +                                    }
        +                                ]
        +                            },
        +                            {
        +                                label: 'File'
        +                            }
        +                    ]}
        +                ]
        +            },
        +            {
        +                label: 'Actions',
        +                icon: 'fa-gear',
        +                items: [
        +                    {
        +                        label: 'Edit',
        +                        icon: 'fa-refresh',
        +                        items: [
        +                            {label: 'Save', icon: 'fa-save'},
        +                            {label: 'Update', icon: 'fa-save'},
        +                        ]
        +                    },
        +                    {
        +                        label: 'Other',
        +                        icon: 'fa-phone',
        +                        items: [
        +                            {label: 'Delete', icon: 'fa-minus'}
        +                        ]
        +                    }
        +                ]
        +            }
        +        ];
        +    }
        +}
        +
        +
        + +

        Initial State

        +

        MenuItem has an expanded property to control the visibility of a submenu, you may use this property to control the state from the menumodel.

        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        modelarraynullAn array of menuitems.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-panelmenuContainer element.
        ui-panelmenu-headerAccordion header of root submenu.
        ui-panelmenu-contentAccordion content of root submenu.
        ui-menu-listList element.
        ui-menuitemMenuitem element.
        ui-menuitem-textLabel of a menuitem.
        ui-menuitem-iconIcon of a menuitem.
        ui-panelmenu-iconArrow icon of an accordion header.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<p-panelMenu [model]="items" [style]="{'width':'300px'}"></p-panelMenu>
        +
        +
        + +
        +
        +export class PanelMenuDemo {
        +  
        +    private items: MenuItem[];
        +
        +    ngOnInit() {
        +        this.items = [
        +            {
        +                label: 'File',
        +                icon: 'fa-file-o',
        +                items: [{
        +                        label: 'New', 
        +                        icon: 'fa-plus',
        +                        items: [
        +                            {label: 'Project'},
        +                            {label: 'Other'},
        +                        ]
        +                    },
        +                    {label: 'Open'},
        +                    {label: 'Quit'}
        +                ]
        +            },
        +            {
        +                label: 'Edit',
        +                icon: 'fa-edit',
        +                items: [
        +                    {label: 'Undo', icon: 'fa-mail-forward'},
        +                    {label: 'Redo', icon: 'fa-mail-reply'}
        +                ]
        +            },
        +            {
        +                label: 'Help',
        +                icon: 'fa-question',
        +                items: [
        +                    {
        +                        label: 'Contents'
        +                    },
        +                    {
        +                        label: 'Search', 
        +                        icon: 'fa-search', 
        +                        items: [
        +                            {
        +                                label: 'Text', 
        +                                items: [
        +                                    {
        +                                        label: 'Workspace'
        +                                    }
        +                                ]
        +                            },
        +                            {
        +                                label: 'File'
        +                            }
        +                    ]}
        +                ]
        +            },
        +            {
        +                label: 'Actions',
        +                icon: 'fa-gear',
        +                items: [
        +                    {
        +                        label: 'Edit',
        +                        icon: 'fa-refresh',
        +                        items: [
        +                            {label: 'Save', icon: 'fa-save'},
        +                            {label: 'Update', icon: 'fa-save'},
        +                        ]
        +                    },
        +                    {
        +                        label: 'Other',
        +                        icon: 'fa-phone',
        +                        items: [
        +                            {label: 'Delete', icon: 'fa-minus'}
        +                        ]
        +                    }
        +                ]
        +            }
        +        ];
        +    }
        +}
        +
        +
        +
        +
        +
        diff --git a/src/app/showcase/components/panelmenu/panelmenudemo.module.ts b/src/app/showcase/components/panelmenu/panelmenudemo.module.ts new file mode 100644 index 00000000000..5ac1d53a53f --- /dev/null +++ b/src/app/showcase/components/panelmenu/panelmenudemo.module.ts @@ -0,0 +1,21 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {PanelMenuDemo} from './panelmenudemo'; +import {PanelMenuDemoRoutingModule} from './panelmenudemo-routing.module'; +import {PanelMenuModule} from '../../../components/panelmenu/panelmenu'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + PanelMenuDemoRoutingModule, + PanelMenuModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + PanelMenuDemo + ] +}) +export class PanelMenuDemoModule {} diff --git a/src/app/showcase/components/panelmenu/panelmenudemo.ts b/src/app/showcase/components/panelmenu/panelmenudemo.ts new file mode 100644 index 00000000000..c88b078dbdd --- /dev/null +++ b/src/app/showcase/components/panelmenu/panelmenudemo.ts @@ -0,0 +1,84 @@ +import {Component} from '@angular/core'; +import {MenuItem} from '../../../components/common/api'; + +@Component({ + templateUrl: './panelmenudemo.html' +}) +export class PanelMenuDemo { + + private items: MenuItem[]; + + ngOnInit() { + this.items = [ + { + label: 'File', + icon: 'fa-file-o', + items: [{ + label: 'New', + icon: 'fa-plus', + items: [ + {label: 'Project'}, + {label: 'Other'}, + ] + }, + {label: 'Open'}, + {label: 'Quit'} + ] + }, + { + label: 'Edit', + icon: 'fa-edit', + items: [ + {label: 'Undo', icon: 'fa-mail-forward'}, + {label: 'Redo', icon: 'fa-mail-reply'} + ] + }, + { + label: 'Help', + icon: 'fa-question', + items: [ + { + label: 'Contents' + }, + { + label: 'Search', + icon: 'fa-search', + items: [ + { + label: 'Text', + items: [ + { + label: 'Workspace' + } + ] + }, + { + label: 'File' + } + ]} + ] + }, + { + label: 'Actions', + icon: 'fa-gear', + items: [ + { + label: 'Edit', + icon: 'fa-refresh', + items: [ + {label: 'Save', icon: 'fa-save'}, + {label: 'Update', icon: 'fa-save'}, + ] + }, + { + label: 'Other', + icon: 'fa-phone', + items: [ + {label: 'Delete', icon: 'fa-minus'} + ] + } + ] + } + ]; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/password/passworddemo-routing.module.ts b/src/app/showcase/components/password/passworddemo-routing.module.ts new file mode 100644 index 00000000000..6cd544b306e --- /dev/null +++ b/src/app/showcase/components/password/passworddemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {PasswordDemo} from './passworddemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: PasswordDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class PasswordDemoRoutingModule {} diff --git a/src/app/showcase/components/password/passworddemo.html b/src/app/showcase/components/password/passworddemo.html new file mode 100644 index 00000000000..7ad498c111b --- /dev/null +++ b/src/app/showcase/components/password/passworddemo.html @@ -0,0 +1,127 @@ +
        +
        + Password + Password displays strength indicator for password fields. +
        +
        + +
        +

        Password

        + +
        + +
        + + +

        Import

        +
        +
        +import {PasswordModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Password is applied to an input field with pPassword directive.

        + +
        +
        +<input type="password" pPassword />
        +
        +
        + +

        Model Binding

        +

        A model can be bound using standard ngModel directive.

        +
        +
        +<input type="password" pPassword [(ngModel)]="property"/>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        promptLabelstringPlease enter a passwordText to prompt password entry.
        weakLabelstringWeakText for a weak password.
        mediumLabelstringMediumText for a medium password.
        strongLabelstringStrongText for a strong password.
        feedbackbooleantrueWhether to show the strength indicator or not.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-password-panelContainer of password panel
        ui-password-meterMeter element of password strength
        ui-password-infoText to display strength
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<h3 class="first">Password</h3>
        +<input pPassword type="password"/>
        +
        +
        + +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/password/passworddemo.module.ts b/src/app/showcase/components/password/passworddemo.module.ts new file mode 100644 index 00000000000..b7da95ad6b8 --- /dev/null +++ b/src/app/showcase/components/password/passworddemo.module.ts @@ -0,0 +1,21 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {PasswordDemo} from './passworddemo'; +import {PasswordDemoRoutingModule} from './passworddemo-routing.module'; +import {PasswordModule} from '../../../components/password/password'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + PasswordDemoRoutingModule, + PasswordModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + PasswordDemo + ] +}) +export class PasswordDemoModule {} diff --git a/src/app/showcase/components/password/passworddemo.ts b/src/app/showcase/components/password/passworddemo.ts new file mode 100644 index 00000000000..2d649a5d29c --- /dev/null +++ b/src/app/showcase/components/password/passworddemo.ts @@ -0,0 +1,8 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './passworddemo.html' +}) +export class PasswordDemo { + +} \ No newline at end of file diff --git a/src/app/showcase/components/picklist/picklistdemo-routing.module.ts b/src/app/showcase/components/picklist/picklistdemo-routing.module.ts new file mode 100644 index 00000000000..3e19c1c2224 --- /dev/null +++ b/src/app/showcase/components/picklist/picklistdemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {PickListDemo} from './picklistdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: PickListDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class PickListDemoRoutingModule {} diff --git a/src/app/showcase/components/picklist/picklistdemo.html b/src/app/showcase/components/picklist/picklistdemo.html new file mode 100644 index 00000000000..2f1d58d0a97 --- /dev/null +++ b/src/app/showcase/components/picklist/picklistdemo.html @@ -0,0 +1,287 @@ +
        +
        + PickList + PickList is used to reorder items between differents lists. +
        +
        + +
        + + + +
        + +
        {{car.brand}} - {{car.year}} - {{car.color}}
        +
        +
        +
        + +
        + +
        + + +

        Import

        +
        +
        +import {PickListModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        PickList requires two arrays as its lists and a ng-template for the item content where each item in the array + can be accessed inside the ng-template using a local ng-template variable.

        +
        +
        +<p-pickList [source]="list1" [target]="list2">
        +    <ng-template let-car pTemplate="item">
        +        <div class="ui-helper-clearfix">
        +            <img src="showcase/resources/demo/images/car/{{car.brand}}.gif" style="display:inline-block;margin:2px 0 2px 2px"/>
        +            <div style="font-size:14px;float:right;margin:15px 5px 0 0">{{car.brand}} - {{car.year}} - {{car.color}}</div>
        +        </div>
        +    </ng-template>
        +</p-pickList>
        +
        +
        + +
        +
        +export class MyComponent {
        +
        +    list1: any[];
        +    
        +    list2: any[];
        +    
        +    ngOnInit() {
        +        this.list1 = //initialize list 1
        +        this.list2 = //initialize list 2
        +    }
        +}
        +
        +
        +

        Responsive

        +

        In responsive mode, picklist adjusts its controls based on screen size. To activate this mode, set responsive as true.

        +
        +
        +<p-pickList [responsive]="true">
        +
        +
        + +

        Headers

        +

        sourceHeader and targetHeader attributes are used to define captions for the lists.

        +
        +
        +<p-pickList sourceHeader="Source List" targetHeader="Target List">
        +
        +
        + +

        Multiple Selection

        +

        Multiple items can either be selected using metaKey or toggled individually depending on the value of metaKeySelection property value which is true by default. On touch enabled + devices metaKeySelection is turned off automatically.

        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        sourcearraynullAn array of objects for the source list.
        targetarraynullAn array of objects for the target list.
        sourceHeaderstringnullText for the source list caption
        targetHeaderstringnullText for the target list caption
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        sourceStylestringnullInline style of the source list element.
        targetStylestringnullInline style of the target list element.
        responsivebooleanfalseWhen enabled orderlist adjusts its controls based on screen size.
        showSourceControlsbooleantrueWhether to show buttons of source list.
        showTargetControlsbooleantrueWhether to show buttons of target list.
        metaKeySelectionbooleantrueDefines how multiple items can be selected, when true metaKey needs to be pressed to select or unselect an item and when set to false selection of each item + can be toggled individually. On touch enabled devices, metaKeySelection is turned off automatically.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onMoveToTargetevent.items: Moved items arrayCallback to invoke when items are moved from source to target.
        onMoveToSourceevent.items: Moved items arrayCallback to invoke when items are moved from target to source.
        onSourceReorderevent.items: Moved items arrayCallback to invoke when items are reordered within source list.
        onTargetReorderevent.items: Moved items arrayCallback to invoke when items are reordered within target list.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-picklistContainer element.
        ui-picklist-source-controlsContainer of source list buttons.
        ui-picklist-target-controlsContainer of target list buttons.
        ui-picklist-buttonsContainer of buttons.
        ui-picklist-listwrapperParent of a list element.
        ui-picklist-listList element.
        ui-picklist-itemAn item in the list.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<p-pickList [source]="sourceCars" [target]="targetCars" sourceHeader="Available" targetHeader="Selected" [responsive]="true" [sourceStyle]="{'height':'300px'}" [targetStyle]="{'height':'300px'}">
        +    <ng-template let-car pTemplate="item">
        +        <div class="ui-helper-clearfix">
        +            <img src="showcase/resources/demo/images/car/{{car.brand}}.gif" style="display:inline-block;margin:2px 0 2px 2px"/>
        +            <div style="font-size:14px;float:right;margin:15px 5px 0 0">{{car.brand}} - {{car.year}} - {{car.color}}</div>
        +        </div>
        +    </ng-template>
        +</p-pickList>
        +
        +
        + +
        +
        +export class PickListDemo {
        +
        +    sourceCars: Car[];
        +    
        +    targetCars: Car[];
        +    
        +    constructor(private carService: CarService) { }
        +
        +    ngOnInit() {
        +        this.carService.getCarsSmall().then(cars => this.sourceCars = cars);
        +        this.targetCars = [];
        +    }
        +}
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/picklist/picklistdemo.module.ts b/src/app/showcase/components/picklist/picklistdemo.module.ts new file mode 100644 index 00000000000..564b379e2d2 --- /dev/null +++ b/src/app/showcase/components/picklist/picklistdemo.module.ts @@ -0,0 +1,21 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {PickListDemo} from './picklistdemo'; +import {PickListDemoRoutingModule} from './picklistdemo-routing.module'; +import {PickListModule} from '../../../components/picklist/picklist'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + PickListDemoRoutingModule, + PickListModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + PickListDemo + ] +}) +export class PickListDemoModule {} diff --git a/src/app/showcase/components/picklist/picklistdemo.ts b/src/app/showcase/components/picklist/picklistdemo.ts new file mode 100644 index 00000000000..7b67c076f39 --- /dev/null +++ b/src/app/showcase/components/picklist/picklistdemo.ts @@ -0,0 +1,20 @@ +import {Component} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; + +@Component({ + templateUrl: './picklistdemo.html' +}) +export class PickListDemo { + + sourceCars: Car[]; + + targetCars: Car[]; + + constructor(private carService: CarService) { } + + ngOnInit() { + this.carService.getCarsSmall().then(cars => this.sourceCars = cars); + this.targetCars = []; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/progressbar/progressbardemo-routing.module.ts b/src/app/showcase/components/progressbar/progressbardemo-routing.module.ts new file mode 100644 index 00000000000..71254deb878 --- /dev/null +++ b/src/app/showcase/components/progressbar/progressbardemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {ProgressBarDemo} from './progressbardemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: ProgressBarDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class ProgressBarDemoRoutingModule {} diff --git a/src/app/showcase/components/progressbar/progressbardemo.html b/src/app/showcase/components/progressbar/progressbardemo.html new file mode 100644 index 00000000000..1575826478f --- /dev/null +++ b/src/app/showcase/components/progressbar/progressbardemo.html @@ -0,0 +1,148 @@ +
        +
        + ProgressBar + ProgressBar is a process status indicator. +
        +
        + +
        + + +

        Dynamic

        + + +

        Static

        + +
        + +
        + + +

        Import

        +
        +
        +import {ProgressBarModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        ProgressBar requires a value between 0 and 100 to display the progress.

        +
        +
        +<p-progressBar [value]="value"></p-progressBar>
        +
        +
        + +
        +
        +export class ModelComponent {
        +
        +    value: number = 0;
        +
        +}
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        valuenumbernullCurrent value of the progress.
        showValuebooleantrueShow or hide progress bar value.
        unitstring%Unit sign appended to the value.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-progressbarContainer element.
        ui-progressbar-valueElement whose width changes according to value.
        ui-progressbar-labelLabel element that displays the current value.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<p-growl [(value)]="msgs"></p-growl>
        +
        +<h3 class="first">Dynamic</h3>
        +<p-progressBar [value]="value"></p-progressBar>
        +
        +<h3>Static</h3>
        +<p-progressBar [value]="50"></p-progressBar>
        +
        +
        + +
        +
        +export class ProgressBarDemo {
        +
        +    value: number = 0;
        +
        +    msgs: Message[];
        +
        +    ngOnInit() {
        +        let interval = setInterval(() => {
        +            this.value = this.value + Math.floor(Math.random() * 10) + 1;
        +            if(this.value >= 100) {
        +                this.value = 100;
        +                this.msgs = [{severity: 'info', summary: 'Success', detail: 'Process Completed'}];
        +                clearInterval(interval);
        +            }
        +        }, 2000);
        +    }
        +
        +}
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/progressbar/progressbardemo.module.ts b/src/app/showcase/components/progressbar/progressbardemo.module.ts new file mode 100644 index 00000000000..a3b4b99d346 --- /dev/null +++ b/src/app/showcase/components/progressbar/progressbardemo.module.ts @@ -0,0 +1,23 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {ProgressBarDemo} from './progressbardemo'; +import {ProgressBarDemoRoutingModule} from './progressbardemo-routing.module'; +import {ProgressBarModule} from '../../../components/progressbar/progressbar'; +import {GrowlModule} from '../../../components/growl/growl'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + ProgressBarDemoRoutingModule, + ProgressBarModule, + GrowlModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + ProgressBarDemo + ] +}) +export class ProgressBarDemoModule {} diff --git a/src/app/showcase/components/progressbar/progressbardemo.ts b/src/app/showcase/components/progressbar/progressbardemo.ts new file mode 100644 index 00000000000..40608fad3f6 --- /dev/null +++ b/src/app/showcase/components/progressbar/progressbardemo.ts @@ -0,0 +1,24 @@ +import {Component,OnInit} from '@angular/core'; +import {Message} from '../../../components/common/api'; + +@Component({ + templateUrl: './progressbardemo.html' +}) +export class ProgressBarDemo { + + value: number = 0; + + msgs: Message[]; + + ngOnInit() { + let interval = setInterval(() => { + this.value = this.value + Math.floor(Math.random() * 10) + 1; + if(this.value >= 100) { + this.value = 100; + this.msgs = [{severity: 'info', summary: 'Success', detail: 'Process Completed'}]; + clearInterval(interval); + } + }, 2000); + } + +} \ No newline at end of file diff --git a/src/app/showcase/components/radiobutton/radiobuttondemo-routing.module.ts b/src/app/showcase/components/radiobutton/radiobuttondemo-routing.module.ts new file mode 100644 index 00000000000..36b3759f154 --- /dev/null +++ b/src/app/showcase/components/radiobutton/radiobuttondemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {RadioButtonDemo} from './radiobuttondemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: RadioButtonDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class RadioButtonDemoRoutingModule {} diff --git a/src/app/showcase/components/radiobutton/radiobuttondemo.html b/src/app/showcase/components/radiobutton/radiobuttondemo.html new file mode 100644 index 00000000000..f8618292137 --- /dev/null +++ b/src/app/showcase/components/radiobutton/radiobuttondemo.html @@ -0,0 +1,237 @@ +
        +
        + RadioButton + RadioButton is an extension to standard radio button element with skinning capabilities. +
        +
        + +
        +

        Basic

        +
        +
        +
        +
        +
        + Selected Value = {{val1||'none'}} + +

        Preselection

        +
        +
        +
        +
        +
        + Selected Value = {{val2||'none'}} +
        + +
        + + +

        Import

        +
        +
        +import {RadioButtonModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Two-way value binding is defined using the standard ngModel directive.

        + +
        +
        +<p-radioButton name="groupname" value="val1" [(ngModel)]="selectedValue"></p-radioButton>
        +<p-radioButton name="groupname" value="val2" [(ngModel)]="selectedValue"></p-radioButton>
        +
        +
        + +
        +
        +export class ModelComponent {
        +
        +    selectedValue: string;
        +
        +}
        +
        +
        + +

        As model is two-way binding enabled, giving a default value to the model is enough to display a radio button as checked by default.

        +
        +
        +export class ModelComponent {
        +
        +    selectedValue: string = 'val1';
        +
        +}
        +
        +
        + +

        Model Driven Forms

        +

        RadioButton can be used in a model driven form as well.

        +
        +
        +<p-radioButton name="groupname" value="ps4" formControlName="console"></p-radioButton>
        +
        +
        + +

        Label

        +

        The label attribute provides a label text for the radio button. This label is also clickable and selects value.

        +
        +
        +<p-radioButton name="groupname" value="val1" label="Option 2" [(ngModel)]="selectedValue"></p-radioButton>
        +
        +            
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        namestringnullName of the radiobutton group.
        valueanynullValue of the radiobutton.
        labelstringnullLabel of the radiobutton.
        disabledbooleanfalseWhen present, it specifies that the element should be disabled.
        tabindexnumbernullIndex of the element in tabbing order.
        inputIdstringnullIdentifier of the focus input to match a label defined for the component.
        styleobjectnullInline style of the component.
        styleClassstringnullStyle class of the component.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + +
        NameParametersDescription
        onClick-Callback to invoke on radio button click.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-radiobuttonContainer element
        ui-radiobutton-boxContainer of icon.
        ui-radiobutton-iconIcon element.
        ui-chkbox-labelLabel element.
        +
        + +

        Dependencies

        +

        None.

        + +
        + + +
        +
        +<h3 class="first">Basic</h3>
        +<div class="ui-g" style="width:250px;margin-bottom:10px">
        +    <div class="ui-g-12"><p-radioButton name="group1" value="Option 1" label="Option 1" [(ngModel)]="val1"></p-radioButton></div>
        +    <div class="ui-g-12"><p-radioButton name="group1" value="Option 2" label="Option 2" [(ngModel)]="val1"></p-radioButton></div>
        +    <div class="ui-g-12"><p-radioButton name="group1" value="Option 3" label="Option 3" [(ngModel)]="val1"></p-radioButton></div>
        +</div>
        +Selected Value = {{val1||'none'}}
        +
        +<h3>Preselection</h3>
        +<div class="ui-g" style="width:250px;margin-bottom:10px">
        +    <div class="ui-g-12"><p-radioButton name="group2" value="Option 1" label="Option 1" [(ngModel)]="val2"></p-radioButton></div>
        +    <div class="ui-g-12"><p-radioButton name="group2" value="Option 2" label="Option 2" [(ngModel)]="val2"></p-radioButton></div>
        +    <div class="ui-g-12"><p-radioButton name="group2" value="Option 3" label="Option 3" [(ngModel)]="val2"></p-radioButton></div>
        +</div>
        +Selected Value = {{val2||'none'}}
        +
        +
        + +
        +
        +export class RadioButtonDemo {
        +
        +    val1: string;
        +
        +    val2: string = 'Option 2';
        +    
        +}
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/radiobutton/radiobuttondemo.module.ts b/src/app/showcase/components/radiobutton/radiobuttondemo.module.ts new file mode 100644 index 00000000000..ca6068c12b5 --- /dev/null +++ b/src/app/showcase/components/radiobutton/radiobuttondemo.module.ts @@ -0,0 +1,23 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {RadioButtonDemo} from './radiobuttondemo'; +import {RadioButtonDemoRoutingModule} from './radiobuttondemo-routing.module'; +import {RadioButtonModule} from '../../../components/radiobutton/radiobutton'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + RadioButtonDemoRoutingModule, + RadioButtonModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + RadioButtonDemo + ] +}) +export class RadioButtonDemoModule {} diff --git a/src/app/showcase/components/radiobutton/radiobuttondemo.ts b/src/app/showcase/components/radiobutton/radiobuttondemo.ts new file mode 100644 index 00000000000..e2d067908a6 --- /dev/null +++ b/src/app/showcase/components/radiobutton/radiobuttondemo.ts @@ -0,0 +1,17 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './radiobuttondemo.html', + styles: [` + .ui-grid label { + display: inline-block; + margin: 3px 0px 0px 4px; + } + `] +}) +export class RadioButtonDemo { + + val1: string; + + val2: string = 'Option 2'; +} \ No newline at end of file diff --git a/src/app/showcase/components/rating/ratingdemo-routing.module.ts b/src/app/showcase/components/rating/ratingdemo-routing.module.ts new file mode 100644 index 00000000000..d48f89d3731 --- /dev/null +++ b/src/app/showcase/components/rating/ratingdemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {RatingDemo} from './ratingdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: RatingDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class RatingDemoRoutingModule {} diff --git a/src/app/showcase/components/rating/ratingdemo.html b/src/app/showcase/components/rating/ratingdemo.html new file mode 100644 index 00000000000..3dce0ba70a1 --- /dev/null +++ b/src/app/showcase/components/rating/ratingdemo.html @@ -0,0 +1,226 @@ +
        +
        + Rating + Rating components is a star based selection input. +
        +
        + +
        +

        Basic {{val1}}

        + +
        + +

        Callback {{val2}}

        + {{msg}} +
        + +

        No Cancel {{val3}}

        + +
        + +

        ReadOnly

        + +
        + +

        Disabled

        + +
        +
        + +
        + + +

        Import

        +
        +
        +import {RatingModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Two-way value binding is defined using ngModel.

        + +
        +
        +<p-rating [(ngModel)]="val"></p-rating>
        +
        +
        + +
        +
        +export class ModelComponent {
        +
        +    val: number;
        +
        +}
        +
        +
        + +

        Defining a default value would be enough to display the initial number of selected stars.

        +
        +
        +export class ModelComponent {
        +
        +    val: number = 3;
        +
        +}
        +
        +
        + +

        Model Driven Forms

        +

        Rating can be used in a model driven form as well.

        +
        +
        +<p-rating formControlName="score"></p-rating>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        starsnumber5Number of stars.
        cancelbooleantrueWhen specified a cancel icon is displayed to allow removing the value.
        disabledbooleanfalseWhen present, it specifies that the element should be disabled.
        readonlybooleanfalseWhen present, changing the value is not possible.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onRateevent.originalEvent: browser event
        + event.value: selected value +
        Callback to invoke on rate change.
        onCancelevent: browser eventCallback to invoke when value is removed.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-ratingContainer element
        ui-rating-starStar element
        ui-rating-star-onSelected star element.
        ui-rating-cancelCancel icon.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<h3 class="first">Basic {{val1}}</h3> 
        +<p-rating [(ngModel)]="val1"></p-rating>
        +
        +<h3>Callback {{val2}}</h3>
        +<p-rating [(ngModel)]="val2" (onRate)="handleRate($event)" (onCancel)="handleCancel($event)"></p-rating> <span *ngIf="msg" style="margin-left:10px">{{msg}}</span>
        +
        +<h3>No Cancel {{val3}}</h3> 
        +<p-rating [(ngModel)]="val3" [cancel]="false"></p-rating>
        +
        +<h3>ReadOnly</h3> 
        +<p-rating [ngModel]="5" readonly="true" stars="10" [cancel]="false"></p-rating>
        +
        +<h3>Disabled</h3> 
        +<p-rating [ngModel]="val4" disabled="true" stars="10"></p-rating>
        +
        +
        + +
        +
        +export class RatingDemo {
        +
        +    val1: number;
        +
        +    val2: number = 5;
        +
        +    val3: number;
        +
        +    val4: number = 5;
        +
        +    msg: string;
        +
        +    handleRate(event) {
        +        this.msg = "You have rated " + event.value;
        +    }
        +
        +    handleCancel(event) {
        +        this.msg = "Rating Cancelled";
        +    }
        +}
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/rating/ratingdemo.module.ts b/src/app/showcase/components/rating/ratingdemo.module.ts new file mode 100644 index 00000000000..86fe2fe5351 --- /dev/null +++ b/src/app/showcase/components/rating/ratingdemo.module.ts @@ -0,0 +1,23 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {RatingDemo} from './ratingdemo'; +import {RatingDemoRoutingModule} from './ratingdemo-routing.module'; +import {RatingModule} from '../../../components/rating/rating'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + RatingDemoRoutingModule, + RatingModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + RatingDemo + ] +}) +export class RatingDemoModule {} diff --git a/src/app/showcase/components/rating/ratingdemo.ts b/src/app/showcase/components/rating/ratingdemo.ts new file mode 100644 index 00000000000..574fad2317a --- /dev/null +++ b/src/app/showcase/components/rating/ratingdemo.ts @@ -0,0 +1,25 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './ratingdemo.html' +}) +export class RatingDemo { + + val1: number; + + val2: number; + + val3: number; + + val4: number = 5; + + msg: string; + + handleRate(event) { + this.msg = "You have rated " + event.value; + } + + handleCancel(event) { + this.msg = "Rating Cancelled"; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/responsive/responsivedemo-routing.module.ts b/src/app/showcase/components/responsive/responsivedemo-routing.module.ts new file mode 100644 index 00000000000..011dd49a3c4 --- /dev/null +++ b/src/app/showcase/components/responsive/responsivedemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {ResponsiveDemo} from './responsivedemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: ResponsiveDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class ResponsiveDemoRoutingModule {} diff --git a/src/app/showcase/components/responsive/responsivedemo.html b/src/app/showcase/components/responsive/responsivedemo.html new file mode 100644 index 00000000000..a7dbe27ed93 --- /dev/null +++ b/src/app/showcase/components/responsive/responsivedemo.html @@ -0,0 +1,610 @@ +
        +
        +
        + Responsive + .ui-fluid style class provides fluid width to components for efficient use of space in screen. + This example demonstrates ui-fluid in combination with Grid CSS and the components having built-in responsive modes like datatable. Note that Grid CSS is not mandatory, any grid system + can be used with ui-fluid. +
        +
        + +
        +
        +
        +
        + InputText +
        +
        + +
        +
        +
        +
        + Textarea +
        +
        + +
        +
        +
        +
        + Calendar +
        +
        + +
        +
        +
        +
        + Suggest +
        +
        + +
        +
        +
        +
        + Button +
        +
        + +
        +
        +
        +
        + SplitButton +
        +
        + +
        +
        +
        +
        + Dropdown +
        +
        + +
        +
        +
        +
        + Password +
        +
        + +
        +
        + +
        +
        + Listbox +
        +
        + +
        +
        +
        +
        + Radio +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        + Dialog +
        +
        + +
        +
        + + +

        The story begins as Don Vito Corleone, the head of a New York Mafia family, oversees his daughter's wedding. + His beloved son Michael has just come home from the war, but does not intend to become part of his father's business. + Through Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, + kind and benevolent to those who give respect, + but given to ruthless violence whenever anything stands against the good of the family.

        +
        + + + The story begins as Don Vito Corleone, the head of a New York Mafia family, oversees his daughter's wedding. + His beloved son Michael has just come home from the war, but does not intend to become part of his father's business. + Through Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, + kind and benevolent to those who give respect, + but given to ruthless violence whenever anything stands against the good of the family. + + + + Cars + + + + + + + + + Datagrid + + +
        + + +
        {{car.year}} - {{car.color}}
        +
        +
        +
        +
        +
        + + + + + + +
        {{car.brand}} - {{car.year}} - {{car.color}}
        +
        +
        + + + + + + + + + + +
        {{car.brand}} - {{car.year}} - {{car.color}}
        +
        +
        +
        +
        + +
        +
        + +
        +
        +
        +
        + +
        + + +
        +
        +<div class="ui-g">
        +    <div class="ui-g-12 ui-md-6">
        +        <div class="ui-g-4">
        +            InputText
        +        </div>
        +        <div class="ui-g-8">
        +            <input pInputText type="text" />
        +        </div>
        +    </div>
        +    <div class="ui-g-12 ui-md-6">
        +        <div class="ui-g-4">
        +            Textarea
        +        </div>
        +        <div class="ui-g-8">
        +            <textarea pInputTextarea type="text"></textarea>
        +        </div>
        +    </div>
        +    <div class="ui-g-12 ui-md-6">
        +        <div class="ui-g-4">
        +            Calendar
        +        </div>
        +        <div class="ui-g-8">
        +            <p-calendar [(ngModel)]="date"></p-calendar>
        +        </div>
        +    </div>
        +    <div class="ui-g-12 ui-md-6">
        +        <div class="ui-g-4">
        +            Suggest
        +        </div>
        +        <div class="ui-g-8">
        +            <p-autoComplete [(ngModel)]="country" [suggestions]="filteredCountriesSingle" (completeMethod)="filterCountrySingle($event)" field="name" [size]="30"
        +            placeholder="Countries" [minLength]="1"></p-autoComplete>
        +        </div>
        +    </div>
        +    <div class="ui-g-12 ui-md-6">
        +        <div class="ui-g-4">
        +            Button
        +        </div>
        +        <div class="ui-g-8">
        +            <button pButton label="Save"type="button"></button>
        +        </div>
        +    </div>
        +    <div class="ui-g-12 ui-md-6">
        +        <div class="ui-g-4">
        +            SplitButton
        +        </div>
        +        <div class="ui-g-8">
        +            <p-splitButton label="Save" icon="fa-check" [model]="splitMenuItems"></p-splitButton>
        +        </div>
        +    </div>
        +    <div class="ui-g-12 ui-md-6">
        +        <div class="ui-g-4">
        +            Dropdown
        +        </div>
        +        <div class="ui-g-8">
        +            <p-dropdown [options]="cities" [(ngModel)]="selectedCity" [autoWidth]="false"></p-dropdown>
        +        </div>
        +    </div>
        +    <div class="ui-g-12 ui-md-6">
        +        <div class="ui-g-4">
        +            Password
        +        </div>
        +        <div class="ui-g-8">
        +            <input type="text" pPassword />
        +        </div>
        +    </div>
        +
        +    <div class="ui-g-12 ui-md-6">
        +        <div class="ui-g-4">
        +            Listbox
        +        </div>
        +        <div class="ui-g-8">
        +            <p-listbox [options]="options" [(ngModel)]="selectedOptions"></p-listbox>
        +        </div>
        +    </div>
        +    <div class="ui-g-12 ui-md-6">
        +        <div class="ui-g-4">
        +            Radio
        +        </div>
        +        <div class="ui-g-8">
        +            <div class="ui-g radiobuttons">
        +                <div class="ui-g-12"><p-radioButton name="group1" value="Option 1" [(ngModel)]="val"></p-radioButton><label class="ui-widget">Option 1</label></div>
        +                <div class="ui-g-12"><p-radioButton name="group1" value="Option 2" [(ngModel)]="val"></p-radioButton><label class="ui-widget">Option 2</label></div>
        +                <div class="ui-g-12"><p-radioButton name="group1" value="Option 3" [(ngModel)]="val"></p-radioButton><label class="ui-widget">Option 3</label></div>
        +                <div class="ui-g-12"><p-radioButton name="group1" value="Option 4" [(ngModel)]="val"></p-radioButton><label class="ui-widget">Option 4</label></div>
        +            </div>
        +        </div>
        +    </div>
        +    <div class="ui-g-2">
        +        Dialog
        +    </div>
        +    <div class="ui-g-10">
        +        <button pButton label="Show" type="button" icon='fa-external-link' (click)="showDialog()"></button>
        +    </div>
        +</div>
        +
        +<p-dialog header="Godfather 1" [(visible)]="display" [responsive]="true" [resizable]="false" [width]="300">
        +    <p>The story begins as Don Vito Corleone, the head of a New York Mafia family, oversees his daughter's wedding.
        +        His beloved son Michael has just come home from the war, but does not intend to become part of his father's business.
        +        Through Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family,
        +        kind and benevolent to those who give respect,
        +        but given to ruthless violence whenever anything stands against the good of the family.</p>
        +</p-dialog>
        +
        +<p-panel header="Panel" [style]="{'margin-top':'20px'}">
        +    The story begins as Don Vito Corleone, the head of a New York Mafia family, oversees his daughter's wedding.
        +    His beloved son Michael has just come home from the war, but does not intend to become part of his father's business.
        +    Through Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family,
        +    kind and benevolent to those who give respect,
        +    but given to ruthless violence whenever anything stands against the good of the family.
        +</p-panel>
        +
        +<p-dataTable [style]="{'margin-top':'20px'}" [value]="cars" [rows]="10" [paginator]="true" [pageLinks]="3" [responsive]="true">
        +    <p-header>Cars</p-header>
        +    <p-column field="vin" header="Vin"></p-column>
        +    <p-column field="year" header="Year"></p-column>
        +    <p-column field="brand" header="Brand"></p-column>
        +    <p-column field="color" header="Color"></p-column>
        +</p-dataTable>
        +
        +<p-dataGrid [style]="{'margin-top':'20px','margin-bottom':'20px'}" [value]="cars" [paginator]="true" [rows]="20">
        +    <p-header>
        +        Datagrid
        +    </p-header>
        +    <ng-template let-car pTemplate="item">
        +        <div style="padding:3px" class="ui-g-12 ui-md-3">
        +            <p-panel [header]="car.vin" [style]="{'text-align':'center'}">
        +                <img src="showcase/resources/demo/images/car/{{car.brand}}.gif">
        +                <div class="car-detail">{{car.year}} - {{car.color}}</div>
        +                <hr class="ui-widget-content" style="border-top:0">
        +            </p-panel>
        +        </div>
        +    </ng-template>
        +</p-dataGrid>
        +
        +<p-tree [value]="files" [style]="{'margin-top':'20px','margin-bottom':'20px'}"></p-tree>
        +
        +<p-orderList [value]="cars" [listStyle]="{'height':'250px'}" [style]="{'margin-top':'20px','margin-bottom':'20px'}" [responsive]="true" header="Responsive Cars">
        +    <ng-template let-car pTemplate="item">
        +        <img src="showcase/resources/demo/images/car/{{car.brand}}.gif" style="display:inline-block;margin:2px 0 2px 2px"/>
        +        <div style="font-size:14px;float:right;margin:15px 5px 0 0">{{car.brand}} - {{car.year}} - {{car.color}}</div>
        +    </ng-template>
        +</p-orderList>
        +
        +<p-carousel headerText="Cars" [value]="cars2" [style]="{'margin-top':'20px','margin-bottom':'20px'}">
        +    <ng-template let-car pTemplate="item">
        +        <li class="ui-carousel-item ui-widget-content ui-corner-all">
        +            <div class="ui-g" style="text-align:center">
        +                <div class="ui-g-12"><img src="showcase/resources/demo/images/car/{{car.brand}}.gif" /></div>
        +                
        +                <div class="ui-g-6">Vin</div>
        +                <div class="ui-g-6">{{car.vin}}</div>
        +                
        +                <div class="ui-g-6">Year</div>
        +                <div class="ui-g-6">{{car.year}}</div>
        +
        +                <div class="ui-g-6">Color</div>
        +                <div class="ui-g-6">{{car.color}}</div>
        +            </div>
        +        </li>
        +    </ng-template>
        +</p-carousel>
        +
        +<p-pickList [source]="sourceCars" [target]="targetCars" sourceHeader="Available" targetHeader="Selected" [responsive]="true" 
        +    [sourceStyle]="{'height':'300px'}" [targetStyle]="{'height':'300px'}" [style]="{'margin-top':'20px','margin-bottom':'20px'}">
        +    <ng-template let-car pTemplate="item">
        +        <img src="showcase/resources/demo/images/car/{{car.brand}}.gif" style="display:inline-block;margin:2px 0 2px 2px"/>
        +        <div style="font-size:14px;float:right;margin:15px 5px 0 0">{{car.brand}} - {{car.year}} - {{car.color}}</div>
        +    </ng-template>
        +</p-pickList>
        +<div class="ui-g">
        +    <div class="ui-g-12 ui-md-4">
        +        <p-menu [model]="items1"></p-menu>
        +    </div>
        +    <div class="ui-g-12 ui-md-8">
        +        <p-panelMenu [model]="items2"></p-panelMenu>
        +    </div>
        +</div>
        +
        +
        + +
        +
        +export class ResponsiveDemo implements OnInit {
        +
        +    cities: SelectItem[];
        +
        +    files: TreeNode[];
        +
        +    sourceCars: Car[];
        +
        +    targetCars: Car[];
        +
        +    data: any;
        +
        +    selectedCity: string;
        +
        +    val: string;
        +
        +    options: SelectItem[];
        +
        +    selectedOption: string;
        +
        +    display: boolean = false;
        +
        +    cars: Car[];
        +
        +    cars1: Car[];
        +
        +    cars2: Car[];
        +
        +    cars3: Car[];
        +
        +    date: string;
        +
        +    text: string;
        +
        +    filteredCountriesSingle: any[];
        +    
        +    items1: MenuItem[];
        +    
        +    items2: MenuItem[];
        +    
        +    splitMenuItems: MenuItem[];
        +
        +    showDialog() {
        +        this.display = true;
        +    }
        +
        +    constructor(private carService: CarService, private countryService: CountryService, private nodeService: NodeService) {
        +        this.cars2 = [
        +            {vin: 'r3278r2', year: 2010, brand: 'Audi', color: 'Black'},
        +            {vin: 'jhto2g2', year: 2015, brand: 'BMW', color: 'White'},
        +            {vin: 'h453w54', year: 2012, brand: 'Honda', color: 'Blue'},
        +            {vin: 'g43gwwg', year: 1998, brand: 'Renault', color: 'White'},
        +            {vin: 'gf45wg5', year: 2011, brand: 'VW', color: 'Red'},
        +            {vin: 'bhv5y5w', year: 2015, brand: 'Jaguar', color: 'Blue'},
        +            {vin: 'ybw5fsd', year: 2012, brand: 'Ford', color: 'Yellow'},
        +            {vin: '45665e5', year: 2011, brand: 'Mercedes', color: 'Brown'},
        +            {vin: 'he6sb5v', year: 2015, brand: 'Ford', color: 'Black'}
        +        ];
        +
        +        this.cities = [];
        +        this.cities.push({label:'Select Cities', value:'Select Cities'});
        +        this.cities.push({label:'New York', value:'New York'});
        +        this.cities.push({label:'Rome', value:'Rome'});
        +        this.cities.push({label:'London', value:'London'});
        +        this.cities.push({label:'Istanbul', value:'Istanbul'});
        +        this.cities.push({label:'Paris', value:'Paris'});
        +
        +        this.options = [];
        +        this.options.push({label:'Option 1', value:'Option 1'});
        +        this.options.push({label:'Option 2', value:'Option 2'});
        +        this.options.push({label:'Option 3', value:'Option 3'});
        +        this.options.push({label:'Option 4', value:'Option 4'});
        +        this.options.push({label:'Option 5', value:'Option 5'});
        +
        +        this.data = {
        +            labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
        +            datasets: [
        +                {
        +                    label: 'My First dataset',
        +                    fillColor: 'rgba(220,220,220,0.2)',
        +                    strokeColor: 'rgba(220,220,220,1)',
        +                    pointColor: 'rgba(220,220,220,1)',
        +                    pointStrokeColor: '#fff',
        +                    pointHighlightFill: '#fff',
        +                    pointHighlightStroke: 'rgba(220,220,220,1)',
        +                    data: [65, 59, 80, 81, 56, 55, 40]
        +                },
        +                {
        +                    label: 'My Second dataset',
        +                    fillColor: 'rgba(151,187,205,0.2)',
        +                    strokeColor: 'rgba(151,187,205,1)',
        +                    pointColor: 'rgba(151,187,205,1)',
        +                    pointStrokeColor: '#fff',
        +                    pointHighlightFill: '#fff',
        +                    pointHighlightStroke: 'rgba(151,187,205,1)',
        +                    data: [28, 48, 40, 19, 86, 27, 90]
        +                }
        +            ]
        +        }
        +    }
        +
        +    ngOnInit() {
        +        this.carService.getCarsMedium().then(cars => this.cars = cars);
        +        this.nodeService.getFiles().then(files => this.files = files);
        +        this.carService.getCarsSmall().then(cars1 => this.cars1 = cars1);
        +        this.carService.getCarsSmall().then(cars3 => this.sourceCars = cars3);
        +        this.targetCars = [];
        +        
        +        this.items1 = [{
        +            label: 'File',
        +            items: [
        +                {label: 'New', icon: 'fa-plus'},
        +                {label: 'Open', icon: 'fa-download'}
        +            ]
        +        },
        +        {
        +            label: 'Edit',
        +            items: [
        +                {label: 'Undo', icon: 'fa-refresh'},
        +                {label: 'Redo', icon: 'fa-repeat'}
        +            ]
        +        }];
        +        
        +        this.items2 = [
        +            {
        +                label: 'File',
        +                icon: 'fa-file-o',
        +                items: [{
        +                        label: 'New', 
        +                        icon: 'fa-plus',
        +                        items: [
        +                            {label: 'Project'},
        +                            {label: 'Other'},
        +                        ]
        +                    },
        +                    {label: 'Open'},
        +                    {label: 'Quit'}
        +                ]
        +            },
        +            {
        +                label: 'Edit',
        +                icon: 'fa-edit',
        +                items: [
        +                    {label: 'Undo', icon: 'fa-mail-forward'},
        +                    {label: 'Redo', icon: 'fa-mail-reply'}
        +                ]
        +            },
        +            {
        +                label: 'Help',
        +                icon: 'fa-question',
        +                items: [
        +                    {
        +                        label: 'Contents'
        +                    },
        +                    {
        +                        label: 'Search', 
        +                        icon: 'fa-search', 
        +                        items: [
        +                            {
        +                                label: 'Text', 
        +                                items: [
        +                                    {
        +                                        label: 'Workspace'
        +                                    }
        +                                ]
        +                            },
        +                            {
        +                                label: 'File'
        +                            }
        +                    ]}
        +                ]
        +            },
        +            {
        +                label: 'Actions',
        +                icon: 'fa-gear',
        +                items: [
        +                    {
        +                        label: 'Edit',
        +                        icon: 'fa-refresh',
        +                        items: [
        +                            {label: 'Save', icon: 'fa-save'},
        +                            {label: 'Update', icon: 'fa-save'},
        +                        ]
        +                    },
        +                    {
        +                        label: 'Other',
        +                        icon: 'fa-phone',
        +                        items: [
        +                            {label: 'Delete', icon: 'fa-minus'}
        +                        ]
        +                    }
        +                ]
        +            }
        +        ];
        +        
        +        this.splitMenuItems = [
        +            {label: 'Update', icon: 'fa-refresh'},
        +            {label: 'Delete', icon: 'fa-close'},
        +            {label: 'Angular.io', icon: 'fa-link', url: 'http://angular.io'},
        +            {label: 'Theming', icon: 'fa-paint-brush', routerLink: ['/theming']}
        +        ];
        +    }
        +
        +    filterCountrySingle(event) {
        +        let query = event.query;
        +        this.countryService.getCountries().then(countries => {
        +            this.filteredCountriesSingle = this.filterCountry(query, countries);
        +        });
        +    }
        +
        +    filterCountry(query, countries: any[]):any[] {
        +        //in a real application, make a request to a remote url with the query and return filtered results, for demo we filter at client side
        +        let filtered : any[] = [];
        +        for(let i = 0; i < countries.length; i++) {
        +            let country = countries[i];
        +            if(country.name.toLowerCase().indexOf(query.toLowerCase()) == 0) {
        +                filtered.push(country);
        +            }
        +        }
        +        return filtered;
        +    }
        +
        +}
        +
        +
        + + +
        +
        +
        diff --git a/src/app/showcase/components/responsive/responsivedemo.module.ts b/src/app/showcase/components/responsive/responsivedemo.module.ts new file mode 100644 index 00000000000..f3597be6431 --- /dev/null +++ b/src/app/showcase/components/responsive/responsivedemo.module.ts @@ -0,0 +1,60 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {ResponsiveDemo} from './responsivedemo'; +import {ResponsiveDemoRoutingModule} from './responsivedemo-routing.module'; +import {InputTextModule} from '../../../components/inputtext/inputtext'; +import {InputTextareaModule} from '../../../components/inputtextarea/inputtextarea'; +import {CalendarModule} from '../../../components/calendar/calendar'; +import {AutoCompleteModule} from '../../../components/autocomplete/autocomplete'; +import {ButtonModule} from '../../../components/button/button'; +import {SplitButtonModule} from '../../../components/splitbutton/splitbutton'; +import {DropdownModule} from '../../../components/dropdown/dropdown'; +import {PasswordModule} from '../../../components/password/password'; +import {ListboxModule} from '../../../components/listbox/listbox'; +import {RadioButtonModule} from '../../../components/radiobutton/radiobutton'; +import {DialogModule} from '../../../components/dialog/dialog'; +import {PanelModule} from '../../../components/panel/panel'; +import {DataTableModule} from '../../../components/datatable/datatable'; +import {DataGridModule} from '../../../components/datagrid/datagrid'; +import {CarouselModule} from '../../../components/carousel/carousel'; +import {OrderListModule} from '../../../components/orderlist/orderlist'; +import {PickListModule} from '../../../components/picklist/picklist'; +import {MenuModule} from '../../../components/menu/menu'; +import {PanelMenuModule} from '../../../components/panelmenu/panelmenu'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {TreeModule} from '../../../components/tree/tree'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + ResponsiveDemoRoutingModule, + InputTextModule, + InputTextareaModule, + CalendarModule, + AutoCompleteModule, + SplitButtonModule, + PasswordModule, + DropdownModule, + ListboxModule, + RadioButtonModule, + DialogModule, + PanelModule, + DataTableModule, + DataGridModule, + CarouselModule, + OrderListModule, + PickListModule, + MenuModule, + PanelMenuModule, + TreeModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + ResponsiveDemo + ] +}) +export class ResponsiveDemoModule {} diff --git a/src/app/showcase/components/responsive/responsivedemo.ts b/src/app/showcase/components/responsive/responsivedemo.ts new file mode 100644 index 00000000000..009a82ba5ce --- /dev/null +++ b/src/app/showcase/components/responsive/responsivedemo.ts @@ -0,0 +1,243 @@ +import {Component,OnInit,ViewEncapsulation} from '@angular/core'; +import {Car} from '../../components/domain/car'; +import {CarService} from '../../service/carservice'; +import {NodeService} from '../../service/nodeservice'; +import {CountryService} from '../../service/countryservice'; +import {SelectItem,MenuItem,TreeNode} from '../../../components/common/api'; + +@Component({ + templateUrl: './responsivedemo.html', + styles: [` + .ui-datagrid .ui-datagrid-column { + text-align: center; + } + + .radiobuttons > * { + vertical-align: middle; + } + `], + encapsulation: ViewEncapsulation.None +}) +export class ResponsiveDemo implements OnInit { + + cities: SelectItem[]; + + files: TreeNode[]; + + sourceCars: Car[]; + + targetCars: Car[]; + + data: any; + + selectedCity: string; + + val: string; + + options: SelectItem[]; + + selectedOption: string; + + display: boolean = false; + + cars: Car[]; + + cars1: Car[]; + + cars2: Car[]; + + cars3: Car[]; + + date: string; + + text: string; + + filteredCountriesSingle: any[]; + + items1: MenuItem[]; + + items2: MenuItem[]; + + splitMenuItems: MenuItem[]; + + showDialog() { + this.display = true; + } + + constructor(private carService: CarService, private countryService: CountryService, private nodeService: NodeService) { + this.cars2 = [ + {vin: 'r3278r2', year: 2010, brand: 'Audi', color: 'Black'}, + {vin: 'jhto2g2', year: 2015, brand: 'BMW', color: 'White'}, + {vin: 'h453w54', year: 2012, brand: 'Honda', color: 'Blue'}, + {vin: 'g43gwwg', year: 1998, brand: 'Renault', color: 'White'}, + {vin: 'gf45wg5', year: 2011, brand: 'VW', color: 'Red'}, + {vin: 'bhv5y5w', year: 2015, brand: 'Jaguar', color: 'Blue'}, + {vin: 'ybw5fsd', year: 2012, brand: 'Ford', color: 'Yellow'}, + {vin: '45665e5', year: 2011, brand: 'Mercedes', color: 'Brown'}, + {vin: 'he6sb5v', year: 2015, brand: 'Ford', color: 'Black'} + ]; + + this.cities = []; + this.cities.push({label:'Select Cities', value:'Select Cities'}); + this.cities.push({label:'New York', value:'New York'}); + this.cities.push({label:'Rome', value:'Rome'}); + this.cities.push({label:'London', value:'London'}); + this.cities.push({label:'Istanbul', value:'Istanbul'}); + this.cities.push({label:'Paris', value:'Paris'}); + + this.options = []; + this.options.push({label:'Option 1', value:'Option 1'}); + this.options.push({label:'Option 2', value:'Option 2'}); + this.options.push({label:'Option 3', value:'Option 3'}); + this.options.push({label:'Option 4', value:'Option 4'}); + this.options.push({label:'Option 5', value:'Option 5'}); + + this.data = { + labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], + datasets: [ + { + label: 'My First dataset', + fillColor: 'rgba(220,220,220,0.2)', + strokeColor: 'rgba(220,220,220,1)', + pointColor: 'rgba(220,220,220,1)', + pointStrokeColor: '#fff', + pointHighlightFill: '#fff', + pointHighlightStroke: 'rgba(220,220,220,1)', + data: [65, 59, 80, 81, 56, 55, 40] + }, + { + label: 'My Second dataset', + fillColor: 'rgba(151,187,205,0.2)', + strokeColor: 'rgba(151,187,205,1)', + pointColor: 'rgba(151,187,205,1)', + pointStrokeColor: '#fff', + pointHighlightFill: '#fff', + pointHighlightStroke: 'rgba(151,187,205,1)', + data: [28, 48, 40, 19, 86, 27, 90] + } + ] + } + } + + ngOnInit() { + this.carService.getCarsMedium().then(cars => this.cars = cars); + this.nodeService.getFiles().then(files => this.files = files); + this.carService.getCarsSmall().then(cars1 => this.cars1 = cars1); + this.carService.getCarsSmall().then(cars3 => this.sourceCars = cars3); + this.targetCars = []; + + this.items1 = [{ + label: 'File', + items: [ + {label: 'New', icon: 'fa-plus'}, + {label: 'Open', icon: 'fa-download'} + ] + }, + { + label: 'Edit', + items: [ + {label: 'Undo', icon: 'fa-refresh'}, + {label: 'Redo', icon: 'fa-repeat'} + ] + }]; + + this.items2 = [ + { + label: 'File', + icon: 'fa-file-o', + items: [{ + label: 'New', + icon: 'fa-plus', + items: [ + {label: 'Project'}, + {label: 'Other'}, + ] + }, + {label: 'Open'}, + {label: 'Quit'} + ] + }, + { + label: 'Edit', + icon: 'fa-edit', + items: [ + {label: 'Undo', icon: 'fa-mail-forward'}, + {label: 'Redo', icon: 'fa-mail-reply'} + ] + }, + { + label: 'Help', + icon: 'fa-question', + items: [ + { + label: 'Contents' + }, + { + label: 'Search', + icon: 'fa-search', + items: [ + { + label: 'Text', + items: [ + { + label: 'Workspace' + } + ] + }, + { + label: 'File' + } + ]} + ] + }, + { + label: 'Actions', + icon: 'fa-gear', + items: [ + { + label: 'Edit', + icon: 'fa-refresh', + items: [ + {label: 'Save', icon: 'fa-save'}, + {label: 'Update', icon: 'fa-save'}, + ] + }, + { + label: 'Other', + icon: 'fa-phone', + items: [ + {label: 'Delete', icon: 'fa-minus'} + ] + } + ] + } + ]; + + this.splitMenuItems = [ + {label: 'Update', icon: 'fa-refresh'}, + {label: 'Delete', icon: 'fa-close'}, + {label: 'Angular.io', icon: 'fa-link', url: 'http://angular.io'}, + {label: 'Theming', icon: 'fa-paint-brush', routerLink: ['/theming']} + ]; + } + + filterCountrySingle(event) { + let query = event.query; + this.countryService.getCountries().then(countries => { + this.filteredCountriesSingle = this.filterCountry(query, countries); + }); + } + + filterCountry(query, countries: any[]):any[] { + //in a real application, make a request to a remote url with the query and return filtered results, for demo we filter at client side + let filtered : any[] = []; + for(let i = 0; i < countries.length; i++) { + let country = countries[i]; + if(country.name.toLowerCase().indexOf(query.toLowerCase()) == 0) { + filtered.push(country); + } + } + return filtered; + } + +} diff --git a/src/app/showcase/components/rtl/rtldemo-routing.module.ts b/src/app/showcase/components/rtl/rtldemo-routing.module.ts new file mode 100644 index 00000000000..374dfadc29c --- /dev/null +++ b/src/app/showcase/components/rtl/rtldemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {RTLDemo} from './rtldemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: RTLDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class RTLDemoRoutingModule {} diff --git a/src/app/showcase/components/rtl/rtldemo.html b/src/app/showcase/components/rtl/rtldemo.html new file mode 100644 index 00000000000..410d8355fbd --- /dev/null +++ b/src/app/showcase/components/rtl/rtldemo.html @@ -0,0 +1,114 @@ +
        +
        + RTL + RTL is enabled by adding "ui-rtl" style class along with dir="rtl" to an ancestor element of PrimeNG components. +
        +
        + +
        +
        +

        Input

        + + +

        Dialog

        + + The story begins as Don Vito Corleone, the head of a New York Mafia family, oversees his daughter's wedding. + His beloved son Michael has just come home from the war, but does not intend to become part of his father's business. + Through Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, + kind and benevolent to those who give respect, + but given to ruthless violence whenever anything stands against the good of the family. + +
        + + +
        +
        +
        + + + +

        Accordion

        + + + The story begins as Don Vito Corleone, the head of a New York Mafia family, overseeshis daughter's wedding. His beloved son ichael has just come home from the war, but does not intend to become part of his father's business. T hrough Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, kind and benevolent to those who give respect, but given to ruthless violence whenever anything stands against the good of the family. + + + Francis Ford Coppola's legendary continuation and sequel to his landmark 1972 film, The_Godfather parallels the young Vito Corleone's rise with his son Michael's spiritual fall, deepening The_Godfather's depiction of the dark side of the American dream. In the early 1900s, the child Vito flees his Sicilian village for America after the local Mafia kills his family. Vito struggles to make a living, legally or illegally, for his wife and growing brood in Little Italy, killing the local Black Hand Fanucci after he demands his customary cut of the tyro's business. With Fanucci gone, Vito's communal stature grows. + + + After a break of more than 15 years, director Francis Ford Coppola and writer Mario Puzo returned to the well for this third and final story of the fictional Corleone crime family. Two decades have passed, and crime kingpin Michael Corleone, now divorced from his wife Kay has nearly succeeded in keeping his promise that his family would one day be completely legitimate. + + + +

        TabView

        + + + The story begi ns as Don Vito Corleone, the head of a New York Mafia family, overseeshis daughter's wedding. His beloved son ichael has just come home from the war, but does not intend to become part of his father's business. T hrough Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, kind and benevolent to those who give respect, but given to ruthless violence whenever anything stands against the good of the family. + + + Francis Ford Coppola's legendary continuation and sequel to his landmark 1972 film, The_Godfather parallels the young Vito Corleone's rise with his son Michael's spiritual fall, deepening The_Godfather's depiction of the dark side of the American dream. In the early 1900s, the child Vito flees his Sicilian village for America after the local Mafia kills his family. Vito struggles to make a living, legally or illegally, for his wife and growing brood in Little Italy, killing the local Black Hand Fanucci after he demands his customary cut of the tyro's business. With Fanucci gone, Vito's communal stature grows. + + + After a break of more than 15 years, director Francis Ford Coppola and writer Mario Puzo returned to the well for this third and final story of the fictional Corleone crime family. Two decades have passed, and crime kingpin Michael Corleone, now divorced from his wife Kay has nearly succeeded in keeping his promise that his family would one day be completely legitimate. + + +
        +
        + +
        + + +
        +
        +<div class="ui-rtl" dir="rtl">
        +    <h3 class="first">Input</h3>
        +    <input id="in" type="text" size="30" pInputText>
        +
        +    <h3>Dialog</h3>
        +    <p-dialog header="Godfather I" [(visible)]="display" modal="modal" width="350" [responsive]="true">
        +        <span>The story begins as Don Vito Corleone, the head of a New York Mafia family, oversees his daughter's wedding. 
        +           His beloved son Michael has just come home from the war, but does not intend to become part of his father's business. 
        +           Through Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, 
        +           kind and benevolent to those who give respect,
        +           but given to ruthless violence whenever anything stands against the good of the family.</span>
        +        <p-footer>
        +            <div class="ui-dialog-buttonpane ui-helper-clearfix">
        +                <button type="button" pButton icon="fa-close" (click)="display=false" label="No"></button>
        +                <button type="button" pButton icon="fa-check" (click)="display=false" label="Yes"></button>
        +            </div>
        +        </p-footer>
        +    </p-dialog>
        +
        +    <button type="text" (click)="showDialog()" pButton icon="fa-external-link-square" label="Show"></button>
        +    
        +    <h3>Accordion</h3>
        +    <p-accordion>
        +        <p-accordionTab header="Godfather I" [selected]="true">
        +            The story begins as Don Vito Corleone, the head of a New York Mafia family, overseeshis daughter's wedding. His beloved son ichael has just come home from the war, but does not intend to become part of his father's business. T hrough Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, kind and benevolent to those who give respect, but given to ruthless violence whenever anything stands against the good of the family.
        +        </p-accordionTab>
        +        <p-accordionTab header="Godfather II">
        +            Francis Ford Coppola's legendary continuation and sequel to his landmark 1972 film, The_Godfather parallels the young Vito Corleone's rise with his son Michael's spiritual fall, deepening The_Godfather's depiction of the dark side of the American dream. In the early 1900s, the child Vito flees his Sicilian village for America after the local Mafia kills his family. Vito struggles to make a living, legally or illegally, for his wife and growing brood in Little Italy, killing the local Black Hand Fanucci after he demands his customary cut of the tyro's business. With Fanucci gone, Vito's communal stature grows.
        +        </p-accordionTab>
        +        <p-accordionTab header="Godfather III">
        +            After a break of more than  15 years, director Francis Ford Coppola and writer Mario Puzo returned to the well for this third and final story of the fictional Corleone crime family. Two decades have passed, and crime kingpin Michael Corleone, now divorced from his wife Kay has nearly succeeded in keeping his promise that his family would one day be completely legitimate.
        +        </p-accordionTab>
        +    </p-accordion>
        +    
        +    <h3>TabView</h3>
        +    <p-tabView>
        +        <p-tabPanel header="Godfather I">
        +            The story begins as Don Vito Corleone, the head of a New York Mafia family, overseeshis daughter's wedding. His beloved son ichael has just come home from the war, but does not intend to become part of his father's business. T hrough Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, kind and benevolent to those who give respect, but given to ruthless violence whenever anything stands against the good of the family.
        +        </p-tabPanel>
        +        <p-tabPanel header="Godfather II">
        +            Francis Ford Coppola's legendary continuation and sequel to his landmark 1972 film, The_Godfather parallels the young Vito Corleone's rise with his son Michael's spiritual fall, deepening The_Godfather's depiction of the dark side of the American dream. In the early 1900s, the child Vito flees his Sicilian village for America after the local Mafia kills his family. Vito struggles to make a living, legally or illegally, for his wife and growing brood in Little Italy, killing the local Black Hand Fanucci after he demands his customary cut of the tyro's business. With Fanucci gone, Vito's communal stature grows.
        +        </p-tabPanel>
        +        <p-tabPanel header="Godfather III">
        +            After a break of more than  15 years, director Francis Ford Coppola and writer Mario Puzo returned to the well for this third and final story of the fictional Corleone crime family. Two decades have passed, and crime kingpin Michael Corleone, now divorced from his wife Kay has nearly succeeded in keeping his promise that his family would one day be completely legitimate.
        +        </p-tabPanel>
        +    </p-tabView>
        +</div>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/rtl/rtldemo.module.ts b/src/app/showcase/components/rtl/rtldemo.module.ts new file mode 100644 index 00000000000..c547d76e159 --- /dev/null +++ b/src/app/showcase/components/rtl/rtldemo.module.ts @@ -0,0 +1,29 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {RTLDemo} from './rtldemo'; +import {RTLDemoRoutingModule} from './rtldemo-routing.module'; +import {DialogModule} from '../../../components/dialog/dialog'; +import {InputTextModule} from '../../../components/inputtext/inputtext'; +import {ButtonModule} from '../../../components/button/button'; +import {AccordionModule} from '../../../components/accordion/accordion'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + RTLDemoRoutingModule, + FormsModule, + DialogModule, + ButtonModule, + InputTextModule, + AccordionModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + RTLDemo + ] +}) +export class RTLDemoModule {} diff --git a/src/app/showcase/components/rtl/rtldemo.ts b/src/app/showcase/components/rtl/rtldemo.ts new file mode 100644 index 00000000000..d1c5d407fe8 --- /dev/null +++ b/src/app/showcase/components/rtl/rtldemo.ts @@ -0,0 +1,9 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './rtldemo.html' +}) +export class RTLDemo { + + visible: boolean; +} \ No newline at end of file diff --git a/src/app/showcase/components/schedule/scheduledemo-routing.module.ts b/src/app/showcase/components/schedule/scheduledemo-routing.module.ts new file mode 100644 index 00000000000..6694af9325e --- /dev/null +++ b/src/app/showcase/components/schedule/scheduledemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {ScheduleDemo} from './scheduledemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: ScheduleDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class ScheduleDemoRoutingModule {} diff --git a/src/app/showcase/components/schedule/scheduledemo.html b/src/app/showcase/components/schedule/scheduledemo.html new file mode 100644 index 00000000000..16df754f7d8 --- /dev/null +++ b/src/app/showcase/components/schedule/scheduledemo.html @@ -0,0 +1,735 @@ +
        +
        + Schedule + Schedule is an event calendar based on FullCalendar. This sample demonstrates a crud scenario using a Dialog. +
        +
        + +
        + + + +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        + +
        + + +
        +
        +
        +
        + +
        + + +

        Import

        +
        +
        +import {ScheduleModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Schedule is based on FullCalendar. For a complete documentation and samples please refer to the fullcalendar website. + Events of schedule should be an array and defined using the events property.

        +
        +
        +<p-schedule [events]="events"></p-schedule>
        +
        +
        + +
        +
        +export class MyModel {
        +
        +    events: any[];
        +
        +    ngOnInit() {
        +        this.events = [
        +            {
        +                "title": "All Day Event",
        +                "start": "2016-01-01"
        +            },
        +            {
        +                "title": "Long Event",
        +                "start": "2016-01-07",
        +                "end": "2016-01-10"
        +            },
        +            {
        +                "title": "Repeating Event",
        +                "start": "2016-01-09T16:00:00"
        +            },
        +            {
        +                "title": "Repeating Event",
        +                "start": "2016-01-16T16:00:00"
        +            },
        +            {
        +                "title": "Conference",
        +                "start": "2016-01-11",
        +                "end": "2016-01-13"
        +            }
        +        ];
        +    }
        +    
        +}
        +
        +
        +

        In a real application, it is likely to populate the events by making a service call, when the events are updated, schedule component will detect the change and render them.

        +
        +
        +@Injectable()
        +export class EventService {
        +    
        +    constructor(private http: Http) {}
        +
        +    getEvents() {
        +        return this.http.get('showcase/resources/data/scheduleevents.json')
        +                    .toPromise()
        +                    .then(res => <any[]> res.json().data)
        +                    .then(data => { return data; });
        +    }
        +}
        +
        +
        + +
        +
        +export class MyModel {
        +
        +    events: any[];
        +
        +    ngOnInit() {
        +        this.eventService.getEvents().then(events => {this.events = events;});
        +    }
        +    
        +}
        +
        +
        + +

        Lazy Loading

        +

        onViewRender call is used to implement lazy loading which is triggered when a new date-range is rendered or when the view type changes.

        +
        +
        +<p-schedule [events]="events" (onViewRender)="loadEvents($event)"></p-schedule>
        +
        +
        + +
        +
        +loadEvents(event) {
        +    let start = event.view.start
        +    let end = event.view.end
        +    this.events = this.eventService.getEvents().then(events => {this.events = events;});
        +}
        +
        +
        + + +

        Event API

        +

        Event object has various properties to define an event, refer to official documentation for the whole list.

        + +

        Header Customization

        +

        Header is customized using the header property that takes an object as its value. Default configuration is;

        +
        +
        +{
        +    left:   'title',
        +    center: '',
        +    right:  'today prev,next'
        +}
        +
        +
        + +

        Here is a customized version of header.

        +
        +
        +<p-schedule [events]="events" [header]="headerConfig"></p-schedule>
        +
        +
        + +
        +
        +export class MyModel {
        +
        +    events: any[];
        +    
        +    headerConfig: any;
        +
        +    ngOnInit() {
        +        this.headerConfig = {
        +			left: 'prev,next today',
        +			center: 'title',
        +			right: 'month,agendaWeek,agendaDay'
        +		};
        +    }
        +    
        +}
        +
        +
        + +

        Localization

        +

        Localization for different languages and formats is defined by binding the settings object to the locale property. + Following is a schedule with Spanish month names.

        +
        +
        +<p-schedule [events]="events" locale="es"></p-schedule>
        +
        +
        + +

        Visit the fullcalendar documentation to get the available locales.

        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDescription
        eventsarrayAn array of events to display.
        headerobjectRead more
        isRTLbooleanRead more
        weekendsbooleanRead more
        hiddenDaysarrayRead more
        localeobjectRead more
        fixedWeekCountbooleanRead more
        weekNumbersbooleanRead more
        businessHoursanyRead more
        heightanyRead more
        contentHeightanyRead more
        aspectRatioanyRead more
        eventLimitanyRead more
        defaultDateanyRead more
        editablebooleanRead more
        droppablebooleanRead more
        eventStartEditablebooleanRead more
        eventDurationEditablebooleanRead more
        defaultViewstringRead more
        allDaySlotbooleanRead more
        allDayTextstringRead more
        slotDurationDurationRead more
        slotLabelIntervalDurationRead more
        snapDurationDurationRead more
        scrollTimeDurationRead more
        minTimeDurationRead more
        maxTimeDurationRead more
        slotEventOverlapbooleanRead more
        nowIndicatorbooleanRead more
        dragRevertDurationnumberRead more
        dragOpacitynumberRead more
        dragScrollbooleanRead more
        eventOverlapanyRead more
        eventConstraintanyRead more
        eventRenderFunctionRead more
        dayRenderFunctionRead more
        timezoneboolean|stringRead more
        timeFormatstringRead more
        optionsObjectA configuration object to define properties of FullCalendar that do not have a corresponding option in schedule.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameDescription
        onDayClickRead more
        onEventClickRead more
        onEventMouseoverRead more
        onEventMouseoutRead more
        onEventDragStartRead more
        onEventDragStopRead more
        onEventDropRead more
        onEventResizeStartRead more
        onEventResizeStopRead more
        onEventResizeRead more
        onViewRenderRead more
        onDropRead more
        +
        + +
        +
        +<p-schedule [events]="events" [header]="headerConfig" (onEventClick)="handleEventClick($event)"></p-schedule>
        +
        +
        + +
        +
        +export class MyModel {
        +
        +    handleEventClick(e) {
        +        //e.event = Selected event
        +        //e.jsEvent = Browser click event
        +        //e.view = Current view object
        +    }
        +    
        +}
        +
        +
        + +

        Methods

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        prev()-Read more
        next()-Read more
        prevYear()-Read more
        nextYear()-Read more
        today()-Read more
        gotoDate(date)date: Date to navigateRead more
        incrementDate(duration)duration: Duration to add to current dateRead more
        getDate()-Read more
        changeView(viewName)viewName: A valid view string to change toRead more
        +
        + +
        +
        +<p-schedule [events]="events" #fc></p-schedule>
        +
        +<button type="button" pButton (click)="back(fc)"></p-button>
        +
        +
        + +
        +
        +export class MyModel {
        +
        +    back(fc) {
        +        fc.prev();
        +    }
        +    
        +}
        +
        +
        + +

        Dependencies

        +

        FullCalendar.

        +
        + + +
        +
        +<p-schedule [events]="events" [header]="header" defaultDate="2017-02-01" [eventLimit]="4" [editable]="true"
        +            (onDayClick)="handleDayClick($event)" (onEventClick)="handleEventClick($event)"></p-schedule>
        +
        +<p-dialog header="Event Details" [(visible)]="dialogVisible" [responsive]="true" showEffect="fade" [modal]="false" [contentStyle]="{'overflow':'visible'}"
        +    [style]="{'overflow':'visible'}" [resizable]="false">
        +    <div class="ui-grid ui-grid-responsive ui-fluid" *ngIf="event">
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4"><label for="vin">Title</label></div>
        +            <div class="ui-grid-col-8"><input pInputText id="title" [(ngModel)]="event.title" /></div>
        +        </div>
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4"><label for="start">Start</label></div>
        +            <div class="ui-grid-col-8"><p-calendar [(ngModel)]="event.start" dateFormat="yy-mm-dd" dataType="string"></p-calendar></div>
        +        </div>
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4"><label for="end">End</label></div>
        +            <div class="ui-grid-col-8"><p-calendar [(ngModel)]="event.end" dateFormat="yy-mm-dd" dataType="string"></p-calendar></div>
        +        </div>
        +        <div class="ui-grid-row">
        +            <div class="ui-grid-col-4"><label for="allday">All Day</label></div>
        +            <div class="ui-grid-col-8"><p-checkbox [(ngModel)]="event.allDay" binary="checkbox"></p-checkbox></div>
        +        </div>
        +    </div>
        +    <p-footer>
        +        <div class="ui-dialog-buttonpane ui-helper-clearfix">
        +            <button type="button" pButton icon="fa-close" (click)="deleteEvent()" label="Delete" [disabled]="!event?.id"></button>
        +            <button type="button" pButton icon="fa-check" (click)="saveEvent()" label="Save" [disabled]="!event?.start"></button>
        +        </div>
        +    </p-footer>
        +</p-dialog>
        +
        +
        + +
        +
        +export class ScheduleDemo implements OnInit {
        +
        +    events: any[];
        +    
        +    header: any;
        +    
        +    event: MyEvent;
        +    
        +    dialogVisible: boolean = false;
        +    
        +    idGen: number = 100;
        +    
        +    constructor(private eventService: EventService, private cd: ChangeDetectorRef) { }
        +
        +    ngOnInit() {
        +        this.eventService.getEvents().then(events => {this.events = events;});
        +        
        +        this.header = {
        +			left: 'prev,next today',
        +			center: 'title',
        +			right: 'month,agendaWeek,agendaDay'
        +		};
        +    }
        +    
        +    handleDayClick(event) {
        +        this.event = new MyEvent();
        +        this.event.start = event.date.format();
        +        this.dialogVisible = true;
        +        
        +        //trigger detection manually as somehow only moving the mouse quickly after click triggers the automatic detection
        +        this.cd.detectChanges();
        +    }
        +    
        +    handleEventClick(e) {
        +        this.event = new MyEvent();
        +        this.event.title = e.calEvent.title;
        +        
        +        let start = e.calEvent.start;
        +        let end = e.calEvent.end;
        +        if(e.view.name === 'month') {
        +            start.stripTime();
        +        }
        +        
        +        if(end) {
        +            end.stripTime();
        +            this.event.end = end.format();
        +        }
        +
        +        this.event.id = e.calEvent.id;
        +        this.event.start = start.format();
        +        this.event.allDay = e.calEvent.allDay;
        +        this.dialogVisible = true;
        +    }
        +    
        +    saveEvent() {
        +        //update
        +        if(this.event.id) {
        +            let index: number = this.findEventIndexById(this.event.id);
        +            if(index >= 0) {
        +                this.events[index] = this.event;
        +            }
        +        }
        +        //new
        +        else {
        +            this.event.id = this.idGen++;
        +            this.events.push(this.event);
        +            this.event = null;
        +        }
        +        
        +        this.dialogVisible = false;
        +    }
        +    
        +    deleteEvent() {
        +        let index: number = this.findEventIndexById(this.event.id);
        +        if(index >= 0) {
        +            this.events.splice(index, 1);
        +        }
        +        this.dialogVisible = false;
        +    }
        +    
        +    findEventIndexById(id: number) {
        +        let index = -1;
        +        for(let i = 0; i < this.events.length; i++) {
        +            if(id == this.events[i].id) {
        +                index = i;
        +                break;
        +            }
        +        }
        +        
        +        return index;
        +    }
        +}
        +
        +export class MyEvent {
        +    id: number;
        +    title: string;
        +    start: string;
        +    end: string;
        +    allDay: boolean = true;
        +}
        +
        +
        + +
        +
        +@Injectable()
        +export class EventService {
        +    
        +    constructor(private http: Http) {}
        +
        +    getEvents() {
        +        return this.http.get('showcase/resources/data/scheduleevents.json')
        +                    .toPromise()
        +                    .then(res => <any[]> res.json().data)
        +                    .then(data => { return data; });
        +    }
        +}
        +
        +
        +
        +
        +
        diff --git a/src/app/showcase/components/schedule/scheduledemo.module.ts b/src/app/showcase/components/schedule/scheduledemo.module.ts new file mode 100644 index 00000000000..7b0b610cc03 --- /dev/null +++ b/src/app/showcase/components/schedule/scheduledemo.module.ts @@ -0,0 +1,33 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {ScheduleDemo} from './scheduledemo'; +import {ScheduleDemoRoutingModule} from './scheduledemo-routing.module'; +import {ScheduleModule} from '../../../components/schedule/schedule'; +import {DialogModule} from '../../../components/dialog/dialog'; +import {InputTextModule} from '../../../components/inputtext/inputtext'; +import {CalendarModule} from '../../../components/calendar/calendar'; +import {CheckboxModule} from '../../../components/checkbox/checkbox'; +import {ButtonModule} from '../../../components/button/button'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + ScheduleDemoRoutingModule, + ScheduleModule, + DialogModule, + InputTextModule, + CalendarModule, + CheckboxModule, + ButtonModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + ScheduleDemo + ] +}) +export class ScheduleDemoModule {} diff --git a/src/app/showcase/components/schedule/scheduledemo.ts b/src/app/showcase/components/schedule/scheduledemo.ts new file mode 100644 index 00000000000..a18ef39ca85 --- /dev/null +++ b/src/app/showcase/components/schedule/scheduledemo.ts @@ -0,0 +1,112 @@ +import {Component,OnInit} from '@angular/core'; +import {EventService} from '../../service/eventservice'; + +@Component({ + templateUrl: './scheduledemo.html', + styles: [` + .ui-grid-row div { + padding: 4px 10px + } + + .ui-grid-row div label { + font-weight: bold; + } + `] +}) +export class ScheduleDemo implements OnInit { + + events: any[]; + + header: any; + + event: MyEvent; + + dialogVisible: boolean = false; + + idGen: number = 100; + + constructor(private eventService: EventService) { } + + ngOnInit() { + this.eventService.getEvents().then(events => {this.events = events;}); + + this.header = { + left: 'prev,next today', + center: 'title', + right: 'month,agendaWeek,agendaDay' + }; + } + + handleDayClick(event) { + this.event = new MyEvent(); + this.event.start = event.date.format(); + this.dialogVisible = true; + } + + handleEventClick(e) { + this.event = new MyEvent(); + this.event.title = e.calEvent.title; + + let start = e.calEvent.start; + let end = e.calEvent.end; + if(e.view.name === 'month') { + start.stripTime(); + } + + if(end) { + end.stripTime(); + this.event.end = end.format(); + } + + this.event.id = e.calEvent.id; + this.event.start = start.format(); + this.event.allDay = e.calEvent.allDay; + this.dialogVisible = true; + } + + saveEvent() { + //update + if(this.event.id) { + let index: number = this.findEventIndexById(this.event.id); + if(index >= 0) { + this.events[index] = this.event; + } + } + //new + else { + this.event.id = this.idGen++; + this.events.push(this.event); + this.event = null; + } + + this.dialogVisible = false; + } + + deleteEvent() { + let index: number = this.findEventIndexById(this.event.id); + if(index >= 0) { + this.events.splice(index, 1); + } + this.dialogVisible = false; + } + + findEventIndexById(id: number) { + let index = -1; + for(let i = 0; i < this.events.length; i++) { + if(id == this.events[i].id) { + index = i; + break; + } + } + + return index; + } +} + +export class MyEvent { + id: number; + title: string; + start: string; + end: string; + allDay: boolean = true; +} \ No newline at end of file diff --git a/src/app/showcase/components/selectbutton/selectbuttondemo-routing.module.ts b/src/app/showcase/components/selectbutton/selectbuttondemo-routing.module.ts new file mode 100644 index 00000000000..02c702716e0 --- /dev/null +++ b/src/app/showcase/components/selectbutton/selectbuttondemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {SelectButtonDemo} from './selectbuttondemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: SelectButtonDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class SelectButtonDemoRoutingModule {} diff --git a/src/app/showcase/components/selectbutton/selectbuttondemo.html b/src/app/showcase/components/selectbutton/selectbuttondemo.html new file mode 100644 index 00000000000..d143ae1d6c2 --- /dev/null +++ b/src/app/showcase/components/selectbutton/selectbuttondemo.html @@ -0,0 +1,227 @@ +
        +
        + SelectButton + SelectButton is used to choose single or multiple items from a list using buttons. +
        +
        + +
        +

        Single

        + + +

        Selected Type: {{selectedType}}

        + +

        Multiple

        + +

        Selected Types: {{type}}

        + +
        + + +
        + +
        + + +

        Import

        +
        +
        +import {SelectButtonModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Two-way value binding is defined using ngModel and selectbutton requires a collection of options + where each option should follow the SelectItem interface that defines label-value properties.

        +
        +
        +<p-selectButton [options]="cities" [(ngModel)]="selectedCity"></p-selectButton>
        +
        +
        + +
        +
        +import {SelectItem} from 'primeng/primeng';
        +
        +export class MyModel {
        +
        +    cities: SelectItem[];
        +
        +    selectedCity: string;
        +
        +    constructor() {
        +        this.cities = [];
        +        this.cities.push({label:'New York', value:'New York'});
        +        this.cities.push({label:'Rome', value:'Rome'});
        +        this.cities.push({label:'London', value:'London'});
        +        this.cities.push({label:'Istanbul', value:'Istanbul'});
        +        this.cities.push({label:'Paris', value:'Paris'});
        +    }
        +
        +}
        +
        +
        + +

        Multiple

        +

        SelectButton allows selecting only one item by default and setting multiple option enables choosing more than one item. + In multiple case, model property should be an array instance that is not null or undefined.

        +
        +
        +<p-selectButton [options]="cities" [(ngModel)]="selectedCities"></p-selectButton>
        +
        +
        + +
        +
        +import {SelectItem} from 'primeng/primeng';
        +
        +export class MyModel {
        +
        +    cities: SelectItem[];
        +
        +    selectedCities: string[] = [];
        +
        +    constructor() {
        +        this.cities = [];
        +        this.cities.push({label:'New York', value:'New York'});
        +        this.cities.push({label:'Rome', value:'Rome'});
        +        this.cities.push({label:'London', value:'London'});
        +        this.cities.push({label:'Istanbul', value:'Istanbul'});
        +        this.cities.push({label:'Paris', value:'Paris'});
        +    }
        +
        +}
        +
        +
        + +

        Model Driven Forms

        +

        SelectButton can be used in a model driven form as well.

        +
        +
        +<p-selectButton [options]="cities" formControlName="selectedCity"></p-selectButton>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        optionsarraynullAn array of selectitems to display as the available options.
        multiplebooleanfalseWhen specified, allows selecting multiple values.
        tabindexnumbernullIndex of the element in tabbing order.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        disabledbooleanfalseWhen present, it specifies that the element should be disabled.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + +
        NameParametersDescription
        onChangeevent.originalEvent: browser event
        + event.value: single value or an array of values that are selected +
        Callback to invoke when value changes.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<h3 class="first">Single</h3>
        +<p-selectButton [options]="types" [(ngModel)]="selectedType"></p-selectButton>
        +
        +<p>Selected Type: {{selectedType}}</p>
        +
        +<h3>Multiple</h3>
        +<p-selectButton [options]="types" [(ngModel)]="selectedTypes" multiple="multiple"></p-selectButton>
        +<p>Selected Types: <span *ngFor="let type of selectedTypes">{{type}} </span></p>
        +
        +<hr />
        +
        +<button type="button" (click)="clear()" pButton icon="fa-close" label="Clear"></button>
        +
        +
        + +
        +
        +export class SelectButtonDemo {
        +
        +    types: SelectItem[];
        +
        +    selectedType: string;
        +
        +    selectedTypes: string[] = ['Apartment','Studio'];
        +
        +    constructor() {
        +        this.types = [];
        +        this.types.push({label: 'Apartment', value: 'Apartment'});
        +        this.types.push({label: 'House', value: 'House'});
        +        this.types.push({label: 'Studio', value: 'Studio'});
        +    }
        +
        +    clear() {
        +        this.selectedType = null;
        +        this.selectedTypes = [];
        +    }
        +}
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/selectbutton/selectbuttondemo.module.ts b/src/app/showcase/components/selectbutton/selectbuttondemo.module.ts new file mode 100644 index 00000000000..349051e8020 --- /dev/null +++ b/src/app/showcase/components/selectbutton/selectbuttondemo.module.ts @@ -0,0 +1,25 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {SelectButtonDemo} from './selectbuttondemo'; +import {SelectButtonDemoRoutingModule} from './selectbuttondemo-routing.module'; +import {SelectButtonModule} from '../../../components/selectbutton/selectbutton'; +import {ButtonModule} from '../../../components/button/button'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + SelectButtonDemoRoutingModule, + FormsModule, + SelectButtonModule, + ButtonModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + SelectButtonDemo + ] +}) +export class SelectButtonDemoModule {} diff --git a/src/app/showcase/components/selectbutton/selectbuttondemo.ts b/src/app/showcase/components/selectbutton/selectbuttondemo.ts new file mode 100644 index 00000000000..b30eddf3d79 --- /dev/null +++ b/src/app/showcase/components/selectbutton/selectbuttondemo.ts @@ -0,0 +1,26 @@ +import {Component} from '@angular/core'; +import {SelectItem} from '../../../components/common/api'; + +@Component({ + templateUrl: './selectbuttondemo.html' +}) +export class SelectButtonDemo { + + types: SelectItem[]; + + selectedType: string; + + selectedTypes: string[] = ['Apartment','Studio']; + + constructor() { + this.types = []; + this.types.push({label: 'Apartment', value: 'Apartment'}); + this.types.push({label: 'House', value: 'House'}); + this.types.push({label: 'Studio', value: 'Studio'}); + } + + clear() { + this.selectedType = null; + this.selectedTypes = []; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/service/carservice.ts b/src/app/showcase/components/service/carservice.ts new file mode 100644 index 00000000000..036ff7142f7 --- /dev/null +++ b/src/app/showcase/components/service/carservice.ts @@ -0,0 +1,30 @@ +import {Injectable} from '@angular/core'; +import {Http, Response} from '@angular/http'; +import {Car} from '../../components/domain/car'; + +@Injectable() +export class CarService { + + constructor(private http: Http) {} + + getCarsSmall() { + return this.http.get('showcase/resources/data/cars-small.json') + .toPromise() + .then(res => res.json().data) + .then(data => { return data; }); + } + + getCarsMedium() { + return this.http.get('showcase/resources/data/cars-medium.json') + .toPromise() + .then(res => res.json().data) + .then(data => { return data; }); + } + + getCarsLarge() { + return this.http.get('showcase/resources/data/cars-large.json') + .toPromise() + .then(res => res.json().data) + .then(data => { return data; }); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/service/countryservice.ts b/src/app/showcase/components/service/countryservice.ts new file mode 100644 index 00000000000..779c98c808b --- /dev/null +++ b/src/app/showcase/components/service/countryservice.ts @@ -0,0 +1,15 @@ +import {Injectable} from '@angular/core'; +import {Http, Response} from '@angular/http'; + +@Injectable() +export class CountryService { + + constructor(private http: Http) {} + + getCountries() { + return this.http.get('showcase/resources/data/countries.json') + .toPromise() + .then(res => res.json().data) + .then(data => { return data; }); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/service/eventservice.ts b/src/app/showcase/components/service/eventservice.ts new file mode 100644 index 00000000000..abb1213482f --- /dev/null +++ b/src/app/showcase/components/service/eventservice.ts @@ -0,0 +1,15 @@ +import {Injectable} from '@angular/core'; +import {Http, Response} from '@angular/http'; + +@Injectable() +export class EventService { + + constructor(private http: Http) {} + + getEvents() { + return this.http.get('showcase/resources/data/scheduleevents.json') + .toPromise() + .then(res => res.json().data) + .then(data => { return data; }); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/service/nodeservice.ts b/src/app/showcase/components/service/nodeservice.ts new file mode 100644 index 00000000000..9cda9b9d6e9 --- /dev/null +++ b/src/app/showcase/components/service/nodeservice.ts @@ -0,0 +1,33 @@ +import {Injectable} from '@angular/core'; +import {Http, Response} from '@angular/http'; +import {TreeNode} from '../../../components/common/api'; + +@Injectable() +export class NodeService { + + constructor(private http: Http) {} + + getFiles() { + return this.http.get('showcase/resources/data/files.json') + .toPromise() + .then(res => res.json().data); + } + + getLazyFiles() { + return this.http.get('showcase/resources/data/files-lazy.json') + .toPromise() + .then(res => res.json().data); + } + + getFilesystem() { + return this.http.get('showcase/resources/data/filesystem.json') + .toPromise() + .then(res => res.json().data); + } + + getLazyFilesystem() { + return this.http.get('showcase/resources/data/filesystem-lazy.json') + .toPromise() + .then(res => res.json().data); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/setup/setup-routing.module.ts b/src/app/showcase/components/setup/setup-routing.module.ts new file mode 100644 index 00000000000..b8c612403c2 --- /dev/null +++ b/src/app/showcase/components/setup/setup-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router'; +import {SetupComponent} from './setup.component'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: SetupComponent} + ]) + ], + exports: [ + RouterModule + ] +}) +export class SetupRoutingModule {} \ No newline at end of file diff --git a/src/app/showcase/components/setup/setup.component.css b/src/app/showcase/components/setup/setup.component.css new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/app/showcase/components/setup/setup.component.html b/src/app/showcase/components/setup/setup.component.html new file mode 100644 index 00000000000..c0f6b92bdb6 --- /dev/null +++ b/src/app/showcase/components/setup/setup.component.html @@ -0,0 +1,163 @@ +
        +
        + Setup + PrimeNG is a rich set of open source native Angular UI components. +
        +
        + +
        +

        Download

        +

        PrimeNG is available at npm, if you have an existing application run the following command to download it to your project.

        +
        +
        +npm install primeng --save
        +
        +
        + +

        Load Configuration

        +

        PrimeNG is distributed in commonjs format, a module manager of your choice is required and this guide provides a sample for SystemJS and Webpack.

        + +

        Import

        +

        UI components are configured as modules, once PrimeNG is downloaded and configured, modules and apis can be imported from 'primeng/primeng' shorthand in your application code.

        +
        +
        +import {AccordionModule} from 'primeng/primeng';     //accordion and accordion tab
        +import {MenuItem} from 'primeng/primeng';            //api
        +
        +
        + +

        Importing from primeng/primeng will load all other components as well, to only import a specific component pattern would result in a smaller bundle size.

        +
        +
        +//import {ComponentModule} from 'primeng/components/componentname/componentname';
        +//import {InterfaceName} from 'primeng/common/api';
        +
        +import {AccordionModule} from 'primeng/components/accordion/accordion';
        +import {MenuItem} from 'primeng/components/common/api';
        +
        +
        + +

        Dependencies

        +

        Majority of PrimeNG components (95%) are native and there are some exceptions having 3rd party dependencies. In addition, components require font-awesome for icons.

        + +

        The css dependencies are as follows, note that you may change the theme with another one of your choice.

        +
        +
        +<link rel="stylesheet" type="text/css" href="/node_modules/primeng/resources/themes/omega/theme.css" />
        +<link rel="stylesheet" type="text/css" href="/node_modules/primeng/resources/primeng.min.css" />
        +<link rel="stylesheet" type="text/css" href="YOUR_PATH/font-awesome.min.css" />
        +
        +
        + +

        Here is the list of components with 3rd party dependencies.

        + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        ComponentDependency
        ScheduleFullCalendar and Moment.js
        EditorQuill Editor
        GMapGoogle Maps
        ChartsCharts.js 2.1.x
        CaptchaGoogle Recaptcha
        +
        + +

        Animations with Angular 4+

        +

        Various components utilize angular animations to improve the user experience, starting with Angular 4 animations have their own module so you need + to import BrowserAnimationsModule to your application. If you prefer not to NoopAnimationsModule instead.

        + +
        +
        +npm install @angular/animations
        +
        +
        + +
        +
        +import {BrowserModule} from '@angular/platform-browser';
        +
        +@NgModule({
        +    imports: [
        +        BrowserModule,
        +        //...
        +    ],
        +    //...
        +})
        +export class YourAppModule { }
        +
        +
        + +

        Angular CLI Integration

        +

        Angular CLI is the official CLI tool for Angular. We strongly suggest using Angular CLI when starting an Angular project.

        + +

        Dependencies

        +

        Add PrimeNG and FontAwesome as a dependency

        +
        +
        +"dependencies": {
        +  //...
        +  "primeng": "^2.0.3",
        +  "font-awesome": "^4.7.0"
        +},
        +
        +
        + +

        Styles Configuration

        +

        Configure required styles at the styles section, example below uses the Omega theme.

        +
        +
        +"styles": [
        +  "../node_modules/primeng/resources/primeng.min.css",
        +  "../node_modules/primeng/resources/themes/omega/theme.css",
        +  "../node_modules/font-awesome/css/font-awesome.min.css",
        +  //...
        +],
        +
        +
        + +

        That is all, you may now import PrimeNG components, for a working example visit the PrimeNG CLI QuickStart sample at GitHub.

        + +

        Angular Seed Integration

        +

        Angular2 Seed is a modular starter project, there is an official entry at the project wiki + describing how to use PrimeNG with seed.

        + +

        QuickStart with System.js

        +

        The official quickstart example of Angular uses System.JS and we + have extended it to add PrimeNG. Visit the PrimeNG-Quickstart at GitHub for an example.

        + +

        QuickStart with Webpack

        +

        There is also a webpack version of the The official quickstart example of Angular and we + have extended it to add PrimeNG. Visit the PrimeNG-Quickstart-Webpack at GitHub for an example.

        + +

        External Articles

        + +
        \ No newline at end of file diff --git a/src/app/showcase/components/setup/setup.component.ts b/src/app/showcase/components/setup/setup.component.ts new file mode 100644 index 00000000000..65d6364ae93 --- /dev/null +++ b/src/app/showcase/components/setup/setup.component.ts @@ -0,0 +1,8 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './setup.component.html' +}) +export class SetupComponent { + +} \ No newline at end of file diff --git a/src/app/showcase/components/setup/setup.module.ts b/src/app/showcase/components/setup/setup.module.ts new file mode 100644 index 00000000000..cd1aae7676a --- /dev/null +++ b/src/app/showcase/components/setup/setup.module.ts @@ -0,0 +1,17 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {SetupComponent} from './setup.component'; +import {SetupRoutingModule} from './setup-routing.module'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + CodeHighlighterModule, + SetupRoutingModule + ], + declarations: [ + SetupComponent + ] +}) +export class SetupModule {} \ No newline at end of file diff --git a/src/app/showcase/components/slidemenu/slidemenudemo-routing.module.ts b/src/app/showcase/components/slidemenu/slidemenudemo-routing.module.ts new file mode 100644 index 00000000000..7a70ff0c8d2 --- /dev/null +++ b/src/app/showcase/components/slidemenu/slidemenudemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {SlideMenuDemo} from './slidemenudemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: SlideMenuDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class SlideMenuDemoRoutingModule {} diff --git a/src/app/showcase/components/slidemenu/slidemenudemo.html b/src/app/showcase/components/slidemenu/slidemenudemo.html new file mode 100644 index 00000000000..ab248e29899 --- /dev/null +++ b/src/app/showcase/components/slidemenu/slidemenudemo.html @@ -0,0 +1,348 @@ +
        +
        + Slide Menu + SlideMenu displays submenus with slide animation. +
        +
        + +
        +

        Default

        + + +

        Popup

        + + +
        + +
        + + +

        Import

        +
        +
        +import {SlideMenuModule,MenuItem} from 'primeng/primeng';
        +
        +
        + +

        MenuModel API

        +

        SlideMenu uses the common menumodel api to define its items, visit MenuModel API for details.

        + +

        Getting Started

        +

        SlideMenu requires nested menuitems as its model.

        +
        +
        +<p-slideMenu [model]="items"></p-slideMenu>
        +
        +
        + +
        +
        +export class SlideMenuDemo {
        +
        +    private items: MenuItem[];
        +
        +    ngOnInit() {
        +        this.items = [
        +            {
        +                label: 'File',
        +                items: [{
        +                        label: 'New', 
        +                        icon: 'fa-plus',
        +                        items: [
        +                            {label: 'Project'},
        +                            {label: 'Other'},
        +                        ]
        +                    },
        +                    {label: 'Open'},
        +                    {label: 'Quit'}
        +                ]
        +            },
        +            {
        +                label: 'Edit',
        +                icon: 'fa-edit',
        +                items: [
        +                    {label: 'Undo', icon: 'fa-mail-forward'},
        +                    {label: 'Redo', icon: 'fa-mail-reply'}
        +                ]
        +            }
        +        ];
        +    }
        +}
        +
        +
        + +

        Popup Mode

        +

        SlideMenu is inline by default, popup mode is also supported by enabling popup property and calling toggle method by passing the event + from the anchor element.

        +
        +
        +<p-slideMenu #menu [model]="items" [popup]="true"></p-slideMenu>
        +<button #btn type="button" pButton icon="fa fa-list" label="Show" (click)="menu.toggle($event)"></button>
        +
        +
        + +

        Effects

        +

        The easing function to use is "ease-out" by default and this can be customized using easing property. + See here for possible alternative values.

        +
        +
        +<p-slideMenu #menu [model]="items" effectDuration="1000" easing="ease-in"></p-slideMenu>
        +
        +
        + + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        modelarraynullAn array of menuitems.
        popupbooleanfalseDefines if menu would displayed as a popup.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        easingstringease-outEasing animation to use for sliding.
        effectDurationany500Duration of the sliding animation in milliseconds.
        backLabelstringBackLabel of element to navigate back.
        menuWidthnumber180Width of the submenus.
        viewportHeightnumber175Height of the scrollable area, a scrollbar appears if a menu height is longer than this value.
        +
        + +

        Methods

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        toggleevent: browser eventToggles the visibility of the popup menu.
        showevent: browser eventDisplays the popup menu.
        hide-Hides the popup menu.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-slidemenuContainer element.
        ui-slidemenu-wrapperWrapper of content.
        ui-slidemenu-contentContent element.
        ui-slidemenu-backwardElement to navigate to previous menu on click.
        ui-menu-listList element.
        ui-menuitemMenuitem element.
        ui-menuitem-textLabel of a menuitem.
        ui-menuitem-iconIcon of a menuitem.
        ui-submenu-iconArrow icon of a submenu.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<h3 class="first">Default</h3>
        +<p-slideMenu [model]="items"></p-slideMenu>
        +
        +<h3>Popup</h3>
        +<p-slideMenu #menu [model]="items" [popup]="true"></p-slideMenu>
        +<button #btn type="button" pButton icon="fa fa-list" label="Show" (click)="menu.toggle($event)"></button>
        +
        +
        + +
        +
        +export class SlideMenuDemo {
        +
        +    private items: MenuItem[];
        +
        +    ngOnInit() {
        +        this.items = [
        +            {
        +                label: 'File',
        +                icon: 'fa-file-o',
        +                items: [{
        +                        label: 'New', 
        +                        icon: 'fa-plus',
        +                        items: [
        +                            {label: 'Project'},
        +                            {label: 'Other'},
        +                        ]
        +                    },
        +                    {label: 'Open'},
        +                    {label: 'Quit'}
        +                ]
        +            },
        +            {
        +                label: 'Edit',
        +                icon: 'fa-edit',
        +                items: [
        +                    {label: 'Undo', icon: 'fa-mail-forward'},
        +                    {label: 'Redo', icon: 'fa-mail-reply'}
        +                ]
        +            },
        +            {
        +                label: 'Help',
        +                icon: 'fa-question',
        +                items: [
        +                    {
        +                        label: 'Contents'
        +                    },
        +                    {
        +                        label: 'Search', 
        +                        icon: 'fa-search', 
        +                        items: [
        +                            {
        +                                label: 'Text', 
        +                                items: [
        +                                    {
        +                                        label: 'Workspace'
        +                                    }
        +                                ]
        +                            },
        +                            {
        +                                label: 'File'
        +                            }
        +                    ]}
        +                ]
        +            },
        +            {
        +                label: 'Actions',
        +                icon: 'fa-gear',
        +                items: [
        +                    {
        +                        label: 'Edit',
        +                        icon: 'fa-refresh',
        +                        items: [
        +                            {label: 'Save', icon: 'fa-save'},
        +                            {label: 'Update', icon: 'fa-save'},
        +                        ]
        +                    },
        +                    {
        +                        label: 'Other',
        +                        icon: 'fa-phone',
        +                        items: [
        +                            {label: 'Delete', icon: 'fa-minus'}
        +                        ]
        +                    }
        +                ]
        +            },
        +            {
        +                label: 'Quit', icon: 'fa-minus'
        +            }
        +        ];
        +    }
        +}
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/slidemenu/slidemenudemo.module.ts b/src/app/showcase/components/slidemenu/slidemenudemo.module.ts new file mode 100644 index 00000000000..b09c640ae39 --- /dev/null +++ b/src/app/showcase/components/slidemenu/slidemenudemo.module.ts @@ -0,0 +1,23 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {SlideMenuDemo} from './slidemenudemo'; +import {SlideMenuDemoRoutingModule} from './slidemenudemo-routing.module'; +import {SlideMenuModule} from '../../../components/slidemenu/slidemenu'; +import {ButtonModule} from '../../../components/button/button'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + SlideMenuDemoRoutingModule, + SlideMenuModule, + ButtonModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + SlideMenuDemo + ] +}) +export class SlideMenuDemoModule {} diff --git a/src/app/showcase/components/slidemenu/slidemenudemo.ts b/src/app/showcase/components/slidemenu/slidemenudemo.ts new file mode 100644 index 00000000000..1fb68bdcf1f --- /dev/null +++ b/src/app/showcase/components/slidemenu/slidemenudemo.ts @@ -0,0 +1,87 @@ +import {Component} from '@angular/core'; +import {MenuItem} from '../../../components/common/api'; + +@Component({ + templateUrl: './slidemenudemo.html' +}) +export class SlideMenuDemo { + + private items: MenuItem[]; + + ngOnInit() { + this.items = [ + { + label: 'File', + icon: 'fa-file-o', + items: [{ + label: 'New', + icon: 'fa-plus', + items: [ + {label: 'Project'}, + {label: 'Other'}, + ] + }, + {label: 'Open'}, + {label: 'Quit'} + ] + }, + { + label: 'Edit', + icon: 'fa-edit', + items: [ + {label: 'Undo', icon: 'fa-mail-forward'}, + {label: 'Redo', icon: 'fa-mail-reply'} + ] + }, + { + label: 'Help', + icon: 'fa-question', + items: [ + { + label: 'Contents' + }, + { + label: 'Search', + icon: 'fa-search', + items: [ + { + label: 'Text', + items: [ + { + label: 'Workspace' + } + ] + }, + { + label: 'File' + } + ]} + ] + }, + { + label: 'Actions', + icon: 'fa-gear', + items: [ + { + label: 'Edit', + icon: 'fa-refresh', + items: [ + {label: 'Save', icon: 'fa-save'}, + {label: 'Update', icon: 'fa-save'}, + ] + }, + { + label: 'Other', + icon: 'fa-phone', + items: [ + {label: 'Delete', icon: 'fa-minus'} + ] + } + ] + }, + { + label: 'Quit', icon: 'fa-minus' + } + ]; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/slider/sliderdemo-routing.module.ts b/src/app/showcase/components/slider/sliderdemo-routing.module.ts new file mode 100644 index 00000000000..32595a3c38b --- /dev/null +++ b/src/app/showcase/components/slider/sliderdemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {SliderDemo} from './sliderdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: SliderDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class SliderDemoRoutingModule {} diff --git a/src/app/showcase/components/slider/sliderdemo.html b/src/app/showcase/components/slider/sliderdemo.html new file mode 100644 index 00000000000..ab78961a515 --- /dev/null +++ b/src/app/showcase/components/slider/sliderdemo.html @@ -0,0 +1,293 @@ +
        +
        + Slider + Slider is a component to provide input using dragging of a handle. +
        +
        + +
        +

        Basic: {{val1}}

        + + +

        Input: {{val2}}

        + + + +

        Animate: {{val3}}

        + + +

        Step: {{val4}}

        + + +

        Range: {{rangeValues[0] + ' - ' + rangeValues[1]}}

        + + +

        Vertical: {{val5}}

        + +
        + +
        + + +

        Import

        +
        +
        +import {SliderModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Two-way binding is defined using the standard ngModel directive.

        +
        +
        +<p-slider [(ngModel)]="val"></p-slider>
        +
        +
        + +
        +
        +export class MyModel {
        +
        +    val: number;
        +
        +}
        +
        +
        + +

        Model Driven Forms

        +

        Slider can be used in a model driven form as well.

        +
        +
        +<p-slider formControlName="age"></p-slider>
        +
        +
        + +

        Min-Max

        +

        Boundaries are specified with min and max attributes.

        +
        +
        +<p-slider [(ngModel)]="val" [min]="0" [max]="100"></p-slider>
        +
        +
        + +

        Step

        +

        Step factor is 1 by default and can be customized with step option.

        +
        +
        +<p-slider [(ngModel)]="val" [step]="10"></p-slider>
        +
        +
        + +

        Range

        +

        Range slider provides two handles to define two values. In this case, value binding should refer to an array.

        +
        +
        +<p-slider [(ngModel)]="rangeValues" [range]="true"></p-slider>
        +
        +
        + +
        +
        +export class MyModel {
        +
        +    rangeValues: number[];
        +
        +}
        +
        +
        + +

        Orientation

        +

        Sliders supports two orientations, horizontal is the default and other alternative is vertical.

        +
        +
        +<p-slider [(ngModel)]="val" orientation="vertical"></p-slider>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        animatebooleanfalseWhen enabled, displays an animation on click of the slider bar.
        disabledbooleanfalseWhen present, it specifies that the element should be disabled.
        minnumber0Mininum boundary value.
        maxnumber100Maximum boundary value.
        orientationstringhorizontalOrientation of the slider, valid values are horizontal and vertical.
        stepnumber1Step factor to increment/decrement the value.
        rangebooleanfalseWhen speficed, allows two boundary values to be picked.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onChange + event.originalEvent: Slide event
        + event.value: New value
        + event.values: Values in range mode
        +
        Callback to invoke on value change via slide.
        onSlideEnd + event.originalEvent: Mouseup event
        + event.value: New value +
        Callback to invoke when slide stops.
        +
        +
        +
        +<p-slider [(ngModel)]="val" (onChange)="handleChange($event)"></p-slider>
        +
        +
        + +
        +
        +handleChange(e) {
        +    //e.value is the new value
        +}
        +
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + +
        NameElement
        ui-sliderContainer element
        ui-slider-handleHandle element
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<h3 class="first">Basic: {{val1}}</h3>
        +<p-slider [(ngModel)]="val1" [style]="{'width':'200px'}"></p-slider>
        +
        +<h3>Input: {{val2}}</h3>
        +<input type="text" pInputText [(ngModel)]="val2" style="width:190px"/>
        +<p-slider [(ngModel)]="val2" [style]="{'width':'200px'}"></p-slider>
        +
        +<h3>Animate: {{val3}}</h3>
        +<p-slider [(ngModel)]="val3" [style]="{'width':'200px'}" [animate]="true"></p-slider>
        +
        +<h3>Step: {{val4}}</h3>
        +<p-slider [(ngModel)]="val4" [style]="{'width':'200px'}" [step]="20"></p-slider>
        +
        +<h3>Range: {{rangeValues[0] + ' - ' + rangeValues[1]}}</h3>
        +<p-slider [(ngModel)]="rangeValues" [style]="{'width':'200px'}" [range]="true"></p-slider>
        +
        +<h3>Vertical: {{val5}}</h3>
        +<p-slider [(ngModel)]="val5" [style]="{'height':'200px'}" orientation="vertical"></p-slider>
        +
        +
        + +
        +
        +export class SliderDemo {
        +
        +    val1: number;
        +
        +    val2: number = 50;
        +
        +    val3: number;
        +
        +    val4: number;
        +
        +    val5: number;
        +
        +    rangeValues: number[] = [20,80];
        +}
        +
        +
        +
        +
        +
        diff --git a/src/app/showcase/components/slider/sliderdemo.module.ts b/src/app/showcase/components/slider/sliderdemo.module.ts new file mode 100644 index 00000000000..c748bd561ff --- /dev/null +++ b/src/app/showcase/components/slider/sliderdemo.module.ts @@ -0,0 +1,25 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {SliderDemo} from './sliderdemo'; +import {SliderDemoRoutingModule} from './sliderdemo-routing.module'; +import {SliderModule} from '../../../components/slider/slider'; +import {InputTextModule} from '../../../components/inputtext/inputtext'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + SliderDemoRoutingModule, + SliderModule, + InputTextModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + SliderDemo + ] +}) +export class SliderDemoModule {} diff --git a/src/app/showcase/components/slider/sliderdemo.ts b/src/app/showcase/components/slider/sliderdemo.ts new file mode 100644 index 00000000000..113cc47b79f --- /dev/null +++ b/src/app/showcase/components/slider/sliderdemo.ts @@ -0,0 +1,19 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './sliderdemo.html' +}) +export class SliderDemo { + + val1: number; + + val2: number = 50; + + val3: number; + + val4: number; + + val5: number; + + rangeValues: number[] = [20,80]; +} \ No newline at end of file diff --git a/src/app/showcase/components/spinner/spinnerdemo-routing.module.ts b/src/app/showcase/components/spinner/spinnerdemo-routing.module.ts new file mode 100644 index 00000000000..916bc3ba0ad --- /dev/null +++ b/src/app/showcase/components/spinner/spinnerdemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {SpinnerDemo} from './spinnerdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: SpinnerDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class SpinnerDemoRoutingModule {} diff --git a/src/app/showcase/components/spinner/spinnerdemo.html b/src/app/showcase/components/spinner/spinnerdemo.html new file mode 100644 index 00000000000..4584d94a16c --- /dev/null +++ b/src/app/showcase/components/spinner/spinnerdemo.html @@ -0,0 +1,248 @@ +
        +
        + Spinner + Spinner is an input component to provide a numerical input. +
        +
        + +
        +

        Basic

        + + +

        Min/Max

        + + +

        Step

        + + +

        Disabled

        + +
        + +
        + + +

        Import

        +
        +
        +import {SpinnerModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Two-way value binding is defined using standard ngModel directive.

        +
        +
        +<p-spinner size="30" [(ngModel)]="val"></p-spinner>
        +
        +
        + +

        Model Driven Forms

        +

        Spinner can be used in a model driven form as well.

        +
        +
        +<p-spinner formControlName="age"></p-spinner>
        +
        +
        + +

        Min-Max

        +

        Boundaries are specified with min and max attributes.

        +
        +
        +<p-spinner size="30" [(ngModel)]="val" [min]="0" [max]="100"></p-spinner>
        +
        +
        + +

        Step

        +

        Step factor is 1 by default and can be customized with step option.

        +
        +
        +<p-spinner size="30" [(ngModel)]="val" [step]="0.25"></p-spinner>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        stepnumber1Step factor to increment/decrement the value.
        minnumbernullMininum boundary value.
        maxnumbernullMaximum boundary value.
        placeholderstringnullHint text for the input field.
        disabledbooleanfalseWhen present, it specifies that the element should be disabled.
        readonlybooleanfalseWhen present, it specifies that the element should be read-only.
        maxlengthnumbernullMaximum number of character allows in the input field.
        sizenumbernullSize of the input field.
        decimalSeparatorstring.Separator character for decimals.
        thousandSeparatorstring,Separator character for thousands.
        tabindexnumbernullIndex of the element in tabbing order.
        formatInputbooleantrueWhen present, formats the user input.
        inputIdstringnullIdentifier of the focus input to match a label defined for the component.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onBlurevent: Blur eventCallback to invoke when autocomplete loses focus.
        onChangeevent: Change eventCallback to invoke on value change.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-spinnerContainer element
        ui-spinner-upUp element
        ui-spinner-downDown button
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<h3 class="first">Basic</h3>
        +<p-spinner size="30" [(ngModel)]="val1"></p-spinner>
        +
        +<h3>Min/Max</h3>
        +<p-spinner size="30" [(ngModel)]="val2" [min]="0" [max]="100"></p-spinner>
        +
        +<h3>Step</h3>
        +<p-spinner size="30" [(ngModel)]="val3" [step]="0.25"></p-spinner>
        +
        +<h3>Disabled</h3>
        +<p-spinner size="30" [(ngModel)]="val4" [disabled]="true"></p-spinner>
        +
        +
        + +
        +
        +export class SpinnerDemo {
        +
        +    val1: number;
        +
        +    val2: number;
        +
        +    val3: number;
        +
        +    val4: number = 100;
        +    
        +}
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/spinner/spinnerdemo.module.ts b/src/app/showcase/components/spinner/spinnerdemo.module.ts new file mode 100644 index 00000000000..dadd43f253c --- /dev/null +++ b/src/app/showcase/components/spinner/spinnerdemo.module.ts @@ -0,0 +1,23 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common' +import {FormsModule} from '@angular/forms';; +import {SpinnerDemo} from './spinnerdemo'; +import {SpinnerDemoRoutingModule} from './spinnerdemo-routing.module'; +import {SpinnerModule} from '../../../components/spinner/spinner'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + SpinnerDemoRoutingModule, + SpinnerModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + SpinnerDemo + ] +}) +export class SpinnerDemoModule {} diff --git a/src/app/showcase/components/spinner/spinnerdemo.ts b/src/app/showcase/components/spinner/spinnerdemo.ts new file mode 100644 index 00000000000..5b72279e55f --- /dev/null +++ b/src/app/showcase/components/spinner/spinnerdemo.ts @@ -0,0 +1,15 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './spinnerdemo.html' +}) +export class SpinnerDemo { + + val1: number; + + val2: number; + + val3: number; + + val4: number = 100; +} \ No newline at end of file diff --git a/src/app/showcase/components/splitbutton/splitbuttondemo-routing.module.ts b/src/app/showcase/components/splitbutton/splitbuttondemo-routing.module.ts new file mode 100644 index 00000000000..59e2b0017c0 --- /dev/null +++ b/src/app/showcase/components/splitbutton/splitbuttondemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {SplitButtonDemo} from './splitbuttondemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: SplitButtonDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class SplitButtonDemoRoutingModule {} diff --git a/src/app/showcase/components/splitbutton/splitbuttondemo.html b/src/app/showcase/components/splitbutton/splitbuttondemo.html new file mode 100644 index 00000000000..40f70697872 --- /dev/null +++ b/src/app/showcase/components/splitbutton/splitbuttondemo.html @@ -0,0 +1,210 @@ +
        +
        + SplitButton + SplitButton groups a set of commands in an overlay with a default command. +
        +
        + +
        + + + +
        + +
        + + +

        Import

        +
        +
        +import {SplitButtonModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        SplitButton has a default command button and a collection of menuitems to be displayed in an overlay.

        + +
        +
        +<p-splitButton label="Save" icon="fa-check" (onClick)="save()" [model]="items"></p-splitButton>
        +
        +
        + +

        MenuModel API

        +

        SplitButton uses the common menumodel api to define its items, visit MenuModel API for details.

        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        labelstringnullText of the button.
        iconstringnullName of the icon.
        iconPosstringleftPosition of the icon, valid values are "left" and "right".
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        menuStylestringnullInline style of the overlay menu.
        menuStyleClassstringnullStyle class of the overlay menu.
        disabledbooleanfalseWhen present, it specifies that the component should be disabled.
        tabindexnumbernullIndex of the element in tabbing order.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onClickevent: browser event
        Callback to invoke when default command button is clicked.
        onDropdownClickevent: browser event
        Callback to invoke when dropdown button is clicked.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page. SplitButton uses + button and menu components internally, refer to their documentation for the detailed style list.

        +
        + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-splitbuttonContainer element.
        ui-splitbutton-buttonDropdown button.
        ui-menuOverlay menu.
        +
        + +

        Dependencies

        +

        None.

        +
        + +
        +
        +<p-growl [value]="msgs"></p-growl>
        +
        +<p-splitButton label="Save" icon="fa-check" (onClick)="save()" [model]="items"></p-splitButton>
        +
        +
        +
        +
        +export class SplitButtonDemo implements OnInit {
        +
        +    msgs: Message[] = [];
        +    
        +    items: MenuItem[];
        +    
        +    ngOnInit() {
        +        this.items = [
        +            {label: 'Update', icon: 'fa-refresh', command: () => {
        +                this.update();
        +            }},
        +            {label: 'Delete', icon: 'fa-close', command: () => {
        +                this.delete();
        +            }},
        +            {label: 'Angular.io', icon: 'fa-link', url: 'http://angular.io'},
        +            {label: 'Theming', icon: 'fa-paint-brush', routerLink: ['/theming']}
        +        ];
        +    }
        +
        +    save() {
        +        this.msgs = [];
        +        this.msgs.push({severity:'info', summary:'Success', detail:'Data Saved'});
        +    }
        +    
        +    update() {
        +        this.msgs = [];
        +        this.msgs.push({severity:'info', summary:'Success', detail:'Data Updated'});
        +    }
        +    
        +    delete() {
        +        this.msgs = [];
        +        this.msgs.push({severity:'info', summary:'Success', detail:'Data Deleted'});
        +    }
        +}
        +
        +
        + +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/splitbutton/splitbuttondemo.module.ts b/src/app/showcase/components/splitbutton/splitbuttondemo.module.ts new file mode 100644 index 00000000000..9b5d8e8db92 --- /dev/null +++ b/src/app/showcase/components/splitbutton/splitbuttondemo.module.ts @@ -0,0 +1,23 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {SplitButtonDemo} from './splitbuttondemo'; +import {SplitButtonDemoRoutingModule} from './splitbuttondemo-routing.module'; +import {SplitButtonModule} from '../../../components/splitbutton/splitbutton'; +import {GrowlModule} from '../../../components/growl/growl'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + SplitButtonDemoRoutingModule, + SplitButtonModule, + GrowlModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + SplitButtonDemo + ] +}) +export class SplitButtonDemoModule {} diff --git a/src/app/showcase/components/splitbutton/splitbuttondemo.ts b/src/app/showcase/components/splitbutton/splitbuttondemo.ts new file mode 100644 index 00000000000..a771e4fbec2 --- /dev/null +++ b/src/app/showcase/components/splitbutton/splitbuttondemo.ts @@ -0,0 +1,41 @@ +import {Component,OnInit} from '@angular/core'; +import {Message} from '../../../components/common/api'; +import {MenuItem} from '../../../components/common/api'; + +@Component({ + templateUrl: './splitbuttondemo.html' +}) +export class SplitButtonDemo implements OnInit { + + msgs: Message[] = []; + + items: MenuItem[]; + + ngOnInit() { + this.items = [ + {label: 'Update', icon: 'fa-refresh', command: () => { + this.update(); + }}, + {label: 'Delete', icon: 'fa-close', command: () => { + this.delete(); + }}, + {label: 'Angular.io', icon: 'fa-link', url: 'http://angular.io'}, + {label: 'Theming', icon: 'fa-paint-brush', routerLink: ['/theming']} + ]; + } + + save() { + this.msgs = []; + this.msgs.push({severity:'info', summary:'Success', detail:'Data Saved'}); + } + + update() { + this.msgs = []; + this.msgs.push({severity:'info', summary:'Success', detail:'Data Updated'}); + } + + delete() { + this.msgs = []; + this.msgs.push({severity:'info', summary:'Success', detail:'Data Deleted'}); + } +} diff --git a/src/app/showcase/components/steps/stepsdemo-routing.module.ts b/src/app/showcase/components/steps/stepsdemo-routing.module.ts new file mode 100644 index 00000000000..f8456549fa7 --- /dev/null +++ b/src/app/showcase/components/steps/stepsdemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {StepsDemo} from './stepsdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: StepsDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class StepsDemoRoutingModule {} diff --git a/src/app/showcase/components/steps/stepsdemo.html b/src/app/showcase/components/steps/stepsdemo.html new file mode 100644 index 00000000000..8787d982926 --- /dev/null +++ b/src/app/showcase/components/steps/stepsdemo.html @@ -0,0 +1,266 @@ +
        +
        + Steps + Steps components is an indicator for the steps in a workflow. Layout of steps component is optimized for responsive design. +
        +
        + +
        + + +

        Basic

        + + +

        Clickable

        + + +

        Custom Style

        + +
        + +
        + + +

        Import

        +
        +
        +import {StepsModule,MenuItem} from 'primeng/primeng';
        +
        +
        + +

        MenuModel API

        +

        Steps uses the common menumodel api to define its items, visit MenuModel API for details.

        + +

        Getting Started

        +

        Steps requires a collection of menuitems as its model.

        +
        +
        +<p-steps [model]="items"></p-steps>
        +
        +
        + +
        +
        +export class MenuDemo {
        +    
        +    private items: MenuItem[];
        +
        +    ngOnInit() {
        +        this.items = [
        +            {label: 'Step 1'},
        +            {label: 'Step 2'},
        +            {label: 'Step 3'}
        +        ];
        +    }
        +}
        +
        +
        + +

        Readonly

        +

        Items are readonly by default, if you'd like to make them interactive then disable readonly.

        +
        +
        +<p-steps [model]="items" [readonly]="false"></p-steps>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        modelarraynullAn array of menuitems.
        activeIndexnumber0Index of the active item.
        readonlybooleantrueWhether the items are clickable or not.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + +
        NameParametersDescription
        activeIndexChangeindex: Index of the active step itemCallback to invoke when the new step is selected.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-stepsContainer element.
        ui-steps-itemMenuitem element.
        ui-steps-numberNumber of menuitem.
        ui-steps-titleLabel of menuitem.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<p-growl [value]="msgs"></p-growl>
        +
        +<h3 class="first">Basic</h3>
        +<p-steps [model]="items"></p-steps>
        +
        +<h3>Clickable</h3>
        +<p-steps [model]="items" [(activeIndex)]="activeIndex" [readonly]="false"></p-steps>
        +
        +<h3>Custom Style</h3>
        +<p-steps [model]="items" styleClass="steps-custom"></p-steps>
        +
        +
        + +
        +
        +@Component({
        +    templateUrl: 'showcase/demo/steps/stepsdemo.html',
        +    styles: [`
        +        .ui-steps .ui-steps-item {
        +            width: 25%;
        +        }
        +        
        +        .ui-steps.steps-custom {
        +            margin-bottom: 30px;
        +        }
        +         
        +        .ui-steps.steps-custom .ui-steps-item .ui-menuitem-link {
        +            height: 10px;
        +            padding: 0 1em;
        +        }
        +         
        +        .ui-steps.steps-custom .ui-steps-item .ui-steps-number {
        +            background-color: #0081c2;
        +            color: #FFFFFF;
        +            display: inline-block;
        +            width: 36px;
        +            border-radius: 50%;
        +            margin-top: -14px;
        +            margin-bottom: 10px;
        +        }
        +        
        +        .ui-steps.steps-custom .ui-steps-item .ui-steps-title {
        +            color: #555555;
        +        }
        +    `],
        +    encapsulation: ViewEncapsulation.None
        +})
        +export class StepsDemo implements OnInit {
        +
        +    private items: MenuItem[];
        +    
        +    msgs: Message[] = [];
        +    
        +    activeIndex: number = 1;
        +
        +    ngOnInit() {
        +        this.items = [{
        +                label: 'Personal',
        +                command: (event: any) => {
        +                    this.activeIndex = 0;
        +                    this.msgs.length = 0;
        +                    this.msgs.push({severity:'info', summary:'First Step', detail: event.item.label});
        +                }
        +            },
        +            {
        +                label: 'Seat',
        +                command: (event: any) => {
        +                    this.activeIndex = 1;
        +                    this.msgs.length = 0;
        +                    this.msgs.push({severity:'info', summary:'Seat Selection', detail: event.item.label});
        +                }
        +            },
        +            {
        +                label: 'Payment',
        +                command: (event: any) => {
        +                    this.activeIndex = 2;
        +                    this.msgs.length = 0;
        +                    this.msgs.push({severity:'info', summary:'Pay with CC', detail: event.item.label});
        +                }
        +            },
        +            {
        +                label: 'Confirmation',
        +                command: (event: any) => {
        +                    this.activeIndex = 3;
        +                    this.msgs.length = 0;
        +                    this.msgs.push({severity:'info', summary:'Last Step', detail: event.item.label});
        +                }
        +            }
        +        ];
        +    }
        +}
        +
        +
        +
        +
        +
        diff --git a/src/app/showcase/components/steps/stepsdemo.module.ts b/src/app/showcase/components/steps/stepsdemo.module.ts new file mode 100644 index 00000000000..777896fa643 --- /dev/null +++ b/src/app/showcase/components/steps/stepsdemo.module.ts @@ -0,0 +1,23 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {StepsDemo} from './stepsdemo'; +import {StepsDemoRoutingModule} from './stepsdemo-routing.module'; +import {StepsModule} from '../../../components/steps/steps'; +import {GrowlModule} from '../../../components/growl/growl'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + StepsDemoRoutingModule, + StepsModule, + GrowlModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + StepsDemo + ] +}) +export class StepsDemoModule {} diff --git a/src/app/showcase/components/steps/stepsdemo.ts b/src/app/showcase/components/steps/stepsdemo.ts new file mode 100644 index 00000000000..9737024d516 --- /dev/null +++ b/src/app/showcase/components/steps/stepsdemo.ts @@ -0,0 +1,81 @@ +import {Component,OnInit,ViewEncapsulation} from '@angular/core'; +import {MenuItem} from '../../../components/common/api'; +import {Message} from '../../../components/common/api'; + +@Component({ + templateUrl: './stepsdemo.html', + styles: [` + .ui-steps .ui-steps-item { + width: 25%; + } + + .ui-steps.steps-custom { + margin-bottom: 30px; + } + + .ui-steps.steps-custom .ui-steps-item .ui-menuitem-link { + height: 10px; + padding: 0 1em; + overflow: visible; + } + + .ui-steps.steps-custom .ui-steps-item .ui-steps-number { + background-color: #0081c2; + color: #FFFFFF; + display: inline-block; + width: 36px; + border-radius: 50%; + margin-top: -14px; + margin-bottom: 10px; + } + + .ui-steps.steps-custom .ui-steps-item .ui-steps-title { + color: #555555; + } + `], + encapsulation: ViewEncapsulation.None +}) +export class StepsDemo implements OnInit { + + private items: MenuItem[]; + + msgs: Message[] = []; + + activeIndex: number = 1; + + ngOnInit() { + this.items = [{ + label: 'Personal', + command: (event: any) => { + this.activeIndex = 0; + this.msgs.length = 0; + this.msgs.push({severity:'info', summary:'First Step', detail: event.item.label}); + } + }, + { + label: 'Seat', + command: (event: any) => { + this.activeIndex = 1; + this.msgs.length = 0; + this.msgs.push({severity:'info', summary:'Seat Selection', detail: event.item.label}); + } + }, + { + label: 'Payment', + command: (event: any) => { + this.activeIndex = 2; + this.msgs.length = 0; + this.msgs.push({severity:'info', summary:'Pay with CC', detail: event.item.label}); + } + }, + { + label: 'Confirmation', + command: (event: any) => { + this.activeIndex = 3; + this.msgs.length = 0; + this.msgs.push({severity:'info', summary:'Last Step', detail: event.item.label}); + } + } + ]; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/tabmenu/tabmenudemo-routing.module.ts b/src/app/showcase/components/tabmenu/tabmenudemo-routing.module.ts new file mode 100644 index 00000000000..efc2341175f --- /dev/null +++ b/src/app/showcase/components/tabmenu/tabmenudemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {TabMenuDemo} from './tabmenudemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: TabMenuDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class TabMenuDemoRoutingModule {} diff --git a/src/app/showcase/components/tabmenu/tabmenudemo.html b/src/app/showcase/components/tabmenu/tabmenudemo.html new file mode 100644 index 00000000000..82c5c39efe1 --- /dev/null +++ b/src/app/showcase/components/tabmenu/tabmenudemo.html @@ -0,0 +1,193 @@ +
        +
        + TabMenu + Menu is a navigation/command component that displays items as tab headers. +
        +
        + +
        + +
        + +
        + + +

        Import

        +
        +
        +import {TabMenuModule,MenuItem} from 'primeng/primeng';
        +
        +
        + +

        MenuModel API

        +

        TabMenu uses the common menumodel api to define its items, visit MenuModel API for details.

        + +

        Getting Started

        +

        TabMenu requires a collection of menuitems as its model.

        +
        +
        +<p-tabMenu [model]="items"></p-tabMenu>
        +
        +
        + +
        +
        +export class TabMenuDemo {
        +    
        +    private items: MenuItem[];
        +
        +    ngOnInit() {
        +        this.items = [
        +            {label: 'Stats', icon: 'fa-bar-chart'},
        +            {label: 'Calendar', icon: 'fa-calendar'},
        +            {label: 'Documentation', icon: 'fa-book'},
        +            {label: 'Support', icon: 'fa-support'},
        +            {label: 'Social', icon: 'fa-twitter'}
        +        ];
        +    }
        +}
        +
        +
        + +

        ActiveItem

        +

        By default, first item is activated, use activeItem property to choose the initial active item.

        +
        +
        +<p-tabMenu [model]="items" [activeItem]="activeItem"></p-tabMenu>
        +
        +
        + +
        +
        +export class TabMenuDemo {
        +    
        +    private items: MenuItem[];
        +    
        +    private activeItem: MenuItem;
        +
        +    ngOnInit() {
        +        this.items = [
        +            {label: 'Stats', icon: 'fa-bar-chart'},
        +            {label: 'Calendar', icon: 'fa-calendar'},
        +            {label: 'Documentation', icon: 'fa-book'},
        +            {label: 'Support', icon: 'fa-support'},
        +            {label: 'Social', icon: 'fa-twitter'}
        +        ];
        +        
        +        this.activeItem = this.items[2];
        +    }
        +}
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        modelarraynullAn array of menuitems.
        activeItemMenuItemnullDefines the default active menuitem
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-tabmenuContainer element.
        ui-tabmenu-navList element of headers.
        ui-tabmenuitemMenuitem element.
        ui-menuitem-linkLink inside a menuitem.
        ui-menuitem-textLabel of a menuitem.
        ui-menuitem-iconIcon of a menuitem.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<p-tabMenu [model]="items"></p-tabMenu>
        +
        +
        + +
        +
        +export class TabMenuDemo {
        +    
        +    private items: MenuItem[];
        +
        +    ngOnInit() {
        +        this.items = [
        +            {label: 'Stats', icon: 'fa-bar-chart'},
        +            {label: 'Calendar', icon: 'fa-calendar'},
        +            {label: 'Documentation', icon: 'fa-book'},
        +            {label: 'Support', icon: 'fa-support'},
        +            {label: 'Social', icon: 'fa-twitter'}
        +        ];
        +    }
        +}
        +
        +
        +
        +
        +
        diff --git a/src/app/showcase/components/tabmenu/tabmenudemo.module.ts b/src/app/showcase/components/tabmenu/tabmenudemo.module.ts new file mode 100644 index 00000000000..174d00cdf90 --- /dev/null +++ b/src/app/showcase/components/tabmenu/tabmenudemo.module.ts @@ -0,0 +1,21 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {TabMenuDemo} from './tabmenudemo'; +import {TabMenuDemoRoutingModule} from './tabmenudemo-routing.module'; +import {TabMenuModule} from '../../../components/tabmenu/tabmenu'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + TabMenuDemoRoutingModule, + TabMenuModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + TabMenuDemo + ] +}) +export class TabMenuDemoModule {} diff --git a/src/app/showcase/components/tabmenu/tabmenudemo.ts b/src/app/showcase/components/tabmenu/tabmenudemo.ts new file mode 100644 index 00000000000..8313f6ffa5f --- /dev/null +++ b/src/app/showcase/components/tabmenu/tabmenudemo.ts @@ -0,0 +1,20 @@ +import {Component} from '@angular/core'; +import {MenuItem} from '../../../components/common/api'; + +@Component({ + templateUrl: './tabmenudemo.html' +}) +export class TabMenuDemo { + + private items: MenuItem[]; + + ngOnInit() { + this.items = [ + {label: 'Stats', icon: 'fa-bar-chart'}, + {label: 'Calendar', icon: 'fa-calendar'}, + {label: 'Documentation', icon: 'fa-book'}, + {label: 'Support', icon: 'fa-support'}, + {label: 'Social', icon: 'fa-twitter'} + ]; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/tabview/tabviewdemo-routing.module.ts b/src/app/showcase/components/tabview/tabviewdemo-routing.module.ts new file mode 100644 index 00000000000..319d13f1863 --- /dev/null +++ b/src/app/showcase/components/tabview/tabviewdemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {TabViewDemo} from './tabviewdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: TabViewDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class TabViewDemoRoutingModule {} diff --git a/src/app/showcase/components/tabview/tabviewdemo.html b/src/app/showcase/components/tabview/tabviewdemo.html new file mode 100644 index 00000000000..39e7e6ee5c9 --- /dev/null +++ b/src/app/showcase/components/tabview/tabviewdemo.html @@ -0,0 +1,443 @@ +
        +
        + TabView + TabView is a container component to group content with tabs. +
        +
        + +
        + + +

        Default

        + + + The story begins as Don Vito Corleone, the head of a New York Mafia family, overseeshis daughter's wedding. His beloved son ichael has just come home from the war, but does not intend to become part of his father's business. T hrough Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, kind and benevolent to those who give respect, but given to ruthless violence whenever anything stands against the good of the family. + + + Francis Ford Coppola's legendary continuation and sequel to his landmark 1972 film, The_Godfather parallels the young Vito Corleone's rise with his son Michael's spiritual fall, deepening The_Godfather's depiction of the dark side of the American dream. In the early 1900s, the child Vito flees his Sicilian village for America after the local Mafia kills his family. Vito struggles to make a living, legally or illegally, for his wife and growing brood in Little Italy, killing the local Black Hand Fanucci after he demands his customary cut of the tyro's business. With Fanucci gone, Vito's communal stature grows. + + + After a break of more than 15 years, director Francis Ford Coppola and writer Mario Puzo returned to the well for this third and final story of the fictional Corleone crime family. Two decades have passed, and crime kingpin Michael Corleone, now divorced from his wife Kay has nearly succeeded in keeping his promise that his family would one day be completely legitimate. + + + +

        Closable

        + + + The story begins as Don Vito Corleone, the head of a New York Mafia family, overseeshis daughter's wedding. His beloved son ichael has just come home from the war, but does not intend to become part of his father's business. T hrough Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, kind and benevolent to those who give respect, but given to ruthless violence whenever anything stands against the good of the family. + + + Francis Ford Coppola's legendary continuation and sequel to his landmark 1972 film, The_Godfather parallels the young Vito Corleone's rise with his son Michael's spiritual fall, deepening The_Godfather's depiction of the dark side of the American dream. In the early 1900s, the child Vito flees his Sicilian village for America after the local Mafia kills his family. Vito struggles to make a living, legally or illegally, for his wife and growing brood in Little Italy, killing the local Black Hand Fanucci after he demands his customary cut of the tyro's business. With Fanucci gone, Vito's communal stature grows. + + + After a break of more than 15 years, director Francis Ford Coppola and writer Mario Puzo returned to the well for this third and final story of the fictional Corleone crime family. Two decades have passed, and crime kingpin Michael Corleone, now divorced from his wife Kay has nearly succeeded in keeping his promise that his family would one day be completely legitimate. + + + +

        Event

        + + + The story begins as Don Vito Corleone, the head of a New York Mafia family, overseeshis daughter's wedding. His beloved son ichael has just come home from the war, but does not intend to become part of his father's business. T hrough Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, kind and benevolent to those who give respect, but given to ruthless violence whenever anything stands against the good of the family. + + + Francis Ford Coppola's legendary continuation and sequel to his landmark 1972 film, The_Godfather parallels the young Vito Corleone's rise with his son Michael's spiritual fall, deepening The_Godfather's depiction of the dark side of the American dream. In the early 1900s, the child Vito flees his Sicilian village for America after the local Mafia kills his family. Vito struggles to make a living, legally or illegally, for his wife and growing brood in Little Italy, killing the local Black Hand Fanucci after he demands his customary cut of the tyro's business. With Fanucci gone, Vito's communal stature grows. + + + After a break of more than 15 years, director Francis Ford Coppola and writer Mario Puzo returned to the well for this third and final story of the fictional Corleone crime family. Two decades have passed, and crime kingpin Michael Corleone, now divorced from his wife Kay has nearly succeeded in keeping his promise that his family would one day be completely legitimate. + + + After a break of more than 15 years, director Francis Ford Coppola and writer Mario Puzo returned to the well for this third and final story of the fictional Corleone crime family. Two decades have passed, and crime kingpin Michael Corleone, now divorced from his wife Kay has nearly succeeded in keeping his promise that his family would one day be completely legitimate. + + + +

        Orientation

        + + + The story begins as Don Vito Corleone, the head of a New York Mafia family, overseeshis daughter's wedding. His beloved son ichael has just come home from the war, but does not intend to become part of his father's business. T hrough Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, kind and benevolent to those who give respect, but given to ruthless violence whenever anything stands against the good of the family. + + + Francis Ford Coppola's legendary continuation and sequel to his landmark 1972 film, The_Godfather parallels the young Vito Corleone's rise with his son Michael's spiritual fall, deepening The_Godfather's depiction of the dark side of the American dream. In the early 1900s, the child Vito flees his Sicilian village for America after the local Mafia kills his family. Vito struggles to make a living, legally or illegally, for his wife and growing brood in Little Italy, killing the local Black Hand Fanucci after he demands his customary cut of the tyro's business. With Fanucci gone, Vito's communal stature grows. + + + After a break of more than 15 years, director Francis Ford Coppola and writer Mario Puzo returned to the well for this third and final story of the fictional Corleone crime family. Two decades have passed, and crime kingpin Michael Corleone, now divorced from his wife Kay has nearly succeeded in keeping his promise that his family would one day be completely legitimate. + + +
        + +
        + + +

        Import

        +
        +
        +import {TabViewModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Tabview element consists of one or more p-tabPanel elements. Header of the tab is defined using header attribute.

        + +
        +
        +<p-tabView>
        +    <p-tabPanel header="Header 1">
        +       Content 1
        +    </p-tabPanel>
        +    <p-tabPanel header="Header 2">
        +        Content 2
        +    </p-tabPanel>
        +    <p-tabPanel header="Header 3">
        +        Content 3    
        +    </p-tabPanel>
        +</p-tabView>
        +
        +
        + +

        Selection

        +

        First tab is selected by default, to customize this enable selected property on another panel.

        +
        +
        +<p-tabView>
        +    <p-tabPanel header="Header 1">
        +       Content 1
        +    </p-tabPanel>
        +    <p-tabPanel header="Header 2" [selected]="true">
        +        Content 2
        +    </p-tabPanel>
        +    <p-tabPanel header="Header 3">
        +        Content 3    
        +    </p-tabPanel>
        +</p-tabView>
        +
        +
        + +

        Closable

        +

        When closable attribute is enabled, an icon is displayed to close the tab. onClose event is fired when a tab is closed.

        +
        +
        +<p-tabPanel header="Header Text" [closable]="true">
        +    Content 1
        +</p-tabPanel>
        +
        +
        + +

        If you'd like to control whether a tab can be closed, enable controlClose property which gives you the control + to decide at onClose event. In this case, the event gets a 3rd parameter called close callback and invoking this function + actually closes the tab.

        +
        +
        +<p-tabView [controlClose]="true" (onClose)="handleClose($event)">
        +<p-tabPanel header="Header Text" [closable]="true">
        +    Content 1
        +</p-tabPanel>
        +</p-tabView>
        +
        +
        + +
        +
        +handleClose(e) {
        +   if(condition)
        +       e.close();
        +}
        +
        +
        + +

        Disabled

        +

        A tab can be disabled to prevent the content to be displayed by setting the disabled property on a panel.

        +
        +
        +<p-tabPanel header="Header Text" [disabled]="true">
        +    Content 1
        +</p-tabPanel>
        +
        +
        + +

        Icons

        +

        Icons can be placed at left and right of a header using leftIcon and rightIcon properties of tabPanel.

        +
        +
        +<p-tabPanel header="Header Text" leftIcon="fa-bell-o" rightIcon="fa-bookmark-o">;
        +    Content
        +</p-tabPanel>
        +
        +
        + +

        Orientation

        +

        TabView has four different orientations; "top", "bottom", "left" and "right". Top is the default one + and this can be changed using orientation attribute.

        +
        +
        +<p-tabView orientation="left">
        +
        +
        + +

        Attributes for TabView

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        orientationstringtopOrientation of tab headers.
        activeIndexnumbernullIndex of the active tab to change selected tab programmatically.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        +
        + +

        Attributes for TabPanel

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        headerstringnullOrientation of tab headers.
        selectedbooleanfalseDefines if tab is active.
        disabledbooleanfalseWhen true, tab cannot be activated.
        closablebooleanfalseDefines if tab can be removed.
        headerStylestringnullInline style of the tab header.
        headerStyleClassstringnullStyle class of the tab header.
        controlClosebooleanfalseWhether tab close is controlled at onClose event or not.
        lazybooleanfalseDefines whether the elements of an inactive panel are created on load or on demand when the panel gets selected.
        +
        + + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onChange + event.originalEvent: Click event
        + event.index: Index of the selected tab +
        Callback to invoke on tab change.
        onClose + event.originalEvent: Click event
        + event.index: Index of the closed tab
        + event.close: Callback to actually close the tab, only available if controlClose is enabled. +
        Callback to invoke on tab close.
        +
        +
        +
        +<p-tabView (onChange)="handleChange($event)">
        +
        +
        + +
        +
        +handleChange(e) {
        +    var index = e.index;
        +}
        +
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-tabviewContainer element
        ui-tabview-navContainer of headers.
        ui-tabview-selectedSelected tab header.
        ui-tabview-panelsContainer panels.
        ui-tabview-panelContent of a tab.
        +
        + +

        Dependencies

        +

        None.

        + +
        + + +
        +
        +<p-growl [value]="msgs"></p-growl>
        +
        +<h3 class="first">Default</h3>
        +<p-tabView>
        +    <p-tabPanel header="Godfather I" leftIcon="fa-calendar">
        +        The story begins as Don Vito Corleone, the head of a New York Mafia family, overseeshis daughter's wedding. His beloved son ichael has just come home from the war, but does not intend to become part of his father's business. T hrough Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, kind and benevolent to those who give respect, but given to ruthless violence whenever anything stands against the good of the family.
        +    </p-tabPanel>
        +    <p-tabPanel header="Godfather II" leftIcon="fa-print">
        +        Francis Ford Coppola's legendary continuation and sequel to his landmark 1972 film, The_Godfather parallels the young Vito Corleone's rise with his son Michael's spiritual fall, deepening The_Godfather's depiction of the dark side of the American dream. In the early 1900s, the child Vito flees his Sicilian village for America after the local Mafia kills his family. Vito struggles to make a living, legally or illegally, for his wife and growing brood in Little Italy, killing the local Black Hand Fanucci after he demands his customary cut of the tyro's business. With Fanucci gone, Vito's communal stature grows.
        +    </p-tabPanel>
        +    <p-tabPanel header="Godfather III" leftIcon="fa-bell-o" rightIcon="fa-bookmark-o">
        +        After a break of more than  15 years, director Francis Ford Coppola and writer Mario Puzo returned to the well for this third and final story of the fictional Corleone crime family. Two decades have passed, and crime kingpin Michael Corleone, now divorced from his wife Kay has nearly succeeded in keeping his promise that his family would one day be completely legitimate.
        +    </p-tabPanel>
        +</p-tabView>
        +
        +<h3>Closable</h3>
        +<p-tabView>
        +    <p-tabPanel header="Godfather I" [selected]="true">
        +        The story begins as Don Vito Corleone, the head of a New York Mafia family, overseeshis daughter's wedding. His beloved son ichael has just come home from the war, but does not intend to become part of his father's business. T hrough Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, kind and benevolent to those who give respect, but given to ruthless violence whenever anything stands against the good of the family.
        +    </p-tabPanel>
        +    <p-tabPanel header="Godfather II" [closable]="true">
        +        Francis Ford Coppola's legendary continuation and sequel to his landmark 1972 film, The_Godfather parallels the young Vito Corleone's rise with his son Michael's spiritual fall, deepening The_Godfather's depiction of the dark side of the American dream. In the early 1900s, the child Vito flees his Sicilian village for America after the local Mafia kills his family. Vito struggles to make a living, legally or illegally, for his wife and growing brood in Little Italy, killing the local Black Hand Fanucci after he demands his customary cut of the tyro's business. With Fanucci gone, Vito's communal stature grows.
        +    </p-tabPanel>
        +    <p-tabPanel header="Godfather III" [closable]="true">
        +        After a break of more than  15 years, director Francis Ford Coppola and writer Mario Puzo returned to the well for this third and final story of the fictional Corleone crime family. Two decades have passed, and crime kingpin Michael Corleone, now divorced from his wife Kay has nearly succeeded in keeping his promise that his family would one day be completely legitimate.
        +    </p-tabPanel>
        +</p-tabView>
        +
        +<h3>Event</h3>
        +<p-tabView (onChange)="onTabChange($event)">
        +    <p-tabPanel header="Godfather I">
        +        The story begins as Don Vito Corleone, the head of a New York Mafia family, overseeshis daughter's wedding. His beloved son ichael has just come home from the war, but does not intend to become part of his father's business. T hrough Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, kind and benevolent to those who give respect, but given to ruthless violence whenever anything stands against the good of the family.
        +    </p-tabPanel>
        +    <p-tabPanel header="Godfather II" [selected]="true">
        +        Francis Ford Coppola's legendary continuation and sequel to his landmark 1972 film, The_Godfather parallels the young Vito Corleone's rise with his son Michael's spiritual fall, deepening The_Godfather's depiction of the dark side of the American dream. In the early 1900s, the child Vito flees his Sicilian village for America after the local Mafia kills his family. Vito struggles to make a living, legally or illegally, for his wife and growing brood in Little Italy, killing the local Black Hand Fanucci after he demands his customary cut of the tyro's business. With Fanucci gone, Vito's communal stature grows.
        +    </p-tabPanel>
        +    <p-tabPanel header="Godfather III">
        +        After a break of more than  15 years, director Francis Ford Coppola and writer Mario Puzo returned to the well for this third and final story of the fictional Corleone crime family. Two decades have passed, and crime kingpin Michael Corleone, now divorced from his wife Kay has nearly succeeded in keeping his promise that his family would one day be completely legitimate.
        +    </p-tabPanel>
        +    <p-tabPanel header="Godfather IV" [disabled]="true">
        +        After a break of more than  15 years, director Francis Ford Coppola and writer Mario Puzo returned to the well for this third and final story of the fictional Corleone crime family. Two decades have passed, and crime kingpin Michael Corleone, now divorced from his wife Kay has nearly succeeded in keeping his promise that his family would one day be completely legitimate.
        +    </p-tabPanel>
        +</p-tabView>
        +
        +<h3>Orientation</h3>
        +<p-tabView orientation="left">
        +    <p-tabPanel header="Godfather I" [selected]="true">
        +        The story begins as Don Vito Corleone, the head of a New York Mafia family, overseeshis daughter's wedding. His beloved son ichael has just come home from the war, but does not intend to become part of his father's business. T hrough Michael's life the nature of the family business becomes clear. The business of the family is just like the head of the family, kind and benevolent to those who give respect, but given to ruthless violence whenever anything stands against the good of the family.
        +    </p-tabPanel>
        +     <p-tabPanel header="Godfather II">
        +        Francis Ford Coppola's legendary continuation and sequel to his landmark 1972 film, The_Godfather parallels the young Vito Corleone's rise with his son Michael's spiritual fall, deepening The_Godfather's depiction of the dark side of the American dream. In the early 1900s, the child Vito flees his Sicilian village for America after the local Mafia kills his family. Vito struggles to make a living, legally or illegally, for his wife and growing brood in Little Italy, killing the local Black Hand Fanucci after he demands his customary cut of the tyro's business. With Fanucci gone, Vito's communal stature grows.
        +    </p-tabPanel>
        +    <p-tabPanel header="Godfather III">
        +        After a break of more than  15 years, director Francis Ford Coppola and writer Mario Puzo returned to the well for this third and final story of the fictional Corleone crime family. Two decades have passed, and crime kingpin Michael Corleone, now divorced from his wife Kay has nearly succeeded in keeping his promise that his family would one day be completely legitimate.
        +    </p-tabPanel>
        +</p-tabView>
        +
        +
        + +
        +
        +export class TabViewDemo {
        +
        +    msgs: Message[];
        +    
        +    onTabChange(event) {
        +        this.msgs = [];
        +        this.msgs.push({severity:'info', summary:'Tab Expanded', detail: 'Index: ' + event.index});
        +    }
        +}
        +
        +
        +
        +
        +
        diff --git a/src/app/showcase/components/tabview/tabviewdemo.module.ts b/src/app/showcase/components/tabview/tabviewdemo.module.ts new file mode 100644 index 00000000000..a703218ee31 --- /dev/null +++ b/src/app/showcase/components/tabview/tabviewdemo.module.ts @@ -0,0 +1,21 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {TabViewDemo} from './tabviewdemo'; +import {TabViewDemoRoutingModule} from './tabviewdemo-routing.module'; +import {GrowlModule} from '../../../components/growl/growl'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + TabViewDemoRoutingModule, + GrowlModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + TabViewDemo + ] +}) +export class TabViewDemoModule {} diff --git a/src/app/showcase/components/tabview/tabviewdemo.ts b/src/app/showcase/components/tabview/tabviewdemo.ts new file mode 100644 index 00000000000..6bd7c8b4d5f --- /dev/null +++ b/src/app/showcase/components/tabview/tabviewdemo.ts @@ -0,0 +1,15 @@ +import {Component} from '@angular/core'; +import {Message} from '../../../components/common/api'; + +@Component({ + templateUrl: './tabviewdemo.html' +}) +export class TabViewDemo { + + msgs: Message[]; + + onTabChange(event) { + this.msgs = []; + this.msgs.push({severity:'info', summary:'Tab Expanded', detail: 'Index: ' + event.index}); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/terminal/terminaldemo-routing.module.ts b/src/app/showcase/components/terminal/terminaldemo-routing.module.ts new file mode 100644 index 00000000000..5607d8545a0 --- /dev/null +++ b/src/app/showcase/components/terminal/terminaldemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {TerminalDemo} from './terminaldemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: TerminalDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class TerminalDemoRoutingModule {} diff --git a/src/app/showcase/components/terminal/terminaldemo.html b/src/app/showcase/components/terminal/terminaldemo.html new file mode 100644 index 00000000000..09dd0025fd2 --- /dev/null +++ b/src/app/showcase/components/terminal/terminaldemo.html @@ -0,0 +1,174 @@ +
        +
        + Terminal + Terminal is a text based user interface. Enter "date" to display the current date. +
        +
        + +
        + +
        + +
        + + +

        Import

        +
        +
        +import {TerminalModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Terminal is defined using p-terminal element with a command handler and a response property. The entered command + is passed to the handler by the event parameter and the response is sent back using a binding to the response property.

        +
        +
        +export class TerminalDemo {
        +    
        +    response: string;
        +
        +    onCommand(event) {
        +        //event.command = entered command
        +        //in a real application connect to remote service to process the command and update the response field in return
        +        this.response = 'Unknown command: ' +event.command;
        +    }
        +}
        +
        +
        + +
        +
        +<p-terminal (handler)="onCommand($event)" [response]="response" welcomeMessage="Welcome to PrimeNG" prompt="primeng $"></p-terminal>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        welcomeMessagestringnullInitial text to display on terminal.
        promptstringnullPrompt text for each command.
        responsestringnullResponse to give for a command.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + +
        NameParametersDescription
        handlerevent.originalEvent: browser event
        + event.command: command to process
        Callback to invoke when user enters a command
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-terminalContainer element.
        ui-terminal-contentContent of terminal.
        ui-terminal-content-promptPrompt text.
        ui-terminal-inputInput element to enter commands.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<p-terminal (handler)="onCommand($event)" [response]="response" welcomeMessage="Welcome to PrimeNG" prompt="primeng $"></p-terminal>
        +
        +
        + +
        +
        +export class TerminalDemo {
        +    
        +    response: string;
        +
        +    onCommand(event) {
        +        if(event.command === 'date')
        +            this.response = new Date().toDateString();
        +        else
        +            this.response = 'Unknown command: ' + event.command;
        +    }
        +}
        +
        +
        +
        + + +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/terminal/terminaldemo.module.ts b/src/app/showcase/components/terminal/terminaldemo.module.ts new file mode 100644 index 00000000000..e0b6d4abaee --- /dev/null +++ b/src/app/showcase/components/terminal/terminaldemo.module.ts @@ -0,0 +1,21 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {TerminalDemo} from './terminaldemo'; +import {TerminalDemoRoutingModule} from './terminaldemo-routing.module'; +import {TerminalModule} from '../../../components/terminal/terminal'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + TerminalDemoRoutingModule, + TerminalModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + TerminalDemo + ] +}) +export class TerminalDemoModule {} diff --git a/src/app/showcase/components/terminal/terminaldemo.ts b/src/app/showcase/components/terminal/terminaldemo.ts new file mode 100644 index 00000000000..58d548aaaee --- /dev/null +++ b/src/app/showcase/components/terminal/terminaldemo.ts @@ -0,0 +1,16 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './terminaldemo.html' +}) +export class TerminalDemo { + + response: string; + + onCommand(event) { + if(event.command === 'date') + this.response = new Date().toDateString(); + else + this.response = 'Unknown command: ' + event.command; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/theming/theming-routing.module.ts b/src/app/showcase/components/theming/theming-routing.module.ts new file mode 100644 index 00000000000..e8414257dcd --- /dev/null +++ b/src/app/showcase/components/theming/theming-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router'; +import {ThemingComponent} from './theming.component'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: ThemingComponent} + ]) + ], + exports: [ + RouterModule + ] +}) +export class ThemingRoutingModule {} \ No newline at end of file diff --git a/src/app/showcase/components/theming/theming.component.html b/src/app/showcase/components/theming/theming.component.html new file mode 100644 index 00000000000..c8d1dc63bb7 --- /dev/null +++ b/src/app/showcase/components/theming/theming.component.html @@ -0,0 +1,82 @@ +
        +
        + Theming + PrimeNG is based on ThemeRoller CSS Framework. +
        +
        + +
        +

        Structural CSS

        +

        These style classes define the skeleton of the components and include css properties such as margin, padding, display type, dimensions and positioning.

        + +

        Skinning CSS

        +

        Skinning defines the look and feel properties like colors, border colors, background images.

        + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        Style ClassApplies
        ui-widgetAll PrimeNG components
        ui-widget-headerHeader section of a component
        ui-widget-contentContent section of a component
        ui-state-defaultDefault state of a clickable element
        ui-state-hoverHover state of a clickable element like mouse over
        ui-state-activeActive state of a clickable element like mouse press
        ui-state-highlightHighlighed elements
        ui-state-disabledDisabled elements
        faIcon elements based on font awesome
        +
        + +

        These classes are not aware of structural css like margins and paddings, mostly they only define colors. This clean separation brings great flexibility in theming because you don’t need to know each and every skinning selectors of components to change their style.

        + +

        For example Panel component’s header section has the "ui-panel-titlebar" structural class, to change the color of a panel header you don’t need to about this class as "ui-widget-header" defines colors for panel header.

        + +

        Free Themes

        +

        16 free themes are available for PrimeNG, these include the themeroller themes, twitter bootstrap theme and our custom themes. ThemeSwitcher on the top right section + of the page dynamically changes the theme at demo pages. Themes are distributed along with PrimeNG itself. In addition, online ThemeRoller designer allows you to create a PrimeNG theme.

        + +

        Font-size of free themes use em to define the font size of the widgets using .ui-widget class. This is 1em by default and it is suggested to define a base font-size at the body element of your application to adjust the size of + components.

        + +

        Premium Layouts and Themes

        +

        PrimeNG also supports premium themes and layouts such as Ultima.

        + + + Ultima + + +
        \ No newline at end of file diff --git a/src/app/showcase/components/theming/theming.component.ts b/src/app/showcase/components/theming/theming.component.ts new file mode 100644 index 00000000000..82c9868aae2 --- /dev/null +++ b/src/app/showcase/components/theming/theming.component.ts @@ -0,0 +1,8 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './theming.component.html' +}) +export class ThemingComponent { + +} \ No newline at end of file diff --git a/src/app/showcase/components/theming/theming.module.ts b/src/app/showcase/components/theming/theming.module.ts new file mode 100644 index 00000000000..78098fd2b6e --- /dev/null +++ b/src/app/showcase/components/theming/theming.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {ThemingComponent} from './theming.component'; +import {ThemingRoutingModule} from './theming-routing.module'; + +@NgModule({ + imports: [ + CommonModule, + ThemingRoutingModule + ], + declarations: [ + ThemingComponent + ] +}) +export class ThemingModule {} \ No newline at end of file diff --git a/src/app/showcase/components/tieredmenu/tieredmenudemo-routing.module.ts b/src/app/showcase/components/tieredmenu/tieredmenudemo-routing.module.ts new file mode 100644 index 00000000000..6106c8b6422 --- /dev/null +++ b/src/app/showcase/components/tieredmenu/tieredmenudemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {TieredMenuDemo} from './tieredmenudemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: TieredMenuDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class TieredMenuDemoRoutingModule {} diff --git a/src/app/showcase/components/tieredmenu/tieredmenudemo.html b/src/app/showcase/components/tieredmenu/tieredmenudemo.html new file mode 100644 index 00000000000..80c7cc26771 --- /dev/null +++ b/src/app/showcase/components/tieredmenu/tieredmenudemo.html @@ -0,0 +1,296 @@ +
        +
        + Tiered Menu + TieredMenu displays submenus in nested overlays. +
        +
        + +
        +

        Default

        + + +

        Popup

        + + +
        + +
        + + +

        Import

        +
        +
        +import {TieredMenuModule,MenuItem} from 'primeng/primeng';
        +
        +
        + +

        MenuModel API

        +

        TieredMenu uses the common menumodel api to define its items, visit MenuModel API for details.

        + +

        Getting Started

        +

        TieredMenu requires nested menuitems as its model.

        +
        +
        +<p-tieredMenu [model]="items"></p-tieredMenu>
        +
        +
        + +
        +
        +export class TieredMenuDemo {
        +
        +    private items: MenuItem[];
        +
        +    ngOnInit() {
        +        this.items = [
        +            {
        +                label: 'File',
        +                items: [{
        +                        label: 'New', 
        +                        icon: 'fa-plus',
        +                        items: [
        +                            {label: 'Project'},
        +                            {label: 'Other'},
        +                        ]
        +                    },
        +                    {label: 'Open'},
        +                    {label: 'Quit'}
        +                ]
        +            },
        +            {
        +                label: 'Edit',
        +                icon: 'fa-edit',
        +                items: [
        +                    {label: 'Undo', icon: 'fa-mail-forward'},
        +                    {label: 'Redo', icon: 'fa-mail-reply'}
        +                ]
        +            }
        +        ];
        +    }
        +}
        +
        +
        + +

        Popup Mode

        +

        Menu is inline by default, popup mode is also supported by enabling popup property and calling toggle method by passing the event + from the anchor element.

        +
        +
        +<p-tieredMenu #menu [model]="items" [popup]="true"></p-tieredMenu>
        +<button #btn type="button" pButton icon="fa fa-list" label="Show" (click)="menu.toggle($event)"></button>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        modelarraynullAn array of menuitems.
        popupbooleanfalseDefines if menu would displayed as a popup.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        +
        + +

        Methods

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        toggleevent: browser eventToggles the visibility of the popup menu.
        showevent: browser eventDisplays the popup menu.
        hide-Hides the popup menu.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-tieredmenuContainer element.
        ui-menu-listList element.
        ui-menuitemMenuitem element.
        ui-menuitem-textLabel of a menuitem.
        ui-menuitem-iconIcon of a menuitem.
        ui-submenu-iconArrow icon of a submenu.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<h3 class="first">Default</h3>
        +<p-tieredMenu [model]="items"></p-tieredMenu>
        +
        +<h3>Popup</h3>
        +<p-tieredMenu #menu [model]="items" [popup]="true"></p-tieredMenu>
        +<button #btn type="button" pButton icon="fa fa-list" label="Show" (click)="menu.toggle($event)"></button>
        +
        +
        + +
        +
        +export class TieredMenuDemo {
        +
        +    private items: MenuItem[];
        +
        +    ngOnInit() {
        +        this.items = [
        +            {
        +                label: 'File',
        +                icon: 'fa-file-o',
        +                items: [{
        +                        label: 'New', 
        +                        icon: 'fa-plus',
        +                        items: [
        +                            {label: 'Project'},
        +                            {label: 'Other'},
        +                        ]
        +                    },
        +                    {label: 'Open'},
        +                    {label: 'Quit'}
        +                ]
        +            },
        +            {
        +                label: 'Edit',
        +                icon: 'fa-edit',
        +                items: [
        +                    {label: 'Undo', icon: 'fa-mail-forward'},
        +                    {label: 'Redo', icon: 'fa-mail-reply'}
        +                ]
        +            },
        +            {
        +                label: 'Help',
        +                icon: 'fa-question',
        +                items: [
        +                    {
        +                        label: 'Contents'
        +                    },
        +                    {
        +                        label: 'Search', 
        +                        icon: 'fa-search', 
        +                        items: [
        +                            {
        +                                label: 'Text', 
        +                                items: [
        +                                    {
        +                                        label: 'Workspace'
        +                                    }
        +                                ]
        +                            },
        +                            {
        +                                label: 'File'
        +                            }
        +                    ]}
        +                ]
        +            },
        +            {
        +                label: 'Actions',
        +                icon: 'fa-gear',
        +                items: [
        +                    {
        +                        label: 'Edit',
        +                        icon: 'fa-refresh',
        +                        items: [
        +                            {label: 'Save', icon: 'fa-save'},
        +                            {label: 'Update', icon: 'fa-save'},
        +                        ]
        +                    },
        +                    {
        +                        label: 'Other',
        +                        icon: 'fa-phone',
        +                        items: [
        +                            {label: 'Delete', icon: 'fa-minus'}
        +                        ]
        +                    }
        +                ]
        +            },
        +            {
        +                label: 'Quit', icon: 'fa-minus'
        +            }
        +        ];
        +    }
        +}
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/tieredmenu/tieredmenudemo.module.ts b/src/app/showcase/components/tieredmenu/tieredmenudemo.module.ts new file mode 100644 index 00000000000..4e49a42060d --- /dev/null +++ b/src/app/showcase/components/tieredmenu/tieredmenudemo.module.ts @@ -0,0 +1,23 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {TieredMenuDemo} from './tieredmenudemo'; +import {TieredMenuDemoRoutingModule} from './tieredmenudemo-routing.module'; +import {TieredMenuModule} from '../../../components/tieredmenu/tieredmenu'; +import {ButtonModule} from '../../../components/button/button'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + TieredMenuDemoRoutingModule, + TieredMenuModule, + ButtonModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + TieredMenuDemo + ] +}) +export class TieredMenuDemoModule {} diff --git a/src/app/showcase/components/tieredmenu/tieredmenudemo.ts b/src/app/showcase/components/tieredmenu/tieredmenudemo.ts new file mode 100644 index 00000000000..dbced5b1e46 --- /dev/null +++ b/src/app/showcase/components/tieredmenu/tieredmenudemo.ts @@ -0,0 +1,87 @@ +import {Component} from '@angular/core'; +import {MenuItem} from '../../../components/common/api'; + +@Component({ + templateUrl: './tieredmenudemo.html' +}) +export class TieredMenuDemo { + + private items: MenuItem[]; + + ngOnInit() { + this.items = [ + { + label: 'File', + icon: 'fa-file-o', + items: [{ + label: 'New', + icon: 'fa-plus', + items: [ + {label: 'Project'}, + {label: 'Other'}, + ] + }, + {label: 'Open'}, + {label: 'Quit'} + ] + }, + { + label: 'Edit', + icon: 'fa-edit', + items: [ + {label: 'Undo', icon: 'fa-mail-forward'}, + {label: 'Redo', icon: 'fa-mail-reply'} + ] + }, + { + label: 'Help', + icon: 'fa-question', + items: [ + { + label: 'Contents' + }, + { + label: 'Search', + icon: 'fa-search', + items: [ + { + label: 'Text', + items: [ + { + label: 'Workspace' + } + ] + }, + { + label: 'File' + } + ]} + ] + }, + { + label: 'Actions', + icon: 'fa-gear', + items: [ + { + label: 'Edit', + icon: 'fa-refresh', + items: [ + {label: 'Save', icon: 'fa-save'}, + {label: 'Update', icon: 'fa-save'}, + ] + }, + { + label: 'Other', + icon: 'fa-phone', + items: [ + {label: 'Delete', icon: 'fa-minus'} + ] + } + ] + }, + { + label: 'Quit', icon: 'fa-minus' + } + ]; + } +} \ No newline at end of file diff --git a/src/app/showcase/components/togglebutton/togglebuttondemo-routing.module.ts b/src/app/showcase/components/togglebutton/togglebuttondemo-routing.module.ts new file mode 100644 index 00000000000..50d88b73706 --- /dev/null +++ b/src/app/showcase/components/togglebutton/togglebuttondemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {ToggleButtonDemo} from './togglebuttondemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: ToggleButtonDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class ToggleButtonDemoRoutingModule {} diff --git a/src/app/showcase/components/togglebutton/togglebuttondemo.html b/src/app/showcase/components/togglebutton/togglebuttondemo.html new file mode 100644 index 00000000000..e056e86a655 --- /dev/null +++ b/src/app/showcase/components/togglebutton/togglebuttondemo.html @@ -0,0 +1,233 @@ +
        +
        + Togglebutton + ToggleButton is used to select a boolean value using a button. +
        +
        + +
        +

        Basic - ({{checked1}})

        + + +

        Customized - ({{checked2}})

        + +
        + +
        + + +

        Import

        +
        +
        +import {ToggleButtonModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Two-way binding to a boolean property is defined using the standard ngModel directive.

        + +
        +
        +<p-toggleButton [(ngModel)]="checked"></p-toggleButton>
        +
        +
        + +
        +
        +export class ModelComponent {
        +
        +    checked: boolean;
        +
        +}
        +
        +
        + +

        As model is two-way binding enabled, setting the bound value as true displays the state as checked.

        +
        +
        +export class ModelComponent {
        +
        +   checked: boolean = true;
        +
        +}
        +
        +
        + +

        Model Driven Forms

        +

        ToggleButton can be used in a model driven form as well.

        +
        +
        +<p-toggleButton formControlName="agreed"></p-toggleButton>
        +
        +
        + +

        Customization

        +

        Icons and Labels can be customized using onLabel, offLabel, onIcon and OffIcon attributes.

        +
        +
        +<p-toggleButton onLabel="I confirm" offLabel="I reject" 
        +        onIcon="fa-check-square" offIcon="fa-square" [(ngModel)]="val"></p-toggleButton>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        onLabelstringYesLabel for the on state.
        offLabelstringNoLabel for the off state.
        onIconstringnullIcon for the on state.
        offIconstringnullIcon for the off state.
        stylestringnullInline style of the element.
        styleClassstringnullStyle class of the element.
        disabledbooleanfalseWhen present, it specifies that the element should be disabled.
        tabindexnumbernullIndex of the element in tabbing order.
        inputIdstringnullIdentifier of the focus input to match a label defined for the component.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + +
        NameParametersDescription
        onChangeevent.originalEvent: browser event
        + evebt.checked: boolean value to represent checked state.
        Callback to invoke on state change.
        +
        +
        +
        +<p-toggleButton (onChange)="handleChange($event)" [(ngModel)]="val">
        +
        +
        +
        +
        +export class ModelComponent {
        +    
        +    handleChange(e) {
        +        var isChecked = e.checked;
        +    }
        +}
        +
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-togglebuttonContainer element
        ui-button-icon-leftIcon element.
        ui-button-textLabel element.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<h3 class="first">Basic - ({{checked1}})</h3>
        +<p-toggleButton [(ngModel)]="checked1" [style]="{'width':'150px'}"></p-toggleButton>
        +
        +<h3>Customized - ({{checked2}})</h3>
        +<p-toggleButton [(ngModel)]="checked2" onLabel="I confirm" offLabel="I reject" onIcon="fa-check-square" offIcon="fa-square" [style]="{'width':'150px'}"></p-toggleButton>
        +
        +
        + +
        +
        +export class ToggleButtonDemo {
        +    
        +    checked1: boolean = false;
        +
        +    checked2: boolean = true;
        +}
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/togglebutton/togglebuttondemo.module.ts b/src/app/showcase/components/togglebutton/togglebuttondemo.module.ts new file mode 100644 index 00000000000..9449f973f12 --- /dev/null +++ b/src/app/showcase/components/togglebutton/togglebuttondemo.module.ts @@ -0,0 +1,23 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {ToggleButtonDemo} from './togglebuttondemo'; +import {ToggleButtonDemoRoutingModule} from './togglebuttondemo-routing.module'; +import {ToggleButtonModule} from '../../../components/togglebutton/togglebutton'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + ToggleButtonDemoRoutingModule, + ToggleButtonModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + ToggleButtonDemo + ] +}) +export class ToggleButtonDemoModule {} diff --git a/src/app/showcase/components/togglebutton/togglebuttondemo.ts b/src/app/showcase/components/togglebutton/togglebuttondemo.ts new file mode 100644 index 00000000000..baa8d0d971b --- /dev/null +++ b/src/app/showcase/components/togglebutton/togglebuttondemo.ts @@ -0,0 +1,11 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './togglebuttondemo.html' +}) +export class ToggleButtonDemo { + + checked1: boolean = false; + + checked2: boolean = true; +} \ No newline at end of file diff --git a/src/app/showcase/components/toolbar/toolbardemo-routing.module.ts b/src/app/showcase/components/toolbar/toolbardemo-routing.module.ts new file mode 100644 index 00000000000..894bb91b4bc --- /dev/null +++ b/src/app/showcase/components/toolbar/toolbardemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {ToolbarDemo} from './toolbardemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: ToolbarDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class ToolbarDemoRoutingModule {} diff --git a/src/app/showcase/components/toolbar/toolbardemo.html b/src/app/showcase/components/toolbar/toolbardemo.html new file mode 100644 index 00000000000..9539d5017ed --- /dev/null +++ b/src/app/showcase/components/toolbar/toolbardemo.html @@ -0,0 +1,146 @@ +
        +
        + Toolbar + Toolbar is a grouping component for buttons and other content. +
        +
        + +
        + +
        + + + + + + +
        + +
        + + + + +
        +
        +
        + +
        + + +

        Import

        +
        +
        +import {ToolbarModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Toolbar is a container component defined using p-toolbar element. Left aligned content is placed inside a div + having .ui-toolbar-group-left class and similarly .ui-toolbar-group-right for right alignment.

        +
        +
        +<p-toolbar>
        +    <div class="ui-toolbar-group-left">
        +        <button pButton type="button" label="New" icon="fa-plus"></button>
        +        <button pButton type="button" label="Open" icon="fa-folder-open"></button>
        +            
        +        <i class="fa fa-bars"></i>
        +        
        +        <p-splitButton label="Save" icon="fa-check" [model]="items"></p-splitButton>
        +    </div>
        +    
        +    <div class="ui-toolbar-group-right">
        +        <button pButton type="button" icon="fa-search"></button>
        +        <i class="fa fa-bars"></i>
        +        <button pButton type="button" icon="fa-refresh"></button>
        +        <button pButton type="button" icon="fa-trash"></button>
        +    </div>
        +</p-toolbar>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-toolbarMain container element.
        ui-toolbar-group-leftLeft content container.
        ui-toolbar-group-rightRight content container.
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<p-toolbar>
        +    <div class="ui-toolbar-group-left">
        +        <button pButton type="button" label="New" icon="fa-plus"></button>
        +        <button pButton type="button" label="Open" icon="fa-folder-open"></button>
        +            
        +        <i class="fa fa-bars"></i>
        +        
        +        <p-splitButton label="Save" icon="fa-check" (onClick)="save()" [model]="items"></p-splitButton>
        +    </div>
        +    
        +    <div class="ui-toolbar-group-right">
        +        <button pButton type="button" icon="fa-search"></button>
        +        <i class="fa fa-bars"></i>
        +        <button pButton type="button" icon="fa-refresh"></button>
        +        <button pButton type="button" icon="fa-trash"></button>
        +    </div>
        +</p-toolbar>
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/toolbar/toolbardemo.module.ts b/src/app/showcase/components/toolbar/toolbardemo.module.ts new file mode 100644 index 00000000000..2fd9fdd1f52 --- /dev/null +++ b/src/app/showcase/components/toolbar/toolbardemo.module.ts @@ -0,0 +1,25 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {ToolbarDemo} from './toolbardemo'; +import {ToolbarDemoRoutingModule} from './toolbardemo-routing.module'; +import {ToolbarModule} from '../../../components/toolbar/toolbar'; +import {ButtonModule} from '../../../components/button/button'; +import {SplitButtonModule} from '../../../components/splitbutton/splitbutton'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + ToolbarDemoRoutingModule, + ToolbarModule, + ButtonModule, + SplitButtonModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + ToolbarDemo + ] +}) +export class ToolbarDemoModule {} diff --git a/src/app/showcase/components/toolbar/toolbardemo.ts b/src/app/showcase/components/toolbar/toolbardemo.ts new file mode 100644 index 00000000000..fc9d01a2ea3 --- /dev/null +++ b/src/app/showcase/components/toolbar/toolbardemo.ts @@ -0,0 +1,17 @@ +import {Component,OnInit} from '@angular/core'; +import {MenuItem} from '../../../components/common/api'; + +@Component({ + templateUrl: './toolbardemo.html' +}) +export class ToolbarDemo implements OnInit { + + items: MenuItem[]; + + ngOnInit() { + this.items = [ + {label: 'Angular.io', icon: 'fa-link', url: 'http://angular.io'}, + {label: 'Theming', icon: 'fa-paint-brush', routerLink: ['/theming']} + ]; + } +} diff --git a/src/app/showcase/components/tooltip/tooltipdemo-routing.module.ts b/src/app/showcase/components/tooltip/tooltipdemo-routing.module.ts new file mode 100644 index 00000000000..6e391d55fa5 --- /dev/null +++ b/src/app/showcase/components/tooltip/tooltipdemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {TooltipDemo} from './tooltipdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: TooltipDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class TooltipDemoRoutingModule {} diff --git a/src/app/showcase/components/tooltip/tooltipdemo.html b/src/app/showcase/components/tooltip/tooltipdemo.html new file mode 100644 index 00000000000..2267b0773c8 --- /dev/null +++ b/src/app/showcase/components/tooltip/tooltipdemo.html @@ -0,0 +1,203 @@ +
        +
        + Tooltip + Tooltip provides advisory information for a component. +
        +
        + +
        +

        Positions

        +
        +
        +
        + +
        +
        + +
        +
        + +
        +
        + +
        +
        +
        + +

        Focus and Blur

        + +
        + +
        + + +

        Import

        +
        +
        +import {TooltipModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Tooltip is applied to an element with pTooltip directive where the value of the directive defines the text to display.

        + +
        +
        +<input type="text" pTooltip="Enter your username">
        +
        +
        + +

        Position

        +

        There are four choices to position the tooltip, default value is "right" and alternatives are "top", "bottom", "left". Position is + specified using tooltipPosition attribute.

        + +
        +
        +<input type="text" pTooltip="Enter your username" tooltipPosition="top">
        +
        +
        + +

        Events

        +

        Tooltip gets displayed on hover event of its target by default, other option is the focus event to display and blur to hide.

        + +
        +
        +<input type="text" pTooltip="Enter your username" tooltipPosition="top" tooltipEvent="focus">
        +
        +
        + +

        Scrolling Containers

        +

        When placed inside a scrolling container like an overflown div, tooltip must be appended to another element that has + relative positioning instead of document body which is the default.

        +
        +
        +<div #container style="display:inline-block;position:relative">
        +    <input type="text" pInputText pTooltip="Enter your username" placeholder="Right" [appendTo]="container">
        +</div>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        pTooltipstringnullText of the tooltip.
        tooltipPositionstringrightPosition of the tooltip, valid values are right, left, top and bottom.
        tooltipEventstringhoverEvent to show the tooltip, valid values are hover and focus.
        positionStylestringabsoluteType of CSS position.
        tooltipDisabledbooleanfalseWhen present, it specifies that the component should be disabled.
        appendTostringanyTarget element to attach the overlay, valid values are "body", "target" or a local ng-template variable of another element.
        tooltipStyleClassstringnullStyle class of the tooltip.
        escapebooleantrueBy default the tooltip contents are rendered as text. Set to false to support html tags in the content
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-tooltipContainer element
        ui-tooltip-arrowArrow of the tooltip
        ui-tooltip-textText of the tooltip
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<h3 class="first">Positions</h3>
        +<div class="ui-grid ui-grid-responsive ui-fluid ui-grid-pad">
        +    <div class="ui-grid-row">
        +        <div class="ui-grid-col-3">
        +            <input type="text" pInputText pTooltip="Enter your username" placeholder="Right">
        +        </div>
        +        <div class="ui-grid-col-3">
        +            <input type="text" pInputText pTooltip="Enter your username" tooltipPosition="top" placeholder="Top">
        +        </div>
        +        <div class="ui-grid-col-3">
        +            <input type="text" pInputText pTooltip="Enter your username" tooltipPosition="bottom" placeholder="Bottom">
        +        </div>
        +        <div class="ui-grid-col-3">
        +            <input type="text" pInputText pTooltip="Enter your username" tooltipPosition="left" placeholder="Left">
        +        </div>
        +    </div>
        +</div>
        +
        +<h3>Focus and Blur</h3>
        +<input type="text" pInputText pTooltip="Enter your username" placeholder="Right" tooltipEvent="focus" style="margin-left:10px">
        +
        +
        + +
        +
        +
        diff --git a/src/app/showcase/components/tooltip/tooltipdemo.module.ts b/src/app/showcase/components/tooltip/tooltipdemo.module.ts new file mode 100644 index 00000000000..ff6a17e9def --- /dev/null +++ b/src/app/showcase/components/tooltip/tooltipdemo.module.ts @@ -0,0 +1,23 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {TooltipDemo} from './tooltipdemo'; +import {TooltipDemoRoutingModule} from './tooltipdemo-routing.module'; +import {TooltipModule} from '../../../components/tooltip/tooltip'; +import {InputTextModule} from '../../../components/inputtext/inputtext'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + TooltipDemoRoutingModule, + TooltipModule, + InputTextModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + TooltipDemo + ] +}) +export class TooltipDemoModule {} diff --git a/src/app/showcase/components/tooltip/tooltipdemo.ts b/src/app/showcase/components/tooltip/tooltipdemo.ts new file mode 100644 index 00000000000..b82120d4a13 --- /dev/null +++ b/src/app/showcase/components/tooltip/tooltipdemo.ts @@ -0,0 +1,8 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './tooltipdemo.html' +}) +export class TooltipDemo { + +} \ No newline at end of file diff --git a/src/app/showcase/components/tree/treedemo-routing.module.ts b/src/app/showcase/components/tree/treedemo-routing.module.ts new file mode 100644 index 00000000000..5caea24ca20 --- /dev/null +++ b/src/app/showcase/components/tree/treedemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {TreeDemo} from './treedemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: TreeDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class TreeDemoRoutingModule {} diff --git a/src/app/showcase/components/tree/treedemo.html b/src/app/showcase/components/tree/treedemo.html new file mode 100644 index 00000000000..0517a880916 --- /dev/null +++ b/src/app/showcase/components/tree/treedemo.html @@ -0,0 +1,943 @@ +
        +
        + Tree + Tree is used to display hierarchical data. +
        +
        + +
        + + +

        Basic

        + + +

        Single Selection

        + +
        Selected Node: {{selectedFile ? selectedFile.label : 'none'}}
        + +

        Multiple Selection with Metakey

        + +
        Selected Nodes: {{file.label}}
        + +

        Multiple Selection with Checkbox

        + +
        Selected Nodes: {{file.label}}
        + +

        Lazy Loading

        + + +

        Template

        + + + + + + +

        Context Menu

        + + + +

        DragDrop

        +
        +
        +

        Files

        + +
        + +
        + +
        + +
        +

        Server 1

        + +
        + +
        + +
        + +
        +

        Server 2

        + +
        + +
        + +
        +
        + +

        Programatic Tree Expansion

        + +
        + + +
        + +

        Horizontal Tree

        + +
        Selected Node: {{selectedFile3 ? selectedFile3.label : 'none'}}
        +
        + +
        + + +

        Import

        +
        +
        +import {TreeModule,TreeNode} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        Tree component requires an array of TreeNode objects as its value. Let's begin with the TreeNode api. Note that all of the properties are optional.

        + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        labelstringnullLabel of the node.
        dataanynullData represented by the node.
        iconstringnullIcon of the node to display next to content.
        expandedIconstringnullIcon to use in expanded state.
        collapsedIconstringnullIcon to use in collapsed state.
        childrenTreeNode[]nullAn array of treenodes as children.
        leafbooleannullSpecifies if the node has children. Used in lazy loading.
        stylestringnullInline style of the node.
        styleClassstringnullStyle class of the node.
        expandedbooleannullWhether the node is in an expanded or collapsed state.
        typestringnullType of the node to match ng-template type.
        parentTreeNodenullParent of the node.
        styleClassstringnullName of the style class for the node element.
        draggablebooleannullWhether to disable dragging for a particular node even if draggableNodes is enabled.
        droppablebooleannullWhether to disable dropping for a particular node even if droppableNodes is enabled.
        selectablebooleannullUsed to disable selection of a particular node.
        +
        + +

        Most of the time, nodes will be loaded from a remote datasoure, here is an example NodeService that fetches the data from a json file.

        +
        +
        +@Injectable()
        +export class NodeService {
        +    
        +    constructor(private http: Http) {}
        +
        +    getFiles() {
        +        return this.http.get('showcase/resources/data/files.json')
        +                    .toPromise()
        +                    .then(res => <TreeNode[]> res.json().data);
        +    }
        +}
        +
        +
        + +

        The files.json file consists of sample data. In a real application, this should be a dynamic response generated from the remote call.

        +
        +
        +{
        +    "data": 
        +    [
        +        {
        +            "label": "Documents",
        +            "data": "Documents Folder",
        +            "expandedIcon": "fa-folder-open",
        +            "collapsedIcon": "fa-folder",
        +            "children": [{
        +                    "label": "Work",
        +                    "data": "Work Folder",
        +                    "expandedIcon": "fa-folder-open",
        +                    "collapsedIcon": "fa-folder",
        +                    "children": [{"label": "Expenses.doc", "icon": "fa-file-word-o", "data": "Expenses Document"}, {"label": "Resume.doc", "icon": "fa-file-word-o", "data": "Resume Document"}]
        +                },
        +                {
        +                    "label": "Home",
        +                    "data": "Home Folder",
        +                    "expandedIcon": "fa-folder-open",
        +                    "collapsedIcon": "fa-folder",
        +                    "children": [{"label": "Invoices.txt", "icon": "fa-file-word-o", "data": "Invoices for this month"}]
        +                }]
        +        },
        +        {
        +            "label": "Pictures",
        +            "data": "Pictures Folder",
        +            "expandedIcon": "fa-folder-open",
        +            "collapsedIcon": "fa-folder",
        +            "children": [
        +                {"label": "barcelona.jpg", "icon": "fa-file-image-o", "data": "Barcelona Photo"},
        +                {"label": "logo.jpg", "icon": "fa-file-image-o", "data": "PrimeFaces Logo"},
        +                {"label": "primeui.png", "icon": "fa-file-image-o", "data": "PrimeUI Logo"}]
        +        },
        +        {
        +            "label": "Movies",
        +            "data": "Movies Folder",
        +            "expandedIcon": "fa-folder-open",
        +            "collapsedIcon": "fa-folder",
        +            "children": [{
        +                    "label": "Al Pacino",
        +                    "data": "Pacino Movies",
        +                    "children": [{"label": "Scarface", "icon": "fa-file-video-o", "data": "Scarface Movie"}, {"label": "Serpico", "icon": "fa-file-video-o", "data": "Serpico Movie"}]
        +                },
        +                {
        +                    "label": "Robert De Niro",
        +                    "data": "De Niro Movies",
        +                    "children": [{"label": "Goodfellas", "icon": "fa-file-video-o", "data": "Goodfellas Movie"}, {"label": "Untouchables", "icon": "fa-file-video-o", "data": "Untouchables Movie"}]
        +                }]
        +        }
        +    ]
        +}
        +
        +
        + +

        The component that uses this service makes a call to getFiles() and assigns them back to files property that is bound to the tree.

        + +
        +
        +export class TreeDemoComponent implements OnInit {
        +    
        +    files: TreeNode[];
        +
        +    constructor(private nodeService: NodeService) {}
        +    
        +    ngOnInit() {
        +        this.nodeService.getFiles().then(files => this.files = files);
        +    }
        +
        +}
        +
        +
        + +
        +
        +<p-tree [value]="files"></p-tree>
        +
        +
        + +

        Selection

        +

        Tree supports 3 selection methods, single, multiple and checkbox. Selection is enabled by setting selectionMode property and providing a single TreeNode or + an array of TreeNodes to reference the selections depending on the selection mode.

        +
        +
        +export class TreeDemoComponent implements OnInit {
        +    
        +    files: TreeNode[];
        +    
        +    selectedFile: TreeNode;
        +
        +    constructor(private nodeService: NodeService) {}
        +    
        +    ngOnInit() {
        +        this.nodeService.getFiles().then(files => this.files = files);
        +    }
        +
        +}
        +
        +
        +
        +
        +<p-tree [value]="files" selectionMode="single" [(selection)]="selectedFile"></p-tree>
        +
        +
        + +

        In multiple mode or checkbox mode, selection property should be an array. In multiple mode, items can either be selected + using metaKey or toggled individually depending on the value of metaKeySelection property value which is true by default. On touch enabled + devices metaKeySelection is turned off automatically.

        +
        +
        +    export class TreeDemoComponent implements OnInit {
        +        
        +        files: TreeNode[];
        +        
        +        selectedFiles: TreeNode[];
        +
        +        constructor(private nodeService: NodeService) {}
        +        
        +        ngOnInit() {
        +            this.nodeService.getFiles().then(files => this.files = files);
        +        }
        +
        +    }
        +
        +
        + +
        +
        +<p-tree [value]="files" selectionMode="single" [(selection)]="selectedFiles"></p-tree>
        +
        +
        + +

        In checkbox mode, selections propagate up and down, if you prefer not to do so, propagation can be turned of by propapageSelectionDown and + propagateSelectionUp properties.

        +
        +
        +<p-tree [value]="files" selectionMode="checkbox" [(selection)]="selectedFiles"
        +                [propagateSelectionUp]="false" [propagateSelectionDown]="false"></p-tree>
        +
        +
        + +

        Tree provides onNodeSelect and onNodeUnselect options as callbacks for selection feature.

        +
        +
        +<p-tree [value]="files" selectionMode="single" [(selection)]="selectedFiles" (onNodeSelect)="nodeSelect($event)"></p-tree>
        +
        +
        + +
        +
        +export class TreeDemoComponent implements OnInit {
        +    
        +    files: TreeNode[];
        +    
        +    selectedFiles: TreeNode[];
        +
        +    constructor(private nodeService: NodeService) {}
        +    
        +    ngOnInit() {
        +        this.nodeService.getFiles().then(files => this.files = files);
        +    }
        +    
        +    nodeSelect(event) {
        +        //event.node = selected node
        +    }
        +
        +}
        +
        +
        + +

        Selection of a particular node can be disabled by setting the selectable property of the node to false.

        + +

        Icons

        +

        Icon of a treenode is defined using the icon property, if you need an icon depending on the expand or collapse state, use + expandedIcon and collapsedIcon instead.

        + +

        Templating

        +

        By default label of a treenode is displayed inside a tree node, in case you need to place custom content define a pTemplate that gets + the treenode as an implicit variable. Example below places an input field to create editable treenodes.

        + +
        +
        +<h3>ng-template</h3>
        +<p-tree [value]="files">
        +    <ng-template let-node  pTemplate="default">
        +        <input [(ngModel)]="node.label" type="text" style="width:100%">
        +    </ng-template>
        +</p-tree>
        +
        +
        + +

        Multiple templates are supported by matching the type property of the TreeNode with the type of pTemplate. If a node as no type, + then default ng-template is used.

        +
        +
        +<h3>ng-template</h3>
        +<p-tree [value]="files">
        +    <ng-template let-node  pTemplate="picture">
        +        <img [attrs.src]="picture.path">
        +    </ng-template>
        +    <ng-template let-node  pTemplate="default">
        +        <input [(ngModel)]="node.label" type="text" style="width:100%">
        +    </ng-template>
        +</p-tree>
        +
        +
        + +

        ContextMenu

        +

        Tree has exclusive integration with context menu created by binding a menu instance to the tree.

        +
        +
        +<p-tree [value]="files" selectionMode="single" [(selection)]="selectedFile2" [contextMenu]="cm"></p-tree>
        +
        +<p-contextMenu #cm [model]="items"></p-contextMenu>
        +
        +
        + +

        Lazy Loading

        +

        Lazy loading is handy to deal with large datasets. Instead of loading the whole tree, nodes can be loaded at onNodeExpand event. + Important part of implementing lazy loading is defining leaf property of a node as false, this will instruct tree to display an arrow icon + to indicate there are children of this node although they are not loaded yet. When the lazy node is expanded, onNodeExpand is called + and a remote call can be made to add the children to the expanded node.

        +
        +
        +<p-tree [value]="files" (onNodeExpand)="loadNode($event)"></p-tree>
        +
        +
        + +
        +
        +export class TreeDemoComponent implements OnInit {
        +    
        +    files: TreeNode[];
        +    
        +    selectedFiles: TreeNode[];
        +
        +    constructor(private nodeService: NodeService) {}
        +    
        +    ngOnInit() {
        +        //initial nodes
        +        this.nodeService.getFiles().then(files => this.files = files);
        +    }
        +    
        +    loadNode(event) {
        +        if(event.node) {
        +            //in a real application, make a call to a remote url to load children of the current node and add the new nodes as children
        +            this.nodeService.getLazyFiles().then(nodes => event.node.children = nodes);
        +        }
        +    }
        +
        +}
        +
        +
        + +

        Assume at ngOnInit tree is initialized with a data like below that has nodes having no actual children but leaf property is set false.

        +
        +
        +{
        +    "data": 
        +    [
        +        {
        +            "label": "Lazy Node 0",
        +            "data": "Node 0",
        +            "expandedIcon": "fa-folder-open",
        +            "collapsedIcon": "fa-folder",
        +            "leaf": false
        +        },
        +        {
        +            "label": "Lazy Node 1",
        +            "data": "Node 1",
        +            "expandedIcon": "fa-folder-open",
        +            "collapsedIcon": "fa-folder",
        +            "leaf": false
        +        },
        +        {
        +            "label": "Lazy Node 1",
        +            "data": "Node 2",
        +            "expandedIcon": "fa-folder-open",
        +            "collapsedIcon": "fa-folder",
        +            "leaf": false
        +        }
        +    ]
        +}
        +
        +
        + +

        Drag and Drop

        +

        Nodes can be reordered within a tree and also can be transferred between multiple trees. To enable dragging from a tree set draggableNodes to true and to allow + dropping enable droppableNodes property. In addition, import TreeDragDropService and configure it as a provider at your component or module.

        +
        +
        +import {TreeDragDropService} from 'primeng/primeng';
        +
        +
        + +
        +
        +<p-tree [value]="files" draggableNodes="true" droppableNodes="true"></p-tree>
        +
        +
        +

        Multiple tree can be used in a drag drop operation, in order to add constraints like rejecting drags from a certain tree but allow from another use draggableScope + and droppableScope properties which can be a string or an array. Following example uses 3 trees where second one only accepts drags from first tree and second one only + accepts from second tree whereas first tree accepts drops from 3rd tree.

        +
        +
        +<p-tree [value]="files" draggableNodes="true" droppableNodes="true" draggableScope="a" droppableScope="c"></p-tree>
        +<p-tree [value]="files" draggableNodes="true" droppableNodes="true" draggableScope="b" droppableScope="a"></p-tree>
        +<p-tree [value]="files" draggableNodes="true" droppableNodes="true" draggableScope="c" droppableScope="b"></p-tree>
        +
        +
        + +

        Horizontal Orientation

        +

        Horizontal mode is the alternative option for orientation.

        + +
        +
        +<p-tree [value]="files" layout="horizontal"></p-tree>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        valuearraynullAn array of treenodes.
        selectionModestringnullDefines the selection mode, valid values "single", "multiple", and "checkbox".
        selectionanynullA single treenode instance or an array to refer to the selections.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        contextMenuContextMenunullContext menu instance.
        orientationstringverticalDefines the orientation of the tree, valid values are 'vertical' and 'horizontal'.
        metaKeySelectionbooleantrueDefines how multiple items can be selected, when true metaKey needs to be pressed to select or unselect an item and when set to false selection of each item + can be toggled individually. On touch enabled devices, metaKeySelection is turned off automatically.
        propagateSelectionUpbooleantrueWhether checkbox selections propagate to ancestor nodes.
        propagateSelectionDownbooleantrueWhether checkbox selections propagate to descendant nodes.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onNodeSelectevent.originalEvent: browser event
        + event.node: Selected node instance.
        Callback to invoke when a node is selected.
        onNodeUnselectevent.originalEvent: browser event
        + event.node: Unselected node instance.
        Callback to invoke when a node is unselected.
        onNodeExpandevent.originalEvent: browser event
        + event.node: Expanded node instance.
        Callback to invoke when a node is expanded.
        onNodeCollapseevent.originalEvent: browser event
        + event.node: Collapsed node instance.
        Callback to invoke when a node is collapsed.
        onNodeContextMenuSelectevent.originalEvent: browser event
        + event.node: Selected node instance.
        Callback to invoke when a node is selected with right click.
        onNodeDropevent.originalEvent: browser event
        + event.dragNode: Dragged node instance
        + event.dropNode: Dropped node instance.
        Callback to invoke when a node is selected with right click.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-treeMain container element
        ui-tree-horizontalMain container element in horizontal mode
        ui-tree-containerContainer of nodes
        ui-treenodeA treenode element
        ui-treenode-contentContent of a treenode
        ui-treenode-togglerToggle icon
        ui-treenode-iconIcon of a treenode
        ui-treenode-labelLabel of a treenode
        ui-treenode-childrenContainer element for node children
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<p-growl [value]="msgs"></p-growl>
        +
        +<h3 class="first">Basic</h3>
        +<p-tree [value]="filesTree1"></p-tree>
        +
        +<h3>Single Selection</h3>
        +<p-tree [value]="filesTree2" selectionMode="single" [(selection)]="selectedFile" 
        +    (onNodeSelect)="nodeSelect($event)" (onNodeUnselect)="nodeUnselect($event)"></p-tree>
        +<div style="margin-top:8px">Selected Node: {selectedFile ? selectedFile.label : 'none'}</div>
        +
        +<h3>Multiple Selection with Metakey</h3>
        +<p-tree [value]="filesTree3" selectionMode="multiple" [(selection)]="selectedFiles" 
        +    (onNodeSelect)="nodeSelect($event)" (onNodeUnselect)="nodeUnselect($event)"></p-tree>
        +<div>Selected Nodes: <span *ngFor="let file of selectedFiles">{file.label} </span></div>
        +
        +<h3>Multiple Selection with Checkbox</h3>
        +<p-tree [value]="filesTree4" selectionMode="checkbox" [(selection)]="selectedFiles2"></p-tree>
        +<div>Selected Nodes: <span *ngFor="let file of selectedFiles2">{file.label} </span></div>
        +
        +<h3>Lazy Loading</h3>
        +<p-tree [value]="lazyFiles" (onNodeExpand)="nodeExpand($event)" [style]="{'max-height':'200px','overflow':'auto'}"></p-tree>
        +
        +<h3>ng-template</h3>
        +<p-tree [value]="filesTree5">
        +    <ng-template let-node pTemplate="default">
        +        <input [(ngModel)]="node.label" type="text" style="width:100%">
        +    </ng-template>
        +</p-tree>
        +
        +<h3>Context Menu</h3>
        +<p-tree [value]="filesTree6" selectionMode="single" [(selection)]="selectedFile2" [contextMenu]="cm"></p-tree>
        +<p-contextMenu #cm [model]="items"></p-contextMenu>
        +
        +<h3>DragDrop</h3>
        +<div class="ui-g ui-fluid">
        +    <div class="ui-g-12 ui-md-3">
        +        <h4>Files</h4>
        +        <p-tree [value]="filesTree7" draggableNodes="true" droppableNodes="true" dragdropScope="files"></p-tree>
        +    </div>
        +    
        +    <div class="ui-g-12 ui-md-1" style="text-align:center">
        +        <i class="fa fa-exchange" style="font-size:36px;margin-top: 28px;"></i>
        +    </div>
        +    
        +    <div class="ui-g-12 ui-md-3">
        +        <h4>Server 1</h4>
        +        <p-tree [value]="filesTree8" draggableNodes="true" droppableNodes="true" dragdropScope="files"></p-tree>
        +    </div>
        +    
        +    <div class="ui-g-12 ui-md-1" style="text-align:center">
        +        <i class="fa fa-exchange" style="font-size:36px;margin-top: 28px;"></i>
        +    </div>
        +    
        +    <div class="ui-g-12 ui-md-3">
        +        <h4>Server 2</h4>
        +        <p-tree [value]="filesTree9" draggableNodes="true" droppableNodes="true" dragdropScope="other"></p-tree>
        +    </div>
        +    
        +    <div class="ui-g-12 ui-md-1">
        +        
        +    </div>
        +</div>
        +
        +<h3>Programatic Tree Expansion</h3>
        +<p-tree #expandingTree [value]="filesTree10"></p-tree>
        +<div style="margin-top: 8px">
        +    <button pButton type="text" label="Expand all" (click)="expandAll()"></button>
        +    <button pButton type="text" label="Collapse all" (click)="collapseAll()"></button>
        +</div>
        +
        +<h3>Horizontal Tree</h3>
        +<p-tree [value]="filesTree11" layout="horizontal" selectionMode="single" [(selection)]="selectedFile3" ></p-tree>
        +<div style="margin-top:8px">Selected Node: {selectedFile3 ? selectedFile3.label : 'none'}</div>
        +
        +
        + +
        +
        +export class TreeDemo implements OnInit {
        +    
        +    msgs: Message[];
        +
        +    @ViewChild('expandingTree')
        +    expandingTree: Tree;
        +
        +    filesTree1: TreeNode[];
        +    filesTree2: TreeNode[];
        +    filesTree3: TreeNode[];
        +    filesTree4: TreeNode[];
        +    filesTree5: TreeNode[];
        +    filesTree6: TreeNode[];
        +    filesTree7: TreeNode[];
        +    filesTree8: TreeNode[];
        +    filesTree9: TreeNode[];
        +    filesTree10: TreeNode[];
        +    filesTree11: TreeNode[];
        +    
        +    lazyFiles: TreeNode[];
        +    
        +    selectedFile: TreeNode;
        +    
        +    selectedFile2: TreeNode;
        +    
        +    selectedFile3: TreeNode;
        +    
        +    selectedFiles: TreeNode[];
        +    
        +    selectedFiles2: TreeNode[];
        +    
        +    items: MenuItem[];
        +        
        +    constructor(private nodeService: NodeService) { }
        +
        +    ngOnInit() {
        +        this.nodeService.getFiles().then(files => this.filesTree1 = files);
        +        this.nodeService.getFiles().then(files => this.filesTree2 = files);
        +        this.nodeService.getFiles().then(files => this.filesTree3 = files);
        +        this.nodeService.getFiles().then(files => this.filesTree4 = files);
        +        this.nodeService.getFiles().then(files => this.filesTree5 = files);
        +        this.nodeService.getFiles().then(files => this.filesTree6 = files);
        +        this.nodeService.getFiles().then(files => this.filesTree7 = files);
        +        this.filesTree8 = [
        +            {
        +                label: "Backup",
        +                data: "Backup Folder",
        +                expandedIcon: "fa-folder-open",
        +                collapsedIcon: "fa-folder"
        +            }
        +        ];
        +        this.filesTree9 = [
        +            {
        +                label: "Storage",
        +                data: "Storage Folder",
        +                expandedIcon: "fa-folder-open",
        +                collapsedIcon: "fa-folder"
        +            }
        +        ];
        +        this.nodeService.getFiles().then(files => this.filesTree10 = files);
        +        this.nodeService.getFiles().then(files => {
        +            this.filesTree11 = [{
        +                label: 'Root',
        +                children: files
        +            }];
        +        });
        +
        +        this.nodeService.getLazyFiles().then(files => this.lazyFiles = files);
        +        
        +        this.items = [
        +            {label: 'View', icon: 'fa-search', command: (event) => this.viewFile(this.selectedFile2)},
        +            {label: 'Unselect', icon: 'fa-close', command: (event) => this.unselectFile()}
        +        ];
        +    }
        +    
        +    nodeSelect(event) {
        +        this.msgs = [];
        +        this.msgs.push({severity: 'info', summary: 'Node Selected', detail: event.node.label});
        +    }
        +    
        +    nodeUnselect(event) {
        +        this.msgs = [];
        +        this.msgs.push({severity: 'info', summary: 'Node Unselected', detail: event.node.label});
        +    }
        +
        +    nodeExpandMessage(event) {
        +        this.msgs = [];
        +        this.msgs.push({severity: 'info', summary: 'Node Expanded', detail: event.node.label});
        +    }
        +    
        +    nodeExpand(event) {
        +        if(event.node) {
        +            //in a real application, make a call to a remote url to load children of the current node and add the new nodes as children
        +            this.nodeService.getLazyFiles().then(nodes => event.node.children = nodes);
        +        }
        +    }
        +    
        +    viewFile(file: TreeNode) {
        +        this.msgs = [];
        +        this.msgs.push({severity: 'info', summary: 'Node Selected with Right Click', detail: file.label});
        +    }
        +    
        +    unselectFile() {
        +        this.selectedFile2 = null;
        +    }
        +
        +    expandAll(){
        +        this.filesTree6.forEach( node => {
        +            this.expandRecursive(node, true);
        +        } );
        +    }
        +
        +    collapseAll(){
        +        this.filesTree6.forEach( node => {
        +            this.expandRecursive(node, false);
        +        } );
        +    }
        +    
        +    private expandRecursive(node:TreeNode, isExpand:boolean){
        +        node.expanded = isExpand;
        +        if(node.children){
        +            node.children.forEach( childNode => {
        +                this.expandRecursive(childNode, isExpand);
        +            } );
        +        }
        +    }
        +}
        +
        +
        +
        +
        +
        diff --git a/src/app/showcase/components/tree/treedemo.module.ts b/src/app/showcase/components/tree/treedemo.module.ts new file mode 100644 index 00000000000..138b26e40f2 --- /dev/null +++ b/src/app/showcase/components/tree/treedemo.module.ts @@ -0,0 +1,29 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {TreeDemo} from './treedemo'; +import {TreeDemoRoutingModule} from './treedemo-routing.module'; +import {TreeModule} from '../../../components/tree/tree'; +import {GrowlModule} from '../../../components/growl/growl'; +import {ButtonModule} from '../../../components/button/button'; +import {ContextMenuModule} from '../../../components/contextmenu/contextmenu'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + TreeDemoRoutingModule, + TreeModule, + GrowlModule, + ButtonModule, + ContextMenuModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + TreeDemo + ] +}) +export class TreeDemoModule {} diff --git a/src/app/showcase/components/tree/treedemo.ts b/src/app/showcase/components/tree/treedemo.ts new file mode 100644 index 00000000000..cde5cdfefa9 --- /dev/null +++ b/src/app/showcase/components/tree/treedemo.ts @@ -0,0 +1,143 @@ +import {Component,OnInit,ViewChild} from '@angular/core'; +import {NodeService} from '../../service/nodeservice'; +import {Message,MenuItem,TreeNode} from '../../../components/common/api'; +import {Tree} from '../../../components/tree/tree'; +import {TreeDragDropService} from '../../../components/common/api'; + +@Component({ + templateUrl: './treedemo.html', + styles:[` + h4 { + text-align: center; + margin: 0 0 8px 0; + } + `], + providers: [TreeDragDropService] +}) +export class TreeDemo implements OnInit { + + msgs: Message[]; + + @ViewChild('expandingTree') + expandingTree: Tree; + + filesTree1: TreeNode[]; + filesTree2: TreeNode[]; + filesTree3: TreeNode[]; + filesTree4: TreeNode[]; + filesTree5: TreeNode[]; + filesTree6: TreeNode[]; + filesTree7: TreeNode[]; + filesTree8: TreeNode[]; + filesTree9: TreeNode[]; + filesTree10: TreeNode[]; + filesTree11: TreeNode[]; + + lazyFiles: TreeNode[]; + + selectedFile: TreeNode; + + selectedFile2: TreeNode; + + selectedFile3: TreeNode; + + selectedFiles: TreeNode[]; + + selectedFiles2: TreeNode[]; + + items: MenuItem[]; + + constructor(private nodeService: NodeService) { } + + ngOnInit() { + this.nodeService.getFiles().then(files => this.filesTree1 = files); + this.nodeService.getFiles().then(files => this.filesTree2 = files); + this.nodeService.getFiles().then(files => this.filesTree3 = files); + this.nodeService.getFiles().then(files => this.filesTree4 = files); + this.nodeService.getFiles().then(files => this.filesTree5 = files); + this.nodeService.getFiles().then(files => this.filesTree6 = files); + this.nodeService.getFiles().then(files => this.filesTree7 = files); + this.filesTree8 = [ + { + label: "Backup", + data: "Backup Folder", + expandedIcon: "fa-folder-open", + collapsedIcon: "fa-folder" + } + ]; + this.filesTree9 = [ + { + label: "Storage", + data: "Storage Folder", + expandedIcon: "fa-folder-open", + collapsedIcon: "fa-folder" + } + ]; + this.nodeService.getFiles().then(files => this.filesTree10 = files); + this.nodeService.getFiles().then(files => { + this.filesTree11 = [{ + label: 'Root', + children: files + }]; + }); + + this.nodeService.getLazyFiles().then(files => this.lazyFiles = files); + + this.items = [ + {label: 'View', icon: 'fa-search', command: (event) => this.viewFile(this.selectedFile2)}, + {label: 'Unselect', icon: 'fa-close', command: (event) => this.unselectFile()} + ]; + } + + nodeSelect(event) { + this.msgs = []; + this.msgs.push({severity: 'info', summary: 'Node Selected', detail: event.node.label}); + } + + nodeUnselect(event) { + this.msgs = []; + this.msgs.push({severity: 'info', summary: 'Node Unselected', detail: event.node.label}); + } + + nodeExpandMessage(event) { + this.msgs = []; + this.msgs.push({severity: 'info', summary: 'Node Expanded', detail: event.node.label}); + } + + nodeExpand(event) { + if(event.node) { + //in a real application, make a call to a remote url to load children of the current node and add the new nodes as children + this.nodeService.getLazyFiles().then(nodes => event.node.children = nodes); + } + } + + viewFile(file: TreeNode) { + this.msgs = []; + this.msgs.push({severity: 'info', summary: 'Node Selected with Right Click', detail: file.label}); + } + + unselectFile() { + this.selectedFile2 = null; + } + + expandAll(){ + this.filesTree10.forEach( node => { + this.expandRecursive(node, true); + } ); + } + + collapseAll(){ + this.filesTree10.forEach( node => { + this.expandRecursive(node, false); + } ); + } + + private expandRecursive(node:TreeNode, isExpand:boolean){ + node.expanded = isExpand; + if(node.children){ + node.children.forEach( childNode => { + this.expandRecursive(childNode, isExpand); + } ); + } + } +} diff --git a/src/app/showcase/components/treetable/treetabledemo-routing.module.ts b/src/app/showcase/components/treetable/treetabledemo-routing.module.ts new file mode 100644 index 00000000000..b55b8af16ac --- /dev/null +++ b/src/app/showcase/components/treetable/treetabledemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {TreeTableDemo} from './treetabledemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: TreeTableDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class TreeTableDemoRoutingModule {} diff --git a/src/app/showcase/components/treetable/treetabledemo.html b/src/app/showcase/components/treetable/treetabledemo.html new file mode 100644 index 00000000000..2fec55dc1ab --- /dev/null +++ b/src/app/showcase/components/treetable/treetabledemo.html @@ -0,0 +1,909 @@ +
        +
        + TreeTable + TreeTable is used to display hierarchical data in tabular format.. +
        +
        + +
        + + + + Basic + + + + + + + Single Selection + + + + +

        Selected Node: {{selectedFile ? selectedFile.data.name : 'none'}}

        + + + Multiple Selection with MetaKey + + + + +

        Selected Nodes: {{file.data.name}}

        + + + Checkbox Selection + + + + +

        Selected Nodes: {{file.data.name}}

        + + + Editable Cells with Templating + + + + + + + + + + + + + + + + + + + Context Menu + + + + + + + + + Lazy Loading + + + + +
        + +
        + + +

        Import

        +
        +
        +import {TreeTableModule,TreeNode,SharedModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        TreeTable component requires an array of TreeNode objects as its value. Let's begin with the TreeNode api.

        + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        labelstringnullLabel of the node.
        dataanynullData represented by the node.
        iconstringnullIcon of the node to display next to content. Not used by TreeTable.
        expandedIconstringnullIcon to use in expanded state. Not used by TreeTable.
        collapsedIconstringnullIcon to use in collapsed state. Not used by TreeTable.
        childrenTreeNode[]nullAn array of treenodes as children.
        leafbooleannullSpecifies if the node has children. Used in lazy loading.
        stylestringnullInline style of the node.
        styleClassstringnullStyle class of the node.
        +
        + +

        Most of the time, nodes will be loaded from a remote datasoure, here is an example NodeService that fetches the data from a json file.

        +
        +
        +@Injectable()
        +export class NodeService {
        +    
        +    constructor(private http: Http) {}
        +
        +    getFilesystem() {
        +        return this.http.get('showcase/resources/data/filesystem.json')
        +                    .toPromise()
        +                    .then(res => <TreeNode[]> res.json().data);
        +    }
        +}
        +
        +
        + +

        The filesystem.json file consists of sample data. In a real application, this should be a dynamic response generated from the remote call.

        +
        +
        +{
        +    "data":
        +    [  
        +        {  
        +            "data":{  
        +                "name":"Documents",
        +                "size":"75kb",
        +                "type":"Folder"
        +            },
        +            "children":[
        +                {  
        +                    "data":{  
        +                        "name":"Work",
        +                        "size":"55kb",
        +                        "type":"Folder"
        +                    },
        +                    "children":[  
        +                        {  
        +                            "data":{  
        +                                "name":"Expenses.doc",
        +                                "size":"30kb",
        +                                "type":"Document"
        +                            }
        +                        },
        +                        {  
        +                            "data":{  
        +                                "name":"Resume.doc",
        +                                "size":"25kb",
        +                                "type":"Resume"
        +                            }
        +                        }
        +                    ]
        +                },
        +                {  
        +                    "data":{  
        +                        "name":"Home",
        +                        "size":"20kb",
        +                        "type":"Folder"
        +                    },
        +                    "children":[  
        +                        {  
        +                            "data":{  
        +                                "name":"Invoices",
        +                                "size":"20kb",
        +                                "type":"Text"
        +                            }
        +                        }
        +                    ]
        +                }
        +            ]
        +        },
        +        {  
        +            "data":{  
        +                "name":"Pictures",
        +                "size":"150kb",
        +                "type":"Folder"
        +            },
        +            "children":[  
        +                {  
        +                    "data":{  
        +                        "name":"barcelona.jpg",
        +                        "size":"90kb",
        +                        "type":"Picture"
        +                    }
        +                },
        +                {  
        +                    "data":{  
        +                        "name":"primeui.png",
        +                        "size":"30kb",
        +                        "type":"Picture"
        +                    }
        +                },
        +                {  
        +                    "data":{  
        +                        "name":"optimus.jpg",
        +                        "size":"30kb",
        +                        "type":"Picture"
        +                    }
        +                }
        +            ]
        +        }
        +    ]
        +}
        +
        +
        + +

        The component that uses this service makes a call to getFiles() and assigns them back to files property that is bound to the tree.

        + +
        +
        +export class TreeTableDemoComponent implements OnInit {
        +    
        +    files: TreeNode[];
        +
        +    constructor(private nodeService: NodeService) {}
        +    
        +    ngOnInit() {
        +        this.nodeService.getFileSystem().then(files => this.files = files);
        +    }
        +
        +}
        +
        +
        + +
        +
        +<p-treeTable [value]="files">
        +    <p-column field="name" header="Name"></p-column>
        +    <p-column field="size" header="Size"></p-column>
        +    <p-column field="type" header="Type"></p-column>
        +</p-treeTable>
        +
        +
        + +

        Column Component

        +

        TreeTable utilizes the following options defined by a column component.

        +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        fieldstringnullProperty of a row data.
        headerstringnullHeader text of a column.
        footerstringnullFooter text of a column.
        stylestringnullInline style of the column.
        styleClassstringnullStyle class of the column.
        +
        + +
        +
        +<p-column field="vin" header="Vin"></p-column>
        +
        +
        + +

        Dynamic Colums

        +

        Columns can be instantiated using an array as well by iterating with ngFor.

        +
        +
        +export class TreeTableDemoComponent implements OnInit {
        +
        +    files: TreeNode[];
        +
        +    constructor(private nodeService: NodeService) {}
        +    
        +    ngOnInit() {
        +        this.nodeService.getFileSystem().then(files => this.files = files);
        +
        +        this.cols = [
        +                {field: 'name', header: 'Name'},
        +                {field: 'size', header: 'Size'},
        +                {field: 'type', header: 'Type'}
        +            ];
        +        }
        +    }
        +}
        +
        +
        + +
        +
        +<p-treeTable [value]="cars">
        +    <p-column *ngFor="let col of cols" [field]="col.field" [header]="col.header"></p-column>
        +</p-treeTable>
        +
        +
        + +

        Facets

        +

        Header and Footer are the two sections aka facets that are capable of displaying custom content.

        +
        +
        +import {Header} from 'primeng/primeng';
        +import {Footer} from 'primeng/primeng';
        +
        +
        +
        +
        +<p-treeTable [value]="files">
        +    <p-header>List of Files</p-header>
        +    <p-footer>Choose from the list.</p-footer>
        +    <p-column field="name" header="Name"></p-column>
        +    <p-column field="size" header="Size"></p-column>
        +    <p-column field="type" header="Type"></p-column>
        +</p-treeTable>
        +
        +
        + +

        Selection

        +

        TreeTable supports three selection methods, single, multiple and checkbox. Selection is enabled by setting selectionMode property and providing a single TreeNode or + an array of TreeNodes to reference the selections depending on the selection mode.

        +
        +
        +export class TreeTableDemoComponent implements OnInit {
        +    
        +    files: TreeNode[];
        +    
        +    selectedFile: TreeNode;
        +
        +    constructor(private nodeService: NodeService) {}
        +    
        +    ngOnInit() {
        +        this.nodeService.getFiles().then(files => this.files = files);
        +    }
        +
        +}
        +
        +
        + +
        +
        +<p-treeTable [value]="files" selectionMode="single" [(selection)]="selectedFile"></p-treeTable>
        +
        +
        + +

        In multiple mode or checkbox mode, selection property should be an array. In multiple mode, items can either be selected +using metaKey or toggled individually depending on the value of metaKeySelection property value which is true by default. On touch enabled +devices metaKeySelection is turned off automatically.

        +
        +
        +    export class TreeTableDemoComponent implements OnInit {
        +        
        +        files: TreeNode[];
        +        
        +        selectedFiles: TreeNode[];
        +
        +        constructor(private nodeService: NodeService) {}
        +        
        +        ngOnInit() {
        +            this.nodeService.getFiles().then(files => this.files = files);
        +        }
        +
        +    }
        +
        +
        + +
        +
        +<p-treeTable [value]="files" selectionMode="single" [(selection)]="selectedFiles"></p-treeTable>
        +
        +
        + +

        TreeTable provides onNodeSelect and onNodeUnselect options as callbacks for selection feature.

        +
        +
        +<p-treeTable [value]="files" selectionMode="single" [(selection)]="selectedFiles" (onNodeSelect)="nodeSelect($event)"></p-treeTable>
        +
        +
        + +
        +
        +export class TreeTableDemoComponent implements OnInit {
        +    
        +    files: TreeNode[];
        +    
        +    selectedFiles: TreeNode[];
        +
        +    constructor(private nodeService: NodeService) {}
        +    
        +    ngOnInit() {
        +        this.nodeService.getFiles().then(files => this.files = files);
        +    }
        +    
        +    nodeSelect(event) {
        +        //event.node = selected node
        +    }
        +
        +}
        +
        +
        + +

        Selection of a particular node can be disabled by setting the selectable property of the node to false.

        + +

        ContextMenu

        +

        TreeTable has exclusive integration with contextmenu component. In order to attach a menu to a treetable, define a local template + variable for the menu and bind it to the contextMenu property of the treetable. This enables showing the menu whenever a row is right clicked.

        +
        +
        +<p-treeTable [value]="files" selectionMode="single" [(selection)]="selectedFile" [contextMenu]="cm">
        +    <p-header>Context Menu</p-header>
        +    <p-column field="name" header="Name"></p-column>
        +    <p-column field="size" header="Size"></p-column>
        +    <p-column field="type" header="Type"></p-column>
        +</p-treeTable>
        +
        +<p-contextMenu #cm [model]="items"></p-contextMenu>
        +
        +
        + +
        +
        +export class TreeTableDemoComponent implements OnInit {
        +    
        +    files: TreeNode[];
        +    
        +    selectedFile: TreeNode;
        +
        +    constructor(private nodeService: NodeService) {}
        +    
        +    ngOnInit() {
        +        this.nodeService.getFiles().then(files => this.files = files);
        +        
        +        this.items = [
        +            {label: 'View', icon: 'fa-search', command: (event) => this.viewNode(this.selectedFile2)},
        +            {label: 'Delete', icon: 'fa-close', command: (event) => this.deleteNode(this.selectedFile2)}
        +        ];
        +    }
        +    
        +    viewNode(node: TreeNode) {
        +        this.msgs = [];
        +        this.msgs.push({severity: 'info', summary: 'Node Selected', detail: node.data.name});
        +    }
        +
        +    deleteNode(node: TreeNode) {
        +        node.parent.children = node.parent.children.filter( n => n.data !== node.data);
        +        this.msgs = [];
        +        this.msgs.push({severity: 'info', summary: 'Node Deleted', detail: node.data.name});
        +    }
        +
        +}
        +
        +
        + +

        Templating

        +

        By default label of a treenode is displayed inside a tree node, in case you need to place custom content define a ng-template inside a column that gets + the column as an implicit variable and rowData as the node instance. Similarly, custom content can be placed at the header and footer of a column with templating. + Example below places an input field to create editable treenodes.

        + +
        +
        +<h3>ng-template</h3>
        +<p-treeTable [value]="files">
        +    <p:column>
        +        <ng-template let-col let-node="rowData" pTemplate="header">
        +            <button type="button" pButton label="Refresh"></button>
        +        </ng-template>
        +        <ng-template let-col let-node="rowData" pTemplate="body">
        +            <input [(ngModel)]="node.data.name" type="text" style="width:100%">
        +        </ng-template>
        +    </p:column>
        +</p-treeTable>
        +
        +
        + +

        Lazy Loading

        +

        Lazy loading is handy to deal with large datasets. Instead of loading the whole tree, nodes can be loaded at onNodeExpand event. + Important part of implementing lazy loading is defining leaf property of a node as false, this will instruct tree to display an arrow icon + to indicate there are children of this node although they are not loaded yet. When the lazy node is expanded, onNodeExpand is called + and a remote call can be made to add the children to the expanded node.

        +
        +
        +<p-treeTable [value]="files" (onNodeExpand)="loadNode($event)"></p-treeTable>
        +
        +
        + +
        +
        +export class TreeTableDemoComponent implements OnInit {
        +    
        +    files: TreeNode[];
        +    
        +    selectedFiles: TreeNode[];
        +
        +    constructor(private nodeService: NodeService) {}
        +    
        +    ngOnInit() {
        +        //initial nodes
        +        this.nodeService.getFiles().then(files => this.files = files);
        +    }
        +    
        +    loadNode(event) {
        +        if(event.node) {
        +            //in a real application, make a call to a remote url to load children of the current node and add the new nodes as children
        +            this.nodeService.getLazyFilesystem().then(nodes => event.node.children = nodes);
        +        }
        +    }
        +
        +}
        +
        +
        + +

        Assume at ngOnInit treetable is initialized with a data like below that has nodes having no actual children but leaf property is set false.

        +
        +
        +{
        +    "data":
        +    [  
        +        {  
        +            "data":{  
        +                "name":"Lazy Folder 0",
        +                "size":"75kb",
        +                "type":"Folder"
        +            },
        +            "leaf": false
        +        },
        +        {  
        +            "data":{  
        +                "name":"Lazy Folder 1",
        +                "size":"150kb",
        +                "type":"Folder"
        +            },
        +            "leaf": false
        +        }
        +    ]
        +}
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        valuearraynullAn array of treenodes.
        labelExpandstringExpandTooltip and screenreader text for expand icon.
        labelCollapsestringCollapseTooltip and screenreader text for collapse icon.
        selectionModestringnullDefines the selection mode, valid values "single" and "multiple".
        selectionanynullA single treenode instance or an array to refer to the selections.
        stylestringnullInline style of the component.
        styleClassstringnullStyle class of the component.
        metaKeySelectionbooleantrueDefines how multiple items can be selected, when true metaKey needs to be pressed to select or unselect an item and when set to false selection of each item + can be toggled individually. On touch enabled devices, metaKeySelection is turned off automatically.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameParametersDescription
        onNodeSelectevent.originalEvent: browser event
        + event.node: Selected node instance.
        Callback to invoke when a node is selected.
        onNodeUnselectevent.originalEvent: browser event
        + event.node: Unselected node instance.
        Callback to invoke when a node is unselected.
        onNodeExpandevent.originalEvent: browser event
        + event.node: Expanded node instance.
        Callback to invoke when a node is expanded.
        onNodeCollapseevent.originalEvent: browser event
        + event.node: Collapsed node instance.
        Callback to invoke when a node is collapsed.
        onContextMenuSelectevent.originalEvent: browser event
        + event.node: Selected node instance.
        Callback to invoke when a node is selected with right click.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-treetableMain container element
        ui-treetable-headerHeader element
        ui-treetable-tablewrapperContainer of table
        ui-treetable-footerFooter element
        +
        + +

        Dependencies

        +

        None.

        +
        + + +
        +
        +<p-growl [value]="msgs"></p-growl>
        +
        +<p-treeTable [value]="files1">
        +    <p-header>Basic</p-header>
        +    <p-column field="name" header="Name"></p-column>
        +    <p-column field="size" header="Size"></p-column>
        +    <p-column field="type" header="Type"></p-column>
        +</p-treeTable>
        +    
        +<p-treeTable [value]="files2" selectionMode="single" [(selection)]="selectedFile"
        +    (onNodeSelect)="nodeSelect($event)" (onNodeUnselect)="nodeUnselect($event)" [style]="{'margin-top':'50px'}">
        +    <p-header>Singe Selection</p-header>
        +    <p-column field="name" header="Name"></p-column>
        +    <p-column field="size" header="Size"></p-column>
        +    <p-column field="type" header="Type"></p-column>
        +</p-treeTable>
        +<p>Selected Node: {{selectedFile ? selectedFile.data.name : 'none'}}</p>
        +    
        +<p-treeTable [value]="files3" selectionMode="multiple" [(selection)]="selectedFiles" 
        +    (onNodeSelect)="nodeSelect($event)" (onNodeUnselect)="nodeUnselect($event)" [style]="{'margin-top':'50px'}">
        +    <p-header>Multiple Selection</p-header>
        +    <p-column field="name" header="Name"></p-column>
        +    <p-column field="size" header="Size"></p-column>
        +    <p-column field="type" header="Type"></p-column>
        +</p-treeTable>
        +<p>Selected Nodes: <span *ngFor="let file of selectedFiles">{{file.data.name}} </span></p>
        +
        +<p-treeTable [value]="files4" selectionMode="checkbox" [(selection)]="selectedFiles2" [style]="{'margin-top':'50px'}">
        +    <p-header>Checkbox Selection</p-header>
        +    <p-column field="name" header="Name"></p-column>
        +    <p-column field="size" header="Size"></p-column>
        +    <p-column field="type" header="Type"></p-column>
        +</p-treeTable>
        +<p>Selected Nodes: <span *ngFor="let file of selectedFiles2">{{file.data.name}} </span></p>
        +
        +<p-treeTable [value]="files5" [style]="{'margin-top':'50px'}">
        +    <p-header>Editable Cells with Templating</p-header>
        +    <p-column field="name" header="Name">
        +        <ng-template let-node="rowData" pTemplate="body">
        +            <input type="text" [(ngModel)]="node.data.name" style="width:100%;border-width:0px 0px 1px 0px">
        +        </ng-template>
        +    </p-column>
        +    <p-column field="size" header="Size">
        +        <ng-template let-node="rowData" pTemplate="body">
        +            <input type="text" [(ngModel)]="node.data.size" style="width:100%;border-width:0px 0px 1px 0px">
        +        </ng-template>
        +    </p-column>
        +    <p-column field="type" header="Type">
        +        <ng-template let-node="rowData" pTemplate="body">
        +            <input type="text" [(ngModel)]="node.data.type" style="width:100%;border-width:0px 0px 1px 0px">
        +        </ng-template>
        +    </p-column>
        +</p-treeTable>
        +
        +<p-treeTable [value]="files6" selectionMode="single" [(selection)]="selectedFile2" [style]="{'margin-top':'50px'}" [contextMenu]="cm">
        +    <p-header>Context Menu</p-header>
        +    <p-column field="name" header="Name"></p-column>
        +    <p-column field="size" header="Size"></p-column>
        +    <p-column field="type" header="Type"></p-column>
        +</p-treeTable>
        +
        +<p-treeTable [value]="lazyFiles" [style]="{'margin-top':'50px'}"
        +    (onNodeExpand)="nodeExpand($event)">
        +    <p-header>Lazy Loading</p-header>
        +    <p-column field="name" header="Name"></p-column>
        +    <p-column field="size" header="Size"></p-column>
        +    <p-column field="type" header="Type"></p-column>
        +</p-treeTable>
        +
        +
        + +
        +
        +export class TreeTableDemo implements OnInit {
        +    
        +    msgs: Message[];
        +    
        +    files1: TreeNode[];
        +    
        +    files2: TreeNode[];
        +    
        +    files3: TreeNode[];
        +    
        +    files4: TreeNode[];
        +    
        +    lazyFiles: TreeNode[];
        +        
        +    selectedFile: TreeNode;
        +    
        +    selectedFile2: TreeNode;
        +    
        +    selectedFiles: TreeNode[];
        +        
        +    constructor(private nodeService: NodeService) { }
        +
        +    ngOnInit() {
        +        this.nodeService.getFilesystem().then(files => this.files = files);
        +        this.nodeService.getLazyFilesystem().then(files => this.lazyFiles = files);
        +        
        +        this.items = [
        +            {label: 'View', icon: 'fa-search', command: (event) => this.viewNode(this.selectedFile2)},
        +            {label: 'Delete', icon: 'fa-close', command: (event) => this.deleteNode(this.selectedFile2)}
        +        ];
        +    }
        +    
        +    nodeSelect(event) {
        +        this.msgs = [];
        +        this.msgs.push({severity: 'info', summary: 'Node Selected', detail: event.node.data.name});
        +    }
        +    
        +    nodeUnselect(event) {
        +        this.msgs = [];
        +        this.msgs.push({severity: 'info', summary: 'Node Unselected', detail: event.node.data.name});
        +    }
        +    
        +    nodeExpand(event) {
        +        if(event.node) {
        +            //in a real application, make a call to a remote url to load children of the current node and add the new nodes as children
        +            this.nodeService.getLazyFilesystem().then(nodes => event.node.children = nodes);
        +        }
        +    }
        +    
        +    viewNode(node: TreeNode) {
        +        this.msgs = [];
        +        this.msgs.push({severity: 'info', summary: 'Node Selected', detail: node.data.name});
        +    }
        +
        +    deleteNode(node: TreeNode) {
        +        node.parent.children = node.parent.children.filter( n => n.data !== node.data);
        +        this.msgs = [];
        +        this.msgs.push({severity: 'info', summary: 'Node Deleted', detail: node.data.name});
        +    ~
        +    
        +}
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/src/app/showcase/components/treetable/treetabledemo.module.ts b/src/app/showcase/components/treetable/treetabledemo.module.ts new file mode 100644 index 00000000000..042e2594231 --- /dev/null +++ b/src/app/showcase/components/treetable/treetabledemo.module.ts @@ -0,0 +1,27 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {TreeTableDemo} from './treetabledemo'; +import {TreeTableDemoRoutingModule} from './treetabledemo-routing.module'; +import {TreeTableModule} from '../../../components/treetable/treetable'; +import {GrowlModule} from '../../../components/growl/growl'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {ContextMenuModule} from '../../../components/contextmenu/contextmenu'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + TreeTableDemoRoutingModule, + TreeTableModule, + GrowlModule, + TabViewModule, + ContextMenuModule, + CodeHighlighterModule + ], + declarations: [ + TreeTableDemo + ] +}) +export class TreeTableDemoModule {} diff --git a/src/app/showcase/components/treetable/treetabledemo.ts b/src/app/showcase/components/treetable/treetabledemo.ts new file mode 100644 index 00000000000..65a3f9c4e6c --- /dev/null +++ b/src/app/showcase/components/treetable/treetabledemo.ts @@ -0,0 +1,80 @@ +import {Component,OnInit} from '@angular/core'; +import {NodeService} from '../../service/nodeservice'; +import {Message,TreeNode,MenuItem} from '../../../components/common/api'; + +@Component({ + templateUrl: './treetabledemo.html' +}) +export class TreeTableDemo implements OnInit { + + msgs: Message[]; + + files1: TreeNode[]; + + files2: TreeNode[]; + + files3: TreeNode[]; + + files4: TreeNode[]; + + files5: TreeNode[]; + + files6: TreeNode[]; + + lazyFiles: TreeNode[]; + + selectedFile: TreeNode; + + selectedFile2: TreeNode; + + selectedFiles: TreeNode[]; + + selectedFiles2: TreeNode[]; + + items: MenuItem[]; + + constructor(private nodeService: NodeService) { } + + ngOnInit() { + this.nodeService.getFilesystem().then(files => this.files1 = files); + this.nodeService.getFilesystem().then(files => this.files2 = files); + this.nodeService.getFilesystem().then(files => this.files3 = files); + this.nodeService.getFilesystem().then(files => this.files4 = files); + this.nodeService.getFilesystem().then(files => this.files5 = files); + this.nodeService.getFilesystem().then(files => this.files6 = files); + this.nodeService.getLazyFilesystem().then(files => this.lazyFiles = files); + + this.items = [ + {label: 'View', icon: 'fa-search', command: (event) => this.viewNode(this.selectedFile2)}, + {label: 'Delete', icon: 'fa-close', command: (event) => this.deleteNode(this.selectedFile2)} + ]; + } + + nodeSelect(event) { + this.msgs = []; + this.msgs.push({severity: 'info', summary: 'Node Selected', detail: event.node.data.name}); + } + + nodeUnselect(event) { + this.msgs = []; + this.msgs.push({severity: 'info', summary: 'Node Unselected', detail: event.node.data.name}); + } + + nodeExpand(event) { + if(event.node) { + //in a real application, make a call to a remote url to load children of the current node and add the new nodes as children + this.nodeService.getLazyFilesystem().then(nodes => event.node.children = nodes); + } + } + + viewNode(node: TreeNode) { + this.msgs = []; + this.msgs.push({severity: 'info', summary: 'Node Selected', detail: node.data.name}); + } + + deleteNode(node: TreeNode) { + node.parent.children = node.parent.children.filter( n => n.data !== node.data); + this.msgs = []; + this.msgs.push({severity: 'info', summary: 'Node Deleted', detail: node.data.name}); + } +} \ No newline at end of file diff --git a/src/app/showcase/components/tristatecheckbox/tristatecheckboxdemo-routing.module.ts b/src/app/showcase/components/tristatecheckbox/tristatecheckboxdemo-routing.module.ts new file mode 100644 index 00000000000..3f8de3febf1 --- /dev/null +++ b/src/app/showcase/components/tristatecheckbox/tristatecheckboxdemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {TriStateCheckboxDemo} from './tristatecheckboxdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: TriStateCheckboxDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class TriStateCheckboxDemoRoutingModule {} diff --git a/src/app/showcase/components/tristatecheckbox/tristatecheckboxdemo.html b/src/app/showcase/components/tristatecheckbox/tristatecheckboxdemo.html new file mode 100644 index 00000000000..632b9653f44 --- /dev/null +++ b/src/app/showcase/components/tristatecheckbox/tristatecheckboxdemo.html @@ -0,0 +1,175 @@ +
        +
        + TriStateCheckbox + TriStateCheckbox is used to select either "true", "false" or "null" as the value. +
        +
        + +
        +

        Value: {{value}}

        + +
        + +
        + + +

        Import

        +
        +
        +import {TriStateCheckboxModule} from 'primeng/primeng';
        +
        +
        + +

        Getting Started

        +

        TriStateCheckbox is defined using p-triStateCheckbox element and requires a value binding via ngModel.

        +
        +
        +<p-triStateCheckbox [(ngModel)]="value"></p-triStateCheckbox>
        +
        +
        + +
        +
        +export class ModelComponent {
        +
        +    value: any;
        +
        +}
        +
        +
        + +

        Model Driven Forms

        +

        TriStateCheckbox can be used in a model driven form as well.

        +
        +
        +<p-triStateCheckbox formControlName="property"></p-triStateCheckbox>
        +
        +
        + +

        Properties

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameTypeDefaultDescription
        namestringnullName of the component.
        disabledbooleanfalseWhen present, it specifies that the element should be disabled.
        tabindexnumbernullIndex of the element in tabbing order.
        inputIdstringnullIdentifier of the focus input to match a label defined for the component.
        styleobjectnullInline style of the component.
        styleClassstringnullStyle class of the component.
        +
        + +

        Events

        +
        + + + + + + + + + + + + + + + +
        NameParametersDescription
        onChangeevent.originalEvent: Original browser event
        + event.value: Current value.
        Callback to invoke on value change.
        +
        + +

        Styling

        +

        Following is the list of structural style classes, for theming classes visit theming page.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + +
        NameElement
        ui-chkboxContainer element
        ui-tristatechkboxContainer element
        ui-chkbox-boxContainer of icon.
        ui-chkbox-iconIcon element.
        +
        + +

        Dependencies

        +

        None.

        +
        + +
        +
        +<h3 class="first">Value: {{value}}</h3>
        +<p-triStateCheckbox [(ngModel)]="value"></p-triStateCheckbox>
        +
        +
        + +
        +
        +export class TriStateCheckboxDemo {
        +
        +    value: any;
        +    
        +}
        +
        +
        +
        +
        +
        diff --git a/src/app/showcase/components/tristatecheckbox/tristatecheckboxdemo.module.ts b/src/app/showcase/components/tristatecheckbox/tristatecheckboxdemo.module.ts new file mode 100644 index 00000000000..6ad7e1eb859 --- /dev/null +++ b/src/app/showcase/components/tristatecheckbox/tristatecheckboxdemo.module.ts @@ -0,0 +1,23 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {TriStateCheckboxDemo} from './tristatecheckboxdemo'; +import {TriStateCheckboxDemoRoutingModule} from './tristatecheckboxdemo-routing.module'; +import {TriStateCheckboxModule} from '../../../components/tristatecheckbox/tristatecheckbox'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + TriStateCheckboxDemoRoutingModule, + TriStateCheckboxModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + TriStateCheckboxDemo + ] +}) +export class TriStateCheckboxDemoModule {} diff --git a/src/app/showcase/components/tristatecheckbox/tristatecheckboxdemo.ts b/src/app/showcase/components/tristatecheckbox/tristatecheckboxdemo.ts new file mode 100644 index 00000000000..376bb8382c3 --- /dev/null +++ b/src/app/showcase/components/tristatecheckbox/tristatecheckboxdemo.ts @@ -0,0 +1,9 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './tristatecheckboxdemo.html', +}) +export class TriStateCheckboxDemo { + + value: any; +} \ No newline at end of file diff --git a/src/app/showcase/components/validation/validationdemo-routing.module.ts b/src/app/showcase/components/validation/validationdemo-routing.module.ts new file mode 100644 index 00000000000..68e2ec83866 --- /dev/null +++ b/src/app/showcase/components/validation/validationdemo-routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router' +import {ValidationDemo} from './validationdemo'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + {path:'',component: ValidationDemo} + ]) + ], + exports: [ + RouterModule + ] +}) +export class ValidationDemoRoutingModule {} diff --git a/src/app/showcase/components/validation/validationdemo.html b/src/app/showcase/components/validation/validationdemo.html new file mode 100644 index 00000000000..0e4b2cc7f3e --- /dev/null +++ b/src/app/showcase/components/validation/validationdemo.html @@ -0,0 +1,244 @@ +
        +
        + Validation + PrimeNG input components indicate validation errors automatically when their value is marked as invalid. +
        +
        + +
        + + +
        + +
        +
        +
        + First Name *: +
        +
        + +
        +
        +
        + + Firstname is required +
        +
        +
        +
        +
        + Last Name *: +
        +
        + +
        +
        +
        + + Lastname is required +
        +
        +
        +
        +
        + Password *: +
        +
        + +
        +
        +
        + + Password is required + Must be longer than 6 characters +
        +
        +
        +
        +
        + Description: +
        +
        + +
        +
        +
        +
        +
        + Gender *: +
        +
        + +
        +
        +
        + + Gender is required +
        +
        +
        +
        +
        +
        + +
        +
        +
        +
        + Form Submitted +
        + {{diagnostic}} +
        +
        +
        +
        +
        + +
        + + +
        +
        +import {Component,OnInit} from '@angular/core';
        +import {Validators,FormControl,FormGroup,FormBuilder} from '@angular/forms';
        +import {Message,SelectItem} from '../../../components/common/api';
        +
        +@Component({
        +    templateUrl: 'showcase/demo/validation/validationdemo.html'
        +})
        +export class ValidationDemo implements OnInit {
        +    
        +    msgs: Message[] = [];
        +    
        +    userform: ControlGroup;
        +    
        +    submitted: boolean;
        +    
        +    genders: SelectItem[];
        +        
        +    description: string;
        +    
        +    constructor(private fb: FormBuilder) {}
        +    
        +    ngOnInit() {
        +        this.userform = this.fb.group({
        +            'firstname': new Control('', Validators.required),
        +            'lastname': new Control('', Validators.required),
        +            'password': new Control('', Validators.compose([Validators.required, Validators.minLength(6)])),
        +            'description': new Control(''),
        +            'gender': new Control('', Validators.required)
        +        });
        +        
        +        this.genders = [];
        +        this.genders.push({label:'Select Gender', value:''});
        +        this.genders.push({label:'Male', value:'Male'});
        +        this.genders.push({label:'Female', value:'Female'});
        +    }
        +    
        +    onSubmit(value: string) {
        +        this.submitted = true;
        +        this.msgs = [];
        +        this.msgs.push({severity:'info', summary:'Success', detail:'Form Submitted'});
        +    }
        +    
        +    get diagnostic() { return JSON.stringify(this.userform.value); }
        +    
        +}
        +
        +
        +
        + + +
        +
        +<p-growl [value]="msgs" sticky="sticky"></p-growl>
        +    
        +<form [formGroup]="userform" (ngSubmit)="onSubmit(userform.value)">
        +    <p-panel header="Validate">
        +        <div class="ui-grid ui-grid-responsive ui-grid-pad ui-fluid" style="margin: 10px 0px">
        +            <div class="ui-grid-row">
        +                <div class="ui-grid-col-2">
        +                    First Name *:
        +                </div>
        +                <div class="ui-grid-col-6">
        +                    <input pInputText type="text" formControlName="firstname" placeholder="Required"/>
        +                </div>
        +                <div class="ui-grid-col-4">
        +                    <div class="ui-message ui-messages-error ui-corner-all" *ngIf="!userform.controls['firstname'].valid&&userform.controls['firstname'].dirty">
        +                        <i class="fa fa-close"></i>
        +                        Firstname is required
        +                    </div>
        +                </div>
        +            </div>
        +            <div class="ui-grid-row">
        +                <div class="ui-grid-col-2">
        +                    Last Name *:
        +                </div>
        +                <div class="ui-grid-col-6">
        +                    <input pInputText type="text" formControlName="lastname" placeholder="Required"/>
        +                </div>
        +                <div class="ui-grid-col-4">
        +                    <div class="ui-message ui-messages-error ui-corner-all" *ngIf="!userform.controls['lastname'].valid&&userform.controls['lastname'].dirty">
        +                        <i class="fa fa-close"></i>
        +                        Lastname is required
        +                    </div>
        +                </div>
        +            </div>
        +            <div class="ui-grid-row">
        +                <div class="ui-grid-col-2">
        +                    Password *:
        +                </div>
        +                <div class="ui-grid-col-6">
        +                    <input pInputText type="password" formControlName="password" placeholder="Required - Min(6)"/>
        +                </div>
        +                <div class="ui-grid-col-4">
        +                    <div class="ui-message ui-messages-error ui-corner-all" *ngIf="!userform.controls['password'].valid&&userform.controls['password'].dirty">
        +                        <i class="fa fa-close"></i>
        +                        <span *ngIf="userform.controls['password'].errors['required']">Password is required</span>
        +                        <span *ngIf="userform.controls['password'].errors['minlength']">Must be longer than 6 characters</span>
        +                    </div>
        +                </div>
        +            </div>
        +            <div class="ui-grid-row">
        +                <div class="ui-grid-col-2">
        +                    Description:
        +                </div>
        +                <div class="ui-grid-col-6">
        +                    <textarea pInputTextarea type="text" formControlName="description"></textarea>
        +                </div>
        +                <div class="ui-grid-col-4"></div>
        +            </div>
        +            <div class="ui-grid-row">
        +                <div class="ui-grid-col-2">
        +                    Gender *:
        +                </div>
        +                <div class="ui-grid-col-6">
        +                    <p-dropdown [options]="genders" formControlName="gender" [autoWidth]="false"></p-dropdown>
        +                </div>
        +                <div class="ui-grid-col-4">
        +                    <div class="ui-message ui-messages-error ui-corner-all" *ngIf="!userform.controls['gender'].valid&&userform.controls['gender'].dirty">
        +                        <i class="fa fa-close"></i>
        +                        Gender is required
        +                    </div>
        +                </div>
        +            </div>
        +            <div class="ui-grid-row">
        +                <div class="ui-grid-col-2"></div>
        +                <div class="ui-grid-col-6">
        +                    <button pButton type="submit" label="Submit" [disabled]="!userform.valid"></button>
        +                </div>
        +                <div class="ui-grid-col-4"></div>
        +            </div>
        +            <div style="text-align:center;margin-top:20px" *ngIf="submitted">
        +                Form Submitted
        +                <br>
        +                {{diagnostic}}
        +            </div>
        +        </div>   
        +    </p-panel> 
        +</form>
        +
        +
        +
        +
        +
        diff --git a/src/app/showcase/components/validation/validationdemo.module.ts b/src/app/showcase/components/validation/validationdemo.module.ts new file mode 100644 index 00000000000..f604034d6ca --- /dev/null +++ b/src/app/showcase/components/validation/validationdemo.module.ts @@ -0,0 +1,34 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule,ReactiveFormsModule} from '@angular/forms'; +import {ValidationDemo} from './validationdemo'; +import {ValidationDemoRoutingModule} from './validationdemo-routing.module'; +import {GrowlModule} from '../../../components/growl/growl'; +import {PanelModule} from '../../../components/panel/panel'; +import {DropdownModule} from '../../../components/dropdown/dropdown'; +import {InputTextModule} from '../../../components/inputtext/inputtext'; +import {InputTextareaModule} from '../../../components/inputtextarea/inputtextarea'; +import {ButtonModule} from '../../../components/button/button'; +import {TabViewModule} from '../../../components/tabview/tabview'; +import {CodeHighlighterModule} from '../../../components/codehighlighter/codehighlighter'; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + ReactiveFormsModule, + ValidationDemoRoutingModule, + GrowlModule, + PanelModule, + DropdownModule, + InputTextModule, + InputTextareaModule, + ButtonModule, + TabViewModule, + CodeHighlighterModule + ], + declarations: [ + ValidationDemo + ] +}) +export class ValidationDemoModule {} diff --git a/src/app/showcase/components/validation/validationdemo.ts b/src/app/showcase/components/validation/validationdemo.ts new file mode 100644 index 00000000000..c6a674e795b --- /dev/null +++ b/src/app/showcase/components/validation/validationdemo.ts @@ -0,0 +1,45 @@ +import {Component,OnInit} from '@angular/core'; +import {Validators,FormControl,FormGroup,FormBuilder} from '@angular/forms'; +import {Message,SelectItem} from '../../../components/common/api'; + +@Component({ + templateUrl: './validationdemo.html' +}) +export class ValidationDemo implements OnInit { + + msgs: Message[] = []; + + userform: FormGroup; + + submitted: boolean; + + genders: SelectItem[]; + + description: string; + + constructor(private fb: FormBuilder) {} + + ngOnInit() { + this.userform = this.fb.group({ + 'firstname': new FormControl('', Validators.required), + 'lastname': new FormControl('', Validators.required), + 'password': new FormControl('', [Validators.required, Validators.minLength(6)]), + 'description': new FormControl(''), + 'gender': new FormControl('', Validators.required) + }); + + this.genders = []; + this.genders.push({label:'Select Gender', value:''}); + this.genders.push({label:'Male', value:'Male'}); + this.genders.push({label:'Female', value:'Female'}); + } + + onSubmit(value: string) { + this.submitted = true; + this.msgs = []; + this.msgs.push({severity:'info', summary:'Success', detail:'Form Submitted'}); + } + + get diagnostic() { return JSON.stringify(this.userform.value); } + +} \ No newline at end of file diff --git a/src/app/showcase/domain/car.ts b/src/app/showcase/domain/car.ts new file mode 100644 index 00000000000..a728a44d11a --- /dev/null +++ b/src/app/showcase/domain/car.ts @@ -0,0 +1,8 @@ +export interface Car { + vin?; + year?; + brand?; + color?; + price?; + saleDate?; +} \ No newline at end of file diff --git a/src/app/showcase/service/carservice.ts b/src/app/showcase/service/carservice.ts new file mode 100644 index 00000000000..829ac29133a --- /dev/null +++ b/src/app/showcase/service/carservice.ts @@ -0,0 +1,31 @@ +import { Injectable } from '@angular/core'; +import { Http, Response } from '@angular/http'; +import { Car } from '../domain/car'; +import 'rxjs/add/operator/toPromise'; + +@Injectable() +export class CarService { + + constructor(private http: Http) {} + + getCarsSmall() { + return this.http.get('assets/showcase/data/cars-small.json') + .toPromise() + .then(res => res.json().data) + .then(data => { return data; }); + } + + getCarsMedium() { + return this.http.get('assets/showcase/data/cars-medium.json') + .toPromise() + .then(res => res.json().data) + .then(data => { return data; }); + } + + getCarsLarge() { + return this.http.get('assets/showcase/data/cars-large.json') + .toPromise() + .then(res => res.json().data) + .then(data => { return data; }); + } +} \ No newline at end of file diff --git a/src/app/showcase/service/countryservice.ts b/src/app/showcase/service/countryservice.ts new file mode 100644 index 00000000000..803c22ed4a1 --- /dev/null +++ b/src/app/showcase/service/countryservice.ts @@ -0,0 +1,16 @@ +import { Injectable } from '@angular/core'; +import { Http, Response } from '@angular/http'; +import 'rxjs/add/operator/toPromise'; + +@Injectable() +export class CountryService { + + constructor(private http: Http) {} + + getCountries() { + return this.http.get('assets/showcase/data/countries.json') + .toPromise() + .then(res => res.json().data) + .then(data => { return data; }); + } +} \ No newline at end of file diff --git a/src/app/showcase/service/eventservice.ts b/src/app/showcase/service/eventservice.ts new file mode 100644 index 00000000000..3d9716417b1 --- /dev/null +++ b/src/app/showcase/service/eventservice.ts @@ -0,0 +1,16 @@ +import { Injectable } from '@angular/core'; +import { Http, Response } from '@angular/http'; +import 'rxjs/add/operator/toPromise'; + +@Injectable() +export class EventService { + + constructor(private http: Http) {} + + getEvents() { + return this.http.get('assets/showcase/data/scheduleevents.json') + .toPromise() + .then(res => res.json().data) + .then(data => { return data; }); + } +} \ No newline at end of file diff --git a/src/app/showcase/service/nodeservice.ts b/src/app/showcase/service/nodeservice.ts new file mode 100644 index 00000000000..6c9305c362f --- /dev/null +++ b/src/app/showcase/service/nodeservice.ts @@ -0,0 +1,34 @@ +import { Injectable } from '@angular/core'; +import { Http, Response } from '@angular/http'; +import { TreeNode } from '../../components/common/api'; +import 'rxjs/add/operator/toPromise'; + +@Injectable() +export class NodeService { + + constructor(private http: Http) {} + + getFiles() { + return this.http.get('assets/showcase/data/files.json') + .toPromise() + .then(res => res.json().data); + } + + getLazyFiles() { + return this.http.get('assets/showcase/data/files-lazy.json') + .toPromise() + .then(res => res.json().data); + } + + getFilesystem() { + return this.http.get('assets/showcase/data/filesystem.json') + .toPromise() + .then(res => res.json().data); + } + + getLazyFilesystem() { + return this.http.get('assets/showcase/data/filesystem-lazy.json') + .toPromise() + .then(res => res.json().data); + } +} \ No newline at end of file diff --git a/src/assets/.gitkeep b/src/assets/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/assets/components/images/line.gif b/src/assets/components/images/line.gif new file mode 100755 index 00000000000..64e2280ec55 Binary files /dev/null and b/src/assets/components/images/line.gif differ diff --git a/src/assets/components/images/loading.gif b/src/assets/components/images/loading.gif new file mode 100644 index 00000000000..19c67bbd040 Binary files /dev/null and b/src/assets/components/images/loading.gif differ diff --git a/src/assets/components/images/password-meter.png b/src/assets/components/images/password-meter.png new file mode 100644 index 00000000000..eec05cfb434 Binary files /dev/null and b/src/assets/components/images/password-meter.png differ diff --git a/src/assets/components/themes/_theme.scss b/src/assets/components/themes/_theme.scss new file mode 100644 index 00000000000..56fccea75d2 --- /dev/null +++ b/src/assets/components/themes/_theme.scss @@ -0,0 +1,541 @@ +@mixin hover-element() { + border-color: $stateHoverBorderColor; + background: $stateHoverBgColor; + color: $stateHoverTextColor; + + a { + color: $stateHoverTextColor; + } +} + +@mixin icon-override($icon) { + background: none !important; + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-indent: 0px !important; + text-align: center; + + &:before { + content: $icon; + } +} + +.ui-widget { + font-family: $fontFamily; + font-size: $fontSize; + + input, select, textarea, button { + font-family: $fontFamily; + font-size: $fontSize; + } + + :active { + outline: none; + } +} + +.ui-widget-content { + border: $contentBorderWidth solid $contentBorderColor; + background: $contentBgColor; + color: $contentTextColor; + + a { + color: $contentTextColor; + } +} + +.ui-widget-header { + border: $headerBorderWidth solid $headerBorderColor; + background: $headerBgColor; + color: $headerTextColor; + font-weight: $headerFontWeight; + + a { + color: $headerTextColor; + } +} + +.ui-widget-overlay { + background: #666666; + opacity: .50; + filter:Alpha(Opacity=50); +} + +.ui-widget-header .ui-state-default, +.ui-widget-content .ui-state-default, +.ui-state-default { + border: $stateDefaultBorderWidth solid $stateDefaultBorderColor; + background: $stateDefaultBgColor; + color: $stateDefaultTextColor; + + a { + color: $stateDefaultTextColor ; + } +} + +.ui-widget-header .ui-state-active, +.ui-widget-content .ui-state-active, +.ui-state-active { + border-color: $stateActiveBorderColor; + background: $stateActiveBgColor; + color: $stateActiveTextColor; + + a { + color: $stateActiveTextColor; + } +} + +.ui-widget-header .ui-state-highlight, +.ui-widget-content .ui-state-highlight, +.ui-state-highlight { + border-color: $stateHighlightBorderColor; + background: $stateHighlightBgColor; + color: $stateHighlightTextColor; + + a { + color: $stateHighlightTextColor; + } +} + +.ui-widget-header .ui-state-focus, +.ui-widget-content .ui-state-focus, +.ui-state-focus { + border-color: $stateFocusBorderColor; + background: $stateFocusBgColor; + color: $stateFocusTextColor; + + a { + color: $stateFocusTextColor; + } +} + +.ui-widget-header .ui-state-error, +.ui-widget-content .ui-state-error, +.ui-state-error { + border-color: $stateErrorBorderColor; + background: $stateErrorBgColor; + color: $stateErrorTextColor; + + a { + color: $stateErrorTextColor; + } +} + +.ui-state-disabled, +.ui-widget:disabled { + opacity: $disabledOpacity; + filter: Alpha(Opacity= $disabledOpacity * 100); + background-image: none; + cursor: default !important; + + * { + cursor: default !important; + } +} + +/* Forms */ +.ui-inputtext { + background: $inputBgColor; + color: $inputTextColor; +} + +.ui-inputtext:enabled:hover { + border-color: $stateHoverBorderColor; +} + +.ui-inputtext.ui-state-focus, +.ui-inputtext:focus { + outline: 0 none; + border-color: $stateFocusBorderColor; + -moz-box-shadow: 0px 0px 5px $stateFocusBorderColor; + -webkit-box-shadow: 0px 0px 5px $stateFocusBorderColor; + box-shadow: 0px 0px 5px $stateFocusBorderColor; +} + +.ui-autocomplete { + .ui-autocomplete-multiple-container:not(.ui-state-disabled) { + &:hover { + border-color: $stateHoverBorderColor; + } + + &.ui-state-focus { + border-color: $stateFocusBorderColor; + } + } +} + +.ui-chips { + > ul:not(.ui-state-disabled) { + &:hover { + border-color: $stateHoverBorderColor; + } + + &.ui-state-focus { + border-color: $stateFocusBorderColor; + } + } +} + +.ui-button:focus, +.ui-button:enabled:hover { + outline: 0 none; + @include hover-element(); +} + +.ui-button:enabled:active { + border-color: $stateActiveBorderColor; + background: $stateActiveBgColor; + color: $stateActiveTextColor; +} + +.ui-chkbox-box:not(.ui-state-disabled):not(.ui-state-active):hover { + @include hover-element(); +} + +.ui-radiobutton-box:not(.ui-state-disabled):not(.ui-state-active):hover { + @include hover-element(); +} + +.ui-dropdown:not(.ui-state-disabled):hover { + @include hover-element(); +} + +.ui-dropdown-panel .ui-dropdown-item:not(.ui-state-highlight):hover { + @include hover-element(); +} + +.ui-listbox { + .ui-listbox-header { + .ui-listbox-filter-container { + .fa { + color: $inputTextColor; + } + } + } + + &:not(.ui-state-disabled) { + .ui-listbox-item:not(.ui-state-highlight):hover { + @include hover-element(); + } + } + + &.ui-state-disabled { + .ui-chkbox-box:not(.ui-state-active):hover { + border-color: $stateDefaultBorderColor; + background: $stateDefaultBgColor; + color: $stateDefaultTextColor; + } + } +} + +.ui-multiselect:not(.ui-state-disabled):hover { + @include hover-element(); +} + +.ui-multiselect-panel .ui-multiselect-item:not(.ui-state-highlight):hover { + @include hover-element(); +} + +.ui-multiselect-panel .ui-multiselect-close { + color: $headerIconTextColor; +} + +.ui-multiselect-panel .ui-multiselect-filter-container .fa { + color: $inputTextColor; +} + +.ui-spinner:not(.ui-state-disabled) .ui-spinner-button:enabled:hover { + @include hover-element(); +} + +.ui-spinner:not(.ui-state-disabled) .ui-spinner-button:enabled:active { + border-color: $stateActiveBorderColor; + background: $stateActiveBgColor; + color: $stateActiveTextColor; +} + +.ui-selectbutton .ui-button:not(.ui-state-disabled):not(.ui-state-active):hover { + @include hover-element(); +} + +.ui-togglebutton:not(.ui-state-disabled):not(.ui-state-active):hover { + @include hover-element(); +} + +.ui-paginator a:not(.ui-state-disabled):not(.ui-state-active):hover { + @include hover-element(); +} + +.ui-datatable { + .ui-rowgroup-header a { + color: $headerTextColor; + } + + .ui-sortable-column:not(.ui-state-active):hover { + background: $stateHoverBgColor; + color: $stateHoverTextColor; + } + + .ui-row-toggler { + color: $contentTextColor; + } + + tbody.ui-datatable-hoverable-rows { + > tr.ui-widget-content:not(.ui-state-highlight):hover { + cursor: pointer; + background: $stateHoverBgColor; + color: $stateHoverTextColor; + } + } +} + +.ui-orderlist { + .ui-orderlist-item:not(.ui-state-highlight):hover { + @include hover-element(); + } +} + +.ui-picklist { + .ui-picklist-item:not(.ui-state-highlight):hover { + @include hover-element(); + } +} + +.ui-tree { + &.ui-treenode-dragover { + border-color: $stateHighlightBorderColor; + } + + .ui-treenode-content { + &.ui-treenode-selectable { + .ui-treenode-label:not(.ui-state-highlight):hover { + @include hover-element(); + } + } + + &.ui-treenode-dragover { + background: $stateActiveBgColor; + color: $stateActiveTextColor; + } + } + + &.ui-tree-horizontal { + .ui-treenode-content.ui-treenode-selectable { + .ui-treenode-label:not(.ui-state-highlight):hover { + background-color: inherit; + color: inherit; + } + + &:not(.ui-state-highlight):hover { + @include hover-element(); + } + } + } +} + +.ui-treetable { + .ui-treetable-row.ui-treetable-row-selectable:not(.ui-state-highlight):hover { + background: $stateHoverBgColor; + color: $stateHoverTextColor; + } +} + +.ui-accordion { + .ui-accordion-header:not(.ui-state-active):not(.ui-state-disabled):hover { + @include hover-element(); + } +} + +.ui-fieldset { + &.ui-fieldset-toggleable { + .ui-fieldset-legend:hover { + @include hover-element(); + } + } +} + +.ui-panel { + .ui-panel-titlebar { + .ui-panel-titlebar-icon:hover { + @include hover-element(); + } + } +} + +.ui-tabview { + .ui-tabview-nav { + li { + &:not(.ui-state-active):not(.ui-state-disabled):hover { + @include hover-element(); + } + } + } +} + +.ui-dialog { + .ui-dialog-titlebar-icon { + color: $headerTextColor; + + &:hover { + @include hover-element(); + } + } +} + +.ui-overlaypanel { + .ui-overlaypanel-close:hover { + @include hover-element(); + } +} + +.ui-inplace { + .ui-inplace-display:hover { + @include hover-element(); + } +} + +.ui-breadcrumb { + a { + color: $headerTextColor; + } +} + +.ui-menu { + .ui-menuitem { + .ui-menuitem-link { + color: $contentTextColor; + + &:hover { + @include hover-element(); + border-color: transparent; + } + } + + &.ui-menuitem-active { + > .ui-menuitem-link { + @include hover-element(); + border-color: transparent; + } + } + } +} + +.ui-tabmenu { + .ui-tabmenu-nav { + li:not(.ui-state-active):hover { + @include hover-element(); + } + } +} + +.ui-steps { + .ui-steps-item:not(.ui-state-highlight):not(.ui-state-disabled):hover { + @include hover-element(); + } +} + +.ui-panelmenu { + .ui-panelmenu-header { + &:not(.ui-state-active):hover { + @include hover-element(); + + a { + color: $stateHoverTextColor; + } + } + + &.ui-state-active { + a { + color: $stateActiveTextColor; + } + } + } + + .ui-panelmenu-content { + .ui-menuitem-link { + color: $contentTextColor; + + &:hover { + @include hover-element(); + border-color: transparent; + } + } + } +} + +.ui-datepicker { + .ui-datepicker-header { + a { + color: $headerTextColor; + + &:hover { + @include hover-element(); + } + } + } + + .ui-datepicker-calendar { + td:not(.ui-state-disabled) { + a:hover { + @include hover-element(); + } + } + } +} + +.fc { + .fc-toolbar { + .fc-prev-button { + .ui-icon-circle-triangle-w { + margin-top: .3em; + @include icon_override("\f053"); + } + } + + .fc-next-button { + .ui-icon-circle-triangle-e { + margin-top: .3em; + @include icon_override("\f054"); + } + } + } +} + +.ui-rating { + a { + color: $inputTextColor; + } +} + +/* Validation */ +.ui-inputtext.ng-dirty.ng-invalid, +p-dropdown.ng-dirty.ng-invalid > .ui-dropdown, +p-autocomplete.ng-dirty.ng-invalid > .ui-autocomplete > .ui-inputtext, +p-calendar.ng-dirty.ng-invalid > .ui-inputtext, +p-chips.ng-dirty.ng-invalid > .ui-inputtext, +p-inputmask.ng-dirty.ng-invalid > .ui-inputtext, +p-checkbox.ng-dirty.ng-invalid .ui-chkbox-box, +p-radiobutton.ng-dirty.ng-invalid .ui-radiobutton-box, +p-inputswitch.ng-dirty.ng-invalid .ui-inputswitch, +p-listbox.ng-dirty.ng-invalid .ui-inputtext, +p-multiselect.ng-dirty.ng-invalid > .ui-multiselect, +p-spinner.ng-dirty.ng-invalid > .ui-inputtext, +p-selectbutton.ng-dirty.ng-invalid .ui-button, +p-togglebutton.ng-dirty.ng-invalid .ui-button { + border-bottom-color: $invalidInputBorderColor; +} + +/* Cornering */ +.ui-corner-tl { -moz-border-radius-topleft: $borderRadius; -webkit-border-top-left-radius: $borderRadius; border-top-left-radius: $borderRadius; } +.ui-corner-tr { -moz-border-radius-topright: $borderRadius; -webkit-border-top-right-radius: $borderRadius; border-top-right-radius: $borderRadius; } +.ui-corner-bl { -moz-border-radius-bottomleft: $borderRadius; -webkit-border-bottom-left-radius: $borderRadius; border-bottom-left-radius: $borderRadius; } +.ui-corner-br { -moz-border-radius-bottomright: $borderRadius; -webkit-border-bottom-right-radius: $borderRadius; border-bottom-right-radius: $borderRadius; } +.ui-corner-top { -moz-border-radius-topleft: $borderRadius; -webkit-border-top-left-radius: $borderRadius; border-top-left-radius: $borderRadius; -moz-border-radius-topright: $borderRadius; -webkit-border-top-right-radius: $borderRadius; border-top-right-radius: $borderRadius; } +.ui-corner-bottom { -moz-border-radius-bottomleft: $borderRadius; -webkit-border-bottom-left-radius: $borderRadius; border-bottom-left-radius: $borderRadius; -moz-border-radius-bottomright: $borderRadius; -webkit-border-bottom-right-radius: $borderRadius; border-bottom-right-radius: $borderRadius; } +.ui-corner-right { -moz-border-radius-topright: $borderRadius; -webkit-border-top-right-radius: $borderRadius; border-top-right-radius: $borderRadius; -moz-border-radius-bottomright: $borderRadius; -webkit-border-bottom-right-radius: $borderRadius; border-bottom-right-radius: $borderRadius; } +.ui-corner-left { -moz-border-radius-topleft: $borderRadius; -webkit-border-top-left-radius: $borderRadius; border-top-left-radius: $borderRadius; -moz-border-radius-bottomleft: $borderRadius; -webkit-border-bottom-left-radius: $borderRadius; border-bottom-left-radius: $borderRadius; } +.ui-corner-all { -moz-border-radius: $borderRadius; -webkit-border-radius: $borderRadius; border-radius: $borderRadius; } \ No newline at end of file diff --git a/src/assets/components/themes/bootstrap/theme.css b/src/assets/components/themes/bootstrap/theme.css new file mode 100644 index 00000000000..65722f8ec3e --- /dev/null +++ b/src/assets/components/themes/bootstrap/theme.css @@ -0,0 +1,2200 @@ +@charset "UTF-8"; + +body .ui-widget, +body .ui-widget .ui-widget, +body .ui-widget input, body .ui-widget select, body .ui-widget textarea, body .ui-widget button { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; + text-decoration: none; + font-size: 1em; +} +body .ui-widget-content { + background-color: #ffffff; + border: 1px solid #c7c7c7; +} +body .ui-widget-header { + background: #ffffff; + color: #2d353c; + border: 1px solid #cdcdcd; +} +body .ui-state-active, +body .ui-state-highlight { + background-color: #0275d8; + color: #ffffff; +} +body .ui-state-error, +body .ui-state-default.ui-state-error { + border-bottom-color: #e13131; +} +body .ui-icon { + width: 1em; + height: 1em; + line-height: 1em; +} +body .ui-state-disabled, +body .ui-widget:disabled { + opacity: .35; + filter: Alpha(Opacity= 35); + background-image: none; + cursor: default !important; +} +body .ui-state-disabled *, +body .ui-widget:disabled * { + cursor: default !important; +} +body .ui-corner-all { + -moz-border-radius: 0.25em; + -webkit-border-radius: 0.25em; + border-radius: 0.25em; +} +body .ui-corner-top { + -moz-border-radius-topleft: 0.25em; + -webkit-border-top-left-radius: 0.25em; + border-top-left-radius: 0.25em; + -moz-border-radius-topright: 0.25em; + -webkit-border-top-right-radius: 0.25em; + border-top-right-radius: 0.25em; +} +body .ui-corner-bottom { + -moz-border-radius-bottomleft: 0.25em; + -webkit-border-bottom-left-radius: 0.25em; + border-bottom-left-radius: 0.25em; + -moz-border-radius-bottomright: 0.25em; + -webkit-border-bottom-right-radius: 0.25em; + border-bottom-right-radius: 0.25em; +} +body .ui-corner-left { + -moz-border-radius-topleft: 0.25em; + -webkit-border-top-left-radius: 0.25em; + border-top-left-radius: 0.25em; + -moz-border-radius-bottomleft: 0.25em; + -webkit-border-bottom-left-radius: 0.25em; + border-bottom-left-radius: 0.25em; +} +body .ui-corner-right { + -moz-border-radius-topright: 0.25em; + -webkit-border-top-right-radius: 0.25em; + border-top-right-radius: 0.25em; + -moz-border-radius-bottomright: 0.25em; + -webkit-border-bottom-right-radius: 0.25em; + border-bottom-right-radius: 0.25em; +} +body .ui-widget-overlay { + background-color: #424242; + opacity: 0.7; + filter: alpha(opacity=70); +} +body a { + color: #0275d8; + text-decoration: none; +} +body a:hover { + color: #0283f1; +} +body .ui-inputtext { + background: #ffffff; + padding: 0.5em 0.75em; + border: 1px solid rgba(0, 0, 0, 0.15); + -moz-border-radius: 0.25em; + -webkit-border-radius: 0.25em; + border-radius: 0.25em; + font-size: 1em; + color: #55595c; + line-height: 1.25; +} +body .ui-inputtext.ui-state-focus, +body .ui-inputtext:focus { + border: 1px solid #66afe9; +} +body .ui-button { + color: #ffffff; + background-color: #0275d8; + border: 1px solid transparent; + padding: 0.2em; + font-size: 1em; + -moz-transition: background-color 0.3s; + -o-transition: background-color 0.3s; + -webkit-transition: background-color 0.3s; + transition: background-color 0.3s; +} +body .ui-button:focus, +body .ui-button:enabled:hover { + outline: 0 none; + background-color: #0267bf; +} +body .ui-button:enabled:active { + background-color: #025aa5; + -moz-box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.2); + -webkit-box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.2); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +body .ui-button.raised-btn { + -moz-box-shadow: 0 1px 2.5px 0 rgba(0, 0, 0, 0.26), 0 1px 5px 0 rgba(0, 0, 0, 0.16); + -webkit-box-shadow: 0 1px 2.5px 0 rgba(0, 0, 0, 0.26), 0 1px 5px 0 rgba(0, 0, 0, 0.16); + box-shadow: 0 1px 2.5px 0 rgba(0, 0, 0, 0.26), 0 1px 5px 0 rgba(0, 0, 0, 0.16); +} +body .ui-togglebutton.ui-button.ui-state-focus { + -moz-box-shadow: 0px 0px 5px #1f89ce; + -webkit-box-shadow: 0px 0px 5px #1f89ce; + box-shadow: 0px 0px 5px #1f89ce; +} +body .ui-togglebutton:not(.ui-state-disabled):not(.ui-state-active):hover { + background-color: #0267bf; +} +body .ui-togglebutton:not(.ui-state-disabled).ui-state-active { + background-color: #025aa5; +} +body .ui-chips .ui-chips-token .ui-chips-token-label { + padding: 0.125em; +} +body .ui-chips .ui-chips-input-token input:focus { + border: none; +} +body .ui-chkbox .ui-chkbox-box { + border: 1px solid rgba(0, 0, 0, 0.15); + background-color: #ffffff; + -moz-transition: background-color 0.3s; + -o-transition: background-color 0.3s; + -webkit-transition: background-color 0.3s; + transition: background-color 0.3s; +} +body .ui-chkbox .ui-chkbox-box:not(.ui-state-disabled):not(.ui-state-active):hover { + border: 1px solid #b3b3b3; +} +body .ui-chkbox .ui-chkbox-box.ui-state-active { + border: 1px solid #0275d8; + background-color: #0275d8; + color: #ffffff; +} +body .ui-chkbox .ui-chkbox-box.ui-state-focus { + border: 1px solid #0275d8; + -webkit-box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.2); + box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.2); +} +body .ui-radiobutton { + display: inline-block; +} +body .ui-radiobutton .ui-radiobutton-box { + border: 1px solid rgba(0, 0, 0, 0.15); + background-color: #ffffff; + -moz-border-radius: 50%; + -webkit-border-radius: 50%; + border-radius: 50%; +} +body .ui-radiobutton .ui-radiobutton-box:not(.ui-state-disabled):not(.ui-state-active):hover { + border: 1px solid #b3b3b3; +} +body .ui-radiobutton .ui-radiobutton-box.ui-state-active { + border: 1px solid #0275d8; + background-color: #0275d8; + color: #ffffff; +} +body .ui-radiobutton .ui-radiobutton-box.ui-state-active .ui-radiobutton-icon.fa-circle { + color: #ffffff; +} +body .ui-radiobutton .ui-radiobutton-box.ui-state-focus { + border: 1px solid #0275d8; + -webkit-box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.2); + box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.2); +} +body .ui-radiobutton .ui-radiobutton-box .ui-radiobutton-icon { + font-size: 0.5em; + overflow: hidden; + position: relative; + top: -0.15em; +} +body .ui-inputswitch { + background-color: #0275d8; + text-transform: uppercase; +} +body .ui-inputswitch .ui-inputswitch-handle { + background-color: #ffffff; + border: 1px solid transparent; + box-sizing: border-box; +} +body .ui-inputswitch .ui-inputswitch-handle.ui-state-focus { + -webkit-box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.2); + box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.2); +} +body .ui-inputswitch .ui-inputswitch-on, +body .ui-inputswitch .ui-inputswitch-off { + color: #fff; +} +body .ui-inputswitch .ui-inputswitch-on span, +body .ui-inputswitch .ui-inputswitch-off span { + margin-right: 0.2em; + position: relative; + top: -0.1em; + font-weight: 700; +} +body .ui-selectbutton.ui-buttonset .ui-button { + background-color: #ffffff; + border-color: #cccccc; +} +body .ui-selectbutton.ui-buttonset .ui-button:not(.ui-state-disabled):not(.ui-state-active):hover { + background-color: #e6e6e6; + color: #373a3c; +} +body .ui-selectbutton.ui-buttonset .ui-button.ui-state-active { + background-color: #0275d8; + color: #ffffff; +} +body .ui-autocomplete .ui-autocomplete-dropdown .ui-button-text { + padding: 0.35em; +} +body .ui-autocomplete.ui-autocomplete-multiple .ui-autocomplete-multiple-container { + padding: 0.5em 0.75em; +} +body .ui-autocomplete.ui-autocomplete-multiple .ui-autocomplete-multiple-container .ui-autocomplete-input-token input:focus { + border: none; +} +body .ui-autocomplete-panel { + -webkit-box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.3); + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.3); +} +body .ui-autocomplete-panel .ui-autocomplete-items { + padding: 0; +} +body .ui-autocomplete-panel .ui-autocomplete-items .ui-autocomplete-list-item { + margin: 0; + padding: 0.375em 0.75em; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; +} +body .ui-autocomplete-panel .ui-autocomplete-items .ui-autocomplete-group { + padding: 0.375em 0.75em; + background-color: #e6e6e6; + color: #373a3c; +} +body .ui-dropdown { + border: 1px solid #d6d6d6; +} +body .ui-dropdown:not(.ui-state-disabled):hover { + background-color: #d9d9d9; + border-color: #cccccc; +} +body .ui-dropdown .ui-dropdown-label { + background: #ffffff; +} +body .ui-dropdown .ui-dropdown-trigger { + background-color: #ffffff; +} +body .ui-dropdown .ui-dropdown-trigger .fa { + color: #55595c; + margin-top: .65em; +} +body .ui-dropdown:not(.ui-state-disabled):hover .ui-dropdown-trigger, +body .ui-dropdown.ui-state-focus .ui-dropdown-trigger, +body .ui-dropdown.ui-state-focus .ui-dropdown-label, +body .ui-dropdown:not(.ui-state-disabled):hover .ui-dropdown-label { + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; + -moz-border-top-left-radius: 0; + -webkit-border-top-left-radius: 0; + border-top-left-radius: 0; + -moz-border-bottom-left-radius: 0; + -webkit-border-bottom-left-radius: 0; + border-bottom-left-radius: 0; + background-color: #d9d9d9; +} +body .ui-dropdown.ui-state-focus .ui-dropdown-label.ui-inputtext { + border: 0 none; +} +body .ui-dropdown-panel .ui-dropdown-filter-container { + padding: 0.375em 0.75em; +} +body .ui-dropdown-panel .ui-dropdown-filter-container .ui-dropdown-filter { + width: 100%; + box-sizing: border-box; + padding-right: 1.250em; +} +body .ui-dropdown-panel .ui-dropdown-filter-container .fa { + top: 1.05em; + right: 1.25em; +} +body .ui-dropdown-panel .ui-dropdown-items { + padding: 0; +} +body .ui-dropdown-panel .ui-dropdown-items .ui-dropdown-item { + padding: 0.375em 0.75em; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; +} +body .ui-dropdown-panel .ui-dropdown-items .ui-dropdown-item:not(.ui-state-highlight):hover { + background-color: #f4f3f4; + color: #373a3c; +} +body .ui-dropdown-panel .ui-dropdown-items .ui-dropdown-item.ui-state-highlight { + background-color: #0275d8; + color: #ffffff; +} +body .ui-dropdown-panel .ui-dropdown-items .ui-dropdown-item > td { + padding: 0.375em 0.75em; +} +body .ui-dropdown-panel .ui-dropdown-items .ui-dropdown-item-group { + padding: 0.375em 0.75em; + background-color: #e6e6e6; +} +body .ui-multiselect { + background: #ffffff; + padding: 0.5em 0.75em; + border: 1px solid #e6e6e6; + -moz-border-radius: 0.25em; + -webkit-border-radius: 0.25em; + border-radius: 0.25em; +} +body .ui-multiselect .ui-multiselect-trigger { + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; + -moz-border-top-left-radius: 0; + -webkit-border-top-left-radius: 0; + border-top-left-radius: 0; + -moz-border-bottom-left-radius: 0; + -webkit-border-bottom-left-radius: 0; + border-bottom-left-radius: 0; +} +body .ui-multiselect:not(.ui-state-disabled):hover { + color: #212121; +} +body .ui-multiselect:not(.ui-state-disabled):hover .ui-multiselect-trigger { + background-color: #d9d9d9; +} +body .ui-multiselect .ui-multiselect-trigger .fa { + margin-top: .8em; +} +body .ui-multiselect:not(.ui-state-disabled) .ui-multiselect-trigger:hover { + background-color: #d9d9d9; +} +body .ui-multiselect .ui-multiselect-panel { + padding: 0; +} +body .ui-multiselect .ui-multiselect-header { + border-top: 0 none; + border-left: 0 none; + border-right: 0 none; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; + padding: 0.375em 0.75em; +} +body .ui-multiselect .ui-multiselect-header .ui-multiselect-close { + color: #373a3c; +} +body .ui-multiselect .ui-multiselect-item { + margin: 0; + padding: 0.375em 0.75em; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; +} +body .ui-multiselect .ui-multiselect-item:not(.ui-state-highlight):hover { + background-color: #f4f3f4; + color: #373a3c; +} +body .ui-multiselect .ui-multiselect-item.ui-state-highlight { + background-color: #0275d8; + color: #ffffff; +} +body .ui-multiselect .ui-multiselect-item.ui-state-highlight .ui-chkbox { + border: 1px solid #108ffd; +} +body .ui-multiselect .ui-multiselect-item > td { + padding: 0.375em 0.75em; +} +body .ui-listbox { + padding: 0; + width: 12.5em; +} +body .ui-listbox .ui-listbox-item { + margin: 0; + padding: 0.375em 0.75em; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; +} +body .ui-listbox .ui-listbox-item:last-child { + border-bottom: none; +} +body .ui-listbox:not(.ui-state-disabled) .ui-listbox-item:hover { + background-color: #f4f3f4; + color: #373a3c; +} +body .ui-listbox .ui-listbox-item.ui-state-highlight { + background-color: #0275d8; + color: #ffffff; +} +body .ui-listbox .ui-listbox-item.ui-state-highlight .ui-chkbox { + border: 1px solid #108ffd; +} +body .ui-listbox.ui-state-disabled .ui-chkbox-box:not(.ui-state-active):hover { + border: 1px solid rgba(0, 0, 0, 0.15); + background-color: #ffffff; +} +body .ui-listbox .ui-listbox-item > td { + padding: 0.375em 0.75em; +} +body .ui-listbox .ui-listbox-header { + padding: 0.375em 0.75em; + border-top: 0 none; + border-right: 0 none; + border-left: 0 none; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; +} +body .ui-listbox .ui-listbox-header .ui-listbox-filter-container { + width: 8em; +} +body .ui-multiselectlistbox { + padding: 0; +} +body .ui-multiselectlistbox .ui-multiselectlistbox-header { + padding: 0.375em 0.75em; +} +body .ui-multiselectlistbox .ui-multiselectlistbox-item { + margin: 0; + padding: 0.375em 0.75em; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; +} +body .ui-multiselectlistbox .ui-multiselectlistbox-item:not(.ui-state-highlight):hover { + background-color: #f4f3f4; + color: #373a3c; +} +body .ui-multiselectlistbox .ui-multiselectlistbox-item.ui-state-highlight { + background-color: #0275d8; + color: #ffffff; +} +body .ui-rating .ui-rating-cancel { + display: inline-block; +} +body .ui-rating .ui-rating-cancel a { + background: none !important; + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-indent: 0px !important; + text-align: center; + display: block; + -moz-transition: color 0.3s; + -o-transition: color 0.3s; + -webkit-transition: color 0.3s; + transition: color 0.3s; + color: #e42a7b; +} +body .ui-rating .ui-rating-cancel a:before { + content: ""; +} +body .ui-rating .ui-rating-cancel a:hover { + color: #e74189; +} +body .ui-rating .ui-rating-star { + display: inline-block; +} +body .ui-rating .ui-rating-star a { + background: none !important; + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-indent: 0px !important; + text-align: center; + display: block; + color: #373a3c; +} +body .ui-rating .ui-rating-star a:before { + content: ""; +} +body .ui-rating .ui-rating-star a:hover { + color: #0275d8; +} +body .ui-rating .ui-rating-star-on a { + color: #0275d8; + background: none !important; + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-indent: 0px !important; + text-align: center; + display: block; +} +body .ui-rating .ui-rating-star-on a:before { + content: ""; +} +body .ui-spinner .ui-spinner-button { + z-index: auto; + box-sizing: border-box; +} +body .ui-spinner:not(.ui-state-disabled) .ui-spinner-button:hover { + background-color: #0267bf; + color: #ffffff; +} +body .ui-spinner:not(.ui-state-disabled) .ui-spinner-button:active { + background-color: #025aa5; + color: #ffffff; +} +body .ui-slider { + background-color: #e6e6e6; + border-color: #e6e6e6; +} +body .ui-slider.ui-slider-horizontal .ui-slider-handle { + top: -.2em; +} +body .ui-slider.ui-slider-vertical .ui-slider-handle { + left: -.2em; +} +body .ui-slider .ui-slider-handle { + background-color: #0275d8; + -moz-transition: background-color 0.3s; + -o-transition: background-color 0.3s; + -webkit-transition: background-color 0.3s; + transition: background-color 0.3s; + -moz-border-radius: 100%; + -webkit-border-radius: 100%; + border-radius: 100%; +} +body .ui-slider.ui-slider-animate .ui-slider-handle { + -moz-transition: background-color 0.3s,left 0.3s; + -o-transition: background-color 0.3s,left 0.3s; + -webkit-transition: background-color 0.3s,left 0.3s; + transition: background-color 0.3s,left 0.3s; +} +body .ui-slider .ui-slider-handle:hover { + background-color: #0267bf; +} +body .ui-slider .ui-slider-range { + background: #43a7fd; +} +body .ui-buttonset.ui-selectbutton .ui-button:first-child { + border-right: none; +} +body .ui-buttonset.ui-selectbutton .ui-button:last-child { + border-left: none; +} +body .ui-buttonset .ui-button { + background-color: #e6e6e6; + color: #373a3c; + border: 1px solid transparent; + -moz-border-radius: 0px; + -webkit-border-radius: 0px; + border-radius: 0px; +} +body .ui-buttonset .ui-button:hover { + background-color: #cdcdcd; +} +body .ui-buttonset .ui-button:focus { + background-color: #e6e6e6; + color: #373a3c; + -webkit-box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.2); + box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.2); + border: 1px solid #0275d8; +} +body .ui-buttonset .ui-button:active { + background-color: #0275d8; + color: #ffffff; +} +body .ui-buttonset .ui-button:active:focus { + background-color: #0275d8; + color: #ffffff; + -webkit-box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.2); + box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.2); +} +body .ui-buttonset .ui-button:first-child { + -moz-border-radius-topleft: 0.25em; + -webkit-border-top-left-radius: 0.25em; + border-top-left-radius: 0.25em; + -moz-border-radius-bottomleft: 0.25em; + -webkit-border-bottom-left-radius: 0.25em; + border-bottom-left-radius: 0.25em; +} +body .ui-buttonset .ui-button:last-child { + -moz-border-radius-topright: 0.25em; + -webkit-border-top-right-radius: 0.25em; + border-top-right-radius: 0.25em; + -moz-border-radius-bottomright: 0.25em; + -webkit-border-bottom-right-radius: 0.25em; + border-bottom-right-radius: 0.25em; +} +@media (max-width: 640px) { + body .ui-buttonset .ui-button { + margin-bottom: 0.063em; + -moz-border-radius: 0.25em; + -webkit-border-radius: 0.25em; + border-radius: 0.25em; + } +} +body .ui-splitbutton.ui-buttonset .ui-button { + color: #ffffff; + background-color: #0275d8; + border: 1px solid transparent; +} +body .ui-splitbutton.ui-buttonset .ui-button.ui-splitbutton-menubutton { + -moz-border-radius-topright: 0.25em; + -webkit-border-top-right-radius: 0.25em; + border-top-right-radius: 0.25em; + -moz-border-radius-bottomright: 0.25em; + -webkit-border-bottom-right-radius: 0.25em; + border-bottom-right-radius: 0.25em; +} +body .ui-splitbutton.ui-buttonset .ui-button.ui-splitbutton-menubutton .fa { + margin-left: -.65em; +} +body .ui-splitbutton.ui-buttonset .ui-button:hover { + background-color: #0267bf; + color: #ffffff; +} +body .ui-splitbutton.ui-buttonset .ui-button.ui-state-focus { + background-color: #0267bf; + color: #ffffff; +} +body .ui-splitbutton.ui-buttonset .ui-button.ui-state-active { + background-color: #025aa5; + color: #ffffff; +} +body .ui-datepicker { + padding: 0; +} +body .ui-datepicker .ui-datepicker-header { + padding: .75em 0; + background-color: #f5f5f5; + border: 0; + border-bottom: 1px solid #c7c7c7; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} +body .ui-datepicker .ui-datepicker-header .ui-datepicker-prev { + cursor: pointer; + color: #767b7f; + background: none !important; + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-indent: 0px !important; + text-align: center; + -moz-transition: color 0.3s; + -o-transition: color 0.3s; + -webkit-transition: color 0.3s; + transition: color 0.3s; + top: 1.25em; +} +body .ui-datepicker .ui-datepicker-header .ui-datepicker-prev:before { + content: ""; +} +body .ui-datepicker .ui-datepicker-header .ui-datepicker-prev span { + display: none; +} +body .ui-datepicker .ui-datepicker-header .ui-datepicker-prev.ui-datepicker-prev-hover { + color: #2d353c; +} +body .ui-datepicker .ui-datepicker-header .ui-datepicker-next { + cursor: pointer; + color: #767b7f; + background: none !important; + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-indent: 0px !important; + text-align: center; + -moz-transition: color 0.3s; + -o-transition: color 0.3s; + -webkit-transition: color 0.3s; + transition: color 0.3s; + top: 1.25em; +} +body .ui-datepicker .ui-datepicker-header .ui-datepicker-next:before { + content: ""; +} +body .ui-datepicker .ui-datepicker-header .ui-datepicker-next span { + display: none; +} +body .ui-datepicker .ui-datepicker-header .ui-datepicker-next.ui-datepicker-next-hover { + color: #2d353c; +} +body .ui-datepicker table { + font-size: 1em; +} +body .ui-datepicker table td a { + min-width: 1em; + text-align: center; + color: #373a3c; + font-size: .9em; +} +body .ui-datepicker table td a:hover { + background-color: #f4f3f4; +} +body .ui-datepicker table td a.ui-state-highlight { + color: #373a3c; + background-color: #e6e6e6; +} +body .ui-datepicker table td a.ui-state-active { + color: #ffffff; + background-color: #0275d8; +} +body .ui-datepicker .ui-datepicker-calendar td:not(.ui-state-disabled) a:hover { + background-color: #f4f3f4; +} +body .ui-trigger-calendar .ui-datepicker-trigger.ui-button { + -moz-border-radius-topleft: 0; + -webkit-border-top-left-radius: 0; + border-top-left-radius: 0; + -moz-border-radius-bottomleft: 0; + -webkit-border-bottom-left-radius: 0; + border-bottom-left-radius: 0; +} +body .ui-inplace .ui-inplace-display { + padding: 0.5em 0.75em; + -moz-border-radius: 0.25em; + -webkit-border-radius: 0.25em; + border-radius: 0.25em; +} +body .ui-inplace .ui-inplace-display:hover { + background-color: #f4f3f4; +} +body .ui-fileupload .ui-fileupload-buttonbar { + padding: .75em 1.25em; + background-color: #f5f5f5; + border-bottom: 0 none; +} +body .ui-fileupload .ui-fileupload-content { + padding: 1.25em; +} +body .ui-panel { + padding: 0; + border-color: rgba(0, 0, 0, 0.125); +} +body .ui-panel .ui-panel-titlebar { + border: 0 none; + border-bottom: 1px solid #e6e6e6; + padding: .75em 1.25em; + background-color: #f5f5f5; + -moz-border-radius-topleft: 0.25em; + -webkit-border-top-left-radius: 0.25em; + border-top-left-radius: 0.25em; + -moz-border-radius-topright: 0.25em; + -webkit-border-top-right-radius: 0.25em; + border-top-right-radius: 0.25em; + -moz-border-radius-bottomleft: 0px; + -webkit-border-bottom-left-radius: 0px; + border-bottom-left-radius: 0px; + -moz-border-radius-bottomright: 0px; + -webkit-border-bottom-right-radius: 0px; + border-bottom-right-radius: 0px; +} +body .ui-panel .ui-panel-titlebar .ui-panel-titlebar-icon { + position: relative; + color: #767b7f; + top: 0.125em; + -moz-transition: color 0.3s; + -o-transition: color 0.3s; + -webkit-transition: color 0.3s; + transition: color 0.3s; +} +body .ui-panel .ui-panel-titlebar .ui-panel-titlebar-icon:hover { + color: #2d353c; +} +body .ui-panel .ui-panel-content { + height: 100%; + box-sizing: border-box; + padding: 1.25em; +} +body .ui-panel .ui-panel-footer { + padding: 0.375em 0.75em; + border: 0 none; + border-top: 1px solid #c7c7c7; + margin: 0; +} +body .ui-fieldset { + border-color: #e6e6e6; +} +body .ui-fieldset .ui-fieldset-legend { + color: #2d353c; + background-color: #ffffff; + border: 1px solid #e6e6e6; + -moz-transition: background-color 0.3s; + -o-transition: background-color 0.3s; + -webkit-transition: background-color 0.3s; + transition: background-color 0.3s; +} +body .ui-fieldset .ui-fieldset-legend .ui-fieldset-toggler { + display: inline-block; + color: #767b7f; +} +body .ui-fieldset .ui-fieldset-legend:hover { + background-color: #f4f3f4; +} +body .ui-fieldset .ui-fieldset-legend:hover .ui-fieldset-toggler { + color: #2d353c; +} +body .ui-fieldset .ui-fieldset-legend.ui-state-focus { + background-color: #e6e6e6; +} +body .ui-fieldset .ui-fieldset-content { + padding: 0.375em 0.75em; +} +body .ui-notificationbar { + background-color: #0275d8; + color: #ffffff; +} +body .ui-accordion .ui-accordion-header { + background-color: #ffffff; + border: 1px solid #e6e6e6; + color: #0275d8; + -moz-transition: background-color 0.3s; + -o-transition: background-color 0.3s; + -webkit-transition: background-color 0.3s; + transition: background-color 0.3s; + margin-top: 0.625em; +} + +body .ui-accordion .ui-accordion-header a { + padding: .75em 1.25em .75em 2em; +} + +body .ui-accordion .ui-accordion-header:not(.ui-state-active):not(.ui-state-disabled):hover { + background-color: #f4f3f4; +} +body .ui-accordion .ui-accordion-header:not(.ui-state-active):not(.ui-state-disabled):hover .ui-icon { + color: #2d353c; +} +body .ui-accordion .ui-accordion-header.ui-state-active { + background-color: #0275d8; + color: #ffffff; +} +body .ui-accordion .ui-accordion-header.ui-state-active a { + color: #ffffff; +} +body .ui-accordion .ui-accordion-header.ui-tabview-outline { + border: 0 none; + outline: 0 none; + background-color: #e6e6e6; +} +body .ui-accordion .ui-accordion-header.ui-tabview-outline.ui-state-active { + background-color: #0283f1; +} +body .ui-accordion .ui-accordion-content { + padding: 1.25em; +} +body .ui-tabview { + padding: 0; + border-bottom: 1px solid #c7c7c7; +} +body .ui-tabview.ui-tabview-top, +body .ui-tabview.ui-tabview-bottom, +body .ui-tabview.ui-tabview-left, +body .ui-tabview.ui-tabview-right { + border: 0 none; +} +body .ui-tabview.ui-tabview-top .ui-tabview-nav, +body .ui-tabview.ui-tabview-bottom .ui-tabview-nav, +body .ui-tabview.ui-tabview-left .ui-tabview-nav, +body .ui-tabview.ui-tabview-right .ui-tabview-nav { + padding: 0; + border: 0 none; + background: #ffffff; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; + border-bottom: 1px solid #cccccc; +} +body .ui-tabview.ui-tabview-top .ui-tabview-nav li, +body .ui-tabview.ui-tabview-bottom .ui-tabview-nav li, +body .ui-tabview.ui-tabview-left .ui-tabview-nav li, +body .ui-tabview.ui-tabview-right .ui-tabview-nav li { + position: static; + -moz-transition: background-color 0.3s; + -o-transition: background-color 0.3s; + -webkit-transition: background-color 0.3s; + transition: background-color 0.3s; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; + margin: 0; + box-sizing: border-box; + background-color: #ffffff; + border: 1px solid transparent; + border-bottom: none; +} +body .ui-tabview.ui-tabview-top .ui-tabview-nav li.ui-state-default a, +body .ui-tabview.ui-tabview-bottom .ui-tabview-nav li.ui-state-default a, +body .ui-tabview.ui-tabview-left .ui-tabview-nav li.ui-state-default a, +body .ui-tabview.ui-tabview-right .ui-tabview-nav li.ui-state-default a { + padding: 0.375em 0.75em; + color: #2d353c; +} +body .ui-tabview.ui-tabview-top .ui-tabview-nav li.ui-state-default a:focus, +body .ui-tabview.ui-tabview-bottom .ui-tabview-nav li.ui-state-default a:focus, +body .ui-tabview.ui-tabview-left .ui-tabview-nav li.ui-state-default a:focus, +body .ui-tabview.ui-tabview-right .ui-tabview-nav li.ui-state-default a:focus { + outline: 0 none; +} +body .ui-tabview.ui-tabview-top .ui-tabview-nav li:not(.ui-state-active):not(.ui-state-disabled):hover, +body .ui-tabview.ui-tabview-bottom .ui-tabview-nav li:not(.ui-state-active):not(.ui-state-disabled):hover, +body .ui-tabview.ui-tabview-left .ui-tabview-nav li:not(.ui-state-active):not(.ui-state-disabled):hover, +body .ui-tabview.ui-tabview-right .ui-tabview-nav li:not(.ui-state-active):not(.ui-state-disabled):hover { + border-color: #dedede; + border-bottom: none; + background-color: #ffffff; +} +body .ui-tabview.ui-tabview-top .ui-tabview-nav li.ui-tabview-outline, +body .ui-tabview.ui-tabview-bottom .ui-tabview-nav li.ui-tabview-outline, +body .ui-tabview.ui-tabview-left .ui-tabview-nav li.ui-tabview-outline, +body .ui-tabview.ui-tabview-right .ui-tabview-nav li.ui-tabview-outline { + outline: 0 none; + background-color: #e6e6e6; +} +body .ui-tabview.ui-tabview-top .ui-tabview-nav li.ui-state-active, +body .ui-tabview.ui-tabview-bottom .ui-tabview-nav li.ui-state-active, +body .ui-tabview.ui-tabview-left .ui-tabview-nav li.ui-state-active, +body .ui-tabview.ui-tabview-right .ui-tabview-nav li.ui-state-active { + background-color: #0275d8; + border-color: #0275d8; +} +body .ui-tabview.ui-tabview-top .ui-tabview-nav li.ui-state-active a, +body .ui-tabview.ui-tabview-bottom .ui-tabview-nav li.ui-state-active a, +body .ui-tabview.ui-tabview-left .ui-tabview-nav li.ui-state-active a, +body .ui-tabview.ui-tabview-right .ui-tabview-nav li.ui-state-active a { + color: #ffffff; +} +body .ui-tabview.ui-tabview-top .ui-tabview-nav li.ui-state-active.ui-tabview-outline, +body .ui-tabview.ui-tabview-bottom .ui-tabview-nav li.ui-state-active.ui-tabview-outline, +body .ui-tabview.ui-tabview-left .ui-tabview-nav li.ui-state-active.ui-tabview-outline, +body .ui-tabview.ui-tabview-right .ui-tabview-nav li.ui-state-active.ui-tabview-outline { + background-color: #0283f1; +} +body .ui-tabview.ui-tabview-top .ui-tabview-navscroller-btn, +body .ui-tabview.ui-tabview-bottom .ui-tabview-navscroller-btn, +body .ui-tabview.ui-tabview-left .ui-tabview-navscroller-btn, +body .ui-tabview.ui-tabview-right .ui-tabview-navscroller-btn { + background-color: #ffffff; +} +body .ui-tabview.ui-tabview-top .ui-tabview-navscroller-btn:not(.ui-state-active):not(.ui-state-disabled):hover, +body .ui-tabview.ui-tabview-bottom .ui-tabview-navscroller-btn:not(.ui-state-active):not(.ui-state-disabled):hover, +body .ui-tabview.ui-tabview-left .ui-tabview-navscroller-btn:not(.ui-state-active):not(.ui-state-disabled):hover, +body .ui-tabview.ui-tabview-right .ui-tabview-navscroller-btn:not(.ui-state-active):not(.ui-state-disabled):hover { + background-color: #f4f3f4; +} +body .ui-tabview.ui-tabview-top .ui-tabview-navscroller-btn.ui-tabview-navscroller-btn-left, +body .ui-tabview.ui-tabview-bottom .ui-tabview-navscroller-btn.ui-tabview-navscroller-btn-left, +body .ui-tabview.ui-tabview-left .ui-tabview-navscroller-btn.ui-tabview-navscroller-btn-left, +body .ui-tabview.ui-tabview-right .ui-tabview-navscroller-btn.ui-tabview-navscroller-btn-left { + left: 0; + height: 2.063em; +} +body .ui-tabview.ui-tabview-top .ui-tabview-navscroller-btn.ui-tabview-navscroller-btn-right, +body .ui-tabview.ui-tabview-bottom .ui-tabview-navscroller-btn.ui-tabview-navscroller-btn-right, +body .ui-tabview.ui-tabview-left .ui-tabview-navscroller-btn.ui-tabview-navscroller-btn-right, +body .ui-tabview.ui-tabview-right .ui-tabview-navscroller-btn.ui-tabview-navscroller-btn-right { + right: 0; + height: 2.125em; +} +body .ui-tabview.ui-tabview-top .ui-tabview-navscroller-btn .ui-icon, +body .ui-tabview.ui-tabview-bottom .ui-tabview-navscroller-btn .ui-icon, +body .ui-tabview.ui-tabview-left .ui-tabview-navscroller-btn .ui-icon, +body .ui-tabview.ui-tabview-right .ui-tabview-navscroller-btn .ui-icon { + margin-top: 0.5em; +} +body .ui-tabview.ui-tabview-top .ui-tabview-nav li { + margin-right: 0.125em; + -moz-border-radius-topleft: 0.25em; + -webkit-border-top-left-radius: 0.25em; + border-top-left-radius: 0.25em; + -moz-border-radius-topright: 0.25em; + -webkit-border-top-right-radius: 0.25em; + border-top-right-radius: 0.25em; +} +body .ui-tabview.ui-tabview-left .ui-tabview-nav, +body .ui-tabview.ui-tabview-right .ui-tabview-nav { + border-bottom: none; +} +body .ui-tabview.ui-tabview-left .ui-tabview-nav li, +body .ui-tabview.ui-tabview-right .ui-tabview-nav li { + border: 1px solid transparent; + width: 100%; +} +body .ui-tabview.ui-tabview-left .ui-tabview-nav li:hover, +body .ui-tabview.ui-tabview-right .ui-tabview-nav li:hover { + border: 1px solid #dedede; +} +body .ui-tabview.ui-tabview-left .ui-tabview-nav li.ui-state-active, +body .ui-tabview.ui-tabview-right .ui-tabview-nav li.ui-state-active { + border-color: #0275d8; + border-bottom: none; +} +body .ui-tabview.ui-tabview-bottom .ui-tabview-nav { + border-bottom: none; + border-top: 1px solid #cccccc; +} +body .ui-tabview.ui-tabview-bottom .ui-tabview-nav li { + -moz-border-radius-bottomleft: 4px; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -moz-border-radius-bottomright: 4px; + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + margin-right: 0.125em; +} +body .ui-tabview.ui-tabview-bottom .ui-tabview-nav li:hover { + border-bottom: 1px solid #cccccc; + border-top-color: transparent; +} +body .ui-tabview.ui-tabview-left .ui-tabview-nav { + border-right: 1px solid #cccccc; +} +body .ui-tabview.ui-tabview-left .ui-tabview-nav li { + -moz-border-radius-topleft: 4px; + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; +} +body .ui-tabview.ui-tabview-left .ui-tabview-nav li:hover { + border-right: none; +} +body .ui-tabview.ui-tabview-right .ui-tabview-nav { + border-left: 1px solid #cccccc; + height: 9.375em; +} +body .ui-tabview.ui-tabview-right .ui-tabview-nav li { + -moz-border-radius-topright: 4px; + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -moz-border-radius-bottomright: 4px; + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; +} +body .ui-tabview.ui-tabview-right .ui-tabview-nav li:hover { + border-left-color: transparent; +} +body .ui-tabview .ui-tabview-panel { + padding: 0.375em 0.75em; +} +body .ui-scrollpanel .ui-scrollpanel-drag { + background-color: #e3e3e3; +} +body .ui-scrollpanel .ui-scrollpanel-track { + background-color: #f7f7f7; + border: 0 none; +} +body .ui-scrollpanel .ui-scrollpanel-corner { + background-color: #f7f7f7; +} +body .ui-toolbar { + padding: 0.375em 0.75em; +} +body .ui-toolbar .fa-ellipsis-v { + color: #aaaaaa; + margin: 0 0.5em; +} +body .ui-tooltip .ui-tooltip-arrow { + color: #2d353c; +} +body .ui-tooltip .ui-tooltip-text { + background-color: #2d353c; +} +@media (max-width: 640px) { + body .ui-panelgrid .ui-grid-responsive .ui-grid-row { + border: 0 none; + } +} +body .ui-paginator { + background-color: #ffffff; + padding: 0; + box-sizing: border-box; +} +body .ui-paginator .ui-paginator-first, +body .ui-paginator .ui-paginator-prev, +body .ui-paginator .ui-paginator-next, +body .ui-paginator .ui-paginator-last { + color: #0275d8; + -moz-transition: background-color 0.3s; + -o-transition: background-color 0.3s; + -webkit-transition: background-color 0.3s; + transition: background-color 0.3s; + min-height: 0.875em; + min-width: 2em; + padding: 0.5em 0.5em; + vertical-align: top; +} +body .ui-paginator .ui-paginator-first:hover, +body .ui-paginator .ui-paginator-prev:hover, +body .ui-paginator .ui-paginator-next:hover, +body .ui-paginator .ui-paginator-last:hover { + background-color: #f4f3f4; +} +body .ui-paginator .ui-paginator-first:before, +body .ui-paginator .ui-paginator-prev:before, +body .ui-paginator .ui-paginator-next:before, +body .ui-paginator .ui-paginator-last:before { + position: relative; + top: 0.063em; +} +body .ui-paginator .ui-paginator-first { + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; +} +body .ui-paginator .ui-paginator-prev { + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; +} +body .ui-paginator .ui-paginator-next { + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; +} +body .ui-paginator .ui-paginator-last { + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; +} +body .ui-paginator .ui-paginator-pages { + padding: 0; +} +body .ui-paginator .ui-paginator-pages .ui-paginator-page { + padding: 0.5em 0.625em; + min-width: 2em; + color: #0275d8; + -moz-transition: background-color 0.3s; + -o-transition: background-color 0.3s; + -webkit-transition: background-color 0.3s; + transition: background-color 0.3s; + border-radius: 0; +} +body .ui-paginator .ui-paginator-pages .ui-paginator-page.ui-state-active { + color: #ffffff; +} +body .ui-paginator .ui-paginator-pages .ui-paginator-page:hover { + background-color: #f4f3f4; +} +body .ui-paginator .ui-paginator-pages .ui-paginator-page:hover.ui-state-active { + background-color: #0275d8; +} +body .ui-datatable .ui-datatable-header, +body .ui-datatable .ui-datatable-footer { + padding: .75em 1.25em; + background-color: #f5f5f5; +} +body .ui-datatable .ui-editable-column.ui-cell-editing .ui-cell-editor { + font-size: medium; +} +body .ui-datatable .ui-paginator { + padding: 0; +} +body .ui-datatable .ui-datatable-thead > tr > th, +body .ui-datatable .ui-datatable-tfoot > tr > td { + background-color: #ffffff; + padding: .75em; + border-color: #c7c7c7; + color: #373a3c; +} +body .ui-datatable thead th.ui-sortable-column:not(.ui-state-active):hover { + background-color: #e3e3e3; +} +body .ui-datatable thead th.ui-state-active { + background-color: #0275d8; + border-color: #0267bf; + color: #ffffff; +} +body .ui-datatable thead th.ui-state-active .ui-dropdown-item { + color: #373a3c; +} +body .ui-datatable thead th:focus { + outline: 0 none; + background-color: #f0f3f5; +} +body .ui-datatable thead th:focus.ui-state-active { + background-color: #0283f1; +} +body .ui-datatable tfoot th.ui-state-default { + background-color: #ffffff; + padding: 0.375em 0.75em; + border-color: #c7c7c7; + color: #373a3c; +} +body .ui-datatable .ui-datatable-data tr.ui-datatable-even { + background-color: #f7f7f7; +} +body .ui-datatable .ui-datatable-data tr.ui-datatable-even.ui-state-highlight { + background-color: #0275d8; + color: #ffffff; + border-color: #0267bf; +} +body .ui-datatable .ui-datatable-data tr.ui-state-highlight { + border-color: #0267bf; +} +body .ui-datatable .ui-datatable-data.ui-datatable-hoverable-rows > tr.ui-widget-content:not(.ui-state-highlight):hover { + background-color: #e3e3e3; + cursor: pointer; +} +body .ui-datatable .ui-datatable-data tr.ui-row-editing.ui-datatable-odd, +body .ui-datatable .ui-datatable-data tr.ui-row-editing.ui-datatable-even { + border-color: #c7c7c7; + border-bottom-color: #0275d8; +} +body .ui-datatable .ui-datatable-data > tr > td { + padding: .75em; +} +body .ui-datatable .ui-datatable-data tr td.ui-editable-column input { + width: 100%; + box-sizing: border-box; + border: 0 none; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; +} +body .ui-datatable .ui-datatable-scrollable-header, +body .ui-datatable .ui-datatable-scrollable-footer { + background-color: #f5f5f5; +} +body .ui-datatable .ui-datatable-scrollable-header .ui-datatable-scrollable-header-box td, +body .ui-datatable .ui-datatable-scrollable-footer .ui-datatable-scrollable-header-box td { + color: #373a3c; +} +body .ui-datatable .ui-datatable-data tr.ui-rowgroup-header { + font-weight: bold; +} +body .ui-datatable .ui-rowgroup-header { + color: #2d353c; +} + +body .ui-datatable .ui-rowgroup-header a { + color: #2d353c; +} + +body .ui-datagrid .ui-datagrid-header { + padding: .75em 1.25em; + background-color: #f5f5f5; +} +body .ui-datagrid .ui-paginator { + padding: 0; +} +body .ui-datalist .ui-datalist-header { + padding: .75em 1.25em; + background-color: #f5f5f5; +} +body .ui-datalist .ui-paginator { + padding: 0; +} +body .ui-datascroller .ui-datascroller-header { + padding: .75em 1.25em; + background-color: #f5f5f5; +} +body .ui-picklist .ui-picklist-buttons button { + font-size: 1.1em; +} +body .ui-picklist .ui-picklist-caption { + padding: .75em 1.25em; + background-color: #f5f5f5; +} +body .ui-picklist .ui-picklist-filter-container { + margin-bottom: 0.063em; +} +body .ui-picklist .ui-picklist-filter-container .ui-icon { + top: 0.313em; + right: 0.25em; + color: #747a7f; +} +body .ui-picklist .ui-picklist-list .ui-picklist-item { + padding: 0.375em 0.75em; + margin: 0; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; + border-bottom: 1px solid rgba(0, 0, 0, 0.15); +} +body .ui-picklist .ui-picklist-list .ui-picklist-item:not(.ui-state-highlight):hover { + background-color: #f4f3f4; + color: #373a3c; +} +body .ui-picklist .ui-picklist-list .ui-picklist-item.ui-state-highlight { + background-color: #0275d8; + color: #ffffff; +} +body .ui-orderlist .ui-orderlist-controls button { + font-size: 1.1em; +} +body .ui-orderlist .ui-orderlist-caption { + padding: .75em 1.25em; + background-color: #f5f5f5; + box-sizing: border-box; + width: 12.5em; +} +body .ui-orderlist .ui-orderlist-list { + box-sizing: border-box; +} +body .ui-orderlist .ui-orderlist-list .ui-orderlist-item { + padding: 0.375em 0.75em; + margin: 0; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; + border-bottom: 1px solid rgba(0, 0, 0, 0.15); +} +body .ui-orderlist .ui-orderlist-list .ui-orderlist-item:last-child { + border-bottom: none; +} +body .ui-orderlist .ui-orderlist-list .ui-orderlist-item:not(.ui-state-highlight):hover { + background-color: #f4f3f4; + color: #373a3c; +} +body .ui-orderlist .ui-orderlist-list .ui-orderlist-item.ui-state-highlight { + background-color: #0275d8; + color: #ffffff; +} +body .ui-orderlist.ui-grid-responsive .ui-grid-row .ui-orderlist-controls { + margin-right: 0; + padding-right: 0.5em; +} +body .ui-carousel { + padding: 0; +} +body .ui-carousel .ui-carousel-header { + margin: 0; + border: 0 none; + border-bottom: 1px solid #e6e6e6; + padding: .75em 1.25em; + background-color: #f5f5f5; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} +body .ui-carousel .ui-carousel-header .ui-carousel-header-title { + padding: 0; +} +body .ui-carousel .ui-carousel-footer { + border: 0 none; + border-top: 1px solid #e6e6e6; + margin: 0; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; + padding: .75em 1.25em; + background-color: #f5f5f5; +} +body .ui-carousel .ui-carousel-button { + margin-top: 0.2em; + -moz-transition: color 0.3s; + -o-transition: color 0.3s; + -webkit-transition: color 0.3s; + transition: color 0.3s; + color: #767b7f; +} +body .ui-carousel .ui-carousel-button:hover { + color: #2d353c; +} +body .ui-carousel .ui-carousel-button.ui-state-disabled:hover { + color: #2d353c; +} +body .ui-carousel .ui-carousel-page-links { + margin-top: 0.188em; +} +body .ui-carousel .ui-carousel-page-links .ui-carousel-page-link { + color: #767b7f; +} +body .ui-carousel .ui-carousel-page-links .ui-carousel-page-link.fa-circle-o { + background: none !important; + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-indent: 0px !important; + text-align: center; +} +body .ui-carousel .ui-carousel-page-links .ui-carousel-page-link.fa-circle-o:before { + content: ""; +} +body .ui-carousel .ui-carousel-page-links .ui-carousel-page-link.fa-dot-circle-o { + background: none !important; + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-indent: 0px !important; + text-align: center; +} +body .ui-carousel .ui-carousel-page-links .ui-carousel-page-link.fa-dot-circle-o:before { + content: ""; +} +body .ui-carousel .ui-carousel-page-links .ui-carousel-page-link.ui-icon-radio-on { + color: #0275d8; + background-color: #767b7f; +} +body .ui-treetable .ui-treetable-header { + padding: .75em 1.25em; + background-color: #f5f5f5; +} +body .ui-treetable .ui-treetable-footer { + padding: .75em 1.25em; + background-color: #f5f5f5; +} +body .ui-treetable .ui-paginator { + padding: 0.375em 0.75em; +} +body .ui-treetable thead th { + background-color: #ffffff; + padding: .75em; + border-color: #c7c7c7; + color: #373a3c; +} +body .ui-treetable thead th.ui-state-active { + border-color: #0267bf; + background-color: #0275d8; + color: #ffffff; +} +body .ui-treetable tfoot td { + background-color: #ffffff; + padding: .75em; + border-color: #e6e6e6; +} +body .ui-treetable .ui-treetable-data tr:not(.ui-state-highlight):hover { + background-color: #e3e3e3; +} +body .ui-treetable .ui-treetable-row.ui-state-highlight .ui-chkbox-icon { + color: #555555; + margin: 0; +} +body .ui-treetable .ui-treetable-row.ui-state-highlight .ui-treetable-toggler { + color: #ffffff; +} +body .ui-treetable .ui-treetable-row.ui-treetable-row-selectable:not(.ui-state-highlight):hover { + background-color: #e3e3e3; +} +body .ui-treetable .ui-treetable-data tr.ui-state-highlight { + border-color: #0267bf; +} +body .ui-treetable .ui-treetable-data tr td .ui-treetable-toggler { + font-size: 3em; + vertical-align: middle; + display: inline-block; + position: relative; +} +body .ui-treetable .ui-treetable-data tr td .ui-chkbox { + vertical-align: middle; + display: inline-block; + position: relative; +} +body .ui-treetable tbody td{ + padding: .75em; +} +body .ui-treetable .ui-treetable-data tr td .ui-chkbox .ui-chkbox-icon { + color: #0275d8; + left: 0px; +} +body .ui-treetable .ui-treetable-scrollable-header, +body .ui-treetable .ui-treetable-scrollable-footer { + background-color: #f0f3f5; +} +body .ui-treetable .ui-treetable-scrollable-header .ui-treetable-scrollable-header-box td, +body .ui-treetable .ui-treetable-scrollable-footer .ui-treetable-scrollable-header-box td { + color: #373a3c; +} +body .ui-treetable .ui-treetable-scrollable-body::-webkit-scrollbar { + background-color: #f0f3f5; +} +body .ui-tree { + box-sizing: border-box; +} +body .ui-tree .ui-treenode .ui-treenode-content .ui-tree-toggler { + font-size: 1.1em; + vertical-align: middle; + display: inline-block; + color: #747a7f; + margin-top: 0.2em; +} +body .ui-tree .ui-treenode .ui-treenode-content .ui-treenode-icon { + vertical-align: middle; + display: inline-block; + margin: 0.2em 0.375em 0 0; + font-size: 1.1em; + color: #747a7f; +} +body .ui-tree .ui-treenode .ui-treenode-content .ui-treenode-label { + margin: 0; + vertical-align: middle; + display: inline-block; + padding: 0; +} +body .ui-tree.ui-tree-selectable .ui-treenode .ui-treenode-content .ui-treenode-label:not(.ui-state-highlight):hover { + background-color: #f4f3f4; + color: #373a3c; +} +body .ui-tree .ui-treenode .ui-treenode-content .ui-treenode-label.ui-state-highlight { + background-color: #0275d8; + color: #ffffff; +} +body .ui-tree .ui-tree-droppoint:hover { + background-color: #0275d8; +} +body .ui-tree.ui-tree-horizontal .ui-treenode-content { + background-color: #ffffff; + border: 1px solid #c7c7c7; +} +body .ui-tree.ui-tree-horizontal .ui-treenode-content.ui-treenode-selectable .ui-treenode-label:not(.ui-state-highlight):hover { + background-color: inherit; + color: inherit; +} +body .ui-tree.ui-tree-horizontal .ui-treenode-content.ui-treenode-selectable:not(.ui-state-highlight):hover { + background-color: #f4f3f4; + color: #373a3c; +} +body .ui-tree.ui-tree-horizontal .ui-treenode-content.ui-state-highlight { + background-color: #0275d8; + color: #ffffff; +} +body .ui-tree.ui-tree-horizontal .ui-treenode-content.ui-state-highlight .ui-tree-toggler, +body .ui-tree.ui-tree-horizontal .ui-treenode-content.ui-state-highlight .ui-treenode-icon { + color: #ffffff; +} +body .ui-tree.ui-tree-horizontal .ui-treenode-content .ui-chkbox .ui-icon { + color: #0275d8; +} +body .ui-tree-draghelper { + border: 1px solid #0275d8; +} +body .fc .fc-event { + background-color: #025aa5; + border-color: #025aa5; +} +body .fc .fc-slats td { + background-color: #ffffff; +} +body .fc .fc-toolbar .fc-prev-button span { + line-height: inherit; + background: none !important; + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-indent: 0px !important; + text-align: center; +} +body .fc .fc-toolbar .fc-prev-button span:before { + content: ""; +} +body .fc .fc-toolbar .fc-prev-button .ui-icon { + position: relative; + top: 0.186em; +} +body .fc .fc-toolbar .fc-next-button span { + line-height: inherit; + background: none !important; + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-indent: 0px !important; + text-align: center; +} +body .fc .fc-toolbar .fc-next-button span:before { + content: ""; +} +body .fc .fc-toolbar .fc-next-button .ui-icon { + position: relative; + top: 0.186em; +} +/* Messages */ + +.ui-messages.ui-messages-success { + background-color: #dff0d8; + border-color: #d0e9c6; + color: #3c763d; +} +.ui-messages.ui-messages-success .ui-messages-close { + color: #3c763d; +} +.ui-messages.ui-messages-info { + background-color: #d9edf7; + border-color: #bcdff1; + color: #31708f; +} +.ui-messages.ui-messages-info .ui-messages-close { + color: #31708f; +} +.ui-messages.ui-messages-warn { + background-color: #fcf8e3; + border-color: #faf2cc; + color: #8a6d3b; +} +.ui-messages.ui-messages-warn .ui-messages-close { + color: #8a6d3b; +} +.ui-messages.ui-messages-error { + background-color: #f2dede; + border-color: #ebcccc; + color: #a94442; +} +.ui-messages.ui-messages-error .ui-messages-close { + color: #a94442; +} +/* Growl */ + +.ui-growl .ui-growl-message-success { + background-color: #dff0d8; + color: #3c763d; +} +.ui-growl .ui-growl-message-info { + background-color: #d9edf7; + color: #31708f; +} +.ui-growl .ui-growl-message-warn { + background-color: #fcf8e3; + color: #8a6d3b; +} +.ui-growl .ui-growl-message-error { + background-color: #f2dede; + color: #a94442; +} +body .ui-overlaypanel { + -webkit-box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.3); + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.3); +} +body .ui-overlaypanel .ui-overlaypanel-close { + background-color: #ffffff; + color: #373a3c; + border: 1px solid #c7c7c7; + padding: 0.125em; + border-radius: 15px; + -moz-transition: color 0.3s; + -o-transition: color 0.3s; + -webkit-transition: color 0.3s; + transition: color 0.3s; +} +body .ui-overlaypanel .ui-overlaypanel-close:hover { + color: #0275d8; +} +body .ui-overlaypanel .ui-overlaypanel-close span { + margin-left: 0.063em; +} +body .ui-dialog { + -webkit-box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.3); + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.3); +} +body .ui-dialog .ui-dialog-titlebar { + padding: 1em; + border-bottom: 1px solid #e5e5e5; +} +body .ui-dialog .ui-dialog-titlebar .ui-dialog-title { + margin: 0; + float: none; + font-size: 1.5em; + font-weight: bold; +} +body .ui-dialog .ui-dialog-titlebar .ui-dialog-titlebar-icon { + color: #767b7f; + border: 0 none; + -moz-transition: color 0.3s; + -o-transition: color 0.3s; + -webkit-transition: color 0.3s; + transition: color 0.3s; + padding: 0; +} +body .ui-dialog .ui-dialog-titlebar .ui-dialog-titlebar-icon:hover { + color: #2d353c; +} +body .ui-dialog .ui-dialog-content { + padding: 1em; +} +body .ui-dialog .ui-dialog-buttonpane { + padding: 0.375em 0.75em; + text-align: right; + border-top: 1px solid #e5e5e5; +} +body .ui-dialog.ui-confirm-dialog .ui-dialog-content > span { + display: inline-block; + vertical-align: middle; + line-height: 1em; + margin: 0; +} +body .ui-tooltip .ui-tooltip-text { + -webkit-box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.3); + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.3); +} +body .ui-tooltip.ui-state-error { + border: 0 none; +} +body .ui-lightbox { + -webkit-box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.3); + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.3); +} +body .ui-lightbox .ui-lightbox-caption { + padding: 0.375em 0.75em; +} +body .ui-lightbox .ui-lightbox-caption .ui-lightbox-caption-text { + color: #2d353c; + margin: 0; +} +body .ui-lightbox .ui-lightbox-caption .ui-lightbox-close { + padding: 0; + color: #2d353c; + -moz-transition: color 0.3s; + -o-transition: color 0.3s; + -webkit-transition: color 0.3s; + transition: color 0.3s; +} +body .ui-lightbox .ui-lightbox-caption .ui-lightbox-close:hover { + color: #0275d8; +} +body .ui-lightbox .ui-lightbox-content-wrapper { + overflow: hidden; +} +body .ui-lightbox .ui-lightbox-content-wrapper .ui-lightbox-nav-left { + background: none !important; + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-indent: 0px !important; + text-align: center; + -moz-transition: all 0.3s; + -o-transition: all 0.3s; + -webkit-transition: all 0.3s; + transition: all 0.3s; + font-size: 1.5em; + margin-left: 0.25em; +} +body .ui-lightbox .ui-lightbox-content-wrapper .ui-lightbox-nav-left:before { + content: ""; +} +body .ui-lightbox .ui-lightbox-content-wrapper .ui-lightbox-nav-left:hover { + -webkit-transform: scale(1.2); + -moz-transform: scale(1.2); + -o-transform: scale(1.2); + -ms-transform: scale(1.2); + transform: scale(1.2); +} +body .ui-lightbox .ui-lightbox-content-wrapper .ui-lightbox-nav-left span { + display: none; +} +body .ui-lightbox .ui-lightbox-content-wrapper .ui-lightbox-nav-right { + background: none !important; + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-indent: 0px !important; + text-align: center; + -moz-transition: all 0.3s; + -o-transition: all 0.3s; + -webkit-transition: all 0.3s; + transition: all 0.3s; + font-size: 1.5em; + margin-right: 0.25em; +} +body .ui-lightbox .ui-lightbox-content-wrapper .ui-lightbox-nav-right:before { + content: ""; +} +body .ui-lightbox .ui-lightbox-content-wrapper .ui-lightbox-nav-right:hover { + -webkit-transform: scale(1.2); + -moz-transform: scale(1.2); + -o-transform: scale(1.2); + -ms-transform: scale(1.2); + transform: scale(1.2); +} +body .ui-lightbox .ui-lightbox-content-wrapper .ui-lightbox-nav-right span { + display: none; +} +body .ui-lightbox .ui-lightbox-content-wrapper .ui-lightbox-content.ui-lightbox-loading + a { + display: none; +} +body .ui-breadcrumb { + background-color: #ffffff; + padding: 0.375em 0.75em; +} +body .ui-breadcrumb ul li { + float: none; + display: inline-block; + vertical-align: middle; +} +body .ui-breadcrumb ul li .ui-menuitem-link { + color: #0275d8; + margin: 0; + position: relative; + top: 0; +} +body .ui-breadcrumb ul li.ui-breadcrumb-chevron { + font-size: 1em; + margin: 0.25em 0.375em 0 0.375em; + color: #767b7f; +} +body .ui-breadcrumb ul li.ui-breadcrumb-chevron.fa-chevron-right:before { + content: "/"; + font-size: 1.375em; + font-weight: 700; +} +body .ui-breadcrumb ul li:first-child { + font-size: 1.2em; +} +body .ui-breadcrumb ul li:first-child a.ui-icon-home { + color: #767b7f; + margin: 0; +} +body .ui-steps { + position: relative; +} +body .ui-steps .ui-steps-item { + background-color: transparent; + text-align: center; +} +body .ui-steps .ui-steps-item.ui-state-disabled { + opacity: 1; + filter: alpha(opacity=100); +} +body .ui-steps .ui-steps-item .ui-menuitem-link { + display: inline-block; + text-align: center; + background-color: transparent; + overflow: hidden; +} +body .ui-steps .ui-steps-item .ui-menuitem-link .ui-steps-number { + display: inline-block; + background-color: #ffffff; + -moz-border-radius: 50%; + -webkit-border-radius: 50%; + border-radius: 50%; + padding: 0.25em 0.563em; + color: #747a7f; + position: relative; + width: 28px; + margin-top: 0; + font-size: 1em; + top: 0.875em; + margin-bottom: 0.75em; + border: 1px solid #cccccc; +} +body .ui-steps .ui-steps-item .ui-menuitem-link .ui-steps-title { + display: block; + margin-top: 0.375em; + color: #747a7f; +} +body .ui-steps .ui-steps-item.ui-state-highlight .ui-steps-number { + background-color: #0275d8; + color: #ffffff; + border-color: #0275d8; +} +body .ui-steps .ui-steps-item:not(.ui-state-highlight) .ui-steps-number:hover { + background-color: #e6e6e6; +} +body .ui-steps .ui-steps-item.ui-state-highlight .ui-steps-title { + font-weight: 700; + color: #373a3c; +} +body .ui-steps .ui-steps-item:last-child .ui-menuitem-link { + display: block; +} +body .ui-steps:before { + content: ' '; + border: 1px solid #0275d8; + width: 100%; + top: 45%; + left: 0; + display: block; + position: absolute; +} +body .ui-menu { + padding: 0; +} +body .ui-menu.ui-shadow { + -webkit-box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.3); + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.3); +} +body .ui-menu .ui-menu-parent .ui-submenu-icon { + margin-top: 0.2em; +} +body .ui-menu .ui-menu-list .ui-widget-header { + width: 100%; + box-sizing: border-box; + border: 0 none; + background: #e6e6e6; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; +} +body .ui-menu .ui-menu-list .ui-widget-header h3 { + padding: 0.375em 0.75em; + font-weight: 400; +} +body .ui-menu .ui-menu-list .ui-widget-header .ui-icon { + color: #767b7f; +} +body .ui-menu .ui-menu-list .ui-widget-header:hover { + background-color: #e6e6e6; +} +body .ui-menu .ui-menu-list .ui-widget-header:hover .ui-icon { + color: #2d353c; +} +body .ui-menu .ui-menu-list .ui-widget-header:first-child { + margin-top: 0; +} +body .ui-menu .ui-menu-list .ui-menuitem { + margin: 0; + box-sizing: border-box; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; +} +body .ui-menu .ui-menu-list .ui-menuitem .ui-menuitem-link { + padding: 0.5em 0.75em; + width: 100%; + box-sizing: border-box; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; + color: #373a3c; +} +body .ui-menu .ui-menu-list .ui-menuitem .ui-menuitem-link:hover, +body .ui-menu .ui-menu-list .ui-menuitem.ui-menuitem-active > .ui-menuitem-link { + background-color: #0275d8; + color: #ffffff; +} +body .ui-menu .ui-menu-list .ui-menu-child { + padding: 0; +} +body .ui-menu .ui-menu-list .ui-menu-child.ui-shadow { + -webkit-box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.3); + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.3); +} +body .ui-menu.ui-menubar { + background-color: #ffffff; + border-color: #e6e6e6; +} +body .ui-menu.ui-menubar > .ui-menu-list > .ui-menuitem { + width: auto; +} +body .ui-menu.ui-menubar > .ui-menu-list > .ui-menuitem > .ui-menuitem-link { + color: #2d353c; +} +body .ui-menu.ui-menubar > .ui-menu-list > .ui-menuitem > .ui-menuitem-link .ui-menuitem-icon { + color: #767b7f; +} +body .ui-menu.ui-menubar > .ui-menu-list > .ui-menuitem > .ui-menuitem-link:hover { + color: #ffffff; +} +body .ui-menu.ui-menubar > .ui-menu-list > .ui-menuitem > .ui-menuitem-link:hover .ui-menuitem-icon { + color: #ffffff; +} +body .ui-menu.ui-menubar > .ui-menu-list > .ui-menuitem.ui-menubar-options { + margin-right: 8px; +} +body .ui-menu.ui-megamenu .ui-menu-list > table > tbody > tr > td { + padding: 0; +} +body .ui-menu.ui-megamenu.ui-megamenu-vertical > .ui-menu-list .ui-menuitem { + width: 100%; +} +body .ui-tabmenu { + border: 0 none; +} +body .ui-tabmenu .ui-tabmenu-nav { + padding: 0; +} +body .ui-tabmenu .ui-tabmenu-nav .ui-tabmenuitem { + margin: 0; + position: static; + -moz-transition: background-color 0.3s; + -o-transition: background-color 0.3s; + -webkit-transition: background-color 0.3s; + transition: background-color 0.3s; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; +} +body .ui-tabmenu .ui-tabmenu-nav .ui-tabmenuitem .ui-menuitem-link { + color: #2d353c; + padding: 0.375em 0.75em; +} +body .ui-tabmenu .ui-tabmenu-nav .ui-tabmenuitem .ui-menuitem-link .ui-menuitem-icon, +body .ui-tabmenu .ui-tabmenu-nav .ui-tabmenuitem .ui-menuitem-link .ui-menuitem-text { + vertical-align: middle; + display: inline-block; + float: none; +} +body .ui-tabmenu .ui-tabmenu-nav .ui-tabmenuitem .ui-menuitem-link .ui-menuitem-icon { + color: #767b7f; +} +body .ui-tabmenu .ui-tabmenu-nav .ui-tabmenuitem:not(.ui-state-active):hover { + background-color: #e6e6e6; +} +body .ui-tabmenu .ui-tabmenu-nav .ui-tabmenuitem:hover .ui-menuitem-icon { + color: #2d353c; +} +body .ui-tabmenu .ui-tabmenu-nav .ui-tabmenuitem.ui-state-active .ui-menuitem-link { + background-color: #0275d8; + color: #ffffff; +} +body .ui-tabmenu .ui-tabmenu-nav .ui-tabmenuitem.ui-state-active .ui-menuitem-link .ui-menuitem-icon { + color: #ffffff; +} +body .ui-menubutton .ui-button.ui-button-text-icon-left .ui-icon { + margin-top: -.625em; +} +body .ui-panelmenu .fa { + position: static; +} +body .ui-panelmenu .ui-panelmenu-panel { + border: 1px solid #c7c7c7; + border-bottom: none; +} +body .ui-panelmenu .ui-panelmenu-panel:last-child { + border-bottom: 1px solid #c7c7c7; +} +body .ui-panelmenu .ui-panelmenu-header { + background-color: #ffffff; + padding: 0; + font-size: 1em; + color: #2d353c; + -moz-transition: background-color 0.3s; + -o-transition: background-color 0.3s; + -webkit-transition: background-color 0.3s; + transition: background-color 0.3s; +} +body .ui-panelmenu .ui-panelmenu-header .fa { + color: #767b7f; +} +body .ui-panelmenu .ui-panelmenu-header a { + padding: 0.5em 0.75em; + color: #2d353c; +} +body .ui-panelmenu .ui-panelmenu-header:not(.ui-state-active):hover { + background-color: #e6e6e6; +} +body .ui-panelmenu .ui-panelmenu-header:not(.ui-state-active):hover .fa { + color: #2d353c; +} +body .ui-panelmenu .ui-panelmenu-header.ui-state-active { + background-color: #0275d8; +} +body .ui-panelmenu .ui-panelmenu-header.ui-state-active a { + color: #ffffff; +} +body .ui-panelmenu .ui-panelmenu-header.ui-state-active .fa { + color: #ffffff; +} +body .ui-panelmenu .ui-panelmenu-content .ui-menuitem-link { + padding: 0.375em 0.75em; + color: #373a3c; + -moz-transition: background-color 0.3s; + -o-transition: background-color 0.3s; + -webkit-transition: background-color 0.3s; + transition: background-color 0.3s; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; +} +body .ui-panelmenu .ui-panelmenu-content .ui-menuitem-link:hover { + background-color: #f4f3f4; + color: #373a3c; +} +body .ui-panelmenu .ui-panelmenu-content .ui-menuitem-link > span.fa { + display: inline-block; + vertical-align: middle; + left: auto; +} +body .ui-panelmenu .ui-panelmenu-content .ui-menuitem-link .ui-menuitem-text { + display: inline-block; + vertical-align: middle; +} +body .ui-progressbar { + border: 0 none; + background-color: #e3e3e3; +} +body .ui-progressbar .ui-progressbar-value { + border: 0 none; + background: #299bfd; + margin: 0; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; +} +body .ui-progressbar .ui-progressbar-label { + margin-top: -0.063em; +} +body .ui-galleria .ui-galleria-nav-prev { + font-size: 1em; + color: #767b7f; + -moz-transition: color 0.3s; + -o-transition: color 0.3s; + -webkit-transition: color 0.3s; + transition: color 0.3s; +} +body .ui-galleria .ui-galleria-nav-prev:hover { + color: #2d353c; +} +body .ui-galleria .ui-galleria-nav-next { + font-size: 1em; + color: #767b7f; + -moz-transition: color 0.3s; + -o-transition: color 0.3s; + -webkit-transition: color 0.3s; + transition: color 0.3s; +} +body .ui-galleria .ui-galleria-nav-next:hover { + color: #2d353c; +} + +body .ui-slidemenu .ui-slidemenu-backward { + border: 0 none; + background-color: #f5f5f5; + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +/* Validation */ +.ui-inputtext.ng-dirty.ng-invalid, +p-dropdown.ng-dirty.ng-invalid > .ui-dropdown, +p-autocomplete.ng-dirty.ng-invalid > .ui-autocomplete > .ui-inputtext, +p-calendar.ng-dirty.ng-invalid > .ui-inputtext, +p-chips.ng-dirty.ng-invalid > .ui-inputtext, +p-inputmask.ng-dirty.ng-invalid > .ui-inputtext, +p-checkbox.ng-dirty.ng-invalid .ui-chkbox-box, +p-radiobutton.ng-dirty.ng-invalid .ui-radiobutton-box, +p-inputswitch.ng-dirty.ng-invalid .ui-inputswitch, +p-listbox.ng-dirty.ng-invalid .ui-inputtext, +p-multiselect.ng-dirty.ng-invalid > .ui-multiselect, +p-spinner.ng-dirty.ng-invalid > .ui-inputtext, +p-selectbutton.ng-dirty.ng-invalid .ui-button, +p-togglebutton.ng-dirty.ng-invalid .ui-button { + border-bottom-color: #e13131; +} \ No newline at end of file diff --git a/src/assets/components/themes/cruze/theme.scss b/src/assets/components/themes/cruze/theme.scss new file mode 100644 index 00000000000..ce7740d106d --- /dev/null +++ b/src/assets/components/themes/cruze/theme.scss @@ -0,0 +1,56 @@ +$fontFamily: Segoe UI, Arial, sans-serif; +$fontSize: 1em; +$borderRadius: 3px; +$disabledOpacity: 0.35; + +//Header +$headerBorderWidth: 1px; +$headerBorderColor: #333333; +$headerBgColor: #333333; +$headerTextColor: #eeeeee; +$headerFontWeight: bold; +$headerIconTextColor: #eeeeee; + +//Content +$contentBorderWidth: 1px; +$contentBorderColor: #666666; +$contentBgColor: #575757; +$contentTextColor: #eeeeee; + +//Default State +$stateDefaultBorderWidth: 1px; +$stateDefaultBorderColor: #2e2e2e; +$stateDefaultBgColor: #3d3d3d; +$stateDefaultTextColor: #eeeeee; + +//Active State +$stateActiveBorderColor: #2e2e2e; +$stateActiveBgColor: #0099e0; +$stateActiveTextColor: #ffffff; + +//Highlight State +$stateHighlightBorderColor: #cccccc; +$stateHighlightBgColor: #eeeeee; +$stateHighlightTextColor: #0099e0; + +//Focus State +$stateFocusBorderColor: #2e2e2e; +$stateFocusBgColor: #474747; +$stateFocusTextColor: #ffffff; + +//Error State +$stateErrorBorderColor: #ffb73d; +$stateErrorBgColor: #ffc73d; +$stateErrorTextColor: #111111; + +//Hover State +$stateHoverBorderColor: #2e2e2e; +$stateHoverBgColor: #474747; +$stateHoverTextColor: #ffffff; + +//Forms +$inputBgColor: #ffffff; +$inputTextColor: #222222; +$invalidInputBorderColor: #ffb73d; + +@import '../_theme'; \ No newline at end of file diff --git a/src/assets/components/themes/cupertino/theme.scss b/src/assets/components/themes/cupertino/theme.scss new file mode 100644 index 00000000000..5f9f2213e0f --- /dev/null +++ b/src/assets/components/themes/cupertino/theme.scss @@ -0,0 +1,56 @@ +$fontFamily: Lucida Grande, Lucida Sans, Arial, sans-serif; +$fontSize: 1em; +$borderRadius: 6px; +$disabledOpacity: 0.35; + +//Header +$headerBorderWidth: 1px; +$headerBorderColor: #aed0ea; +$headerBgColor: #deedf7; +$headerTextColor: #222222; +$headerFontWeight: bold; +$headerIconTextColor: #222222; + +//Content +$contentBorderWidth: 1px; +$contentBorderColor: #dddddd; +$contentBgColor: #f2f5f7; +$contentTextColor: #362b36; + +//Default State +$stateDefaultBorderWidth: 1px; +$stateDefaultBorderColor: #aed0ea; +$stateDefaultBgColor: #d7ebf9; +$stateDefaultTextColor: #2779aa; + +//Active State +$stateActiveBorderColor: #2694e8; +$stateActiveBgColor: #3baae3; +$stateActiveTextColor: #ffffff; + +//Highlight State +$stateHighlightBorderColor: #f9dd34; +$stateHighlightBgColor: #ffef8f; +$stateHighlightTextColor: #363636; + +//Focus State +$stateFocusBorderColor: #74b2e2; +$stateFocusBgColor: #e4f1fb; +$stateFocusTextColor: #0070a3; + +//Error State +$stateErrorBorderColor: #cd0a0a; +$stateErrorBgColor: #cd0a0a; +$stateErrorTextColor: #ffffff; + +//Hover State +$stateHoverBorderColor: #74b2e2; +$stateHoverBgColor: #e4f1fb; +$stateHoverTextColor: #0070a3; + +//Forms +$inputBgColor: #ffffff; +$inputTextColor: #222222; +$invalidInputBorderColor: #cd0a0a; + +@import '../_theme'; \ No newline at end of file diff --git a/src/assets/components/themes/darkness/theme.scss b/src/assets/components/themes/darkness/theme.scss new file mode 100644 index 00000000000..9de738aaaa2 --- /dev/null +++ b/src/assets/components/themes/darkness/theme.scss @@ -0,0 +1,56 @@ +$fontFamily: Segoe UI, Arial, sans-serif; +$fontSize: 1em; +$borderRadius: 6px; +$disabledOpacity: 0.35; + +//Header +$headerBorderWidth: 1px; +$headerBorderColor: #323232; +$headerBgColor: #333333; +$headerTextColor: #cccccc; +$headerFontWeight: bold; +$headerIconTextColor: #cccccc; + +//Content +$contentBorderWidth: 1px; +$contentBorderColor: #323232; +$contentBgColor: #000000; +$contentTextColor: #cccccc; + +//Default State +$stateDefaultBorderWidth: 1px; +$stateDefaultBorderColor: #666666; +$stateDefaultBgColor: #555555; +$stateDefaultTextColor: #eeeeee; + +//Active State +$stateActiveBorderColor: #ffaf0f; +$stateActiveBgColor: #f58400; +$stateActiveTextColor: #ffffff; + +//Highlight State +$stateHighlightBorderColor: #cccccc; +$stateHighlightBgColor: #eeeeee; +$stateHighlightTextColor: #2e7db2; + +//Focus State +$stateFocusBorderColor: #59b4d4; +$stateFocusBgColor: #0078a3; +$stateFocusTextColor: #ffffff; + +//Error State +$stateErrorBorderColor: #ffb73d; +$stateErrorBgColor: #ffb73d; +$stateErrorTextColor: #111111; + +//Hover State +$stateHoverBorderColor: #59b4d4; +$stateHoverBgColor: #0078a3; +$stateHoverTextColor: #ffffff; + +//Forms +$inputBgColor: #ffffff; +$inputTextColor: #333333; +$invalidInputBorderColor: #ffb73d; + +@import '../_theme'; \ No newline at end of file diff --git a/src/assets/components/themes/flick/theme.scss b/src/assets/components/themes/flick/theme.scss new file mode 100644 index 00000000000..89339c9bb9b --- /dev/null +++ b/src/assets/components/themes/flick/theme.scss @@ -0,0 +1,56 @@ +$fontFamily: Helvetica, Arial, sans-serif; +$fontSize: 1em; +$borderRadius: 2px; +$disabledOpacity: 0.35; + +//Header +$headerBorderWidth: 1px; +$headerBorderColor: #dddddd; +$headerBgColor: #dddddd; +$headerTextColor: #444444; +$headerFontWeight: bold; +$headerIconTextColor: #444444; + +//Content +$contentBorderWidth: 1px; +$contentBorderColor: #dddddd; +$contentBgColor: #ffffff; +$contentTextColor: #444444; + +//Default State +$stateDefaultBorderWidth: 1px; +$stateDefaultBorderColor: #dddddd; +$stateDefaultBgColor: #f6f6f6; +$stateDefaultTextColor: #0073ea; + +//Active State +$stateActiveBorderColor: #dddddd; +$stateActiveBgColor: #ffffff; +$stateActiveTextColor: #ff0084; + +//Highlight State +$stateHighlightBorderColor: #FF0084; +$stateHighlightBgColor: #FF0084; +$stateHighlightTextColor: #FFFFFF; + +//Focus State +$stateFocusBorderColor: #0073ea; +$stateFocusBgColor: #0073ea; +$stateFocusTextColor: #ffffff; + +//Error State +$stateErrorBorderColor: #ff0084; +$stateErrorBgColor: #ffffff; +$stateErrorTextColor: #222222; + +//Hover State +$stateHoverBorderColor: #0073ea; +$stateHoverBgColor: #0073ea; +$stateHoverTextColor: #ffffff; + +//Forms +$inputBgColor: #ffffff; +$inputTextColor: #444444; +$invalidInputBorderColor: #ff0084; + +@import '../_theme'; \ No newline at end of file diff --git a/src/assets/components/themes/home/theme.scss b/src/assets/components/themes/home/theme.scss new file mode 100644 index 00000000000..9c2c8c7f1df --- /dev/null +++ b/src/assets/components/themes/home/theme.scss @@ -0,0 +1,56 @@ +$fontFamily: Verdana, Arial, sans-serif; +$fontSize: 1em; +$borderRadius: 4px; +$disabledOpacity: 0.35; + +//Header +$headerBorderWidth: 1px; +$headerBorderColor: #56585C; +$headerBgColor: #424548; +$headerTextColor: #F9F7F7; +$headerFontWeight: bold; +$headerIconTextColor: #F9F7F7; + +//Content +$contentBorderWidth: 1px; +$contentBorderColor: #cccccc; +$contentBgColor: #F2F1F1; +$contentTextColor: #222222; + +//Default State +$stateDefaultBorderWidth: 1px; +$stateDefaultBorderColor: #68727B; +$stateDefaultBgColor: #68727B; +$stateDefaultTextColor: #ffffff; + +//Active State +$stateActiveBorderColor: #506C8A; +$stateActiveBgColor: #365073; +$stateActiveTextColor: #ffffff; + +//Highlight State +$stateHighlightBorderColor: #ffde2e; +$stateHighlightBgColor: #ffeb80; +$stateHighlightTextColor: #363636; + +//Focus State +$stateFocusBorderColor: #68727B; +$stateFocusBgColor: #6580A1; +$stateFocusTextColor: #ffffff; + +//Error State +$stateErrorBorderColor: #9e0505; +$stateErrorBgColor: #cd0a0a; +$stateErrorTextColor: #ffffff; + +//Hover State +$stateHoverBorderColor: #68727B; +$stateHoverBgColor: #6580A1; +$stateHoverTextColor: #ffffff; + +//Forms +$inputBgColor: #ffffff; +$inputTextColor: #222222; +$invalidInputBorderColor: #ff0084; + +@import '../_theme'; \ No newline at end of file diff --git a/src/assets/components/themes/kasper/theme.scss b/src/assets/components/themes/kasper/theme.scss new file mode 100644 index 00000000000..7435b26bbee --- /dev/null +++ b/src/assets/components/themes/kasper/theme.scss @@ -0,0 +1,56 @@ +$fontFamily: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Segoe UI Symbol"; +$fontSize: 1em; +$borderRadius: 3px; +$disabledOpacity: 0.35; + +//Header +$headerBorderWidth: 1px; +$headerBorderColor: #758aa0; +$headerBgColor: #758aa0; +$headerTextColor: #ffffff; +$headerFontWeight: 500; +$headerIconTextColor: #ffffff; + +//Content +$contentBorderWidth: 1px; +$contentBorderColor: #d1d7dc; +$contentBgColor: #eef1f4; +$contentTextColor: #414550; + +//Default State +$stateDefaultBorderWidth: 1px; +$stateDefaultBorderColor: #d1d7dc; +$stateDefaultBgColor: #374c61; +$stateDefaultTextColor: #ffffff; + +//Active State +$stateActiveBorderColor: #5a92d1; +$stateActiveBgColor: #5a92d1; +$stateActiveTextColor: #ffffff; + +//Highlight State +$stateHighlightBorderColor: #5a92d1; +$stateHighlightBgColor: #5a92d1; +$stateHighlightTextColor: #ffffff; + +//Focus State +$stateFocusBorderColor: #5a92d1; +$stateFocusBgColor: #5a92d1; +$stateFocusTextColor: #081c22; + +//Error State +$stateErrorBorderColor: #ec4e4e; +$stateErrorBgColor: #ec4e4e; +$stateErrorTextColor: #ffffff; + +//Hover State +$stateHoverBorderColor: #d1d7dc; +$stateHoverBgColor: #eef1f4; +$stateHoverTextColor: #374c61; + +//Forms +$inputBgColor: #ffffff; +$inputTextColor: #333333; +$invalidInputBorderColor: #ec4e4e; + +@import '../_theme'; \ No newline at end of file diff --git a/src/assets/components/themes/lightness/theme.scss b/src/assets/components/themes/lightness/theme.scss new file mode 100644 index 00000000000..96ab1a192e2 --- /dev/null +++ b/src/assets/components/themes/lightness/theme.scss @@ -0,0 +1,56 @@ +$fontFamily: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; +$fontSize: 1em; +$borderRadius: 4px; +$disabledOpacity: 0.35; + +//Header +$headerBorderWidth: 1px; +$headerBorderColor: #e78f08; +$headerBgColor: #f6a828; +$headerTextColor: #ffffff; +$headerFontWeight: bold; +$headerIconTextColor: #ffffff; + +//Content +$contentBorderWidth: 1px; +$contentBorderColor: #dddddd; +$contentBgColor: #eeeeee; +$contentTextColor: #333333; + +//Default State +$stateDefaultBorderWidth: 1px; +$stateDefaultBorderColor: #cccccc; +$stateDefaultBgColor: #f6f6f6; +$stateDefaultTextColor: #1c94c4; + +//Active State +$stateActiveBorderColor: #fbd850; +$stateActiveBgColor: #ffffff; +$stateActiveTextColor: #eb8f00; + +//Highlight State +$stateHighlightBorderColor: #fed22f; +$stateHighlightBgColor: #ffe45c; +$stateHighlightTextColor: #363636; + +//Focus State +$stateFocusBorderColor: #fbcb09; +$stateFocusBgColor: #fdf5ce; +$stateFocusTextColor: #c77405; + +//Error State +$stateErrorBorderColor: #cd0a0a; +$stateErrorBgColor: #b81900; +$stateErrorTextColor: #ffffff; + +//Hover State +$stateHoverBorderColor: #fbcb09; +$stateHoverBgColor: #fdf5ce; +$stateHoverTextColor: #c77405; + +//Forms +$inputBgColor: #ffffff; +$inputTextColor: #333333; +$invalidInputBorderColor: #cd0a0a; + +@import '../_theme'; \ No newline at end of file diff --git a/src/assets/components/themes/ludvig/theme.scss b/src/assets/components/themes/ludvig/theme.scss new file mode 100644 index 00000000000..e8ec6d72945 --- /dev/null +++ b/src/assets/components/themes/ludvig/theme.scss @@ -0,0 +1,56 @@ +$fontFamily: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Segoe UI Symbol"; +$fontSize: 1em; +$borderRadius: 2px; +$disabledOpacity: 0.35; + +//Header +$headerBorderWidth: 1px; +$headerBorderColor: #2790b0; +$headerBgColor: #2790b0; +$headerTextColor: #ffffff; +$headerFontWeight: 500; +$headerIconTextColor: #ffffff; + +//Content +$contentBorderWidth: 1px; +$contentBorderColor: #d4d4d4; +$contentBgColor: #fafafa; +$contentTextColor: #081c22; + +//Default State +$stateDefaultBorderWidth: 1px; +$stateDefaultBorderColor: #d4d4d4; +$stateDefaultBgColor: #fafafa; +$stateDefaultTextColor: #081c22; + +//Active State +$stateActiveBorderColor: #b8ccd2; +$stateActiveBgColor: #cad7dc; +$stateActiveTextColor: #081c22; + +//Highlight State +$stateHighlightBorderColor: #eecc00; +$stateHighlightBgColor: #eecc00; +$stateHighlightTextColor: #081c22; + +//Focus State +$stateFocusBorderColor: #eecc00; +$stateFocusBgColor: #eecc00; +$stateFocusTextColor: #081c22; + +//Error State +$stateErrorBorderColor: #ec4e4e; +$stateErrorBgColor: #ec4e4e; +$stateErrorTextColor: #ffffff; + +//Hover State +$stateHoverBorderColor: #d4d4d4; +$stateHoverBgColor: #eaeaea; +$stateHoverTextColor: #081c22; + +//Forms +$inputBgColor: #ffffff; +$inputTextColor: #333333; +$invalidInputBorderColor: #ec4e4e; + +@import '../_theme'; \ No newline at end of file diff --git a/src/assets/components/themes/omega/fonts/roboto-v15-latin-regular.eot b/src/assets/components/themes/omega/fonts/roboto-v15-latin-regular.eot new file mode 100644 index 00000000000..d26bc8f519b Binary files /dev/null and b/src/assets/components/themes/omega/fonts/roboto-v15-latin-regular.eot differ diff --git a/src/assets/components/themes/omega/fonts/roboto-v15-latin-regular.svg b/src/assets/components/themes/omega/fonts/roboto-v15-latin-regular.svg new file mode 100644 index 00000000000..ed55c105d7a --- /dev/null +++ b/src/assets/components/themes/omega/fonts/roboto-v15-latin-regular.svg @@ -0,0 +1,308 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/components/themes/omega/fonts/roboto-v15-latin-regular.ttf b/src/assets/components/themes/omega/fonts/roboto-v15-latin-regular.ttf new file mode 100644 index 00000000000..7b25f3ce940 Binary files /dev/null and b/src/assets/components/themes/omega/fonts/roboto-v15-latin-regular.ttf differ diff --git a/src/assets/components/themes/omega/fonts/roboto-v15-latin-regular.woff b/src/assets/components/themes/omega/fonts/roboto-v15-latin-regular.woff new file mode 100644 index 00000000000..941dfa4bae8 Binary files /dev/null and b/src/assets/components/themes/omega/fonts/roboto-v15-latin-regular.woff differ diff --git a/src/assets/components/themes/omega/fonts/roboto-v15-latin-regular.woff2 b/src/assets/components/themes/omega/fonts/roboto-v15-latin-regular.woff2 new file mode 100644 index 00000000000..120796bb719 Binary files /dev/null and b/src/assets/components/themes/omega/fonts/roboto-v15-latin-regular.woff2 differ diff --git a/src/assets/components/themes/omega/images/icons_16.png b/src/assets/components/themes/omega/images/icons_16.png new file mode 100644 index 00000000000..09d6ec7f840 Binary files /dev/null and b/src/assets/components/themes/omega/images/icons_16.png differ diff --git a/src/assets/components/themes/omega/images/slider_handles.png b/src/assets/components/themes/omega/images/slider_handles.png new file mode 100644 index 00000000000..0fddde5fe86 Binary files /dev/null and b/src/assets/components/themes/omega/images/slider_handles.png differ diff --git a/src/assets/components/themes/omega/images/slider_handles@2x.png b/src/assets/components/themes/omega/images/slider_handles@2x.png new file mode 100644 index 00000000000..d8c901ec80c Binary files /dev/null and b/src/assets/components/themes/omega/images/slider_handles@2x.png differ diff --git a/src/assets/components/themes/omega/images/ui-bg_flat_0_aaaaaa_40x100.png b/src/assets/components/themes/omega/images/ui-bg_flat_0_aaaaaa_40x100.png new file mode 100644 index 00000000000..5b5dab2ab7b Binary files /dev/null and b/src/assets/components/themes/omega/images/ui-bg_flat_0_aaaaaa_40x100.png differ diff --git a/src/assets/components/themes/omega/images/ui-bg_flat_75_ffffff_40x100.png b/src/assets/components/themes/omega/images/ui-bg_flat_75_ffffff_40x100.png new file mode 100644 index 00000000000..ac8b229af95 Binary files /dev/null and b/src/assets/components/themes/omega/images/ui-bg_flat_75_ffffff_40x100.png differ diff --git a/src/assets/components/themes/omega/images/ui-bg_glass_55_fbf9ee_1x400.png b/src/assets/components/themes/omega/images/ui-bg_glass_55_fbf9ee_1x400.png new file mode 100644 index 00000000000..ad3d6346e00 Binary files /dev/null and b/src/assets/components/themes/omega/images/ui-bg_glass_55_fbf9ee_1x400.png differ diff --git a/src/assets/components/themes/omega/images/ui-bg_glass_65_ffffff_1x400.png b/src/assets/components/themes/omega/images/ui-bg_glass_65_ffffff_1x400.png new file mode 100644 index 00000000000..42ccba269b6 Binary files /dev/null and b/src/assets/components/themes/omega/images/ui-bg_glass_65_ffffff_1x400.png differ diff --git a/src/assets/components/themes/omega/images/ui-bg_glass_75_dadada_1x400.png b/src/assets/components/themes/omega/images/ui-bg_glass_75_dadada_1x400.png new file mode 100644 index 00000000000..5a46b47cb16 Binary files /dev/null and b/src/assets/components/themes/omega/images/ui-bg_glass_75_dadada_1x400.png differ diff --git a/src/assets/components/themes/omega/images/ui-bg_glass_75_e6e6e6_1x400.png b/src/assets/components/themes/omega/images/ui-bg_glass_75_e6e6e6_1x400.png new file mode 100644 index 00000000000..86c2baa655e Binary files /dev/null and b/src/assets/components/themes/omega/images/ui-bg_glass_75_e6e6e6_1x400.png differ diff --git a/src/assets/components/themes/omega/images/ui-bg_glass_95_fef1ec_1x400.png b/src/assets/components/themes/omega/images/ui-bg_glass_95_fef1ec_1x400.png new file mode 100644 index 00000000000..4443fdc1a15 Binary files /dev/null and b/src/assets/components/themes/omega/images/ui-bg_glass_95_fef1ec_1x400.png differ diff --git a/src/assets/components/themes/omega/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/src/assets/components/themes/omega/images/ui-bg_highlight-soft_75_cccccc_1x100.png new file mode 100644 index 00000000000..7c9fa6c6edc Binary files /dev/null and b/src/assets/components/themes/omega/images/ui-bg_highlight-soft_75_cccccc_1x100.png differ diff --git a/src/assets/components/themes/omega/images/ui-icons_222222_256x240.png b/src/assets/components/themes/omega/images/ui-icons_222222_256x240.png new file mode 100644 index 00000000000..b273ff111d2 Binary files /dev/null and b/src/assets/components/themes/omega/images/ui-icons_222222_256x240.png differ diff --git a/src/assets/components/themes/omega/images/ui-icons_2e83ff_256x240.png b/src/assets/components/themes/omega/images/ui-icons_2e83ff_256x240.png new file mode 100644 index 00000000000..84defe6e8ab Binary files /dev/null and b/src/assets/components/themes/omega/images/ui-icons_2e83ff_256x240.png differ diff --git a/src/assets/components/themes/omega/images/ui-icons_454545_256x240.png b/src/assets/components/themes/omega/images/ui-icons_454545_256x240.png new file mode 100644 index 00000000000..59bd45b907c Binary files /dev/null and b/src/assets/components/themes/omega/images/ui-icons_454545_256x240.png differ diff --git a/src/assets/components/themes/omega/images/ui-icons_cd0a0a_256x240.png b/src/assets/components/themes/omega/images/ui-icons_cd0a0a_256x240.png new file mode 100644 index 00000000000..2ab019b73ec Binary files /dev/null and b/src/assets/components/themes/omega/images/ui-icons_cd0a0a_256x240.png differ diff --git a/src/assets/components/themes/omega/images/ui-icons_ffffff_256x240.png b/src/assets/components/themes/omega/images/ui-icons_ffffff_256x240.png new file mode 100644 index 00000000000..42f8f992c72 Binary files /dev/null and b/src/assets/components/themes/omega/images/ui-icons_ffffff_256x240.png differ diff --git a/src/assets/components/themes/omega/theme.scss b/src/assets/components/themes/omega/theme.scss new file mode 100644 index 00000000000..980963a000d --- /dev/null +++ b/src/assets/components/themes/omega/theme.scss @@ -0,0 +1,542 @@ +$fontFamily: "Roboto", "Trebuchet MS", Arial, Helvetica, sans-serif; +$fontSize: 1em; +$borderRadius: 3px; +$disabledOpacity: 0.35; + +//Header +$headerBorderWidth: 1px; +$headerBorderColor: #d9d9d9; +$headerBgColor: #f6f7f9; +$headerTextColor: #1b1d1f; +$headerFontWeight: normal; +$headerIconTextColor: #1b1d1f; + +//Content +$contentBorderWidth: 1px; +$contentBorderColor: #D5D5D5; +$contentBgColor: #ffffff; +$contentTextColor: #222222; + +//Default State +$stateDefaultBorderWidth: 1px; +$stateDefaultBorderColor: #d6d6d6; +$stateDefaultBgColor: #ffffff; +$stateDefaultTextColor: #555555; + +//Active State +$stateActiveBorderColor: #bebebe; +$stateActiveBgColor: #d6d6d6; +$stateActiveTextColor: #212121; + +//Highlight State +$stateHighlightBorderColor: #156090; +$stateHighlightBgColor: #186ba0; +$stateHighlightTextColor: #FFFFFF; + +//Focus State +$stateFocusBorderColor: #c0c0c0; +$stateFocusBgColor: #eeeeee; +$stateFocusTextColor: #212121; + +//Error State +$stateErrorBorderColor: #f44336; +$stateErrorBgColor: #f5554a; +$stateErrorTextColor: #cd0a0a; + +//Hover State +$stateHoverBorderColor: #c0c0c0; +$stateHoverBgColor: #eeeeee; +$stateHoverTextColor: #212121; + +//Forms +$inputBgColor: #ffffff; +$inputTextColor: #222222; +$invalidInputBorderColor: #f44336; + +@import '../_theme'; + +/* roboto-regular - latin */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + src: url('fonts/roboto-v15-latin-regular.eot'); /* IE9 Compat Modes */ + src: local('Roboto'), local('Roboto-Regular'), + url('fonts/roboto-v15-latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('fonts/roboto-v15-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */ + url('fonts/roboto-v15-latin-regular.woff') format('woff'), /* Modern Browsers */ + url('fonts/roboto-v15-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */ + url('fonts/roboto-v15-latin-regular.svg#Roboto') format('svg'); /* Legacy iOS */ +} + +.ui-widget-header { + background: #f6f7f9 0 0 repeat-x; /* Old browsers */ + background: -moz-linear-gradient(top, #f6f7f9 0%, #ebedf0 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f6f7f9), color-stop(100%,#ebedf0)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #f6f7f9 0%,#ebedf0 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #f6f7f9 0%,#ebedf0 100%); /* Opera11.10+ */ + background: -ms-linear-gradient(top, #f6f7f9 0%,#ebedf0 100%); /* IE10+ */ + background: linear-gradient(to bottom, #f6f7f9 0%,#ebedf0 100%); /* W3C */ +} + +.ui-accordion { + .ui-accordion-header { + background: $headerBgColor; + border-top: 1px solid $headerBorderColor; + + a { + color: $headerTextColor; + } + + &:not(.ui-state-active):not(.ui-state-disabled):hover { + background: #ededf0; + } + + &.ui-state-active { + background: #ffffff; + border-left-color: transparent; + border-right-color: transparent; + border-bottom-color: transparent; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; + } + } + + .ui-accordion-content { + border: 0 none; + } +} + +/* Tabview */ +.ui-tabview { + &.ui-widget-content { + border: 0 none; + } + + .ui-tabview-nav { + background: transparent; + + > li { + &.ui-state-default { + background: #f6f7f9; + } + + &.ui-state-active { + background: #ffffff; + font-weight: normal; + color: #555555; + } + + &:not(.ui-state-active):not(.ui-state-disabled):hover { + background: #ededf0; + } + } + } +} + +/* Spinner */ +.ui-spinner:not(.ui-state-disabled) .ui-spinner-button:enabled:hover { + border: 1px solid #1f89ce; + background: #1f89ce; + outline: 0 none; + color: #ffffff; +} + +.ui-spinner:not(.ui-state-disabled) .ui-spinner-button:enabled:active { + border: 1px solid #156090; + background: #186ba0; + color: #ffffff, +} + +.ui-slider { position: relative; text-align: left; background: #838688; border: none; -webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.6) inset; -moz-box-shadow: 0 1px 3px rgba(0,0,0,0.6) inset; box-shadow: 0 1px 3px rgba(0,0,0,0.6) inset;} +.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 17px !important; height: 21px !important; cursor: default; background: url("images/slider_handles.png") 0 0 no-repeat; outline: none; -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; border: none; } +.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background: #14a4ff; -webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.6) inset; -moz-box-shadow: 0 1px 3px rgba(0,0,0,0.6) inset; box-shadow: 0 1px 3px rgba(0,0,0,0.6) inset; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; } +.ui-slider .ui-slider-handle.ui-state-active { background-position: -17px 0; } + +.ui-slider-horizontal { height: 6px; } +.ui-slider-horizontal .ui-slider-handle { top: -2px !important; margin-left: -.6em; } +.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } +.ui-slider-horizontal .ui-slider-range-min { left: 0; } +.ui-slider-horizontal .ui-slider-range-max { right: 0; } + +.ui-slider-vertical { width: .8em; height: 100px; } +.ui-slider-vertical .ui-slider-handle { left: -.1em !important; margin-left: 0; margin-bottom: -.6em; } +.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } +.ui-slider-vertical .ui-slider-range-min { bottom: 0; } +.ui-slider-vertical .ui-slider-range-max { top: 0; } + +.ui-progressbar .ui-progressbar-value { + border: 1px solid #3f94e9; + background: #8ec5fc; +} + +.ui-progressbar .ui-progressbar-label { + color: #222222; +} + +.ui-widget-header .ui-button, +.ui-widget-content .ui-button, +.ui-button { + border: 1px solid #2399e5; + color: #FFFFFF; + background: #2399e5; + -webkit-transition: background-color .2s; + -moz-transition: background-color .2s; + transition: background-color .2s; + + &:enabled:hover, + &:focus { + border: 1px solid #1f89ce; + background: #1f89ce; + outline: 0 none; + color: #ffffff; + } + + &:enabled:active { + border: 1px solid #156090; + background: #186ba0; + color: #ffffff, + } +} + +/* Checkbox and Radio */ +.ui-chkbox-box.ui-state-active, +.ui-radiobutton-box.ui-state-active { + border: 1px solid #156090; + background: #186ba0; + color: #FFFFFF; +} + +.ui-chkbox-box.ui-state-focus, +.ui-radiobutton-box.ui-state-focus { + -moz-box-shadow: 0px 0px 5px #1f89ce; + -webkit-box-shadow: 0px 0px 5px #1f89ce; + box-shadow: 0px 0px 5px #1f89ce; +} + +.ui-chkbox-box.ui-state-focus.ui-state-active { + background: #186ba0; +} + +/* Inputs */ +.ui-inputtext { + background: #ffffff; + color: #222222; + -webkit-transition: .2s; + -moz-transition: .2s; + transition: .2s; +} + +.ui-inputtext.ui-state-focus, +.ui-inputtext:focus { + -moz-box-shadow: 0px 0px 5px #1f89ce; + -webkit-box-shadow: 0px 0px 5px #1f89ce; + box-shadow: 0px 0px 5px #1f89ce; +} + +/* InputSwitch */ +.ui-inputswitch-on { + background: #186ba0 !important; + color: #ffffff !important; +} + +.ui-paginator .ui-paginator-page.ui-state-active { + background: #186ba0; + color: #ffffff; + border-color: #156090; +} + +/* DataTable */ +.ui-datatable { + th { + &.ui-state-default { + background: #ebedf0; + border-color: #d9d9d9; + } + + &.ui-sortable-column:not(.ui-state-active):hover { + background: #d3d5d8; + border-color: #d9d9d9; + } + + &.ui-state-active { + background: #186ba0; + color: #ffffff; + } + } + + tbody { + > tr.ui-widget-content { + border-color: #d9d9d9; + + &.ui-datatable-odd { + background-color: #fafafb; + } + + &.ui-state-highlight { + background-color: $stateHighlightBgColor; + color: $stateHighlightTextColor; + } + } + } + + tfoot { + td { + &.ui-state-default { + background: #ebedf0; + border-color: #d9d9d9; + } + } + } +} + +/* Panel */ +.ui-panel.ui-widget { + padding: 0; + + .ui-panel-titlebar.ui-corner-all { + -moz-border-radius-bottom-left: 0; + -webkit-border-bottom-left-radius: 0; + border-bottom-left-radius: 0; + -moz-border-radius-bottom-right: 0; + -webkit-border-bottom-right-radius: 0; + border-bottom-right-radius: 0; + } + + .ui-panel-titlebar { + border-width: 0 0 1px 0; + } + + .ui-panel-titlebar-icon span { + position: relative; + top: 1px; + } + +} + +/* TreeTable */ +.ui-treetable { + th.ui-state-default { + background: #ebedf0; + border-color: #d9d9d9; + } +} + +/* ButtonSet */ +.ui-togglebutton.ui-button.ui-state-default, +.ui-selectbutton .ui-button.ui-state-default { + border: 1px solid #d6d6d6; + background: #ffffff; + font-weight: normal; + color: #555555; +} + +.ui-togglebutton.ui-button.ui-state-hover,.ui-togglebutton.ui-button.ui-state-focus, +.ui-selectbutton .ui-button.ui-state-hover,.ui-selectbutton .ui-button.ui-state-focus { + border: 1px solid #c0c0c0; + background: #eeeeee; + font-weight: normal; + color: #212121; +} + +.ui-togglebutton.ui-button.ui-state-focus, +.ui-selectbutton .ui-button.ui-state-focus.ui-state-active { + -moz-box-shadow: 0px 0px 5px #1f89ce; + -webkit-box-shadow: 0px 0px 5px #1f89ce; + box-shadow: 0px 0px 5px #1f89ce; +} + +.ui-togglebutton.ui-button.ui-state-active, +.ui-selectbutton .ui-button.ui-state-active { + border: 1px solid #156090; + background: #186ba0; + color: #FFFFFF; +} + +.ui-multiselect { + .ui-multiselect-label { + background-color: #ffffff; + } +} + +.ui-dropdown.ui-state-focus, .ui-multiselect.ui-state-focus { + -moz-box-shadow: 0px 0px 5px #1f89ce; + -webkit-box-shadow: 0px 0px 5px #1f89ce; + box-shadow: 0px 0px 5px #1f89ce; +} + +/* Growl */ +.ui-growl-item-container.ui-state-highlight { + &.ui-growl-message-info { + background-color: #2196f3; + border-color :#2196f3; + } + + &.ui-growl-message-error { + background-color: #f44336; + border-color :#f44336; + } + + &.ui-growl-message-warn { + background-color: #FFB300; + border-color :#FFB300; + } + + &.ui-growl-message-success { + background-color: #4CAF50; + border-color :#4CAF50; + } +} + +/* TabMenu */ +.ui-tabmenu { + border: 0 none; + + .ui-tabmenu-nav { + background: none; + + > li { + &.ui-state-default { + background: #f6f7f9; + } + + &.ui-state-active { + background: #ffffff; + font-weight: normal; + color: #555555; + } + + &:not(.ui-state-active):not(.ui-state-disabled):hover { + background: #ededf0; + } + } + } +} + +/* Menus */ +.ui-menu, +.ui-menu .ui-menu-child { + border: 1px solid #d9d9d9; + color: #1b1d1f; + background: #f6f7f9 0 0 repeat-x; /* Old browsers */ + background: -moz-linear-gradient(top, #f6f7f9 0%, #ebedf0 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f6f7f9), color-stop(100%,#ebedf0)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #f6f7f9 0%,#ebedf0 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #f6f7f9 0%,#ebedf0 100%); /* Opera11.10+ */ + background: -ms-linear-gradient(top, #f6f7f9 0%,#ebedf0 100%); /* IE10+ */ + background: linear-gradient(to bottom, #f6f7f9 0%,#ebedf0 100%); /* W3C */ +} + +.ui-menu { + .ui-menuitem { + .ui-menuitem-link { + &:hover { + background-color: #a6a6a6; + color: #ffffff; + } + } + + &.ui-menuitem-active { + > .ui-menuitem-link { + background-color: #a6a6a6; + color: #ffffff; + } + } + } +} + +/* PanelMenu */ +.ui-panelmenu .ui-panelmenu-header.ui-state-active, +.ui-panelmenu .ui-panelmenu-header.ui-state-active a { + border-color: #156090; + background: #186ba0; + color: #FFFFFF; +} + +/* DatePicker */ +.ui-datepicker.ui-widget { + padding: 0; + + .ui-datepicker-header { + -webkit-border-radius: 0px; + -moz-border-radius: 0px; + border-radius: 0px; + border-top: 0 none; + border-left: 0 none; + border-right: 0 none; + + a { + &:hover { + border-width: 1px; + } + } + } + + .ui-datepicker-calendar { + margin: 0; + + thead th { + background-color: #f6f8fa; + padding: 8px; + } + + td { + border-bottom: 1px solid rgba(213, 213, 213, 0.5); + padding: 0; + + a { + border: 0 none; + text-align: center; + padding: 8px; + + &.ui-state-highlight { + background-color: #d6d6d6; + color: #212121; + } + + &.ui-state-active { + background-color: #186ba0; + color: #ffffff; + } + } + } + + tr:last-child td { + border-bottom: 0 none; + } + } + + .ui-timepicker { + border-bottom: 0 none; + border-left: 0 none; + border-right: 0 none; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; + } + + &.ui-datepicker-timeonly { + .ui-timepicker { + border-top: 0 none; + } + } +} + +/* Steps */ +.ui-steps .ui-steps-item.ui-state-highlight .ui-menuitem-link { + color: #ffffff; +} + +/* Dialog */ +.ui-dialog.ui-widget .ui-dialog-titlebar { + padding: 1em 1.5em; +} + +.ui-dialog.ui-widget .ui-dialog-titlebar .ui-dialog-title { + font-size: 1.25em; +} + +.ui-dialog.ui-widget .ui-dialog-content { + padding: 1em 1.5em; +} diff --git a/src/assets/components/themes/pepper-grinder/theme.scss b/src/assets/components/themes/pepper-grinder/theme.scss new file mode 100644 index 00000000000..987d4493208 --- /dev/null +++ b/src/assets/components/themes/pepper-grinder/theme.scss @@ -0,0 +1,56 @@ +$fontFamily: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; +$fontSize: 1em; +$borderRadius: 6px; +$disabledOpacity: 0.35; + +//Header +$headerBorderWidth: 1px; +$headerBorderColor: #d4d1bf; +$headerBgColor: #ffffff; +$headerTextColor: #453821; +$headerFontWeight: bold; +$headerIconTextColor: #453821; + +//Content +$contentBorderWidth: 1px; +$contentBorderColor: #d9d6c4; +$contentBgColor: #eceadf; +$contentTextColor: #1f1f1f; + +//Default State +$stateDefaultBorderWidth: 1px; +$stateDefaultBorderColor: #cbc7bd; +$stateDefaultBgColor: #f8f7f6; +$stateDefaultTextColor: #654b24; + +//Active State +$stateActiveBorderColor: #d9d6c4; +$stateActiveBgColor: #eceadf; +$stateActiveTextColor: #140f06; + +//Highlight State +$stateHighlightBorderColor: #654b24; +$stateHighlightBgColor: #654b24; +$stateHighlightTextColor: #ffffff; + +//Focus State +$stateFocusBorderColor: #b2a266; +$stateFocusBgColor: #f7f3de; +$stateFocusTextColor: #3a3427; + +//Error State +$stateErrorBorderColor: #681818; +$stateErrorBgColor: #b83400; +$stateErrorTextColor: #ffffff; + +//Hover State +$stateHoverBorderColor: #b2a266; +$stateHoverBgColor: #f7f3de; +$stateHoverTextColor: #3a3427; + +//Forms +$inputBgColor: #ffffff; +$inputTextColor: #222222; +$invalidInputBorderColor: #681818; + +@import '../_theme'; \ No newline at end of file diff --git a/src/assets/components/themes/redmond/theme.scss b/src/assets/components/themes/redmond/theme.scss new file mode 100644 index 00000000000..043d9f9f9f7 --- /dev/null +++ b/src/assets/components/themes/redmond/theme.scss @@ -0,0 +1,56 @@ +$fontFamily: Lucida Grande, Lucida Sans, Arial, sans-serif; +$fontSize: 1em; +$borderRadius: 5px; +$disabledOpacity: 0.35; + +//Header +$headerBorderWidth: 1px; +$headerBorderColor: #4297d7; +$headerBgColor: #5c9ccc; +$headerTextColor: #ffffff; +$headerFontWeight: bold; +$headerIconTextColor: #ffffff; + +//Content +$contentBorderWidth: 1px; +$contentBorderColor: #a6c9e2; +$contentBgColor: #fcfdfd; +$contentTextColor: #222222; + +//Default State +$stateDefaultBorderWidth: 1px; +$stateDefaultBorderColor: #c5dbec; +$stateDefaultBgColor: #dfeffc; +$stateDefaultTextColor: #2e6e9e; + +//Active State +$stateActiveBorderColor: #79b7e7; +$stateActiveBgColor: #f5f8f9; +$stateActiveTextColor: #e17009; + +//Highlight State +$stateHighlightBorderColor: #fad42e; +$stateHighlightBgColor: #fbec88; +$stateHighlightTextColor: #363636; + +//Highlight State +$stateFocusBorderColor: #79b7e7; +$stateFocusBgColor: #d0e5f5; +$stateFocusTextColor: #1d5987; + +//Error State +$stateErrorBorderColor: #cd0a0a; +$stateErrorBgColor: #fef1ec; +$stateErrorTextColor: #cd0a0a; + +//Hover State +$stateHoverBorderColor: #79b7e7; +$stateHoverBgColor: #d0e5f5; +$stateHoverTextColor: #1d5987; + +//Forms +$inputBgColor: #ffffff; +$inputTextColor: #2E6E9E; +$invalidInputBorderColor: #cd0a0a; + +@import '../_theme'; \ No newline at end of file diff --git a/src/assets/components/themes/rocket/theme.scss b/src/assets/components/themes/rocket/theme.scss new file mode 100644 index 00000000000..7fbc96255c4 --- /dev/null +++ b/src/assets/components/themes/rocket/theme.scss @@ -0,0 +1,56 @@ +$fontFamily: Arial, Helvetica, sans-serif; +$fontSize: 1em; +$borderRadius: 4px; +$disabledOpacity: 0.35; + +//Header +$headerBorderWidth: 1px; +$headerBorderColor: #404040; +$headerBgColor: #242122; +$headerTextColor: #f4f4f9; +$headerFontWeight: bold; +$headerIconTextColor: #f4f4f9; + +//Content +$contentBorderWidth: 1px; +$contentBorderColor: #e3e3e3; +$contentBgColor: #f1f1f1; +$contentTextColor: #404040; + +//Default State +$stateDefaultBorderWidth: 1px; +$stateDefaultBorderColor: #404040; +$stateDefaultBgColor: #242122; +$stateDefaultTextColor: #fafafa; + +//Active State +$stateActiveBorderColor: #9dc939; +$stateActiveBgColor: #9dc939; +$stateActiveTextColor: #304915; + +//Highlight State +$stateHighlightBorderColor: #723c9b; +$stateHighlightBgColor: #65358a; +$stateHighlightTextColor: #ffffff; + +//Focus State +$stateFocusBorderColor: #00a6dd; +$stateFocusBgColor: #00a6dd; +$stateFocusTextColor: #fafafa; + +//Error State +$stateErrorBorderColor: #ca3838; +$stateErrorBgColor: #ca3838; +$stateErrorTextColor: #ff8f8f; + +//Hover State +$stateHoverBorderColor: #00a6dd; +$stateHoverBgColor: #00a6dd; +$stateHoverTextColor: #fafafa; + +//Forms +$inputBgColor: #ffffff; +$inputTextColor: #304915; +$invalidInputBorderColor: #ca3838; + +@import '../_theme'; \ No newline at end of file diff --git a/src/assets/components/themes/south-street/theme.scss b/src/assets/components/themes/south-street/theme.scss new file mode 100644 index 00000000000..0268fc92f05 --- /dev/null +++ b/src/assets/components/themes/south-street/theme.scss @@ -0,0 +1,56 @@ +$fontFamily: segoe ui, Arial, sans-serif; +$fontSize: 1em; +$borderRadius: 6px; +$disabledOpacity: 0.35; + +//Header +$headerBorderWidth: 1px; +$headerBorderColor: #d4ccb0; +$headerBgColor: #ece8da; +$headerTextColor: #433f38; +$headerFontWeight: bold; +$headerIconTextColor: #433f38; + +//Content +$contentBorderWidth: 1px; +$contentBorderColor: #dfd9c3; +$contentBgColor: #f5f3e5; +$contentTextColor: #312e25; + +//Default State +$stateDefaultBorderWidth: 1px; +$stateDefaultBorderColor: #327e04; +$stateDefaultBgColor: #459e00; +$stateDefaultTextColor: #ffffff; + +//Active State +$stateActiveBorderColor: #d4ccb0; +$stateActiveBgColor: #fafaf4; +$stateActiveTextColor: #459e00; + +//Highlight State +$stateHighlightBorderColor: #327e04; +$stateHighlightBgColor: #67b021; +$stateHighlightTextColor: #ffffff; + +//Focus State +$stateFocusBorderColor: #e8e1b5; +$stateFocusBgColor: #bcb9ae; +$stateFocusTextColor: #363636; + +//Error State +$stateErrorBorderColor: #e3a345; +$stateErrorBgColor: #ffedad; +$stateErrorTextColor: #cd5c0a; + +//Hover State +$stateHoverBorderColor: #e8e1b5; +$stateHoverBgColor: #bcb9ae; +$stateHoverTextColor: #363636; + +//Forms +$inputBgColor: #ffffff; +$inputTextColor: #433f38; +$invalidInputBorderColor: #e3a345; + +@import '../_theme'; \ No newline at end of file diff --git a/src/assets/components/themes/start/theme.scss b/src/assets/components/themes/start/theme.scss new file mode 100644 index 00000000000..d4f7f208d5d --- /dev/null +++ b/src/assets/components/themes/start/theme.scss @@ -0,0 +1,56 @@ +$fontFamily: Verdana,Arial,sans-serif; +$fontSize: 1em; +$borderRadius: 5px; +$disabledOpacity: 0.35; + +//Header +$headerBorderWidth: 1px; +$headerBorderColor: #4297d7; +$headerBgColor: #2191c0; +$headerTextColor: #eaf5f7; +$headerFontWeight: bold; +$headerIconTextColor: #eaf5f7; + +//Content +$contentBorderWidth: 1px; +$contentBorderColor: #a6c9e2; +$contentBgColor: #fcfdfd; +$contentTextColor: #222222; + +//Default State +$stateDefaultBorderWidth: 1px; +$stateDefaultBorderColor: #77d5f7; +$stateDefaultBgColor: #0078ae; +$stateDefaultTextColor: #ffffff; + +//Active State +$stateActiveBorderColor: #acdd4a; +$stateActiveBgColor: #6eac2c; +$stateActiveTextColor: #ffffff; + +//Highlight State +$stateHighlightBorderColor: #fcd113; +$stateHighlightBgColor: #f8da4e; +$stateHighlightTextColor: #222222; + +//Focus State +$stateFocusBorderColor: #448dae; +$stateFocusBgColor: #79c9ec; +$stateFocusTextColor: #222222; + +//Error State +$stateErrorBorderColor: #cd0a0a; +$stateErrorBgColor: #e14f1c; +$stateErrorTextColor: #ffffff; + +//Hover State +$stateHoverBorderColor: #448dae; +$stateHoverBgColor: #79c9ec; +$stateHoverTextColor: #222222; + +//Forms +$inputBgColor: #ffffff; +$inputTextColor: #026890; +$invalidInputBorderColor: #cd0a0a; + +@import '../_theme'; \ No newline at end of file diff --git a/src/assets/components/themes/trontastic/theme.scss b/src/assets/components/themes/trontastic/theme.scss new file mode 100644 index 00000000000..1d5e58a5388 --- /dev/null +++ b/src/assets/components/themes/trontastic/theme.scss @@ -0,0 +1,56 @@ +$fontFamily: Segoe UI, Arial, sans-serif; +$fontSize: 1em; +$borderRadius: 6px; +$disabledOpacity: 0.35; + +//Header +$headerBorderWidth: 1px; +$headerBorderColor: #000000; +$headerBgColor: #9fda58; +$headerTextColor: #222222; +$headerFontWeight: bold; +$headerIconTextColor: #222222; + +//Content +$contentBorderWidth: 1px; +$contentBorderColor: #4a4a4a; +$contentBgColor: #000000; +$contentTextColor: #ffffff; + +//Default State +$stateDefaultBorderWidth: 1px; +$stateDefaultBorderColor: #4a4a4a; +$stateDefaultBgColor: #0a0a0a; +$stateDefaultTextColor: #b8ec79; + +//Active State +$stateActiveBorderColor: #696969; +$stateActiveBgColor: #4c4c4c; +$stateActiveTextColor: #ffffff; + +//Highlight State +$stateHighlightBorderColor: #8cce3b; +$stateHighlightBgColor: #f1fbe5; +$stateHighlightTextColor: #030303; + +//Focus State +$stateFocusBorderColor: #000000; +$stateFocusBgColor: #666666; +$stateFocusTextColor: #ffffff; + +//Error State +$stateErrorBorderColor: #f1ac88; +$stateErrorBgColor: #f6ecd5; +$stateErrorTextColor: #74736d; + +//Hover State +$stateHoverBorderColor: #000000; +$stateHoverBgColor: #666666; +$stateHoverTextColor: #ffffff; + +//Forms +$inputBgColor: #ffffff; +$inputTextColor: #000000; +$invalidInputBorderColor: #f1ac88; + +@import '../_theme'; \ No newline at end of file diff --git a/src/assets/components/themes/voclain/theme.scss b/src/assets/components/themes/voclain/theme.scss new file mode 100644 index 00000000000..06d6fe52745 --- /dev/null +++ b/src/assets/components/themes/voclain/theme.scss @@ -0,0 +1,56 @@ +$fontFamily: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Segoe UI Symbol"; +$fontSize: 1em; +$borderRadius: 4px; +$disabledOpacity: 0.35; + +//Header +$headerBorderWidth: 1px; +$headerBorderColor: #606d7b; +$headerBgColor: #606d7b; +$headerTextColor: #ffffff; +$headerFontWeight: 500; +$headerIconTextColor: #ffffff; + +//Content +$contentBorderWidth: 1px; +$contentBorderColor: #e2e5e8; +$contentBgColor: #eef1f4; +$contentTextColor: #414550; + +//Default State +$stateDefaultBorderWidth: 1px; +$stateDefaultBorderColor: #2c3e50; +$stateDefaultBgColor: #2c3e50; +$stateDefaultTextColor: #ffffff; + +//Active State +$stateActiveBorderColor: #c95864; +$stateActiveBgColor: #c95864; +$stateActiveTextColor: #ffffff; + +//Highlight State +$stateHighlightBorderColor: #c95864; +$stateHighlightBgColor: #c95864; +$stateHighlightTextColor: #ffffff; + +//Focus State +$stateFocusBorderColor: #606d7b; +$stateFocusBgColor: #606d7b; +$stateFocusTextColor: #081c22; + +//Error State +$stateErrorBorderColor: #ec4e4e; +$stateErrorBgColor: #ec4e4e; +$stateErrorTextColor: #ffffff; + +//Hover State +$stateHoverBorderColor: #485562; +$stateHoverBgColor: #485562; +$stateHoverTextColor: #ffffff; + +//Forms +$inputBgColor: #ffffff; +$inputTextColor: #333333; +$invalidInputBorderColor: #ec4e4e; + +@import '../_theme'; \ No newline at end of file diff --git a/src/assets/showcase/css/code.css b/src/assets/showcase/css/code.css new file mode 100644 index 00000000000..b8b6bb57642 --- /dev/null +++ b/src/assets/showcase/css/code.css @@ -0,0 +1,234 @@ +/* http://prismjs.com/download.html?themes=prism-coy&languages=markup+css+clike+javascript+typescript */ +/** + * prism.js Coy theme for JavaScript, CoffeeScript, CSS and HTML + * Based on https://github.com/tshedor/workshop-wp-theme (Example: http://workshop.kansan.com/category/sessions/basics or http://workshop.timshedor.com/category/sessions/basics); + * @author Tim Shedor + */ + +code[class*="language-"], +pre[class*="language-"] { + color: black; + background: none; + font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: 1.5; + + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; +} + +/* Code blocks */ +pre[class*="language-"] { + position: relative; + margin: .5em 0; + -webkit-box-shadow: -1px 0px 0px 0px #dae8ef, 0px 0px 0px 1px #dfdfdf; + -moz-box-shadow: -1px 0px 0px 0px #dae8ef, 0px 0px 0px 1px #dfdfdf; + box-shadow: -1px 0px 0px 0px #dae8ef, 0px 0px 0px 1px #dfdfdf; + border-left: 10px solid #dae8ef; + background-color: #fdfdfd; + background-image: -webkit-linear-gradient(transparent 50%, rgba(69, 142, 209, 0.04) 50%); + background-image: -moz-linear-gradient(transparent 50%, rgba(69, 142, 209, 0.04) 50%); + background-image: -ms-linear-gradient(transparent 50%, rgba(69, 142, 209, 0.04) 50%); + background-image: -o-linear-gradient(transparent 50%, rgba(69, 142, 209, 0.04) 50%); + background-image: linear-gradient(transparent 50%, rgba(69, 142, 209, 0.04) 50%); + background-size: 3em 3em; + background-origin: content-box; + overflow: visible; + padding: 0; +} + +code[class*="language"] { + max-height: inherit; + height: 100%; + padding: 0 1em; + display: block; + overflow: auto; +} + +/* Margin bottom to accomodate shadow */ +:not(pre) > code[class*="language-"], +pre[class*="language-"] { + background-color: #fdfdfd; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + margin-bottom: 1em; +} + +/* Inline code */ +:not(pre) > code[class*="language-"] { + position: relative; + padding: .2em; + -webkit-border-radius: 0.3em; + -moz-border-radius: 0.3em; + -ms-border-radius: 0.3em; + -o-border-radius: 0.3em; + border-radius: 0.3em; + color: #c92c2c; + border: 1px solid rgba(0, 0, 0, 0.1); + display: inline; + white-space: normal; +} + +pre[class*="language-"]:before, +pre[class*="language-"]:after { + content: ''; + z-index: -2; + display: block; + position: absolute; + bottom: 0.75em; + left: 0.18em; + width: 40%; + height: 20%; + max-height: 13em; + -webkit-transform: rotate(-2deg); + -moz-transform: rotate(-2deg); + -ms-transform: rotate(-2deg); + -o-transform: rotate(-2deg); + transform: rotate(-2deg); +} + +:not(pre) > code[class*="language-"]:after, +pre[class*="language-"]:after { + right: 0.75em; + left: auto; + -webkit-transform: rotate(2deg); + -moz-transform: rotate(2deg); + -ms-transform: rotate(2deg); + -o-transform: rotate(2deg); + transform: rotate(2deg); +} + +.token.comment, +.token.block-comment, +.token.prolog, +.token.doctype, +.token.cdata { + color: #7D8B99; +} + +.token.punctuation { + color: #5F6364; +} + +.token.property, +.token.tag, +.token.boolean, +.token.number, +.token.function-name, +.token.constant, +.token.symbol, +.token.deleted { + color: #c92c2c; +} + +.token.selector, +.token.attr-name, +.token.string, +.token.char, +.token.function, +.token.builtin, +.token.inserted { + color: #2f9c0a; +} + +.token.operator, +.token.entity, +.token.url, +.token.variable { + color: #a67f59; + background: rgba(255, 255, 255, 0.5); +} + +.token.atrule, +.token.attr-value, +.token.keyword, +.token.class-name { + color: #1990b8; +} + +.token.regex, +.token.important { + color: #e90; +} + +.language-css .token.string, +.style .token.string { + color: #a67f59; + background: rgba(255, 255, 255, 0.5); +} + +.token.important { + font-weight: normal; +} + +.token.bold { + font-weight: bold; +} +.token.italic { + font-style: italic; +} + +.token.entity { + cursor: help; +} + +.namespace { + opacity: .7; +} + +@media screen and (max-width: 767px) { + pre[class*="language-"]:before, + pre[class*="language-"]:after { + bottom: 14px; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + } + +} + +/* Plugin styles */ +.token.tab:not(:empty):before, +.token.cr:before, +.token.lf:before { + color: #e0d7d1; +} + +/* Plugin styles: Line Numbers */ +pre[class*="language-"].line-numbers { + padding-left: 0; +} + +pre[class*="language-"].line-numbers code { + padding-left: 3.8em; +} + +pre[class*="language-"].line-numbers .line-numbers-rows { + left: 0; +} + +/* Plugin styles: Line Highlight */ +pre[class*="language-"][data-line] { + padding-top: 0; + padding-bottom: 0; + padding-left: 0; +} +pre[data-line] code { + position: relative; + padding-left: 4em; +} +pre .line-highlight { + margin-top: 0; +} + diff --git a/src/assets/showcase/css/primeng.css b/src/assets/showcase/css/primeng.css new file mode 100644 index 00000000000..75bd091f8fb --- /dev/null +++ b/src/assets/showcase/css/primeng.css @@ -0,0 +1,51 @@ +@import '../../../app/components/common/common.css'; +@import '../../../app/components/autocomplete/autocomplete.css'; +@import '../../../app/components/accordion/accordion.css'; +@import '../../../app/components/blockui/blockui.css'; +@import '../../../app/components/breadcrumb/breadcrumb.css'; +@import '../../../app/components/button/button.css'; +@import '../../../app/components/calendar/calendar.css'; +@import '../../../app/components/carousel/carousel.css'; +@import '../../../app/components/checkbox/checkbox.css'; +@import '../../../app/components/chips/chips.css'; +@import '../../../app/components/datagrid/datagrid.css'; +@import '../../../app/components/datalist/datalist.css'; +@import '../../../app/components/datascroller/datascroller.css'; +@import '../../../app/components/datatable/datatable.css'; +@import '../../../app/components/dialog/dialog.css'; +@import '../../../app/components/dropdown/dropdown.css'; +@import '../../../app/components/fieldset/fieldset.css'; +@import '../../../app/components/fileupload/fileupload.css'; +@import '../../../app/components/galleria/galleria.css'; +@import '../../../app/components/grid/grid.css'; +@import '../../../app/components/growl/growl.css'; +@import '../../../app/components/inplace/inplace.css'; +@import '../../../app/components/inputswitch/inputswitch.css'; +@import '../../../app/components/inputtext/inputtext.css'; +@import '../../../app/components/inputtextarea/inputtextarea.css'; +@import '../../../app/components/lightbox/lightbox.css'; +@import '../../../app/components/listbox/listbox.css'; +@import '../../../app/components/menu/menu.css'; +@import '../../../app/components/messages/messages.css'; +@import '../../../app/components/multiselect/multiselect.css'; +@import '../../../app/components/orderlist/orderlist.css'; +@import '../../../app/components/overlaypanel/overlaypanel.css'; +@import '../../../app/components/paginator/paginator.css'; +@import '../../../app/components/panel/panel.css'; +@import '../../../app/components/password/password.css'; +@import '../../../app/components/picklist/picklist.css'; +@import '../../../app/components/progressbar/progressbar.css'; +@import '../../../app/components/radiobutton/radiobutton.css'; +@import '../../../app/components/schedule/schedule.css'; +@import '../../../app/components/selectbutton/selectbutton.css'; +@import '../../../app/components/slider/slider.css'; +@import '../../../app/components/spinner/spinner.css'; +@import '../../../app/components/splitbutton/splitbutton.css'; +@import '../../../app/components/steps/steps.css'; +@import '../../../app/components/tabmenu/tabmenu.css'; +@import '../../../app/components/tabview/tabview.css'; +@import '../../../app/components/terminal/terminal.css'; +@import '../../../app/components/toolbar/toolbar.css'; +@import '../../../app/components/tooltip/tooltip.css'; +@import '../../../app/components/tree/tree.css'; +@import '../../../app/components/treetable/treetable.css'; \ No newline at end of file diff --git a/src/assets/showcase/css/site.css b/src/assets/showcase/css/site.css new file mode 100644 index 00000000000..a6ebe53417c --- /dev/null +++ b/src/assets/showcase/css/site.css @@ -0,0 +1,959 @@ +@charset "UTF-8"; +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + src: url('../fonts/roboto-v15-latin-regular.eot'); + /* IE9 Compat Modes */ + + src: local('Roboto'), local('Roboto-Regular'), url('../fonts/roboto-v15-latin-regular.eot?#iefix') format('embedded-opentype'), + /* IE6-IE8 */ + + url('../fonts/roboto-v15-latin-regular.woff2') format('woff2'), + /* Super Modern Browsers */ + + url('../fonts/roboto-v15-latin-regular.woff') format('woff'), + /* Modern Browsers */ + + url('../fonts/roboto-v15-latin-regular.ttf') format('truetype'), + /* Safari, Android, iOS */ + + url('../fonts/roboto-v15-latin-regular.svg#Roboto') format('svg'); + /* Legacy iOS */ +} +/* ----------------------------------------------------------------------------------------------------- */ +html { + height: 100%; +} + +body { + margin: 0px; + height: 100%; + overflow-x: hidden; + overflow-y: auto; + background-color: #20272a; + font-family: 'Roboto', "Trebuchet MS", Arial, Helvetica, sans-serif; + font-weight: normal; + color: #404C51; + -webkit-font-smoothing: antialiased; + font-size: 1em; +} + +#layout-sidebar { + position: absolute; + left: 0; + top: 0; + background-color: #313b3f; + border-right: solid 1px #151d21; + overflow: hidden; + width: 299px; +} + +.layout-logo { + height: 65px; + display: block; + padding: 15px 0 17px 0; + z-index: 997; + background-color: #313b3f; + text-align: center; +} + +.layout-logo img { + height: 70px; +} + +#layout-sidebar > a { + width: 100%; + height: 50px; + display: block; + padding: 15px 0px 0px 25px; + cursor: pointer; + border-top: solid 1px #404a4e; + box-sizing: border-box; +} + +#layout-sidebar> a.active-menuitem { + background-color: #20282b !important; + -webkit-transition: all 0.5s ease; + -moz-transition: all 0.5s ease; + -ms-transition: all 0.5s ease; + -o-transition: all 0.5s ease; + transition: all 0.5s ease; +} + +#layout-sidebar > a:hover { + background-color: #20282b; + -webkit-transition: all 0.5s ease; + -moz-transition: all 0.5s ease; + -ms-transition: all 0.5s ease; + -o-transition: all 0.5s ease; + transition: all 0.5s ease; +} + +#layout-sidebar > a img { + width: 20px; + height: auto; + float: left; +} + +#layout-sidebar > a span { + color: #9ba5ac; + font-size: 16px; + margin: 0px 0px 0px 30px; + display: block; +} + +#layout-sidebar > div { + width: auto; + padding: 20px 15px; + overflow: hidden; + background-color: #20282b; +} + +#layout-sidebar > div.submenuhide { + overflow: hidden; + max-height: 0; + padding-top: 0; + padding-bottom: 0; + margin-top: 0; + margin-bottom: 0; + -moz-transition-duration: 0.3s; + -webkit-transition-duration: 0.3s; + -o-transition-duration: 0.3s; + transition-duration: 0.3s; + -moz-transition-timing-function: cubic-bezier(0.86, 0, 0.07, 1); + -webkit-transition-timing-function: cubic-bezier(0.86, 0, 0.07, 1); + -o-transition-timing-function: cubic-bezier(0.86, 0, 0.07, 1); + transition-timing-function: cubic-bezier(0.86, 0, 0.07, 1); +} + +#layout-sidebar > div.submenushow { + -moz-transition-duration: 0.3s; + -webkit-transition-duration: 0.3s; + -o-transition-duration: 0.3s; + transition-duration: 0.3s; + -moz-transition-timing-function: cubic-bezier(0.86, 0, 0.07, 1); + -webkit-transition-timing-function: cubic-bezier(0.86, 0, 0.07, 1); + -o-transition-timing-function: cubic-bezier(0.86, 0, 0.07, 1); + transition-timing-function: cubic-bezier(0.86, 0, 0.07, 1); + max-height: 500px; +} + +#layout-sidebar > div a { + width: 50%; + float: left; + padding: 6px; + box-sizing: border-box; + cursor: pointer; + border-radius: 4homepapx; + -webkit-border-radius: 4px; + color: #659eb3; + font-size: 14px; +} + +#layout-sidebar > div a:hover { + background-color: #101517; + color: #8dc5d9; +} + +#layout-content { + margin-left: 300px; + background-color: #FFFFFF; +} + +.content-section { + display: block; + border-bottom: solid 1px #dde3e6; + padding: 30px; + overflow: hidden; + background-color: #f5f7f8; +} + +.content-section:first-of-type > div > span { + line-height: 1.5em; +} + +.content-section h2 { + margin-top: 0; +} + +.feature-title { + font-size: 30px; + margin-bottom: 20px; + display: block; + color: #fca752; +} + +#topbar { + background-color: #1976D2; + box-sizing: border-box; + display: block; + border-bottom: solid 1px #dde3e6; + padding: 15px; + overflow: hidden; +} + +.topbar-link { + float: right; + width: 80px; + text-align: center; + padding: 10px 5px; + border-radius: 5px; + font-size: 12px; + -webkit-border-radius: 5px; + background-color: rgb(246, 249, 251); + margin-left: 5px; + -webkit-transition: all 0.5s ease; + -moz-transition: all 0.5s ease; + -ms-transition: all 0.5s ease; + -o-transition: all 0.5s ease; + transition: all 0.5s ease; + overflow: hidden; + color:#313b3f; +} +.topbar-link:hover { + background-color: rgba(255, 255, 255, 0.8); + -webkit-transition: all 0.5s ease; + -moz-transition: all 0.5s ease; + -ms-transition: all 0.5s ease; + -o-transition: all 0.5s ease; + transition: all 0.5s ease; +} +.topbar-link img { + width: 80%; + height: 30px; +} +/* +.PFGrayText { + color: #aab7c1; +} +.PFDarkText { + color: #313b3f; +}*/ + +#menu-button { + float: left; + padding: 10px 10px 5px 10px; + border-radius: 5px; + display: none; +} +#menu-button-mobile { + float: left; + padding: 10px 10px 5px 10px; + border-radius: 5px; + display: none; +} +#menu-button.active, +#menu-button:hover, +#menu-button:focus, +#menu-button-mobile:hover, +#menu-button-mobile:focus { + background-color: #2F88E0; +} +#menu-button img, +#menu-button-mobile img { + width: 30px; + height: 25px; +} + +.property-box { + height: 280px; + float: left; + overflow: hidden; + text-align: center; + border-radius: 5px; + -webkit-border-radius: 5px; + display: block; +} +.property-box img { + width: 60%; +} +.property-box .property-topic { + display: block; + color: #25aae1; + font-size: 18px; + margin-bottom: 10px; +} +.property-box .property-text { + display: block; + color: #414D52; + font-size: 14px; + line-height: 22px; +} + +.footer { + font-size: 14px; + color: #84939f; +} +.footer span:last-child { + float: right; + +} + +/** ThemeSwitcher **/ +#GlobalThemeSwitcher { + display: block; + text-align: left; + width: 200px; + max-height: 400px; + overflow-y: auto; + background-color: #eff3f6; + border: solid 1px #bcc7cf; + z-index: 99999999999; + position: absolute; + border-radius: 10px; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + -webkit-box-shadow: 0px 0px 3px 0px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0px 0px 3px 0px rgba(0, 0, 0, 0.2); + box-shadow: 0px 0px 3px 0px rgba(0, 0, 0, 0.2); + margin-left: -60px; +} +#GlobalThemeSwitcher a { + display: block; + padding: 10px; + border-bottom: solid 1px #dde3e7; + text-align: left; + color: #87939B; + overflow: hidden; +} +#GlobalThemeSwitcher a:hover { + color: #fdd106; +} +#GlobalThemeSwitcher a span.ui-theme { + width: 30px; + height: 27px; + float: left; + border: solid 1px #D7DCE0; + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; +} +#GlobalThemeSwitcher a img { + float: left; + width: 30px; + height: 27px; +} +#GlobalThemeSwitcher a span.ui-text { + display: inline-block; + margin-top: 7px; + margin-left: 10px; + font-size: 14px; +} +#GlobalThemeSwitcher > span { + font-size: 18px; + display: inline-block; + margin: 20px 0 0 9px; +} + +.topbar-link { + display: block +} + +.mobile-logo { + display: none; +} + +/* cursor */ +.cursorPointer { + cursor: pointer; +} + +/* OTHERS */ +a { + text-decoration: none; + color: #25AAE1 +} +.intro-text { + font-size: 16px; + color: #404C51; + line-height: 24px; +} +.intro-title { + font-size: 46px; + color: #DB2226; + line-height: 46px; + padding: 10px 0px 10px 0px; +} +/* buttons */ +.intro-btn { + width: 100%; + display: block; + box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + font-size: 16px; + cursor: pointer; + padding: 10px 14px; + border-radius: 3px; + -moz-box-shadow: 0 1px 2.5px 0 rgba(0, 0, 0, 0.26), 0 1px 5px 0 rgba(0, 0, 0, 0.16); + -webkit-box-shadow: 0 1px 2.5px 0 rgba(0, 0, 0, 0.26), 0 1px 5px 0 rgba(0, 0, 0, 0.16); + box-shadow: 0 1px 2.5px 0 rgba(0, 0, 0, 0.26), 0 1px 5px 0 rgba(0, 0, 0, 0.16); + transition: background-color .3s; +} + +.download-btn { + background-color: #ffd100; + color: #404c51; +} + +.download-btn:hover { + background-color: #ffda32; +} + +.download-btn:active { + background-color: #e5bc00; +} + +.github-btn { + background-color: #404c51; + color: #f8f8f8; +} + +.github-btn:hover { + background-color: #666f73; +} + +.github-btn:active { + background-color: #333c40; +} + +.prosupport-btn { + color: #f8f8f8; + background-color: #26a9e0; +} + +.prosupport-btn:hover { + background-color: #51bae6; +} + +.prosupport-btn:active { + background-color: #1e87b3; +} + +/* text colors */ +.orange { + color: #fca752; +} +.gray { + color: #84939f; +} +.pink { + color: #e26e61; +} +.yellow { + color: #fdd106; +} +.green { + color: #39b54a; +} +.blue { + color: #25aae1; +} +.subitem { + color: #84939f; +} +.fixedTop { + position: fixed !important; + margin-top: 0 !important; +} +.animated { + -webkit-transition: all 0.5s ease; + -moz-transition: all 0.5s ease; + -ms-transition: all 0.5s ease; + -o-transition: all 0.5s ease; + transition: all 0.5s ease; +} +input.searchInput { + padding-left: 30px; +} + +/** ClearFix **/ +.clearfix:after { + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden; +} +.clearfix { + display: inline-block; +} +/* required comment for clearfix to work in Opera \*/ +* html .clearfix { + height: 1%; +} +.clearfix { + display: block; +} + +.implementation { + background-color: #FFFFFF; + overflow: visible; +} +.implementation > h3 { + margin-top: 30px; + color: #5C666A; +} +.implementation h3.first { + margin-top: 0px !important; +} +.implementation h4 { + color: #5C666A; +} + +.SubSubMenu { + padding: 15px 30px; +} +.SubSubMenu ul { + margin: 0; + padding: 0; + width: 100%; +} +.SubSubMenu ul li { + list-style: none; + width: 20%; + float: left; + margin-top: 5px; +} +.SubSubMenu ul li a:hover { + color: #fdd106 +} + +/* Source Section */ +.source .ui-tabview-panel { + color: #404C51 !important; +} +.source h3 { + margin-top: 25px; + margin-bottom: 0px; + font-size: 24px; + font-weight: normal; +} +.source h4 { + margin-top: 25px; + margin-bottom: 0px; + font-size: 20px; + font-weight: normal; +} +.source p { + font-size: 16px; + line-height: 24px; + margin: 10px 0; + opacity: .90; +} +.source .doc-tablewrapper { + margin: 10px 0; +} +.source a { + color: #0273D4; +} +/* Tabs Source */ +.source .ui-tabview { + background: none; + border: 0 none; + color: #5C666A; + font-weight: lighter; + -moz-border-radius: 4px !important; + -webkit-border-radius: 4px !important; + border-radius: 4px !important; +} +.source .ui-tabview .ui-tabview-nav { + background: #1976D2 !important;; + margin-bottom: -1px; + padding: 3px 3px 0px 3px !important; + border-top-right-radius: 4px !important; + border-top-left-radius: 4px !important; + border-bottom-right-radius: 0px; + border-bottom-left-radius: 0px; +} +.source .ui-tabview .ui-tabview-nav li, +.source .ui-tabview .ui-tabview-nav li.ui-state-hover { + border: 0px none !important; + background: #3F94E9 !important;; + border-color: #3F94E9 !important;; + box-shadow: none !important; + border-top-right-radius: 4px !important; + border-top-left-radius: 4px !important; +} +.source .ui-tabview .ui-tabview-nav li a { + padding: .5em 1em !important; +} +.source .ui-tabview .ui-tabview-nav li.tab-doc { + margin-right: 0; +} +.source .ui-tabview .ui-tabview-nav li.ui-state-default a { + color: #fff !important; + font-weight: normal !important; + text-shadow: none ; +} +.source .ui-tabview .ui-tabview-nav li.ui-state-active a { + color: #5C666A !important; + font-weight: normal !important; +} +.source .ui-tabview .ui-tabview-nav li.ui-state-hover { + box-shadow: none !important;; +} +.source .ui-tabview .ui-tabview-nav li.ui-tabview-selected { + background: #F5F6F7 !important; +} +.source .ui-tabview .ui-tabview-panels { + border-top: 1px solid #F5F6F7 !important;; + color: #5C666A !important; + background: #F5F6F7; +} +.source .ui-tabview.ui-tabview-top > .ui-tabview-nav li { + top: 0px !important; +} + +/* Docs Table */ +.doc-table { + border-collapse: collapse; + width: 100%; +} +.doc-table th { + background-color: #dae8ef; + color: #404C51; + border: solid 1px #C1D5DF; + padding: 5px; + font-size: 16px; + text-align: left; +} +.doc-table tbody td { + color: #404C51; + padding: 4px 10px; + border: 1px solid #E5EBF0; + font-size: 15px; + opacity: .90; +} +.doc-table tbody tr:nth-child(even) { + background-color: #FBFCFD; +} +.doc-table tbody tr:nth-child(odd) { + background-color: #F3F6F9; +} + +@media (min-width: 1025px) { + .home-logo { + width: 100%; + } +} + +@media screen and (max-width: 64em) { + .home-logo { + width: 340px; + } + + .topbar-link { + display: none + } + .mobile-logo { + display: block; + float: right; + margin-top: 6px; + } + .mobile-logo img { + height: 30px; + } + #layout-sidebar { + display: none; + overflow-y: auto; + z-index: 999; + } + #layout-sidebar.active { + display: block; + width: 100%; + height: 100%; + overflow-y: auto; + z-index: 999; + } + .layout-logo { + padding: 15px; + height: 68px; + box-sizing: border-box; + } + .layout-logo .sidebar-logo { + display: none; + } + + #layout-content { + margin-left: 0 + } + .content-section { + padding: 14px 24px; + } + #menu-button { + display: inline-block; + border-radius: 5px; + position: relative; + z-index: 1000; + } + #menu-button.active { + display: none; + } + #menu-button-mobile.active { + display: inline-block; + background-color: #1976D2; + } + #menu-button:hover, + #menu-button:focus, + #menu-button-mobile:hover, + #menu-button-mobile:focus { + background-color: #2F88E0; + } + + .ui-tabview.ui-tabview-top > .ui-tabview-nav li { + width: 100%; + } + .BigButton { + width: 100%; + } + .SubSubMenu ul li { + width: 50% + } + .property-box img { + width: 40%; + } +} + +@media (max-width: 768px) { + .doc-table tbody td { + word-break: break-word; + } +} + +/* Themes */ +.ui-theme { + display: block; +} +.ui-theme.ui-theme-afterdark { + background-position: 0 0; + width: 30px; + height: 25px; +} +.ui-theme.ui-theme-afternoon { + background-position: 0 -75px; + width: 30px; + height: 25px; +} +.ui-theme.ui-theme-afterwork { + background-position: 0 -150px; + width: 30px; + height: 25px; +} +.ui-theme.ui-theme-aristo { + background-position: 0 -225px; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-black-tie { + background-position: 0 -302px; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-blitzer { + background-position: 0 -379px; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-bluesky { + background-position: 0 -456px; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-bootstrap { + background-position: 0 -533px; + width: 30px; + height: 26px; +} +.ui-theme.ui-theme-casablanca { + background-position: 0 -609px; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-cruze { + background-position: 0 -686px; + width: 30px; + height: 25px; +} +.ui-theme.ui-theme-cupertino { + background-position: 0 -761px; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-dark-hive { + background-position: 0 -838px; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-delta { + background-position: 0 -915px; + width: 30px; + height: 30px; +} +.ui-theme.ui-theme-dot-luv { + background-position: 0 -995px; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-eggplant { + background-position: 0 -1072px; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-excite-bike { + background-position: 0 -1149px; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-flick { + background-position: 0 -1226px; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-glass-x { + background-position: 0 -1303px; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-home { + background-position: 0 -1380px; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-hot-sneaks { + background-position: 0 -1457px; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-humanity { + background-position: 0 -1534px; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-le-frog { + background-position: 0 -1611px; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-midnight { + background-position: 0 -1688px; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-mint-choc { + background-position: 0 -1765px; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-omega { + background-position: 0 -915px; + width: 30px; + height: 30px; +} +.ui-theme.ui-theme-overcast { + background-position: 0 -1842px; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-pepper-grinder { + background-position: 0 -1919px; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-redmond { + background-position: -80px 0; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-rocket { + background-position: -80px -77px; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-sam { + background-position: -80px -154px; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-smoothness { + background-position: -80px -231px; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-south-street { + background-position: -80px -308px; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-start { + background-position: -80px -385px; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-sunny { + background-position: -80px -462px; + width: 30px; + height: 25px; +} +.ui-theme.ui-theme-swanky-purse { + background-position: -80px -537px; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-trontastic { + background-position: -80px -614px; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-ui-darkness { + background-position: -80px -691px; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-ui-lightness { + background-position: -80px -768px; + width: 30px; + height: 27px; +} +.ui-theme.ui-theme-vader { + background-position: -80px -845px; + width: 30px; + height: 27px; +} + +/* Code Styles */ +pre { + white-space: pre-wrap; + white-space: -moz-pre-wrap; + white-space: -o-pre-wrap; + word-wrap: break-word; + font-family: Courier, 'New Courier', monospace; + font-size: 14px; + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + padding: 1em; + background-color: #CFD8DC; + color: #404C51; + margin: 10px 0px; +} +.ui-tabview-left > .ui-tabview-nav { + height: 150px; +} +.col-button { + width: 10%; + text-align: center; +} +.col-icon { + width: 38px; + text-align: center; +} + +.whouses { + background: #ffffff; +} + +.whouses img { + width: 100%; +} \ No newline at end of file diff --git a/src/assets/showcase/data/cars-large.json b/src/assets/showcase/data/cars-large.json new file mode 100644 index 00000000000..75115028491 --- /dev/null +++ b/src/assets/showcase/data/cars-large.json @@ -0,0 +1,1204 @@ +{ + "data":[ + { + "vin":"ee8a89d8", + "brand":"Fiat", + "year":1987, + "color":"Maroon" + }, + { + "vin":"642b3edc", + "brand":"Renault", + "year":1968, + "color":"White" + }, + { + "vin":"19ec7580", + "brand":"Renault", + "year":1981, + "color":"Black" + }, + { + "vin":"39980f30", + "brand":"VW", + "year":1986, + "color":"Red" + }, + { + "vin":"ec9cc4e4", + "brand":"Fiat", + "year":1981, + "color":"Brown" + }, + { + "vin":"09a06548", + "brand":"VW", + "year":1965, + "color":"Green" + }, + { + "vin":"05c47246", + "brand":"Mercedes", + "year":2007, + "color":"Blue" + }, + { + "vin":"a9cb87aa", + "brand":"Fiat", + "year":1962, + "color":"Green" + }, + { + "vin":"eae758fa", + "brand":"BMW", + "year":1999, + "color":"Yellow" + }, + { + "vin":"1241c403", + "brand":"Jaguar", + "year":1964, + "color":"Yellow" + }, + { + "vin":"13f853a7", + "brand":"Honda", + "year":2006, + "color":"White" + }, + { + "vin":"447d9ed9", + "brand":"Jaguar", + "year":2005, + "color":"Orange" + }, + { + "vin":"78fa052e", + "brand":"Jaguar", + "year":1990, + "color":"Orange" + }, + { + "vin":"8b77772a", + "brand":"Mercedes", + "year":1991, + "color":"Blue" + }, + { + "vin":"23ba7e86", + "brand":"Honda", + "year":1975, + "color":"Yellow" + }, + { + "vin":"9bacb32d", + "brand":"Volvo", + "year":1968, + "color":"Brown" + }, + { + "vin":"62094d91", + "brand":"Mercedes", + "year":1962, + "color":"Green" + }, + { + "vin":"dc7003f4", + "brand":"Jaguar", + "year":1976, + "color":"Maroon" + }, + { + "vin":"08607aef", + "brand":"Mercedes", + "year":1987, + "color":"Maroon" + }, + { + "vin":"45eee33a", + "brand":"BMW", + "year":1980, + "color":"Silver" + }, + { + "vin":"f199ec5c", + "brand":"Jaguar", + "year":1961, + "color":"Green" + }, + { + "vin":"b34cd9e8", + "brand":"VW", + "year":1993, + "color":"Silver" + }, + { + "vin":"54b20b02", + "brand":"Renault", + "year":1967, + "color":"Brown" + }, + { + "vin":"5dd8766e", + "brand":"Honda", + "year":1998, + "color":"Orange" + }, + { + "vin":"df50ce22", + "brand":"Mercedes", + "year":1964, + "color":"White" + }, + { + "vin":"ecb3e9e1", + "brand":"Honda", + "year":2003, + "color":"Silver" + }, + { + "vin":"750d731d", + "brand":"Renault", + "year":1962, + "color":"Blue" + }, + { + "vin":"bec38cf4", + "brand":"Renault", + "year":1960, + "color":"Blue" + }, + { + "vin":"b7752002", + "brand":"Jaguar", + "year":1964, + "color":"Black" + }, + { + "vin":"315fe9c4", + "brand":"Fiat", + "year":1985, + "color":"Red" + }, + { + "vin":"be65f786", + "brand":"Mercedes", + "year":1963, + "color":"Orange" + }, + { + "vin":"786a7d57", + "brand":"Mercedes", + "year":2003, + "color":"Black" + }, + { + "vin":"a3aee412", + "brand":"Volvo", + "year":2003, + "color":"Maroon" + }, + { + "vin":"749e6bdd", + "brand":"Audi", + "year":1995, + "color":"Brown" + }, + { + "vin":"8cc40f50", + "brand":"BMW", + "year":1961, + "color":"Brown" + }, + { + "vin":"5de63a6f", + "brand":"Renault", + "year":1961, + "color":"White" + }, + { + "vin":"bdae1e20", + "brand":"Jaguar", + "year":2008, + "color":"Blue" + }, + { + "vin":"290cc891", + "brand":"VW", + "year":1992, + "color":"Brown" + }, + { + "vin":"007e1014", + "brand":"Renault", + "year":1966, + "color":"Black" + }, + { + "vin":"429c502d", + "brand":"Honda", + "year":1995, + "color":"Silver" + }, + { + "vin":"c336f9b6", + "brand":"Honda", + "year":1991, + "color":"Maroon" + }, + { + "vin":"a6783ba3", + "brand":"Honda", + "year":2004, + "color":"Yellow" + }, + { + "vin":"2ddaf8d5", + "brand":"Volvo", + "year":1982, + "color":"Blue" + }, + { + "vin":"c09c4b15", + "brand":"VW", + "year":1991, + "color":"Blue" + }, + { + "vin":"4609844c", + "brand":"Honda", + "year":1972, + "color":"Black" + }, + { + "vin":"8db7df27", + "brand":"Audi", + "year":1982, + "color":"Blue" + }, + { + "vin":"dcc58086", + "brand":"Audi", + "year":2001, + "color":"Brown" + }, + { + "vin":"f1274cbe", + "brand":"Fiat", + "year":1995, + "color":"Silver" + }, + { + "vin":"0858a5d4", + "brand":"Renault", + "year":1992, + "color":"Green" + }, + { + "vin":"c2d42bb6", + "brand":"Volvo", + "year":1972, + "color":"Green" + }, + { + "vin":"5535cd5a", + "brand":"Renault", + "year":1980, + "color":"Silver" + }, + { + "vin":"e3313e1e", + "brand":"Honda", + "year":2009, + "color":"Orange" + }, + { + "vin":"f4dea691", + "brand":"BMW", + "year":2002, + "color":"Brown" + }, + { + "vin":"ec15a449", + "brand":"Honda", + "year":1990, + "color":"Yellow" + }, + { + "vin":"80b74a0e", + "brand":"BMW", + "year":1979, + "color":"Yellow" + }, + { + "vin":"513fe268", + "brand":"Honda", + "year":1987, + "color":"White" + }, + { + "vin":"6934c8f8", + "brand":"Renault", + "year":1989, + "color":"Red" + }, + { + "vin":"6a4c3ad0", + "brand":"Honda", + "year":1994, + "color":"Yellow" + }, + { + "vin":"e0acd7b5", + "brand":"Mercedes", + "year":1965, + "color":"Red" + }, + { + "vin":"2f31ac35", + "brand":"Jaguar", + "year":1991, + "color":"Brown" + }, + { + "vin":"36104237", + "brand":"VW", + "year":1992, + "color":"Silver" + }, + { + "vin":"5be099b4", + "brand":"BMW", + "year":1991, + "color":"Yellow" + }, + { + "vin":"e2f55f31", + "brand":"BMW", + "year":1967, + "color":"Silver" + }, + { + "vin":"11274338", + "brand":"Mercedes", + "year":1999, + "color":"Blue" + }, + { + "vin":"f710e177", + "brand":"Fiat", + "year":2007, + "color":"White" + }, + { + "vin":"d8375b4b", + "brand":"Volvo", + "year":1977, + "color":"Blue" + }, + { + "vin":"a27ddfe3", + "brand":"VW", + "year":1978, + "color":"Blue" + }, + { + "vin":"d8848162", + "brand":"BMW", + "year":2008, + "color":"Black" + }, + { + "vin":"e9cb3677", + "brand":"BMW", + "year":2004, + "color":"Black" + }, + { + "vin":"c9dc321d", + "brand":"BMW", + "year":1989, + "color":"Red" + }, + { + "vin":"4c75c610", + "brand":"Volvo", + "year":1972, + "color":"Yellow" + }, + { + "vin":"1c90c93d", + "brand":"Audi", + "year":2004, + "color":"Silver" + }, + { + "vin":"5ccc9f7f", + "brand":"Jaguar", + "year":1961, + "color":"Red" + }, + { + "vin":"94498bc0", + "brand":"Fiat", + "year":1965, + "color":"Silver" + }, + { + "vin":"1d1a21f3", + "brand":"Honda", + "year":1985, + "color":"Red" + }, + { + "vin":"ea463ad3", + "brand":"BMW", + "year":1992, + "color":"Blue" + }, + { + "vin":"c24bdeb2", + "brand":"Honda", + "year":1991, + "color":"Red" + }, + { + "vin":"af3b744b", + "brand":"Audi", + "year":1998, + "color":"Green" + }, + { + "vin":"bebd5a96", + "brand":"Jaguar", + "year":1989, + "color":"Black" + }, + { + "vin":"6ef9dbf3", + "brand":"Fiat", + "year":1962, + "color":"Orange" + }, + { + "vin":"eede8f1e", + "brand":"Jaguar", + "year":1977, + "color":"Brown" + }, + { + "vin":"9d11b02d", + "brand":"BMW", + "year":1971, + "color":"Yellow" + }, + { + "vin":"1d4223a1", + "brand":"Mercedes", + "year":1975, + "color":"Brown" + }, + { + "vin":"4d118346", + "brand":"Mercedes", + "year":1985, + "color":"Brown" + }, + { + "vin":"cce76f06", + "brand":"Honda", + "year":1980, + "color":"Maroon" + }, + { + "vin":"2af398ed", + "brand":"Renault", + "year":1970, + "color":"Yellow" + }, + { + "vin":"c0ddab4c", + "brand":"Audi", + "year":2003, + "color":"Silver" + }, + { + "vin":"a27ea639", + "brand":"Mercedes", + "year":1968, + "color":"Yellow" + }, + { + "vin":"e6441f09", + "brand":"Jaguar", + "year":1982, + "color":"Green" + }, + { + "vin":"c4c59d58", + "brand":"Fiat", + "year":2005, + "color":"Orange" + }, + { + "vin":"9d31fc0a", + "brand":"Mercedes", + "year":1974, + "color":"Brown" + }, + { + "vin":"b0ffce2d", + "brand":"Volvo", + "year":1966, + "color":"Yellow" + }, + { + "vin":"ca7e52e3", + "brand":"Honda", + "year":1971, + "color":"Orange" + }, + { + "vin":"56b36f0e", + "brand":"Mercedes", + "year":2008, + "color":"Orange" + }, + { + "vin":"ba045e1e", + "brand":"Jaguar", + "year":1968, + "color":"White" + }, + { + "vin":"fd579989", + "brand":"BMW", + "year":1975, + "color":"Black" + }, + { + "vin":"084850a3", + "brand":"Audi", + "year":1990, + "color":"Red" + }, + { + "vin":"e39245ab", + "brand":"BMW", + "year":1969, + "color":"White" + }, + { + "vin":"41ab14a1", + "brand":"Jaguar", + "year":1987, + "color":"Silver" + }, + { + "vin":"7ec4c1c0", + "brand":"Jaguar", + "year":1980, + "color":"Black" + }, + { + "vin":"bf1c14aa", + "brand":"Audi", + "year":1984, + "color":"Yellow" + }, + { + "vin":"adeff567", + "brand":"Volvo", + "year":2000, + "color":"Brown" + }, + { + "vin":"61e5e07d", + "brand":"Mercedes", + "year":1978, + "color":"Orange" + }, + { + "vin":"7555e46a", + "brand":"Audi", + "year":1966, + "color":"Blue" + }, + { + "vin":"95babbd1", + "brand":"Honda", + "year":1998, + "color":"Black" + }, + { + "vin":"ff6885f7", + "brand":"Audi", + "year":1996, + "color":"White" + }, + { + "vin":"5b5a0031", + "brand":"Audi", + "year":1968, + "color":"Brown" + }, + { + "vin":"de63c575", + "brand":"Mercedes", + "year":1989, + "color":"Yellow" + }, + { + "vin":"6bf3bfbc", + "brand":"Audi", + "year":1968, + "color":"Green" + }, + { + "vin":"d2d2e8d4", + "brand":"Fiat", + "year":1985, + "color":"Green" + }, + { + "vin":"edcab1f7", + "brand":"VW", + "year":1979, + "color":"Silver" + }, + { + "vin":"03234e20", + "brand":"Mercedes", + "year":1962, + "color":"Orange" + }, + { + "vin":"de2a7b08", + "brand":"Honda", + "year":2007, + "color":"Blue" + }, + { + "vin":"717b8282", + "brand":"BMW", + "year":1999, + "color":"Yellow" + }, + { + "vin":"790e7f03", + "brand":"Volvo", + "year":1983, + "color":"White" + }, + { + "vin":"8eefb223", + "brand":"Jaguar", + "year":1983, + "color":"Silver" + }, + { + "vin":"5e524acd", + "brand":"Jaguar", + "year":1994, + "color":"Maroon" + }, + { + "vin":"26b1aff9", + "brand":"BMW", + "year":1965, + "color":"Black" + }, + { + "vin":"c007a623", + "brand":"Renault", + "year":1968, + "color":"Maroon" + }, + { + "vin":"76733e83", + "brand":"Honda", + "year":1991, + "color":"White" + }, + { + "vin":"ef3c14f7", + "brand":"Fiat", + "year":1987, + "color":"Brown" + }, + { + "vin":"2b4ca005", + "brand":"Honda", + "year":2009, + "color":"Silver" + }, + { + "vin":"8191dbb6", + "brand":"BMW", + "year":2005, + "color":"Black" + }, + { + "vin":"f6b3bd94", + "brand":"Renault", + "year":1967, + "color":"Yellow" + }, + { + "vin":"abb19f41", + "brand":"Volvo", + "year":1975, + "color":"Blue" + }, + { + "vin":"7470c95f", + "brand":"Renault", + "year":1996, + "color":"Black" + }, + { + "vin":"5f1b57a3", + "brand":"Volvo", + "year":1986, + "color":"Red" + }, + { + "vin":"ed47a74b", + "brand":"BMW", + "year":2007, + "color":"Brown" + }, + { + "vin":"ed6030f7", + "brand":"Honda", + "year":1990, + "color":"Red" + }, + { + "vin":"944c71dc", + "brand":"Mercedes", + "year":1991, + "color":"Silver" + }, + { + "vin":"c7d838a5", + "brand":"VW", + "year":1980, + "color":"Yellow" + }, + { + "vin":"712db898", + "brand":"Audi", + "year":1965, + "color":"Red" + }, + { + "vin":"99acc06f", + "brand":"BMW", + "year":1995, + "color":"Silver" + }, + { + "vin":"6c68ffa5", + "brand":"Jaguar", + "year":1999, + "color":"Green" + }, + { + "vin":"63893922", + "brand":"Renault", + "year":1991, + "color":"Brown" + }, + { + "vin":"dca5f739", + "brand":"Jaguar", + "year":2002, + "color":"Blue" + }, + { + "vin":"16da6dcb", + "brand":"Jaguar", + "year":2006, + "color":"Blue" + }, + { + "vin":"fe9ca30c", + "brand":"Fiat", + "year":1967, + "color":"Maroon" + }, + { + "vin":"f0193ac7", + "brand":"Mercedes", + "year":1979, + "color":"Orange" + }, + { + "vin":"145f5551", + "brand":"Jaguar", + "year":1993, + "color":"Brown" + }, + { + "vin":"24714317", + "brand":"Mercedes", + "year":1971, + "color":"White" + }, + { + "vin":"1a9c6e4e", + "brand":"Jaguar", + "year":1997, + "color":"Yellow" + }, + { + "vin":"c9b7ef72", + "brand":"Fiat", + "year":1992, + "color":"Maroon" + }, + { + "vin":"b1b6c375", + "brand":"Fiat", + "year":1963, + "color":"Silver" + }, + { + "vin":"7254a003", + "brand":"Audi", + "year":1982, + "color":"White" + }, + { + "vin":"6f0de80f", + "brand":"Renault", + "year":1987, + "color":"Blue" + }, + { + "vin":"e3048f87", + "brand":"Fiat", + "year":1989, + "color":"Blue" + }, + { + "vin":"361e435a", + "brand":"BMW", + "year":1973, + "color":"Green" + }, + { + "vin":"59e6a9f3", + "brand":"BMW", + "year":1964, + "color":"Maroon" + }, + { + "vin":"b791fe05", + "brand":"Mercedes", + "year":1993, + "color":"Yellow" + }, + { + "vin":"68b0dd88", + "brand":"BMW", + "year":2002, + "color":"Green" + }, + { + "vin":"5b439d1f", + "brand":"BMW", + "year":1964, + "color":"Maroon" + }, + { + "vin":"9a7ac9e3", + "brand":"Renault", + "year":1988, + "color":"White" + }, + { + "vin":"d214751d", + "brand":"Honda", + "year":1997, + "color":"White" + }, + { + "vin":"72229390", + "brand":"Mercedes", + "year":1996, + "color":"White" + }, + { + "vin":"b5fbbeee", + "brand":"VW", + "year":1999, + "color":"Brown" + }, + { + "vin":"8972b543", + "brand":"Audi", + "year":1973, + "color":"Black" + }, + { + "vin":"7bc21024", + "brand":"Renault", + "year":1980, + "color":"Yellow" + }, + { + "vin":"5d661964", + "brand":"Renault", + "year":2005, + "color":"Silver" + }, + { + "vin":"a6ccc2d8", + "brand":"Honda", + "year":1994, + "color":"Blue" + }, + { + "vin":"c1f15f28", + "brand":"Volvo", + "year":1999, + "color":"Black" + }, + { + "vin":"161512ce", + "brand":"VW", + "year":1962, + "color":"Black" + }, + { + "vin":"16e0b448", + "brand":"Fiat", + "year":1990, + "color":"Green" + }, + { + "vin":"f0734442", + "brand":"Audi", + "year":1966, + "color":"Orange" + }, + { + "vin":"5e233279", + "brand":"Audi", + "year":1964, + "color":"Green" + }, + { + "vin":"1de720b2", + "brand":"Renault", + "year":2003, + "color":"Orange" + }, + { + "vin":"46efaeb2", + "brand":"Jaguar", + "year":1993, + "color":"Green" + }, + { + "vin":"88f2354c", + "brand":"Jaguar", + "year":2006, + "color":"Black" + }, + { + "vin":"04819fd6", + "brand":"Mercedes", + "year":1983, + "color":"White" + }, + { + "vin":"401771c8", + "brand":"Volvo", + "year":1962, + "color":"Silver" + }, + { + "vin":"8600877b", + "brand":"VW", + "year":1996, + "color":"Black" + }, + { + "vin":"946bd645", + "brand":"Honda", + "year":1991, + "color":"Red" + }, + { + "vin":"ad078e69", + "brand":"Fiat", + "year":1991, + "color":"Brown" + }, + { + "vin":"93138901", + "brand":"Mercedes", + "year":1961, + "color":"Silver" + }, + { + "vin":"f365dfa4", + "brand":"Mercedes", + "year":1980, + "color":"Black" + }, + { + "vin":"22647161", + "brand":"Audi", + "year":2007, + "color":"Blue" + }, + { + "vin":"92d1ee27", + "brand":"Jaguar", + "year":1977, + "color":"Silver" + }, + { + "vin":"137c2b3a", + "brand":"Honda", + "year":1970, + "color":"Blue" + }, + { + "vin":"b05b5235", + "brand":"BMW", + "year":1967, + "color":"Yellow" + }, + { + "vin":"1afbf400", + "brand":"Audi", + "year":1966, + "color":"Maroon" + }, + { + "vin":"8530ae50", + "brand":"BMW", + "year":1979, + "color":"Brown" + }, + { + "vin":"c9a487a3", + "brand":"Volvo", + "year":1981, + "color":"Silver" + }, + { + "vin":"5cb0bed6", + "brand":"Honda", + "year":1962, + "color":"Orange" + }, + { + "vin":"cf7d0b45", + "brand":"Fiat", + "year":1997, + "color":"Green" + }, + { + "vin":"bc762dd0", + "brand":"Jaguar", + "year":2000, + "color":"Yellow" + }, + { + "vin":"97207a61", + "brand":"VW", + "year":1976, + "color":"Blue" + }, + { + "vin":"17680899", + "brand":"Mercedes", + "year":2006, + "color":"Silver" + }, + { + "vin":"d8a98d30", + "brand":"Renault", + "year":1990, + "color":"Green" + }, + { + "vin":"ff01ead0", + "brand":"Audi", + "year":1962, + "color":"Blue" + }, + { + "vin":"38b30a61", + "brand":"Fiat", + "year":1977, + "color":"White" + }, + { + "vin":"9a6793c1", + "brand":"Renault", + "year":1983, + "color":"Red" + }, + { + "vin":"b1f27273", + "brand":"Mercedes", + "year":2007, + "color":"Brown" + }, + { + "vin":"0fa8c1aa", + "brand":"Jaguar", + "year":1982, + "color":"Blue" + }, + { + "vin":"a7520f42", + "brand":"Volvo", + "year":2008, + "color":"Maroon" + }, + { + "vin":"494eba81", + "brand":"BMW", + "year":1966, + "color":"Silver" + }, + { + "vin":"683535b8", + "brand":"Renault", + "year":2003, + "color":"White" + }, + { + "vin":"62e5d216", + "brand":"Audi", + "year":1962, + "color":"Orange" + }, + { + "vin":"16a65b56", + "brand":"Jaguar", + "year":2009, + "color":"Blue" + }, + { + "vin":"d00250a3", + "brand":"BMW", + "year":1978, + "color":"Blue" + }, + { + "vin":"f3c3909d", + "brand":"Renault", + "year":2003, + "color":"Green" + } + ] +} \ No newline at end of file diff --git a/src/assets/showcase/data/cars-medium.json b/src/assets/showcase/data/cars-medium.json new file mode 100644 index 00000000000..cf686997320 --- /dev/null +++ b/src/assets/showcase/data/cars-medium.json @@ -0,0 +1,54 @@ +{ + "data":[ + {"vin":"a1653d4d","brand":"VW","year":1998,"color":"White","price":10000}, + {"vin":"ddeb9b10","brand":"Mercedes","year":1985,"color":"Green","price":25000}, + {"vin":"d8ebe413","brand":"Jaguar","year":1979,"color":"Silver","price":30000}, + {"vin":"aab227b7","brand":"Audi","year":1970,"color":"Black","price":12000}, + {"vin":"631f7412","brand":"Volvo","year":1992,"color":"Red","price":15500}, + {"vin":"7d2d22b0","brand":"VW","year":1993,"color":"Maroon","price":40000}, + {"vin":"50e900ca","brand":"Fiat","year":1964,"color":"Blue","price":25000}, + {"vin":"4bbcd603","brand":"Renault","year":1983,"color":"Maroon","price":22000}, + {"vin":"70214c7e","brand":"Renault","year":1961,"color":"Black","price":19000}, + {"vin":"ec229a92","brand":"Audi","year":1984,"color":"Brown","price":36000}, + {"vin":"1083ee40","brand":"VW","year":1984,"color":"Silver","price":215000}, + {"vin":"6e0da3ab","brand":"Volvo","year":1987,"color":"Silver","price":32000}, + {"vin":"5aee636b","brand":"Jaguar","year":1995,"color":"Maroon","price":20000}, + {"vin":"7cc43997","brand":"Jaguar","year":1984,"color":"Orange","price":14000}, + {"vin":"88ec9f66","brand":"Honda","year":1989,"color":"Maroon","price":36000}, + {"vin":"f5a4a5f5","brand":"BMW","year":1986,"color":"Blue","price":28000}, + {"vin":"15b9a5c9","brand":"Mercedes","year":1986,"color":"Orange","price":14000}, + {"vin":"f7e18d01","brand":"Mercedes","year":1991,"color":"White","price":25000}, + {"vin":"cec593d7","brand":"VW","year":1992,"color":"Blue","price":36000}, + {"vin":"d5bac4f0","brand":"Renault","year":2001,"color":"Blue","price":25000}, + {"vin":"56b527c8","brand":"Jaguar","year":1990,"color":"Yellow","price":52000}, + {"vin":"1ac011ff","brand":"Audi","year":1966,"color":"Maroon","price":45000}, + {"vin":"fc074185","brand":"BMW","year":1962,"color":"Blue","price":54000}, + {"vin":"606ba663","brand":"Honda","year":1982,"color":"Blue","price":22000}, + {"vin":"d05060b8","brand":"Mercedes","year":2003,"color":"Silver","price":15000}, + {"vin":"46e4bbe8","brand":"Mercedes","year":1986,"color":"White","price":18000}, + {"vin":"c29da0d7","brand":"BMW","year":1983,"color":"Brown","price":32000}, + {"vin":"24622f70","brand":"VW","year":1973,"color":"Maroon","price":36000}, + {"vin":"7f573d2c","brand":"Mercedes","year":1991,"color":"Red","price":21000}, + {"vin":"b69e6f5c","brand":"Jaguar","year":1993,"color":"Yellow","price":16000}, + {"vin":"ead9bf1d","brand":"Fiat","year":1968,"color":"Maroon","price":43000}, + {"vin":"bc58113e","brand":"Renault","year":1981,"color":"Silver","price":36000}, + {"vin":"2989d5b1","brand":"Honda","year":2006,"color":"Blue","price":240000}, + {"vin":"c243e3a0","brand":"Fiat","year":1990,"color":"Maroon","price":15000}, + {"vin":"e3d3ebf3","brand":"Audi","year":1996,"color":"White","price":28000}, + {"vin":"45337e7a","brand":"Mercedes","year":1982,"color":"Blue","price":14000}, + {"vin":"36e9cf7e","brand":"Fiat","year":2000,"color":"Orange","price":26000}, + {"vin":"036bf135","brand":"Mercedes","year":1973,"color":"Black","price":22000}, + {"vin":"ad612e9f","brand":"Mercedes","year":1975,"color":"Red","price":45000}, + {"vin":"97c6e1e9","brand":"Volvo","year":1967,"color":"Green","price":42000}, + {"vin":"ae962274","brand":"Volvo","year":1982,"color":"Red","price":36000}, + {"vin":"81f8972a","brand":"BMW","year":2007,"color":"Black","price":56000}, + {"vin":"f8506743","brand":"Audi","year":1975,"color":"Blue","price":42000}, + {"vin":"596859d1","brand":"Fiat","year":2002,"color":"Green","price":48000}, + {"vin":"d83c1d9a","brand":"Volvo","year":1972,"color":"Black","price":29000}, + {"vin":"32f41550","brand":"Mercedes","year":1978,"color":"Brown","price":17000}, + {"vin":"c28cd2e4","brand":"Volvo","year":1982,"color":"Silver","price":24000}, + {"vin":"80890dcc","brand":"Audi","year":1962,"color":"White","price":36000}, + {"vin":"4bf1aeb5","brand":"VW","year":2000,"color":"Silver","price":24000}, + {"vin":"45ca4786","brand":"BMW","year":1995,"color":"Maroon","price":50000} + ] +} \ No newline at end of file diff --git a/src/assets/showcase/data/cars-small.json b/src/assets/showcase/data/cars-small.json new file mode 100644 index 00000000000..7a2bc59ef63 --- /dev/null +++ b/src/assets/showcase/data/cars-small.json @@ -0,0 +1,14 @@ +{ + "data": [ + {"brand": "VW", "year": 2012, "color": "Orange", "vin": "dsad231ff"}, + {"brand": "Audi", "year": 2011, "color": "Black", "vin": "gwregre345"}, + {"brand": "Renault", "year": 2005, "color": "Gray", "vin": "h354htr"}, + {"brand": "BMW", "year": 2003, "color": "Blue", "vin": "j6w54qgh"}, + {"brand": "Mercedes", "year": 1995, "color": "Orange", "vin": "hrtwy34"}, + {"brand": "Volvo", "year": 2005, "color": "Black", "vin": "jejtyj"}, + {"brand": "Honda", "year": 2012, "color": "Yellow", "vin": "g43gr"}, + {"brand": "Jaguar", "year": 2013, "color": "Orange", "vin": "greg34"}, + {"brand": "Ford", "year": 2000, "color": "Black", "vin": "h54hw5"}, + {"brand": "Fiat", "year": 2013, "color": "Red", "vin": "245t2s"} + ] +} diff --git a/src/assets/showcase/data/countries.json b/src/assets/showcase/data/countries.json new file mode 100644 index 00000000000..bf5bf652fe2 --- /dev/null +++ b/src/assets/showcase/data/countries.json @@ -0,0 +1,247 @@ +{ + "data": [ + {"name": "Afghanistan", "code": "AF"}, + {"name": "Åland Islands", "code": "AX"}, + {"name": "Albania", "code": "AL"}, + {"name": "Algeria", "code": "DZ"}, + {"name": "American Samoa", "code": "AS"}, + {"name": "Andorra", "code": "AD"}, + {"name": "Angola", "code": "AO"}, + {"name": "Anguilla", "code": "AI"}, + {"name": "Antarctica", "code": "AQ"}, + {"name": "Antigua and Barbuda", "code": "AG"}, + {"name": "Argentina", "code": "AR"}, + {"name": "Armenia", "code": "AM"}, + {"name": "Aruba", "code": "AW"}, + {"name": "Australia", "code": "AU"}, + {"name": "Austria", "code": "AT"}, + {"name": "Azerbaijan", "code": "AZ"}, + {"name": "Bahamas", "code": "BS"}, + {"name": "Bahrain", "code": "BH"}, + {"name": "Bangladesh", "code": "BD"}, + {"name": "Barbados", "code": "BB"}, + {"name": "Belarus", "code": "BY"}, + {"name": "Belgium", "code": "BE"}, + {"name": "Belize", "code": "BZ"}, + {"name": "Benin", "code": "BJ"}, + {"name": "Bermuda", "code": "BM"}, + {"name": "Bhutan", "code": "BT"}, + {"name": "Bolivia", "code": "BO"}, + {"name": "Bosnia and Herzegovina", "code": "BA"}, + {"name": "Botswana", "code": "BW"}, + {"name": "Bouvet Island", "code": "BV"}, + {"name": "Brazil", "code": "BR"}, + {"name": "British Indian Ocean Territory", "code": "IO"}, + {"name": "Brunei Darussalam", "code": "BN"}, + {"name": "Bulgaria", "code": "BG"}, + {"name": "Burkina Faso", "code": "BF"}, + {"name": "Burundi", "code": "BI"}, + {"name": "Cambodia", "code": "KH"}, + {"name": "Cameroon", "code": "CM"}, + {"name": "Canada", "code": "CA"}, + {"name": "Cape Verde", "code": "CV"}, + {"name": "Cayman Islands", "code": "KY"}, + {"name": "Central African Republic", "code": "CF"}, + {"name": "Chad", "code": "TD"}, + {"name": "Chile", "code": "CL"}, + {"name": "China", "code": "CN"}, + {"name": "Christmas Island", "code": "CX"}, + {"name": "Cocos (Keeling) Islands", "code": "CC"}, + {"name": "Colombia", "code": "CO"}, + {"name": "Comoros", "code": "KM"}, + {"name": "Congo", "code": "CG"}, + {"name": "Congo, The Democratic Republic of the", "code": "CD"}, + {"name": "Cook Islands", "code": "CK"}, + {"name": "Costa Rica", "code": "CR"}, + {"name": "Cote D\"Ivoire", "code": "CI"}, + {"name": "Croatia", "code": "HR"}, + {"name": "Cuba", "code": "CU"}, + {"name": "Cyprus", "code": "CY"}, + {"name": "Czech Republic", "code": "CZ"}, + {"name": "Denmark", "code": "DK"}, + {"name": "Djibouti", "code": "DJ"}, + {"name": "Dominica", "code": "DM"}, + {"name": "Dominican Republic", "code": "DO"}, + {"name": "Ecuador", "code": "EC"}, + {"name": "Egypt", "code": "EG"}, + {"name": "El Salvador", "code": "SV"}, + {"name": "Equatorial Guinea", "code": "GQ"}, + {"name": "Eritrea", "code": "ER"}, + {"name": "Estonia", "code": "EE"}, + {"name": "Ethiopia", "code": "ET"}, + {"name": "Falkland Islands (Malvinas)", "code": "FK"}, + {"name": "Faroe Islands", "code": "FO"}, + {"name": "Fiji", "code": "FJ"}, + {"name": "Finland", "code": "FI"}, + {"name": "France", "code": "FR"}, + {"name": "French Guiana", "code": "GF"}, + {"name": "French Polynesia", "code": "PF"}, + {"name": "French Southern Territories", "code": "TF"}, + {"name": "Gabon", "code": "GA"}, + {"name": "Gambia", "code": "GM"}, + {"name": "Georgia", "code": "GE"}, + {"name": "Germany", "code": "DE"}, + {"name": "Ghana", "code": "GH"}, + {"name": "Gibraltar", "code": "GI"}, + {"name": "Greece", "code": "GR"}, + {"name": "Greenland", "code": "GL"}, + {"name": "Grenada", "code": "GD"}, + {"name": "Guadeloupe", "code": "GP"}, + {"name": "Guam", "code": "GU"}, + {"name": "Guatemala", "code": "GT"}, + {"name": "Guernsey", "code": "GG"}, + {"name": "Guinea", "code": "GN"}, + {"name": "Guinea-Bissau", "code": "GW"}, + {"name": "Guyana", "code": "GY"}, + {"name": "Haiti", "code": "HT"}, + {"name": "Heard Island and Mcdonald Islands", "code": "HM"}, + {"name": "Holy See (Vatican City State)", "code": "VA"}, + {"name": "Honduras", "code": "HN"}, + {"name": "Hong Kong", "code": "HK"}, + {"name": "Hungary", "code": "HU"}, + {"name": "Iceland", "code": "IS"}, + {"name": "India", "code": "IN"}, + {"name": "Indonesia", "code": "ID"}, + {"name": "Iran, Islamic Republic Of", "code": "IR"}, + {"name": "Iraq", "code": "IQ"}, + {"name": "Ireland", "code": "IE"}, + {"name": "Isle of Man", "code": "IM"}, + {"name": "Israel", "code": "IL"}, + {"name": "Italy", "code": "IT"}, + {"name": "Jamaica", "code": "JM"}, + {"name": "Japan", "code": "JP"}, + {"name": "Jersey", "code": "JE"}, + {"name": "Jordan", "code": "JO"}, + {"name": "Kazakhstan", "code": "KZ"}, + {"name": "Kenya", "code": "KE"}, + {"name": "Kiribati", "code": "KI"}, + {"name": "Korea, Democratic People\"S Republic of", "code": "KP"}, + {"name": "Korea, Republic of", "code": "KR"}, + {"name": "Kuwait", "code": "KW"}, + {"name": "Kyrgyzstan", "code": "KG"}, + {"name": "Lao People\"S Democratic Republic", "code": "LA"}, + {"name": "Latvia", "code": "LV"}, + {"name": "Lebanon", "code": "LB"}, + {"name": "Lesotho", "code": "LS"}, + {"name": "Liberia", "code": "LR"}, + {"name": "Libyan Arab Jamahiriya", "code": "LY"}, + {"name": "Liechtenstein", "code": "LI"}, + {"name": "Lithuania", "code": "LT"}, + {"name": "Luxembourg", "code": "LU"}, + {"name": "Macao", "code": "MO"}, + {"name": "Macedonia, The Former Yugoslav Republic of", "code": "MK"}, + {"name": "Madagascar", "code": "MG"}, + {"name": "Malawi", "code": "MW"}, + {"name": "Malaysia", "code": "MY"}, + {"name": "Maldives", "code": "MV"}, + {"name": "Mali", "code": "ML"}, + {"name": "Malta", "code": "MT"}, + {"name": "Marshall Islands", "code": "MH"}, + {"name": "Martinique", "code": "MQ"}, + {"name": "Mauritania", "code": "MR"}, + {"name": "Mauritius", "code": "MU"}, + {"name": "Mayotte", "code": "YT"}, + {"name": "Mexico", "code": "MX"}, + {"name": "Micronesia, Federated States of", "code": "FM"}, + {"name": "Moldova, Republic of", "code": "MD"}, + {"name": "Monaco", "code": "MC"}, + {"name": "Mongolia", "code": "MN"}, + {"name": "Montserrat", "code": "MS"}, + {"name": "Morocco", "code": "MA"}, + {"name": "Mozambique", "code": "MZ"}, + {"name": "Myanmar", "code": "MM"}, + {"name": "Namibia", "code": "NA"}, + {"name": "Nauru", "code": "NR"}, + {"name": "Nepal", "code": "NP"}, + {"name": "Netherlands", "code": "NL"}, + {"name": "Netherlands Antilles", "code": "AN"}, + {"name": "New Caledonia", "code": "NC"}, + {"name": "New Zealand", "code": "NZ"}, + {"name": "Nicaragua", "code": "NI"}, + {"name": "Niger", "code": "NE"}, + {"name": "Nigeria", "code": "NG"}, + {"name": "Niue", "code": "NU"}, + {"name": "Norfolk Island", "code": "NF"}, + {"name": "Northern Mariana Islands", "code": "MP"}, + {"name": "Norway", "code": "NO"}, + {"name": "Oman", "code": "OM"}, + {"name": "Pakistan", "code": "PK"}, + {"name": "Palau", "code": "PW"}, + {"name": "Palestinian Territory, Occupied", "code": "PS"}, + {"name": "Panama", "code": "PA"}, + {"name": "Papua New Guinea", "code": "PG"}, + {"name": "Paraguay", "code": "PY"}, + {"name": "Peru", "code": "PE"}, + {"name": "Philippines", "code": "PH"}, + {"name": "Pitcairn", "code": "PN"}, + {"name": "Poland", "code": "PL"}, + {"name": "Portugal", "code": "PT"}, + {"name": "Puerto Rico", "code": "PR"}, + {"name": "Qatar", "code": "QA"}, + {"name": "Reunion", "code": "RE"}, + {"name": "Romania", "code": "RO"}, + {"name": "Russian Federation", "code": "RU"}, + {"name": "RWANDA", "code": "RW"}, + {"name": "Saint Helena", "code": "SH"}, + {"name": "Saint Kitts and Nevis", "code": "KN"}, + {"name": "Saint Lucia", "code": "LC"}, + {"name": "Saint Pierre and Miquelon", "code": "PM"}, + {"name": "Saint Vincent and the Grenadines", "code": "VC"}, + {"name": "Samoa", "code": "WS"}, + {"name": "San Marino", "code": "SM"}, + {"name": "Sao Tome and Principe", "code": "ST"}, + {"name": "Saudi Arabia", "code": "SA"}, + {"name": "Senegal", "code": "SN"}, + {"name": "Serbia and Montenegro", "code": "CS"}, + {"name": "Seychelles", "code": "SC"}, + {"name": "Sierra Leone", "code": "SL"}, + {"name": "Singapore", "code": "SG"}, + {"name": "Slovakia", "code": "SK"}, + {"name": "Slovenia", "code": "SI"}, + {"name": "Solomon Islands", "code": "SB"}, + {"name": "Somalia", "code": "SO"}, + {"name": "South Africa", "code": "ZA"}, + {"name": "South Georgia and the South Sandwich Islands", "code": "GS"}, + {"name": "Spain", "code": "ES"}, + {"name": "Sri Lanka", "code": "LK"}, + {"name": "Sudan", "code": "SD"}, + {"name": "Suriname", "code": "SR"}, + {"name": "Svalbard and Jan Mayen", "code": "SJ"}, + {"name": "Swaziland", "code": "SZ"}, + {"name": "Sweden", "code": "SE"}, + {"name": "Switzerland", "code": "CH"}, + {"name": "Syrian Arab Republic", "code": "SY"}, + {"name": "Taiwan, Province of China", "code": "TW"}, + {"name": "Tajikistan", "code": "TJ"}, + {"name": "Tanzania, United Republic of", "code": "TZ"}, + {"name": "Thailand", "code": "TH"}, + {"name": "Timor-Leste", "code": "TL"}, + {"name": "Togo", "code": "TG"}, + {"name": "Tokelau", "code": "TK"}, + {"name": "Tonga", "code": "TO"}, + {"name": "Trinidad and Tobago", "code": "TT"}, + {"name": "Tunisia", "code": "TN"}, + {"name": "Turkey", "code": "TR"}, + {"name": "Turkmenistan", "code": "TM"}, + {"name": "Turks and Caicos Islands", "code": "TC"}, + {"name": "Tuvalu", "code": "TV"}, + {"name": "Uganda", "code": "UG"}, + {"name": "Ukraine", "code": "UA"}, + {"name": "United Arab Emirates", "code": "AE"}, + {"name": "United Kingdom", "code": "GB"}, + {"name": "United States", "code": "US"}, + {"name": "United States Minor Outlying Islands", "code": "UM"}, + {"name": "Uruguay", "code": "UY"}, + {"name": "Uzbekistan", "code": "UZ"}, + {"name": "Vanuatu", "code": "VU"}, + {"name": "Venezuela", "code": "VE"}, + {"name": "Viet Nam", "code": "VN"}, + {"name": "Virgin Islands, British", "code": "VG"}, + {"name": "Virgin Islands, U.S.", "code": "VI"}, + {"name": "Wallis and Futuna", "code": "WF"}, + {"name": "Western Sahara", "code": "EH"}, + {"name": "Yemen", "code": "YE"}, + {"name": "Zambia", "code": "ZM"}, + {"name": "Zimbabwe", "code": "ZW"} + ] +} \ No newline at end of file diff --git a/src/assets/showcase/data/files-lazy.json b/src/assets/showcase/data/files-lazy.json new file mode 100644 index 00000000000..94f80d0ddd8 --- /dev/null +++ b/src/assets/showcase/data/files-lazy.json @@ -0,0 +1,26 @@ +{ + "data": + [ + { + "label": "Lazy Node 0", + "data": "Node 0", + "expandedIcon": "fa-folder-open", + "collapsedIcon": "fa-folder", + "leaf": false + }, + { + "label": "Lazy Node 1", + "data": "Node 1", + "expandedIcon": "fa-folder-open", + "collapsedIcon": "fa-folder", + "leaf": false + }, + { + "label": "Lazy Node 1", + "data": "Node 2", + "expandedIcon": "fa-folder-open", + "collapsedIcon": "fa-folder", + "leaf": false + } + ] +} \ No newline at end of file diff --git a/src/assets/showcase/data/files.json b/src/assets/showcase/data/files.json new file mode 100644 index 00000000000..ca851f814f9 --- /dev/null +++ b/src/assets/showcase/data/files.json @@ -0,0 +1,51 @@ +{ + "data": + [ + { + "label": "Documents", + "data": "Documents Folder", + "expandedIcon": "fa-folder-open", + "collapsedIcon": "fa-folder", + "children": [{ + "label": "Work", + "data": "Work Folder", + "expandedIcon": "fa-folder-open", + "collapsedIcon": "fa-folder", + "children": [{"label": "Expenses.doc", "icon": "fa-file-word-o", "data": "Expenses Document"}, {"label": "Resume.doc", "icon": "fa-file-word-o", "data": "Resume Document"}] + }, + { + "label": "Home", + "data": "Home Folder", + "expandedIcon": "fa-folder-open", + "collapsedIcon": "fa-folder", + "children": [{"label": "Invoices.txt", "icon": "fa-file-word-o", "data": "Invoices for this month"}] + }] + }, + { + "label": "Pictures", + "data": "Pictures Folder", + "expandedIcon": "fa-folder-open", + "collapsedIcon": "fa-folder", + "children": [ + {"label": "barcelona.jpg", "icon": "fa-file-image-o", "data": "Barcelona Photo"}, + {"label": "logo.jpg", "icon": "fa-file-image-o", "data": "PrimeFaces Logo"}, + {"label": "primeui.png", "icon": "fa-file-image-o", "data": "PrimeUI Logo"}] + }, + { + "label": "Movies", + "data": "Movies Folder", + "expandedIcon": "fa-folder-open", + "collapsedIcon": "fa-folder", + "children": [{ + "label": "Al Pacino", + "data": "Pacino Movies", + "children": [{"label": "Scarface", "icon": "fa-file-video-o", "data": "Scarface Movie"}, {"label": "Serpico", "icon": "fa-file-video-o", "data": "Serpico Movie"}] + }, + { + "label": "Robert De Niro", + "data": "De Niro Movies", + "children": [{"label": "Goodfellas", "icon": "fa-file-video-o", "data": "Goodfellas Movie"}, {"label": "Untouchables", "icon": "fa-file-video-o", "data": "Untouchables Movie"}] + }] + } + ] +} \ No newline at end of file diff --git a/src/assets/showcase/data/filesystem-lazy.json b/src/assets/showcase/data/filesystem-lazy.json new file mode 100644 index 00000000000..f9a2c3a5f54 --- /dev/null +++ b/src/assets/showcase/data/filesystem-lazy.json @@ -0,0 +1,21 @@ +{ + "data": + [ + { + "data":{ + "name":"Lazy Folder 0", + "size":"75kb", + "type":"Folder" + }, + "leaf": false + }, + { + "data":{ + "name":"Lazy Folder 1", + "size":"150kb", + "type":"Folder" + }, + "leaf": false + } + ] +} \ No newline at end of file diff --git a/src/assets/showcase/data/filesystem.json b/src/assets/showcase/data/filesystem.json new file mode 100644 index 00000000000..5183be8b489 --- /dev/null +++ b/src/assets/showcase/data/filesystem.json @@ -0,0 +1,83 @@ +{ + "data": + [ + { + "data":{ + "name":"Documents", + "size":"75kb", + "type":"Folder" + }, + "children":[ + { + "data":{ + "name":"Work", + "size":"55kb", + "type":"Folder" + }, + "children":[ + { + "data":{ + "name":"Expenses.doc", + "size":"30kb", + "type":"Document" + } + }, + { + "data":{ + "name":"Resume.doc", + "size":"25kb", + "type":"Resume" + } + } + ] + }, + { + "data":{ + "name":"Home", + "size":"20kb", + "type":"Folder" + }, + "children":[ + { + "data":{ + "name":"Invoices", + "size":"20kb", + "type":"Text" + } + } + ] + } + ] + }, + { + "data":{ + "name":"Pictures", + "size":"150kb", + "type":"Folder" + }, + "children":[ + { + "data":{ + "name":"barcelona.jpg", + "size":"90kb", + "type":"Picture" + } + }, + { + "data":{ + "name":"primeui.png", + "size":"30kb", + "type":"Picture" + } + }, + { + "data":{ + "name":"optimus.jpg", + "size":"30kb", + "type":"Picture" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assets/showcase/data/scheduleevents.json b/src/assets/showcase/data/scheduleevents.json new file mode 100644 index 00000000000..4b7d64037c6 --- /dev/null +++ b/src/assets/showcase/data/scheduleevents.json @@ -0,0 +1,68 @@ +{ + "data": [ + { + "id": 1, + "title": "All Day Event", + "start": "2017-02-01" + }, + { + "id": 2, + "title": "Long Event", + "start": "2017-02-07", + "end": "2017-02-10" + }, + { + "id": 3, + "title": "Repeating Event", + "start": "2017-02-09T16:00:00" + }, + { + "id": 4, + "title": "Repeating Event", + "start": "2017-02-16T16:00:00" + }, + { + "id": 5, + "title": "Conference", + "start": "2017-02-11", + "end": "2017-02-13" + }, + { + "id": 6, + "title": "Meeting", + "start": "2017-02-12T10:30:00", + "end": "2017-02-12T12:30:00" + }, + { + "id": 7, + "title": "Lunch", + "start": "2017-02-12T12:00:00" + }, + { + "id": 8, + "title": "Meeting", + "start": "2017-02-12T14:30:00" + }, + { + "id": 9, + "title": "Happy Hour", + "start": "2017-02-12T17:30:00" + }, + { + "id": 10, + "title": "Dinner", + "start": "2017-02-12T20:00:00" + }, + { + "id": 11, + "title": "Birthday Party", + "start": "2017-02-13T07:00:00" + }, + { + "id": 12, + "title": "Click for Google", + "url": "http://google.com/", + "start": "2017-02-28" + } + ] +} \ No newline at end of file diff --git a/src/assets/showcase/favicon/android-icon-144x144.png b/src/assets/showcase/favicon/android-icon-144x144.png new file mode 100644 index 00000000000..ea6d090b869 Binary files /dev/null and b/src/assets/showcase/favicon/android-icon-144x144.png differ diff --git a/src/assets/showcase/favicon/android-icon-192x192.png b/src/assets/showcase/favicon/android-icon-192x192.png new file mode 100644 index 00000000000..6d926e9e2b9 Binary files /dev/null and b/src/assets/showcase/favicon/android-icon-192x192.png differ diff --git a/src/assets/showcase/favicon/android-icon-36x36.png b/src/assets/showcase/favicon/android-icon-36x36.png new file mode 100644 index 00000000000..47120fa007d Binary files /dev/null and b/src/assets/showcase/favicon/android-icon-36x36.png differ diff --git a/src/assets/showcase/favicon/android-icon-48x48.png b/src/assets/showcase/favicon/android-icon-48x48.png new file mode 100644 index 00000000000..8969b7d5878 Binary files /dev/null and b/src/assets/showcase/favicon/android-icon-48x48.png differ diff --git a/src/assets/showcase/favicon/android-icon-72x72.png b/src/assets/showcase/favicon/android-icon-72x72.png new file mode 100644 index 00000000000..1bdeb512194 Binary files /dev/null and b/src/assets/showcase/favicon/android-icon-72x72.png differ diff --git a/src/assets/showcase/favicon/android-icon-96x96.png b/src/assets/showcase/favicon/android-icon-96x96.png new file mode 100644 index 00000000000..c3b3afea0ca Binary files /dev/null and b/src/assets/showcase/favicon/android-icon-96x96.png differ diff --git a/src/assets/showcase/favicon/apple-icon-114x114.png b/src/assets/showcase/favicon/apple-icon-114x114.png new file mode 100644 index 00000000000..6a8bab12d9b Binary files /dev/null and b/src/assets/showcase/favicon/apple-icon-114x114.png differ diff --git a/src/assets/showcase/favicon/apple-icon-120x120.png b/src/assets/showcase/favicon/apple-icon-120x120.png new file mode 100644 index 00000000000..42c3ca97870 Binary files /dev/null and b/src/assets/showcase/favicon/apple-icon-120x120.png differ diff --git a/src/assets/showcase/favicon/apple-icon-144x144.png b/src/assets/showcase/favicon/apple-icon-144x144.png new file mode 100644 index 00000000000..ea6d090b869 Binary files /dev/null and b/src/assets/showcase/favicon/apple-icon-144x144.png differ diff --git a/src/assets/showcase/favicon/apple-icon-152x152.png b/src/assets/showcase/favicon/apple-icon-152x152.png new file mode 100644 index 00000000000..deceb1c4eec Binary files /dev/null and b/src/assets/showcase/favicon/apple-icon-152x152.png differ diff --git a/src/assets/showcase/favicon/apple-icon-180x180.png b/src/assets/showcase/favicon/apple-icon-180x180.png new file mode 100644 index 00000000000..a321d9a9f9a Binary files /dev/null and b/src/assets/showcase/favicon/apple-icon-180x180.png differ diff --git a/src/assets/showcase/favicon/apple-icon-57x57.png b/src/assets/showcase/favicon/apple-icon-57x57.png new file mode 100644 index 00000000000..c4aad60ea81 Binary files /dev/null and b/src/assets/showcase/favicon/apple-icon-57x57.png differ diff --git a/src/assets/showcase/favicon/apple-icon-60x60.png b/src/assets/showcase/favicon/apple-icon-60x60.png new file mode 100644 index 00000000000..dc57520cc00 Binary files /dev/null and b/src/assets/showcase/favicon/apple-icon-60x60.png differ diff --git a/src/assets/showcase/favicon/apple-icon-72x72.png b/src/assets/showcase/favicon/apple-icon-72x72.png new file mode 100644 index 00000000000..1bdeb512194 Binary files /dev/null and b/src/assets/showcase/favicon/apple-icon-72x72.png differ diff --git a/src/assets/showcase/favicon/apple-icon-76x76.png b/src/assets/showcase/favicon/apple-icon-76x76.png new file mode 100644 index 00000000000..3efaa9fbb75 Binary files /dev/null and b/src/assets/showcase/favicon/apple-icon-76x76.png differ diff --git a/src/assets/showcase/favicon/apple-icon-precomposed.png b/src/assets/showcase/favicon/apple-icon-precomposed.png new file mode 100644 index 00000000000..2cbc1863857 Binary files /dev/null and b/src/assets/showcase/favicon/apple-icon-precomposed.png differ diff --git a/src/assets/showcase/favicon/apple-icon.png b/src/assets/showcase/favicon/apple-icon.png new file mode 100644 index 00000000000..2cbc1863857 Binary files /dev/null and b/src/assets/showcase/favicon/apple-icon.png differ diff --git a/src/assets/showcase/favicon/browserconfig.xml b/src/assets/showcase/favicon/browserconfig.xml new file mode 100644 index 00000000000..c5541482230 --- /dev/null +++ b/src/assets/showcase/favicon/browserconfig.xml @@ -0,0 +1,2 @@ + +#ffffff \ No newline at end of file diff --git a/src/assets/showcase/favicon/favicon-16x16.png b/src/assets/showcase/favicon/favicon-16x16.png new file mode 100644 index 00000000000..4ee7b992d6a Binary files /dev/null and b/src/assets/showcase/favicon/favicon-16x16.png differ diff --git a/src/assets/showcase/favicon/favicon-32x32.png b/src/assets/showcase/favicon/favicon-32x32.png new file mode 100644 index 00000000000..c41758af4a9 Binary files /dev/null and b/src/assets/showcase/favicon/favicon-32x32.png differ diff --git a/src/assets/showcase/favicon/favicon-96x96.png b/src/assets/showcase/favicon/favicon-96x96.png new file mode 100644 index 00000000000..c3b3afea0ca Binary files /dev/null and b/src/assets/showcase/favicon/favicon-96x96.png differ diff --git a/src/assets/showcase/favicon/favicon.ico b/src/assets/showcase/favicon/favicon.ico new file mode 100644 index 00000000000..092ffe8cc7f Binary files /dev/null and b/src/assets/showcase/favicon/favicon.ico differ diff --git a/src/assets/showcase/favicon/manifest.json b/src/assets/showcase/favicon/manifest.json new file mode 100644 index 00000000000..013d4a6a533 --- /dev/null +++ b/src/assets/showcase/favicon/manifest.json @@ -0,0 +1,41 @@ +{ + "name": "App", + "icons": [ + { + "src": "\/android-icon-36x36.png", + "sizes": "36x36", + "type": "image\/png", + "density": "0.75" + }, + { + "src": "\/android-icon-48x48.png", + "sizes": "48x48", + "type": "image\/png", + "density": "1.0" + }, + { + "src": "\/android-icon-72x72.png", + "sizes": "72x72", + "type": "image\/png", + "density": "1.5" + }, + { + "src": "\/android-icon-96x96.png", + "sizes": "96x96", + "type": "image\/png", + "density": "2.0" + }, + { + "src": "\/android-icon-144x144.png", + "sizes": "144x144", + "type": "image\/png", + "density": "3.0" + }, + { + "src": "\/android-icon-192x192.png", + "sizes": "192x192", + "type": "image\/png", + "density": "4.0" + } + ] +} \ No newline at end of file diff --git a/src/assets/showcase/favicon/ms-icon-144x144.png b/src/assets/showcase/favicon/ms-icon-144x144.png new file mode 100644 index 00000000000..ea6d090b869 Binary files /dev/null and b/src/assets/showcase/favicon/ms-icon-144x144.png differ diff --git a/src/assets/showcase/favicon/ms-icon-150x150.png b/src/assets/showcase/favicon/ms-icon-150x150.png new file mode 100644 index 00000000000..e733fb8102a Binary files /dev/null and b/src/assets/showcase/favicon/ms-icon-150x150.png differ diff --git a/src/assets/showcase/favicon/ms-icon-310x310.png b/src/assets/showcase/favicon/ms-icon-310x310.png new file mode 100644 index 00000000000..c3cf7dd0b20 Binary files /dev/null and b/src/assets/showcase/favicon/ms-icon-310x310.png differ diff --git a/src/assets/showcase/favicon/ms-icon-70x70.png b/src/assets/showcase/favicon/ms-icon-70x70.png new file mode 100644 index 00000000000..c0d2af326b0 Binary files /dev/null and b/src/assets/showcase/favicon/ms-icon-70x70.png differ diff --git a/src/assets/showcase/fonts/roboto-v15-latin-regular.eot b/src/assets/showcase/fonts/roboto-v15-latin-regular.eot new file mode 100644 index 00000000000..d26bc8f519b Binary files /dev/null and b/src/assets/showcase/fonts/roboto-v15-latin-regular.eot differ diff --git a/src/assets/showcase/fonts/roboto-v15-latin-regular.svg b/src/assets/showcase/fonts/roboto-v15-latin-regular.svg new file mode 100644 index 00000000000..ed55c105d7a --- /dev/null +++ b/src/assets/showcase/fonts/roboto-v15-latin-regular.svg @@ -0,0 +1,308 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/showcase/fonts/roboto-v15-latin-regular.ttf b/src/assets/showcase/fonts/roboto-v15-latin-regular.ttf new file mode 100644 index 00000000000..7b25f3ce940 Binary files /dev/null and b/src/assets/showcase/fonts/roboto-v15-latin-regular.ttf differ diff --git a/src/assets/showcase/fonts/roboto-v15-latin-regular.woff b/src/assets/showcase/fonts/roboto-v15-latin-regular.woff new file mode 100644 index 00000000000..941dfa4bae8 Binary files /dev/null and b/src/assets/showcase/fonts/roboto-v15-latin-regular.woff differ diff --git a/src/assets/showcase/fonts/roboto-v15-latin-regular.woff2 b/src/assets/showcase/fonts/roboto-v15-latin-regular.woff2 new file mode 100644 index 00000000000..120796bb719 Binary files /dev/null and b/src/assets/showcase/fonts/roboto-v15-latin-regular.woff2 differ diff --git a/src/assets/showcase/images/ajaxFramework.svg b/src/assets/showcase/images/ajaxFramework.svg new file mode 100644 index 00000000000..e97573496cf --- /dev/null +++ b/src/assets/showcase/images/ajaxFramework.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/showcase/images/angularbeers.png b/src/assets/showcase/images/angularbeers.png new file mode 100644 index 00000000000..86e266dcec9 Binary files /dev/null and b/src/assets/showcase/images/angularbeers.png differ diff --git a/src/assets/showcase/images/bootstrap.png b/src/assets/showcase/images/bootstrap.png new file mode 100644 index 00000000000..8ac750bf24f Binary files /dev/null and b/src/assets/showcase/images/bootstrap.png differ diff --git a/src/assets/showcase/images/btnArrow.svg b/src/assets/showcase/images/btnArrow.svg new file mode 100644 index 00000000000..a8dd7ce92c8 --- /dev/null +++ b/src/assets/showcase/images/btnArrow.svg @@ -0,0 +1,8 @@ + + + + + + diff --git a/src/assets/showcase/images/btnDocumenticon.svg b/src/assets/showcase/images/btnDocumenticon.svg new file mode 100644 index 00000000000..578d50ba1df --- /dev/null +++ b/src/assets/showcase/images/btnDocumenticon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + diff --git a/src/assets/showcase/images/color/ajaxCore.svg b/src/assets/showcase/images/color/ajaxCore.svg new file mode 100644 index 00000000000..b09395ff29a --- /dev/null +++ b/src/assets/showcase/images/color/ajaxCore.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + diff --git a/src/assets/showcase/images/community.svg b/src/assets/showcase/images/community.svg new file mode 100644 index 00000000000..0e821c29f65 --- /dev/null +++ b/src/assets/showcase/images/community.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + diff --git a/src/assets/showcase/images/components.svg b/src/assets/showcase/images/components.svg new file mode 100644 index 00000000000..1f14d3053be --- /dev/null +++ b/src/assets/showcase/images/components.svg @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/showcase/images/demo/car/Audi-big.gif b/src/assets/showcase/images/demo/car/Audi-big.gif new file mode 100644 index 00000000000..70ef35a5a7b Binary files /dev/null and b/src/assets/showcase/images/demo/car/Audi-big.gif differ diff --git a/src/assets/showcase/images/demo/car/Audi.gif b/src/assets/showcase/images/demo/car/Audi.gif new file mode 100644 index 00000000000..accceb9a4e2 Binary files /dev/null and b/src/assets/showcase/images/demo/car/Audi.gif differ diff --git a/src/assets/showcase/images/demo/car/BMW-big.gif b/src/assets/showcase/images/demo/car/BMW-big.gif new file mode 100644 index 00000000000..b229d8bd85f Binary files /dev/null and b/src/assets/showcase/images/demo/car/BMW-big.gif differ diff --git a/src/assets/showcase/images/demo/car/BMW.gif b/src/assets/showcase/images/demo/car/BMW.gif new file mode 100644 index 00000000000..ef3de48cbfa Binary files /dev/null and b/src/assets/showcase/images/demo/car/BMW.gif differ diff --git a/src/assets/showcase/images/demo/car/Fiat-big.gif b/src/assets/showcase/images/demo/car/Fiat-big.gif new file mode 100644 index 00000000000..851cc2d3c24 Binary files /dev/null and b/src/assets/showcase/images/demo/car/Fiat-big.gif differ diff --git a/src/assets/showcase/images/demo/car/Fiat.gif b/src/assets/showcase/images/demo/car/Fiat.gif new file mode 100644 index 00000000000..3b41ed37ebe Binary files /dev/null and b/src/assets/showcase/images/demo/car/Fiat.gif differ diff --git a/src/assets/showcase/images/demo/car/Ford-big.gif b/src/assets/showcase/images/demo/car/Ford-big.gif new file mode 100644 index 00000000000..2c52041b73e Binary files /dev/null and b/src/assets/showcase/images/demo/car/Ford-big.gif differ diff --git a/src/assets/showcase/images/demo/car/Ford.gif b/src/assets/showcase/images/demo/car/Ford.gif new file mode 100644 index 00000000000..fbfd1c39db4 Binary files /dev/null and b/src/assets/showcase/images/demo/car/Ford.gif differ diff --git a/src/assets/showcase/images/demo/car/Honda-big.gif b/src/assets/showcase/images/demo/car/Honda-big.gif new file mode 100644 index 00000000000..87917d9b028 Binary files /dev/null and b/src/assets/showcase/images/demo/car/Honda-big.gif differ diff --git a/src/assets/showcase/images/demo/car/Honda.gif b/src/assets/showcase/images/demo/car/Honda.gif new file mode 100644 index 00000000000..58e7a4f7bf2 Binary files /dev/null and b/src/assets/showcase/images/demo/car/Honda.gif differ diff --git a/src/assets/showcase/images/demo/car/Jaguar-big.gif b/src/assets/showcase/images/demo/car/Jaguar-big.gif new file mode 100644 index 00000000000..30dbe2a93c2 Binary files /dev/null and b/src/assets/showcase/images/demo/car/Jaguar-big.gif differ diff --git a/src/assets/showcase/images/demo/car/Jaguar.gif b/src/assets/showcase/images/demo/car/Jaguar.gif new file mode 100644 index 00000000000..80937957c5a Binary files /dev/null and b/src/assets/showcase/images/demo/car/Jaguar.gif differ diff --git a/src/assets/showcase/images/demo/car/Mercedes-big.gif b/src/assets/showcase/images/demo/car/Mercedes-big.gif new file mode 100644 index 00000000000..28f903e66e3 Binary files /dev/null and b/src/assets/showcase/images/demo/car/Mercedes-big.gif differ diff --git a/src/assets/showcase/images/demo/car/Mercedes.gif b/src/assets/showcase/images/demo/car/Mercedes.gif new file mode 100644 index 00000000000..2f150bb8445 Binary files /dev/null and b/src/assets/showcase/images/demo/car/Mercedes.gif differ diff --git a/src/assets/showcase/images/demo/car/Renault-big.gif b/src/assets/showcase/images/demo/car/Renault-big.gif new file mode 100644 index 00000000000..a5cd2e71ef6 Binary files /dev/null and b/src/assets/showcase/images/demo/car/Renault-big.gif differ diff --git a/src/assets/showcase/images/demo/car/Renault.gif b/src/assets/showcase/images/demo/car/Renault.gif new file mode 100644 index 00000000000..6b79d678533 Binary files /dev/null and b/src/assets/showcase/images/demo/car/Renault.gif differ diff --git a/src/assets/showcase/images/demo/car/VW-big.gif b/src/assets/showcase/images/demo/car/VW-big.gif new file mode 100644 index 00000000000..573e8213303 Binary files /dev/null and b/src/assets/showcase/images/demo/car/VW-big.gif differ diff --git a/src/assets/showcase/images/demo/car/VW.gif b/src/assets/showcase/images/demo/car/VW.gif new file mode 100644 index 00000000000..d7984c262ee Binary files /dev/null and b/src/assets/showcase/images/demo/car/VW.gif differ diff --git a/src/assets/showcase/images/demo/car/Volvo-big.gif b/src/assets/showcase/images/demo/car/Volvo-big.gif new file mode 100644 index 00000000000..254fbeb9bd2 Binary files /dev/null and b/src/assets/showcase/images/demo/car/Volvo-big.gif differ diff --git a/src/assets/showcase/images/demo/car/Volvo-big_1.gif b/src/assets/showcase/images/demo/car/Volvo-big_1.gif new file mode 100644 index 00000000000..254fbeb9bd2 Binary files /dev/null and b/src/assets/showcase/images/demo/car/Volvo-big_1.gif differ diff --git a/src/assets/showcase/images/demo/car/Volvo.gif b/src/assets/showcase/images/demo/car/Volvo.gif new file mode 100644 index 00000000000..00af6b6188d Binary files /dev/null and b/src/assets/showcase/images/demo/car/Volvo.gif differ diff --git a/src/assets/showcase/images/demo/galleria/galleria1.jpg b/src/assets/showcase/images/demo/galleria/galleria1.jpg new file mode 100755 index 00000000000..15b628cf72a Binary files /dev/null and b/src/assets/showcase/images/demo/galleria/galleria1.jpg differ diff --git a/src/assets/showcase/images/demo/galleria/galleria10.jpg b/src/assets/showcase/images/demo/galleria/galleria10.jpg new file mode 100755 index 00000000000..d7e126a27b1 Binary files /dev/null and b/src/assets/showcase/images/demo/galleria/galleria10.jpg differ diff --git a/src/assets/showcase/images/demo/galleria/galleria11.jpg b/src/assets/showcase/images/demo/galleria/galleria11.jpg new file mode 100755 index 00000000000..57201ce0a18 Binary files /dev/null and b/src/assets/showcase/images/demo/galleria/galleria11.jpg differ diff --git a/src/assets/showcase/images/demo/galleria/galleria12.jpg b/src/assets/showcase/images/demo/galleria/galleria12.jpg new file mode 100755 index 00000000000..760658e5e9b Binary files /dev/null and b/src/assets/showcase/images/demo/galleria/galleria12.jpg differ diff --git a/src/assets/showcase/images/demo/galleria/galleria2.jpg b/src/assets/showcase/images/demo/galleria/galleria2.jpg new file mode 100755 index 00000000000..eb118853107 Binary files /dev/null and b/src/assets/showcase/images/demo/galleria/galleria2.jpg differ diff --git a/src/assets/showcase/images/demo/galleria/galleria3.jpg b/src/assets/showcase/images/demo/galleria/galleria3.jpg new file mode 100755 index 00000000000..47ce93d7e87 Binary files /dev/null and b/src/assets/showcase/images/demo/galleria/galleria3.jpg differ diff --git a/src/assets/showcase/images/demo/galleria/galleria4.jpg b/src/assets/showcase/images/demo/galleria/galleria4.jpg new file mode 100755 index 00000000000..84ee1277930 Binary files /dev/null and b/src/assets/showcase/images/demo/galleria/galleria4.jpg differ diff --git a/src/assets/showcase/images/demo/galleria/galleria5.jpg b/src/assets/showcase/images/demo/galleria/galleria5.jpg new file mode 100755 index 00000000000..a0215c25352 Binary files /dev/null and b/src/assets/showcase/images/demo/galleria/galleria5.jpg differ diff --git a/src/assets/showcase/images/demo/galleria/galleria6.jpg b/src/assets/showcase/images/demo/galleria/galleria6.jpg new file mode 100755 index 00000000000..cf2396b28ec Binary files /dev/null and b/src/assets/showcase/images/demo/galleria/galleria6.jpg differ diff --git a/src/assets/showcase/images/demo/galleria/galleria7.jpg b/src/assets/showcase/images/demo/galleria/galleria7.jpg new file mode 100755 index 00000000000..a7d0a67f2d8 Binary files /dev/null and b/src/assets/showcase/images/demo/galleria/galleria7.jpg differ diff --git a/src/assets/showcase/images/demo/galleria/galleria8.jpg b/src/assets/showcase/images/demo/galleria/galleria8.jpg new file mode 100755 index 00000000000..5d6764a2eba Binary files /dev/null and b/src/assets/showcase/images/demo/galleria/galleria8.jpg differ diff --git a/src/assets/showcase/images/demo/galleria/galleria9.jpg b/src/assets/showcase/images/demo/galleria/galleria9.jpg new file mode 100755 index 00000000000..b39b46c7bdf Binary files /dev/null and b/src/assets/showcase/images/demo/galleria/galleria9.jpg differ diff --git a/src/assets/showcase/images/demo/sopranos/sopranos1.jpg b/src/assets/showcase/images/demo/sopranos/sopranos1.jpg new file mode 100755 index 00000000000..024f49cb117 Binary files /dev/null and b/src/assets/showcase/images/demo/sopranos/sopranos1.jpg differ diff --git a/src/assets/showcase/images/demo/sopranos/sopranos1_small.jpg b/src/assets/showcase/images/demo/sopranos/sopranos1_small.jpg new file mode 100755 index 00000000000..443d5655a36 Binary files /dev/null and b/src/assets/showcase/images/demo/sopranos/sopranos1_small.jpg differ diff --git a/src/assets/showcase/images/demo/sopranos/sopranos2.jpg b/src/assets/showcase/images/demo/sopranos/sopranos2.jpg new file mode 100755 index 00000000000..fff0038161a Binary files /dev/null and b/src/assets/showcase/images/demo/sopranos/sopranos2.jpg differ diff --git a/src/assets/showcase/images/demo/sopranos/sopranos2_small.jpg b/src/assets/showcase/images/demo/sopranos/sopranos2_small.jpg new file mode 100755 index 00000000000..a5287bd7989 Binary files /dev/null and b/src/assets/showcase/images/demo/sopranos/sopranos2_small.jpg differ diff --git a/src/assets/showcase/images/demo/sopranos/sopranos3.jpg b/src/assets/showcase/images/demo/sopranos/sopranos3.jpg new file mode 100755 index 00000000000..3259ad7838a Binary files /dev/null and b/src/assets/showcase/images/demo/sopranos/sopranos3.jpg differ diff --git a/src/assets/showcase/images/demo/sopranos/sopranos3_small.jpg b/src/assets/showcase/images/demo/sopranos/sopranos3_small.jpg new file mode 100755 index 00000000000..850f4abab7a Binary files /dev/null and b/src/assets/showcase/images/demo/sopranos/sopranos3_small.jpg differ diff --git a/src/assets/showcase/images/demo/sopranos/sopranos4.jpg b/src/assets/showcase/images/demo/sopranos/sopranos4.jpg new file mode 100755 index 00000000000..ebac372deb5 Binary files /dev/null and b/src/assets/showcase/images/demo/sopranos/sopranos4.jpg differ diff --git a/src/assets/showcase/images/demo/sopranos/sopranos4_small.jpg b/src/assets/showcase/images/demo/sopranos/sopranos4_small.jpg new file mode 100755 index 00000000000..29f3b30aae3 Binary files /dev/null and b/src/assets/showcase/images/demo/sopranos/sopranos4_small.jpg differ diff --git a/src/assets/showcase/images/demo/themes/afterdark.png b/src/assets/showcase/images/demo/themes/afterdark.png new file mode 100755 index 00000000000..087b705c67b Binary files /dev/null and b/src/assets/showcase/images/demo/themes/afterdark.png differ diff --git a/src/assets/showcase/images/demo/themes/afternoon.png b/src/assets/showcase/images/demo/themes/afternoon.png new file mode 100755 index 00000000000..3c780417673 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/afternoon.png differ diff --git a/src/assets/showcase/images/demo/themes/afterwork.png b/src/assets/showcase/images/demo/themes/afterwork.png new file mode 100755 index 00000000000..9feedbb5ed6 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/afterwork.png differ diff --git a/src/assets/showcase/images/demo/themes/aristo.png b/src/assets/showcase/images/demo/themes/aristo.png new file mode 100755 index 00000000000..ce0b369e234 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/aristo.png differ diff --git a/src/assets/showcase/images/demo/themes/black-tie.png b/src/assets/showcase/images/demo/themes/black-tie.png new file mode 100755 index 00000000000..33b59fe778f Binary files /dev/null and b/src/assets/showcase/images/demo/themes/black-tie.png differ diff --git a/src/assets/showcase/images/demo/themes/blitzer.png b/src/assets/showcase/images/demo/themes/blitzer.png new file mode 100755 index 00000000000..0de5ea041f1 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/blitzer.png differ diff --git a/src/assets/showcase/images/demo/themes/bluesky.png b/src/assets/showcase/images/demo/themes/bluesky.png new file mode 100755 index 00000000000..3c7d8fb4449 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/bluesky.png differ diff --git a/src/assets/showcase/images/demo/themes/bootstrap.png b/src/assets/showcase/images/demo/themes/bootstrap.png new file mode 100755 index 00000000000..842ed2af357 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/bootstrap.png differ diff --git a/src/assets/showcase/images/demo/themes/casablanca.png b/src/assets/showcase/images/demo/themes/casablanca.png new file mode 100755 index 00000000000..6986242613b Binary files /dev/null and b/src/assets/showcase/images/demo/themes/casablanca.png differ diff --git a/src/assets/showcase/images/demo/themes/cruze.png b/src/assets/showcase/images/demo/themes/cruze.png new file mode 100755 index 00000000000..233b755673b Binary files /dev/null and b/src/assets/showcase/images/demo/themes/cruze.png differ diff --git a/src/assets/showcase/images/demo/themes/cupertino.png b/src/assets/showcase/images/demo/themes/cupertino.png new file mode 100755 index 00000000000..a82a0c897f5 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/cupertino.png differ diff --git a/src/assets/showcase/images/demo/themes/dark-hive.png b/src/assets/showcase/images/demo/themes/dark-hive.png new file mode 100755 index 00000000000..c6db40a5c2e Binary files /dev/null and b/src/assets/showcase/images/demo/themes/dark-hive.png differ diff --git a/src/assets/showcase/images/demo/themes/dot-luv.png b/src/assets/showcase/images/demo/themes/dot-luv.png new file mode 100755 index 00000000000..b03472b8b93 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/dot-luv.png differ diff --git a/src/assets/showcase/images/demo/themes/eggplant.png b/src/assets/showcase/images/demo/themes/eggplant.png new file mode 100755 index 00000000000..cd5b485e954 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/eggplant.png differ diff --git a/src/assets/showcase/images/demo/themes/excite-bike.png b/src/assets/showcase/images/demo/themes/excite-bike.png new file mode 100755 index 00000000000..3e1ec9c78af Binary files /dev/null and b/src/assets/showcase/images/demo/themes/excite-bike.png differ diff --git a/src/assets/showcase/images/demo/themes/flick.png b/src/assets/showcase/images/demo/themes/flick.png new file mode 100755 index 00000000000..61f67263ed9 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/flick.png differ diff --git a/src/assets/showcase/images/demo/themes/glass-x.png b/src/assets/showcase/images/demo/themes/glass-x.png new file mode 100755 index 00000000000..8260e019f08 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/glass-x.png differ diff --git a/src/assets/showcase/images/demo/themes/home.png b/src/assets/showcase/images/demo/themes/home.png new file mode 100755 index 00000000000..b73f63752ae Binary files /dev/null and b/src/assets/showcase/images/demo/themes/home.png differ diff --git a/src/assets/showcase/images/demo/themes/hot-sneaks.png b/src/assets/showcase/images/demo/themes/hot-sneaks.png new file mode 100755 index 00000000000..c2a2e8a1dc2 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/hot-sneaks.png differ diff --git a/src/assets/showcase/images/demo/themes/humanity.png b/src/assets/showcase/images/demo/themes/humanity.png new file mode 100755 index 00000000000..b66b5f14c47 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/humanity.png differ diff --git a/src/assets/showcase/images/demo/themes/le-frog.png b/src/assets/showcase/images/demo/themes/le-frog.png new file mode 100755 index 00000000000..fc95e6b844f Binary files /dev/null and b/src/assets/showcase/images/demo/themes/le-frog.png differ diff --git a/src/assets/showcase/images/demo/themes/midnight.png b/src/assets/showcase/images/demo/themes/midnight.png new file mode 100755 index 00000000000..dc5efcc3db4 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/midnight.png differ diff --git a/src/assets/showcase/images/demo/themes/mint-choc.png b/src/assets/showcase/images/demo/themes/mint-choc.png new file mode 100755 index 00000000000..1eae9dedcbb Binary files /dev/null and b/src/assets/showcase/images/demo/themes/mint-choc.png differ diff --git a/src/assets/showcase/images/demo/themes/overcast.png b/src/assets/showcase/images/demo/themes/overcast.png new file mode 100755 index 00000000000..814a64f1ef0 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/overcast.png differ diff --git a/src/assets/showcase/images/demo/themes/pepper-grinder.png b/src/assets/showcase/images/demo/themes/pepper-grinder.png new file mode 100755 index 00000000000..26a4b7658ef Binary files /dev/null and b/src/assets/showcase/images/demo/themes/pepper-grinder.png differ diff --git a/src/assets/showcase/images/demo/themes/redmond.png b/src/assets/showcase/images/demo/themes/redmond.png new file mode 100755 index 00000000000..858e88fac6e Binary files /dev/null and b/src/assets/showcase/images/demo/themes/redmond.png differ diff --git a/src/assets/showcase/images/demo/themes/rocket.png b/src/assets/showcase/images/demo/themes/rocket.png new file mode 100755 index 00000000000..fb2725eb77f Binary files /dev/null and b/src/assets/showcase/images/demo/themes/rocket.png differ diff --git a/src/assets/showcase/images/demo/themes/sam.png b/src/assets/showcase/images/demo/themes/sam.png new file mode 100755 index 00000000000..f91ea264cab Binary files /dev/null and b/src/assets/showcase/images/demo/themes/sam.png differ diff --git a/src/assets/showcase/images/demo/themes/smoothness.png b/src/assets/showcase/images/demo/themes/smoothness.png new file mode 100755 index 00000000000..a30f3186529 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/smoothness.png differ diff --git a/src/assets/showcase/images/demo/themes/south-street.png b/src/assets/showcase/images/demo/themes/south-street.png new file mode 100755 index 00000000000..f2782006366 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/south-street.png differ diff --git a/src/assets/showcase/images/demo/themes/start.png b/src/assets/showcase/images/demo/themes/start.png new file mode 100755 index 00000000000..02101ea4460 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/start.png differ diff --git a/src/assets/showcase/images/demo/themes/sunny.png b/src/assets/showcase/images/demo/themes/sunny.png new file mode 100755 index 00000000000..541d6f09dcc Binary files /dev/null and b/src/assets/showcase/images/demo/themes/sunny.png differ diff --git a/src/assets/showcase/images/demo/themes/swanky-purse.png b/src/assets/showcase/images/demo/themes/swanky-purse.png new file mode 100755 index 00000000000..2c2094c0a7d Binary files /dev/null and b/src/assets/showcase/images/demo/themes/swanky-purse.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/afterdark.png b/src/assets/showcase/images/demo/themes/themesIndex/afterdark.png new file mode 100755 index 00000000000..e7027c4d584 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/afterdark.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/afternoon.png b/src/assets/showcase/images/demo/themes/themesIndex/afternoon.png new file mode 100755 index 00000000000..9b1c3b648db Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/afternoon.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/afterwork.png b/src/assets/showcase/images/demo/themes/themesIndex/afterwork.png new file mode 100755 index 00000000000..e4c3f362c29 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/afterwork.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/aristo.png b/src/assets/showcase/images/demo/themes/themesIndex/aristo.png new file mode 100755 index 00000000000..33f1d03a3c6 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/aristo.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/black-tie.png b/src/assets/showcase/images/demo/themes/themesIndex/black-tie.png new file mode 100755 index 00000000000..b9bfd3fb31b Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/black-tie.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/blitzer.png b/src/assets/showcase/images/demo/themes/themesIndex/blitzer.png new file mode 100755 index 00000000000..8ae2089ffc0 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/blitzer.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/bluesky.png b/src/assets/showcase/images/demo/themes/themesIndex/bluesky.png new file mode 100755 index 00000000000..5d0e84c2578 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/bluesky.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/bootstrap.png b/src/assets/showcase/images/demo/themes/themesIndex/bootstrap.png new file mode 100755 index 00000000000..be4c3feaf62 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/bootstrap.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/casablanca.png b/src/assets/showcase/images/demo/themes/themesIndex/casablanca.png new file mode 100755 index 00000000000..e7f8c43763a Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/casablanca.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/cruze.png b/src/assets/showcase/images/demo/themes/themesIndex/cruze.png new file mode 100755 index 00000000000..296b9d5ba15 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/cruze.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/cupertino.png b/src/assets/showcase/images/demo/themes/themesIndex/cupertino.png new file mode 100755 index 00000000000..f26a1dc6e15 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/cupertino.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/dark-hive.png b/src/assets/showcase/images/demo/themes/themesIndex/dark-hive.png new file mode 100755 index 00000000000..9e81a8a7c99 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/dark-hive.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/delta.png b/src/assets/showcase/images/demo/themes/themesIndex/delta.png new file mode 100755 index 00000000000..a58b71bdeff Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/delta.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/dot-luv.png b/src/assets/showcase/images/demo/themes/themesIndex/dot-luv.png new file mode 100755 index 00000000000..ca57d670488 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/dot-luv.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/eggplant.png b/src/assets/showcase/images/demo/themes/themesIndex/eggplant.png new file mode 100755 index 00000000000..96fe5131b99 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/eggplant.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/excite-bike.png b/src/assets/showcase/images/demo/themes/themesIndex/excite-bike.png new file mode 100755 index 00000000000..744bd5cf3c3 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/excite-bike.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/flick.png b/src/assets/showcase/images/demo/themes/themesIndex/flick.png new file mode 100755 index 00000000000..5af6ee657c7 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/flick.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/glass-x.png b/src/assets/showcase/images/demo/themes/themesIndex/glass-x.png new file mode 100755 index 00000000000..0e2cf745745 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/glass-x.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/home.png b/src/assets/showcase/images/demo/themes/themesIndex/home.png new file mode 100755 index 00000000000..b46a19e556a Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/home.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/hot-sneaks.png b/src/assets/showcase/images/demo/themes/themesIndex/hot-sneaks.png new file mode 100755 index 00000000000..8eaf622bf8c Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/hot-sneaks.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/humanity.png b/src/assets/showcase/images/demo/themes/themesIndex/humanity.png new file mode 100755 index 00000000000..5e79c3cb0a1 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/humanity.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/le-frog.png b/src/assets/showcase/images/demo/themes/themesIndex/le-frog.png new file mode 100755 index 00000000000..d09f523fc39 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/le-frog.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/midnight.png b/src/assets/showcase/images/demo/themes/themesIndex/midnight.png new file mode 100755 index 00000000000..e9d253fcdf8 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/midnight.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/mint-choc.png b/src/assets/showcase/images/demo/themes/themesIndex/mint-choc.png new file mode 100755 index 00000000000..bc0b6227e06 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/mint-choc.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/overcast.png b/src/assets/showcase/images/demo/themes/themesIndex/overcast.png new file mode 100755 index 00000000000..7e7cea83e48 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/overcast.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/pepper-grinder.png b/src/assets/showcase/images/demo/themes/themesIndex/pepper-grinder.png new file mode 100755 index 00000000000..e7c5e593dc5 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/pepper-grinder.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/redmond.png b/src/assets/showcase/images/demo/themes/themesIndex/redmond.png new file mode 100755 index 00000000000..34fa1fb6e69 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/redmond.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/rocket.png b/src/assets/showcase/images/demo/themes/themesIndex/rocket.png new file mode 100755 index 00000000000..a47868d8a60 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/rocket.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/sam.png b/src/assets/showcase/images/demo/themes/themesIndex/sam.png new file mode 100755 index 00000000000..a691a121cf0 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/sam.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/smoothness.png b/src/assets/showcase/images/demo/themes/themesIndex/smoothness.png new file mode 100755 index 00000000000..5dc8f339120 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/smoothness.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/south-street.png b/src/assets/showcase/images/demo/themes/themesIndex/south-street.png new file mode 100755 index 00000000000..12fec417407 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/south-street.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/start.png b/src/assets/showcase/images/demo/themes/themesIndex/start.png new file mode 100755 index 00000000000..02869edc9f8 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/start.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/sunny.png b/src/assets/showcase/images/demo/themes/themesIndex/sunny.png new file mode 100755 index 00000000000..d810c10e463 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/sunny.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/swanky-purse.png b/src/assets/showcase/images/demo/themes/themesIndex/swanky-purse.png new file mode 100755 index 00000000000..7f4bd56a82f Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/swanky-purse.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/trontastic.png b/src/assets/showcase/images/demo/themes/themesIndex/trontastic.png new file mode 100755 index 00000000000..b357d0b6618 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/trontastic.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/ui-darkness.png b/src/assets/showcase/images/demo/themes/themesIndex/ui-darkness.png new file mode 100755 index 00000000000..30c060a4703 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/ui-darkness.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/ui-lightness.png b/src/assets/showcase/images/demo/themes/themesIndex/ui-lightness.png new file mode 100755 index 00000000000..c04c09c75bb Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/ui-lightness.png differ diff --git a/src/assets/showcase/images/demo/themes/themesIndex/vader.png b/src/assets/showcase/images/demo/themes/themesIndex/vader.png new file mode 100755 index 00000000000..e7819e4fc2e Binary files /dev/null and b/src/assets/showcase/images/demo/themes/themesIndex/vader.png differ diff --git a/src/assets/showcase/images/demo/themes/trontastic.png b/src/assets/showcase/images/demo/themes/trontastic.png new file mode 100755 index 00000000000..efa6aaeaf8f Binary files /dev/null and b/src/assets/showcase/images/demo/themes/trontastic.png differ diff --git a/src/assets/showcase/images/demo/themes/ui-darkness.png b/src/assets/showcase/images/demo/themes/ui-darkness.png new file mode 100755 index 00000000000..d068579fbdf Binary files /dev/null and b/src/assets/showcase/images/demo/themes/ui-darkness.png differ diff --git a/src/assets/showcase/images/demo/themes/ui-lightness.png b/src/assets/showcase/images/demo/themes/ui-lightness.png new file mode 100755 index 00000000000..a0e19c4520a Binary files /dev/null and b/src/assets/showcase/images/demo/themes/ui-lightness.png differ diff --git a/src/assets/showcase/images/demo/themes/vader.png b/src/assets/showcase/images/demo/themes/vader.png new file mode 100755 index 00000000000..f109d07b027 Binary files /dev/null and b/src/assets/showcase/images/demo/themes/vader.png differ diff --git a/src/assets/showcase/images/desktop.svg b/src/assets/showcase/images/desktop.svg new file mode 100644 index 00000000000..769cc565c3d --- /dev/null +++ b/src/assets/showcase/images/desktop.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + diff --git a/src/assets/showcase/images/download.svg b/src/assets/showcase/images/download.svg new file mode 100644 index 00000000000..180a84ee594 --- /dev/null +++ b/src/assets/showcase/images/download.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + diff --git a/src/assets/showcase/images/keynote.png b/src/assets/showcase/images/keynote.png new file mode 100644 index 00000000000..d4237c97a17 Binary files /dev/null and b/src/assets/showcase/images/keynote.png differ diff --git a/src/assets/showcase/images/layouts.svg b/src/assets/showcase/images/layouts.svg new file mode 100644 index 00000000000..1141e9b4166 --- /dev/null +++ b/src/assets/showcase/images/layouts.svg @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/showcase/images/layouts/atlantis-ng.png b/src/assets/showcase/images/layouts/atlantis-ng.png new file mode 100644 index 00000000000..03a8abc80e7 Binary files /dev/null and b/src/assets/showcase/images/layouts/atlantis-ng.png differ diff --git a/src/assets/showcase/images/layouts/barcelona-ng.png b/src/assets/showcase/images/layouts/barcelona-ng.png new file mode 100644 index 00000000000..e9f021635c0 Binary files /dev/null and b/src/assets/showcase/images/layouts/barcelona-ng.png differ diff --git a/src/assets/showcase/images/layouts/morpheus-ng.png b/src/assets/showcase/images/layouts/morpheus-ng.png new file mode 100644 index 00000000000..952a267ef95 Binary files /dev/null and b/src/assets/showcase/images/layouts/morpheus-ng.png differ diff --git a/src/assets/showcase/images/layouts/omega-ng.png b/src/assets/showcase/images/layouts/omega-ng.png new file mode 100644 index 00000000000..3eabb287838 Binary files /dev/null and b/src/assets/showcase/images/layouts/omega-ng.png differ diff --git a/src/assets/showcase/images/layouts/paradise-ng.png b/src/assets/showcase/images/layouts/paradise-ng.png new file mode 100644 index 00000000000..b5697a547a6 Binary files /dev/null and b/src/assets/showcase/images/layouts/paradise-ng.png differ diff --git a/src/assets/showcase/images/layouts/poseidon-ng.png b/src/assets/showcase/images/layouts/poseidon-ng.png new file mode 100644 index 00000000000..5e8674b8b36 Binary files /dev/null and b/src/assets/showcase/images/layouts/poseidon-ng.png differ diff --git a/src/assets/showcase/images/layouts/ultima-ng.png b/src/assets/showcase/images/layouts/ultima-ng.png new file mode 100644 index 00000000000..b28475329c1 Binary files /dev/null and b/src/assets/showcase/images/layouts/ultima-ng.png differ diff --git a/src/assets/showcase/images/license.svg b/src/assets/showcase/images/license.svg new file mode 100644 index 00000000000..5c7c1f5bec2 --- /dev/null +++ b/src/assets/showcase/images/license.svg @@ -0,0 +1,230 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/showcase/images/loader.gif b/src/assets/showcase/images/loader.gif new file mode 100644 index 00000000000..39449f0620b Binary files /dev/null and b/src/assets/showcase/images/loader.gif differ diff --git a/src/assets/showcase/images/logo.svg b/src/assets/showcase/images/logo.svg new file mode 100644 index 00000000000..36574aa9244 --- /dev/null +++ b/src/assets/showcase/images/logo.svg @@ -0,0 +1,60 @@ + + + + diff --git a/src/assets/showcase/images/logoBlue.svg b/src/assets/showcase/images/logoBlue.svg new file mode 100644 index 00000000000..d64bc60e3dc --- /dev/null +++ b/src/assets/showcase/images/logoBlue.svg @@ -0,0 +1,60 @@ + + + + diff --git a/src/assets/showcase/images/logoCircuitLines.svg b/src/assets/showcase/images/logoCircuitLines.svg new file mode 100644 index 00000000000..8dd0dc74c82 --- /dev/null +++ b/src/assets/showcase/images/logoCircuitLines.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/showcase/images/logoDark.svg b/src/assets/showcase/images/logoDark.svg new file mode 100644 index 00000000000..6705e64de63 --- /dev/null +++ b/src/assets/showcase/images/logoDark.svg @@ -0,0 +1,60 @@ + + + + diff --git a/src/assets/showcase/images/logos/airbus.png b/src/assets/showcase/images/logos/airbus.png new file mode 100644 index 00000000000..6ad924e968e Binary files /dev/null and b/src/assets/showcase/images/logos/airbus.png differ diff --git a/src/assets/showcase/images/logos/bankofamerica.png b/src/assets/showcase/images/logos/bankofamerica.png new file mode 100644 index 00000000000..1f6ae772742 Binary files /dev/null and b/src/assets/showcase/images/logos/bankofamerica.png differ diff --git a/src/assets/showcase/images/logos/bmw.png b/src/assets/showcase/images/logos/bmw.png new file mode 100644 index 00000000000..a188f58ae3b Binary files /dev/null and b/src/assets/showcase/images/logos/bmw.png differ diff --git a/src/assets/showcase/images/logos/deutschebank.png b/src/assets/showcase/images/logos/deutschebank.png new file mode 100644 index 00000000000..4c4ce232d6d Binary files /dev/null and b/src/assets/showcase/images/logos/deutschebank.png differ diff --git a/src/assets/showcase/images/logos/ebay.png b/src/assets/showcase/images/logos/ebay.png new file mode 100644 index 00000000000..0309e2874cf Binary files /dev/null and b/src/assets/showcase/images/logos/ebay.png differ diff --git a/src/assets/showcase/images/logos/ford.png b/src/assets/showcase/images/logos/ford.png new file mode 100644 index 00000000000..734c66c306a Binary files /dev/null and b/src/assets/showcase/images/logos/ford.png differ diff --git a/src/assets/showcase/images/logos/fox.png b/src/assets/showcase/images/logos/fox.png new file mode 100644 index 00000000000..76899b06f01 Binary files /dev/null and b/src/assets/showcase/images/logos/fox.png differ diff --git a/src/assets/showcase/images/logos/intel.png b/src/assets/showcase/images/logos/intel.png new file mode 100644 index 00000000000..4b58c72f3fd Binary files /dev/null and b/src/assets/showcase/images/logos/intel.png differ diff --git a/src/assets/showcase/images/logos/lufthansa.png b/src/assets/showcase/images/logos/lufthansa.png new file mode 100644 index 00000000000..973f321fb27 Binary files /dev/null and b/src/assets/showcase/images/logos/lufthansa.png differ diff --git a/src/assets/showcase/images/logos/mercedes.png b/src/assets/showcase/images/logos/mercedes.png new file mode 100644 index 00000000000..e415cef6cdd Binary files /dev/null and b/src/assets/showcase/images/logos/mercedes.png differ diff --git a/src/assets/showcase/images/logos/unicredit.png b/src/assets/showcase/images/logos/unicredit.png new file mode 100644 index 00000000000..17f913694d2 Binary files /dev/null and b/src/assets/showcase/images/logos/unicredit.png differ diff --git a/src/assets/showcase/images/logos/verizon.png b/src/assets/showcase/images/logos/verizon.png new file mode 100644 index 00000000000..000f20b98b4 Binary files /dev/null and b/src/assets/showcase/images/logos/verizon.png differ diff --git a/src/assets/showcase/images/loveClients.svg b/src/assets/showcase/images/loveClients.svg new file mode 100644 index 00000000000..eb7a1cb9585 --- /dev/null +++ b/src/assets/showcase/images/loveClients.svg @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/showcase/images/menuicon.svg b/src/assets/showcase/images/menuicon.svg new file mode 100644 index 00000000000..c8aa4d05220 --- /dev/null +++ b/src/assets/showcase/images/menuicon.svg @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/src/assets/showcase/images/mobile.svg b/src/assets/showcase/images/mobile.svg new file mode 100644 index 00000000000..724a906c5b8 --- /dev/null +++ b/src/assets/showcase/images/mobile.svg @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/showcase/images/mono/apps.svg b/src/assets/showcase/images/mono/apps.svg new file mode 100644 index 00000000000..7303d160408 --- /dev/null +++ b/src/assets/showcase/images/mono/apps.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/showcase/images/mono/button.svg b/src/assets/showcase/images/mono/button.svg new file mode 100644 index 00000000000..699c492e822 --- /dev/null +++ b/src/assets/showcase/images/mono/button.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + diff --git a/src/assets/showcase/images/mono/charts.svg b/src/assets/showcase/images/mono/charts.svg new file mode 100644 index 00000000000..0e98eafd16a --- /dev/null +++ b/src/assets/showcase/images/mono/charts.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/src/assets/showcase/images/mono/components.svg b/src/assets/showcase/images/mono/components.svg new file mode 100644 index 00000000000..ebfd6a82fd1 --- /dev/null +++ b/src/assets/showcase/images/mono/components.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/assets/showcase/images/mono/data.svg b/src/assets/showcase/images/mono/data.svg new file mode 100644 index 00000000000..625502ca77c --- /dev/null +++ b/src/assets/showcase/images/mono/data.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/src/assets/showcase/images/mono/dragdrop.svg b/src/assets/showcase/images/mono/dragdrop.svg new file mode 100644 index 00000000000..45b0aa2d46f --- /dev/null +++ b/src/assets/showcase/images/mono/dragdrop.svg @@ -0,0 +1,132 @@ + + + + + + + + + + diff --git a/src/assets/showcase/images/mono/file.svg b/src/assets/showcase/images/mono/file.svg new file mode 100644 index 00000000000..a8735eb1d9c --- /dev/null +++ b/src/assets/showcase/images/mono/file.svg @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/src/assets/showcase/images/mono/input.svg b/src/assets/showcase/images/mono/input.svg new file mode 100644 index 00000000000..17193c3b04c --- /dev/null +++ b/src/assets/showcase/images/mono/input.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + diff --git a/src/assets/showcase/images/mono/menu.svg b/src/assets/showcase/images/mono/menu.svg new file mode 100644 index 00000000000..0a72b4528dc --- /dev/null +++ b/src/assets/showcase/images/mono/menu.svg @@ -0,0 +1,29 @@ + + + + + + + + + + diff --git a/src/assets/showcase/images/mono/message.svg b/src/assets/showcase/images/mono/message.svg new file mode 100644 index 00000000000..48c7029eca1 --- /dev/null +++ b/src/assets/showcase/images/mono/message.svg @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/src/assets/showcase/images/mono/misc.svg b/src/assets/showcase/images/mono/misc.svg new file mode 100644 index 00000000000..aed6a1f1a5f --- /dev/null +++ b/src/assets/showcase/images/mono/misc.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + diff --git a/src/assets/showcase/images/mono/multimedia.svg b/src/assets/showcase/images/mono/multimedia.svg new file mode 100644 index 00000000000..d7df87d8455 --- /dev/null +++ b/src/assets/showcase/images/mono/multimedia.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + diff --git a/src/assets/showcase/images/mono/overlay.svg b/src/assets/showcase/images/mono/overlay.svg new file mode 100644 index 00000000000..47dda994d9c --- /dev/null +++ b/src/assets/showcase/images/mono/overlay.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + diff --git a/src/assets/showcase/images/mono/panel.svg b/src/assets/showcase/images/mono/panel.svg new file mode 100644 index 00000000000..785cd112f44 --- /dev/null +++ b/src/assets/showcase/images/mono/panel.svg @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/src/assets/showcase/images/optimushear.svg b/src/assets/showcase/images/optimushear.svg new file mode 100644 index 00000000000..9bddb6c623c --- /dev/null +++ b/src/assets/showcase/images/optimushear.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/showcase/images/primeelements.png b/src/assets/showcase/images/primeelements.png new file mode 100644 index 00000000000..5cb3424055c Binary files /dev/null and b/src/assets/showcase/images/primeelements.png differ diff --git a/src/assets/showcase/images/primeng-ngconf.png b/src/assets/showcase/images/primeng-ngconf.png new file mode 100644 index 00000000000..16134a06b20 Binary files /dev/null and b/src/assets/showcase/images/primeng-ngconf.png differ diff --git a/src/assets/showcase/images/primeng-sidebar.svg b/src/assets/showcase/images/primeng-sidebar.svg new file mode 100644 index 00000000000..c48a37a9c96 --- /dev/null +++ b/src/assets/showcase/images/primeng-sidebar.svg @@ -0,0 +1,45 @@ + + + + Group 2 + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/showcase/images/primeng-text.svg b/src/assets/showcase/images/primeng-text.svg new file mode 100644 index 00000000000..ac7dbd4ae98 --- /dev/null +++ b/src/assets/showcase/images/primeng-text.svg @@ -0,0 +1,18 @@ + + + + primeng-text + Created with Sketch. + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/showcase/images/primeng-topbar.svg b/src/assets/showcase/images/primeng-topbar.svg new file mode 100644 index 00000000000..f5cece4a23a --- /dev/null +++ b/src/assets/showcase/images/primeng-topbar.svg @@ -0,0 +1,60 @@ + + + + primengfull + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/showcase/images/primeng.png b/src/assets/showcase/images/primeng.png new file mode 100644 index 00000000000..938cacf8a5a Binary files /dev/null and b/src/assets/showcase/images/primeng.png differ diff --git a/src/assets/showcase/images/primeng.svg b/src/assets/showcase/images/primeng.svg new file mode 100644 index 00000000000..e0c129662f1 --- /dev/null +++ b/src/assets/showcase/images/primeng.svg @@ -0,0 +1,54 @@ + + + + angular copy + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/showcase/images/primengdark.svg b/src/assets/showcase/images/primengdark.svg new file mode 100644 index 00000000000..1eb8cb53043 --- /dev/null +++ b/src/assets/showcase/images/primengdark.svg @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/showcase/images/primengfull.svg b/src/assets/showcase/images/primengfull.svg new file mode 100644 index 00000000000..46a77287d04 --- /dev/null +++ b/src/assets/showcase/images/primengfull.svg @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/showcase/images/productivity.svg b/src/assets/showcase/images/productivity.svg new file mode 100644 index 00000000000..b493ffce0e1 --- /dev/null +++ b/src/assets/showcase/images/productivity.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + diff --git a/src/assets/showcase/images/quote.png b/src/assets/showcase/images/quote.png new file mode 100644 index 00000000000..fa1e40478de Binary files /dev/null and b/src/assets/showcase/images/quote.png differ diff --git a/src/assets/showcase/images/setup.svg b/src/assets/showcase/images/setup.svg new file mode 100644 index 00000000000..a233a1c3f04 --- /dev/null +++ b/src/assets/showcase/images/setup.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + diff --git a/src/assets/showcase/images/tab-widgets.png b/src/assets/showcase/images/tab-widgets.png new file mode 100644 index 00000000000..49e383b4af3 Binary files /dev/null and b/src/assets/showcase/images/tab-widgets.png differ diff --git a/src/assets/showcase/images/themes.png b/src/assets/showcase/images/themes.png new file mode 100644 index 00000000000..3c96118db46 Binary files /dev/null and b/src/assets/showcase/images/themes.png differ diff --git a/src/assets/showcase/images/themeswitcher-atlantis.png b/src/assets/showcase/images/themeswitcher-atlantis.png new file mode 100644 index 00000000000..10936720b31 Binary files /dev/null and b/src/assets/showcase/images/themeswitcher-atlantis.png differ diff --git a/src/assets/showcase/images/themeswitcher-barcelona.png b/src/assets/showcase/images/themeswitcher-barcelona.png new file mode 100644 index 00000000000..92bc5a5a856 Binary files /dev/null and b/src/assets/showcase/images/themeswitcher-barcelona.png differ diff --git a/src/assets/showcase/images/themeswitcher-morpheus.png b/src/assets/showcase/images/themeswitcher-morpheus.png new file mode 100644 index 00000000000..3520d27e2b0 Binary files /dev/null and b/src/assets/showcase/images/themeswitcher-morpheus.png differ diff --git a/src/assets/showcase/images/themeswitcher-omega.png b/src/assets/showcase/images/themeswitcher-omega.png new file mode 100644 index 00000000000..386bc0ac2a9 Binary files /dev/null and b/src/assets/showcase/images/themeswitcher-omega.png differ diff --git a/src/assets/showcase/images/themeswitcher-paradise.png b/src/assets/showcase/images/themeswitcher-paradise.png new file mode 100644 index 00000000000..399a988cfbc Binary files /dev/null and b/src/assets/showcase/images/themeswitcher-paradise.png differ diff --git a/src/assets/showcase/images/themeswitcher-poseidon.png b/src/assets/showcase/images/themeswitcher-poseidon.png new file mode 100644 index 00000000000..3c167b148e3 Binary files /dev/null and b/src/assets/showcase/images/themeswitcher-poseidon.png differ diff --git a/src/assets/showcase/images/themeswitcher-ultima.png b/src/assets/showcase/images/themeswitcher-ultima.png new file mode 100644 index 00000000000..6cd6e90129e Binary files /dev/null and b/src/assets/showcase/images/themeswitcher-ultima.png differ diff --git a/src/assets/showcase/images/themeswitcher.svg b/src/assets/showcase/images/themeswitcher.svg new file mode 100644 index 00000000000..23410788b89 --- /dev/null +++ b/src/assets/showcase/images/themeswitcher.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts new file mode 100644 index 00000000000..3612073bc31 --- /dev/null +++ b/src/environments/environment.prod.ts @@ -0,0 +1,3 @@ +export const environment = { + production: true +}; diff --git a/src/environments/environment.ts b/src/environments/environment.ts new file mode 100644 index 00000000000..b7f639aecac --- /dev/null +++ b/src/environments/environment.ts @@ -0,0 +1,8 @@ +// The file contents for the current environment will overwrite these during build. +// The build system defaults to the dev environment which uses `environment.ts`, but if you do +// `ng build --env=prod` then `environment.prod.ts` will be used instead. +// The list of which env maps to which file can be found in `.angular-cli.json`. + +export const environment = { + production: false +}; diff --git a/src/favicon.png b/src/favicon.png new file mode 100644 index 00000000000..c41758af4a9 Binary files /dev/null and b/src/favicon.png differ diff --git a/src/index.html b/src/index.html new file mode 100644 index 00000000000..dca45dd4c66 --- /dev/null +++ b/src/index.html @@ -0,0 +1,25 @@ + + + + + PrimeNG + + + + + + + + +
        +
        + +
        + +
        + +
        +
        +
        + + diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 00000000000..34bf9649d49 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,11 @@ +import { enableProdMode } from '@angular/core'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { AppModule } from './app/showcase/app.module'; +import { environment } from './environments/environment'; + +if (environment.production) { + enableProdMode(); +} + +platformBrowserDynamic().bootstrapModule(AppModule); diff --git a/src/polyfills.ts b/src/polyfills.ts new file mode 100644 index 00000000000..fd01cc9f1dd --- /dev/null +++ b/src/polyfills.ts @@ -0,0 +1,73 @@ +/** + * This file includes polyfills needed by Angular and is loaded before the app. + * You can add your own extra polyfills to this file. + * + * This file is divided into 2 sections: + * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. + * 2. Application imports. Files imported after ZoneJS that should be loaded before your main + * file. + * + * The current setup is for so-called "evergreen" browsers; the last versions of browsers that + * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), + * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. + * + * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html + */ + +/*************************************************************************************************** + * BROWSER POLYFILLS + */ + +/** IE9, IE10 and IE11 requires all of the following polyfills. **/ +// import 'core-js/es6/symbol'; +// import 'core-js/es6/object'; +// import 'core-js/es6/function'; +// import 'core-js/es6/parse-int'; +// import 'core-js/es6/parse-float'; +// import 'core-js/es6/number'; +// import 'core-js/es6/math'; +// import 'core-js/es6/string'; +// import 'core-js/es6/date'; +// import 'core-js/es6/array'; +// import 'core-js/es6/regexp'; +// import 'core-js/es6/map'; +// import 'core-js/es6/weak-map'; +// import 'core-js/es6/set'; + +/** IE10 and IE11 requires the following for NgClass support on SVG elements */ +// import 'classlist.js'; // Run `npm install --save classlist.js`. + +/** IE10 and IE11 requires the following to support `@angular/animation`. */ +// import 'web-animations-js'; // Run `npm install --save web-animations-js`. + + +/** Evergreen browsers require these. **/ +import 'core-js/es6/reflect'; +import 'core-js/es7/reflect'; + + +/** ALL Firefox browsers require the following to support `@angular/animation`. **/ +// import 'web-animations-js'; // Run `npm install --save web-animations-js`. + + + +/*************************************************************************************************** + * Zone JS is required by Angular itself. + */ +import 'zone.js/dist/zone'; // Included with Angular CLI. + + + +/*************************************************************************************************** + * APPLICATION IMPORTS + */ + +/** + * Date, currency, decimal and percent pipes. + * Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10 + */ +// import 'intl'; // Run `npm install --save intl`. +/** + * Need to import at least one locale-data with intl. + */ +// import 'intl/locale-data/jsonp/en'; diff --git a/src/styles.css b/src/styles.css new file mode 100644 index 00000000000..ec9a603f038 --- /dev/null +++ b/src/styles.css @@ -0,0 +1,3 @@ +@import 'assets/showcase/css/primeng.css'; +@import 'assets/showcase/css/code.css'; +@import 'assets/showcase/css/site.css'; diff --git a/src/test.ts b/src/test.ts new file mode 100644 index 00000000000..cd612eeb0e2 --- /dev/null +++ b/src/test.ts @@ -0,0 +1,32 @@ +// This file is required by karma.conf.js and loads recursively all the .spec and framework files + +import 'zone.js/dist/long-stack-trace-zone'; +import 'zone.js/dist/proxy.js'; +import 'zone.js/dist/sync-test'; +import 'zone.js/dist/jasmine-patch'; +import 'zone.js/dist/async-test'; +import 'zone.js/dist/fake-async-test'; +import { getTestBed } from '@angular/core/testing'; +import { + BrowserDynamicTestingModule, + platformBrowserDynamicTesting +} from '@angular/platform-browser-dynamic/testing'; + +// Unfortunately there's no typing for the `__karma__` variable. Just declare it as any. +declare const __karma__: any; +declare const require: any; + +// Prevent Karma from running prematurely. +__karma__.loaded = function () {}; + +// First, initialize the Angular testing environment. +getTestBed().initTestEnvironment( + BrowserDynamicTestingModule, + platformBrowserDynamicTesting() +); +// Then we find all the tests. +const context = require.context('./', true, /\.spec\.ts$/); +// And load the modules. +context.keys().map(context); +// Finally, start Karma to run the tests. +__karma__.start(); diff --git a/src/tsconfig.app.json b/src/tsconfig.app.json new file mode 100644 index 00000000000..5e2507db58c --- /dev/null +++ b/src/tsconfig.app.json @@ -0,0 +1,13 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "outDir": "../out-tsc/app", + "module": "es2015", + "baseUrl": "", + "types": [] + }, + "exclude": [ + "test.ts", + "**/*.spec.ts" + ] +} diff --git a/src/tsconfig.spec.json b/src/tsconfig.spec.json new file mode 100644 index 00000000000..510e3f1fdae --- /dev/null +++ b/src/tsconfig.spec.json @@ -0,0 +1,20 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "outDir": "../out-tsc/spec", + "module": "commonjs", + "target": "es5", + "baseUrl": "", + "types": [ + "jasmine", + "node" + ] + }, + "files": [ + "test.ts" + ], + "include": [ + "**/*.spec.ts", + "**/*.d.ts" + ] +} diff --git a/src/typings.d.ts b/src/typings.d.ts new file mode 100644 index 00000000000..ef5c7bd6205 --- /dev/null +++ b/src/typings.d.ts @@ -0,0 +1,5 @@ +/* SystemJS module definition */ +declare var module: NodeModule; +interface NodeModule { + id: string; +} diff --git a/tsconfig-aot.json b/tsconfig-aot.json new file mode 100644 index 00000000000..14129b3ba4b --- /dev/null +++ b/tsconfig-aot.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "outDir": "./components", + "target": "es5", + "module": "es2015", + "baseUrl": "src", + "moduleResolution": "node", + "sourceMap": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "removeComments": false, + "noImplicitAny": false, + "suppressImplicitAnyIndexErrors": true, + "lib": ["dom","es6"] + }, + "include": [ + "src/app/components/**/*" + ], + "angularCompilerOptions": { + "genDir": "aot", + "skipMetadataEmit" : false + } +} \ No newline at end of file diff --git a/tsconfig-release.json b/tsconfig-release.json new file mode 100644 index 00000000000..678490288e1 --- /dev/null +++ b/tsconfig-release.json @@ -0,0 +1,24 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "outDir": "./components", + "baseUrl": "src", + "rootDir": "src/app/components", + "sourceMap": true, + "declaration": false, + "moduleResolution": "node", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "target": "es5", + "typeRoots": [ + "node_modules/@types" + ], + "lib": [ + "es2016", + "dom" + ] + }, + "include": [ + "src/app/components/**/*" + ] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000000..a35a8ee3a40 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "outDir": "./dist/out-tsc", + "baseUrl": "src", + "sourceMap": true, + "declaration": false, + "moduleResolution": "node", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "target": "es5", + "typeRoots": [ + "node_modules/@types" + ], + "lib": [ + "es2016", + "dom" + ] + } +} diff --git a/tslint.json b/tslint.json new file mode 100644 index 00000000000..dd117b3871e --- /dev/null +++ b/tslint.json @@ -0,0 +1,135 @@ +{ + "rulesDirectory": [ + "node_modules/codelyzer" + ], + "rules": { + "arrow-return-shorthand": true, + "callable-types": true, + "class-name": true, + "comment-format": [ + true, + "check-space" + ], + "curly": true, + "eofline": true, + "forin": true, + "import-blacklist": [ + true, + "rxjs" + ], + "import-spacing": true, + "indent": [ + true, + "spaces" + ], + "interface-over-type-literal": true, + "label-position": true, + "max-line-length": [ + true, + 140 + ], + "member-access": false, + "member-ordering": [ + true, + "static-before-instance", + "variables-before-functions" + ], + "no-arg": true, + "no-bitwise": true, + "no-console": [ + true, + "debug", + "info", + "time", + "timeEnd", + "trace" + ], + "no-construct": true, + "no-debugger": true, + "no-duplicate-super": true, + "no-empty": false, + "no-empty-interface": true, + "no-eval": true, + "no-inferrable-types": [ + true, + "ignore-params" + ], + "no-misused-new": true, + "no-non-null-assertion": true, + "no-shadowed-variable": true, + "no-string-literal": false, + "no-string-throw": true, + "no-switch-case-fall-through": true, + "no-trailing-whitespace": true, + "no-unnecessary-initializer": true, + "no-unused-expression": true, + "no-use-before-declare": true, + "no-var-keyword": true, + "object-literal-sort-keys": false, + "one-line": [ + true, + "check-open-brace", + "check-catch", + "check-else", + "check-whitespace" + ], + "prefer-const": true, + "quotemark": [ + true, + "single" + ], + "radix": true, + "semicolon": [ + "always" + ], + "triple-equals": [ + true, + "allow-null-check" + ], + "typedef-whitespace": [ + true, + { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + } + ], + "typeof-compare": true, + "unified-signatures": true, + "variable-name": false, + "whitespace": [ + true, + "check-branch", + "check-decl", + "check-operator", + "check-separator", + "check-type" + ], + "directive-selector": [ + true, + "attribute", + "app", + "camelCase" + ], + "component-selector": [ + true, + "element", + "app", + "kebab-case" + ], + "use-input-property-decorator": true, + "use-output-property-decorator": true, + "use-host-property-decorator": true, + "no-input-rename": true, + "no-output-rename": true, + "use-life-cycle-interface": true, + "use-pipe-transform-interface": true, + "component-class-suffix": true, + "directive-class-suffix": true, + "no-access-missing-member": true, + "templates-use-public": true, + "invoke-injectable": true + } +}