(function ($) { var weekdays = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So']; var months = ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember']; function AvailabilityCalendar(container, bookedDates) { this.date = new Date(); this.date.setDate(1); this.container = container; this.bookedDates = bookedDates; this.createCalendar(); this.renderMonth(); } AvailabilityCalendar.prototype = { /** * Setup methods */ __createToolbar: function () { var $toolbar = $('
').appendTo(this.container); $toolbar.addClass('availability-calendar-toolbar'); this.$monthLabel = $('').appendTo($toolbar); var $inputContainer = $('').appendTo($toolbar); $inputContainer.append(''); $inputContainer.append(''); $inputContainer.append(''); var $inputs = $inputContainer.children('input'); var self = this; $inputs.eq(0).on('click', function () { self.date = new Date(); self.date.setDate(1); self.renderMonth(); }); $inputs.eq(1).on('click', function () { self.date.setMonth(self.date.getMonth() - 1); self.renderMonth(); }); $inputs.eq(2).on('click', function () { self.date.setMonth(self.date.getMonth() + 1); self.renderMonth(); }); }, __createTable: function () { var $table = $('
').appendTo(this.container); $table.addClass('availability-calendar'); // Weekday headers var $tr = $('').appendTo($table); weekdays.forEach(function (day) { $('').html(day).appendTo($tr); }); // Day cells for (var i = 0; i < 6; ++i) { $tr = $('').appendTo($table); $tr.append(''); } this.$cells = $table.find('td'); }, createCalendar: function () { this.__createToolbar(); this.__createTable(); }, /** * Month rendering methods */ __addPreviousMonthDays: function (date, cellIndexes, dates) { var firstWeekdayOfMonth = date.getDay() - 1; if (firstWeekdayOfMonth < 0) firstWeekdayOfMonth = 6; if (firstWeekdayOfMonth > 0) { date.setDate(0); var numDays = date.getDate(); for (var i = numDays - firstWeekdayOfMonth + 1; i <= numDays; ++i) { this.$cells.eq(dates.length).html(i).addClass('ex-month'); date.setDate(i); var dateInt = date.valueOf(); cellIndexes[dateInt] = dates.length; dates.push(dateInt); } } }, __addThisMonthDays: function (date, year, month, cellIndexes, dates) { date.setFullYear(year, month + 1, 0); // Need to reset year var numDays = date.getDate(); for (var i = 1; i <= numDays; ++i) { this.$cells.eq(dates.length).html(i); date.setDate(i); var dateInt = date.valueOf(); cellIndexes[dateInt] = dates.length; dates.push(dateInt); } }, __addNextMonthDays: function (date, month, cellIndexes, dates) { if (dates.length < 42) { date.setMonth(month + 1, 1); var remainingDays = 42 - dates.length; for (var i = 1; i <= remainingDays; ++i) { this.$cells.eq(dates.length).html(i).addClass('ex-month'); date.setDate(i); var dateInt = date.valueOf(); cellIndexes[dateInt] = dates.length; dates.push(dateInt); } } }, __addEvents: function (cellIndexes, dates) { var firstDate = dates[0]; var lastDate = dates[dates.length - 1]; var self = this; this.bookedDates.forEach(function (date) { if (date.start <= lastDate && date.end >= firstDate) { var startIndex = cellIndexes[date.start]; var endIndex = cellIndexes[date.end]; if (startIndex !== undefined) { self.$cells.eq(startIndex).addClass('unavailable').append('
'); ++startIndex; } else { startIndex = cellIndexes[firstDate]; } if (endIndex !== undefined) { self.$cells.eq(endIndex).addClass('unavailable').append('
'); --endIndex; } else { endIndex = cellIndexes[lastDate]; } self.$cells.slice(startIndex, endIndex + 1).addClass('unavailable').append('
'); $('.unavailable').attr('data-toggle', 'tooltip'); $('.unavailable').attr('title', 'Artikel nicht verfügbar'); $('.unavailable').addClass('unavailablePointer'); } }); }, renderMonth: function () { var cellIndexes = {}; var dates = []; var year = this.date.getFullYear(); var month = this.date.getMonth(); var date = new Date(year, month, 1); this.$monthLabel.html(months[month] + ' ' + year); this.$cells.removeClass('ex-month'); this.$cells.filter('.unavailable').removeClass('unavailable').children().remove(); this.__addPreviousMonthDays(date, cellIndexes, dates); this.__addThisMonthDays(date, year, month, cellIndexes, dates); this.__addNextMonthDays(date, month, cellIndexes, dates); this.__addEvents(cellIndexes, dates); } }; $.fn.availabilityCalendar = function (bookedDates) { var dates = []; bookedDates.forEach(function (date) { var start = new Date(date.start); var end = new Date(date.end); start.setHours(0, 0, 0, 0); end.setHours(0, 0, 0, 0); start = start.valueOf(); end = end.valueOf(); if (start <= end) { dates.push({ start: start, end: end }); } }); this.each(function () { new AvailabilityCalendar(this, dates); }); return this; }; })(jQuery);