calendar/app/assets/javascripts/bootstrap-datetimepicker.js

1285 lines
42 KiB
JavaScript

/**
* @license
* =========================================================
* bootstrap-datetimepicker.js
* http://www.eyecon.ro/bootstrap-datepicker
* =========================================================
* Copyright 2012 Stefan Petre
*
* Contributions:
* - Andrew Rowls
* - Thiago de Arruda
*
* 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.
* =========================================================
*/
(function($) {
// Picker object
var smartPhone = (window.orientation != undefined);
var DateTimePicker = function(element, options) {
this.id = dpgId++;
this.init(element, options);
};
DateTimePicker.prototype = {
constructor: DateTimePicker,
init: function(element, options) {
var icon;
if (!(options.pickTime || options.pickDate))
throw new Error('Must choose at least one picker');
this.options = options;
this.$element = $(element);
this.language = options.language in dates ? options.language : 'en'
this.pickDate = options.pickDate;
this.pickTime = options.pickTime;
this.isInput = this.$element.is('input');
// this.component = this.$element.is('.input-prepend') ? this.$element.find('.iconbtn') : false;
this.component = this.$element.is('.input-append') ? this.$element.find('.iconbtn') : false;
this.clearDate = this.$element.is('.input-append') ? this.$element.find('.clearDate') : false;
this.format = options.format;
if (!this.format) {
if (this.isInput) this.format = this.$element.data('format');
else this.format = this.$element.find('input').data('format');
if (!this.format) this.format = 'MM/dd/yyyy';
}
this._compileFormat();
if (this.component) {
icon = this.component.find('i');
}
if (this.pickTime) {
if (icon && icon.length) this.timeIcon = icon.data('time-icon');
if (!this.timeIcon) this.timeIcon = 'icon-time';
icon.addClass(this.timeIcon);
}
if (this.pickDate) {
if (icon && icon.length) this.dateIcon = icon.data('date-icon');
if (!this.dateIcon) this.dateIcon = 'icon-calendar';
icon.removeClass(this.timeIcon);
icon.addClass(this.dateIcon);
}
this.widget = $(getTemplate(this.format, this.timeIcon, options.pickDate, options.pickTime, options.pick12HourFormat)).appendTo('body');
this.minViewMode = options.minViewMode||this.$element.data('date-minviewmode')||0;
if (typeof this.minViewMode === 'string') {
switch (this.minViewMode) {
case 'months':
this.minViewMode = 1;
break;
case 'years':
this.minViewMode = 2;
break;
default:
this.minViewMode = 0;
break;
}
}
this.viewMode = options.viewMode||this.$element.data('date-viewmode')||0;
if (typeof this.viewMode === 'string') {
switch (this.viewMode) {
case 'months':
this.viewMode = 1;
break;
case 'years':
this.viewMode = 2;
break;
default:
this.viewMode = 0;
break;
}
}
this.startViewMode = this.viewMode;
this.weekStart = options.weekStart||this.$element.data('date-weekstart')||0;
this.weekEnd = this.weekStart === 0 ? 6 : this.weekStart - 1;
this.fillDow();
this.fillMonths();
this.fillHours();
this.fillMinutes();
this.fillSeconds();
this.update();
this.showMode();
this._attachDatePickerEvents();
},
show: function(e) {
this.widget.show();
this.height = this.component ? this.component.outerHeight() : this.$element.outerHeight();
this.width = this.component ? this.component.outerWidth() : this.$element.outerWidth();
this.place(this.options.place);
this.$element.trigger({
type: 'show',
date: this._date
});
this._attachDatePickerGlobalEvents();
if (e) {
e.stopPropagation();
e.preventDefault();
}
},
hide: function() {
// Ignore event if in the middle of a picker transition
var collapse = this.widget.find('.collapse')
for (var i = 0; i < collapse.length; i++) {
var collapseData = collapse.eq(i).data('collapse');
if (collapseData && collapseData.transitioning)
return;
}
this.widget.hide();
this.viewMode = this.startViewMode;
this.showMode();
// this.set();
this.$element.trigger({
type: 'hide',
date: this._date
});
this.actions.showPicker.call(this);
this._detachDatePickerGlobalEvents();
},
set: function() {
var formatted = '';
if (!this._unset) formatted = this.formatDate(this._date);
if (!this.isInput) {
if (this.component){
var input = this.$element.find('input');
input.val(formatted);
this._resetMaskPos(input);
}
this.$element.data('date', formatted);
} else {
this.$element.val(formatted);
this._resetMaskPos(this.$element);
}
},
setValue: function(newDate) {
if (!newDate) {
this._unset = true;
} else {
this._unset = false;
}
if (typeof newDate === 'string') {
this._date = this.parseDate(newDate);
} else {
this._date = new Date(newDate);
}
this.set();
this.viewDate = UTCDate(this._date.getUTCFullYear(), this._date.getUTCMonth(), 1, 0, 0, 0, 0);
this.fillDate();
this.fillTime();
},
getDate: function() {
if (this._unset) return null;
return new Date(this._date.valueOf());
},
setDate: function(date) {
if (!date) this.setValue(null);
else this.setValue(date.valueOf());
},
getLocalDate: function() {
if (this._unset) return null;
var d = this._date;
return new Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(),
d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), d.getUTCMilliseconds());
},
setLocalDate: function(localDate) {
if (!localDate) this.setValue(null);
else
this.setValue(Date.UTC(
localDate.getFullYear(),
localDate.getMonth(),
localDate.getDate(),
localDate.getHours(),
localDate.getMinutes(),
localDate.getSeconds(),
localDate.getMilliseconds()));
},
place: function(pos){
var offset = this.component ? this.component.offset() : this.$element.offset(),
input = this.$element.find('input'),
widget_height = this.widget.height();
if(pos === "bottom"){
this.widget.css({
top: offset.top + this.height,
left: offset.left - input.outerWidth() - this.width,
});
}else if(pos === "top"){
this.widget.css({
top: offset.top - 13 - widget_height,
left: offset.left - input.outerWidth() - this.width,
});
}
},
notifyChange: function(){
this.$element.trigger({
type: 'changeDate',
date: this.getDate(),
localDate: this.getLocalDate()
});
},
update: function(newDate){
var dateStr = newDate;
if (!dateStr) {
if (this.isInput) {
dateStr = this.$element.val();
} else {
dateStr = this.$element.find('input').val();
}
if (!dateStr) {
var tmp = new Date()
this._date = UTCDate(tmp.getFullYear(),
tmp.getMonth(),
tmp.getDate(),
tmp.getHours(),
tmp.getMinutes(),
tmp.getSeconds(),
tmp.getMilliseconds())
} else {
this._date = this.parseDate(dateStr);
}
}
this.viewDate = UTCDate(this._date.getUTCFullYear(), this._date.getUTCMonth(), 1, 0, 0, 0, 0);
this.fillDate();
this.fillTime();
},
fillDow: function() {
var dowCnt = this.weekStart;
var html = '<tr>';
while (dowCnt < this.weekStart + 7) {
html += '<th class="dow">' + dates[this.language].daysMin[(dowCnt++) % 7] + '</th>';
}
html += '</tr>';
this.widget.find('.datepicker-days thead').append(html);
},
fillMonths: function() {
var html = '';
var i = 0
while (i < 12) {
html += '<span class="month">' + dates[this.language].monthsShort[i++] + '</span>';
}
this.widget.find('.datepicker-months td').append(html);
},
fillDate: function() {
var year = this.viewDate.getUTCFullYear();
var month = this.viewDate.getUTCMonth();
var currentDate = UTCDate(
this._date.getUTCFullYear(),
this._date.getUTCMonth(),
this._date.getUTCDate(),
0, 0, 0, 0
);
this.widget.find('.datepicker-days th:eq(1)').text(
dates[this.language].months[month] + ' ' + year);
var prevMonth = UTCDate(year, month-1, 28, 0, 0, 0, 0);
var day = DPGlobal.getDaysInMonth(
prevMonth.getUTCFullYear(), prevMonth.getUTCMonth());
prevMonth.setUTCDate(day);
prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.weekStart + 7) % 7);
var nextMonth = new Date(prevMonth.valueOf());
nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
nextMonth = nextMonth.valueOf();
var html = [];
var clsName;
while (prevMonth.valueOf() < nextMonth) {
if (prevMonth.getUTCDay() === this.weekStart) {
html.push('<tr>');
}
clsName = '';
if (prevMonth.getUTCFullYear() < year ||
(prevMonth.getUTCFullYear() == year &&
prevMonth.getUTCMonth() < month)) {
clsName += ' old';
} else if (prevMonth.getUTCFullYear() > year ||
(prevMonth.getUTCFullYear() == year &&
prevMonth.getUTCMonth() > month)) {
clsName += ' new';
}
if (prevMonth.valueOf() === currentDate.valueOf()) {
clsName += ' active';
}
html.push('<td class="day' + clsName + '">' + prevMonth.getUTCDate() + '</td>');
if (prevMonth.getUTCDay() === this.weekEnd) {
html.push('</tr>');
}
prevMonth.setUTCDate(prevMonth.getUTCDate() + 1);
}
this.widget.find('.datepicker-days tbody').empty().append(html.join(''));
var currentYear = this._date.getUTCFullYear();
var months = this.widget.find('.datepicker-months').find(
'th:eq(1)').text(year).end().find('span').removeClass('active');
if (currentYear === year) {
months.eq(this._date.getUTCMonth()).addClass('active');
}
html = '';
year = parseInt(year/10, 10) * 10;
var yearCont = this.widget.find('.datepicker-years').find(
'th:eq(1)').text(year + '-' + (year + 9)).end().find('td');
year -= 1;
for (var i = -1; i < 11; i++) {
html += '<span class="year' + (i === -1 || i === 10 ? ' old' : '') + (currentYear === year ? ' active' : '') + '">' + year + '</span>';
year += 1;
}
yearCont.html(html);
},
fillHours: function() {
var table = this.widget.find(
'.timepicker .timepicker-hours table');
table.parent().hide();
var html = '';
if (this.options.pick12HourFormat) {
var current = 1;
for (var i = 0; i < 3; i += 1) {
html += '<tr>';
for (var j = 0; j < 4; j += 1) {
var c = current.toString();
html += '<td class="hour">' + padLeft(c, 2, '0') + '</td>';
current++;
}
html += '</tr>'
}
} else {
var current = 0;
for (var i = 0; i < 6; i += 1) {
html += '<tr>';
for (var j = 0; j < 4; j += 1) {
var c = current.toString();
html += '<td class="hour">' + padLeft(c, 2, '0') + '</td>';
current++;
}
html += '</tr>'
}
}
table.html(html);
},
fillMinutes: function() {
var table = this.widget.find(
'.timepicker .timepicker-minutes table');
table.parent().hide();
var html = '';
var current = 0;
for (var i = 0; i < 3; i++) {
html += '<tr>';
for (var j = 0; j < 4; j += 1) {
var c = current.toString();
html += '<td class="minute">' + padLeft(c, 2, '0') + '</td>';
current += 5;
}
html += '</tr>';
}
table.html(html);
},
fillSeconds: function() {
var table = this.widget.find(
'.timepicker .timepicker-seconds table');
table.parent().hide();
var html = '';
var current = 0;
for (var i = 0; i < 5; i++) {
html += '<tr>';
for (var j = 0; j < 4; j += 1) {
var c = current.toString();
html += '<td class="second">' + padLeft(c, 2, '0') + '</td>';
current += 3;
}
html += '</tr>';
}
table.html(html);
},
fillTime: function() {
if (!this._date)
return;
var timeComponents = this.widget.find('.timepicker span[data-time-component]');
var table = timeComponents.closest('table');
var is12HourFormat = this.options.pick12HourFormat;
var hour = this._date.getUTCHours();
var period = 'AM';
if (is12HourFormat) {
if (hour >= 12) period = 'PM';
if (hour === 0) hour = 12;
else if (hour != 12) hour = hour % 12;
this.widget.find(
'.timepicker [data-action=togglePeriod]').text(period);
}
hour = padLeft(hour.toString(), 2, '0');
var minute = padLeft(this._date.getUTCMinutes().toString(), 2, '0');
var second = padLeft(this._date.getUTCSeconds().toString(), 2, '0');
timeComponents.filter('[data-time-component=hours]').text(hour);
timeComponents.filter('[data-time-component=minutes]').text(minute);
timeComponents.filter('[data-time-component=seconds]').text(second);
},
click: function(e) {
e.stopPropagation();
e.preventDefault();
var target = $(e.target).closest('span, td, th');
if (target.length === 1) {
switch(target[0].nodeName.toLowerCase()) {
case 'th':
switch(target[0].className) {
case 'switch':
this.showMode(1);
break;
case 'prev':
case 'next':
var vd = this.viewDate;
var navFnc;
var step;
if(this.format == 'yyyy') {
navFnc = YGlobal.modes[this.viewMode].navFnc
step = YGlobal.modes[this.viewMode].navStep
} else if(this.format == 'yyyy/MM') {
navFnc = YMGlobal.modes[this.viewMode].navFnc
step = YMGlobal.modes[this.viewMode].navStep
} else {
navFnc = DPGlobal.modes[this.viewMode].navFnc
step = DPGlobal.modes[this.viewMode].navStep
};
if (target[0].className === 'prev') step = step * -1;
vd['set' + navFnc](vd['get' + navFnc]() + step);
this.fillDate();
this.set();
break;
}
break;
case 'span':
if (target.is('.month')) {
var month = target.parent().find('span').index(target);
this.viewDate.setUTCMonth(month);
} else {
var year = parseInt(target.text(), 10) || 0;
this.viewDate.setUTCFullYear(year);
}
// if (this.viewMode !== 0) {
this._date = UTCDate(
this.viewDate.getUTCFullYear(),
this.viewDate.getUTCMonth(),
this.viewDate.getUTCDate(),
this._date.getUTCHours(),
this._date.getUTCMinutes(),
this._date.getUTCSeconds(),
this._date.getUTCMilliseconds()
);
this.notifyChange();
// }
this.showMode(-1);
this.fillDate();
this.set();
break;
case 'td':
if (target.is('.day')) {
var day = parseInt(target.text(), 10) || 1;
var month = this.viewDate.getUTCMonth();
var year = this.viewDate.getUTCFullYear();
if (target.is('.old')) {
if (month === 0) {
month = 11;
year -= 1;
} else {
month -= 1;
}
} else if (target.is('.new')) {
if (month == 11) {
month = 0;
year += 1;
} else {
month += 1;
}
}
this._date = UTCDate(
year, month, day,
this._date.getUTCHours(),
this._date.getUTCMinutes(),
this._date.getUTCSeconds(),
this._date.getUTCMilliseconds()
);
this.viewDate = UTCDate(
year, month, Math.min(28, day) , 0, 0, 0, 0);
this.fillDate();
this.set();
this.notifyChange();
// this.widget.hide();
}
break;
}
}
},
actions: {
incrementHours: function(e) {
this._date.setUTCHours(this._date.getUTCHours() + 1);
},
incrementMinutes: function(e) {
this._date.setUTCMinutes(this._date.getUTCMinutes() + 1);
},
// incrementSeconds: function(e) {
// this._date.setUTCSeconds(this._date.getUTCSeconds() + 1);
// },
decrementHours: function(e) {
this._date.setUTCHours(this._date.getUTCHours() - 1);
},
decrementMinutes: function(e) {
this._date.setUTCMinutes(this._date.getUTCMinutes() - 1);
},
// decrementSeconds: function(e) {
// this._date.setUTCSeconds(this._date.getUTCSeconds() - 1);
// },
togglePeriod: function(e) {
var hour = this._date.getUTCHours();
if (hour >= 12) hour -= 12;
else hour += 12;
this._date.setUTCHours(hour);
},
showPicker: function() {
this.widget.find('.timepicker > div:not(.timepicker-picker)').hide();
this.widget.find('.timepicker .timepicker-picker').show();
},
showHours: function() {
this.widget.find('.timepicker .timepicker-picker').hide();
this.widget.find('.timepicker .timepicker-hours').show();
},
showMinutes: function() {
this.widget.find('.timepicker .timepicker-picker').hide();
this.widget.find('.timepicker .timepicker-minutes').show();
},
// showSeconds: function() {
// this.widget.find('.timepicker .timepicker-picker').hide();
// this.widget.find('.timepicker .timepicker-seconds').show();
// },
selectHour: function(e) {
var tgt = $(e.target);
var value = parseInt(tgt.text(), 10);
if (this.options.pick12HourFormat) {
var current = this._date.getUTCHours();
if (current >= 12) {
if (value != 12) value = (value + 12) % 24;
} else {
if (value === 12) value = 0;
else value = value % 12;
}
}
this._date.setUTCHours(value);
this.actions.showPicker.call(this);
},
selectMinute: function(e) {
var tgt = $(e.target);
var value = parseInt(tgt.text(), 10);
this._date.setUTCMinutes(value);
this.actions.showPicker.call(this);
},
// selectSecond: function(e) {
// var tgt = $(e.target);
// var value = parseInt(tgt.text(), 10);
// this._date.setUTCSeconds(value);
// this.actions.showPicker.call(this);
// }
},
doAction: function(e) {
e.stopPropagation();
e.preventDefault();
if (!this._date) this._date = UTCDate(1970, 0, 0, 0, 0, 0, 0);
var action = $(e.currentTarget).data('action');
var rv = this.actions[action].apply(this, arguments);
this.set();
this.fillTime();
this.notifyChange();
return rv;
},
stopEvent: function(e) {
e.stopPropagation();
e.preventDefault();
},
// part of the following code was taken from
// http://cloud.github.com/downloads/digitalBush/jquery.maskedinput/jquery.maskedinput-1.3.js
keydown: function(e) {
var self = this, k = e.which, input = $(e.target);
if (k == 8 || k == 46) {
// backspace and delete cause the maskPosition
// to be recalculated
setTimeout(function() {
self._resetMaskPos(input);
});
}
},
keypress: function(e) {
var k = e.which;
if (k == 8 || k == 46) {
// For those browsers which will trigger
// keypress on backspace/delete
return;
}
var input = $(e.target);
var c = String.fromCharCode(k);
var val = input.val() || '';
val += c;
var mask = this._mask[this._maskPos];
if (!mask) {
return false;
}
if (mask.end != val.length) {
return;
}
if (!mask.pattern.test(val.slice(mask.start))) {
val = val.slice(0, val.length - 1);
while ((mask = this._mask[this._maskPos]) && mask.character) {
val += mask.character;
// advance mask position past static
// part
this._maskPos++;
}
val += c;
if (mask.end != val.length) {
input.val(val);
return false;
} else {
if (!mask.pattern.test(val.slice(mask.start))) {
input.val(val.slice(0, mask.start));
return false;
} else {
input.val(val);
this._maskPos++;
return false;
}
}
} else {
this._maskPos++;
}
},
change: function(e) {
var input = $(e.target);
var val = input.val();
if (this._formatPattern.test(val)) {
this.update();
this.setValue(this._date.getTime());
this.notifyChange();
this.set();
} else if (val && val.trim()) {
this.setValue(this._date.getTime());
if (this._date) this.set();
else input.val('');
} else {
if (this._date) {
this.setValue(null);
// unset the date when the input is
// erased
this.notifyChange();
}
}
this._resetMaskPos(input);
},
clear: function(e) {
if (this.isInput) this.$element.val(null);
else this.$element.find('input').val(null);
},
showMode: function(dir) {
if (dir) {
if(this.format == 'yyyy') {
this.viewMode = Math.max(this.minViewMode, Math.min(0, this.viewMode + dir));
} else if(this.format == 'yyyy/MM') {
this.viewMode = Math.max(this.minViewMode, Math.min(1, this.viewMode + dir));
} else {
this.viewMode = Math.max(this.minViewMode, Math.min(2, this.viewMode + dir));
}
}
var clsName = null;
if(this.format == 'yyyy') {
clsName = '.datepicker-'+YGlobal.modes[this.viewMode].clsName
} else if(this.format == 'yyyy/MM') {
clsName = '.datepicker-'+YMGlobal.modes[this.viewMode].clsName
} else {
clsName = '.datepicker-'+DPGlobal.modes[this.viewMode].clsName
};
this.widget.find('.datepicker > div').hide().filter(clsName).show();
},
destroy: function() {
this._detachDatePickerEvents();
this._detachDatePickerGlobalEvents();
this.widget.remove();
this.$element.removeData('datetimepicker');
this.component.removeData('datetimepicker');
},
formatDate: function(d) {
return this.format.replace(formatReplacer, function(match) {
var methodName, property, rv, len = match.length;
if (match === 'ms')
len = 1;
property = dateFormatComponents[match].property
if (property === 'Hours12') {
rv = d.getUTCHours();
if (rv === 0) rv = 12;
else if (rv !== 12) rv = rv % 12;
} else if (property === 'Period12') {
if (d.getUTCHours() >= 12) return 'PM';
else return 'AM';
} else {
methodName = 'get' + property;
rv = d[methodName]();
}
if (methodName === 'getUTCMonth') rv = rv + 1;
if (methodName === 'getUTCYear') rv = rv + 1900 - 2000;
return padLeft(rv.toString(), len, '0');
});
},
parseDate: function(str) {
var match, i, property, methodName, value, parsed = {};
if (!(match = this._formatPattern.exec(str)))
return null;
for (i = 1; i < match.length; i++) {
property = this._propertiesByIndex[i];
if (!property)
continue;
value = match[i];
if (/^\d+$/.test(value))
value = parseInt(value, 10);
parsed[property] = value;
}
return this._finishParsingDate(parsed);
},
_resetMaskPos: function(input) {
var val = input.val();
for (var i = 0; i < this._mask.length; i++) {
if (this._mask[i].end > val.length) {
// If the mask has ended then jump to
// the next
this._maskPos = i;
break;
} else if (this._mask[i].end === val.length) {
this._maskPos = i + 1;
break;
}
}
},
_finishParsingDate: function(parsed) {
var year, month, date, hours, minutes, seconds, milliseconds;
year = parsed.UTCFullYear;
if (parsed.UTCYear) year = 2000 + parsed.UTCYear;
if (!year) year = 1970;
if (parsed.UTCMonth) month = parsed.UTCMonth - 1;
else month = 0;
date = parsed.UTCDate || 1;
hours = parsed.UTCHours || 0;
minutes = parsed.UTCMinutes || 0;
seconds = parsed.UTCSeconds || 0;
milliseconds = parsed.UTCMilliseconds || 0;
if (parsed.Hours12) {
hours = parsed.Hours12;
}
if (parsed.Period12) {
if (/pm/i.test(parsed.Period12)) {
if (hours != 12) hours = (hours + 12) % 24;
} else {
hours = hours % 12;
}
}
return UTCDate(year, month, date, hours, minutes, seconds, milliseconds);
},
_compileFormat: function () {
var match, component, components = [], mask = [],
str = this.format, propertiesByIndex = {}, i = 0, pos = 0;
while (match = formatComponent.exec(str)) {
component = match[0];
if (component in dateFormatComponents) {
i++;
propertiesByIndex[i] = dateFormatComponents[component].property;
components.push('\\s*' + dateFormatComponents[component].getPattern(
this) + '\\s*');
mask.push({
pattern: new RegExp(dateFormatComponents[component].getPattern(
this)),
property: dateFormatComponents[component].property,
start: pos,
end: pos += component.length
});
}
else {
components.push(escapeRegExp(component));
mask.push({
pattern: new RegExp(escapeRegExp(component)),
character: component,
start: pos,
end: ++pos
});
}
str = str.slice(component.length);
}
this._mask = mask;
this._maskPos = 0;
this._formatPattern = new RegExp(
'^\\s*' + components.join('') + '\\s*$');
this._propertiesByIndex = propertiesByIndex;
},
_attachDatePickerEvents: function() {
var self = this;
// this handles date picker clicks
this.widget.on('click', '.datepicker *', $.proxy(this.click, this));
// this handles time picker clicks
this.widget.on('click', '[data-action]', $.proxy(this.doAction, this));
this.widget.on('mousedown', $.proxy(this.stopEvent, this));
this.clearDate.on('click', $.proxy(this.clear, this));
if (this.pickDate && this.pickTime) {
this.widget.on('click.togglePicker', '.accordion-toggle', function(e) {
e.stopPropagation();
var $this = $(this);
var $parent = $this.closest('ul');
var expanded = $parent.find('.collapse.in');
var closed = $parent.find('.collapse:not(.in)');
if (expanded && expanded.length) {
var collapseData = expanded.data('collapse');
if (collapseData && collapseData.transitioning) return;
expanded.collapse('hide');
closed.collapse('show')
$this.find('i').toggleClass(self.timeIcon + ' ' + self.dateIcon);
self.$element.find('.iconbtn i').toggleClass(self.timeIcon + ' ' + self.dateIcon);
}
});
}
if (this.isInput) {
this.$element.on({
'focus': $.proxy(this.show, this),
'blur': $.proxy(this.hide, this),
'change': $.proxy(this.change, this),
});
if (this.options.maskInput) {
this.$element.on({
'keydown': $.proxy(this.keydown, this),
'keypress': $.proxy(this.keypress, this)
});
}
} else {
this.$element.on({
'focus': $.proxy(this.show, this),
'blur': $.proxy(this.hide, this),
'change': $.proxy(this.change, this),
}, 'input');
if (this.options.maskInput) {
this.$element.on({
'keydown': $.proxy(this.keydown, this),
'keypress': $.proxy(this.keypress, this)
}, 'input');
}
if (this.component){
this.component.on('click', $.proxy(this.show, this));
} else {
this.$element.on('click', $.proxy(this.show, this));
}
}
},
_attachDatePickerGlobalEvents: function() {
$(window).on(
'resize.datetimepicker' + this.id, $.proxy(this.place, this));
if (!this.isInput) {
$(document).on(
'mousedown.datetimepicker' + this.id, $.proxy(this.hide, this));
}
},
_detachDatePickerEvents: function() {
this.widget.off('click', '.datepicker *', this.click);
this.widget.off('click', '[data-action]');
this.widget.off('mousedown', this.stopEvent);
if (this.pickDate && this.pickTime) {
this.widget.off('click.togglePicker');
}
if (this.isInput) {
this.$element.off({
'focus': this.show,
'change': this.change,
});
if (this.options.maskInput) {
this.$element.off({
'keydown': this.keydown,
'keypress': this.keypress
});
}
} else {
this.$element.off({
'change': this.change,
}, 'input');
if (this.options.maskInput) {
this.$element.off({
'keydown': this.keydown,
'keypress': this.keypress
}, 'input');
}
if (this.component){
this.component.off('click', this.show);
} else {
this.$element.off('click', this.show);
}
}
},
_detachDatePickerGlobalEvents: function () {
$(window).off('resize.datetimepicker' + this.id);
if (!this.isInput) {
$(document).off('mousedown.datetimepicker' + this.id);
}
}
};
$.fn.datetimepicker = function ( option, val ) {
return this.each(function () {
var $this = $(this),
data = $this.data('datetimepicker'),
options = typeof option === 'object' && option;
if (!data) {
$this.data('datetimepicker', (data = new DateTimePicker(
this, $.extend({}, $.fn.datetimepicker.defaults,options))));
}
if (typeof option === 'string') data[option](val);
});
};
$.fn.datetimepicker.defaults = {
maskInput: true,
pickDate: true,
pickTime: true,
pick12HourFormat: false,
place: "bottom"
};
$.fn.datetimepicker.Constructor = DateTimePicker;
var dpgId = 0;
var dates = $.fn.datetimepicker.dates = {
en: {
days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday", "Sunday"],
daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
months: ["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"],
monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
"Aug", "Sep", "Oct", "Nov", "Dec"]
}
};
var dateFormatComponents = {
dd: {property: 'UTCDate', getPattern: function() { return '(0?[1-9]|[1-2][0-9]|3[0-1])\\b';}},
MM: {property: 'UTCMonth', getPattern: function() {return '(0?[1-9]|1[0-2])\\b';}},
yy: {property: 'UTCYear', getPattern: function() {return '(\\d{2})\\b'}},
yyyy: {property: 'UTCFullYear', getPattern: function() {return '(\\d{4})\\b';}},
hh: {property: 'UTCHours', getPattern: function() {return '(0?[0-9]|1[0-9]|2[0-3])\\b';}},
mm: {property: 'UTCMinutes', getPattern: function() {return '(0?[0-9]|[1-5][0-9])\\b';}},
ss: {property: 'UTCSeconds', getPattern: function() {return '(0?[0-9]|[1-5][0-9])\\b';}},
ms: {property: 'UTCMilliseconds', getPattern: function() {return '([0-9]{1,3})\\b';}},
HH: {property: 'Hours12', getPattern: function() {return '(0?[1-9]|1[0-2])\\b';}},
PP: {property: 'Period12', getPattern: function() {return '(AM|PM|am|pm|Am|aM|Pm|pM)\\b';}}
};
var keys = [];
for (var k in dateFormatComponents) keys.push(k);
keys[keys.length - 1] += '\\b';
keys.push('.');
var formatComponent = new RegExp(keys.join('\\b|'));
keys.pop();
var formatReplacer = new RegExp(keys.join('\\b|'), 'g');
function escapeRegExp(str) {
// http://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
}
function padLeft(s, l, c) {
if (l < s.length) return s;
else return Array(l - s.length + 1).join(c || ' ') + s;
}
function getTemplate(format, timeIcon, pickDate, pickTime, is12Hours) {
if (pickDate && pickTime) {
return (
'<div class="bootstrap-datetimepicker-widget dropdown-menu">' +
'<ul>' +
'<li class="collapse in">' +
'<div class="datepicker">' +
DPGlobal.template +
'</div>' +
'</li>' +
'<li class="picker-switch"><a class="accordion-toggle"><i class="' + timeIcon + '"></i></a></li>' +
'<li class="collapse">' +
'<div class="timepicker">' +
TPGlobal.getTemplate(is12Hours) +
'</div>' +
'</li>' +
'</ul>' +
'</div>'
);
} else if (pickTime) {
return (
'<div class="bootstrap-datetimepicker-widget dropdown-menu">' +
'<div class="timepicker">' +
TPGlobal.getTemplate(is12Hours) +
'</div>' +
'</div>'
);
} else {
if(format == 'yyyy') {
return(
'<div class="bootstrap-datetimepicker-widget dropdown-menu">' +
'<div class="datepicker">' +
YGlobal.template +
'</div>' +
'</div>'
)
} else if(format == 'yyyy/MM') {
return (
'<div class="bootstrap-datetimepicker-widget dropdown-menu">' +
'<div class="datepicker">' +
YMGlobal.template +
'</div>' +
'</div>'
);
} else {
return (
'<div class="bootstrap-datetimepicker-widget dropdown-menu">' +
'<div class="datepicker">' +
DPGlobal.template +
'</div>' +
'</div>'
);
}
}
}
function UTCDate() {
return new Date(Date.UTC.apply(Date, arguments));
}
var DPGlobal = {
modes: [
{
clsName: 'days',
navFnc: 'UTCMonth',
navStep: 1
},
{
clsName: 'months',
navFnc: 'UTCFullYear',
navStep: 1
},
{
clsName: 'years',
navFnc: 'UTCFullYear',
navStep: 10
}
],
isLeapYear: function (year) {
return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0))
},
getDaysInMonth: function (year, month) {
return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]
},
headTemplate:
'<thead>' +
'<tr>' +
'<th class="prev">&lsaquo;</th>' +
'<th colspan="5" class="switch"></th>' +
'<th class="next">&rsaquo;</th>' +
'</tr>' +
'</thead>',
contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>'
};
var YMGlobal = {
modes: [
{
clsName: 'months',
navFnc: 'UTCFullYear',
navStep: 1
},
{
clsName: 'years',
navFnc: 'UTCFullYear',
navStep: 10
}
],
isLeapYear: function (year) {
return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0))
},
getDaysInMonth: function (year, month) {
return [31, (YMGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]
},
headTemplate:
'<thead>' +
'<tr>' +
'<th class="prev">&lsaquo;</th>' +
'<th colspan="5" class="switch"></th>' +
'<th class="next">&rsaquo;</th>' +
'</tr>' +
'</thead>',
contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>'
};
var YGlobal = {
modes: [
{
clsName: 'years',
navFnc: 'UTCFullYear',
navStep: 10
}
],
isLeapYear: function (year) {
return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0))
},
headTemplate:
'<thead>' +
'<tr>' +
'<th class="prev">&lsaquo;</th>' +
'<th colspan="5" class="switch"></th>' +
'<th class="next">&rsaquo;</th>' +
'</tr>' +
'</thead>',
contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>'
};
DPGlobal.template =
'<div class="datepicker-days">' +
'<table class="table-condensed">' +
DPGlobal.headTemplate +
'<tbody></tbody>' +
'</table>' +
'</div>' +
'<div class="datepicker-months">' +
'<table class="table-condensed">' +
DPGlobal.headTemplate +
DPGlobal.contTemplate+
'</table>'+
'</div>'+
'<div class="datepicker-years">'+
'<table class="table-condensed">'+
DPGlobal.headTemplate+
DPGlobal.contTemplate+
'</table>'+
'</div>';
YMGlobal.template =
'<div class="datepicker-months">' +
'<table class="table-condensed">' +
DPGlobal.headTemplate +
DPGlobal.contTemplate+
'</table>'+
'</div>'+
'<div class="datepicker-years">'+
'<table class="table-condensed">'+
DPGlobal.headTemplate+
DPGlobal.contTemplate+
'</table>'+
'</div>';
YGlobal.template =
'<div class="datepicker-years">'+
'<table class="table-condensed">'+
DPGlobal.headTemplate+
DPGlobal.contTemplate+
'</table>'+
'</div>';
var TPGlobal = {
hourTemplate: '<span data-action="showHours" data-time-component="hours" class="timepicker-hour"></span>',
minuteTemplate: '<span data-action="showMinutes" data-time-component="minutes" class="timepicker-minute"></span>',
// secondTemplate: '<span data-action="showSeconds" data-time-component="seconds" class="timepicker-second"></span>',
};
TPGlobal.getTemplate = function(is12Hours) {
return (
'<div class="timepicker-picker">' +
'<table class="table-condensed"' +
(is12Hours ? ' data-hour-format="12"' : '') +
'>' +
'<tr>' +
'<td><a href="#" class="btn" data-action="incrementHours"><i class="icon-chevron-up"></i></a></td>' +
'<td class="separator"></td>' +
'<td><a href="#" class="btn" data-action="incrementMinutes"><i class="icon-chevron-up"></i></a></td>' +
// '<td class="separator"></td>' +
// '<td><a href="#" class="btn" data-action="incrementSeconds"><i class="icon-chevron-up"></i></a></td>' +
// (is12Hours ? '<td class="separator"></td>' : '') +
'</tr>' +
'<tr>' +
'<td>' + TPGlobal.hourTemplate + '</td> ' +
'<td class="separator">:</td>' +
'<td>' + TPGlobal.minuteTemplate + '</td> ' +
// '<td class="separator">:</td>' +
// '<td>' + TPGlobal.secondTemplate + '</td>' +
(is12Hours ?
'<td class="separator"></td>' +
'<td>' +
'<button type="button" class="btn btn-primary" data-action="togglePeriod"></button>' +
'</td>' : '') +
'</tr>' +
'<tr>' +
'<td><a href="#" class="btn" data-action="decrementHours"><i class="icon-chevron-down"></i></a></td>' +
'<td class="separator"></td>' +
'<td><a href="#" class="btn" data-action="decrementMinutes"><i class="icon-chevron-down"></i></a></td>' +
// '<td class="separator"></td>' +
// '<td><a href="#" class="btn" data-action="decrementSeconds"><i class="icon-chevron-down"></i></a></td>' +
// (is12Hours ? '<td class="separator"></td>' : '') +
'</tr>' +
'</table>' +
'</div>' +
'<div class="timepicker-hours" data-action="selectHour">' +
'<table class="table-condensed">' +
'</table>'+
'</div>'+
'<div class="timepicker-minutes" data-action="selectMinute">' +
'<table class="table-condensed">' +
'</table>'+
// '</div>'+
// '<div class="timepicker-seconds" data-action="selectSecond">' +
// '<table class="table-condensed">' +
// '</table>'+
'</div>'
);
}
})(window.jQuery)