igniteui-angular-sovn
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
418 lines (367 loc) • 10.8 kB
text/typescript
import {
Component,
Output,
EventEmitter,
Input,
HostBinding,
HostListener,
ViewChildren,
QueryList,
ElementRef
} from '@angular/core';
import { Calendar } from '../calendar';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { IgxCalendarMonthDirective } from '../calendar.directives';
import { noop } from 'rxjs';
import { NgFor, TitleCasePipe, DatePipe } from '@angular/common';
let NEXT_ID = 0;
export class IgxMonthsViewComponent implements ControlValueAccessor {
/**
* Sets/gets the `id` of the months view.
* If not set, the `id` will have value `"igx-months-view-0"`.
* ```html
* <igx-months-view id="my-months-view"></igx-months-view>
* ```
* ```typescript
* let monthsViewId = this.monthsView.id;
* ```
*
* @memberof IgxMonthsViewComponent
*/
public id = `igx-months-view-${NEXT_ID++}`;
/**
* Gets/sets the selected date of the months view.
* By default it is the current date.
* ```html
* <igx-months-view [date]="myDate"></igx-months-view>
* ```
* ```typescript
* let date = this.monthsView.date;
* ```
*
* @memberof IgxMonthsViewComponent
*/
public set date(value: Date) {
if (!(value instanceof Date)) {
return;
}
this._date = value;
this.activeMonth = this.date.getMonth();
}
public get date() {
return this._date;
}
/**
* Gets the month format option of the months view.
* ```typescript
* let monthFormat = this.monthsView.monthFormat.
* ```
*/
public get monthFormat(): any {
return this._monthFormat;
}
/**
* Sets the month format option of the months view.
* ```html
* <igx-months-view> [monthFormat] = "short'"</igx-months-view>
* ```
*
* @memberof IgxMonthsViewComponent
*/
public set monthFormat(value: any) {
this._monthFormat = value;
this.initMonthFormatter();
}
/**
* Gets the `locale` of the months view.
* Default value is `"en"`.
* ```typescript
* let locale = this.monthsView.locale;
* ```
*
* @memberof IgxMonthsViewComponent
*/
public get locale(): string {
return this._locale;
}
/**
* Sets the `locale` of the months view.
* Expects a valid BCP 47 language tag.
* Default value is `"en"`.
* ```html
* <igx-months-view [locale]="de"></igx-months-view>
* ```
*
* @memberof IgxMonthsViewComponent
*/
public set locale(value: string) {
this._locale = value;
this.initMonthFormatter();
}
/**
* Gets/sets whether the view should be rendered
* according to the locale and monthFormat, if any.
*/
public formatView = true;
/**
* Emits an event when a selection is made in the months view.
* Provides reference the `date` property in the `IgxMonthsViewComponent`.
* ```html
* <igx-months-view (selected)="onSelection($event)"></igx-months-view>
* ```
*
* @memberof IgxMonthsViewComponent
*/
public selected = new EventEmitter<Date>();
/**
* The default css class applied to the component.
*
* @hidden
*/
public styleClass = true;
/**
* @hidden
*/
public monthsRef: QueryList<IgxCalendarMonthDirective>;
/**
* Returns an array of date objects which are then used to
* properly render the month names.
*
* Used in the template of the component
*
* @hidden
*/
public get months(): Date[] {
let start = new Date(this.date.getFullYear(), 0, 1);
const result = [];
for (let i = 0; i < 12; i++) {
result.push(start);
start = this._calendarModel.timedelta(start, 'month', 1);
}
return result;
}
/**
* @hidden
* @internal
*/
public activeMonth;
private _date = new Date();
/**
* @hidden
*/
private _formatterMonth: any;
/**
* @hidden
*/
private _locale = 'en';
/**
* @hidden
*/
private _monthFormat = 'short';
/**
* @hidden
*/
private _calendarModel: Calendar;
/**
* @hidden
*/
private _onTouchedCallback: () => void = noop;
/**
* @hidden
*/
private _onChangeCallback: (_: Date) => void = noop;
constructor(public el: ElementRef) {
this.initMonthFormatter();
this._calendarModel = new Calendar();
}
/**
* @hidden
*/
public onKeydownArrowUp(event: KeyboardEvent) {
event.preventDefault();
event.stopPropagation();
const node = this.monthsRef.find((date) => date.nativeElement === event.target);
if (!node) {
return;
}
const months = this.monthsRef.toArray();
const nodeRect = node.nativeElement.getBoundingClientRect();
for (let index = months.indexOf(node) - 1; index >= 0; index--) {
const nextNodeRect = months[index].nativeElement.getBoundingClientRect();
const tolerance = 6;
if (nodeRect.top !== nextNodeRect.top && (nextNodeRect.left - nodeRect.left) < tolerance) {
const month = months[index];
month.nativeElement.focus();
this.activeMonth = month.value.getMonth();
break;
}
}
}
/**
* @hidden
*/
public onKeydownArrowDown(event: KeyboardEvent) {
event.preventDefault();
event.stopPropagation();
const node = this.monthsRef.find((date) => date.nativeElement === event.target);
if (!node) {
return;
}
const months = this.monthsRef.toArray();
const nodeRect = node.nativeElement.getBoundingClientRect();
for (let index = months.indexOf(node) + 1; index < months.length; index++) {
const nextNodeRect = months[index].nativeElement.getBoundingClientRect();
const tolerance = 6;
if (nextNodeRect.top !== nodeRect.top && (nodeRect.left - nextNodeRect.left) < tolerance ) {
const month = months[index];
month.nativeElement.focus();
this.activeMonth = month.value.getMonth();
break;
}
}
}
/**
* @hidden
*/
public onKeydownArrowRight(event: KeyboardEvent) {
event.preventDefault();
event.stopPropagation();
const node = this.monthsRef.find((date) => date.nativeElement === event.target);
if (!node) {
return;
}
const months = this.monthsRef.toArray();
if (months.indexOf(node) + 1 < months.length) {
const month = months[months.indexOf(node) + 1];
this.activeMonth = month.value.getMonth();
month.nativeElement.focus();
}
}
/**
* @hidden
*/
public onKeydownArrowLeft(event: KeyboardEvent) {
event.preventDefault();
event.stopPropagation();
const node = this.monthsRef.find((date) => date.nativeElement === event.target);
if (!node) {
return;
}
const months = this.monthsRef.toArray();
if (months.indexOf(node) - 1 >= 0) {
const month = months[months.indexOf(node) - 1];
this.activeMonth = month.value.getMonth();
month.nativeElement.focus();
}
}
/**
* @hidden
*/
public onKeydownHome(event: KeyboardEvent) {
event.preventDefault();
event.stopPropagation();
const month = this.monthsRef.toArray()[0];
this.activeMonth = month.value.getMonth();
month.nativeElement.focus();
}
/**
* @hidden
*/
public onKeydownEnd(event: KeyboardEvent) {
event.preventDefault();
event.stopPropagation();
const months = this.monthsRef.toArray();
const month = months[months.length - 1];
this.activeMonth = month.value.getMonth();
month.nativeElement.focus();
}
/**
* @hidden
*/
public onKeydownEnter(event) {
const value = this.monthsRef.find((date) => date.nativeElement === event.target).value;
this.date = new Date(value.getFullYear(), value.getMonth(), this.date.getDate());
this.activeMonth = this.date.getMonth();
this.selected.emit(this.date);
this._onChangeCallback(this.date);
}
public resetActiveMonth() {
this.activeMonth = this.date.getMonth();
}
/**
* Returns the locale representation of the month in the months view.
*
* @hidden
*/
public formattedMonth(value: Date): string {
if (this.formatView) {
return this._formatterMonth.format(value);
}
return `${value.getMonth()}`;
}
/**
* @hidden
*/
public selectMonth(event) {
this.selected.emit(event);
this.date = event;
this.activeMonth = this.date.getMonth();
this._onChangeCallback(this.date);
}
/**
* @hidden
*/
public registerOnChange(fn: (v: Date) => void) {
this._onChangeCallback = fn;
}
/**
* @hidden
*/
public registerOnTouched(fn: () => void) {
this._onTouchedCallback = fn;
}
/**
* @hidden
*/
public writeValue(value: Date) {
if (value) {
this.date = value;
}
}
/**
* @hidden
*/
public monthTracker(index, item): string {
return `${item.getMonth()}}`;
}
/**
* @hidden
*/
private initMonthFormatter() {
this._formatterMonth = new Intl.DateTimeFormat(this._locale, { month: this.monthFormat });
}
}