UNPKG

@danielmoncada/angular-datetime-picker

Version:
1,229 lines (1,221 loc) 231 kB
import { ɵɵdefineInjectable, Injectable, InjectionToken, inject, LOCALE_ID, Directive, Optional, Inject, Input, EventEmitter, Component, ChangeDetectionStrategy, ElementRef, NgZone, ChangeDetectorRef, Output, ViewChild, TemplateRef, Injector, SkipSelf, ViewContainerRef, forwardRef, Renderer2, Pipe, NgModule } from '@angular/core'; import { DOCUMENT, Location, getLocaleFirstDayOfWeek, CommonModule } from '@angular/common'; import { FocusTrapFactory, A11yModule } from '@angular/cdk/a11y'; import { NoopScrollStrategy, Overlay, OverlayConfig, OverlayContainer, OverlayModule } from '@angular/cdk/overlay'; import { BasePortalOutlet, CdkPortalOutlet, ComponentPortal, PortalInjector, PortalModule } from '@angular/cdk/portal'; import { SPACE, LEFT_ARROW, UP_ARROW, RIGHT_ARROW, DOWN_ARROW, ESCAPE, ENTER, PAGE_DOWN, PAGE_UP, END, HOME } from '@angular/cdk/keycodes'; import { coerceBooleanProperty, coerceNumberProperty, coerceArray } from '@angular/cdk/coercion'; import { Subject, Subscription, defer, merge, of } from 'rxjs'; import { take, filter, startWith, debounceTime } from 'rxjs/operators'; import { trigger, state, style, transition, group, query, animateChild, animate, keyframes } from '@angular/animations'; import { NG_VALUE_ACCESSOR, NG_VALIDATORS, Validators } from '@angular/forms'; import { Platform, PlatformModule } from '@angular/cdk/platform'; import * as _moment from 'moment'; import _moment__default from 'moment'; /** * date-time-picker-intl.service */ class OwlDateTimeIntl { constructor() { /** * Stream that emits whenever the labels here are changed. Use this to notify * components if the labels have changed after initialization. */ this.changes = new Subject(); /** A label for the up second button (used by screen readers). */ this.upSecondLabel = 'Add a second'; /** A label for the down second button (used by screen readers). */ this.downSecondLabel = 'Minus a second'; /** A label for the up minute button (used by screen readers). */ this.upMinuteLabel = 'Add a minute'; /** A label for the down minute button (used by screen readers). */ this.downMinuteLabel = 'Minus a minute'; /** A label for the up hour button (used by screen readers). */ this.upHourLabel = 'Add a hour'; /** A label for the down hour button (used by screen readers). */ this.downHourLabel = 'Minus a hour'; /** A label for the previous month button (used by screen readers). */ this.prevMonthLabel = 'Previous month'; /** A label for the next month button (used by screen readers). */ this.nextMonthLabel = 'Next month'; /** A label for the previous year button (used by screen readers). */ this.prevYearLabel = 'Previous year'; /** A label for the next year button (used by screen readers). */ this.nextYearLabel = 'Next year'; /** A label for the previous multi-year button (used by screen readers). */ this.prevMultiYearLabel = 'Previous 21 years'; /** A label for the next multi-year button (used by screen readers). */ this.nextMultiYearLabel = 'Next 21 years'; /** A label for the 'switch to month view' button (used by screen readers). */ this.switchToMonthViewLabel = 'Change to month view'; /** A label for the 'switch to year view' button (used by screen readers). */ this.switchToMultiYearViewLabel = 'Choose month and year'; /** A label for the cancel button */ this.cancelBtnLabel = 'Cancel'; /** A label for the set button */ this.setBtnLabel = 'Set'; /** A label for the range 'from' in picker info */ this.rangeFromLabel = 'From'; /** A label for the range 'to' in picker info */ this.rangeToLabel = 'To'; /** A label for the hour12 button (AM) */ this.hour12AMLabel = 'AM'; /** A label for the hour12 button (PM) */ this.hour12PMLabel = 'PM'; } } OwlDateTimeIntl.ɵprov = ɵɵdefineInjectable({ factory: function OwlDateTimeIntl_Factory() { return new OwlDateTimeIntl(); }, token: OwlDateTimeIntl, providedIn: "root" }); OwlDateTimeIntl.decorators = [ { type: Injectable, args: [{ providedIn: 'root' },] } ]; /** * date-time-adapter.class */ /** InjectionToken for date time picker that can be used to override default locale code. */ const OWL_DATE_TIME_LOCALE = new InjectionToken('OWL_DATE_TIME_LOCALE', { providedIn: 'root', factory: OWL_DATE_TIME_LOCALE_FACTORY }); /** @docs-private */ function OWL_DATE_TIME_LOCALE_FACTORY() { return inject(LOCALE_ID); } /** Provider for OWL_DATE_TIME_LOCALE injection token. */ const OWL_DATE_TIME_LOCALE_PROVIDER = { provide: OWL_DATE_TIME_LOCALE, useExisting: LOCALE_ID }; class DateTimeAdapter { constructor() { /** A stream that emits when the locale changes. */ this._localeChanges = new Subject(); /** total milliseconds in a day. */ this.millisecondsInDay = 86400000; /** total milliseconds in a minute. */ this.milliseondsInMinute = 60000; } get localeChanges() { return this._localeChanges; } /** * Compare two given dates * 1 if the first date is after the second, * -1 if the first date is before the second * 0 if dates are equal. * */ compare(first, second) { if (!this.isValid(first) || !this.isValid(second)) { throw Error('JSNativeDate: Cannot compare invalid dates.'); } const dateFirst = this.clone(first); const dateSecond = this.clone(second); const diff = this.getTime(dateFirst) - this.getTime(dateSecond); if (diff < 0) { return -1; } else if (diff > 0) { return 1; } else { // Return 0 if diff is 0; return NaN if diff is NaN return diff; } } /** * Check if two given dates are in the same year * 1 if the first date's year is after the second, * -1 if the first date's year is before the second * 0 if two given dates are in the same year * */ compareYear(first, second) { if (!this.isValid(first) || !this.isValid(second)) { throw Error('JSNativeDate: Cannot compare invalid dates.'); } const yearLeft = this.getYear(first); const yearRight = this.getYear(second); const diff = yearLeft - yearRight; if (diff < 0) { return -1; } else if (diff > 0) { return 1; } else { return 0; } } /** * Attempts to deserialize a value to a valid date object. This is different from parsing in that * deserialize should only accept non-ambiguous, locale-independent formats (e.g. a ISO 8601 * string). The default implementation does not allow any deserialization, it simply checks that * the given value is already a valid date object or null. The `<mat-datepicker>` will call this * method on all of it's `@Input()` properties that accept dates. It is therefore possible to * support passing values from your backend directly to these properties by overriding this method * to also deserialize the format used by your backend. */ deserialize(value) { if (value == null || (this.isDateInstance(value) && this.isValid(value))) { return value; } return this.invalid(); } /** * Sets the locale used for all dates. */ setLocale(locale) { this.locale = locale; this._localeChanges.next(locale); } /** * Get the locale used for all dates. * */ getLocale() { return this.locale; } /** * Clamp the given date between min and max dates. */ clampDate(date, min, max) { if (min && this.compare(date, min) < 0) { return min; } if (max && this.compare(date, max) > 0) { return max; } return date; } } /** * date-time-format.class */ /** InjectionToken for date time picker that can be used to override default format. */ const OWL_DATE_TIME_FORMATS = new InjectionToken('OWL_DATE_TIME_FORMATS'); /** * date-time.class */ let nextUniqueId = 0; var DateView; (function (DateView) { DateView["MONTH"] = "month"; DateView["YEAR"] = "year"; DateView["MULTI_YEARS"] = "multi-years"; })(DateView || (DateView = {})); class OwlDateTime { constructor(dateTimeAdapter, dateTimeFormats) { this.dateTimeAdapter = dateTimeAdapter; this.dateTimeFormats = dateTimeFormats; /** * Whether to show the second's timer */ this._showSecondsTimer = false; /** * Whether the timer is in hour12 format */ this._hour12Timer = false; /** * The view that the calendar should start in. */ this.startView = DateView.MONTH; /** * Whether to should only the year and multi-year views. */ this.yearOnly = false; /** * Whether to should only the multi-year view. */ this.multiyearOnly = false; /** * Hours to change per step */ this._stepHour = 1; /** * Minutes to change per step */ this._stepMinute = 1; /** * Seconds to change per step */ this._stepSecond = 1; /** * Whether to hide dates in other months at the start or end of the current month. */ this._hideOtherMonths = false; /** * Date Time Checker to check if the give dateTime is selectable */ this.dateTimeChecker = (dateTime) => { return (!!dateTime && (!this.dateTimeFilter || this.dateTimeFilter(dateTime)) && (!this.minDateTime || this.dateTimeAdapter.compare(dateTime, this.minDateTime) >= 0) && (!this.maxDateTime || this.dateTimeAdapter.compare(dateTime, this.maxDateTime) <= 0)); }; if (!this.dateTimeAdapter) { throw Error(`OwlDateTimePicker: No provider found for DateTimeAdapter. You must import one of the following ` + `modules at your application root: OwlNativeDateTimeModule, OwlMomentDateTimeModule, or provide a ` + `custom implementation.`); } if (!this.dateTimeFormats) { throw Error(`OwlDateTimePicker: No provider found for OWL_DATE_TIME_FORMATS. You must import one of the following ` + `modules at your application root: OwlNativeDateTimeModule, OwlMomentDateTimeModule, or provide a ` + `custom implementation.`); } this._id = `owl-dt-picker-${nextUniqueId++}`; } get showSecondsTimer() { return this._showSecondsTimer; } set showSecondsTimer(val) { this._showSecondsTimer = coerceBooleanProperty(val); } get hour12Timer() { return this._hour12Timer; } set hour12Timer(val) { this._hour12Timer = coerceBooleanProperty(val); } get stepHour() { return this._stepHour; } set stepHour(val) { this._stepHour = coerceNumberProperty(val, 1); } get stepMinute() { return this._stepMinute; } set stepMinute(val) { this._stepMinute = coerceNumberProperty(val, 1); } get stepSecond() { return this._stepSecond; } set stepSecond(val) { this._stepSecond = coerceNumberProperty(val, 1); } get firstDayOfWeek() { return this._firstDayOfWeek; } set firstDayOfWeek(value) { value = coerceNumberProperty(value); if (value > 6 || value < 0) { this._firstDayOfWeek = undefined; } else { this._firstDayOfWeek = value; } } get hideOtherMonths() { return this._hideOtherMonths; } set hideOtherMonths(val) { this._hideOtherMonths = coerceBooleanProperty(val); } get id() { return this._id; } get formatString() { return this.pickerType === 'both' ? this.dateTimeFormats.fullPickerInput : this.pickerType === 'calendar' ? this.dateTimeFormats.datePickerInput : this.dateTimeFormats.timePickerInput; } get disabled() { return false; } getValidDate(obj) { return this.dateTimeAdapter.isDateInstance(obj) && this.dateTimeAdapter.isValid(obj) ? obj : null; } } OwlDateTime.decorators = [ { type: Directive } ]; OwlDateTime.ctorParameters = () => [ { type: DateTimeAdapter, decorators: [{ type: Optional }] }, { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [OWL_DATE_TIME_FORMATS,] }] } ]; OwlDateTime.propDecorators = { showSecondsTimer: [{ type: Input }], hour12Timer: [{ type: Input }], startView: [{ type: Input }], yearOnly: [{ type: Input }], multiyearOnly: [{ type: Input }], stepHour: [{ type: Input }], stepMinute: [{ type: Input }], stepSecond: [{ type: Input }], firstDayOfWeek: [{ type: Input }], hideOtherMonths: [{ type: Input }] }; /** * calendar.component */ class OwlCalendarComponent { constructor(elmRef, pickerIntl, ngZone, cdRef, dateTimeAdapter, dateTimeFormats) { this.elmRef = elmRef; this.pickerIntl = pickerIntl; this.ngZone = ngZone; this.cdRef = cdRef; this.dateTimeAdapter = dateTimeAdapter; this.dateTimeFormats = dateTimeFormats; this.DateView = DateView; this._selecteds = []; /** * The view that the calendar should start in. */ this.startView = DateView.MONTH; /** * Whether to should only the year and multi-year views. */ this.yearOnly = false; /** * Whether to should only the multi-year view. */ this.multiyearOnly = false; /** Emits when the currently picker moment changes. */ this.pickerMomentChange = new EventEmitter(); /** Emits when the currently selected date changes. */ this.selectedChange = new EventEmitter(); /** Emits when any date is selected. */ this.userSelection = new EventEmitter(); /** * Emits the selected year. This doesn't imply a change on the selected date * */ this.yearSelected = new EventEmitter(); /** * Emits the selected month. This doesn't imply a change on the selected date * */ this.monthSelected = new EventEmitter(); this.intlChangesSub = Subscription.EMPTY; /** * Used for scheduling that focus should be moved to the active cell on the next tick. * We need to schedule it, rather than do it immediately, because we have to wait * for Angular to re-evaluate the view children. */ this.moveFocusOnNextTick = false; /** * Date filter for the month and year view */ this.dateFilterForViews = (date) => { return (!!date && (!this.dateFilter || this.dateFilter(date)) && (!this.minDate || this.dateTimeAdapter.compare(date, this.minDate) >= 0) && (!this.maxDate || this.dateTimeAdapter.compare(date, this.maxDate) <= 0)); }; this.intlChangesSub = this.pickerIntl.changes.subscribe(() => { this.cdRef.markForCheck(); }); } get minDate() { return this._minDate; } set minDate(value) { value = this.dateTimeAdapter.deserialize(value); value = this.getValidDate(value); this._minDate = value ? this.dateTimeAdapter.createDate(this.dateTimeAdapter.getYear(value), this.dateTimeAdapter.getMonth(value), this.dateTimeAdapter.getDate(value)) : null; } get maxDate() { return this._maxDate; } set maxDate(value) { value = this.dateTimeAdapter.deserialize(value); value = this.getValidDate(value); this._maxDate = value ? this.dateTimeAdapter.createDate(this.dateTimeAdapter.getYear(value), this.dateTimeAdapter.getMonth(value), this.dateTimeAdapter.getDate(value)) : null; } get pickerMoment() { return this._pickerMoment; } set pickerMoment(value) { value = this.dateTimeAdapter.deserialize(value); this._pickerMoment = this.getValidDate(value) || this.dateTimeAdapter.now(); } get selected() { return this._selected; } set selected(value) { value = this.dateTimeAdapter.deserialize(value); this._selected = this.getValidDate(value); } get selecteds() { return this._selecteds; } set selecteds(values) { this._selecteds = values.map(v => { v = this.dateTimeAdapter.deserialize(v); return this.getValidDate(v); }); } get periodButtonText() { return this.isMonthView ? this.dateTimeAdapter.format(this.pickerMoment, this.dateTimeFormats.monthYearLabel) : this.dateTimeAdapter.getYearName(this.pickerMoment); } get periodButtonLabel() { return this.isMonthView ? this.pickerIntl.switchToMultiYearViewLabel : this.pickerIntl.switchToMonthViewLabel; } get prevButtonLabel() { if (this._currentView === DateView.MONTH) { return this.pickerIntl.prevMonthLabel; } else if (this._currentView === DateView.YEAR) { return this.pickerIntl.prevYearLabel; } else { return null; } } get nextButtonLabel() { if (this._currentView === DateView.MONTH) { return this.pickerIntl.nextMonthLabel; } else if (this._currentView === DateView.YEAR) { return this.pickerIntl.nextYearLabel; } else { return null; } } get currentView() { return this._currentView; } set currentView(view) { this._currentView = view; this.moveFocusOnNextTick = true; } get isInSingleMode() { return this.selectMode === 'single'; } get isInRangeMode() { return (this.selectMode === 'range' || this.selectMode === 'rangeFrom' || this.selectMode === 'rangeTo'); } get showControlArrows() { return this._currentView !== DateView.MULTI_YEARS; } get isMonthView() { return this._currentView === DateView.MONTH; } /** * Bind class 'owl-dt-calendar' to host * */ get owlDTCalendarClass() { return true; } ngOnInit() { } ngAfterContentInit() { this._currentView = this.startView; } ngAfterViewChecked() { if (this.moveFocusOnNextTick) { this.moveFocusOnNextTick = false; this.focusActiveCell(); } } ngOnDestroy() { this.intlChangesSub.unsubscribe(); } /** * Toggle between month view and year view */ toggleViews() { let nextView = null; if (this._currentView === DateView.MONTH) { nextView = DateView.MULTI_YEARS; } else { if (this.multiyearOnly) { nextView = DateView.MULTI_YEARS; } else if (this.yearOnly) { nextView = this._currentView === DateView.YEAR ? DateView.MULTI_YEARS : DateView.YEAR; } else { nextView = DateView.MONTH; } } this.currentView = nextView; } /** * Handles user clicks on the previous button. * */ previousClicked() { this.pickerMoment = this.isMonthView ? this.dateTimeAdapter.addCalendarMonths(this.pickerMoment, -1) : this.dateTimeAdapter.addCalendarYears(this.pickerMoment, -1); this.pickerMomentChange.emit(this.pickerMoment); } /** * Handles user clicks on the next button. * */ nextClicked() { this.pickerMoment = this.isMonthView ? this.dateTimeAdapter.addCalendarMonths(this.pickerMoment, 1) : this.dateTimeAdapter.addCalendarYears(this.pickerMoment, 1); this.pickerMomentChange.emit(this.pickerMoment); } dateSelected(date) { if (!this.dateFilterForViews(date)) { return; } this.selectedChange.emit(date); /*if ((this.isInSingleMode && !this.dateTimeAdapter.isSameDay(date, this.selected)) || this.isInRangeMode) { this.selectedChange.emit(date); }*/ } /** * Change the pickerMoment value and switch to a specific view */ goToDateInView(date, view) { this.handlePickerMomentChange(date); if ((!this.yearOnly && !this.multiyearOnly) || (this.multiyearOnly && (view !== DateView.MONTH && view !== DateView.YEAR)) || (this.yearOnly && view !== DateView.MONTH)) { this.currentView = view; } return; } /** * Change the pickerMoment value */ handlePickerMomentChange(date) { this.pickerMoment = this.dateTimeAdapter.clampDate(date, this.minDate, this.maxDate); this.pickerMomentChange.emit(this.pickerMoment); return; } userSelected() { this.userSelection.emit(); } /** * Whether the previous period button is enabled. */ prevButtonEnabled() { return (!this.minDate || !this.isSameView(this.pickerMoment, this.minDate)); } /** * Whether the next period button is enabled. */ nextButtonEnabled() { return (!this.maxDate || !this.isSameView(this.pickerMoment, this.maxDate)); } /** * Focus to the host element * */ focusActiveCell() { this.ngZone.runOutsideAngular(() => { this.ngZone.onStable .asObservable() .pipe(take(1)) .subscribe(() => { this.elmRef.nativeElement .querySelector('.owl-dt-calendar-cell-active') .focus(); }); }); } selectYearInMultiYearView(normalizedYear) { this.yearSelected.emit(normalizedYear); } selectMonthInYearView(normalizedMonth) { this.monthSelected.emit(normalizedMonth); } /** * Whether the two dates represent the same view in the current view mode (month or year). */ isSameView(date1, date2) { if (this._currentView === DateView.MONTH) { return !!(date1 && date2 && this.dateTimeAdapter.getYear(date1) === this.dateTimeAdapter.getYear(date2) && this.dateTimeAdapter.getMonth(date1) === this.dateTimeAdapter.getMonth(date2)); } else if (this._currentView === DateView.YEAR) { return !!(date1 && date2 && this.dateTimeAdapter.getYear(date1) === this.dateTimeAdapter.getYear(date2)); } else { return false; } } /** * Get a valid date object */ getValidDate(obj) { return this.dateTimeAdapter.isDateInstance(obj) && this.dateTimeAdapter.isValid(obj) ? obj : null; } } OwlCalendarComponent.decorators = [ { type: Component, args: [{ selector: 'owl-date-time-calendar', exportAs: 'owlDateTimeCalendar', template: "<div class=\"owl-dt-calendar-control\">\n <!-- focus when keyboard tab (http://kizu.ru/en/blog/keyboard-only-focus/#x) -->\n <button class=\"owl-dt-control owl-dt-control-button owl-dt-control-arrow-button\"\n type=\"button\" tabindex=\"0\"\n [style.visibility]=\"showControlArrows? 'visible': 'hidden'\"\n [disabled]=\"!prevButtonEnabled()\"\n [attr.aria-label]=\"prevButtonLabel\"\n (click)=\"previousClicked()\">\n <span class=\"owl-dt-control-content owl-dt-control-button-content\" tabindex=\"-1\">\n <!-- <editor-fold desc=\"SVG Arrow Left\"> -->\n <svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n version=\"1.1\" x=\"0px\" y=\"0px\" viewBox=\"0 0 250.738 250.738\"\n style=\"enable-background:new 0 0 250.738 250.738;\" xml:space=\"preserve\"\n width=\"100%\" height=\"100%\">\n <path style=\"fill-rule: evenodd; clip-rule: evenodd;\" d=\"M96.633,125.369l95.053-94.533c7.101-7.055,7.101-18.492,0-25.546 c-7.1-7.054-18.613-7.054-25.714,0L58.989,111.689c-3.784,3.759-5.487,8.759-5.238,13.68c-0.249,4.922,1.454,9.921,5.238,13.681 l106.983,106.398c7.101,7.055,18.613,7.055,25.714,0c7.101-7.054,7.101-18.491,0-25.544L96.633,125.369z\"/>\n </svg>\n <!-- </editor-fold> -->\n </span>\n </button>\n <div class=\"owl-dt-calendar-control-content\">\n <button class=\"owl-dt-control owl-dt-control-button owl-dt-control-period-button\"\n type=\"button\" tabindex=\"0\"\n [attr.aria-label]=\"periodButtonLabel\"\n (click)=\"toggleViews()\">\n <span class=\"owl-dt-control-content owl-dt-control-button-content\" tabindex=\"-1\">\n {{periodButtonText}}\n\n <span class=\"owl-dt-control-button-arrow\"\n [style.transform]=\"'rotate(' + (isMonthView? 0 : 180) +'deg)'\">\n <!-- <editor-fold desc=\"SVG Arrow\"> -->\n <svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n width=\"50%\" height=\"50%\" viewBox=\"0 0 292.362 292.362\" style=\"enable-background:new 0 0 292.362 292.362;\"\n xml:space=\"preserve\">\n <g>\n <path d=\"M286.935,69.377c-3.614-3.617-7.898-5.424-12.848-5.424H18.274c-4.952,0-9.233,1.807-12.85,5.424\n C1.807,72.998,0,77.279,0,82.228c0,4.948,1.807,9.229,5.424,12.847l127.907,127.907c3.621,3.617,7.902,5.428,12.85,5.428\n s9.233-1.811,12.847-5.428L286.935,95.074c3.613-3.617,5.427-7.898,5.427-12.847C292.362,77.279,290.548,72.998,286.935,69.377z\"/>\n </g>\n </svg>\n <!-- </editor-fold> -->\n </span>\n </span>\n </button>\n </div>\n <button class=\"owl-dt-control owl-dt-control-button owl-dt-control-arrow-button\"\n type=\"button\" tabindex=\"0\"\n [style.visibility]=\"showControlArrows? 'visible': 'hidden'\"\n [disabled]=\"!nextButtonEnabled()\"\n [attr.aria-label]=\"nextButtonLabel\"\n (click)=\"nextClicked()\">\n <span class=\"owl-dt-control-content owl-dt-control-button-content\" tabindex=\"-1\">\n <!-- <editor-fold desc=\"SVG Arrow Right\"> -->\n <svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n viewBox=\"0 0 250.738 250.738\" style=\"enable-background:new 0 0 250.738 250.738;\" xml:space=\"preserve\">\n <path style=\"fill-rule:evenodd;clip-rule:evenodd;\" d=\"M191.75,111.689L84.766,5.291c-7.1-7.055-18.613-7.055-25.713,0\n c-7.101,7.054-7.101,18.49,0,25.544l95.053,94.534l-95.053,94.533c-7.101,7.054-7.101,18.491,0,25.545\n c7.1,7.054,18.613,7.054,25.713,0L191.75,139.05c3.784-3.759,5.487-8.759,5.238-13.681\n C197.237,120.447,195.534,115.448,191.75,111.689z\"/>\n </svg>\n <!-- </editor-fold> -->\n </span>\n </button>\n</div>\n<div class=\"owl-dt-calendar-main\" cdkMonitorSubtreeFocus [ngSwitch]=\"currentView\" tabindex=\"-1\">\n <owl-date-time-month-view\n *ngSwitchCase=\"DateView.MONTH\"\n [pickerMoment]=\"pickerMoment\"\n [firstDayOfWeek]=\"firstDayOfWeek\"\n [selected]=\"selected\"\n [selecteds]=\"selecteds\"\n [selectMode]=\"selectMode\"\n [minDate]=\"minDate\"\n [maxDate]=\"maxDate\"\n [dateFilter]=\"dateFilter\"\n [hideOtherMonths]=\"hideOtherMonths\"\n (pickerMomentChange)=\"handlePickerMomentChange($event)\"\n (selectedChange)=\"dateSelected($event)\"\n (userSelection)=\"userSelected()\"></owl-date-time-month-view>\n\n <owl-date-time-year-view\n *ngSwitchCase=\"DateView.YEAR\"\n [pickerMoment]=\"pickerMoment\"\n [selected]=\"selected\"\n [selecteds]=\"selecteds\"\n [selectMode]=\"selectMode\"\n [minDate]=\"minDate\"\n [maxDate]=\"maxDate\"\n [dateFilter]=\"dateFilter\"\n (keyboardEnter)=\"focusActiveCell()\"\n (pickerMomentChange)=\"handlePickerMomentChange($event)\"\n (monthSelected)=\"selectMonthInYearView($event)\"\n (change)=\"goToDateInView($event, DateView.MONTH)\"></owl-date-time-year-view>\n\n <owl-date-time-multi-year-view\n *ngSwitchCase=\"DateView.MULTI_YEARS\"\n [pickerMoment]=\"pickerMoment\"\n [selected]=\"selected\"\n [selecteds]=\"selecteds\"\n [selectMode]=\"selectMode\"\n [minDate]=\"minDate\"\n [maxDate]=\"maxDate\"\n [dateFilter]=\"dateFilter\"\n (keyboardEnter)=\"focusActiveCell()\"\n (pickerMomentChange)=\"handlePickerMomentChange($event)\"\n (yearSelected)=\"selectYearInMultiYearView($event)\"\n (change)=\"goToDateInView($event, DateView.YEAR)\"></owl-date-time-multi-year-view>\n</div>\n", host: { '[class.owl-dt-calendar]': 'owlDTCalendarClass' }, preserveWhitespaces: false, changeDetection: ChangeDetectionStrategy.OnPush, styles: [""] },] } ]; OwlCalendarComponent.ctorParameters = () => [ { type: ElementRef }, { type: OwlDateTimeIntl }, { type: NgZone }, { type: ChangeDetectorRef }, { type: DateTimeAdapter, decorators: [{ type: Optional }] }, { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [OWL_DATE_TIME_FORMATS,] }] } ]; OwlCalendarComponent.propDecorators = { minDate: [{ type: Input }], maxDate: [{ type: Input }], pickerMoment: [{ type: Input }], selected: [{ type: Input }], selecteds: [{ type: Input }], dateFilter: [{ type: Input }], firstDayOfWeek: [{ type: Input }], selectMode: [{ type: Input }], startView: [{ type: Input }], yearOnly: [{ type: Input }], multiyearOnly: [{ type: Input }], hideOtherMonths: [{ type: Input }], pickerMomentChange: [{ type: Output }], selectedChange: [{ type: Output }], userSelection: [{ type: Output }], yearSelected: [{ type: Output }], monthSelected: [{ type: Output }] }; /** * timer.component */ class OwlTimerComponent { constructor(ngZone, elmRef, pickerIntl, cdRef, dateTimeAdapter) { this.ngZone = ngZone; this.elmRef = elmRef; this.pickerIntl = pickerIntl; this.cdRef = cdRef; this.dateTimeAdapter = dateTimeAdapter; this.isPM = false; // a flag indicates the current timer moment is in PM or AM /** * Hours to change per step */ this.stepHour = 1; /** * Minutes to change per step */ this.stepMinute = 1; /** * Seconds to change per step */ this.stepSecond = 1; this.selectedChange = new EventEmitter(); } get pickerMoment() { return this._pickerMoment; } set pickerMoment(value) { value = this.dateTimeAdapter.deserialize(value); this._pickerMoment = this.getValidDate(value) || this.dateTimeAdapter.now(); } get minDateTime() { return this._minDateTime; } set minDateTime(value) { value = this.dateTimeAdapter.deserialize(value); this._minDateTime = this.getValidDate(value); } get maxDateTime() { return this._maxDateTime; } set maxDateTime(value) { value = this.dateTimeAdapter.deserialize(value); this._maxDateTime = this.getValidDate(value); } get hourValue() { return this.dateTimeAdapter.getHours(this.pickerMoment); } /** * The value would be displayed in hourBox. * We need this because the value displayed in hourBox it not * the same as the hourValue when the timer is in hour12Timer mode. * */ get hourBoxValue() { let hours = this.hourValue; if (!this.hour12Timer) { return hours; } else { if (hours === 0) { hours = 12; this.isPM = false; } else if (hours > 0 && hours < 12) { this.isPM = false; } else if (hours === 12) { this.isPM = true; } else if (hours > 12 && hours < 24) { hours = hours - 12; this.isPM = true; } return hours; } } get minuteValue() { return this.dateTimeAdapter.getMinutes(this.pickerMoment); } get secondValue() { return this.dateTimeAdapter.getSeconds(this.pickerMoment); } get upHourButtonLabel() { return this.pickerIntl.upHourLabel; } get downHourButtonLabel() { return this.pickerIntl.downHourLabel; } get upMinuteButtonLabel() { return this.pickerIntl.upMinuteLabel; } get downMinuteButtonLabel() { return this.pickerIntl.downMinuteLabel; } get upSecondButtonLabel() { return this.pickerIntl.upSecondLabel; } get downSecondButtonLabel() { return this.pickerIntl.downSecondLabel; } get hour12ButtonLabel() { return this.isPM ? this.pickerIntl.hour12PMLabel : this.pickerIntl.hour12AMLabel; } get owlDTTimerClass() { return true; } get owlDTTimeTabIndex() { return -1; } ngOnInit() { } /** * Focus to the host element * */ focus() { this.ngZone.runOutsideAngular(() => { this.ngZone.onStable .asObservable() .pipe(take(1)) .subscribe(() => { this.elmRef.nativeElement.focus(); }); }); } /** * Set the hour value via typing into timer box input * We need this to handle the hour value when the timer is in hour12 mode * */ setHourValueViaInput(hours) { if (this.hour12Timer && this.isPM && hours >= 1 && hours <= 11) { hours = hours + 12; } else if (this.hour12Timer && !this.isPM && hours === 12) { hours = 0; } this.setHourValue(hours); } setHourValue(hours) { const m = this.dateTimeAdapter.setHours(this.pickerMoment, hours); this.selectedChange.emit(m); this.cdRef.markForCheck(); } setMinuteValue(minutes) { const m = this.dateTimeAdapter.setMinutes(this.pickerMoment, minutes); this.selectedChange.emit(m); this.cdRef.markForCheck(); } setSecondValue(seconds) { const m = this.dateTimeAdapter.setSeconds(this.pickerMoment, seconds); this.selectedChange.emit(m); this.cdRef.markForCheck(); } setMeridiem(event) { this.isPM = !this.isPM; let hours = this.hourValue; if (this.isPM) { hours = hours + 12; } else { hours = hours - 12; } if (hours >= 0 && hours <= 23) { this.setHourValue(hours); } this.cdRef.markForCheck(); event.preventDefault(); } /** * Check if the up hour button is enabled */ upHourEnabled() { return (!this.maxDateTime || this.compareHours(this.stepHour, this.maxDateTime) < 1); } /** * Check if the down hour button is enabled */ downHourEnabled() { return (!this.minDateTime || this.compareHours(-this.stepHour, this.minDateTime) > -1); } /** * Check if the up minute button is enabled */ upMinuteEnabled() { return (!this.maxDateTime || this.compareMinutes(this.stepMinute, this.maxDateTime) < 1); } /** * Check if the down minute button is enabled */ downMinuteEnabled() { return (!this.minDateTime || this.compareMinutes(-this.stepMinute, this.minDateTime) > -1); } /** * Check if the up second button is enabled */ upSecondEnabled() { return (!this.maxDateTime || this.compareSeconds(this.stepSecond, this.maxDateTime) < 1); } /** * Check if the down second button is enabled */ downSecondEnabled() { return (!this.minDateTime || this.compareSeconds(-this.stepSecond, this.minDateTime) > -1); } /** * PickerMoment's hour value +/- certain amount and compare it to the give date * 1 is after the comparedDate * -1 is before the comparedDate * 0 is equal the comparedDate * */ compareHours(amount, comparedDate) { const hours = this.dateTimeAdapter.getHours(this.pickerMoment) + amount; const result = this.dateTimeAdapter.setHours(this.pickerMoment, hours); return this.dateTimeAdapter.compare(result, comparedDate); } /** * PickerMoment's minute value +/- certain amount and compare it to the give date * 1 is after the comparedDate * -1 is before the comparedDate * 0 is equal the comparedDate * */ compareMinutes(amount, comparedDate) { const minutes = this.dateTimeAdapter.getMinutes(this.pickerMoment) + amount; const result = this.dateTimeAdapter.setMinutes(this.pickerMoment, minutes); return this.dateTimeAdapter.compare(result, comparedDate); } /** * PickerMoment's second value +/- certain amount and compare it to the give date * 1 is after the comparedDate * -1 is before the comparedDate * 0 is equal the comparedDate * */ compareSeconds(amount, comparedDate) { const seconds = this.dateTimeAdapter.getSeconds(this.pickerMoment) + amount; const result = this.dateTimeAdapter.setSeconds(this.pickerMoment, seconds); return this.dateTimeAdapter.compare(result, comparedDate); } /** * Get a valid date object */ getValidDate(obj) { return this.dateTimeAdapter.isDateInstance(obj) && this.dateTimeAdapter.isValid(obj) ? obj : null; } } OwlTimerComponent.decorators = [ { type: Component, args: [{ exportAs: 'owlDateTimeTimer', selector: 'owl-date-time-timer', template: "<owl-date-time-timer-box\n [upBtnAriaLabel]=\"upHourButtonLabel\"\n [downBtnAriaLabel]=\"downHourButtonLabel\"\n [upBtnDisabled]=\"!upHourEnabled()\"\n [downBtnDisabled]=\"!downHourEnabled()\"\n [boxValue]=\"hourBoxValue\"\n [value]=\"hourValue\" [min]=\"0\" [max]=\"23\"\n [step]=\"stepHour\" [inputLabel]=\"'Hour'\"\n (inputChange)=\"setHourValueViaInput($event)\"\n (valueChange)=\"setHourValue($event)\"></owl-date-time-timer-box>\n<owl-date-time-timer-box\n [showDivider]=\"true\"\n [upBtnAriaLabel]=\"upMinuteButtonLabel\"\n [downBtnAriaLabel]=\"downMinuteButtonLabel\"\n [upBtnDisabled]=\"!upMinuteEnabled()\"\n [downBtnDisabled]=\"!downMinuteEnabled()\"\n [value]=\"minuteValue\" [min]=\"0\" [max]=\"59\"\n [step]=\"stepMinute\" [inputLabel]=\"'Minute'\"\n (inputChange)=\"setMinuteValue($event)\"\n (valueChange)=\"setMinuteValue($event)\"></owl-date-time-timer-box>\n<owl-date-time-timer-box\n *ngIf=\"showSecondsTimer\"\n [showDivider]=\"true\"\n [upBtnAriaLabel]=\"upSecondButtonLabel\"\n [downBtnAriaLabel]=\"downSecondButtonLabel\"\n [upBtnDisabled]=\"!upSecondEnabled()\"\n [downBtnDisabled]=\"!downSecondEnabled()\"\n [value]=\"secondValue\" [min]=\"0\" [max]=\"59\"\n [step]=\"stepSecond\" [inputLabel]=\"'Second'\"\n (inputChange)=\"setSecondValue($event)\"\n (valueChange)=\"setSecondValue($event)\"></owl-date-time-timer-box>\n\n<div *ngIf=\"hour12Timer\" class=\"owl-dt-timer-hour12\">\n <button class=\"owl-dt-control-button owl-dt-timer-hour12-box\"\n type=\"button\" tabindex=\"0\"\n (click)=\"setMeridiem($event)\">\n <span class=\"owl-dt-control-button-content\" tabindex=\"-1\">\n {{hour12ButtonLabel}}\n </span>\n </button>\n</div>\n", preserveWhitespaces: false, changeDetection: ChangeDetectionStrategy.OnPush, host: { '[class.owl-dt-timer]': 'owlDTTimerClass', '[attr.tabindex]': 'owlDTTimeTabIndex' }, styles: [""] },] } ]; OwlTimerComponent.ctorParameters = () => [ { type: NgZone }, { type: ElementRef }, { type: OwlDateTimeIntl }, { type: ChangeDetectorRef }, { type: DateTimeAdapter, decorators: [{ type: Optional }] } ]; OwlTimerComponent.propDecorators = { pickerMoment: [{ type: Input }], minDateTime: [{ type: Input }], maxDateTime: [{ type: Input }], showSecondsTimer: [{ type: Input }], hour12Timer: [{ type: Input }], stepHour: [{ type: Input }], stepMinute: [{ type: Input }], stepSecond: [{ type: Input }], selectedChange: [{ type: Output }] }; /** * date-time-picker.animations */ const owlDateTimePickerAnimations = { transformPicker: trigger('transformPicker', [ state('void', style({ opacity: 0, transform: 'scale(1, 0)' })), state('enter', style({ opacity: 1, transform: 'scale(1, 1)' })), transition('void => enter', group([ query('@fadeInPicker', animateChild(), { optional: true }), animate('400ms cubic-bezier(0.25, 0.8, 0.25, 1)') ])), transition('enter => void', animate('100ms linear', style({ opacity: 0 }))) ]), fadeInPicker: trigger('fadeInPicker', [ state('enter', style({ opacity: 1 })), state('void', style({ opacity: 0 })), transition('void => enter', animate('400ms 100ms cubic-bezier(0.55, 0, 0.55, 0.2)')), ]) }; /** * date-time-picker-container.component */ class OwlDateTimeContainerComponent { constructor(cdRef, elmRef, pickerIntl, dateTimeAdapter) { this.cdRef = cdRef; this.elmRef = elmRef; this.pickerIntl = pickerIntl; this.dateTimeAdapter = dateTimeAdapter; this.activeSelectedIndex = 0; // The current active SelectedIndex in range select mode (0: 'from', 1: 'to') /** * Stream emits when try to hide picker * */ this.hidePicker$ = new Subject(); /** * Stream emits when try to confirm the selected value * */ this.confirmSelected$ = new Subject(); this.pickerOpened$ = new Subject(); } get hidePickerStream() { return this.hidePicker$.asObservable(); } get confirmSelectedStream() { return this.confirmSelected$.asObservable(); } get pickerOpenedStream() { return this.pickerOpened$.asObservable(); } get pickerMoment() { return this._clamPickerMoment; } set pickerMoment(value) { if (value) { this._clamPickerMoment = this.dateTimeAdapter.clampDate(value, this.picker.minDateTime, this.picker.maxDateTime); } this.cdRef.markForCheck(); } get pickerType() { return this.picker.pickerType; } get cancelLabel() { return this.pickerIntl.cancelBtnLabel; } get setLabel() { return this.pickerIntl.setBtnLabel; } /** * The range 'from' label * */ get fromLabel() { return this.pickerIntl.rangeFromLabel; } /** * The range 'to' label * */ get toLabel() { return this.pickerIntl.rangeToLabel; } /** * The range 'from' formatted value * */ get fromFormattedValue() { const value = this.picker.selecteds[0]; return value ? this.dateTimeAdapter.format(value, this.picker.formatString) : ''; } /** * The range 'to' formatted value * */ get toFormattedValue() { const value = this.picker.selecteds[1]; return value ? this.dateTimeAdapter.format(value, this.picker.formatString) : ''; } /** * Cases in which the control buttons show in the picker * 1) picker mode is 'dialog' * 2) picker type is NOT 'calendar' and the picker mode is NOT 'inline' * */ get showControlButtons() { return (this.picker.pickerMode === 'dialog' || (this.picker.pickerType !== 'calendar' && this.picker.pickerMode !== 'inline')); } get containerElm() { return this.elmRef.nativeElement; } get owlDTContainerClass() { return true; } get owlDTPopupContainerClass() { return this.picker.pickerMode === 'popup'; } get owlDTDialogContainerClass() { return this.picker.pickerMode === 'dialog'; } get owlDTInlineContainerClass() { return this.picker.pickerMode === 'inline'; } get owlDTContainerDisabledClass() { return this.picker.disabled; } get owlDTContainerId() { return this.picker.id; } get owlDTContainerAnimation() { return this.picker.pickerMode === 'inline' ? '' : 'enter'; } ngOnInit() { if (this.picker.selectMode === 'range') { if (this.picker.selecteds[0]) { this.retainStartTime = this.dateTimeAdapter.clone(this.picker.selecteds[0]); } if (this.picker.selecteds[1]) { this.retainEndTime = this.dateTimeAdapter.clone(this.picker.selecteds[1]); } } } ngAfterContentInit() { this.initPicker(); } ngAfterViewInit() { this.focusPicker(); } handleContainerAnimationDone(event) { const toState = event.toState; if (toState === 'enter') { this.pickerOpened$.next(); } } dateSelected(date) { let result; if (this.picker.isInSingleMode) { result = this.dateSelectedInSingleMode(date); if (result) { this.pickerMoment = result; this.picker.select(result); } else { // we close the picker when result is null and pickerType is calendar. if (this.pickerType === 'calendar') { this.hidePicker$.next(null); } } return; } if (this.picker.isInRangeMode) { result = this.dateSelectedInRangeMode(date); if (result) { this.pickerMoment = result[this.activeSelectedIndex]; this.picker.select(result); } } } timeSelected(time) { this.pickerMoment = this.dateTimeAdapter.clone(time); if (!this.picker.dateTimeChecker(this.pickerMoment)) { return; } if (this.picker.isInSingleMode) { this.picker.select(this.pickerMoment); return; } if (this.picker.isInRangeMode) { const selecteds = [...this.picker.selecteds]; // check if the 'from' is after 'to' or 'to'is before 'from' // In this case, we set both the 'from' and 'to' the same value if ((this.activeSelectedIndex === 0 && selecteds[1] && this.dateTimeAdapter.compare(this.pickerMoment, selecteds[1]) === 1) || (this.activeSelectedIndex === 1 && selecteds[0] && this.dateTimeAdapter.compare(this.pickerMoment, selecteds[0]) === -1)) { selecteds[0] = this.pickerMoment; selecteds[1] = this.pickerMoment; } else { selecteds[this.activeSelectedIndex] = this.pickerMoment; } if (selecteds[0]) { this.retainStartTime = this.dateTimeAdapter.clone(selecteds[0]); } if (selecteds[1]) { this.retainEndTime = this.dateTimeAdapter.clone(selecteds[1]); } this.picker.select(selecteds); } } /** * Handle click on cancel button */ onCancelClicked(event) { this.hidePicker$.next(null); event.preventDefault(); return; } /** * Handle click on set button */ onSetClicked(event) { if (!this.picker.dateTimeChecker(this.pickerMoment)) { this.hidePicker$.next(null); even