2018-11-12 10:31:58 +00:00
|
|
|
import ngModule from '../../module';
|
2019-10-23 15:38:35 +00:00
|
|
|
import FormInput from '../form-input';
|
2018-11-12 10:31:58 +00:00
|
|
|
import './style.scss';
|
|
|
|
|
|
|
|
/**
|
2019-04-29 09:49:43 +00:00
|
|
|
* Flat calendar.
|
2018-11-12 10:31:58 +00:00
|
|
|
*
|
2019-10-23 15:38:35 +00:00
|
|
|
* @property {Array} defaultDate Array of events
|
2019-09-25 18:06:42 +00:00
|
|
|
* @property {Function} hasEvents Determines if an events exists for a day
|
|
|
|
* @property {Function} getClass Class to apply to specific day
|
2019-10-23 15:38:35 +00:00
|
|
|
* @event selection Emitted when day or weekday is selected
|
|
|
|
* @event move Emitted when month changes
|
2018-11-12 10:31:58 +00:00
|
|
|
*/
|
2019-10-23 15:38:35 +00:00
|
|
|
export default class Calendar extends FormInput {
|
|
|
|
constructor($element, $scope, vnWeekDays) {
|
2018-11-12 10:31:58 +00:00
|
|
|
super($element, $scope);
|
2019-10-23 15:38:35 +00:00
|
|
|
this.weekDays = vnWeekDays.locales;
|
2018-11-12 10:31:58 +00:00
|
|
|
this.defaultDate = new Date();
|
2019-01-21 10:45:53 +00:00
|
|
|
this.displayControls = true;
|
2019-06-26 11:35:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-10-23 15:38:35 +00:00
|
|
|
* The initial date
|
2019-04-03 09:34:58 +00:00
|
|
|
*
|
|
|
|
* @return {Date} - Default date
|
|
|
|
*/
|
2018-11-12 10:31:58 +00:00
|
|
|
get defaultDate() {
|
|
|
|
return this._defaultDate;
|
|
|
|
}
|
|
|
|
|
|
|
|
set defaultDate(value) {
|
2019-09-25 18:06:42 +00:00
|
|
|
if (value) {
|
|
|
|
value = new Date(value);
|
|
|
|
value.setHours(0, 0, 0, 0);
|
|
|
|
value.setDate(1);
|
|
|
|
}
|
2019-01-21 10:45:53 +00:00
|
|
|
|
2019-09-25 18:06:42 +00:00
|
|
|
this._defaultDate = value;
|
2019-10-23 15:38:35 +00:00
|
|
|
this.month = value.getMonth();
|
2019-01-21 10:45:53 +00:00
|
|
|
this.repaint();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns first day of month from a given date
|
|
|
|
*
|
|
|
|
* @param {Date} date - Origin date
|
|
|
|
* @return {Integer}
|
|
|
|
*/
|
|
|
|
firstDay(date) {
|
2019-10-23 15:38:35 +00:00
|
|
|
return new Date(
|
2019-01-21 10:45:53 +00:00
|
|
|
date.getFullYear(),
|
2019-10-23 15:38:35 +00:00
|
|
|
date.getMonth(),
|
|
|
|
1
|
|
|
|
);
|
2019-01-21 10:45:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-10-23 15:38:35 +00:00
|
|
|
* Repaints the calendar.
|
2019-01-21 10:45:53 +00:00
|
|
|
*/
|
|
|
|
repaint() {
|
2019-10-23 15:38:35 +00:00
|
|
|
const firstWeekday = this.firstDay(this.defaultDate).getDay() - 1;
|
|
|
|
let weekdayOffset = firstWeekday >= 0 ? firstWeekday : 6;
|
2018-11-12 10:31:58 +00:00
|
|
|
|
2019-10-23 15:38:35 +00:00
|
|
|
let dayIndex = new Date(this.defaultDate.getTime());
|
|
|
|
dayIndex.setDate(1 - weekdayOffset);
|
2018-11-12 10:31:58 +00:00
|
|
|
|
|
|
|
this.days = [];
|
2019-01-21 10:45:53 +00:00
|
|
|
|
2019-10-23 15:38:35 +00:00
|
|
|
for (let i = 1; i <= 42; i++) {
|
|
|
|
this.days.push(new Date(dayIndex.getTime()));
|
|
|
|
dayIndex.setDate(dayIndex.getDate() + 1);
|
2018-11-12 10:31:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-03 09:34:58 +00:00
|
|
|
/**
|
2019-10-23 15:38:35 +00:00
|
|
|
* Gets CSS classes to apply to the specified day.
|
2019-04-03 09:34:58 +00:00
|
|
|
*
|
2019-10-23 15:38:35 +00:00
|
|
|
* @param {Date} day The day
|
|
|
|
* @return {Object} The CSS classes to apply
|
2019-04-03 09:34:58 +00:00
|
|
|
*/
|
2019-10-23 15:38:35 +00:00
|
|
|
getDayClasses(day) {
|
|
|
|
let wday = day.getDay();
|
|
|
|
let month = day.getMonth();
|
2019-06-26 11:35:38 +00:00
|
|
|
|
2019-10-23 15:38:35 +00:00
|
|
|
let classes = {
|
|
|
|
weekend: wday === 6 || wday === 0,
|
|
|
|
previous: month < this.month,
|
|
|
|
current: month == this.month,
|
|
|
|
next: month > this.month,
|
|
|
|
event: this.hasEvents({$day: day})
|
|
|
|
};
|
2019-06-26 11:35:38 +00:00
|
|
|
|
2019-10-23 15:38:35 +00:00
|
|
|
let userClass = this.getClass({$day: day});
|
|
|
|
if (userClass) classes[userClass] = true;
|
2019-07-31 07:50:47 +00:00
|
|
|
|
2019-10-23 15:38:35 +00:00
|
|
|
return classes;
|
2019-01-21 10:45:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-04-03 09:34:58 +00:00
|
|
|
* Moves to next month(s)
|
2019-01-21 10:45:53 +00:00
|
|
|
*/
|
2019-10-23 15:38:35 +00:00
|
|
|
moveNext() {
|
|
|
|
this.move(1);
|
2018-11-12 10:31:58 +00:00
|
|
|
}
|
|
|
|
|
2019-01-21 10:45:53 +00:00
|
|
|
/**
|
2019-04-03 09:34:58 +00:00
|
|
|
* Moves to previous month(s)
|
2019-01-21 10:45:53 +00:00
|
|
|
*/
|
2019-10-23 15:38:35 +00:00
|
|
|
movePrevious() {
|
|
|
|
this.move(-1);
|
2018-11-12 10:31:58 +00:00
|
|
|
}
|
|
|
|
|
2019-01-21 10:45:53 +00:00
|
|
|
/**
|
2019-10-23 15:38:35 +00:00
|
|
|
* Moves @direction months backwards/forwards.
|
2019-01-21 10:45:53 +00:00
|
|
|
*
|
2019-10-23 15:38:35 +00:00
|
|
|
* @param {Number} direction Negative to move backwards, positive forwards
|
2019-01-21 10:45:53 +00:00
|
|
|
*/
|
2019-10-23 15:38:35 +00:00
|
|
|
move(direction) {
|
|
|
|
let date = new Date(this.defaultDate.getTime());
|
|
|
|
date.setMonth(date.getMonth() + direction);
|
|
|
|
this.defaultDate = date;
|
|
|
|
|
|
|
|
this.repaint();
|
|
|
|
this.emit('move', {$date: date});
|
|
|
|
}
|
2019-01-21 10:45:53 +00:00
|
|
|
|
2019-10-23 15:38:35 +00:00
|
|
|
/*
|
|
|
|
* Day selection event
|
|
|
|
*/
|
2020-02-26 06:02:03 +00:00
|
|
|
select($event, day) {
|
2019-10-23 15:38:35 +00:00
|
|
|
if (!this.editable) return;
|
2019-10-28 16:31:33 +00:00
|
|
|
this.change(day);
|
2019-10-01 11:45:43 +00:00
|
|
|
this.emit('selection', {
|
2020-02-26 06:02:03 +00:00
|
|
|
$event: $event,
|
2019-10-01 11:45:43 +00:00
|
|
|
$days: [day],
|
|
|
|
$type: 'day'
|
|
|
|
});
|
2020-08-10 12:29:25 +00:00
|
|
|
|
|
|
|
// Repaint only if 'selection' event is not listening
|
|
|
|
if (!this.$events || this.$events && !this.$events['selection'])
|
|
|
|
this.repaint();
|
2018-11-12 10:31:58 +00:00
|
|
|
}
|
|
|
|
|
2019-10-23 15:38:35 +00:00
|
|
|
/*
|
2019-04-03 09:34:58 +00:00
|
|
|
* WeekDay selection event
|
|
|
|
*/
|
2020-02-26 06:02:03 +00:00
|
|
|
selectWeekDay($event, weekday) {
|
2019-10-23 15:38:35 +00:00
|
|
|
if (!this.editable) return;
|
2019-10-01 11:45:43 +00:00
|
|
|
let days = [];
|
2019-10-23 15:38:35 +00:00
|
|
|
for (let day of this.days) {
|
|
|
|
if (day.getDay() === weekday && day.getMonth() == this.month)
|
2019-10-01 11:45:43 +00:00
|
|
|
days.push(day);
|
2019-01-21 10:45:53 +00:00
|
|
|
}
|
2019-10-23 15:38:35 +00:00
|
|
|
this.field = days[0];
|
2019-10-01 11:45:43 +00:00
|
|
|
this.emit('selection', {
|
2020-02-26 06:02:03 +00:00
|
|
|
$event: $event,
|
2019-10-01 11:45:43 +00:00
|
|
|
$days: days,
|
|
|
|
$type: 'weekday',
|
|
|
|
$weekday: weekday
|
|
|
|
});
|
2019-10-23 15:38:35 +00:00
|
|
|
this.repaint();
|
2019-06-26 11:35:38 +00:00
|
|
|
}
|
2019-09-25 18:06:42 +00:00
|
|
|
|
|
|
|
hasEvents() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
getClass() {
|
|
|
|
return '';
|
|
|
|
}
|
2018-11-12 10:31:58 +00:00
|
|
|
|
2019-10-23 15:38:35 +00:00
|
|
|
repeatLast() {
|
|
|
|
if (!this.formatDay) return;
|
|
|
|
|
|
|
|
let days = this.element.querySelectorAll('.days > .day');
|
|
|
|
for (let i = 0; i < days.length; i++) {
|
|
|
|
this.formatDay({
|
|
|
|
$day: this.days[i],
|
|
|
|
$element: days[i]
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Calendar.$inject = ['$element', '$scope', 'vnWeekDays'];
|
2018-11-12 10:31:58 +00:00
|
|
|
|
2019-10-23 15:38:35 +00:00
|
|
|
ngModule.vnComponent('vnCalendar', {
|
2018-11-12 10:31:58 +00:00
|
|
|
template: require('./index.html'),
|
|
|
|
controller: Calendar,
|
|
|
|
bindings: {
|
2019-05-17 11:27:51 +00:00
|
|
|
defaultDate: '=?',
|
2019-09-25 18:06:42 +00:00
|
|
|
hasEvents: '&?',
|
|
|
|
getClass: '&?',
|
2019-10-23 15:38:35 +00:00
|
|
|
formatDay: '&?',
|
2019-01-21 10:45:53 +00:00
|
|
|
displayControls: '<?',
|
2019-10-23 15:38:35 +00:00
|
|
|
hideYear: '<?',
|
|
|
|
hideContiguous: '<?'
|
2018-11-12 10:31:58 +00:00
|
|
|
}
|
|
|
|
});
|