Skip to content

Commit

Permalink
feat(module:datepicker): hover to highlight the range
Browse files Browse the repository at this point in the history
  • Loading branch information
hsuanxyz committed Dec 13, 2017
1 parent d5bad61 commit 05d6124
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 63 deletions.
64 changes: 54 additions & 10 deletions src/components/calendar/nz-calendar.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,12 @@ export enum RangePart { Start = 0, End = 1 }
[class.ant-calendar-next-month-btn-day]="day.isNextMonth"
[class.ant-calendar-selected-day]="day.isSelectedDay"
[class.ant-calendar-in-range-cell]="day.isInRange"
[class.ant-calendar-today]="day.isCurrentDay">
<div class="ant-calendar-date" (click)="_clickDay($event,day)">{{ day.number }}</div>
[class.ant-calendar-today]="day.isCurrentDay"
(mouseenter)="_onDayHover($event, day)">
<div class="ant-calendar-date"
(click)="_clickDay($event,day)">
{{ day.number }}
</div>
</td>
</ng-template>
</tr>
Expand Down Expand Up @@ -189,7 +193,7 @@ export enum RangePart { Start = 0, End = 1 }
[class.ant-calendar-month-panel-selected-cell]="month.isSelectedMonth"
[class.ant-calendar-month-panel-cell-disabled]="month.disabled"
[class.ant-calendar-month-panel-current-cell]="month.isCurrentMonth">
<div class="ant-calendar-month-panel-month" (click)="_clickMonth($event,month)">
<div class="ant-calendar-month-panel-month"(click)="_clickMonth($event,month)">
{{ month.name }}
</div>
</td>
Expand All @@ -210,7 +214,7 @@ export class NzCalendarComponent implements OnInit {
private _datePicker = false;
private _fullScreen = true;
private _showHeader = true;
private _isRange = true;
private _isRange = false;

_el: HTMLElement;
_weeksCalendar: WeekInterface[] = [];
Expand All @@ -225,12 +229,14 @@ export class NzCalendarComponent implements OnInit {
_showYear = moment(new Date()).year();
_value: Date = new Date();
_rangeValue: Date[] = [null, null];
_hoveringSelectValue: Date;
_locale = this._localeService.getLocale().locale;
@ContentChild('dateCell') dateCell: TemplateRef<void>;
@ContentChild('monthCell') monthCell: TemplateRef<void>;

@Output() nzClickDay: EventEmitter<DayInterface> = new EventEmitter();
@Output() nzClickMonth: EventEmitter<MonthInterface> = new EventEmitter();
@Output() nzHoverDay: EventEmitter<DayInterface> = new EventEmitter();
@Input() nzClearTime = true;
@Input() nzMode = 'year';

Expand Down Expand Up @@ -298,12 +304,25 @@ export class NzCalendarComponent implements OnInit {

@Input()
get nzRangeValue(): Date[] {
return this._rangeValue;
return this._rangeValue;
}

set nzRangeValue(value: Date[]) {
this._rangeValue = value;
this._buildCalendar();
this._rangeValue = value;
this._buildCalendar();
}

@Input()
get nzHoveringSelectValue(): Date {
return this._hoveringSelectValue;
}

set nzHoveringSelectValue(value: Date) {
if (this._hoveringSelectValue === value) {
return;
}
this._hoveringSelectValue = value;
this._buildCalendar();
}

@Input()
Expand Down Expand Up @@ -362,23 +381,48 @@ export class NzCalendarComponent implements OnInit {
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'))
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 {
if (this.nzIsRange && this._rangeValue[RangePart.End]) {
return date.isBetween(this._rangeValue[RangePart.Start], this._rangeValue[RangePart.End]) && date.month() === month.month();
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;
}
}

_isBetween(date: Moment, targets: Date[]): boolean {
return date.isBetween.apply(date, targets);
}

_buildMonth(d: Moment): WeekInterface[] {
const weeks: WeekInterface[] = [];
const _rawDate = this._removeTime(d);
Expand Down
109 changes: 56 additions & 53 deletions src/components/datepicker/nz-rangepicker.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ import { toBoolean } from '../util/convert';
[value]="_value[type] | nzDate: nzFormat">
</div>
</div>
<div class="ant-calendar-header">
<div class="ant-calendar-header">
<div style="position: relative;" *ngIf="_mode[type] !== 'time'">
<a class="ant-calendar-prev-year-btn"
*ngIf="type !== _part.End || _showBtn(type)"
Expand All @@ -128,8 +128,8 @@ import { toBoolean } from '../util/convert';
</a>
<a class="ant-calendar-year-select"
(click)="_mode[type] = 'decade'"
title="{{ 'DateTime.chooseYear' | nzTranslate }}">{{ 'DateTime.nYear' | nzTranslate: {num: _showYear[type]}
}}</a>
title="{{ 'DateTime.chooseYear' | nzTranslate }}">
{{ 'DateTime.nYear' | nzTranslate: {num: _showYear[type]} }}</a>
</span>
<a class="ant-calendar-next-month-btn"
*ngIf="_mode[type] !== 'month' && (type !== _part.Start || _showBtn(type))"
Expand Down Expand Up @@ -159,11 +159,13 @@ import { toBoolean } from '../util/convert';
[nzHideDisabledOptions]="nzShowTime && nzShowTime.nzHideDisabledOptions||false"
[ngModel]="_value[type]" (ngModelChange)="_changeTime($event, type)"></nz-timepicker-inner>
</div>
<div class="ant-calendar-calendar-body">
<div class="ant-calendar-body">
<nz-calendar
(nzClickMonth)="_clickMonth($event, type)"
(nzClickDay)="_clickDay($event, type)"
[nzClearTime]="!nzShowTime"
(nzHoverDay)="_hoverDay($event)"
[nzHoveringSelectValue]="_hoveringSelectValue"
[nzRangeValue]="_value"
[nzShowMonth]="_showMonth[type]"
[nzShowYear]="_showYear[type]"
Expand All @@ -181,8 +183,8 @@ import { toBoolean } from '../util/convert';
<a class="ant-calendar-year-panel-prev-decade-btn" title="{{ 'DateTime.prevDecade' | nzTranslate }}"
(click)="_preDecade()"></a>
<a class="ant-calendar-year-panel-decade-select" title="{{ 'DateTime.chooseDecade' | nzTranslate }}">
<span class="ant-calendar-year-panel-decade-select-content">{{ _startDecade }}-{{ _startDecade + 9
}}</span>
<span class="ant-calendar-year-panel-decade-select-content">
{{ _startDecade }}-{{ _startDecade + 9 }}</span>
<span class="ant-calendar-year-panel-decade-select-arrow">x</span>
</a>
<a class="ant-calendar-year-panel-next-decade-btn" title="{{ 'DateTime.nextDecade' | nzTranslate }}"
Expand Down Expand Up @@ -233,17 +235,19 @@ export class NzRangePickerComponent implements ControlValueAccessor, OnInit {
private _showTime: Partial<NzTimePickerInnerComponent> = null;

_part = RangePart; // use for template
_now = moment();
_el;
_value: Date[];
_hoveringSelectValue: Date;
_open;
_disabledDate: (value: Date) => boolean;
_disabledDatePart: [(value: Date) => boolean, (value: Date) => boolean] = [null, null];
_disabledDatePart: Array<(value: Date) => boolean> = [null, null];
_mode = ['year', 'year'];
_selectedMonth: number[] = [];
_selectedYear: number[] = [];
_selectedDate: number[] = [];
_showMonth = [moment().month(), moment().add(1, 'month').month()];
_showYear = [moment().year(), moment().year()];
_showMonth = [this._now.month(), this._now.clone().add(1, 'month').month()];
_showYear = [this._now.year(), this._now.year()];
_yearPanel: string[][] = [];
_startDecade = Math.floor(this._showYear[RangePart.Start] / 10) * 10;
_triggerWidth = 0;
Expand All @@ -264,9 +268,15 @@ export class NzRangePickerComponent implements ControlValueAccessor, OnInit {
}

get _showClearIcon(): boolean {
return this._value[RangePart.Start]
&& this._value[RangePart.End]
&& !this.nzDisabled && this.nzAllowClear;
return this._isValidRange() && !this.nzDisabled && this.nzAllowClear;
}

get start(): moment.Moment {
return moment(this._value[RangePart.Start]);
}

get end(): moment.Moment {
return moment(this._value[RangePart.End]);
}

@Input()
Expand Down Expand Up @@ -395,12 +405,19 @@ export class NzRangePickerComponent implements ControlValueAccessor, OnInit {
this._value[part] = $event;
}

_clickDay(day: DayInterface, part: RangePart): void {
_hoverDay(day: DayInterface): void {
if (!this._isValidRange() && this._value.some(e => moment(e).isValid())) {
this._hoveringSelectValue = day.date.toDate();
} else {
this._hoveringSelectValue = null;
}
}

_clickDay(day: DayInterface, part: RangePart): void {
if (this._isValidRange()) {
this._value = this._defaultPickerValue;
this._value[part] = day.date.toDate();
this.setRangeValue();
this.rangeValueSort();
return;
}

Expand All @@ -416,15 +433,15 @@ export class NzRangePickerComponent implements ControlValueAccessor, OnInit {

// the result depends the before step
if (this._isValidRange()) {
this.setRangeValue();
this.rangeValueSort();
if (!this.nzShowTime) {
this._closeCalendar();
return;
}
this._initShow();
}

this.setRangeValue();
this.rangeValueSort();
}

_clickMonth(month: MonthInterface, part: RangePart): void {
Expand Down Expand Up @@ -454,9 +471,9 @@ export class NzRangePickerComponent implements ControlValueAccessor, OnInit {
if (this._mode[part] === 'month') {
return true;
}
const start = moment().month(this._showMonth[RangePart.Start]).year(this._showYear[RangePart.Start]);
const end = moment().month(this._showMonth[RangePart.End]).year(this._showYear[RangePart.End]);
return !start.add(1, 'month').isSame(end, 'month');
const showStart = moment().month(this._showMonth[RangePart.Start]).year(this._showYear[RangePart.Start]);
const showEnd = moment().month(this._showMonth[RangePart.End]).year(this._showYear[RangePart.End]);
return !showStart.add(1, 'month').isSame(showEnd, 'month');
}

_preYear(part: RangePart): void {
Expand Down Expand Up @@ -495,42 +512,33 @@ export class NzRangePickerComponent implements ControlValueAccessor, OnInit {
this._startDecade = this._startDecade + 10;
}

setRangeValue(): void {
const start = moment(this._value[RangePart.Start]);
const end = moment(this._value[RangePart.End]);
if (start.isValid() && end.isValid() && start.isAfter(end)) {
rangeValueSort(): void {
if (this.start.isValid() && this.end.isValid() && this.start.isAfter(this.end)) {
this._value = this._value.reverse();
} else {
this._value = [...this._value];
this._value = this._value.concat();
}
}

_initShow(): void {
const start = moment(this._value[RangePart.Start]);
const end = moment(this._value[RangePart.End]);
const now = moment();

const _showMonth = [];
const _showYear = [];

if (start.isValid()) {
_showMonth[RangePart.Start] = start.month();
_showYear[RangePart.Start] = start.year();
if (this.start.isValid()) {
this._showMonth[RangePart.Start] = this.start.month();
this._showYear[RangePart.Start] = this.start.year();
} else {
_showMonth[RangePart.Start] = now.month();
_showYear[RangePart.Start] = now.year();
this._showMonth[RangePart.Start] = this._now.month();
this._showYear[RangePart.Start] = this._now.year();
}

if (end.isValid() && !start.isSameOrAfter(end, 'month')) {
_showMonth[RangePart.End] = end.month();
_showYear[RangePart.End] = end.year();
if (this.end.isValid() && !this.start.isSameOrAfter(this.end, 'month')) {
this._showMonth[RangePart.End] = this.end.month();
this._showYear[RangePart.End] = this.end.year();
} else {
_showMonth[RangePart.End] = start.isValid() ? start.add(1, 'month').month() : now.add(1, 'month').month();
_showYear[RangePart.End] = start.isValid() ? start.year() : now.year();
const nextMonthOfStart = this.start.clone().add(1, 'month');
const nextMonthOfNow = this._now.clone().add(1, 'month');
this._showMonth[RangePart.End] = this.start.isValid() ? nextMonthOfStart.month() : nextMonthOfNow.month();
this._showYear[RangePart.End] = this.start.isValid() ? nextMonthOfStart.year() : nextMonthOfNow.year();
}

this._showMonth = _showMonth;
this._showYear = _showYear;
this._showMonth = this._showMonth .concat();
this._showYear = this._showYear .concat();
}

adjustShowMonth(): void {
Expand All @@ -548,14 +556,9 @@ export class NzRangePickerComponent implements ControlValueAccessor, OnInit {
}

setSelectedValue(): void {
const start = moment(this._value[RangePart.Start]);
const end = moment(this._value[RangePart.End]);
this._selectedMonth[RangePart.Start] = start.month();
this._selectedYear[RangePart.Start] = start.year();
this._selectedDate[RangePart.Start] = start.date();
this._selectedMonth[RangePart.End] = end.month();
this._selectedYear[RangePart.End] = end.year();
this._selectedDate[RangePart.End] = end.date();
this._selectedYear = [this.start.year(), this.end.year()];
this._selectedMonth = [this.start.month(), this.end.month()];
this._selectedDate = [this.start.date(), this.end.date()];
}

writeValue(value: Date[]): void {
Expand Down

0 comments on commit 05d6124

Please sign in to comment.