(function ($) {
var todayDate = new Date();
todayDate.setHours(0, 0, 0, 0);
var monthMap = {
1: "january",
2: "february",
3: "march",
4: "april",
5: "may",
6: "june",
7: "july",
8: "august",
9: "september",
10: "october",
11: "november",
12: "december",
};
var dayMap = {
0: "sunday",
1: "monday",
2: "tuesday",
3: "wednesday",
4: "thursday",
5: "friday",
6: "saturday",
};
var alternateDayMap = {
1: "monday",
2: "tuesday",
3: "wednesday",
4: "thursday",
5: "friday",
6: "saturday",
7: "sunday",
};
// These are the defaults.
var defaults = {
date: null,
weekDayLength: 1,
prevButton: "Prev",
nextButton: "Next",
monthYearSeparator: " ",
onClickDate: function (date) {},
onChangeMonth: function (date) {},
onClickToday: function (date) {},
onClickMonthNext: function (date) {},
onClickMonthPrev: function (date) {},
onClickYearNext: function (date) {},
onClickYearPrev: function (date) {},
onShowYearView: function (date) {},
onSelectYear: function (date) {},
customDateProps: function (date) {
return { classes: "", data: {} };
},
customDateHeaderProps: function (weekDay) {
return { classes: "", data: {} };
},
customWeekProps: function (weekNo) {
return { classes: "", data: {} };
},
showThreeMonthsInARow: true,
enableMonthChange: true,
enableYearView: true,
showTodayButton: true,
highlightSelectedWeekday: true,
highlightSelectedWeek: true,
todayButtonContent: "Today",
showYearDropdown: false,
min: null,
max: null,
disable: function (date) {},
startOnMonday: false,
monthMap,
dayMap,
alternateDayMap,
};
var el,
selectedDate,
yearView = false;
function getFirstDayOfMonth(currentDate) {
var thisDate =
currentDate.getMonth() + 1 + "/1/" + currentDate.getFullYear();
return new Date(thisDate);
}
function getLastDayOfMonth(currentDate) {
return new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 0);
}
function getLastMonthLastDay(currentDate) {
var month = currentDate.getMonth();
var year = currentDate.getFullYear();
if (month === 0) {
year -= 1;
month = 12;
}
return new Date(year, month, 0);
}
function generateWeekData(currentDate, weekNo) {
var firstDay = getFirstDayOfMonth(currentDate);
var firstDayDate = firstDay.getDate();
var lastDay = getLastDayOfMonth(currentDate);
var lastDayFromLastMonth = getLastMonthLastDay(currentDate).getDate();
var days = [];
var daysFromLastMonth = firstDay.getDay();
if (settings.startOnMonday) {
daysFromLastMonth = daysFromLastMonth - 1;
}
var daysFromNextMonth = 1;
if (weekNo === 1) {
var dayFromLastMonth =
daysFromLastMonth - 1 < 0
? 6 + daysFromLastMonth
: daysFromLastMonth - 1;
if (dayFromLastMonth < 6) {
for (daysFromLastMonth; dayFromLastMonth >= 0; dayFromLastMonth--) {
var dateObj = new Date(
currentDate.getFullYear(),
currentDate.getMonth() - 1,
lastDayFromLastMonth - dayFromLastMonth
);
days.push(dateObj);
}
}
var daysLength = 7 - days.length;
for (var monthDate = 0; monthDate < daysLength; monthDate++) {
var dateObj = new Date(
firstDay.getFullYear(),
firstDay.getMonth(),
firstDayDate + monthDate
);
days.push(dateObj);
}
} else {
var startWeekFrom =
(weekNo - (daysFromLastMonth < 0 ? 2 : 1)) * 7 - daysFromLastMonth;
for (var i = 1; i <= 7; i++) {
if (startWeekFrom + i <= lastDay) {
var dateObj = new Date(
currentDate.getFullYear(),
currentDate.getMonth(),
startWeekFrom + i
);
days.push(dateObj);
} else {
var dateObj = new Date(
currentDate.getFullYear(),
currentDate.getMonth() + 1,
daysFromNextMonth++
);
days.push(dateObj);
}
}
}
return days;
}
function generateMonthData(currentDate) {
var lastMonthLast = getLastDayOfMonth(currentDate).getDate();
var lastDayFromMonth = getLastDayOfMonth(currentDate).getDate();
var weeks = parseInt(lastMonthLast / 7) + 1;
var monthData = [];
for (var weekNo = 1; weekNo <= weeks; weekNo++) {
monthData.push(generateWeekData(currentDate, weekNo));
}
var lastBlock = monthData[monthData.length - 1];
var lastDayInBlock = lastBlock[lastBlock.length - 1].getDate();
if (
lastDayInBlock < lastDayFromMonth &&
lastDayFromMonth - lastDayInBlock < 7
) {
monthData.push(generateWeekData(currentDate, weekNo));
}
return monthData;
}
function generateTodayButton() {
return (
"" +
'
' +
'" +
"
"
);
}
function generateYearHeaderDOM(currentDate) {
var str =
"" +
'' +
(settings.enableMonthChange && settings.enableYearView
? '"
: "") +
'';
if (settings.showYearDropdown) {
str += "" + '";
} else {
str += currentDate.getFullYear();
}
str +=
"" +
(settings.enableMonthChange && settings.enableYearView
? '"
: "") +
"
";
return str;
}
function generateMonthDOM(currentDate) {
var str = "";
str += '';
for (var month in settings.monthMap) {
if (settings.monthMap.hasOwnProperty(month)) {
var showThreeMonthsInARow = "";
showThreeMonthsInARow = settings.showThreeMonthsInARow
? " one-third"
: "";
str +=
'' +
settings.monthMap[month] +
"";
}
}
str += "
";
return str;
}
function generateMonthHeaderDOM(currentDate) {
return (
"" +
'' +
(settings.enableMonthChange
? '"
: "") +
'' +
'' +
settings.monthMap[currentDate.getMonth() + 1] +
"" +
settings.monthYearSeparator +
'' +
currentDate.getFullYear() +
"" +
"" +
(settings.enableMonthChange
? '"
: "") +
"
"
);
}
function generateWeekHeaderDOM(currentDate) {
const { classes: weekClasses, data: weekData } =
settings.customWeekProps(0);
let dataStr = "";
if (Object.keys(weekData)) {
Object.keys(weekData).forEach((item) => {
dataStr += ` data-${item}="${weekData[item]}" `;
});
}
var str = "";
str += '";
return str;
}
function generateWeekDOM(monthData, currentDate) {
var str = "";
str += '';
monthData.forEach(function (week, weekNo) {
const { classes, data } = settings.customWeekProps(weekNo);
let dataStr = "";
if (Object.keys(data)) {
Object.keys(data).forEach((item) => {
dataStr += ` data-${item}="${data[item]}" `;
});
}
str +=
'
";
week.forEach(function (day, dayNo) {
var disabled = false;
if (day.getMonth() !== currentDate.getMonth()) disabled = true;
disabled = disabled ? " disabled" : "";
var selected = false;
if (selectedDate) {
if (day == selectedDate.toString()) selected = true;
selected = selected ? " selected" : "";
} else {
selected = "";
}
var today = false;
if (day == todayDate.toString()) today = true;
today = today ? " today" : "";
var dateDisabled = "ola";
if (
(settings.min && settings.min > day) ||
(settings.max && settings.max < day) ||
(settings.disable &&
typeof settings.disable === "function" &&
settings.disable(day))
) {
dateDisabled = 'disabled="disabled" ';
}
const { classes, data } = settings.customDateProps(day);
let dataStr = "";
if (Object.keys(data)) {
Object.keys(data).forEach((item) => {
dataStr += ` data-${item}="${data[item]}" `;
});
}
str +=
'
" +
(typeof settings.formatDate === "function"
? settings.formatDate(day)
: day.getDate()) +
"
";
});
str += "
";
});
str += "
";
return str;
}
function generateDomString(monthData, currentDate) {
var calendarDump = "";
calendarDump += '';
if (yearView) {
calendarDump += '
';
calendarDump += generateYearHeaderDOM(currentDate);
calendarDump += generateMonthDOM(currentDate);
calendarDump += "
";
} else {
calendarDump += '
';
calendarDump += generateMonthHeaderDOM(currentDate);
calendarDump += generateWeekHeaderDOM(currentDate);
calendarDump += generateWeekDOM(monthData, currentDate);
calendarDump += "
";
}
if (settings.showTodayButton) {
calendarDump += generateTodayButton();
}
calendarDump += "
";
return calendarDump;
}
function highlightDays() {
var selectedElement = el.find(".selected");
if (selectedElement.length > 0) {
var date = new Date(selectedElement.data("date"));
var weekDayNo = date.getDay();
el.find(".week").each(function (i, elm) {
$(elm)
.find(
".day:eq(" + (weekDayNo - (settings.startOnMonday ? 1 : 0)) + ")"
)
.addClass("highlight");
});
}
}
function highlightWeek() {
el.find(".selected").parents(".week").addClass("highlight");
}
function renderToDom(currentDate) {
var monthData = generateMonthData(currentDate);
el.html(generateDomString(monthData, currentDate));
if (settings.highlightSelectedWeekday) {
highlightDays();
}
if (settings.highlightSelectedWeek) {
highlightWeek();
}
}
$.fn.updateCalendarOptions = function (options) {
var updatedOptions = $.extend(settings, options);
var calendarInitFn = $.fn.calendar.bind(this);
calendarInitFn(updatedOptions);
};
$.fn.calendar = function (options) {
settings = $.extend(defaults, options);
if (settings.startOnMonday) {
settings.dayMap = settings.alternateDayMap;
}
if (settings.min) {
settings.min = new Date(settings.min);
settings.min.setHours(0);
settings.min.setMinutes(0);
settings.min.setSeconds(0);
}
if (settings.max) {
settings.max = new Date(settings.max);
settings.max.setHours(0);
settings.max.setMinutes(0);
settings.max.setSeconds(0);
}
el = $(this);
var currentDate;
if (settings.date) {
if (typeof settings.date === "string") {
selectedDate = new Date(settings.date);
} else {
selectedDate = settings.date;
}
selectedDate.setHours(0, 0, 0, 0);
currentDate = selectedDate;
} else {
currentDate = todayDate;
}
window.currentDate = currentDate;
renderToDom(currentDate);
if (settings.enableMonthChange) {
el.off("click", ".weeks-container .prev-button").on(
"click",
".weeks-container .prev-button",
function (e) {
currentDate = new Date(
currentDate.getFullYear(),
currentDate.getMonth() - 1,
1
);
settings.onClickMonthPrev(currentDate);
renderToDom(currentDate);
}
);
el.off("click", ".weeks-container .next-button").on(
"click",
".weeks-container .next-button",
function (e) {
currentDate = new Date(
currentDate.getFullYear(),
currentDate.getMonth() + 1,
1
);
settings.onClickMonthNext(currentDate);
renderToDom(currentDate);
}
);
}
el.off("click", ".day").on("click", ".day", function (e) {
var date = $(this).data("date");
var isDisabled = $(this).attr("disabled") === "disabled";
if (isDisabled) return;
settings.onClickDate(date);
});
if (settings.enableMonthChange && settings.enableYearView) {
el.off("click", ".month-container").on(
"click",
".month-container",
function (e) {
yearView = true;
currentDate = new Date(currentDate.getFullYear(), 0, 1);
settings.onShowYearView(currentDate);
renderToDom(currentDate);
}
);
el.off("click", ".months-container .month").on(
"click",
".months-container .month",
function (e) {
var monthEl = $(this);
var month = monthEl.data("month");
var year = monthEl.data("year");
var selectedMonth = new Date(year, month - 1, 1);
settings.onChangeMonth(selectedMonth);
currentDate = selectedMonth;
yearView = false;
renderToDom(currentDate);
}
);
el.off("click", ".months-container .prev-button").on(
"click",
".months-container .prev-button",
function (e) {
currentDate = new Date(currentDate.getFullYear() - 1, 0, 1);
settings.onClickYearPrev(currentDate);
settings.onSelectYear(currentDate);
renderToDom(currentDate);
}
);
el.off("click", ".months-container .next-button").on(
"click",
".months-container .next-button",
function (e) {
currentDate = new Date(currentDate.getFullYear() + 1, 0, 1);
settings.onClickMonthNext(currentDate);
settings.onSelectYear(currentDate);
renderToDom(currentDate);
}
);
el.off("change", ".months-container .year-dropdown").on(
"change",
".months-container .year-dropdown",
function (e) {
var year = $(this).val();
currentDate = new Date(year, 0, 1);
settings.onSelectYear(currentDate);
renderToDom(currentDate);
}
);
}
if (settings.showTodayButton) {
el.off("click", ".today-button").on(
"click",
".today-button",
function (e) {
currentDate = todayDate;
selectedDate = todayDate;
settings.onClickToday(todayDate);
settings.onClickDate(todayDate);
yearView = false;
renderToDom(currentDate);
}
);
}
this.getSelectedDate = function () {
return selectedDate;
};
return this;
};
})(jQuery);