UNPKG

unicorn-components

Version:

<a target="_blank" href="https://getunicorn.io"><img src="https://bitbucket-assetroot.s3.amazonaws.com/c/photos/2017/Jul/07/2615006260-5-nitsnetsstudios-ondemand-UNI_avatar.png" align="left"></a>

125 lines (107 loc) 4.46 kB
import * as moment from 'moment'; import { Component, EventEmitter, HostBinding, Input, OnChanges, Output } from '@angular/core'; @Component({ selector: 'uni-calendar', templateUrl: 'calendar.component.html', styleUrls: ['calendar.component.scss'], }) export class UniCalendarComponent implements OnChanges { @HostBinding('class.uni-calendar') componentClass = true; @HostBinding('class.uni-calendar--bordered') @Input() bordered = false; private _model; @Input() set model(value: string) { if (value) { this._model = value; this.selected = this.normalizeDate(moment(value, 'YYYY-MM-DD')); this.month = this.selected.clone(); } else { this.selected = null; this.month = moment(); } } get model() { return this._model } @Output() modelChange = new EventEmitter(); @Input() max; @Input() min; @Input() rangeFrom; @Input() rangeTo; selected: moment.Moment = null; month: moment.Moment = moment(); weeks = []; dayNames = ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su']; constructor() { } ngOnChanges(changes) { if (changes.rangeFrom && this.rangeFrom) { this.rangeFrom = moment(this.rangeFrom, 'YYYY-MM-DD'); } if (changes.rangeTo && this.rangeTo) { this.rangeTo = moment(this.rangeTo, 'YYYY-MM-DD'); } this.renderCalendar(); }; select(day) { if (!day) { return; } if (this.max && day.isAfter(this.max)) { day = moment(this.max) } if (this.min && day.isBefore(this.min)) { day = moment(this.min) } this.selected = day; this.modelChange.emit(day.format('YYYY-MM-DD')); }; next() { const next = this.beginOfNextMonth(this.month); this.month.add(1, 'months'); this.renderMonth(next); }; previous() { const previous = this.beginOfPreviousMonth(this.month); this.month.subtract(1, 'months'); this.renderMonth(previous); }; isRangeFromActive() { return this.rangeFrom && this.selected && !this.rangeFrom.isSame(this.selected); } isRangeToActive() { return this.rangeTo && this.selected && !this.rangeTo.isSame(this.selected); } renderCalendar() { this.renderMonth(this.beginOfMonth(this.month)); } private normalizeDate(date: moment.Moment): moment.Moment { return date.hour(0).minute(0).second(0).millisecond(0); } private beginOfMonth(date: moment.Moment): moment.Moment { return this.normalizeDate(date.clone().startOf('month').isoWeekday(1)); } private beginOfPreviousMonth(date: moment.Moment): moment.Moment { return this.beginOfMonth(date.clone().subtract(1, 'months')); } private beginOfNextMonth(date: moment.Moment): moment.Moment { return this.beginOfMonth(date.clone().add(1, 'months')); } private renderMonth(start: moment.Moment) { this.weeks = []; const date = start.clone(); let done = false, monthIndex = date.month(), count = 0; while (!done) { this.weeks.push({ days: this.renderWeek(date.clone()) }); date.add(1, 'w'); done = count++ > 2 && monthIndex !== date.month(); monthIndex = date.month(); } } private renderWeek(date: moment.Moment): Array<any> { const days = []; for (let i = 0; i < 7; i++) { days.push({ name: date ? date.format('dd').substring(0, 1) : '-', number: date.date(), isCurrentMonth: date.month() === this.month.month(), isToday: date.isSame(new Date(), 'day'), isRangeFrom: this.rangeFrom ? date.isSame(this.rangeFrom, 'day') : false, isRangeMiddle: this.rangeTo ? date.isBetween(this.selected, this.rangeTo, 'day') : this.rangeFrom ? date.isBetween(this.rangeFrom, this.selected, 'day') : false, isRangeTo: this.rangeTo ? date.isSame(this.rangeTo, 'day') : false, isUnavailable: (this.max && date.isAfter(this.max)) || (this.min && date.isBefore(this.min)), date: date }); date = date.clone(); date.add(1, 'd'); } return days; } // https://www.codementor.io/angularjs/tutorial/angularjs-calendar-directives-less-cess-moment-font-awesome }