(function ($, moment) { var pluginName = "bootstrapMaterialDatePicker"; var pluginDataName = "plugin_" + pluginName; moment.locale('en'); function Plugin(element, options) { this.currentView = 0; this.minDate; this.maxDate; this._attachedEvents = []; this.element = element; this.$element = $(element); this.params = {date: true, time: true, format: 'YYYY-MM-DD', minDate: null, maxDate: null, currentDate: null, lang: 'en', weekStart: 0, shortTime: false, clearButton: false, nowButton: false, cancelText: 'Cancel', okText: 'OK', clearText: 'Clear', nowText: 'Now', switchOnClick: false}; this.params = $.fn.extend(this.params, options); this.name = "dtp_" + this.setName(); this.$element.attr("data-dtp", this.name); moment.locale(this.params.lang); this.init(); } $.fn[pluginName] = function (options, p) { this.each(function () { if (!$.data(this, pluginDataName)) { $.data(this, pluginDataName, new Plugin(this, options)); } else { if (typeof ($.data(this, pluginDataName)[options]) === 'function') { $.data(this, pluginDataName)[options](p); } if (options === 'destroy') { delete $.data(this, pluginDataName); } } }); return this; }; Plugin.prototype = { init: function () { this.initDays(); this.initDates(); this.initTemplate(); this.initButtons(); this._attachEvent($(window), 'resize', this._centerBox.bind(this)); this._attachEvent(this.$dtpElement.find('.dtp-content'), 'click', this._onElementClick.bind(this)); this._attachEvent(this.$dtpElement, 'click', this._onBackgroundClick.bind(this)); this._attachEvent(this.$dtpElement.find('.dtp-close > a'), 'click', this._onCloseClick.bind(this)); this._attachEvent(this.$element, 'focus', this._onFocus.bind(this)); }, initDays: function () { this.days = []; for (var i = this.params.weekStart; this.days.length < 7; i++) { if (i > 6) { i = 0; } this.days.push(i.toString()); } }, initDates: function () { if (this.$element.val().length > 0) { if (typeof (this.params.format) !== 'undefined' && this.params.format !== null) { this.currentDate = moment(this.$element.val(), this.params.format).locale(this.params.lang); } else { this.currentDate = moment(this.$element.val()).locale(this.params.lang); } } else { if (typeof (this.$element.attr('value')) !== 'undefined' && this.$element.attr('value') !== null && this.$element.attr('value') !== "") { if (typeof (this.$element.attr('value')) === 'string') { if (typeof (this.params.format) !== 'undefined' && this.params.format !== null) { this.currentDate = moment(this.$element.attr('value'), this.params.format).locale(this.params.lang); } else { this.currentDate = moment(this.$element.attr('value')).locale(this.params.lang); } } } else { if (typeof (this.params.currentDate) !== 'undefined' && this.params.currentDate !== null) { if (typeof (this.params.currentDate) === 'string') { if (typeof (this.params.format) !== 'undefined' && this.params.format !== null) { this.currentDate = moment(this.params.currentDate, this.params.format).locale(this.params.lang); } else { this.currentDate = moment(this.params.currentDate).locale(this.params.lang); } } else { if (typeof (this.params.currentDate.isValid) === 'undefined' || typeof (this.params.currentDate.isValid) !== 'function') { var x = this.params.currentDate.getTime(); this.currentDate = moment(x, "x").locale(this.params.lang); } else { this.currentDate = this.params.currentDate; } } this.$element.val(this.currentDate.format(this.params.format)); } else this.currentDate = moment(); } } if (typeof (this.params.minDate) !== 'undefined' && this.params.minDate !== null) { if (typeof (this.params.minDate) === 'string') { if (typeof (this.params.format) !== 'undefined' && this.params.format !== null) { this.minDate = moment(this.params.minDate, this.params.format).locale(this.params.lang); } else { this.minDate = moment(this.params.minDate).locale(this.params.lang); } } else { if (typeof (this.params.minDate.isValid) === 'undefined' || typeof (this.params.minDate.isValid) !== 'function') { var x = this.params.minDate.getTime(); this.minDate = moment(x, "x").locale(this.params.lang); } else { this.minDate = this.params.minDate; } } } else if (this.params.minDate === null) { this.minDate = null; } if (typeof (this.params.maxDate) !== 'undefined' && this.params.maxDate !== null) { if (typeof (this.params.maxDate) === 'string') { if (typeof (this.params.format) !== 'undefined' && this.params.format !== null) { this.maxDate = moment(this.params.maxDate, this.params.format).locale(this.params.lang); } else { this.maxDate = moment(this.params.maxDate).locale(this.params.lang); } } else { if (typeof (this.params.maxDate.isValid) === 'undefined' || typeof (this.params.maxDate.isValid) !== 'function') { var x = this.params.maxDate.getTime(); this.maxDate = moment(x, "x").locale(this.params.lang); } else { this.maxDate = this.params.maxDate; } } } else if (this.params.maxDate === null) { this.maxDate = null; } if (!this.isAfterMinDate(this.currentDate)) { this.currentDate = moment(this.minDate); } if (!this.isBeforeMaxDate(this.currentDate)) { this.currentDate = moment(this.maxDate); } }, initTemplate: function () { this.template = '
'; if ($('body').find("#" + this.name).length <= 0) { $('body').append(this.template); if (this) this.dtpElement = $('body').find("#" + this.name); this.$dtpElement = $(this.dtpElement); } }, initButtons: function () { this._attachEvent(this.$dtpElement.find('.dtp-btn-cancel'), 'click', this._onCancelClick.bind(this)); this._attachEvent(this.$dtpElement.find('.dtp-btn-ok'), 'click', this._onOKClick.bind(this)); this._attachEvent(this.$dtpElement.find('a.dtp-select-month-before'), 'click', this._onMonthBeforeClick.bind(this)); this._attachEvent(this.$dtpElement.find('a.dtp-select-month-after'), 'click', this._onMonthAfterClick.bind(this)); this._attachEvent(this.$dtpElement.find('a.dtp-select-year-before'), 'click', this._onYearBeforeClick.bind(this)); this._attachEvent(this.$dtpElement.find('a.dtp-select-year-after'), 'click', this._onYearAfterClick.bind(this)); if (this.params.clearButton === true) { this._attachEvent(this.$dtpElement.find('.dtp-btn-clear'), 'click', this._onClearClick.bind(this)); this.$dtpElement.find('.dtp-btn-clear').removeClass('hidden'); } if (this.params.nowButton === true) { this._attachEvent(this.$dtpElement.find('.dtp-btn-now'), 'click', this._onNowClick.bind(this)); this.$dtpElement.find('.dtp-btn-now').removeClass('hidden'); } if ((this.params.nowButton === true) && (this.params.clearButton === true)) { this.$dtpElement.find('.dtp-btn-clear, .dtp-btn-now, .dtp-btn-cancel, .dtp-btn-ok').addClass('btn-xs'); } else if ((this.params.nowButton === true) || (this.params.clearButton === true)) { this.$dtpElement.find('.dtp-btn-clear, .dtp-btn-now, .dtp-btn-cancel, .dtp-btn-ok').addClass('btn-sm'); } }, initMeridienButtons: function () { this.$dtpElement.find('a.dtp-meridien-am').off('click').on('click', this._onSelectAM.bind(this)); this.$dtpElement.find('a.dtp-meridien-pm').off('click').on('click', this._onSelectPM.bind(this)); }, initDate: function (d) { this.currentView = 0; this.$dtpElement.find('.dtp-picker-calendar').removeClass('hidden'); this.$dtpElement.find('.dtp-picker-datetime').addClass('hidden'); var _date = ((typeof (this.currentDate) !== 'undefined' && this.currentDate !== null) ? this.currentDate : null); var _calendar = this.generateCalendar(this.currentDate); if (typeof (_calendar.week) !== 'undefined' && typeof (_calendar.days) !== 'undefined') { var _template = this.constructHTMLCalendar(_date, _calendar); this.$dtpElement.find('a.dtp-select-day').off('click'); this.$dtpElement.find('.dtp-picker-calendar').html(_template); this.$dtpElement.find('a.dtp-select-day').on('click', this._onSelectDate.bind(this)); this.toggleButtons(_date); } this._centerBox(); this.showDate(_date); }, initHours: function () { this.currentView = 1; this.showTime(this.currentDate); this.initMeridienButtons(); if (this.currentDate.hour() < 12) { this.$dtpElement.find('a.dtp-meridien-am').click(); } else { this.$dtpElement.find('a.dtp-meridien-pm').click(); } var hFormat = ((this.params.shortTime) ? 'h' : 'H'); this.$dtpElement.find('.dtp-picker-datetime').removeClass('hidden'); this.$dtpElement.find('.dtp-picker-calendar').addClass('hidden'); var svgClockElement = this.createSVGClock(true); for (var i = 0; i < 12; i++) { var x = -(162 * (Math.sin(-Math.PI * 2 * (i / 12)))); var y = -(162 * (Math.cos(-Math.PI * 2 * (i / 12)))); var fill = ((this.currentDate.format(hFormat) == i) ? "#007d72" : 'transparent'); var color = ((this.currentDate.format(hFormat) == i) ? "#fff" : '#000'); var svgHourCircle = this.createSVGElement("circle", {'id': 'h-' + i, 'class': 'dtp-select-hour', 'style': 'cursor:pointer', r: '30', cx: x, cy: y, fill: fill, 'data-hour': i}); var svgHourText = this.createSVGElement("text", {'id': 'th-' + i, 'class': 'dtp-select-hour-text', 'text-anchor': 'middle', 'style': 'cursor:pointer', 'font-weight': 'bold', 'font-size': '20', x: x, y: y + 7, fill: color, 'data-hour': i}); svgHourText.textContent = ((i === 0) ? ((this.params.shortTime) ? 12 : i) : i); if (!this.toggleTime(i, true)) { svgHourCircle.className += " disabled"; svgHourText.className += " disabled"; svgHourText.setAttribute('fill', '#bdbdbd'); } else { svgHourCircle.addEventListener('click', this._onSelectHour.bind(this)); svgHourText.addEventListener('click', this._onSelectHour.bind(this)); } svgClockElement.appendChild(svgHourCircle) svgClockElement.appendChild(svgHourText) } if (!this.params.shortTime) { for (var i = 0; i < 12; i++) { var x = -(110 * (Math.sin(-Math.PI * 2 * (i / 12)))); var y = -(110 * (Math.cos(-Math.PI * 2 * (i / 12)))); var fill = ((this.currentDate.format(hFormat) == (i + 12)) ? "#007d72" : 'transparent'); var color = ((this.currentDate.format(hFormat) == (i + 12)) ? "#fff" : '#000'); var svgHourCircle = this.createSVGElement("circle", {'id': 'h-' + (i + 12), 'class': 'dtp-select-hour', 'style': 'cursor:pointer', r: '30', cx: x, cy: y, fill: fill, 'data-hour': (i + 12)}); var svgHourText = this.createSVGElement("text", {'id': 'th-' + (i + 12), 'class': 'dtp-select-hour-text', 'text-anchor': 'middle', 'style': 'cursor:pointer', 'font-weight': 'bold', 'font-size': '22', x: x, y: y + 7, fill: color, 'data-hour': (i + 12)}); svgHourText.textContent = i + 12; if (!this.toggleTime(i + 12, true)) { svgHourCircle.className += " disabled"; svgHourText.className += " disabled"; svgHourText.setAttribute('fill', '#bdbdbd'); } else { svgHourCircle.addEventListener('click', this._onSelectHour.bind(this)); svgHourText.addEventListener('click', this._onSelectHour.bind(this)); } svgClockElement.appendChild(svgHourCircle) svgClockElement.appendChild(svgHourText) } this.$dtpElement.find('a.dtp-meridien-am').addClass('hidden'); this.$dtpElement.find('a.dtp-meridien-pm').addClass('hidden'); } this._centerBox(); }, initMinutes: function () { this.currentView = 2; this.showTime(this.currentDate); this.initMeridienButtons(); if (this.currentDate.hour() < 12) { this.$dtpElement.find('a.dtp-meridien-am').click(); } else { this.$dtpElement.find('a.dtp-meridien-pm').click(); } this.$dtpElement.find('.dtp-picker-calendar').addClass('hidden'); this.$dtpElement.find('.dtp-picker-datetime').removeClass('hidden'); var svgClockElement = this.createSVGClock(false); for (var i = 0; i < 60; i++) { var s = ((i % 5 === 0) ? 162 : 158); var r = ((i % 5 === 0) ? 30 : 20); var x = -(s * (Math.sin(-Math.PI * 2 * (i / 60)))); var y = -(s * (Math.cos(-Math.PI * 2 * (i / 60)))); var color = ((this.currentDate.format("m") == i) ? "#007d72" : 'transparent'); var svgMinuteCircle = this.createSVGElement("circle", {'id': 'm-' + i, 'class': 'dtp-select-minute', 'style': 'cursor:pointer', r: r, cx: x, cy: y, fill: color, 'data-minute': i}); if (!this.toggleTime(i, false)) { svgMinuteCircle.className += " disabled"; } else { svgMinuteCircle.addEventListener('click', this._onSelectMinute.bind(this)); } svgClockElement.appendChild(svgMinuteCircle) } for (var i = 0; i < 60; i++) { if ((i % 5) === 0) { var x = -(162 * (Math.sin(-Math.PI * 2 * (i / 60)))); var y = -(162 * (Math.cos(-Math.PI * 2 * (i / 60)))); var color = ((this.currentDate.format("m") == i) ? "#fff" : '#000'); var svgMinuteText = this.createSVGElement("text", {'id': 'tm-' + i, 'class': 'dtp-select-minute-text', 'text-anchor': 'middle', 'style': 'cursor:pointer', 'font-weight': 'bold', 'font-size': '20', x: x, y: y + 7, fill: color, 'data-minute': i}); svgMinuteText.textContent = i; if (!this.toggleTime(i, false)) { svgMinuteText.className += " disabled"; svgMinuteText.setAttribute('fill', '#bdbdbd'); } else { svgMinuteText.addEventListener('click', this._onSelectMinute.bind(this)); } svgClockElement.appendChild(svgMinuteText) } } this._centerBox(); }, animateHands: function () { var H = this.currentDate.hour(); var M = this.currentDate.minute(); var hh = this.$dtpElement.find('.hour-hand'); hh[0].setAttribute('transform', "rotate(" + 360 * H / 12 + ")"); var mh = this.$dtpElement.find('.minute-hand'); mh[0].setAttribute('transform', "rotate(" + 360 * M / 60 + ")"); }, createSVGClock: function (isHour) { var hl = ((this.params.shortTime) ? -120 : -90); var svgElement = this.createSVGElement("svg", {class: 'svg-clock', viewBox: '0,0,400,400'}); var svgGElement = this.createSVGElement("g", {transform: 'translate(200,200) '}); var svgClockFace = this.createSVGElement("circle", {r: '192', fill: '#eee', stroke: '#bdbdbd', 'stroke-width': 2}); var svgClockCenter = this.createSVGElement("circle", {r: '15', fill: '#757575'}); svgGElement.appendChild(svgClockFace) if (isHour) { var svgMinuteHand = this.createSVGElement("line", {class: 'minute-hand', x1: 0, y1: 0, x2: 0, y2: -150, stroke: '#bdbdbd', 'stroke-width': 2}); var svgHourHand = this.createSVGElement("line", {class: 'hour-hand', x1: 0, y1: 0, x2: 0, y2: hl, stroke: '#007d72', 'stroke-width': 8}); svgGElement.appendChild(svgMinuteHand); svgGElement.appendChild(svgHourHand); } else { var svgMinuteHand = this.createSVGElement("line", {class: 'minute-hand', x1: 0, y1: 0, x2: 0, y2: -150, stroke: '#007d72', 'stroke-width': 2}); var svgHourHand = this.createSVGElement("line", {class: 'hour-hand', x1: 0, y1: 0, x2: 0, y2: hl, stroke: '#bdbdbd', 'stroke-width': 8}); svgGElement.appendChild(svgHourHand); svgGElement.appendChild(svgMinuteHand); } svgGElement.appendChild(svgClockCenter) svgElement.appendChild(svgGElement) this.$dtpElement.find("#dtp-svg-clock").empty(); this.$dtpElement.find("#dtp-svg-clock")[0].appendChild(svgElement); this.animateHands(); return svgGElement; }, createSVGElement: function (tag, attrs) { var el = document.createElementNS('http://www.w3.org/2000/svg', tag); for (var k in attrs) { el.setAttribute(k, attrs[k]); } return el; }, isAfterMinDate: function (date, checkHour, checkMinute) { var _return = true; if (typeof (this.minDate) !== 'undefined' && this.minDate !== null) { var _minDate = moment(this.minDate); var _date = moment(date); if (!checkHour && !checkMinute) { _minDate.hour(0); _minDate.minute(0); _date.hour(0); _date.minute(0); } _minDate.second(0); _date.second(0); _minDate.millisecond(0); _date.millisecond(0); if (!checkMinute) { _date.minute(0); _minDate.minute(0); _return = (parseInt(_date.format("X")) >= parseInt(_minDate.format("X"))); } else { _return = (parseInt(_date.format("X")) >= parseInt(_minDate.format("X"))); } } return _return; }, isBeforeMaxDate: function (date, checkTime, checkMinute) { var _return = true; if (typeof (this.maxDate) !== 'undefined' && this.maxDate !== null) { var _maxDate = moment(this.maxDate); var _date = moment(date); if (!checkTime && !checkMinute) { _maxDate.hour(0); _maxDate.minute(0); _date.hour(0); _date.minute(0); } _maxDate.second(0); _date.second(0); _maxDate.millisecond(0); _date.millisecond(0); if (!checkMinute) { _date.minute(0); _maxDate.minute(0); _return = (parseInt(_date.format("X")) <= parseInt(_maxDate.format("X"))); } else { _return = (parseInt(_date.format("X")) <= parseInt(_maxDate.format("X"))); } } return _return; }, rotateElement: function (el, deg) { $(el).css ({ WebkitTransform: 'rotate(' + deg + 'deg)', '-moz-transform': 'rotate(' + deg + 'deg)' }); }, showDate: function (date) { if (date) { this.$dtpElement.find('.dtp-actual-day').html(date.locale(this.params.lang).format('dddd')); this.$dtpElement.find('.dtp-actual-month').html(date.locale(this.params.lang).format('MMM').toUpperCase()); this.$dtpElement.find('.dtp-actual-num').html(date.locale(this.params.lang).format('DD')); this.$dtpElement.find('.dtp-actual-year').html(date.locale(this.params.lang).format('YYYY')); } }, showTime: function (date) { if (date) { var minutes = date.minute(); var content = ((this.params.shortTime) ? date.format('hh') : date.format('HH')) + ':' + ((minutes.toString().length == 2) ? minutes : '0' + minutes) + ((this.params.shortTime) ? ' ' + date.format('A') : ''); if (this.params.date) this.$dtpElement.find('.dtp-actual-time').html(content); else { if (this.params.shortTime) this.$dtpElement.find('.dtp-actual-day').html(date.format('A')); else this.$dtpElement.find('.dtp-actual-day').html(' '); this.$dtpElement.find('.dtp-actual-maxtime').html(content); } } }, selectDate: function (date) { if (date) { this.currentDate.date(date); this.showDate(this.currentDate); this.$element.trigger('dateSelected', this.currentDate); } }, generateCalendar: function (date) { var _calendar = {}; if (date !== null) { var startOfMonth = moment(date).locale(this.params.lang).startOf('month'); var endOfMonth = moment(date).locale(this.params.lang).endOf('month'); var iNumDay = startOfMonth.format('d'); _calendar.week = this.days; _calendar.days = []; for (var i = startOfMonth.date(); i <= endOfMonth.date(); i++) { if (i === startOfMonth.date()) { var iWeek = _calendar.week.indexOf(iNumDay.toString()); if (iWeek > 0) { for (var x = 0; x < iWeek; x++) { _calendar.days.push(0); } } } _calendar.days.push(moment(startOfMonth).locale(this.params.lang).date(i)); } } return _calendar; }, constructHTMLCalendar: function (date, calendar) { var _template = ""; _template += '' + moment(parseInt(calendar.week[i]), "d").locale(this.params.lang).format("dd").substring(0, 1) + ' | '; } _template += ''; _template += '
---|
'; if (calendar.days[i] != 0) { if (this.isBeforeMaxDate(moment(calendar.days[i]), false, false) === false || this.isAfterMinDate(moment(calendar.days[i]), false, false) === false) { _template += '' + moment(calendar.days[i]).locale(this.params.lang).format("DD") + ''; } else { if (moment(calendar.days[i]).locale(this.params.lang).format("DD") === moment(this.currentDate).locale(this.params.lang).format("DD")) { _template += '' + moment(calendar.days[i]).locale(this.params.lang).format("DD") + ''; } else { _template += '' + moment(calendar.days[i]).locale(this.params.lang).format("DD") + ''; } } _template += ' | '; } } _template += '