UNPKG

ngx-bootstrap

Version:
1,570 lines (1,554 loc) 379 kB
import { formatDate, getFullYear, getMonth, getDay, isFirstDayOfWeek, isAfter, isBefore, shiftDate, endOf, startOf, getFirstDayOfMonth, getLocale, isSameDay, isSameMonth, isSameYear, setFullDate, isArray, isDateValid, parseDate, isDate } from 'ngx-bootstrap/chronos'; import { Component, EventEmitter, Input, Output, Injectable, forwardRef, ViewChild, NgModule, Directive, ElementRef, Renderer2, ViewContainerRef, ChangeDetectorRef, Host, ChangeDetectionStrategy } from '@angular/core'; import { NG_VALUE_ACCESSOR, FormsModule, NG_VALIDATORS } from '@angular/forms'; import { isBs3, warnOnce } from 'ngx-bootstrap/utils'; import { CommonModule } from '@angular/common'; import { BehaviorSubject } from 'rxjs'; import { filter, map } from 'rxjs/operators'; import { MiniStore, MiniState } from 'ngx-bootstrap/mini-ngrx'; import { ComponentLoaderFactory } from 'ngx-bootstrap/component-loader'; import { PositioningService } from 'ngx-bootstrap/positioning'; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class DateFormatter { /** * @param {?} date * @param {?} format * @param {?} locale * @return {?} */ format(date, format, locale) { return formatDate(date, format, locale); } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class DatePickerInnerComponent { constructor() { this.selectionDone = new EventEmitter(undefined); this.update = new EventEmitter(false); this.activeDateChange = new EventEmitter(undefined); /* tslint:disable-next-line: no-any*/ this.stepDay = {}; /* tslint:disable-next-line: no-any*/ this.stepMonth = {}; /* tslint:disable-next-line: no-any*/ this.stepYear = {}; this.modes = ['day', 'month', 'year']; this.dateFormatter = new DateFormatter(); } /** * @return {?} */ get activeDate() { return this._activeDate; } /** * @param {?} value * @return {?} */ set activeDate(value) { this._activeDate = value; } /** * @return {?} */ ngOnInit() { // todo: use date for unique value this.uniqueId = `datepicker--${Math.floor(Math.random() * 10000)}`; if (this.initDate) { this.activeDate = this.initDate; this.selectedDate = new Date(this.activeDate.valueOf()); this.update.emit(this.activeDate); } else if (this.activeDate === undefined) { this.activeDate = new Date(); } } /** * @param {?} changes * @return {?} */ ngOnChanges(changes) { this.refreshView(); this.checkIfActiveDateGotUpdated(changes["activeDate"]); } /** * @param {?} activeDate * @return {?} */ checkIfActiveDateGotUpdated(activeDate) { if (activeDate && !activeDate.firstChange) { const /** @type {?} */ previousValue = activeDate.previousValue; if (previousValue && previousValue instanceof Date && previousValue.getTime() !== activeDate.currentValue.getTime()) { this.activeDateChange.emit(this.activeDate); } } } /** * @param {?} handler * @param {?} type * @return {?} */ setCompareHandler(handler, type) { if (type === 'day') { this.compareHandlerDay = handler; } if (type === 'month') { this.compareHandlerMonth = handler; } if (type === 'year') { this.compareHandlerYear = handler; } } /** * @param {?} date1 * @param {?} date2 * @return {?} */ compare(date1, date2) { if (date1 === undefined || date2 === undefined) { return undefined; } if (this.datepickerMode === 'day' && this.compareHandlerDay) { return this.compareHandlerDay(date1, date2); } if (this.datepickerMode === 'month' && this.compareHandlerMonth) { return this.compareHandlerMonth(date1, date2); } if (this.datepickerMode === 'year' && this.compareHandlerYear) { return this.compareHandlerYear(date1, date2); } return void 0; } /** * @param {?} handler * @param {?} type * @return {?} */ setRefreshViewHandler(handler, type) { if (type === 'day') { this.refreshViewHandlerDay = handler; } if (type === 'month') { this.refreshViewHandlerMonth = handler; } if (type === 'year') { this.refreshViewHandlerYear = handler; } } /** * @return {?} */ refreshView() { if (this.datepickerMode === 'day' && this.refreshViewHandlerDay) { this.refreshViewHandlerDay(); } if (this.datepickerMode === 'month' && this.refreshViewHandlerMonth) { this.refreshViewHandlerMonth(); } if (this.datepickerMode === 'year' && this.refreshViewHandlerYear) { this.refreshViewHandlerYear(); } } /** * @param {?} date * @param {?} format * @return {?} */ dateFilter(date, format) { return this.dateFormatter.format(date, format, this.locale); } /** * @param {?} dateObject * @return {?} */ isActive(dateObject) { if (this.compare(dateObject.date, this.activeDate) === 0) { this.activeDateId = dateObject.uid; return true; } return false; } /** * @param {?} date * @param {?} format * @return {?} */ createDateObject(date, format) { /* tslint:disable-next-line: no-any*/ const /** @type {?} */ dateObject = {}; dateObject.date = new Date(date.getFullYear(), date.getMonth(), date.getDate()); dateObject.date = this.fixTimeZone(dateObject.date); dateObject.label = this.dateFilter(date, format); dateObject.selected = this.compare(date, this.selectedDate) === 0; dateObject.disabled = this.isDisabled(date); dateObject.current = this.compare(date, new Date()) === 0; dateObject.customClass = this.getCustomClassForDate(dateObject.date); return dateObject; } /** * @param {?} arr * @param {?} size * @return {?} */ split(arr, size) { /* tslint:disable-next-line: no-any*/ const /** @type {?} */ arrays = []; while (arr.length > 0) { arrays.push(arr.splice(0, size)); } return arrays; } /** * @param {?} date * @return {?} */ fixTimeZone(date) { const /** @type {?} */ hours = date.getHours(); return new Date(date.getFullYear(), date.getMonth(), date.getDate(), hours === 23 ? hours + 2 : 0); } /** * @param {?} date * @param {?=} isManual * @return {?} */ select(date, isManual = true) { if (this.datepickerMode === this.minMode) { if (!this.activeDate) { this.activeDate = new Date(0, 0, 0, 0, 0, 0, 0); } this.activeDate = new Date(date.getFullYear(), date.getMonth(), date.getDate()); this.activeDate = this.fixTimeZone(this.activeDate); if (isManual) { this.selectionDone.emit(this.activeDate); } } else { this.activeDate = new Date(date.getFullYear(), date.getMonth(), date.getDate()); this.activeDate = this.fixTimeZone(this.activeDate); if (isManual) { this.datepickerMode = this.modes[this.modes.indexOf(this.datepickerMode) - 1]; } } this.selectedDate = new Date(this.activeDate.valueOf()); this.update.emit(this.activeDate); this.refreshView(); } /** * @param {?} direction * @return {?} */ move(direction) { /* tslint:disable-next-line: no-any*/ let /** @type {?} */ expectedStep; if (this.datepickerMode === 'day') { expectedStep = this.stepDay; } if (this.datepickerMode === 'month') { expectedStep = this.stepMonth; } if (this.datepickerMode === 'year') { expectedStep = this.stepYear; } if (expectedStep) { const /** @type {?} */ year = this.activeDate.getFullYear() + direction * (expectedStep.years || 0); const /** @type {?} */ month = this.activeDate.getMonth() + direction * (expectedStep.months || 0); this.activeDate = new Date(year, month, 1); this.refreshView(); this.activeDateChange.emit(this.activeDate); } } /** * @param {?} _direction * @return {?} */ toggleMode(_direction) { const /** @type {?} */ direction = _direction || 1; if ((this.datepickerMode === this.maxMode && direction === 1) || (this.datepickerMode === this.minMode && direction === -1)) { return; } this.datepickerMode = this.modes[this.modes.indexOf(this.datepickerMode) + direction]; this.refreshView(); } /** * @param {?} date * @return {?} */ getCustomClassForDate(date) { if (!this.customClass) { return ''; } // todo: build a hash of custom classes, it will work faster const /** @type {?} */ customClassObject = this.customClass.find((customClass) => { return (customClass.date.valueOf() === date.valueOf() && customClass.mode === this.datepickerMode); }, this); return customClassObject === undefined ? '' : customClassObject.clazz; } /** * @param {?} date1Disabled * @param {?} date2 * @return {?} */ compareDateDisabled(date1Disabled, date2) { if (date1Disabled === undefined || date2 === undefined) { return undefined; } if (date1Disabled.mode === 'day' && this.compareHandlerDay) { return this.compareHandlerDay(date1Disabled.date, date2); } if (date1Disabled.mode === 'month' && this.compareHandlerMonth) { return this.compareHandlerMonth(date1Disabled.date, date2); } if (date1Disabled.mode === 'year' && this.compareHandlerYear) { return this.compareHandlerYear(date1Disabled.date, date2); } return undefined; } /** * @param {?} date * @return {?} */ isDisabled(date) { let /** @type {?} */ isDateDisabled = false; if (this.dateDisabled) { this.dateDisabled.forEach((disabledDate) => { if (this.compareDateDisabled(disabledDate, date) === 0) { isDateDisabled = true; } }); } if (this.dayDisabled) { isDateDisabled = isDateDisabled || this.dayDisabled.indexOf(date.getDay()) > -1; } return (isDateDisabled || (this.minDate && this.compare(date, this.minDate) < 0) || (this.maxDate && this.compare(date, this.maxDate) > 0)); } } DatePickerInnerComponent.decorators = [ { type: Component, args: [{ selector: 'datepicker-inner', template: ` <!--&lt;!&ndash;ng-keydown="keydown($event)"&ndash;&gt;--> <div *ngIf="datepickerMode" class="well well-sm bg-faded p-a card" role="application" > <ng-content></ng-content> </div> ` }] } ]; /** @nocollapse */ DatePickerInnerComponent.propDecorators = { "locale": [{ type: Input },], "datepickerMode": [{ type: Input },], "startingDay": [{ type: Input },], "yearRange": [{ type: Input },], "minDate": [{ type: Input },], "maxDate": [{ type: Input },], "minMode": [{ type: Input },], "maxMode": [{ type: Input },], "showWeeks": [{ type: Input },], "formatDay": [{ type: Input },], "formatMonth": [{ type: Input },], "formatYear": [{ type: Input },], "formatDayHeader": [{ type: Input },], "formatDayTitle": [{ type: Input },], "formatMonthTitle": [{ type: Input },], "onlyCurrentMonth": [{ type: Input },], "shortcutPropagation": [{ type: Input },], "customClass": [{ type: Input },], "monthColLimit": [{ type: Input },], "yearColLimit": [{ type: Input },], "dateDisabled": [{ type: Input },], "dayDisabled": [{ type: Input },], "initDate": [{ type: Input },], "selectionDone": [{ type: Output },], "update": [{ type: Output },], "activeDateChange": [{ type: Output },], "activeDate": [{ type: Input },], }; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class DatepickerConfig { constructor() { this.locale = 'en'; this.datepickerMode = 'day'; this.startingDay = 0; this.yearRange = 20; this.minMode = 'day'; this.maxMode = 'year'; this.showWeeks = true; this.formatDay = 'DD'; this.formatMonth = 'MMMM'; this.formatYear = 'YYYY'; this.formatDayHeader = 'dd'; this.formatDayTitle = 'MMMM YYYY'; this.formatMonthTitle = 'YYYY'; this.onlyCurrentMonth = false; this.monthColLimit = 3; this.yearColLimit = 5; this.shortcutPropagation = false; } } DatepickerConfig.decorators = [ { type: Injectable } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ const /** @type {?} */ DATEPICKER_CONTROL_VALUE_ACCESSOR = { provide: NG_VALUE_ACCESSOR, /* tslint:disable-next-line: no-use-before-declare */ useExisting: forwardRef(() => DatePickerComponent), multi: true }; /* tslint:enable:component-selector-name component-selector-type */ class DatePickerComponent { /** * @param {?} config */ constructor(config) { /** * sets datepicker mode, supports: `day`, `month`, `year` */ this.datepickerMode = 'day'; /** * if false week numbers will be hidden */ this.showWeeks = true; this.selectionDone = new EventEmitter(undefined); /** * callback to invoke when the activeDate is changed. */ this.activeDateChange = new EventEmitter(undefined); /* tslint:disable-next-line: no-any*/ this.onChange = Function.prototype; /* tslint:disable-next-line: no-any*/ this.onTouched = Function.prototype; this._now = new Date(); this.config = config; this.configureOptions(); } /** * currently active date * @return {?} */ get activeDate() { return this._activeDate || this._now; } /** * @param {?} value * @return {?} */ set activeDate(value) { this._activeDate = value; } /** * @return {?} */ configureOptions() { Object.assign(this, this.config); } /** * @param {?} event * @return {?} */ onUpdate(event) { this.activeDate = event; this.onChange(event); } /** * @param {?} event * @return {?} */ onSelectionDone(event) { this.selectionDone.emit(event); } /** * @param {?} event * @return {?} */ onActiveDateChange(event) { this.activeDateChange.emit(event); } /** * @param {?} value * @return {?} */ writeValue(value) { if (this._datePicker.compare(value, this._activeDate) === 0) { return; } if (value && value instanceof Date) { this.activeDate = value; this._datePicker.select(value, false); return; } this.activeDate = value ? new Date(value) : void 0; } /** * @param {?} fn * @return {?} */ registerOnChange(fn) { this.onChange = fn; } /** * @param {?} fn * @return {?} */ registerOnTouched(fn) { this.onTouched = fn; } } DatePickerComponent.decorators = [ { type: Component, args: [{ selector: 'datepicker', template: ` <datepicker-inner [activeDate]="activeDate" (update)="onUpdate($event)" [locale]="config.locale" [datepickerMode]="datepickerMode" [initDate]="initDate" [minDate]="minDate" [maxDate]="maxDate" [minMode]="minMode" [maxMode]="maxMode" [showWeeks]="showWeeks" [formatDay]="formatDay" [formatMonth]="formatMonth" [formatYear]="formatYear" [formatDayHeader]="formatDayHeader" [formatDayTitle]="formatDayTitle" [formatMonthTitle]="formatMonthTitle" [startingDay]="startingDay" [yearRange]="yearRange" [customClass]="customClass" [dateDisabled]="dateDisabled" [dayDisabled]="dayDisabled" [onlyCurrentMonth]="onlyCurrentMonth" [shortcutPropagation]="shortcutPropagation" [monthColLimit]="monthColLimit" [yearColLimit]="yearColLimit" (selectionDone)="onSelectionDone($event)" (activeDateChange)="onActiveDateChange($event)"> <daypicker tabindex="0"></daypicker> <monthpicker tabindex="0"></monthpicker> <yearpicker tabindex="0"></yearpicker> </datepicker-inner> `, providers: [DATEPICKER_CONTROL_VALUE_ACCESSOR] }] } ]; /** @nocollapse */ DatePickerComponent.ctorParameters = () => [ { type: DatepickerConfig, }, ]; DatePickerComponent.propDecorators = { "datepickerMode": [{ type: Input },], "initDate": [{ type: Input },], "minDate": [{ type: Input },], "maxDate": [{ type: Input },], "minMode": [{ type: Input },], "maxMode": [{ type: Input },], "showWeeks": [{ type: Input },], "formatDay": [{ type: Input },], "formatMonth": [{ type: Input },], "formatYear": [{ type: Input },], "formatDayHeader": [{ type: Input },], "formatDayTitle": [{ type: Input },], "formatMonthTitle": [{ type: Input },], "startingDay": [{ type: Input },], "yearRange": [{ type: Input },], "onlyCurrentMonth": [{ type: Input },], "shortcutPropagation": [{ type: Input },], "monthColLimit": [{ type: Input },], "yearColLimit": [{ type: Input },], "customClass": [{ type: Input },], "dateDisabled": [{ type: Input },], "dayDisabled": [{ type: Input },], "activeDate": [{ type: Input },], "selectionDone": [{ type: Output },], "activeDateChange": [{ type: Output },], "_datePicker": [{ type: ViewChild, args: [DatePickerInnerComponent,] },], }; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class DayPickerComponent { /** * @param {?} datePicker */ constructor(datePicker) { this.labels = []; this.rows = []; this.weekNumbers = []; this.datePicker = datePicker; } /** * @return {?} */ get isBs4() { return !isBs3(); } /** * @return {?} */ ngOnInit() { const /** @type {?} */ self = this; this.datePicker.stepDay = { months: 1 }; this.datePicker.setRefreshViewHandler(function () { const /** @type {?} */ year = this.activeDate.getFullYear(); const /** @type {?} */ month = this.activeDate.getMonth(); const /** @type {?} */ firstDayOfMonth = new Date(year, month, 1); const /** @type {?} */ difference = this.startingDay - firstDayOfMonth.getDay(); const /** @type {?} */ numDisplayedFromPreviousMonth = difference > 0 ? 7 - difference : -difference; const /** @type {?} */ firstDate = new Date(firstDayOfMonth.getTime()); if (numDisplayedFromPreviousMonth > 0) { firstDate.setDate(-numDisplayedFromPreviousMonth + 1); } // 42 is the number of days on a six-week calendar const /** @type {?} */ _days = self.getDates(firstDate, 42); const /** @type {?} */ days = []; for (let /** @type {?} */ i = 0; i < 42; i++) { const /** @type {?} */ _dateObject = this.createDateObject(_days[i], this.formatDay); _dateObject.secondary = _days[i].getMonth() !== month; _dateObject.uid = this.uniqueId + '-' + i; days[i] = _dateObject; } self.labels = []; for (let /** @type {?} */ j = 0; j < 7; j++) { self.labels[j] = {}; self.labels[j].abbr = this.dateFilter(days[j].date, this.formatDayHeader); self.labels[j].full = this.dateFilter(days[j].date, 'EEEE'); } self.title = this.dateFilter(this.activeDate, this.formatDayTitle); self.rows = this.split(days, 7); if (this.showWeeks) { self.weekNumbers = []; const /** @type {?} */ thursdayIndex = (4 + 7 - this.startingDay) % 7; const /** @type {?} */ numWeeks = self.rows.length; for (let /** @type {?} */ curWeek = 0; curWeek < numWeeks; curWeek++) { self.weekNumbers.push(self.getISO8601WeekNumber(self.rows[curWeek][thursdayIndex].date)); } } }, 'day'); this.datePicker.setCompareHandler(function (date1, date2) { const /** @type {?} */ d1 = new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()); const /** @type {?} */ d2 = new Date(date2.getFullYear(), date2.getMonth(), date2.getDate()); return d1.getTime() - d2.getTime(); }, 'day'); this.datePicker.refreshView(); } /** * @param {?} startDate * @param {?} n * @return {?} */ getDates(startDate, n) { const /** @type {?} */ dates = new Array(n); let /** @type {?} */ current = new Date(startDate.getTime()); let /** @type {?} */ i = 0; let /** @type {?} */ date; while (i < n) { date = new Date(current.getTime()); date = this.datePicker.fixTimeZone(date); dates[i++] = date; current = new Date(date.getFullYear(), date.getMonth(), date.getDate() + 1); } return dates; } /** * @param {?} date * @return {?} */ getISO8601WeekNumber(date) { const /** @type {?} */ checkDate = new Date(date.getTime()); // Thursday checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); const /** @type {?} */ time = checkDate.getTime(); // Compare with Jan 1 checkDate.setMonth(0); checkDate.setDate(1); return (Math.floor(Math.round((time - checkDate.getTime()) / 86400000) / 7) + 1); } } DayPickerComponent.decorators = [ { type: Component, args: [{ selector: 'daypicker', template: ` <table *ngIf="datePicker.datepickerMode === 'day'" role="grid" [attr.aria-labelledby]="datePicker.uniqueId + '-title'" aria-activedescendant="activeDateId"> <thead> <tr> <th> <button *ngIf="!isBs4" type="button" class="btn btn-default btn-secondary btn-sm pull-left float-left" (click)="datePicker.move(-1)" tabindex="-1">‹</button> <button *ngIf="isBs4" type="button" class="btn btn-default btn-secondary btn-sm pull-left float-left" (click)="datePicker.move(-1)" tabindex="-1">&lt;</button> </th> <th [attr.colspan]="5 + (datePicker.showWeeks ? 1 : 0)"> <button [id]="datePicker.uniqueId + '-title'" type="button" class="btn btn-default btn-secondary btn-sm" (click)="datePicker.toggleMode(0)" [disabled]="datePicker.datepickerMode === datePicker.maxMode" [ngClass]="{disabled: datePicker.datepickerMode === datePicker.maxMode}" tabindex="-1" style="width:100%;"> <strong>{{ title }}</strong> </button> </th> <th> <button *ngIf="!isBs4" type="button" class="btn btn-default btn-secondary btn-sm pull-right float-right" (click)="datePicker.move(1)" tabindex="-1">›</button> <button *ngIf="isBs4" type="button" class="btn btn-default btn-secondary btn-sm pull-right float-right" (click)="datePicker.move(1)" tabindex="-1">&gt; </button> </th> </tr> <tr> <th *ngIf="datePicker.showWeeks"></th> <th *ngFor="let labelz of labels" class="text-center"> <small aria-label="labelz.full"><b>{{ labelz.abbr }}</b></small> </th> </tr> </thead> <tbody> <ng-template ngFor [ngForOf]="rows" let-rowz="$implicit" let-index="index"> <tr *ngIf="!(datePicker.onlyCurrentMonth && rowz[0].secondary && rowz[6].secondary)"> <td *ngIf="datePicker.showWeeks" class="h6" class="text-center"> <em>{{ weekNumbers[index] }}</em> </td> <td *ngFor="let dtz of rowz" class="text-center" role="gridcell" [id]="dtz.uid"> <button type="button" style="min-width:100%;" class="btn btn-sm {{dtz.customClass}}" *ngIf="!(datePicker.onlyCurrentMonth && dtz.secondary)" [ngClass]="{'btn-secondary': isBs4 && !dtz.selected && !datePicker.isActive(dtz), 'btn-info': dtz.selected, disabled: dtz.disabled, active: !isBs4 && datePicker.isActive(dtz), 'btn-default': !isBs4}" [disabled]="dtz.disabled" (click)="datePicker.select(dtz.date)" tabindex="-1"> <span [ngClass]="{'text-muted': dtz.secondary || dtz.current, 'text-info': !isBs4 && dtz.current}">{{ dtz.label }}</span> </button> </td> </tr> </ng-template> </tbody> </table> `, styles: [` :host .btn-secondary { color: #292b2c; background-color: #fff; border-color: #ccc; } :host .btn-info .text-muted { color: #292b2c !important; } `] }] } ]; // todo: key events implementation /** @nocollapse */ DayPickerComponent.ctorParameters = () => [ { type: DatePickerInnerComponent, }, ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class MonthPickerComponent { /** * @param {?} datePicker */ constructor(datePicker) { this.rows = []; this.datePicker = datePicker; } /** * @return {?} */ get isBs4() { return !isBs3(); } /** * @return {?} */ ngOnInit() { const /** @type {?} */ self = this; this.datePicker.stepMonth = { years: 1 }; this.datePicker.setRefreshViewHandler(function () { const /** @type {?} */ months = new Array(12); const /** @type {?} */ year = this.activeDate.getFullYear(); let /** @type {?} */ date; for (let /** @type {?} */ i = 0; i < 12; i++) { date = new Date(year, i, 1); date = this.fixTimeZone(date); months[i] = this.createDateObject(date, this.formatMonth); months[i].uid = this.uniqueId + '-' + i; } self.title = this.dateFilter(this.activeDate, this.formatMonthTitle); self.rows = this.split(months, self.datePicker.monthColLimit); }, 'month'); this.datePicker.setCompareHandler(function (date1, date2) { const /** @type {?} */ d1 = new Date(date1.getFullYear(), date1.getMonth()); const /** @type {?} */ d2 = new Date(date2.getFullYear(), date2.getMonth()); return d1.getTime() - d2.getTime(); }, 'month'); this.datePicker.refreshView(); } } MonthPickerComponent.decorators = [ { type: Component, args: [{ selector: 'monthpicker', template: ` <table *ngIf="datePicker.datepickerMode==='month'" role="grid"> <thead> <tr> <th> <button type="button" class="btn btn-default btn-sm pull-left float-left" (click)="datePicker.move(-1)" tabindex="-1">‹</button></th> <th [attr.colspan]="((datePicker.monthColLimit - 2) <= 0) ? 1 : datePicker.monthColLimit - 2"> <button [id]="datePicker.uniqueId + '-title'" type="button" class="btn btn-default btn-sm" (click)="datePicker.toggleMode(0)" [disabled]="datePicker.datepickerMode === maxMode" [ngClass]="{disabled: datePicker.datepickerMode === maxMode}" tabindex="-1" style="width:100%;"> <strong>{{ title }}</strong> </button> </th> <th> <button type="button" class="btn btn-default btn-sm pull-right float-right" (click)="datePicker.move(1)" tabindex="-1">›</button> </th> </tr> </thead> <tbody> <tr *ngFor="let rowz of rows"> <td *ngFor="let dtz of rowz" class="text-center" role="gridcell" [attr.id]="dtz.uid" [ngClass]="dtz.customClass"> <button type="button" style="min-width:100%;" class="btn btn-default" [ngClass]="{'btn-link': isBs4 && !dtz.selected && !datePicker.isActive(dtz), 'btn-info': dtz.selected || (isBs4 && !dtz.selected && datePicker.isActive(dtz)), disabled: dtz.disabled, active: !isBs4 && datePicker.isActive(dtz)}" [disabled]="dtz.disabled" (click)="datePicker.select(dtz.date)" tabindex="-1"> <span [ngClass]="{'text-success': isBs4 && dtz.current, 'text-info': !isBs4 && dtz.current}">{{ dtz.label }}</span> </button> </td> </tr> </tbody> </table> `, styles: [` :host .btn-info .text-success { color: #fff !important; } `] }] } ]; // todo: key events implementation /** @nocollapse */ MonthPickerComponent.ctorParameters = () => [ { type: DatePickerInnerComponent, }, ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class YearPickerComponent { /** * @param {?} datePicker */ constructor(datePicker) { this.rows = []; this.datePicker = datePicker; } /** * @return {?} */ get isBs4() { return !isBs3(); } /** * @return {?} */ ngOnInit() { const /** @type {?} */ self = this; this.datePicker.stepYear = { years: this.datePicker.yearRange }; this.datePicker.setRefreshViewHandler(function () { const /** @type {?} */ years = new Array(this.yearRange); let /** @type {?} */ date; const /** @type {?} */ start = self.getStartingYear(this.activeDate.getFullYear()); for (let /** @type {?} */ i = 0; i < this.yearRange; i++) { date = new Date(start + i, 0, 1); date = this.fixTimeZone(date); years[i] = this.createDateObject(date, this.formatYear); years[i].uid = this.uniqueId + '-' + i; } self.title = [years[0].label, years[this.yearRange - 1].label].join(' - '); self.rows = this.split(years, self.datePicker.yearColLimit); }, 'year'); this.datePicker.setCompareHandler(function (date1, date2) { return date1.getFullYear() - date2.getFullYear(); }, 'year'); this.datePicker.refreshView(); } /** * @param {?} year * @return {?} */ getStartingYear(year) { // todo: parseInt return ((year - 1) / this.datePicker.yearRange * this.datePicker.yearRange + 1); } } YearPickerComponent.decorators = [ { type: Component, args: [{ selector: 'yearpicker', template: ` <table *ngIf="datePicker.datepickerMode==='year'" role="grid"> <thead> <tr> <th> <button type="button" class="btn btn-default btn-sm pull-left float-left" (click)="datePicker.move(-1)" tabindex="-1">‹</button> </th> <th [attr.colspan]="((datePicker.yearColLimit - 2) <= 0) ? 1 : datePicker.yearColLimit - 2"> <button [id]="datePicker.uniqueId + '-title'" role="heading" type="button" class="btn btn-default btn-sm" (click)="datePicker.toggleMode(0)" [disabled]="datePicker.datepickerMode === datePicker.maxMode" [ngClass]="{disabled: datePicker.datepickerMode === datePicker.maxMode}" tabindex="-1" style="width:100%;"> <strong>{{ title }}</strong> </button> </th> <th> <button type="button" class="btn btn-default btn-sm pull-right float-right" (click)="datePicker.move(1)" tabindex="-1">›</button> </th> </tr> </thead> <tbody> <tr *ngFor="let rowz of rows"> <td *ngFor="let dtz of rowz" class="text-center" role="gridcell" [attr.id]="dtz.uid"> <button type="button" style="min-width:100%;" class="btn btn-default" [ngClass]="{'btn-link': isBs4 && !dtz.selected && !datePicker.isActive(dtz), 'btn-info': dtz.selected || (isBs4 && !dtz.selected && datePicker.isActive(dtz)), disabled: dtz.disabled, active: !isBs4 && datePicker.isActive(dtz)}" [disabled]="dtz.disabled" (click)="datePicker.select(dtz.date)" tabindex="-1"> <span [ngClass]="{'text-success': isBs4 && dtz.current, 'text-info': !isBs4 && dtz.current}">{{ dtz.label }}</span> </button> </td> </tr> </tbody> </table> `, styles: [` :host .btn-info .text-success { color: #fff !important; } `] }] } ]; /** @nocollapse */ YearPickerComponent.ctorParameters = () => [ { type: DatePickerInnerComponent, }, ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class DatepickerModule { /** * @return {?} */ static forRoot() { return { ngModule: DatepickerModule, providers: [DatepickerConfig] }; } } DatepickerModule.decorators = [ { type: NgModule, args: [{ imports: [CommonModule, FormsModule], declarations: [ DatePickerComponent, DatePickerInnerComponent, DayPickerComponent, MonthPickerComponent, YearPickerComponent ], exports: [ DatePickerComponent, DatePickerInnerComponent, DayPickerComponent, MonthPickerComponent, YearPickerComponent ], entryComponents: [DatePickerComponent] },] } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @abstract */ class BsDatepickerAbstractComponent { constructor() { this._customRangesFish = []; } /** * @param {?} value * @return {?} */ set minDate(value) { this._effects.setMinDate(value); } /** * @param {?} value * @return {?} */ set maxDate(value) { this._effects.setMaxDate(value); } /** * @param {?} value * @return {?} */ set isDisabled(value) { this._effects.setDisabled(value); } /** * @param {?} event * @return {?} */ setViewMode(event) { } /** * @param {?} event * @return {?} */ navigateTo(event) { } /** * @param {?} event * @return {?} */ dayHoverHandler(event) { } /** * @param {?} event * @return {?} */ monthHoverHandler(event) { } /** * @param {?} event * @return {?} */ yearHoverHandler(event) { } /** * @param {?} day * @return {?} */ daySelectHandler(day) { } /** * @param {?} event * @return {?} */ monthSelectHandler(event) { } /** * @param {?} event * @return {?} */ yearSelectHandler(event) { } /** * @param {?} event * @return {?} */ _stopPropagation(event) { event.stopPropagation(); } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * For date range picker there are `BsDaterangepickerConfig` which inherits all properties, * except `displayMonths`, for range picker it default to `2` */ class BsDatepickerConfig { constructor() { /** * CSS class which will be applied to datepicker container, * usually used to set color theme */ this.containerClass = 'theme-green'; // DatepickerRenderOptions this.displayMonths = 1; /** * Allows to hide week numbers in datepicker */ this.showWeekNumbers = true; this.dateInputFormat = 'L'; // range picker this.rangeSeparator = ' - '; /** * Date format for date range input field */ this.rangeInputFormat = 'L'; // DatepickerFormatOptions this.monthTitle = 'MMMM'; this.yearTitle = 'YYYY'; this.dayLabel = 'D'; this.monthLabel = 'MMMM'; this.yearLabel = 'YYYY'; this.weekNumbers = 'w'; } } BsDatepickerConfig.decorators = [ { type: Injectable } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class BsDatepickerActions { /** * @return {?} */ calculate() { return { type: BsDatepickerActions.CALCULATE }; } /** * @return {?} */ format() { return { type: BsDatepickerActions.FORMAT }; } /** * @return {?} */ flag() { return { type: BsDatepickerActions.FLAG }; } /** * @param {?} date * @return {?} */ select(date) { return { type: BsDatepickerActions.SELECT, payload: date }; } /** * @param {?} event * @return {?} */ changeViewMode(event) { return { type: BsDatepickerActions.CHANGE_VIEWMODE, payload: event }; } /** * @param {?} event * @return {?} */ navigateTo(event) { return { type: BsDatepickerActions.NAVIGATE_TO, payload: event }; } /** * @param {?} step * @return {?} */ navigateStep(step) { return { type: BsDatepickerActions.NAVIGATE_OFFSET, payload: step }; } /** * @param {?} options * @return {?} */ setOptions(options) { return { type: BsDatepickerActions.SET_OPTIONS, payload: options }; } /** * @param {?} value * @return {?} */ selectRange(value) { return { type: BsDatepickerActions.SELECT_RANGE, payload: value }; } /** * @param {?} event * @return {?} */ hoverDay(event) { return { type: BsDatepickerActions.HOVER, payload: event.isHovered ? event.cell.date : null }; } /** * @param {?} date * @return {?} */ minDate(date) { return { type: BsDatepickerActions.SET_MIN_DATE, payload: date }; } /** * @param {?} date * @return {?} */ maxDate(date) { return { type: BsDatepickerActions.SET_MAX_DATE, payload: date }; } /** * @param {?} value * @return {?} */ isDisabled(value) { return { type: BsDatepickerActions.SET_IS_DISABLED, payload: value }; } /** * @param {?} locale * @return {?} */ setLocale(locale) { return { type: BsDatepickerActions.SET_LOCALE, payload: locale }; } } BsDatepickerActions.CALCULATE = '[datepicker] calculate dates matrix'; BsDatepickerActions.FORMAT = '[datepicker] format datepicker values'; BsDatepickerActions.FLAG = '[datepicker] set flags'; BsDatepickerActions.SELECT = '[datepicker] select date'; BsDatepickerActions.NAVIGATE_OFFSET = '[datepicker] shift view date'; BsDatepickerActions.NAVIGATE_TO = '[datepicker] change view date'; BsDatepickerActions.SET_OPTIONS = '[datepicker] update render options'; BsDatepickerActions.HOVER = '[datepicker] hover date'; BsDatepickerActions.CHANGE_VIEWMODE = '[datepicker] switch view mode'; BsDatepickerActions.SET_MIN_DATE = '[datepicker] set min date'; BsDatepickerActions.SET_MAX_DATE = '[datepicker] set max date'; BsDatepickerActions.SET_IS_DISABLED = '[datepicker] set is disabled'; BsDatepickerActions.SET_LOCALE = '[datepicker] set datepicker locale'; BsDatepickerActions.SELECT_RANGE = '[daterangepicker] select dates range'; BsDatepickerActions.decorators = [ { type: Injectable } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class BsLocaleService { constructor() { this._defaultLocale = 'en'; this._locale = new BehaviorSubject(this._defaultLocale); this._localeChange = this._locale.asObservable(); } /** * @return {?} */ get locale() { return this._locale; } /** * @return {?} */ get localeChange() { return this._localeChange; } /** * @return {?} */ get currentLocale() { return this._locale.getValue(); } /** * @param {?} locale * @return {?} */ use(locale) { if (locale === this.currentLocale) { return; } this._locale.next(locale); } } BsLocaleService.decorators = [ { type: Injectable } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class BsDatepickerEffects { /** * @param {?} _actions * @param {?} _localeService */ constructor(_actions, _localeService) { this._actions = _actions; this._localeService = _localeService; this._subs = []; } /** * @param {?} _bsDatepickerStore * @return {?} */ init(_bsDatepickerStore) { this._store = _bsDatepickerStore; return this; } /** * setters * @param {?} value * @return {?} */ setValue(value) { this._store.dispatch(this._actions.select(value)); } /** * @param {?} value * @return {?} */ setRangeValue(value) { this._store.dispatch(this._actions.selectRange(value)); } /** * @param {?} value * @return {?} */ setMinDate(value) { this._store.dispatch(this._actions.minDate(value)); return this; } /** * @param {?} value * @return {?} */ setMaxDate(value) { this._store.dispatch(this._actions.maxDate(value)); return this; } /** * @param {?} value * @return {?} */ setDisabled(value) { this._store.dispatch(this._actions.isDisabled(value)); return this; } /** * @param {?} _config * @return {?} */ setOptions(_config) { const /** @type {?} */ _options = Object.assign({ locale: this._localeService.currentLocale }, _config); this._store.dispatch(this._actions.setOptions(_options)); return this; } /** * view to mode bindings * @param {?} container * @return {?} */ setBindings(container) { container.daysCalendar = this._store .select(state => state.flaggedMonths) .pipe(filter(months => !!months)); // month calendar container.monthsCalendar = this._store .select(state => state.flaggedMonthsCalendar) .pipe(filter(months => !!months)); // year calendar container.yearsCalendar = this._store .select(state => state.yearsCalendarFlagged) .pipe(filter(years => !!years)); container.viewMode = this._store.select(state => state.view.mode); container.options = this._store .select(state => state.showWeekNumbers) .pipe(map(showWeekNumbers => ({ showWeekNumbers }))); return this; } /** * event handlers * @param {?} container * @return {?} */ setEventHandlers(container) { container.setViewMode = (event) => { this._store.dispatch(this._actions.changeViewMode(event)); }; container.navigateTo = (event) => { this._store.dispatch(this._actions.navigateStep(event.step)); }; container.dayHoverHandler = (event) => { const /** @type {?} */ _cell = /** @type {?} */ (event.cell); if (_cell.isOtherMonth || _cell.isDisabled) { return; } this._store.dispatch(this._actions.hoverDay(event)); _cell.isHovered = event.isHovered; }; container.monthHoverHandler = (event) => { event.cell.isHovered = event.isHovered; }; container.yearHoverHandler = (event) => { event.cell.isHovered = event.isHovered; }; /** select handlers */ // container.daySelectHandler = (day: DayViewModel): void => { // if (day.isOtherMonth || day.isDisabled) { // return; // } // this._store.dispatch(this._actions.select(day.date)); // }; container.monthSelectHandler = (event) => { if (event.isDisabled) { return; } this._store.dispatch(this._actions.navigateTo({ unit: { month: getMonth(event.date) }, viewMode: 'day' })); }; container.yearSelectHandler = (event) => { if (event.isDisabled) { return; } this._store.dispatch(this._actions.navigateTo({ unit: { year: getFullYear(event.date) }, viewMode: 'month' })); }; return this; } /** * @return {?} */ registerDatepickerSideEffects() { this._subs.push(this._store.select(state => state.view).subscribe(view => { this._store.dispatch(this._actions.calculate()); })); // format calendar values on month model change this._subs.push(this._store .select(state => state.monthsModel) .pipe(filter(monthModel => !!monthModel)) .subscribe(month => this._store.dispatch(this._actions.format()))); // flag day values this._subs.push(this._store .select(state => state.formattedMonths) .pipe(filter(month => !!month)) .subscribe(month => this._store.dispatch(this._actions.flag()))); // flag day values this._subs.push(this._store .select(state => state.selectedDate) .pipe(filter(selectedDate => !!selectedDate)) .subscribe(selectedDate => this._store.dispatch(this._actions.flag()))); // flag for date range picker this._subs.push(this._store .select(state => state.selectedRange) .pipe(filter(selectedRange => !!selectedRange)) .subscribe(selectedRange => this._store.dispatch(this._actions.flag()))); // monthsCalendar this._subs.push(this._store .select(state => state.monthsCalendar) .subscribe(() => this._store.dispatch(this._actions.flag()))); // years calendar this._subs.push(this._store .select(state => state.yearsCalendarModel) .pipe(filter(state => !!state)) .subscribe(() => this._store.dispatch(this._actions.flag()))); // on hover this._subs.push(this._store .select(state => state.hoveredDate) .pipe(filter(hoveredDate => !!hoveredDate)) .subscribe(hoveredDate => this._store.dispatch(this._actions.flag()))); // on locale change this._subs.push(this._localeService.localeChange .subscribe(locale => this._store.dispatch(this._actions.setLocale(locale)))); return this; } /** * @return {?} */ destroy() { for (const /** @type {?} */ sub of this._subs) { sub.unsubscribe(); } } } BsDatepickerEffects.decorators = [ { type: Injectable } ]; /** @nocollapse */ BsDatepickerEffects.ctorParameters = () => [ { type: BsDatepickerActions, }, { type: BsLocaleService, }, ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ const /** @type {?} */ defaultMonthOptions = { width: 7, height: 6 }; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ const /** @type {?} */ _initialView = { date: new Date(), mode: 'day' }; const /** @type {?} */ initialDatepickerState = Object.assign(new BsDatepickerConfig(), { locale: 'en', view: _initialView, selectedRange: [], monthViewOptions: defaultMonthOptions }); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @param {?} date * @param {?} options * @retur