import ngModule from '../../module'; import Component from '../../lib/component'; import './style.scss'; /** * Calendar. * */ export default class Calendar extends Component { constructor($element, $scope) { super($element, $scope); this.events = []; this.defaultDate = new Date(); this.displayControls = true; this.skip = 1; } get defaultDate() { return this._defaultDate; } set defaultDate(value) { this._defaultDate = value; this.repaint(); } get currentMonth() { return this.defaultDate; } get events() { return this._events; } set events(value) { if (!value) return; value.map(event => { event.date = new Date(event.date); }); this._events = value; if (value.length && this.defaultDate) this.repaint(); } get nextMonth() { const newDate = new Date(this.currentMonth); newDate.setMonth(this.currentMonth.getMonth() + 1); return newDate; } get previousMonth() { const newDate = new Date(this.currentMonth); newDate.setMonth(this.currentMonth.getMonth() - 1); return newDate; } /** * Returns first day of month from a given date * * @param {Date} date - Origin date * @return {Integer} */ firstDay(date) { const newDate = new Date( date.getFullYear(), date.getMonth(), 1); return newDate; } /** * Returns last day of month from a given date * * @param {Date} date - Origin date * @return {Integer} */ lastDay(date) { const newDate = new Date( date.getFullYear(), date.getMonth() + 1, 0); return newDate; } repaint() { const firstWeekday = this.firstDay(this.currentMonth).getDay(); const previousLastDay = this.lastDay(this.previousMonth).getDate(); const currentLastDay = this.lastDay(this.currentMonth).getDate(); const maxFields = 42; // Max field limit let weekdayOffset = firstWeekday > 0 ? firstWeekday : 7; let dayPrevious = previousLastDay - (weekdayOffset - 2); let dayCurrent = 1; let dayNext = 1; this.days = []; for (let fieldIndex = 1; fieldIndex <= maxFields; fieldIndex++) { if (fieldIndex < weekdayOffset) { this.addDay(this.previousMonth, dayPrevious, 'gray'); dayPrevious++; } else if (fieldIndex >= weekdayOffset && dayCurrent <= currentLastDay) { this.addDay(this.currentMonth, dayCurrent); dayCurrent++; } else if (fieldIndex >= weekdayOffset && dayCurrent > currentLastDay) { this.addDay(this.nextMonth, dayNext, 'gray'); dayNext++; } } } addDay(date, day, className = '', style) { const newDate = new Date( date.getFullYear(), date.getMonth(), day); let event = this.events.find(event => { return event.date >= newDate && event.date <= newDate; }); if (newDate.getMonth() === this.currentMonth.getMonth() && newDate.getDay() == 0) className = 'red'; if (event) { className = event.className; style = event.style; } this.days.push({date: newDate, className, style, event}); } /** * Adds a new calendar event * * @param {Date} date - Day to add event * @param {String} className - [green, blue, orange, red] * @param {String} title - Tooltip description * @param {Boolean} isRemovable - True if is removable by users */ addEvent(date, className, title = '', isRemovable = true) { const event = this.events.findIndex(event => { return event.date >= date && event.date <= date; }); if (event == -1) this.events.push({date, className, title, isRemovable}); this.repaint(); } removeEvent(date) { const event = this.events.findIndex(event => { return event.date >= date && event.date <= date; }); if (event > -1) this.events.splice(event, 1); this.repaint(); } /** * Moves to next month * * @param {Integer} skip - Months to skip at once */ moveNext(skip = 1) { let next = this.defaultDate.getMonth() + skip; this.defaultDate.setMonth(next); this.repaint(); this.emit('moveNext'); } /** * Moves to previous month * * @param {Integer} skip - Months to skip at once */ movePrevious(skip = 1) { let previous = this.defaultDate.getMonth() - skip; this.defaultDate.setMonth(previous); this.repaint(); this.emit('movePrevious'); } /** * Day selection event * * @param {Integer} index - Index from days array */ select(index) { let day = this.days[index]; day.index = index; this.emit('selection', {values: [day]}); } selectAll(weekday) { let selected = []; for (let i in this.days) { const day = this.days[i]; const date = day.date; day.index = i; if (date.getDay() === weekday && date.getMonth() == this.defaultDate.getMonth()) selected.push(day); } this.emit('selection', {values: selected}); } } Calendar.$inject = ['$element', '$scope', '$attrs']; ngModule.component('vnCalendar', { template: require('./index.html'), controller: Calendar, bindings: { model: '<', events: '