igniteui-angular-sovn
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
462 lines (406 loc) • 11.8 kB
text/typescript
import {
Component,
Output,
EventEmitter,
Input,
HostListener,
ViewChildren,
QueryList,
HostBinding,
DoCheck,
OnInit,
Inject, LOCALE_ID
} from '@angular/core';
import { CalendarSelection, ICalendarDate, isDateInRanges } from '../../calendar/calendar';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { IgxDayItemComponent } from './day-item.component';
import { DateRangeDescriptor, DateRangeType } from '../../core/dates';
import { IgxCalendarBaseDirective } from '../calendar-base';
import { isEqual, PlatformUtil } from '../../core/utils';
import { IViewChangingEventArgs } from './days-view.interface';
import { IgxDaysViewNavigationService } from '../days-view/daysview-navigation.service';
import { NgIf, NgFor, TitleCasePipe } from '@angular/common';
let NEXT_ID = 0;
export class IgxDaysViewComponent extends IgxCalendarBaseDirective implements DoCheck, OnInit {
/**
* Sets/gets the `id` of the days view.
* If not set, the `id` will have value `"igx-days-view-0"`.
* ```html
* <igx-days-view id="my-days-view"></igx-days-view>
* ```
* ```typescript
* let daysViewId = this.daysView.id;
* ```
*/
public id = `igx-days-view-${NEXT_ID++}`;
/**
* @hidden
*/
public changeDaysView = false;
/**
* Show/hide week numbers
*
* @example
* ```html
* <igx-days-view [showWeekNumbers]="true"></igx-days-view>
* ``
*/
public showWeekNumbers: boolean;
/**
* @hidden
* @internal
*/
public set activeDate(value: string) {
this._activeDate = value;
this.activeDateChange.emit(this._activeDate);
}
public get activeDate() {
return this._activeDate ? this._activeDate : this.viewDate.toLocaleDateString();
}
/**
* @hidden
*/
public dateSelection = new EventEmitter<ICalendarDate>();
/**
* @hidden
*/
public viewChanging = new EventEmitter<IViewChangingEventArgs>();
/**
* @hidden
*/
public activeDateChange = new EventEmitter<string>();
/**
* @hidden
*/
public monthsViewBlur = new EventEmitter<any>();
/**
* @hidden
*/
public dates: QueryList<IgxDayItemComponent>;
/**
* The default css class applied to the component.
*
* @hidden
*/
public styleClass = true;
/**
* @hidden
*/
public outOfRangeDates: DateRangeDescriptor[];
/**
* @hidden
*/
public nextMonthView: IgxDaysViewComponent;
/** @hidden */
public prevMonthView: IgxDaysViewComponent;
/** @hidden */
public shouldResetDate = true;
private _activeDate;
/**
* @hidden
*/
constructor(
public daysNavService: IgxDaysViewNavigationService,
platform: PlatformUtil, _localeId: any
) {
super(platform, _localeId);
}
/**
* @hidden
* @internal
*/
public resetActiveMonth() {
if (this.shouldResetDate) {
const date = this.dates.find(day => day.selected && day.isCurrentMonth) ||
this.dates.find(day => day.isToday && day.isCurrentMonth) ||
this.dates.find(d => d.isFocusable);
if (date) {
this.activeDate = date.date.date.toLocaleDateString();
}
this.monthsViewBlur.emit();
}
this.shouldResetDate = true;
}
/**
* @hidden
* @internal
*/
public pointerDown() {
this.shouldResetDate = false;
}
/**
* @hidden
*/
public onKeydownArrow(event: KeyboardEvent) {
event.preventDefault();
event.stopPropagation();
this.shouldResetDate = false;
this.daysNavService.focusNextDate(event.target as HTMLElement, event.key);
}
/**
* @hidden
*/
public onKeydownHome(event: KeyboardEvent) {
event.preventDefault();
event.stopPropagation();
this.shouldResetDate = false;
this.getFirstMonthView().daysNavService.focusHomeDate();
}
/**
* @hidden
*/
public onKeydownEnd(event: KeyboardEvent) {
event.preventDefault();
event.stopPropagation();
this.shouldResetDate = false;
this.getLastMonthView().daysNavService.focusEndDate();
}
/**
* @hidden
*/
public get getCalendarMonth(): ICalendarDate[][] {
return this.calendarModel.monthdatescalendar(this.viewDate.getFullYear(), this.viewDate.getMonth(), true);
}
/**
* @hidden
*/
public ngOnInit() {
this.daysNavService.monthView = this;
}
/**
* @hidden
*/
public ngDoCheck() {
if (!this.changeDaysView && this.dates) {
this.disableOutOfRangeDates();
}
}
/**
* @hidden
* @internal
*/
public tabIndex(day: ICalendarDate): number {
return this.activeDate && this.activeDate === day.date.toLocaleDateString() && day.isCurrentMonth ? 0 : -1;
}
/**
* Returns the week number by date
*
* @hidden
*/
public getWeekNumber(date): number {
return this.calendarModel.getWeekNumber(date);
}
/**
* Returns the locale representation of the date in the days view.
*
* @hidden
*/
public formattedDate(value: Date): string {
if (this.formatViews.day) {
return this.formatterDay.format(value);
}
return `${value.getDate()}`;
}
/**
* @hidden
*/
public generateWeekHeader(): string[] {
const dayNames = [];
const rv = this.calendarModel.monthdatescalendar(this.viewDate.getFullYear(), this.viewDate.getMonth())[0];
for (const day of rv) {
dayNames.push(this.formatterWeekday.format(day.date));
}
return dayNames;
}
/**
* @hidden
*/
public rowTracker(index, item): string {
return `${item[index].date.getMonth()}${item[index].date.getDate()}`;
}
/**
* @hidden
*/
public dateTracker(index, item): string {
return `${item.date.getMonth()}--${item.date.getDate()}`;
}
/**
* @hidden
*/
public isCurrentMonth(value: Date): boolean {
return this.viewDate.getMonth() === value.getMonth();
}
/**
* @hidden
*/
public isCurrentYear(value: Date): boolean {
return this.viewDate.getFullYear() === value.getFullYear();
}
/**
* @hidden
*/
public isSelected(date: ICalendarDate): boolean {
let selectedDates: Date | Date[];
if (this.isDateDisabled(date.date) || !this.value ||
(Array.isArray(this.value) && this.value.length === 0)
) {
return false;
}
if (this.selection === CalendarSelection.SINGLE) {
selectedDates = (this.value as Date);
return this.getDateOnly(selectedDates).getTime() === date.date.getTime();
}
selectedDates = (this.value as Date[]);
if (this.selection === CalendarSelection.RANGE && selectedDates.length === 1) {
return this.getDateOnly(selectedDates[0]).getTime() === date.date.getTime();
}
if (this.selection === CalendarSelection.MULTI) {
const start = this.getDateOnly(selectedDates[0]);
const end = this.getDateOnly(selectedDates[selectedDates.length - 1]);
if (this.isWithinRange(date.date, false, start, end)) {
const currentDate = selectedDates.find(element => element.getTime() === date.date.getTime());
return !!currentDate;
} else {
return false;
}
} else {
return this.isWithinRange(date.date, true);
}
}
/**
* @hidden
*/
public isLastInRange(date: ICalendarDate): boolean {
if (this.isSingleSelection || !this.value) {
return false;
}
const dates = this.value as Date[];
const lastDate = dates[dates.length - 1];
return isEqual(lastDate, date.date);
}
/**
* @hidden
*/
public isFirstInRange(date: ICalendarDate): boolean {
if (this.isSingleSelection || !this.value) {
return false;
}
return isEqual((this.value as Date[])[0], date.date);
}
/**
* @hidden
*/
public isWithinRange(date: Date, checkForRange: boolean, min?: Date, max?: Date): boolean {
if (checkForRange && !(Array.isArray(this.value) && this.value.length > 1)) {
return false;
}
min = min ? min : this.value[0];
max = max ? max : this.value[(this.value as Date[]).length - 1];
return isDateInRanges(date,
[
{
type: DateRangeType.Between,
dateRange: [min, max]
}
]
);
}
/**
* @hidden
*/
public focusActiveDate() {
let date = this.dates.find((d) => d.selected);
if (!date) {
date = this.dates.find((d) => d.isToday);
}
if (date.isFocusable) {
date.nativeElement.focus();
}
}
/**
* @hidden
*/
public selectDay(event) {
this.selectDateFromClient(event.date);
this.dateSelection.emit(event);
this.selected.emit(this.selectedDates);
}
/**
* @hidden
*/
public getFirstMonthView(): IgxDaysViewComponent {
let monthView = this as IgxDaysViewComponent;
while (monthView.prevMonthView) {
monthView = monthView.prevMonthView;
}
return monthView;
}
/**
* @hidden
*/
private disableOutOfRangeDates() {
const dateRange = [];
this.dates.toArray().forEach((date) => {
if (!date.isCurrentMonth) {
dateRange.push(date.date.date);
}
});
this.outOfRangeDates = [{
type: DateRangeType.Specific,
dateRange
}];
}
/**
* @hidden
*/
private getLastMonthView(): IgxDaysViewComponent {
let monthView = this as IgxDaysViewComponent;
while (monthView.nextMonthView) {
monthView = monthView.nextMonthView;
}
return monthView;
}
/**
* @hidden
*/
private get isSingleSelection(): boolean {
return this.selection !== CalendarSelection.RANGE;
}
}