ng-ytl-zorro-antd
Version:
An enterprise-class UI components based on Ant Design and Angular
527 lines (479 loc) • 17.9 kB
text/typescript
/* tslint:disable:no-duplicate-imports max-line-length */
import {
Component,
ContentChild,
ElementRef,
EventEmitter,
HostBinding,
Input,
OnInit,
Output,
TemplateRef,
ViewEncapsulation,
} from '@angular/core';
import * as moment from 'moment';
import { Moment } from 'moment';
// import 'moment/locale/zh-cn';
import { NzLocaleService } from '../locale/index';
import { toBoolean } from '../util/convert';
export interface MonthInterface {
index: number;
name: string;
year: number;
isCurrentMonth: boolean;
isSelectedMonth: boolean;
disabled: boolean;
}
export type QuartersType = MonthInterface[];
export interface DayInterface {
number: number;
isLastMonth: boolean;
isNextMonth: boolean;
isCurrentDay: boolean;
isSelectedDay: boolean;
isInRange?: boolean;
title: string;
date: Moment;
disabled: boolean;
firstDisabled: boolean;
lastDisabled: boolean;
}
export interface WeekInterface {
days: DayInterface[];
}
export enum RangePart { Start = 0, End = 1 }
export class NzCalendarComponent implements OnInit {
private _clearTime = true;
private _datePicker = false;
private _fullScreen = true;
private _showHeader = true;
private _isRange = false;
_el: HTMLElement;
_weeksCalendar: WeekInterface[] = [];
_quartersCalendar: QuartersType[] = [];
_listOfWeekName: string[] = [];
_listOfMonthName: string[] = [];
_listOfYearName: number[] = [];
_disabledDate: (value: Date) => boolean;
_yearUnit = '年';
_monthUnit = '月';
_showMonth = moment(new Date()).month();
_showYear = moment(new Date()).year();
_value: Date = new Date();
_rangeValue: Date[] = [null, null];
_hoveringSelectValue: Date;
_locale = this._localeService.getLocale().locale;
dateCell: TemplateRef<void>;
monthCell: TemplateRef<void>;
nzClickDay: EventEmitter<DayInterface> = new EventEmitter();
nzClickMonth: EventEmitter<MonthInterface> = new EventEmitter();
nzHoverDay: EventEmitter<DayInterface> = new EventEmitter();
nzClearTime = true;
nzMode = 'month';
set nzFullScreen(value: boolean) {
this._fullScreen = toBoolean(value);
}
get nzFullScreen(): boolean {
return this._fullScreen;
}
set nzShowHeader(value: boolean) {
this._showHeader = toBoolean(value);
}
get nzShowHeader(): boolean {
return this._showHeader;
}
set nzIsRange(value: boolean) {
this._isRange = toBoolean(value);
}
get nzIsRange(): boolean {
return this._isRange;
}
set nzDisabledDate(value: (value: Date) => boolean) {
this._disabledDate = value;
this._buildCalendar();
}
get nzDisabledDate(): (value: Date) => boolean {
return this._disabledDate;
}
set nzDatePicker(value: boolean) {
this._datePicker = toBoolean(value);
}
get nzDatePicker(): boolean {
return this._datePicker;
}
set nzValue(value: Date) {
if (this._value === value) {
return;
}
this._value = value || new Date();
this._showMonth = moment(this._value).month();
this._showYear = moment(this._value).year();
this._buildCalendar();
}
get nzValue(): Date {
return this._value || new Date();
}
get nzRangeValue(): Date[] {
return this._rangeValue;
}
set nzRangeValue(value: Date[]) {
this._rangeValue = value;
this._buildCalendar();
}
get nzHoveringSelectValue(): Date {
return this._hoveringSelectValue;
}
set nzHoveringSelectValue(value: Date) {
if (this._hoveringSelectValue === value) {
return;
}
this._hoveringSelectValue = value;
this._buildCalendar();
}
set nzShowYear(value: number) {
this._showYear = value;
this._buildCalendar();
}
get nzShowYear(): number {
return this._showYear;
}
set nzShowMonth(value: number) {
this._showMonth = value;
this._buildCalendar();
}
get nzShowMonth(): number {
return this._showMonth;
}
set nzLocale(value: string) {
this._locale = value;
moment.locale(this._locale);
}
get nzLocale(): string {
return this._locale;
}
_removeTime(date: Moment): Moment {
if (this.nzClearTime) {
return date.hour(0).minute(0).second(0).millisecond(0);
} else {
return date;
}
}
_clickDay($event: MouseEvent, day: DayInterface): void {
$event.preventDefault();
$event.stopPropagation();
if (day.disabled) {
return;
}
this.nzClickDay.emit(day);
}
_clickMonth($event: MouseEvent, month: MonthInterface): void {
$event.preventDefault();
$event.stopPropagation();
if (month.disabled) {
return;
}
this.nzClickMonth.emit(month);
}
_onDayHover($event: MouseEvent, day: DayInterface): void {
$event.preventDefault();
$event.stopPropagation();
if (day.disabled || day.date.isSame(this._hoveringSelectValue)) {
return;
}
this.nzHoverDay.emit(day);
}
_isSelectedDay(date: Moment, month: Moment): boolean {
if (this.nzIsRange) {
return (date.isSame(this._rangeValue[RangePart.Start], 'day')
|| date.isSame(this._rangeValue[RangePart.End], 'day')
|| date.isSame(this._hoveringSelectValue, 'day'))
&& date.month() === month.month();
} else {
return date.isSame(this.nzValue, 'day');
}
}
_isInRange(date: Moment, month: Moment): boolean {
let ghostDate: Date;
if (this.nzIsRange && date.month() === month.month()) {
if (this._rangeValue.every(e => moment(e).isValid())) {
return date.isBetween.apply(date, this._rangeValue);
}
ghostDate = this._rangeValue.find(e => moment(e).isValid());
if (ghostDate && this._hoveringSelectValue) {
const start = moment.min(moment(ghostDate), moment(this._hoveringSelectValue)).toDate();
const end = moment.max(moment(ghostDate), moment(this._hoveringSelectValue)).toDate();
return date.isBetween(start, end);
}
return false;
} else {
return false;
}
}
_buildMonth(d: Moment): WeekInterface[] {
const weeks: WeekInterface[] = [];
const _rawDate = this._removeTime(d);
const start = _rawDate.clone().date(1).day(0);
const month = _rawDate.clone();
let done = false;
const date = start.clone();
let monthIndex = date.month();
let count = 0;
while (!done) {
weeks.push({ days: this._buildWeek(date.clone(), month) });
date.add(1, 'w');
done = count++ > 4;
monthIndex = date.month();
}
return weeks;
}
_buildWeek(firstDate: Moment, month: Moment): DayInterface[] {
let date = firstDate;
const days: DayInterface[] = [];
for (let i = 0; i < 7; i++) {
days.push({
number : date.date(),
isLastMonth : date.month() < month.month(),
isNextMonth : date.month() > month.month(),
isCurrentDay : date.isSame(new Date(), 'day'),
isSelectedDay: this._isSelectedDay(date, month),
isInRange : this._isInRange(date, month),
title : date.format('YYYY-MM-DD'),
date,
disabled : this.nzDisabledDate && this.nzDisabledDate(date.toDate()),
firstDisabled: this.nzDisabledDate && this.nzDisabledDate(date.toDate()) && (date.day() === 0 || (date.day() !== 0 && this.nzDisabledDate && !this.nzDisabledDate(date.clone().subtract(1, 'day').toDate()))),
lastDisabled : this.nzDisabledDate && this.nzDisabledDate(date.toDate()) && (date.day() === 6 || (date.day() !== 6 && this.nzDisabledDate && !this.nzDisabledDate(date.clone().add(1, 'day').toDate())))
});
date = date.clone();
date.add(1, 'd');
}
return days;
}
_buildYears(date: Moment): MonthInterface[][] {
const quarters: MonthInterface[][] = [];
let months: MonthInterface[] = [];
for (let i = 0; i < 12; i++) {
months.push({
index : i,
name : this._listOfMonthName[ i ],
year : date.year(),
isCurrentMonth : moment(new Date()).month() === i && date.isSame(new Date(), 'year'),
isSelectedMonth: this._showMonth === i,
disabled : this.nzDisabledDate && this.nzDisabledDate(date.month(i).toDate())
});
if ((i + 1) % 3 === 0) {
quarters.push(months);
months = [];
}
}
return quarters;
}
_buildCalendar(): void {
moment.locale(this._locale);
/** TODO replace with real i18n*/
if (this._locale !== 'zh-cn') {
try {
this._yearUnit = moment.duration(12, 'month').humanize().split(' ')[ 1 ][ 0 ].toUpperCase() + moment.duration(12, 'month').humanize().split(' ')[ 1 ].slice(1, moment.duration(12, 'month').humanize().split(' ')[ 1 ].length);
this._monthUnit = moment.duration(4, 'week').humanize().split(' ')[ 1 ][ 0 ].toUpperCase() + moment.duration(4, 'week').humanize().split(' ')[ 1 ].slice(1, moment.duration(4, 'week').humanize().split(' ')[ 1 ].length);
} catch (e) { }
}
if (this._locale === 'ru-RU') {
try {
const monthText = moment.duration(12, 'month').humanize().split(' ')[ 0 ];
const weekText = moment.duration(4, 'week').humanize().split(' ')[ 0 ];
this._yearUnit = monthText.charAt(0).toUpperCase() + monthText.slice(1);
this._monthUnit = weekText.charAt(0).toUpperCase() + weekText.slice(1);
} catch (e) { }
}
this._listOfYearName = this._generateYears(this._showYear);
this._listOfWeekName = moment.weekdaysMin();
this._listOfMonthName = moment.monthsShort();
const date = moment(this.nzValue).year(this._showYear).month(this._showMonth);
this._weeksCalendar = this._buildMonth(date);
this._quartersCalendar = this._buildYears(date);
}
_generateYears(year: number): number[] {
const listOfYears: number[] = [];
for (const i of Array.from(Array(20).keys())) {
listOfYears.push(i - 10 + year);
}
return listOfYears;
}
constructor(private _elementRef: ElementRef, private _localeService: NzLocaleService) {
this._el = this._elementRef.nativeElement;
}
ngOnInit(): void {
this._buildCalendar();
}
}