ngx-bootstrap
Version:
Native Angular Bootstrap Components
1,570 lines (1,554 loc) • 379 kB
JavaScript
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: `
<!--<!–ng-keydown="keydown($event)"–>-->
<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"><</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">>
</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