/* =========================================================
* foundation-datepicker.js
* copyright 2015 peter beno, najlepsiwebdesigner@gmail.com, @benopeter
* project website http://foundation-datepicker.peterbeno.com
* ========================================================= */
! function($) {
function utcdate() {
return new date(date.utc.apply(date, arguments));
}
function utctoday() {
var today = new date();
return utcdate(today.getutcfullyear(), today.getutcmonth(), today.getutcdate());
}
var datepicker = function(element, options) {
var that = this;
this.element = $(element);
this.autoshow = options.autoshow || true;
this.appendto = options.appendto || 'body';
this.closebutton = options.closebutton;
this.language = options.language || this.element.data('date-language') || "en";
this.language = this.language in dates ? this.language : this.language.split('-')[0]; //check if "de-de" style date is available, if not language should fallback to 2 letter code eg "de"
this.language = this.language in dates ? this.language : "en";
this.isrtl = dates[this.language].rtl || false;
this.format = dpglobal.parseformat(options.format || this.element.data('date-format') || dates[this.language].format || 'mm/dd/yyyy');
this.isinline = false;
this.isinput = this.element.is('input');
this.component = this.element.is('.date') ? this.element.find('.prefix, .postfix') : false;
this.hasinput = this.component && this.element.find('input').length;
this.disabledblclickselection = options.disabledblclickselection;
this.onrender = options.onrender || function() {};
if (this.component && this.component.length === 0) {
this.component = false;
}
this.linkfield = options.linkfield || this.element.data('link-field') || false;
this.linkformat = dpglobal.parseformat(options.linkformat || this.element.data('link-format') || 'yyyy-mm-dd hh:ii:ss');
this.minutestep = options.minutestep || this.element.data('minute-step') || 5;
this.pickerposition = options.pickerposition || this.element.data('picker-position') || 'bottom-right';
this.initialdate = options.initialdate || null;
this._attachevents();
this.minview = 0;
if ('minview' in options) {
this.minview = options.minview;
} else if ('minview' in this.element.data()) {
this.minview = this.element.data('min-view');
}
this.minview = dpglobal.convertviewmode(this.minview);
this.maxview = dpglobal.modes.length - 1;
if ('maxview' in options) {
this.maxview = options.maxview;
} else if ('maxview' in this.element.data()) {
this.maxview = this.element.data('max-view');
}
this.maxview = dpglobal.convertviewmode(this.maxview);
this.startviewmode = 'month';
if ('startview' in options) {
this.startviewmode = options.startview;
} else if ('startview' in this.element.data()) {
this.startviewmode = this.element.data('start-view');
}
this.startviewmode = dpglobal.convertviewmode(this.startviewmode);
this.viewmode = this.startviewmode;
if (!('minview' in options) && !('maxview' in options) && !(this.element.data('min-view') && !(this.element.data('max-view')))) {
this.picktime = false;
if ('picktime' in options) {
this.picktime = options.picktime;
}
if (this.picktime == true) {
this.minview = 0;
this.maxview = 4;
} else {
this.minview = 2;
this.maxview = 4;
}
}
this.forceparse = true;
if ('forceparse' in options) {
this.forceparse = options.forceparse;
} else if ('dateforceparse' in this.element.data()) {
this.forceparse = this.element.data('date-force-parse');
}
this.picker = $(dpglobal.template)
.appendto(this.isinline ? this.element : this.appendto)
.on({
click: $.proxy(this.click, this),
mousedown: $.proxy(this.mousedown, this)
});
if (this.closebutton) {
this.picker.find('a.datepicker-close').show();
} else {
this.picker.find('a.datepicker-close').hide();
}
if (this.isinline) {
this.picker.addclass('datepicker-inline');
} else {
this.picker.addclass('datepicker-dropdown dropdown-menu');
}
if (this.isrtl) {
this.picker.addclass('datepicker-rtl');
this.picker.find('.prev i, .next i')
.toggleclass('fa-chevron-left fa-chevron-right');
}
$(document).on('mousedown', function(e) {
// clicked outside the datepicker, hide it
if ($(e.target).closest('.datepicker.datepicker-inline, .datepicker.datepicker-dropdown').length === 0) {
that.hide();
}
});
this.autoclose = true;
if ('autoclose' in options) {
this.autoclose = options.autoclose;
} else if ('dateautoclose' in this.element.data()) {
this.autoclose = this.element.data('date-autoclose');
}
this.keyboardnavigation = true;
if ('keyboardnavigation' in options) {
this.keyboardnavigation = options.keyboardnavigation;
} else if ('datekeyboardnavigation' in this.element.data()) {
this.keyboardnavigation = this.element.data('date-keyboard-navigation');
}
this.todaybtn = (options.todaybtn || this.element.data('date-today-btn') || false);
this.todayhighlight = (options.todayhighlight || this.element.data('date-today-highlight') || false);
this.calendarweeks = false;
if ('calendarweeks' in options) {
this.calendarweeks = options.calendarweeks;
} else if ('datecalendarweeks' in this.element.data()) {
this.calendarweeks = this.element.data('date-calendar-weeks');
}
if (this.calendarweeks)
this.picker.find('tfoot th.today')
.attr('colspan', function(i, val) {
return parseint(val) + 1;
});
this.weekstart = ((options.weekstart || this.element.data('date-weekstart') || dates[this.language].weekstart || 0) % 7);
this.weekend = ((this.weekstart + 6) % 7);
this.startdate = -infinity;
this.enddate = infinity;
this.daysofweekdisabled = [];
this.setstartdate(options.startdate || this.element.data('date-startdate'));
this.setenddate(options.enddate || this.element.data('date-enddate'));
this.setdaysofweekdisabled(options.daysofweekdisabled || this.element.data('date-days-of-week-disabled'));
this.filldow();
this.fillmonths();
this.update();
this.showmode();
if (this.isinline) {
this.show();
}
};
datepicker.prototype = {
constructor: datepicker,
_events: [],
_attachevents: function() {
this._detachevents();
if (this.isinput) { // single input
this._events = [
[this.element, {
focus: (this.autoshow) ? $.proxy(this.show, this) : function() {},
keyup: $.proxy(this.update, this),
keydown: $.proxy(this.keydown, this)
}]
];
} else if (this.component && this.hasinput) { // component: input + button
this._events = [
// for components that are not readonly, allow keyboard nav
[this.element.find('input'), {
focus: (this.autoshow) ? $.proxy(this.show, this) : function() {},
keyup: $.proxy(this.update, this),
keydown: $.proxy(this.keydown, this)
}],
[this.component, {
click: $.proxy(this.show, this)
}]
];
} else if (this.element.is('div')) { // inline datepicker
this.isinline = true;
} else {
this._events = [
[this.element, {
click: $.proxy(this.show, this)
}]
];
}
if (this.disabledblclickselection) {
this._events[this._events.length] = [
this.element, {
dblclick: function(e) {
e.preventdefault();
e.stoppropagation();
$(this).blur()
}
}
];
}
for (var i = 0, el, ev; i < this._events.length; i++) {
el = this._events[i][0];
ev = this._events[i][1];
el.on(ev);
}
},
_detachevents: function() {
for (var i = 0, el, ev; i < this._events.length; i++) {
el = this._events[i][0];
ev = this._events[i][1];
el.off(ev);
}
this._events = [];
},
show: function(e) {
this.picker.show();
this.height = this.component ? this.component.outerheight() : this.element.outerheight();
this.update();
this.place();
$(window).on('resize', $.proxy(this.place, this));
if (e) {
e.stoppropagation();
e.preventdefault();
}
this.element.trigger({
type: 'show',
date: this.date
});
},
hide: function(e) {
if (this.isinline) return;
if (!this.picker.is(':visible')) return;
this.picker.hide();
$(window).off('resize', this.place);
this.viewmode = this.startviewmode;
this.showmode();
if (!this.isinput) {
$(document).off('mousedown', this.hide);
}
if (
this.forceparse &&
(
this.isinput && this.element.val() ||
this.hasinput && this.element.find('input').val()
)
)
this.setvalue();
this.element.trigger({
type: 'hide',
date: this.date
});
},
remove: function() {
this._detachevents();
this.picker.remove();
delete this.element.data().datepicker;
},
getdate: function() {
var d = this.getutcdate();
return new date(d.gettime() + (d.gettimezoneoffset() * 60000));
},
getutcdate: function() {
return this.date;
},
setdate: function(d) {
this.setutcdate(new date(d.gettime() - (d.gettimezoneoffset() * 60000)));
},
setutcdate: function(d) {
this.date = d;
this.setvalue();
},
setvalue: function() {
var formatted = this.getformatteddate();
if (!this.isinput) {
if (this.component) {
this.element.find('input').val(formatted);
}
this.element.data('date', formatted);
} else {
this.element.val(formatted);
}
},
getformatteddate: function(format) {
if (format === undefined)
format = this.format;
return dpglobal.formatdate(this.date, format, this.language);
},
setstartdate: function(startdate) {
this.startdate = startdate || -infinity;
if (this.startdate !== -infinity) {
this.startdate = dpglobal.parsedate(this.startdate, this.format, this.language);
}
this.update();
this.updatenavarrows();
},
setenddate: function(enddate) {
this.enddate = enddate || infinity;
if (this.enddate !== infinity) {
this.enddate = dpglobal.parsedate(this.enddate, this.format, this.language);
}
this.update();
this.updatenavarrows();
},
setdaysofweekdisabled: function(daysofweekdisabled) {
this.daysofweekdisabled = daysofweekdisabled || [];
if (!$.isarray(this.daysofweekdisabled)) {
this.daysofweekdisabled = this.daysofweekdisabled.split(/,\s*/);
}
this.daysofweekdisabled = $.map(this.daysofweekdisabled, function(d) {
return parseint(d, 10);
});
this.update();
this.updatenavarrows();
},
place: function() {
if (this.isinline) return;
var zindex = parseint(this.element.parents().filter(function() {
return $(this).css('z-index') != 'auto';
}).first().css('z-index')) + 10;
var textbox = this.component ? this.component : this.element;
var offset = textbox.offset();
var height = textbox.outerheight() + parseint(textbox.css('margin-top'));
var width = textbox.outerwidth() + parseint(textbox.css('margin-left'));
var fulloffsettop = offset.top + height;
var offsetleft = offset.left;
// if the datepicker is going to be below the window, show it on top of the input
if ((fulloffsettop + this.picker.outerheight()) >= $(window).scrolltop() + $(window).height()) {
fulloffsettop = offset.top - this.picker.outerheight();
}
// if the datepicker is going to go past the right side of the window, we want
// to set the right position so the datepicker lines up with the textbox
if (offset.left + this.picker.width() >= $(window).width()) {
offsetleft = (offset.left + width) - this.picker.width();
}
this.picker.css({
top: fulloffsettop,
left: offsetleft,
zindex: zindex
});
},
update: function() {
var date, fromargs = false;
var currentval = this.isinput ? this.element.val() : this.element.data('date') || this.element.find('input').val();
if (arguments && arguments.length && (typeof arguments[0] === 'string' || arguments[0] instanceof date)) {
date = arguments[0];
fromargs = true;
}
else if (!currentval && this.initialdate != null) { // if value is not set, set it to the initialdate
date = this.initialdate
}
else {
date = this.isinput ? this.element.val() : this.element.data('date') || this.element.find('input').val();
}
this.date = dpglobal.parsedate(date, this.format, this.language);
if (fromargs || this.initialdate != null) this.setvalue();
if (this.date < this.startdate) {
this.viewdate = new date(this.startdate.valueof());
} else if (this.date > this.enddate) {
this.viewdate = new date(this.enddate.valueof());
} else {
this.viewdate = new date(this.date.valueof());
}
this.fill();
},
filldow: function() {
var dowcnt = this.weekstart,
html = '
';
if (this.calendarweeks) {
var cell = ' | ';
html += cell;
this.picker.find('.datepicker-days thead tr:first-child').prepend(cell);
}
while (dowcnt < this.weekstart + 7) {
html += '' + dates[this.language].daysmin[(dowcnt++) % 7] + ' | ';
}
html += '
';
this.picker.find('.datepicker-days thead').append(html);
},
fillmonths: function() {
var html = '',
i = 0;
while (i < 12) {
html += '' + dates[this.language].monthsshort[i++] + '';
}
this.picker.find('.datepicker-months td').html(html);
},
fill: function() {
if (this.date == null || this.viewdate == null) {
return;
}
var d = new date(this.viewdate.valueof()),
year = d.getutcfullyear(),
month = d.getutcmonth(),
daymonth = d.getutcdate(),
hours = d.getutchours(),
minutes = d.getutcminutes(),
startyear = this.startdate !== -infinity ? this.startdate.getutcfullyear() : -infinity,
startmonth = this.startdate !== -infinity ? this.startdate.getutcmonth() : -infinity,
endyear = this.enddate !== infinity ? this.enddate.getutcfullyear() : infinity,
endmonth = this.enddate !== infinity ? this.enddate.getutcmonth() : infinity,
currentdate = this.date && this.date.valueof(),
today = new date(),
titleformat = dates[this.language].titleformat || dates['en'].titleformat;
// this.picker.find('.datepicker-days thead th.date-switch')
// .text(dpglobal.formatdate(new utcdate(year, month), titleformat, this.language));
this.picker.find('.datepicker-days thead th:eq(1)')
.text(dates[this.language].months[month] + ' ' + year);
this.picker.find('.datepicker-hours thead th:eq(1)')
.text(daymonth + ' ' + dates[this.language].months[month] + ' ' + year);
this.picker.find('.datepicker-minutes thead th:eq(1)')
.text(daymonth + ' ' + dates[this.language].months[month] + ' ' + year);
this.picker.find('tfoot th.today')
.text(dates[this.language].today)
.toggle(this.todaybtn !== false);
this.updatenavarrows();
this.fillmonths();
var prevmonth = utcdate(year, month - 1, 28, 0, 0, 0, 0),
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('');
if (this.calendarweeks) {
// adapted from https://github.com/timrwood/moment/blob/master/moment.js#l128
var a = new date(prevmonth.getutcfullyear(), prevmonth.getutcmonth(), prevmonth.getutcdate() - prevmonth.getday() + 10 - (this.weekstart && this.weekstart % 7 < 5 && 7)),
b = new date(a.getfullyear(), 0, 4),
calweek = ~~((a - b) / 864e5 / 7 + 1.5);
html.push('' + calweek + ' | ');
}
}
clsname = ' ' + this.onrender(prevmonth) + ' ';
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';
}
// compare internal utc date with local today, not utc today
if (this.todayhighlight &&
prevmonth.getutcfullyear() == today.getfullyear() &&
prevmonth.getutcmonth() == today.getmonth() &&
prevmonth.getutcdate() == today.getdate()) {
clsname += ' today';
}
if (currentdate && prevmonth.valueof() == currentdate) {
clsname += ' active';
}
if (prevmonth.valueof() < this.startdate || prevmonth.valueof() > this.enddate ||
$.inarray(prevmonth.getutcday(), this.daysofweekdisabled) !== -1) {
clsname += ' disabled';
}
html.push('' + prevmonth.getutcdate() + ' | ');
if (prevmonth.getutcday() == this.weekend) {
html.push('
');
}
prevmonth.setutcdate(prevmonth.getutcdate() + 1);
}
this.picker.find('.datepicker-days tbody').empty().append(html.join(''));
html = [];
for (var i = 0; i < 24; i++) {
var actual = utcdate(year, month, daymonth, i);
clsname = '';
// we want the previous hour for the startdate
if ((actual.valueof() + 3600000) < this.startdate || actual.valueof() > this.enddate) {
clsname += ' disabled';
} else if (hours == i) {
clsname += ' active';
}
html.push('' + i + ':00');
}
this.picker.find('.datepicker-hours td').html(html.join(''));
html = [];
for (var i = 0; i < 60; i += this.minutestep) {
var actual = utcdate(year, month, daymonth, hours, i);
clsname = '';
if (actual.valueof() < this.startdate || actual.valueof() > this.enddate) {
clsname += ' disabled';
} else if (math.floor(minutes / this.minutestep) == math.floor(i / this.minutestep)) {
clsname += ' active';
}
html.push('' + hours + ':' + (i < 10 ? '0' + i : i) + '');
}
this.picker.find('.datepicker-minutes td').html(html.join(''));
var currentyear = this.date && this.date.getutcfullyear();
var months = this.picker.find('.datepicker-months')
.find('th:eq(1)')
.text(year)
.end()
.find('span').removeclass('active');
if (currentyear && currentyear == year) {
months.eq(this.date.getutcmonth()).addclass('active');
}
if (year < startyear || year > endyear) {
months.addclass('disabled');
}
if (year == startyear) {
months.slice(0, startmonth).addclass('disabled');
}
if (year == endyear) {
months.slice(endmonth + 1).addclass('disabled');
}
html = '';
year = parseint(year / 10, 10) * 10;
var yearcont = this.picker.find('.datepicker-years')
.find('th:eq(1)')
.text(year + '-' + (year + 9))
.end()
.find('td');
year -= 1;
for (var i = -1; i < 11; i++) {
html += '' + year + '';
year += 1;
}
yearcont.html(html);
},
updatenavarrows: function() {
var d = new date(this.viewdate),
year = d.getutcfullyear(),
month = d.getutcmonth(),
day = d.getutcdate(),
hour = d.getutchours();
switch (this.viewmode) {
case 0:
if (this.startdate !== -infinity && year <= this.startdate.getutcfullyear() && month <= this.startdate.getutcmonth() && day <= this.startdate.getutcdate() && hour <= this.startdate.getutchours()) {
this.picker.find('.prev').css({
visibility: 'hidden'
});
} else {
this.picker.find('.prev').css({
visibility: 'visible'
});
}
if (this.enddate !== infinity && year >= this.enddate.getutcfullyear() && month >= this.enddate.getutcmonth() && day >= this.enddate.getutcdate() && hour >= this.enddate.getutchours()) {
this.picker.find('.next').css({
visibility: 'hidden'
});
} else {
this.picker.find('.next').css({
visibility: 'visible'
});
}
break;
case 1:
if (this.startdate !== -infinity && year <= this.startdate.getutcfullyear() && month <= this.startdate.getutcmonth() && day <= this.startdate.getutcdate()) {
this.picker.find('.prev').css({
visibility: 'hidden'
});
} else {
this.picker.find('.prev').css({
visibility: 'visible'
});
}
if (this.enddate !== infinity && year >= this.enddate.getutcfullyear() && month >= this.enddate.getutcmonth() && day >= this.enddate.getutcdate()) {
this.picker.find('.next').css({
visibility: 'hidden'
});
} else {
this.picker.find('.next').css({
visibility: 'visible'
});
}
break;
case 2:
if (this.startdate !== -infinity && year <= this.startdate.getutcfullyear() && month <= this.startdate.getutcmonth()) {
this.picker.find('.prev').css({
visibility: 'hidden'
});
} else {
this.picker.find('.prev').css({
visibility: 'visible'
});
}
if (this.enddate !== infinity && year >= this.enddate.getutcfullyear() && month >= this.enddate.getutcmonth()) {
this.picker.find('.next').css({
visibility: 'hidden'
});
} else {
this.picker.find('.next').css({
visibility: 'visible'
});
}
break;
case 3:
case 4:
if (this.startdate !== -infinity && year <= this.startdate.getutcfullyear()) {
this.picker.find('.prev').css({
visibility: 'hidden'
});
} else {
this.picker.find('.prev').css({
visibility: 'visible'
});
}
if (this.enddate !== infinity && year >= this.enddate.getutcfullyear()) {
this.picker.find('.next').css({
visibility: 'hidden'
});
} else {
this.picker.find('.next').css({
visibility: 'visible'
});
}
break;
}
},
click: function(e) {
e.stoppropagation();
e.preventdefault();
if ($(e.target).hasclass('datepicker-close') || $(e.target).parent().hasclass('datepicker-close')) {
this.hide();
}
var target = $(e.target).closest('span, td, th');
if (target.length == 1) {
if (target.is('.disabled')) {
this.element.trigger({
type: 'outofrange',
date: this.viewdate,
startdate: this.startdate,
enddate: this.enddate
});
return;
}
switch (target[0].nodename.tolowercase()) {
case 'th':
switch (target[0].classname) {
case 'date-switch':
this.showmode(1);
break;
case 'prev':
case 'next':
var dir = dpglobal.modes[this.viewmode].navstep * (target[0].classname == 'prev' ? -1 : 1);
switch (this.viewmode) {
case 0:
this.viewdate = this.movehour(this.viewdate, dir);
break;
case 1:
this.viewdate = this.movedate(this.viewdate, dir);
break;
case 2:
this.viewdate = this.movemonth(this.viewdate, dir);
break;
case 3:
case 4:
this.viewdate = this.moveyear(this.viewdate, dir);
break;
}
this.fill();
break;
case 'today':
var date = new date();
date = utcdate(date.getfullyear(), date.getmonth(), date.getdate(), date.gethours(), date.getminutes(), date.getseconds());
this.viewmode = this.startviewmode;
this.showmode(0);
this._setdate(date);
break;
}
break;
case 'span':
if (!target.is('.disabled')) {
if (target.is('.month')) {
if (this.minview === 3) {
var month = target.parent().find('span').index(target) || 0;
var year = this.viewdate.getutcfullyear(),
day = 1,
hours = this.viewdate.getutchours(),
minutes = this.viewdate.getutcminutes(),
seconds = this.viewdate.getutcseconds();
this._setdate(utcdate(year, month, day, hours, minutes, seconds, 0));
} else {
this.viewdate.setutcdate(1);
var month = target.parent().find('span').index(target);
this.viewdate.setutcmonth(month);
this.element.trigger({
type: 'changemonth',
date: this.viewdate
});
}
} else if (target.is('.year')) {
if (this.minview === 4) {
var year = parseint(target.text(), 10) || 0;
var month = 0,
day = 1,
hours = this.viewdate.getutchours(),
minutes = this.viewdate.getutcminutes(),
seconds = this.viewdate.getutcseconds();
this._setdate(utcdate(year, month, day, hours, minutes, seconds, 0));
} else {
this.viewdate.setutcdate(1);
var year = parseint(target.text(), 10) || 0;
this.viewdate.setutcfullyear(year);
this.element.trigger({
type: 'changeyear',
date: this.viewdate
});
}
} else if (target.is('.hour')) {
var hours = parseint(target.text(), 10) || 0;
var year = this.viewdate.getutcfullyear(),
month = this.viewdate.getutcmonth(),
day = this.viewdate.getutcdate(),
minutes = this.viewdate.getutcminutes(),
seconds = this.viewdate.getutcseconds();
this._setdate(utcdate(year, month, day, hours, minutes, seconds, 0));
} else if (target.is('.minute')) {
var minutes = parseint(target.text().substr(target.text().indexof(':') + 1), 10) || 0;
var year = this.viewdate.getutcfullyear(),
month = this.viewdate.getutcmonth(),
day = this.viewdate.getutcdate(),
hours = this.viewdate.getutchours(),
seconds = this.viewdate.getutcseconds();
this._setdate(utcdate(year, month, day, hours, minutes, seconds, 0));
}
if (this.viewmode != 0) {
var oldviewmode = this.viewmode;
this.showmode(-1);
this.fill();
if (oldviewmode == this.viewmode && this.autoclose) {
this.hide();
}
} else {
this.fill();
if (this.autoclose) {
this.hide();
}
}
}
break;
case 'td':
if (target.is('.day') && !target.is('.disabled')) {
var day = parseint(target.text(), 10) || 1;
var year = this.viewdate.getutcfullyear(),
month = this.viewdate.getutcmonth(),
hours = this.viewdate.getutchours(),
minutes = this.viewdate.getutcminutes(),
seconds = this.viewdate.getutcseconds();
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._setdate(utcdate(year, month, day, hours, minutes, seconds, 0));
}
var oldviewmode = this.viewmode;
this.showmode(-1);
this.fill();
if (oldviewmode == this.viewmode && this.autoclose) {
this.hide();
}
break;
}
}
},
_setdate: function(date, which) {
if (!which || which == 'date')
this.date = date;
if (!which || which == 'view')
this.viewdate = date;
this.fill();
this.setvalue();
this.element.trigger({
type: 'changedate',
date: this.date
});
var element;
if (this.isinput) {
element = this.element;
} else if (this.component) {
element = this.element.find('input');
}
if (element) {
element.change();
if (this.autoclose && (!which || which == 'date')) {
// this.hide();
}
}
},
movehour: function(date, dir) {
if (!dir) return date;
var new_date = new date(date.valueof());
dir = dir > 0 ? 1 : -1;
new_date.setutchours(new_date.getutchours() + dir);
return new_date;
},
movedate: function(date, dir) {
if (!dir) return date;
var new_date = new date(date.valueof());
dir = dir > 0 ? 1 : -1;
new_date.setutcdate(new_date.getutcdate() + dir);
return new_date;
},
movemonth: function(date, dir) {
if (!dir) return date;
var new_date = new date(date.valueof()),
day = new_date.getutcdate(),
month = new_date.getutcmonth(),
mag = math.abs(dir),
new_month, test;
dir = dir > 0 ? 1 : -1;
if (mag == 1) {
test = dir == -1
// if going back one month, make sure month is not current month
// (eg, mar 31 -> feb 31 == feb 28, not mar 02)
? function() {
return new_date.getutcmonth() == month;
}
// if going forward one month, make sure month is as expected
// (eg, jan 31 -> feb 31 == feb 28, not mar 02)
: function() {
return new_date.getutcmonth() != new_month;
};
new_month = month + dir;
new_date.setutcmonth(new_month);
// dec -> jan (12) or jan -> dec (-1) -- limit expected date to 0-11
if (new_month < 0 || new_month > 11)
new_month = (new_month + 12) % 12;
} else {
// for magnitudes >1, move one month at a time...
for (var i = 0; i < mag; i++)
// ...which might decrease the day (eg, jan 31 to feb 28, etc)...
new_date = this.movemonth(new_date, dir);
// ...then reset the day, keeping it in the new month
new_month = new_date.getutcmonth();
new_date.setutcdate(day);
test = function() {
return new_month != new_date.getutcmonth();
};
}
// common date-resetting loop -- if date is beyond end of month, make it
// end of month
while (test()) {
new_date.setutcdate(--day);
new_date.setutcmonth(new_month);
}
return new_date;
},
moveyear: function(date, dir) {
return this.movemonth(date, dir * 12);
},
datewithinrange: function(date) {
return date >= this.startdate && date <= this.enddate;
},
keydown: function(e) {
if (this.picker.is(':not(:visible)')) {
if (e.keycode == 27) // allow escape to hide and re-show picker
this.show();
return;
}
var datechanged = false,
dir, day, month,
newdate, newviewdate;
switch (e.keycode) {
case 27: // escape
this.hide();
e.preventdefault();
break;
case 37: // left
case 39: // right
if (!this.keyboardnavigation) break;
dir = e.keycode == 37 ? -1 : 1;
if (e.ctrlkey) {
newdate = this.moveyear(this.date, dir);
newviewdate = this.moveyear(this.viewdate, dir);
} else if (e.shiftkey) {
newdate = this.movemonth(this.date, dir);
newviewdate = this.movemonth(this.viewdate, dir);
} else {
newdate = new date(this.date.valueof());
newdate.setutcdate(this.date.getutcdate() + dir);
newviewdate = new date(this.viewdate.valueof());
newviewdate.setutcdate(this.viewdate.getutcdate() + dir);
}
if (this.datewithinrange(newdate)) {
this.date = newdate;
this.viewdate = newviewdate;
this.setvalue();
this.update();
e.preventdefault();
datechanged = true;
}
break;
case 38: // up
case 40: // down
if (!this.keyboardnavigation) break;
dir = e.keycode == 38 ? -1 : 1;
if (e.ctrlkey) {
newdate = this.moveyear(this.date, dir);
newviewdate = this.moveyear(this.viewdate, dir);
} else if (e.shiftkey) {
newdate = this.movemonth(this.date, dir);
newviewdate = this.movemonth(this.viewdate, dir);
} else {
newdate = new date(this.date.valueof());
newdate.setutcdate(this.date.getutcdate() + dir * 7);
newviewdate = new date(this.viewdate.valueof());
newviewdate.setutcdate(this.viewdate.getutcdate() + dir * 7);
}
if (this.datewithinrange(newdate)) {
this.date = newdate;
this.viewdate = newviewdate;
this.setvalue();
this.update();
e.preventdefault();
datechanged = true;
}
break;
case 13: // enter
this.hide();
e.preventdefault();
break;
case 9: // tab
this.hide();
break;
}
if (datechanged) {
this.element.trigger({
type: 'changedate',
date: this.date
});
var element;
if (this.isinput) {
element = this.element;
} else if (this.component) {
element = this.element.find('input');
}
if (element) {
element.change();
}
}
},
showmode: function(dir) {
if (dir) {
var newviewmode = math.max(0, math.min(dpglobal.modes.length - 1, this.viewmode + dir));
if (newviewmode >= this.minview && newviewmode <= this.maxview) {
this.viewmode = newviewmode;
}
}
/*
vitalets: fixing bug of very special conditions:
jquery 1.7.1 + webkit + show inline datepicker in bootstrap popover.
method show() does not set display css correctly and datepicker is not shown.
changed to .css('display', 'block') solve the problem.
see https://github.com/vitalets/x-editable/issues/37
in jquery 1.7.2+ everything works fine.
*/
//this.picker.find('>div').hide().filter('.datepicker-'+dpglobal.modes[this.viewmode].clsname).show();
this.picker.find('>div').hide().filter('.datepicker-' + dpglobal.modes[this.viewmode].clsname).css('display', 'block');
this.updatenavarrows();
},
reset: function(e) {
this._setdate(null, 'date');
}
};
$.fn.fdatepicker = function(option) {
var args = array.apply(null, arguments);
args.shift();
return this.each(function() {
var $this = $(this),
data = $this.data('datepicker'),
options = typeof option == 'object' && option;
if (!data) {
$this.data('datepicker', (data = new datepicker(this, $.extend({}, $.fn.fdatepicker.defaults, options))));
}
if (typeof option == 'string' && typeof data[option] == 'function') {
data[option].apply(data, args);
}
});
};
$.fn.fdatepicker.defaults = {
onrender: function(date) {
return '';
}
};
$.fn.fdatepicker.constructor = datepicker;
var dates = $.fn.fdatepicker.dates = {
'en': {
days: ["鏄熸湡鏃?, "鏄熸湡涓€", "鏄熸湡浜?, "鏄熸湡涓?, "鏄熸湡鍥?, "鏄熸湡浜?, "鏄熸湡鍏?],
daysshort: ["鍛ㄦ棩", "鍛ㄤ竴", "鍛ㄤ簩", "鍛ㄤ笁", "鍛ㄥ洓", "鍛ㄤ簲", "鍛ㄥ叚"],
daysmin: ["鏃?, "涓€", "浜?, "涓?, "鍥?, "浜?, "鍏?],
months: ["涓€鏈?, "浜屾湀", "涓夋湀", "鍥涙湀", "浜旀湀", "鍏湀", "涓冩湀", "鍏湀", "涔濇湀", "鍗佹湀", "鍗佷竴鏈?, "鍗佷簩鏈?],
monthsshort: ["涓€", "浜?, "涓?, "鍥?, "浜?, "鍏?, "涓?, "鍏?, "涔?, "鍗?, "鍗佷竴", "鍗佷簩"],
today: '浠婂ぉ',
titleformat: "mm yyyy"
}
};
var dpglobal = {
modes: [{
clsname: 'minutes',
navfnc: 'hours',
navstep: 1
}, {
clsname: 'hours',
navfnc: 'date',
navstep: 1
}, {
clsname: 'days',
navfnc: 'month',
navstep: 1
}, {
clsname: 'months',
navfnc: 'fullyear',
navstep: 1
}, {
clsname: 'years',
navfnc: 'fullyear',
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];
},
validparts: /hh?|ii?|ss?|dd?|mm?|mm?|yy(?:yy)?/g,
nonpunctuation: /[^ -\/:-@\[\u3400-\u9fff-`{-~\t\n\r]+/g,
parseformat: function(format) {
// ie treats \0 as a string end in inputs (truncating the value),
// so it's a bad format delimiter, anyway
var separators = format.replace(this.validparts, '\0').split('\0'),
parts = format.match(this.validparts);
if (!separators || !separators.length || !parts || parts.length === 0) {
throw new error("invalid date format.");
}
return {
separators: separators,
parts: parts
};
},
parsedate: function(date, format, language) {
if (date instanceof date) return new date(date.valueof() - date.gettimezoneoffset() * 60000);
if (/^\d{4}\-\d{1,2}\-\d{1,2}$/.test(date)) {
format = this.parseformat('yyyy-mm-dd');
}
if (/^\d{4}\-\d{1,2}\-\d{1,2}[t ]\d{1,2}\:\d{1,2}$/.test(date)) {
format = this.parseformat('yyyy-mm-dd hh:ii');
}
if (/^\d{4}\-\d{1,2}\-\d{1,2}[t ]\d{1,2}\:\d{1,2}\:\d{1,2}[z]{0,1}$/.test(date)) {
format = this.parseformat('yyyy-mm-dd hh:ii:ss');
}
if (/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(date)) {
var part_re = /([-+]\d+)([dmwy])/,
parts = date.match(/([-+]\d+)([dmwy])/g),
part, dir;
date = new date();
for (var i = 0; i < parts.length; i++) {
part = part_re.exec(parts[i]);
dir = parseint(part[1]);
switch (part[2]) {
case 'd':
date.setutcdate(date.getutcdate() + dir);
break;
case 'm':
date = datetimepicker.prototype.movemonth.call(datetimepicker.prototype, date, dir);
break;
case 'w':
date.setutcdate(date.getutcdate() + dir * 7);
break;
case 'y':
date = datetimepicker.prototype.moveyear.call(datetimepicker.prototype, date, dir);
break;
}
}
return utcdate(date.getutcfullyear(), date.getutcmonth(), date.getutcdate(), date.getutchours(), date.getutcminutes(), date.getutcseconds());
}
var parts = date && date.match(this.nonpunctuation) || [],
date = new date(),
parsed = {},
setters_order = ['hh', 'h', 'ii', 'i', 'ss', 's', 'yyyy', 'yy', 'm', 'mm', 'm', 'mm', 'd', 'dd'],
setters_map = {
hh: function(d, v) {
return d.setutchours(v);
},
h: function(d, v) {
return d.setutchours(v);
},
ii: function(d, v) {
return d.setutcminutes(v);
},
i: function(d, v) {
return d.setutcminutes(v);
},
ss: function(d, v) {
return d.setutcseconds(v);
},
s: function(d, v) {
return d.setutcseconds(v);
},
yyyy: function(d, v) {
return d.setutcfullyear(v);
},
yy: function(d, v) {
return d.setutcfullyear(2000 + v);
},
m: function(d, v) {
v -= 1;
while (v < 0) v += 12;
v %= 12;
d.setutcmonth(v);
while (d.getutcmonth() != v)
d.setutcdate(d.getutcdate() - 1);
return d;
},
d: function(d, v) {
return d.setutcdate(v);
}
},
val, filtered, part;
setters_map['m'] = setters_map['mm'] = setters_map['mm'] = setters_map['m'];
setters_map['dd'] = setters_map['d'];
date = utcdate(date.getfullyear(), date.getmonth(), date.getdate(), 0, 0, 0); //date.gethours(), date.getminutes(), date.getseconds());
if (parts.length == format.parts.length) {
for (var i = 0, cnt = format.parts.length; i < cnt; i++) {
val = parseint(parts[i], 10);
part = format.parts[i];
if (isnan(val)) {
switch (part) {
case 'mm':
filtered = $(dates[language].months).filter(function() {
var m = this.slice(0, parts[i].length),
p = parts[i].slice(0, m.length);
return m == p;
});
val = $.inarray(filtered[0], dates[language].months) + 1;
break;
case 'm':
filtered = $(dates[language].monthsshort).filter(function() {
var m = this.slice(0, parts[i].length),
p = parts[i].slice(0, m.length);
return m == p;
});
val = $.inarray(filtered[0], dates[language].monthsshort) + 1;
break;
}
}
parsed[part] = val;
}
for (var i = 0, s; i < setters_order.length; i++) {
s = setters_order[i];
if (s in parsed && !isnan(parsed[s]))
setters_map[s](date, parsed[s])
}
}
return date;
},
formatdate: function(date, format, language) {
if (date == null) {
return '';
}
var val = {
h: date.getutchours(),
i: date.getutcminutes(),
s: date.getutcseconds(),
d: date.getutcdate(),
m: date.getutcmonth() + 1,
m: dates[language].monthsshort[date.getutcmonth()],
mm: dates[language].months[date.getutcmonth()],
yy: date.getutcfullyear().tostring().substring(2),
yyyy: date.getutcfullyear()
};
val.hh = (val.h < 10 ? '0' : '') + val.h;
val.ii = (val.i < 10 ? '0' : '') + val.i;
val.ss = (val.s < 10 ? '0' : '') + val.s;
val.dd = (val.d < 10 ? '0' : '') + val.d;
val.mm = (val.m < 10 ? '0' : '') + val.m;
var date = [],
seps = $.extend([], format.separators);
for (var i = 0, cnt = format.parts.length; i < cnt; i++) {
if (seps.length)
date.push(seps.shift())
date.push(val[format.parts[i]]);
}
return date.join('');
},
convertviewmode: function(viewmode) {
switch (viewmode) {
case 4:
case 'decade':
viewmode = 4;
break;
case 3:
case 'year':
viewmode = 3;
break;
case 2:
case 'month':
viewmode = 2;
break;
case 1:
case 'day':
viewmode = 1;
break;
case 0:
case 'hour':
viewmode = 0;
break;
}
return viewmode;
},
headtemplate: '' +
'' +
' | ' +
' | ' +
' | ' +
'
' +
'',
conttemplate: ' |
',
foottemplate: ' |
'
};
dpglobal.template = '' +
'
' +
'
' +
dpglobal.headtemplate +
dpglobal.conttemplate +
dpglobal.foottemplate +
'
' +
'
' +
'
' +
'
' +
dpglobal.headtemplate +
dpglobal.conttemplate +
dpglobal.foottemplate +
'
' +
'
' +
'
' +
'
' +
dpglobal.headtemplate +
'' +
dpglobal.foottemplate +
'
' +
'
' +
'
' +
'
' +
dpglobal.headtemplate +
dpglobal.conttemplate +
dpglobal.foottemplate +
'
' +
'
' +
'
' +
'
' +
dpglobal.headtemplate +
dpglobal.conttemplate +
dpglobal.foottemplate +
'
' +
'
' +
'
' +
'
';
$.fn.fdatepicker.dpglobal = dpglobal;
}(window.jquery);