salix/front/core/components/calendar/index.js

236 lines
5.8 KiB
JavaScript

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: '<?',
defaultDate: '<?',
onSelection: '&?',
onMoveNext: '&?',
onMovePrevious: '&?',
displayControls: '<?',
skip: '<?'
}
});