js-year-calendar
Version:
A fully customizable year calendar widget
1,329 lines (1,097 loc) • 79 kB
JavaScript
(function (global, factory) {
if (typeof define === "function" && define.amd) {
define(["exports"], factory);
} else if (typeof exports !== "undefined") {
factory(exports);
} else {
var mod = {
exports: {}
};
factory(mod.exports);
global.jsYearCalendar = mod.exports;
}
})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports) {
"use strict";
Object.defineProperty(_exports, "__esModule", {
value: true
});
_exports["default"] = void 0;
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
/* =========================================================
* JS year calendar v1.0.0
* Repo: https://github.com/year-calendar/js-year-calendar
* =========================================================
* Created by Paul David-Sivelle
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ========================================================= */
// NodeList forEach() polyfill
if (typeof NodeList !== "undefined" && !NodeList.prototype.forEach) {
NodeList.prototype.forEach = function (callback, thisArg) {
thisArg = thisArg || window;
for (var i = 0; i < this.length; i++) {
callback.call(thisArg, this[i], i, this);
}
};
} // Element closest() polyfill
if (typeof Element !== "undefined" && !Element.prototype.matches) {
var prototype = Element.prototype;
Element.prototype.matches = prototype.msMatchesSelector || prototype.webkitMatchesSelector;
}
if (typeof Element !== "undefined" && !Element.prototype.closest) {
Element.prototype.closest = function (s) {
var el = this;
if (!document.documentElement.contains(el)) return null;
do {
if (el.matches(s)) return el;
el = el.parentElement || el.parentNode;
} while (el !== null && el.nodeType == 1);
return null;
};
}
/**
* Calendar instance.
*/
var Calendar = /*#__PURE__*/function () {
/**
* Fired when a day is clicked.
* @event
* @example
* ```
*
* document.querySelector('.calendar').addEventListener('clickDay', function(e) {
* console.log("Click on day: " + e.date + " (" + e.events.length + " events)");
* })
* ```
*/
/**
* Fired when a day is right clicked.
* @event
* @example
* ```
*
* document.querySelector('.calendar').addEventListener('clickDay', function(e) {
* console.log("Right click on day: " + e.date + " (" + e.events.length + " events)");
* })
* ```
*/
/**
* Fired when the mouse enter in a day.
* @event
* @example
* ```
*
* document.querySelector('.calendar').addEventListener('mouseOnDay', function(e) {
* console.log("Mouse enter in a day: " + e.date + " (" + e.events.length + " events)");
* })
* ```
*/
/**
* Fired when the mouse leave a day.
* @event
* @example
* ```
*
* document.querySelector('.calendar').addEventListener('mouseOutDay', function(e) {
* console.log("Mouse leave a day: " + e.date + " (" + e.events.length + " events)");
* })
* ```
*/
/**
* Fired when the calendar rendering is ended.
* @event
* @example
* ```
*
* document.querySelector('.calendar').addEventListener('renderEnd', function(e) {
* console.log("Render end for year: " + e.currentYear);
* })
* ```
*/
/**
* Fired when a date range is selected.
*
* Don't forget to enable the `enableRangeSelection` option to be able to use the range selection functionality.
* @event
* @example
* ```
*
* document.querySelector('.calendar').addEventListener('selectRange', function(e) {
* console.log("Select the range: " + e.startDate + " - " + e.endDate);
* })
* ```
*/
/**
* Triggered after the changing the current year.
* Works only if the calendar is used in a full year mode. Otherwise, use `periodChanged` event.
* @event
* @example
* ```
*
* document.querySelector('.calendar').addEventListener('yearChanged', function(e) {
* console.log("New year selected: " + e.currentYear);
* })
* ```
*/
/**
* Triggered after the changing the visible period.
* @event
* @example
* ```
*
* document.querySelector('.calendar').addEventListener('periodChanged', function(e) {
* console.log(`New period selected: ${e.startDate} ${e.endDate}`);
* })
* ```
*/
/**
* Create a new calendar.
* @param element The element (or the selector to an element) in which the calendar should be created.
* @param options [Optional] The options used to customize the calendar
*/
function Calendar(element) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
_classCallCheck(this, Calendar);
_defineProperty(this, "element", void 0);
_defineProperty(this, "options", void 0);
_defineProperty(this, "_startDate", void 0);
_defineProperty(this, "_dataSource", void 0);
_defineProperty(this, "_mouseDown", void 0);
_defineProperty(this, "_rangeStart", void 0);
_defineProperty(this, "_rangeEnd", void 0);
_defineProperty(this, "_responsiveInterval", void 0);
_defineProperty(this, "_nbCols", void 0);
_defineProperty(this, "clickDay", void 0);
_defineProperty(this, "dayContextMenu", void 0);
_defineProperty(this, "mouseOnDay", void 0);
_defineProperty(this, "mouseOutDay", void 0);
_defineProperty(this, "renderEnd", void 0);
_defineProperty(this, "selectRange", void 0);
_defineProperty(this, "yearChanged", void 0);
_defineProperty(this, "periodChanged", void 0);
if (element instanceof HTMLElement) {
this.element = element;
} else if (typeof element === "string") {
this.element = document.querySelector(element);
} else {
throw new Error("The element parameter should be a DOM node or a selector");
}
this.element.classList.add('calendar');
this._initializeEvents(options);
this._initializeOptions(options);
var startYear = new Date().getFullYear();
var startMonth = 0;
if (this.options.startDate) {
startYear = this.options.startDate.getFullYear();
startMonth = this.options.startDate.getMonth();
} else if (this.options.startYear) {
startYear = this.options.startYear;
}
this.setStartDate(new Date(startYear, startMonth, 1));
}
_createClass(Calendar, [{
key: "_initializeOptions",
value: function _initializeOptions(opt) {
if (opt == null) {
opt = {};
}
this.options = {
startYear: !isNaN(parseInt(opt.startYear)) ? parseInt(opt.startYear) : null,
startDate: opt.startDate instanceof Date ? opt.startDate : null,
numberMonthsDisplayed: !isNaN(parseInt(opt.numberMonthsDisplayed)) && opt.numberMonthsDisplayed > 0 && opt.numberMonthsDisplayed <= 12 ? parseInt(opt.numberMonthsDisplayed) : 12,
minDate: opt.minDate instanceof Date ? opt.minDate : null,
maxDate: opt.maxDate instanceof Date ? opt.maxDate : null,
language: opt.language != null && Calendar.locales[opt.language] != null ? opt.language : 'en',
allowOverlap: opt.allowOverlap != null ? opt.allowOverlap : true,
displayWeekNumber: opt.displayWeekNumber != null ? opt.displayWeekNumber : false,
displayDisabledDataSource: opt.displayDisabledDataSource != null ? opt.displayDisabledDataSource : false,
displayHeader: opt.displayHeader != null ? opt.displayHeader : true,
alwaysHalfDay: opt.alwaysHalfDay != null ? opt.alwaysHalfDay : false,
enableRangeSelection: opt.enableRangeSelection != null ? opt.enableRangeSelection : false,
disabledDays: opt.disabledDays instanceof Array ? opt.disabledDays : [],
disabledWeekDays: opt.disabledWeekDays instanceof Array ? opt.disabledWeekDays : [],
hiddenWeekDays: opt.hiddenWeekDays instanceof Array ? opt.hiddenWeekDays : [],
roundRangeLimits: opt.roundRangeLimits != null ? opt.roundRangeLimits : false,
dataSource: opt.dataSource instanceof Array || typeof opt.dataSource === "function" ? opt.dataSource : [],
style: opt.style == 'background' || opt.style == 'border' || opt.style == 'custom' ? opt.style : 'border',
enableContextMenu: opt.enableContextMenu != null ? opt.enableContextMenu : false,
contextMenuItems: opt.contextMenuItems instanceof Array ? opt.contextMenuItems : [],
customDayRenderer: typeof opt.customDayRenderer === "function" ? opt.customDayRenderer : null,
customDataSourceRenderer: typeof opt.customDataSourceRenderer === "function" ? opt.customDataSourceRenderer : null,
weekStart: !isNaN(parseInt(opt.weekStart)) ? parseInt(opt.weekStart) : null,
loadingTemplate: typeof opt.loadingTemplate === "string" || opt.loadingTemplate instanceof HTMLElement ? opt.loadingTemplate : null
};
if (this.options.dataSource instanceof Array) {
this._dataSource = this.options.dataSource;
this._initializeDatasourceColors();
}
}
}, {
key: "_initializeEvents",
value: function _initializeEvents(opt) {
if (opt == null) {
opt = [];
}
if (opt.yearChanged) {
this.element.addEventListener('yearChanged', opt.yearChanged);
}
if (opt.periodChanged) {
this.element.addEventListener('periodChanged', opt.periodChanged);
}
if (opt.renderEnd) {
this.element.addEventListener('renderEnd', opt.renderEnd);
}
if (opt.clickDay) {
this.element.addEventListener('clickDay', opt.clickDay);
}
if (opt.dayContextMenu) {
this.element.addEventListener('dayContextMenu', opt.dayContextMenu);
}
if (opt.selectRange) {
this.element.addEventListener('selectRange', opt.selectRange);
}
if (opt.mouseOnDay) {
this.element.addEventListener('mouseOnDay', opt.mouseOnDay);
}
if (opt.mouseOutDay) {
this.element.addEventListener('mouseOutDay', opt.mouseOutDay);
}
}
}, {
key: "_fetchDataSource",
value: function _fetchDataSource(callback) {
if (typeof this.options.dataSource === "function") {
var getDataSource = this.options.dataSource;
var currentPeriod = this.getCurrentPeriod();
var fetchParameters = {
year: currentPeriod.startDate.getFullYear(),
startDate: currentPeriod.startDate,
endDate: currentPeriod.endDate
};
if (getDataSource.length == 2) {
// 2 parameters, means callback method
getDataSource(fetchParameters, callback);
} else {
// 1 parameter, means synchronous or promise method
var result = getDataSource(fetchParameters);
if (result instanceof Array) {
callback(result);
}
if (result && result.then) {
result.then(callback);
}
}
} else {
callback(this.options.dataSource);
}
}
}, {
key: "_initializeDatasourceColors",
value: function _initializeDatasourceColors() {
for (var i = 0; i < this._dataSource.length; i++) {
if (this._dataSource[i].color == null) {
this._dataSource[i].color = Calendar.colors[i % Calendar.colors.length];
}
}
}
/**
* Renders the calendar.
*/
}, {
key: "render",
value: function render() {
var isLoading = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
// Clear the calendar (faster method)
while (this.element.firstChild) {
this.element.removeChild(this.element.firstChild);
}
if (this.options.displayHeader) {
this._renderHeader();
}
if (isLoading) {
this._renderLoading();
} else {
this._renderBody();
this._renderDataSource();
this._applyEvents(); // Fade animation
var months = this.element.querySelector('.months-container');
months.style.opacity = '0';
months.style.display = 'flex';
months.style.transition = 'opacity 0.5s';
setTimeout(function () {
months.style.opacity = '1';
setTimeout(function () {
return months.style.transition = '';
}, 500);
}, 0);
var currentPeriod = this.getCurrentPeriod();
this._triggerEvent('renderEnd', {
currentYear: currentPeriod.startDate.getFullYear(),
startDate: currentPeriod.startDate,
endDate: currentPeriod.endDate
});
}
}
}, {
key: "_renderHeader",
value: function _renderHeader() {
var header = document.createElement('div');
header.classList.add('calendar-header');
var headerTable = document.createElement('table');
var period = this.getCurrentPeriod(); // Left arrow
var prevDiv = document.createElement('th');
prevDiv.classList.add('prev');
if (this.options.minDate != null && this.options.minDate >= period.startDate) {
prevDiv.classList.add('disabled');
}
var prevIcon = document.createElement('span');
prevIcon.innerHTML = "‹";
prevDiv.appendChild(prevIcon);
headerTable.appendChild(prevDiv);
if (this._isFullYearMode()) {
// Year N-2
var prev2YearDiv = document.createElement('th');
prev2YearDiv.classList.add('year-title');
prev2YearDiv.classList.add('year-neighbor2');
prev2YearDiv.textContent = (this._startDate.getFullYear() - 2).toString();
if (this.options.minDate != null && this.options.minDate > new Date(this._startDate.getFullYear() - 2, 11, 31)) {
prev2YearDiv.classList.add('disabled');
}
headerTable.appendChild(prev2YearDiv); // Year N-1
var prevYearDiv = document.createElement('th');
prevYearDiv.classList.add('year-title');
prevYearDiv.classList.add('year-neighbor');
prevYearDiv.textContent = (this._startDate.getFullYear() - 1).toString();
if (this.options.minDate != null && this.options.minDate > new Date(this._startDate.getFullYear() - 1, 11, 31)) {
prevYearDiv.classList.add('disabled');
}
headerTable.appendChild(prevYearDiv);
} // Current year
var yearDiv = document.createElement('th');
yearDiv.classList.add('year-title');
if (this._isFullYearMode()) {
yearDiv.textContent = this._startDate.getFullYear().toString();
} else if (this.options.numberMonthsDisplayed == 12) {
yearDiv.textContent = "".concat(period.startDate.getFullYear(), " - ").concat(period.endDate.getFullYear());
} else if (this.options.numberMonthsDisplayed > 1) {
yearDiv.textContent = "".concat(Calendar.locales[this.options.language].months[period.startDate.getMonth()], " ").concat(period.startDate.getFullYear(), " - ").concat(Calendar.locales[this.options.language].months[period.endDate.getMonth()], " ").concat(period.endDate.getFullYear());
} else {
yearDiv.textContent = "".concat(Calendar.locales[this.options.language].months[period.startDate.getMonth()], " ").concat(period.startDate.getFullYear());
}
headerTable.appendChild(yearDiv);
if (this._isFullYearMode()) {
// Year N+1
var nextYearDiv = document.createElement('th');
nextYearDiv.classList.add('year-title');
nextYearDiv.classList.add('year-neighbor');
nextYearDiv.textContent = (this._startDate.getFullYear() + 1).toString();
if (this.options.maxDate != null && this.options.maxDate < new Date(this._startDate.getFullYear() + 1, 0, 1)) {
nextYearDiv.classList.add('disabled');
}
headerTable.appendChild(nextYearDiv); // Year N+2
var next2YearDiv = document.createElement('th');
next2YearDiv.classList.add('year-title');
next2YearDiv.classList.add('year-neighbor2');
next2YearDiv.textContent = (this._startDate.getFullYear() + 2).toString();
if (this.options.maxDate != null && this.options.maxDate < new Date(this._startDate.getFullYear() + 2, 0, 1)) {
next2YearDiv.classList.add('disabled');
}
headerTable.appendChild(next2YearDiv);
} // Right arrow
var nextDiv = document.createElement('th');
nextDiv.classList.add('next');
if (this.options.maxDate != null && this.options.maxDate <= period.endDate) {
nextDiv.classList.add('disabled');
}
var nextIcon = document.createElement('span');
nextIcon.innerHTML = "›";
nextDiv.appendChild(nextIcon);
headerTable.appendChild(nextDiv);
header.appendChild(headerTable);
this.element.appendChild(header);
}
}, {
key: "_renderBody",
value: function _renderBody() {
var monthsDiv = document.createElement('div');
monthsDiv.classList.add('months-container');
var monthStartDate = new Date(this._startDate.getTime());
for (var m = 0; m < this.options.numberMonthsDisplayed; m++) {
/* Container */
var monthDiv = document.createElement('div');
monthDiv.classList.add('month-container');
monthDiv.dataset.monthId = m.toString();
if (this._nbCols) {
monthDiv.classList.add("month-".concat(this._nbCols));
}
var table = document.createElement('table');
table.classList.add('month');
/* Month header */
var thead = document.createElement('thead');
var titleRow = document.createElement('tr');
var titleCell = document.createElement('th');
titleCell.classList.add('month-title');
titleCell.setAttribute('colspan', this.options.displayWeekNumber ? '8' : '7');
titleCell.textContent = Calendar.locales[this.options.language].months[monthStartDate.getMonth()];
titleRow.appendChild(titleCell);
thead.appendChild(titleRow);
var headerRow = document.createElement('tr');
if (this.options.displayWeekNumber) {
var weekNumberCell = document.createElement('th');
weekNumberCell.classList.add('week-number');
weekNumberCell.textContent = Calendar.locales[this.options.language].weekShort;
headerRow.appendChild(weekNumberCell);
}
var weekStart = this.getWeekStart();
var d = weekStart;
do {
var headerCell = document.createElement('th');
headerCell.classList.add('day-header');
headerCell.textContent = Calendar.locales[this.options.language].daysMin[d];
if (this._isHidden(d)) {
headerCell.classList.add('hidden');
}
headerRow.appendChild(headerCell);
d++;
if (d >= 7) d = 0;
} while (d != weekStart);
thead.appendChild(headerRow);
table.appendChild(thead);
/* Days */
var currentDate = new Date(monthStartDate.getTime());
var lastDate = new Date(monthStartDate.getFullYear(), monthStartDate.getMonth() + 1, 0);
while (currentDate.getDay() != weekStart) {
currentDate.setDate(currentDate.getDate() - 1);
}
while (currentDate <= lastDate) {
var row = document.createElement('tr');
if (this.options.displayWeekNumber) {
var weekNumberCell = document.createElement('td');
var currentThursday = new Date(currentDate.getTime()); // Week number is computed based on the thursday
currentThursday.setDate(currentThursday.getDate() - weekStart + 4);
weekNumberCell.classList.add('week-number');
weekNumberCell.textContent = this.getWeekNumber(currentThursday).toString();
row.appendChild(weekNumberCell);
}
do {
var cell = document.createElement('td');
cell.classList.add('day');
if (this._isHidden(currentDate.getDay())) {
cell.classList.add('hidden');
}
if (currentDate < monthStartDate) {
cell.classList.add('old');
} else if (currentDate > lastDate) {
cell.classList.add('new');
} else {
if (this._isDisabled(currentDate)) {
cell.classList.add('disabled');
}
var cellContent = document.createElement('div');
cellContent.classList.add('day-content');
cellContent.textContent = currentDate.getDate().toString();
cell.appendChild(cellContent);
if (this.options.customDayRenderer) {
this.options.customDayRenderer(cellContent, currentDate);
}
}
row.appendChild(cell);
currentDate.setDate(currentDate.getDate() + 1);
} while (currentDate.getDay() != weekStart);
table.appendChild(row);
}
monthDiv.appendChild(table);
monthsDiv.appendChild(monthDiv);
monthStartDate.setMonth(monthStartDate.getMonth() + 1);
}
this.element.appendChild(monthsDiv);
}
}, {
key: "_renderLoading",
value: function _renderLoading() {
var container = document.createElement('div');
container.classList.add('calendar-loading-container');
container.style.minHeight = this._nbCols * 200 + 'px';
var loading = document.createElement('div');
loading.classList.add('calendar-loading');
if (this.options.loadingTemplate) {
if (typeof this.options.loadingTemplate === "string") {
loading.innerHTML = this.options.loadingTemplate;
} else if (this.options.loadingTemplate instanceof HTMLElement) {
loading.appendChild(this.options.loadingTemplate);
}
} else {
var spinner = document.createElement('div');
spinner.classList.add('calendar-spinner');
for (var i = 1; i <= 3; i++) {
var bounce = document.createElement('div');
bounce.classList.add("bounce".concat(i));
spinner.appendChild(bounce);
}
loading.appendChild(spinner);
}
container.appendChild(loading);
this.element.appendChild(container);
}
}, {
key: "_renderDataSource",
value: function _renderDataSource() {
var _this = this;
if (this._dataSource != null && this._dataSource.length > 0) {
this.element.querySelectorAll('.month-container').forEach(function (month) {
var monthId = parseInt(month.dataset.monthId);
var currentYear = _this._startDate.getFullYear();
var currentMonth = _this._startDate.getMonth() + monthId;
var firstDate = new Date(currentYear, currentMonth, 1);
var lastDate = new Date(currentYear, currentMonth + 1, 1);
if ((_this.options.minDate == null || lastDate > _this.options.minDate) && (_this.options.maxDate == null || firstDate <= _this.options.maxDate)) {
var monthData = [];
for (var i = 0; i < _this._dataSource.length; i++) {
if (!(_this._dataSource[i].startDate >= lastDate) || _this._dataSource[i].endDate < firstDate) {
monthData.push(_this._dataSource[i]);
}
}
if (monthData.length > 0) {
month.querySelectorAll('.day-content').forEach(function (day) {
var currentDate = new Date(currentYear, currentMonth, parseInt(day.textContent));
var nextDate = new Date(currentYear, currentMonth, currentDate.getDate() + 1);
var dayData = [];
if ((_this.options.minDate == null || currentDate >= _this.options.minDate) && (_this.options.maxDate == null || currentDate <= _this.options.maxDate)) {
for (var i = 0; i < monthData.length; i++) {
if (monthData[i].startDate < nextDate && monthData[i].endDate >= currentDate) {
dayData.push(monthData[i]);
}
}
if (dayData.length > 0 && (_this.options.displayDisabledDataSource || !_this._isDisabled(currentDate))) {
_this._renderDataSourceDay(day, currentDate, dayData);
}
}
});
}
}
});
}
}
}, {
key: "_renderDataSourceDay",
value: function _renderDataSourceDay(elt, currentDate, events) {
var parent = elt.parentElement;
switch (this.options.style) {
case 'border':
var weight = 0;
if (events.length == 1) {
weight = 4;
} else if (events.length <= 3) {
weight = 2;
} else {
parent.style.boxShadow = 'inset 0 -4px 0 0 black';
}
if (weight > 0) {
var boxShadow = '';
for (var i = 0; i < events.length; i++) {
if (boxShadow != '') {
boxShadow += ",";
}
boxShadow += "inset 0 -".concat((i + 1) * weight, "px 0 0 ").concat(events[i].color);
}
parent.style.boxShadow = boxShadow;
}
break;
case 'background':
parent.style.backgroundColor = events[events.length - 1].color;
var currentTime = currentDate.getTime();
if (events[events.length - 1].startDate.getTime() == currentTime) {
parent.classList.add('day-start');
if (events[events.length - 1].startHalfDay || this.options.alwaysHalfDay) {
parent.classList.add('day-half'); // Find color for other half
var otherColor = 'transparent';
for (var i = events.length - 2; i >= 0; i--) {
if (events[i].startDate.getTime() != currentTime || !events[i].startHalfDay && !this.options.alwaysHalfDay) {
otherColor = events[i].color;
break;
}
}
parent.style.background = "linear-gradient(-45deg, ".concat(events[events.length - 1].color, ", ").concat(events[events.length - 1].color, " 49%, ").concat(otherColor, " 51%, ").concat(otherColor, ")");
} else if (this.options.roundRangeLimits) {
parent.classList.add('round-left');
}
} else if (events[events.length - 1].endDate.getTime() == currentTime) {
parent.classList.add('day-end');
if (events[events.length - 1].endHalfDay || this.options.alwaysHalfDay) {
parent.classList.add('day-half'); // Find color for other half
var otherColor = 'transparent';
for (var i = events.length - 2; i >= 0; i--) {
if (events[i].endDate.getTime() != currentTime || !events[i].endHalfDay && !this.options.alwaysHalfDay) {
otherColor = events[i].color;
break;
}
}
parent.style.background = "linear-gradient(135deg, ".concat(events[events.length - 1].color, ", ").concat(events[events.length - 1].color, " 49%, ").concat(otherColor, " 51%, ").concat(otherColor, ")");
} else if (this.options.roundRangeLimits) {
parent.classList.add('round-right');
}
}
break;
case 'custom':
if (this.options.customDataSourceRenderer) {
this.options.customDataSourceRenderer.call(this, elt, currentDate, events);
}
break;
}
}
}, {
key: "_applyEvents",
value: function _applyEvents() {
var _this2 = this;
if (this.options.displayHeader) {
/* Header buttons */
this.element.querySelectorAll('.year-neighbor, .year-neighbor2').forEach(function (element) {
element.addEventListener('click', function (e) {
if (!e.currentTarget.classList.contains('disabled')) {
_this2.setYear(parseInt(e.currentTarget.textContent));
}
});
});
this.element.querySelector('.calendar-header .prev').addEventListener('click', function (e) {
if (!e.currentTarget.classList.contains('disabled')) {
var months = _this2.element.querySelector('.months-container');
months.style.transition = 'margin-left 0.1s';
months.style.marginLeft = '100%';
setTimeout(function () {
months.style.visibility = 'hidden';
months.style.transition = '';
months.style.marginLeft = '0';
setTimeout(function () {
_this2.setStartDate(new Date(_this2._startDate.getFullYear(), _this2._startDate.getMonth() - _this2.options.numberMonthsDisplayed, 1));
}, 50);
}, 100);
}
});
this.element.querySelector('.calendar-header .next').addEventListener('click', function (e) {
if (!e.currentTarget.classList.contains('disabled')) {
var months = _this2.element.querySelector('.months-container');
months.style.transition = 'margin-left 0.1s';
months.style.marginLeft = '-100%';
setTimeout(function () {
months.style.visibility = 'hidden';
months.style.transition = '';
months.style.marginLeft = '0';
setTimeout(function () {
_this2.setStartDate(new Date(_this2._startDate.getFullYear(), _this2._startDate.getMonth() + _this2.options.numberMonthsDisplayed, 1));
}, 50);
}, 100);
}
});
}
var cells = this.element.querySelectorAll('.day:not(.old):not(.new):not(.disabled)');
cells.forEach(function (cell) {
/* Click on date */
cell.addEventListener('click', function (e) {
e.stopPropagation();
var date = _this2._getDate(e.currentTarget);
_this2._triggerEvent('clickDay', {
element: e.currentTarget,
date: date,
events: _this2.getEvents(date)
});
});
/* Click right on date */
cell.addEventListener('contextmenu', function (e) {
if (_this2.options.enableContextMenu) {
e.preventDefault();
if (_this2.options.contextMenuItems.length > 0) {
_this2._openContextMenu(e.currentTarget);
}
}
var date = _this2._getDate(e.currentTarget);
_this2._triggerEvent('dayContextMenu', {
element: e.currentTarget,
date: date,
events: _this2.getEvents(date)
});
});
/* Range selection */
if (_this2.options.enableRangeSelection) {
cell.addEventListener('mousedown', function (e) {
if (e.which == 1) {
var currentDate = _this2._getDate(e.currentTarget);
if (_this2.options.allowOverlap || _this2.isThereFreeSlot(currentDate)) {
_this2._mouseDown = true;
_this2._rangeStart = _this2._rangeEnd = currentDate;
_this2._refreshRange();
}
}
});
cell.addEventListener('mouseenter', function (e) {
if (_this2._mouseDown) {
var currentDate = _this2._getDate(e.currentTarget);
if (!_this2.options.allowOverlap) {
var newDate = new Date(_this2._rangeStart.getTime());
if (newDate < currentDate) {
var nextDate = new Date(newDate.getFullYear(), newDate.getMonth(), newDate.getDate() + 1);
while (newDate < currentDate) {
if (!_this2.isThereFreeSlot(nextDate, false)) {
break;
}
newDate.setDate(newDate.getDate() + 1);
nextDate.setDate(nextDate.getDate() + 1);
}
} else {
var nextDate = new Date(newDate.getFullYear(), newDate.getMonth(), newDate.getDate() - 1);
while (newDate > currentDate) {
if (!_this2.isThereFreeSlot(nextDate, true)) {
break;
}
newDate.setDate(newDate.getDate() - 1);
nextDate.setDate(nextDate.getDate() - 1);
}
}
currentDate = newDate;
}
var oldValue = _this2._rangeEnd;
_this2._rangeEnd = currentDate;
if (oldValue.getTime() != _this2._rangeEnd.getTime()) {
_this2._refreshRange();
}
}
});
}
/* Hover date */
cell.addEventListener('mouseenter', function (e) {
if (!_this2._mouseDown) {
var date = _this2._getDate(e.currentTarget);
_this2._triggerEvent('mouseOnDay', {
element: e.currentTarget,
date: date,
events: _this2.getEvents(date)
});
}
});
cell.addEventListener('mouseleave', function (e) {
var date = _this2._getDate(e.currentTarget);
_this2._triggerEvent('mouseOutDay', {
element: e.currentTarget,
date: date,
events: _this2.getEvents(date)
});
});
});
if (this.options.enableRangeSelection) {
// Release range selection
window.addEventListener('mouseup', function (e) {
if (_this2._mouseDown) {
_this2._mouseDown = false;
_this2._refreshRange();
var minDate = _this2._rangeStart < _this2._rangeEnd ? _this2._rangeStart : _this2._rangeEnd;
var maxDate = _this2._rangeEnd > _this2._rangeStart ? _this2._rangeEnd : _this2._rangeStart;
_this2._triggerEvent('selectRange', {
startDate: minDate,
endDate: maxDate,
events: _this2.getEventsOnRange(minDate, new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate() + 1))
});
}
});
}
/* Responsive management */
if (this._responsiveInterval) {
clearInterval(this._responsiveInterval);
this._responsiveInterval = null;
}
this._responsiveInterval = setInterval(function () {
if (_this2.element.querySelector('.month') == null) {
return;
}
var calendarSize = _this2.element.offsetWidth;
var monthSize = _this2.element.querySelector('.month').offsetWidth + 10;
_this2._nbCols = null;
if (monthSize * 6 < calendarSize && _this2.options.numberMonthsDisplayed >= 6) {
_this2._nbCols = 2;
} else if (monthSize * 4 < calendarSize && _this2.options.numberMonthsDisplayed >= 4) {
_this2._nbCols = 3;
} else if (monthSize * 3 < calendarSize && _this2.options.numberMonthsDisplayed >= 3) {
_this2._nbCols = 4;
} else if (monthSize * 2 < calendarSize && _this2.options.numberMonthsDisplayed >= 2) {
_this2._nbCols = 6;
} else {
_this2._nbCols = 12;
}
_this2.element.querySelectorAll('.month-container').forEach(function (month) {
if (!month.classList.contains("month-".concat(_this2._nbCols))) {
['month-2', 'month-3', 'month-4', 'month-6', 'month-12'].forEach(function (className) {
month.classList.remove(className);
});
month.classList.add("month-".concat(_this2._nbCols));
}
});
}, 300);
}
}, {
key: "_refreshRange",
value: function _refreshRange() {
var _this3 = this;
this.element.querySelectorAll('td.day.range').forEach(function (day) {
return day.classList.remove('range');
});
this.element.querySelectorAll('td.day.range-start').forEach(function (day) {
return day.classList.remove('range-start');
});
this.element.querySelectorAll('td.day.range-end').forEach(function (day) {
return day.classList.remove('range-end');
});
if (this._mouseDown) {
var minDate = this._rangeStart < this._rangeEnd ? this._rangeStart : this._rangeEnd;
var maxDate = this._rangeEnd > this._rangeStart ? this._rangeEnd : this._rangeStart;
this.element.querySelectorAll('.month-container').forEach(function (month) {
var monthId = parseInt(month.dataset.monthId);
var monthStartDate = new Date(_this3._startDate.getFullYear(), _this3._startDate.getMonth() + monthId, 1);
var monthEndDate = new Date(_this3._startDate.getFullYear(), _this3._startDate.getMonth() + monthId + 1, 1);
if (minDate.getTime() < monthEndDate.getTime() && maxDate.getTime() >= monthStartDate.getTime()) {
month.querySelectorAll('td.day:not(.old):not(.new)').forEach(function (day) {
var date = _this3._getDate(day);
if (date >= minDate && date <= maxDate) {
day.classList.add('range');
if (date.getTime() == minDate.getTime()) {
day.classList.add('range-start');
}
if (date.getTime() == maxDate.getTime()) {
day.classList.add('range-end');
}
}
});
}
});
}
}
}, {
key: "_getElementPosition",
value: function _getElementPosition(element) {
var top = 0,
left = 0;
do {
top += element.offsetTop || 0;
left += element.offsetLeft || 0;
element = element.offsetParent;
} while (element);
return {
top: top,
left: left
};
}
}, {
key: "_openContextMenu",
value: function _openContextMenu(elt) {
var _this4 = this;
var contextMenu = document.querySelector('.calendar-context-menu');
if (contextMenu !== null) {
contextMenu.style.display = 'none'; // Clear the context menu (faster method)
while (contextMenu.firstChild) {
contextMenu.removeChild(contextMenu.firstChild);
}
} else {
contextMenu = document.createElement('div');
contextMenu.classList.add('calendar-context-menu');
document.body.appendChild(contextMenu);
}
var date = this._getDate(elt);
var events = this.getEvents(date);
for (var i = 0; i < events.length; i++) {
var eventItem = document.createElement('div');
eventItem.classList.add('item');
eventItem.style.paddingLeft = '4px';
eventItem.style.boxShadow = "inset 4px 0 0 0 ".concat(events[i].color);
var eventItemContent = document.createElement('div');
eventItemContent.classList.add('content');
var text = document.createElement('span');
text.classList.add('text');
text.textContent = events[i].name;
eventItemContent.appendChild(text);
var icon = document.createElement('span');
icon.classList.add('arrow');
icon.innerHTML = "›";
eventItemContent.appendChild(icon);
eventItem.appendChild(eventItemContent);
this._renderContextMenuItems(eventItem, this.options.contextMenuItems, events[i]);
contextMenu.appendChild(eventItem);
}
if (contextMenu.children.length > 0) {
var position = this._getElementPosition(elt);
contextMenu.style.left = position.left + 25 + 'px';
contextMenu.style.right = '';
contextMenu.style.top = position.top + 25 + 'px';
contextMenu.style.display = 'block';
if (contextMenu.getBoundingClientRect().right > document.body.offsetWidth) {
contextMenu.style.left = '';
contextMenu.style.right = '0';
} // Launch the position check once the whole context menu tree will be rendered
setTimeout(function () {
return _this4._checkContextMenuItemsPosition();
}, 0);
var closeContextMenu = function closeContextMenu(event) {
if (event.type !== 'click' || !contextMenu.contains(event.target)) {
contextMenu.style.display = 'none';
window.removeEventListener('click', closeContextMenu);
window.removeEventListener('resize', closeContextMenu);
window.removeEventListener('scroll', closeContextMenu);
}
};
window.addEventListener('click', closeContextMenu);
window.addEventListener('resize', closeContextMenu);
window.addEventListener('scroll', closeContextMenu);
}
}
}, {
key: "_renderContextMenuItems",
value: function _renderContextMenuItems(parent, items, evt) {
var subMenu = document.createElement('div');
subMenu.classList.add('submenu');
for (var i = 0; i < items.length; i++) {
if (items[i].visible === false || typeof items[i].visible === "function" && !items[i].visible(evt)) {
continue;
}
var menuItem = document.createElement('div');
menuItem.classList.add('item');
var menuItemContent = document.createElement('div');
menuItemContent.classList.add('content');
var text = document.createElement('span');
text.classList.add('text');
text.textContent = items[i].text;
menuItemContent.appendChild(text);
if (items[i].click) {
(function (index) {
menuItemContent.addEventListener('click', function () {
document.querySelector('.calendar-context-menu').style.display = 'none';
items[index].click(evt);
});
})(i);
}
menuItem.appendChild(menuItemContent);
if (items[i].items && items[i].items.length > 0) {
var icon = document.createElement('span');
icon.classList.add('arrow');
icon.innerHTML = "›";
menuItemContent.appendChild(icon);
this._renderContextMenuItems(menuItem, items[i].items, evt);
}
subMenu.appendChild(menuItem);
}
if (subMenu.children.length > 0) {
parent.appendChild(subMenu);
}
}
}, {
key: "_checkContextMenuItemsPosition",
value: function _checkContextMenuItemsPosition() {
var menus = document.querySelectorAll('.calendar-context-menu .submenu');
menus.forEach(function (menu) {
var htmlMenu = menu;
htmlMenu.style.display = 'block';
htmlMenu.style.visibility = 'hidden';
});
menus.forEach(function (menu) {
var htmlMenu = menu;
if (htmlMenu.getBoundingClientRect().right > document.body.offsetWidth) {
htmlMenu.classList.add('open-left');
} else {
htmlMenu.classList.remove('open-left');
}
});
menus.forEach(function (menu) {
var htmlMenu = menu;
htmlMenu.style.display = '';
htmlMenu.style.visibility = '';
});
}
}, {
key: "_getDate",
value: function _getDate(elt) {
var day = elt.querySelector('.day-content').textContent;
var monthId = parseInt(elt.closest('.month-container').dataset.monthId);
return new Date(this._startDate.getFullYear(), this._startDate.getMonth() + monthId, day);
}
}, {
key: "_triggerEvent",
value: function _triggerEvent(eventName, parameters) {
var event = null;
if (typeof Event === "function") {
event = new Event(eventName);
} else {
event = document.createEvent('Event');
event.initEvent(eventName, false, false);
}
event.calendar = this;
for (var i in parameters) {
event[i] = parameters[i];
}
this.element.dispatchEvent(event);
return event;
}
}, {
key: "_isDisabled",
value: function _isDisabled(date) {
if (this.options.minDate != null && date < this.options.minDate || this.options.maxDate != null && date > this.options.maxDate) {
return true;
}
if (this.options.disabledWeekDays.length > 0) {
for (var d = 0; d < this.options.disabledWeekDays.length; d++) {
if (date.getDay() == this.options.disabledWeekDays[d]) {
return true;
}
}
}
if (this.options.disabledDays.length > 0) {
for (var d = 0; d < this.options.disabledDays.length; d++) {
if (date.getTime() == this.options.disabledDays[d].getTime()) {
return true;
}
}
}
return false;
}
}, {
key: "_isHidden",
value: function _isHidden(day) {
if (this.options.hiddenWeekDays.length > 0) {
for (var d = 0; d < this.options.hiddenWeekDays.length; d++) {
if (day == this.options.hiddenWeekDays[d]) {
return true;
}
}
}
return false;
}
}, {
key: "_isFullYearMode",
value: function _isFullYearMode() {
return this._startDate.getMonth() == 0 && this.options.numberMonthsDisplayed == 12;
}
/**
* Gets the week number for a specified date.
*
* @param date The specified date.
*/
}, {
key: "getWeekNumber",
value: function getWeekNumber(date) {
// Algorithm from https://weeknumber.net/how-to/javascript
var workingDate = new Date(date.getTime());
workingDate.setHours(0, 0, 0, 0); // Thursday in current week decides the year.
workingDate.setDate(workingDate.getDate() + 3 - (workingDate.getDay() + 6) % 7); // January 4 is always in week 1.
var week1 = new Date(workingDate.getFullYear(), 0, 4); // Adjust to Thursday in week 1 and count number of weeks from date to week1.
return 1 + Math.round(((workingDate.getTime() - week1.getTime()) / 86400000 - 3 + (week1.getDay() + 6) % 7) / 7);
}
/**
* Gets the data source elements for a specified day.