vendor/assets/javascripts/bootstrap-datetimepicker.js in bootstrap3-datetimepicker-rails-4.7.14 vs vendor/assets/javascripts/bootstrap-datetimepicker.js in bootstrap3-datetimepicker-rails-4.14.30
- old
+ new
@@ -1,6 +1,6 @@
-/*! version : 4.7.14
+/*! version : 4.14.30
=========================================================
bootstrap-datetimejs
https://github.com/Eonasdan/bootstrap-datetimepicker
Copyright (c) 2015 Jonathan Peterson
=========================================================
@@ -82,13 +82,18 @@
},
{
clsName: 'years',
navFnc: 'y',
navStep: 10
+ },
+ {
+ clsName: 'decades',
+ navFnc: 'y',
+ navStep: 100
}
],
- viewModes = ['days', 'months', 'years'],
+ viewModes = ['days', 'months', 'years', 'decades'],
verticalModes = ['top', 'bottom', 'auto'],
horizontalModes = ['left', 'right', 'auto'],
toolbarPlacements = ['default', 'top', 'bottom'],
keyMap = {
'up': 38,
@@ -147,11 +152,10 @@
return actualFormat.indexOf('s') !== -1;
default:
return false;
}
},
-
hasTime = function () {
return (isEnabled('h') || isEnabled('m') || isEnabled('s'));
},
hasDate = function () {
@@ -187,10 +191,15 @@
),
$('<div>').addClass('datepicker-years')
.append($('<table>').addClass('table-condensed')
.append(headTemplate.clone())
.append(contTemplate.clone())
+ ),
+ $('<div>').addClass('datepicker-decades')
+ .append($('<table>').addClass('table-condensed')
+ .append(headTemplate.clone())
+ .append(contTemplate.clone())
)
];
},
getTimePickerMainTemplate = function () {
@@ -198,53 +207,53 @@
middleRow = $('<tr>'),
bottomRow = $('<tr>');
if (isEnabled('h')) {
topRow.append($('<td>')
- .append($('<a>').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'incrementHours')
+ .append($('<a>').attr({href: '#', tabindex: '-1', 'title':'Increment Hour'}).addClass('btn').attr('data-action', 'incrementHours')
.append($('<span>').addClass(options.icons.up))));
middleRow.append($('<td>')
- .append($('<span>').addClass('timepicker-hour').attr('data-time-component', 'hours').attr('data-action', 'showHours')));
+ .append($('<span>').addClass('timepicker-hour').attr({'data-time-component':'hours', 'title':'Pick Hour'}).attr('data-action', 'showHours')));
bottomRow.append($('<td>')
- .append($('<a>').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'decrementHours')
+ .append($('<a>').attr({href: '#', tabindex: '-1', 'title':'Decrement Hour'}).addClass('btn').attr('data-action', 'decrementHours')
.append($('<span>').addClass(options.icons.down))));
}
if (isEnabled('m')) {
if (isEnabled('h')) {
topRow.append($('<td>').addClass('separator'));
middleRow.append($('<td>').addClass('separator').html(':'));
bottomRow.append($('<td>').addClass('separator'));
}
topRow.append($('<td>')
- .append($('<a>').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'incrementMinutes')
+ .append($('<a>').attr({href: '#', tabindex: '-1', 'title':'Increment Minute'}).addClass('btn').attr('data-action', 'incrementMinutes')
.append($('<span>').addClass(options.icons.up))));
middleRow.append($('<td>')
- .append($('<span>').addClass('timepicker-minute').attr('data-time-component', 'minutes').attr('data-action', 'showMinutes')));
+ .append($('<span>').addClass('timepicker-minute').attr({'data-time-component': 'minutes', 'title':'Pick Minute'}).attr('data-action', 'showMinutes')));
bottomRow.append($('<td>')
- .append($('<a>').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'decrementMinutes')
+ .append($('<a>').attr({href: '#', tabindex: '-1', 'title':'Decrement Minute'}).addClass('btn').attr('data-action', 'decrementMinutes')
.append($('<span>').addClass(options.icons.down))));
}
if (isEnabled('s')) {
if (isEnabled('m')) {
topRow.append($('<td>').addClass('separator'));
middleRow.append($('<td>').addClass('separator').html(':'));
bottomRow.append($('<td>').addClass('separator'));
}
topRow.append($('<td>')
- .append($('<a>').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'incrementSeconds')
+ .append($('<a>').attr({href: '#', tabindex: '-1', 'title':'Increment Second'}).addClass('btn').attr('data-action', 'incrementSeconds')
.append($('<span>').addClass(options.icons.up))));
middleRow.append($('<td>')
- .append($('<span>').addClass('timepicker-second').attr('data-time-component', 'seconds').attr('data-action', 'showSeconds')));
+ .append($('<span>').addClass('timepicker-second').attr({'data-time-component': 'seconds', 'title':'Pick Second'}).attr('data-action', 'showSeconds')));
bottomRow.append($('<td>')
- .append($('<a>').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'decrementSeconds')
+ .append($('<a>').attr({href: '#', tabindex: '-1', 'title':'Decrement Second'}).addClass('btn').attr('data-action', 'decrementSeconds')
.append($('<span>').addClass(options.icons.down))));
}
if (!use24Hours) {
topRow.append($('<td>').addClass('separator'));
middleRow.append($('<td>')
- .append($('<button>').addClass('btn btn-primary').attr('data-action', 'togglePeriod')));
+ .append($('<button>').addClass('btn btn-primary').attr({'data-action': 'togglePeriod', tabindex: '-1', 'title':'Toggle Period'})));
bottomRow.append($('<td>').addClass('separator'));
}
return $('<div>').addClass('timepicker-picker')
.append($('<table>').addClass('table-condensed')
@@ -274,20 +283,20 @@
},
getToolbar = function () {
var row = [];
if (options.showTodayButton) {
- row.push($('<td>').append($('<a>').attr('data-action', 'today').append($('<span>').addClass(options.icons.today))));
+ row.push($('<td>').append($('<a>').attr({'data-action':'today', 'title':'Go to today'}).append($('<span>').addClass(options.icons.today))));
}
if (!options.sideBySide && hasDate() && hasTime()) {
- row.push($('<td>').append($('<a>').attr('data-action', 'togglePicker').append($('<span>').addClass(options.icons.time))));
+ row.push($('<td>').append($('<a>').attr({'data-action':'togglePicker', 'title':'Select Time'}).append($('<span>').addClass(options.icons.time))));
}
if (options.showClear) {
- row.push($('<td>').append($('<a>').attr('data-action', 'clear').append($('<span>').addClass(options.icons.clear))));
+ row.push($('<td>').append($('<a>').attr({'data-action':'clear', 'title':'Clear selection'}).append($('<span>').addClass(options.icons.clear))));
}
if (options.showClose) {
- row.push($('<td>').append($('<a>').attr('data-action', 'close').append($('<span>').addClass(options.icons.close))));
+ row.push($('<td>').append($('<a>').attr({'data-action':'close', 'title':'Close the picker'}).append($('<span>').addClass(options.icons.close))));
}
return $('<table>').addClass('table-condensed').append($('<tbody>').append($('<tr>').append(row)));
},
getTemplate = function () {
@@ -302,10 +311,13 @@
}
if (use24Hours) {
template.addClass('usetwentyfour');
}
+ if (isEnabled('s') && !use24Hours) {
+ template.addClass('wider');
+ }
if (options.sideBySide && hasDate() && hasTime()) {
template.addClass('timepicker-sbs');
template.append(
$('<div>').addClass('row')
.append(dateView.addClass('col-sm-6'))
@@ -364,11 +376,11 @@
parent;
if (options.widgetParent) {
parent = options.widgetParent.append(widget);
} else if (element.is('input')) {
- parent = element.parent().append(widget);
+ parent = element.after(widget).parent();
} else if (options.inline) {
parent = element.append(widget);
return;
} else {
parent = element;
@@ -419,35 +431,46 @@
}
widget.css({
top: vertical === 'top' ? 'auto' : position.top + element.outerHeight(),
bottom: vertical === 'top' ? position.top + element.outerHeight() : 'auto',
- left: horizontal === 'left' ? parent.css('padding-left') : 'auto',
- right: horizontal === 'left' ? 'auto' : parent.width() - element.outerWidth()
+ left: horizontal === 'left' ? (parent === element ? 0 : position.left) : 'auto',
+ right: horizontal === 'left' ? 'auto' : parent.outerWidth() - element.outerWidth() - (parent === element ? 0 : position.left)
});
},
notifyEvent = function (e) {
if (e.type === 'dp.change' && ((e.date && e.date.isSame(e.oldDate)) || (!e.date && !e.oldDate))) {
return;
}
element.trigger(e);
},
+ viewUpdate = function (e) {
+ if (e === 'y') {
+ e = 'YYYY';
+ }
+ notifyEvent({
+ type: 'dp.update',
+ change: e,
+ viewDate: viewDate.clone()
+ });
+ },
+
showMode = function (dir) {
if (!widget) {
return;
}
if (dir) {
- currentViewMode = Math.max(minViewModeNumber, Math.min(2, currentViewMode + dir));
+ currentViewMode = Math.max(minViewModeNumber, Math.min(3, currentViewMode + dir));
}
widget.find('.datepicker > div').hide().filter('.datepicker-' + datePickerModes[currentViewMode].clsName).show();
},
fillDow = function () {
var row = $('<tr>'),
- currentDate = viewDate.clone().startOf('w');
+ currentDate = viewDate.clone().startOf('w').startOf('d');
if (options.calendarWeeks === true) {
row.append($('<th>').addClass('cw').text('#'));
}
@@ -464,35 +487,61 @@
isInEnabledDates = function (testDate) {
return options.enabledDates[testDate.format('YYYY-MM-DD')] === true;
},
+ isInDisabledHours = function (testDate) {
+ return options.disabledHours[testDate.format('H')] === true;
+ },
+
+ isInEnabledHours = function (testDate) {
+ return options.enabledHours[testDate.format('H')] === true;
+ },
+
isValid = function (targetMoment, granularity) {
if (!targetMoment.isValid()) {
return false;
}
- if (options.disabledDates && isInDisabledDates(targetMoment) && granularity !== 'M') {
+ if (options.disabledDates && granularity === 'd' && isInDisabledDates(targetMoment)) {
return false;
}
- if (options.enabledDates && !isInEnabledDates(targetMoment) && granularity !== 'M') {
+ if (options.enabledDates && granularity === 'd' && !isInEnabledDates(targetMoment)) {
return false;
}
if (options.minDate && targetMoment.isBefore(options.minDate, granularity)) {
return false;
}
if (options.maxDate && targetMoment.isAfter(options.maxDate, granularity)) {
return false;
}
- if (granularity === 'd' && options.daysOfWeekDisabled.indexOf(targetMoment.day()) !== -1) { //widget && widget.find('.datepicker-days').length > 0
+ if (options.daysOfWeekDisabled && granularity === 'd' && options.daysOfWeekDisabled.indexOf(targetMoment.day()) !== -1) {
return false;
}
+ if (options.disabledHours && (granularity === 'h' || granularity === 'm' || granularity === 's') && isInDisabledHours(targetMoment)) {
+ return false;
+ }
+ if (options.enabledHours && (granularity === 'h' || granularity === 'm' || granularity === 's') && !isInEnabledHours(targetMoment)) {
+ return false;
+ }
+ if (options.disabledTimeIntervals && (granularity === 'h' || granularity === 'm' || granularity === 's')) {
+ var found = false;
+ $.each(options.disabledTimeIntervals, function () {
+ if (targetMoment.isBetween(this[0], this[1])) {
+ found = true;
+ return false;
+ }
+ });
+ if (found) {
+ return false;
+ }
+ }
return true;
},
fillMonths = function () {
var spans = [],
- monthsShort = viewDate.clone().startOf('y').hour(12); // hour is changed to avoid DST issues in some browsers
+ monthsShort = viewDate.clone().startOf('y').startOf('d');
while (monthsShort.isSame(viewDate, 'y')) {
spans.push($('<span>').attr('data-action', 'selectMonth').addClass('month').text(monthsShort.format('MMM')));
monthsShort.add(1, 'M');
}
widget.find('.datepicker-months td').empty().append(spans);
@@ -501,10 +550,14 @@
updateMonths = function () {
var monthsView = widget.find('.datepicker-months'),
monthsViewHeader = monthsView.find('th'),
months = monthsView.find('tbody').find('span');
+ monthsViewHeader.eq(0).find('span').attr('title', 'Previous Year');
+ monthsViewHeader.eq(1).attr('title', 'Select Year');
+ monthsViewHeader.eq(2).find('span').attr('title', 'Next Year');
+
monthsView.find('.disabled').removeClass('disabled');
if (!isValid(viewDate.clone().subtract(1, 'y'), 'y')) {
monthsViewHeader.eq(0).addClass('disabled');
}
@@ -514,11 +567,11 @@
if (!isValid(viewDate.clone().add(1, 'y'), 'y')) {
monthsViewHeader.eq(2).addClass('disabled');
}
months.removeClass('active');
- if (date.isSame(viewDate, 'y')) {
+ if (date.isSame(viewDate, 'y') && !unset) {
months.eq(date.month()).addClass('active');
}
months.each(function (index) {
if (!isValid(viewDate.clone().month(index), 'M')) {
@@ -532,10 +585,14 @@
yearsViewHeader = yearsView.find('th'),
startYear = viewDate.clone().subtract(5, 'y'),
endYear = viewDate.clone().add(6, 'y'),
html = '';
+ yearsViewHeader.eq(0).find('span').attr('title', 'Previous Decade');
+ yearsViewHeader.eq(1).attr('title', 'Select Decade');
+ yearsViewHeader.eq(2).find('span').attr('title', 'Next Decade');
+
yearsView.find('.disabled').removeClass('disabled');
if (options.minDate && options.minDate.isAfter(startYear, 'y')) {
yearsViewHeader.eq(0).addClass('disabled');
}
@@ -545,42 +602,79 @@
if (options.maxDate && options.maxDate.isBefore(endYear, 'y')) {
yearsViewHeader.eq(2).addClass('disabled');
}
while (!startYear.isAfter(endYear, 'y')) {
- html += '<span data-action="selectYear" class="year' + (startYear.isSame(date, 'y') ? ' active' : '') + (!isValid(startYear, 'y') ? ' disabled' : '') + '">' + startYear.year() + '</span>';
+ html += '<span data-action="selectYear" class="year' + (startYear.isSame(date, 'y') && !unset ? ' active' : '') + (!isValid(startYear, 'y') ? ' disabled' : '') + '">' + startYear.year() + '</span>';
startYear.add(1, 'y');
}
yearsView.find('td').html(html);
},
+ updateDecades = function () {
+ var decadesView = widget.find('.datepicker-decades'),
+ decadesViewHeader = decadesView.find('th'),
+ startDecade = viewDate.isBefore(moment({y: 1999})) ? moment({y: 1899}) : moment({y: 1999}),
+ endDecade = startDecade.clone().add(100, 'y'),
+ html = '';
+
+ decadesViewHeader.eq(0).find('span').attr('title', 'Previous Century');
+ decadesViewHeader.eq(2).find('span').attr('title', 'Next Century');
+
+ decadesView.find('.disabled').removeClass('disabled');
+
+ if (startDecade.isSame(moment({y: 1900})) || (options.minDate && options.minDate.isAfter(startDecade, 'y'))) {
+ decadesViewHeader.eq(0).addClass('disabled');
+ }
+
+ decadesViewHeader.eq(1).text(startDecade.year() + '-' + endDecade.year());
+
+ if (startDecade.isSame(moment({y: 2000})) || (options.maxDate && options.maxDate.isBefore(endDecade, 'y'))) {
+ decadesViewHeader.eq(2).addClass('disabled');
+ }
+
+ while (!startDecade.isAfter(endDecade, 'y')) {
+ html += '<span data-action="selectDecade" class="decade' + (startDecade.isSame(date, 'y') ? ' active' : '') +
+ (!isValid(startDecade, 'y') ? ' disabled' : '') + '" data-selection="' + (startDecade.year() + 6) + '">' + (startDecade.year() + 1) + ' - ' + (startDecade.year() + 12) + '</span>';
+ startDecade.add(12, 'y');
+ }
+ html += '<span></span><span></span><span></span>'; //push the dangling block over, at least this way it's even
+
+ decadesView.find('td').html(html);
+ },
+
fillDate = function () {
var daysView = widget.find('.datepicker-days'),
daysViewHeader = daysView.find('th'),
currentDate,
html = [],
row,
- clsName;
+ clsName,
+ i;
if (!hasDate()) {
return;
}
+ daysViewHeader.eq(0).find('span').attr('title', 'Previous Month');
+ daysViewHeader.eq(1).attr('title', 'Select Month');
+ daysViewHeader.eq(2).find('span').attr('title', 'Next Month');
+
daysView.find('.disabled').removeClass('disabled');
daysViewHeader.eq(1).text(viewDate.format(options.dayViewHeaderFormat));
if (!isValid(viewDate.clone().subtract(1, 'M'), 'M')) {
daysViewHeader.eq(0).addClass('disabled');
}
if (!isValid(viewDate.clone().add(1, 'M'), 'M')) {
daysViewHeader.eq(2).addClass('disabled');
}
- currentDate = viewDate.clone().startOf('M').startOf('week');
+ currentDate = viewDate.clone().startOf('M').startOf('w').startOf('d');
- while (!viewDate.clone().endOf('M').endOf('w').isBefore(currentDate, 'd')) {
+ for (i = 0; i < 42; i++) { //always display 42 days (should show 6 weeks)
if (currentDate.weekday() === 0) {
row = $('<tr>');
if (options.calendarWeeks) {
row.append('<td class="cw">' + currentDate.week() + '</td>');
}
@@ -603,19 +697,21 @@
clsName += ' today';
}
if (currentDate.day() === 0 || currentDate.day() === 6) {
clsName += ' weekend';
}
- row.append('<td data-action="selectDay" class="day' + clsName + '">' + currentDate.date() + '</td>');
+ row.append('<td data-action="selectDay" data-day="' + currentDate.format('L') + '" class="day' + clsName + '">' + currentDate.date() + '</td>');
currentDate.add(1, 'd');
}
daysView.find('tbody').empty().append(html);
updateMonths();
updateYears();
+
+ updateDecades();
},
fillHours = function () {
var table = widget.find('.timepicker-hours table'),
currentHour = viewDate.clone().startOf('d'),
@@ -671,13 +767,23 @@
table.empty().append(html);
},
fillTime = function () {
- var timeComponents = widget.find('.timepicker span[data-time-component]');
+ var toggle, newDate, timeComponents = widget.find('.timepicker span[data-time-component]');
+
if (!use24Hours) {
- widget.find('.timepicker [data-action=togglePeriod]').text(date.format('A'));
+ toggle = widget.find('.timepicker [data-action=togglePeriod]');
+ newDate = date.clone().add((date.hours() >= 12) ? -12 : 12, 'h');
+
+ toggle.text(date.format('A'));
+
+ if (isValid(newDate, 'h')) {
+ toggle.removeClass('disabled');
+ } else {
+ toggle.addClass('disabled');
+ }
}
timeComponents.filter('[data-time-component=hours]').text(date.format(use24Hours ? 'HH' : 'hh'));
timeComponents.filter('[data-time-component=minutes]').text(date.format('mm'));
timeComponents.filter('[data-time-component=seconds]').text(date.format('ss'));
@@ -702,11 +808,11 @@
unset = true;
input.val('');
element.data('date', '');
notifyEvent({
type: 'dp.change',
- date: null,
+ date: false,
oldDate: oldDate
});
update();
return;
}
@@ -720,12 +826,12 @@
if (isValid(targetMoment)) {
date = targetMoment;
viewDate = date.clone();
input.val(date.format(actualFormat));
element.data('date', date.format(actualFormat));
- update();
unset = false;
+ update();
notifyEvent({
type: 'dp.change',
date: date.clone(),
oldDate: oldDate
});
@@ -739,10 +845,11 @@
});
}
},
hide = function () {
+ ///<summary>Hides the widget. Possibly will emit dp.hide</summary>
var transitioning = false;
if (!widget) {
return picker;
}
// Ignore event if in the middle of a picker transition
@@ -785,17 +892,21 @@
* Widget UI interaction functions
*
********************************************************************************/
actions = {
next: function () {
- viewDate.add(datePickerModes[currentViewMode].navStep, datePickerModes[currentViewMode].navFnc);
+ var navFnc = datePickerModes[currentViewMode].navFnc;
+ viewDate.add(datePickerModes[currentViewMode].navStep, navFnc);
fillDate();
+ viewUpdate(navFnc);
},
previous: function () {
- viewDate.subtract(datePickerModes[currentViewMode].navStep, datePickerModes[currentViewMode].navFnc);
+ var navFnc = datePickerModes[currentViewMode].navFnc;
+ viewDate.subtract(datePickerModes[currentViewMode].navStep, navFnc);
fillDate();
+ viewUpdate(navFnc);
},
pickerSwitch: function () {
showMode(1);
},
@@ -810,10 +921,11 @@
}
} else {
showMode(-1);
fillDate();
}
+ viewUpdate('M');
},
selectYear: function (e) {
var year = parseInt($(e.target).text(), 10) || 0;
viewDate.year(year);
@@ -824,12 +936,28 @@
}
} else {
showMode(-1);
fillDate();
}
+ viewUpdate('YYYY');
},
+ selectDecade: function (e) {
+ var year = parseInt($(e.target).data('selection'), 10) || 0;
+ viewDate.year(year);
+ if (currentViewMode === minViewModeNumber) {
+ setValue(date.clone().year(viewDate.year()));
+ if (!options.inline) {
+ hide();
+ }
+ } else {
+ showMode(-1);
+ fillDate();
+ }
+ viewUpdate('YYYY');
+ },
+
selectDay: function (e) {
var day = viewDate.clone();
if ($(e.target).is('.old')) {
day.subtract(1, 'M');
}
@@ -841,31 +969,49 @@
hide();
}
},
incrementHours: function () {
- setValue(date.clone().add(1, 'h'));
+ var newDate = date.clone().add(1, 'h');
+ if (isValid(newDate, 'h')) {
+ setValue(newDate);
+ }
},
incrementMinutes: function () {
- setValue(date.clone().add(options.stepping, 'm'));
+ var newDate = date.clone().add(options.stepping, 'm');
+ if (isValid(newDate, 'm')) {
+ setValue(newDate);
+ }
},
incrementSeconds: function () {
- setValue(date.clone().add(1, 's'));
+ var newDate = date.clone().add(1, 's');
+ if (isValid(newDate, 's')) {
+ setValue(newDate);
+ }
},
decrementHours: function () {
- setValue(date.clone().subtract(1, 'h'));
+ var newDate = date.clone().subtract(1, 'h');
+ if (isValid(newDate, 'h')) {
+ setValue(newDate);
+ }
},
decrementMinutes: function () {
- setValue(date.clone().subtract(options.stepping, 'm'));
+ var newDate = date.clone().subtract(options.stepping, 'm');
+ if (isValid(newDate, 'm')) {
+ setValue(newDate);
+ }
},
decrementSeconds: function () {
- setValue(date.clone().subtract(1, 's'));
+ var newDate = date.clone().subtract(1, 's');
+ if (isValid(newDate, 's')) {
+ setValue(newDate);
+ }
},
togglePeriod: function () {
setValue(date.clone().add((date.hours() >= 12) ? -12 : 12, 'h'));
},
@@ -951,11 +1097,13 @@
},
clear: clear,
today: function () {
- setValue(moment());
+ if (isValid(moment(), 'd')) {
+ setValue(moment());
+ }
},
close: hide
},
@@ -966,10 +1114,11 @@
actions[$(e.currentTarget).data('action')].apply(picker, arguments);
return false;
},
show = function () {
+ ///<summary>Shows the widget. Possibly will emit dp.show and dp.change</summary>
var currentMoment,
useCurrentGranularity = {
'year': function (m) {
return m.month(0).date(1).hours(0).seconds(0).minutes(0);
},
@@ -988,11 +1137,13 @@
};
if (input.prop('disabled') || (!options.ignoreReadonly && input.prop('readonly')) || widget) {
return picker;
}
- if (options.useCurrent && unset && ((input.is('input') && input.val().trim().length === 0) || options.inline)) {
+ if (input.val() !== undefined && input.val().trim().length !== 0) {
+ setValue(parseInputDate(input.val().trim()));
+ } else if (options.useCurrent && unset && ((input.is('input') && input.val().trim().length === 0) || options.inline)) {
currentMoment = moment();
if (typeof options.useCurrent === 'string') {
currentMoment = useCurrentGranularity[options.useCurrent](currentMoment);
}
setValue(currentMoment);
@@ -1018,45 +1169,40 @@
component.toggleClass('active');
}
widget.show();
place();
- if (!input.is(':focus')) {
+ if (options.focusOnShow && !input.is(':focus')) {
input.focus();
}
notifyEvent({
type: 'dp.show'
});
return picker;
},
toggle = function () {
+ /// <summary>Shows or hides the widget</summary>
return (widget ? hide() : show());
},
parseInputDate = function (inputDate) {
- if (moment.isMoment(inputDate) || inputDate instanceof Date) {
- inputDate = moment(inputDate);
+ if (options.parseInputDate === undefined) {
+ if (moment.isMoment(inputDate) || inputDate instanceof Date) {
+ inputDate = moment(inputDate);
+ } else {
+ inputDate = moment(inputDate, parseFormats, options.useStrict);
+ }
} else {
- inputDate = moment(inputDate, parseFormats, options.useStrict);
+ inputDate = options.parseInputDate(inputDate);
}
inputDate.locale(options.locale);
return inputDate;
},
keydown = function (e) {
- //if (e.keyCode === 27 && widget) { // allow escape to hide picker
- // hide();
- // return false;
- //}
- //if (e.keyCode === 40 && !widget) { // allow down to show picker
- // show();
- // e.preventDefault();
- //}
- //return true;
-
var handler = null,
index,
index2,
pressedKeys = [],
pressedModifiers = {},
@@ -1119,11 +1265,12 @@
attachDatePickerElementEvents = function () {
input.on({
'change': change,
'blur': options.debug ? '' : hide,
'keydown': keydown,
- 'keyup': keyup
+ 'keyup': keyup,
+ 'focus': options.allowInputToggle ? show : ''
});
if (element.is('input')) {
input.on({
'focus': show
@@ -1137,11 +1284,12 @@
detachDatePickerElementEvents = function () {
input.off({
'change': change,
'blur': hide,
'keydown': keydown,
- 'keyup': keyup
+ 'keyup': keyup,
+ 'focus': options.allowInputToggle ? hide : ''
});
if (element.is('input')) {
input.off({
'focus': show
@@ -1164,10 +1312,21 @@
}
});
return (Object.keys(givenDatesIndexed).length) ? givenDatesIndexed : false;
},
+ indexGivenHours = function (givenHoursArray) {
+ // Store given enabledHours and disabledHours as keys.
+ // This way we can check their existence in O(1) time instead of looping through whole array.
+ // (for example: options.enabledHours['2014-02-27'] === true)
+ var givenHoursIndexed = {};
+ $.each(givenHoursArray, function () {
+ givenHoursIndexed[this] = true;
+ });
+ return (Object.keys(givenHoursIndexed).length) ? givenHoursIndexed : false;
+ },
+
initFormatting = function () {
var format = options.format || 'L LT';
actualFormat = format.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput) {
var newinput = date.localeData().longDateFormat(formatInput) || formatInput;
@@ -1180,11 +1339,11 @@
parseFormats = options.extraFormats ? options.extraFormats.slice() : [];
if (parseFormats.indexOf(format) < 0 && parseFormats.indexOf(actualFormat) < 0) {
parseFormats.push(actualFormat);
}
- use24Hours = (actualFormat.toLowerCase().indexOf('a') < 1 && actualFormat.indexOf('h') < 1);
+ use24Hours = (actualFormat.toLowerCase().indexOf('a') < 1 && actualFormat.replace(/\[.*?\]/g, '').indexOf('h') < 1);
if (isEnabled('y')) {
minViewModeNumber = 2;
}
if (isEnabled('M')) {
@@ -1210,10 +1369,11 @@
* object to the outer world. Always return a clone when returning values or make
* a clone when setting a private variable.
*
********************************************************************************/
picker.destroy = function () {
+ ///<summary>Destroys the widget and removes all attached event listeners</summary>
hide();
detachDatePickerElementEvents();
element.removeData('DateTimePicker');
element.removeData('date');
};
@@ -1223,19 +1383,22 @@
picker.show = show;
picker.hide = hide;
picker.disable = function () {
+ ///<summary>Disables the input element, the component is attached to, by adding a disabled="true" attribute to it.
+ ///If the widget was visible before that call it is hidden. Possibly emits dp.hide</summary>
hide();
if (component && component.hasClass('btn')) {
component.addClass('disabled');
}
input.prop('disabled', true);
return picker;
};
picker.enable = function () {
+ ///<summary>Enables the input element, the component is attached to, by removing disabled attribute from it.</summary>
if (component && component.hasClass('btn')) {
component.removeClass('disabled');
}
input.prop('disabled', false);
return picker;
@@ -1270,10 +1433,18 @@
});
return picker;
};
picker.date = function (newDate) {
+ ///<signature helpKeyword="$.fn.datetimepicker.date">
+ ///<summary>Returns the component's model current date, a moment object or null if not set.</summary>
+ ///<returns type="Moment">date.clone()</returns>
+ ///</signature>
+ ///<signature>
+ ///<summary>Sets the components model current moment to it. Passing a null value unsets the components model current moment. Parsing of the newDate parameter is made using moment library with the options.format and options.useStrict components configuration.</summary>
+ ///<param name="newDate" locid="$.fn.datetimepicker.date_p:newDate">Takes string, Date, moment, null parameter.</param>
+ ///</signature>
if (arguments.length === 0) {
if (unset) {
return null;
}
return date.clone();
@@ -1286,10 +1457,13 @@
setValue(newDate === null ? null : parseInputDate(newDate));
return picker;
};
picker.format = function (newFormat) {
+ ///<summary>test su</summary>
+ ///<param name="newFormat">info about para</param>
+ ///<returns type="string|boolean">returns foo</returns>
if (arguments.length === 0) {
return options.format;
}
if ((typeof newFormat !== 'string') && ((typeof newFormat !== 'boolean') || (newFormat !== false))) {
@@ -1331,10 +1505,19 @@
}
return picker;
};
picker.disabledDates = function (dates) {
+ ///<signature helpKeyword="$.fn.datetimepicker.disabledDates">
+ ///<summary>Returns an array with the currently set disabled dates on the component.</summary>
+ ///<returns type="array">options.disabledDates</returns>
+ ///</signature>
+ ///<signature>
+ ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of
+ ///options.enabledDates if such exist.</summary>
+ ///<param name="dates" locid="$.fn.datetimepicker.disabledDates_p:dates">Takes an [ string or Date or moment ] of values and allows the user to select only from those days.</param>
+ ///</signature>
if (arguments.length === 0) {
return (options.disabledDates ? $.extend({}, options.disabledDates) : options.disabledDates);
}
if (!dates) {
@@ -1350,10 +1533,18 @@
update();
return picker;
};
picker.enabledDates = function (dates) {
+ ///<signature helpKeyword="$.fn.datetimepicker.enabledDates">
+ ///<summary>Returns an array with the currently set enabled dates on the component.</summary>
+ ///<returns type="array">options.enabledDates</returns>
+ ///</signature>
+ ///<signature>
+ ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of options.disabledDates if such exist.</summary>
+ ///<param name="dates" locid="$.fn.datetimepicker.enabledDates_p:dates">Takes an [ string or Date or moment ] of values and allows the user to select only from those days.</param>
+ ///</signature>
if (arguments.length === 0) {
return (options.enabledDates ? $.extend({}, options.enabledDates) : options.enabledDates);
}
if (!dates) {
@@ -1373,10 +1564,16 @@
picker.daysOfWeekDisabled = function (daysOfWeekDisabled) {
if (arguments.length === 0) {
return options.daysOfWeekDisabled.splice(0);
}
+ if ((typeof daysOfWeekDisabled === 'boolean') && !daysOfWeekDisabled) {
+ options.daysOfWeekDisabled = false;
+ update();
+ return picker;
+ }
+
if (!(daysOfWeekDisabled instanceof Array)) {
throw new TypeError('daysOfWeekDisabled() expects an array parameter');
}
options.daysOfWeekDisabled = daysOfWeekDisabled.reduce(function (previousValue, currentValue) {
currentValue = parseInt(currentValue, 10);
@@ -1386,10 +1583,21 @@
if (previousValue.indexOf(currentValue) === -1) {
previousValue.push(currentValue);
}
return previousValue;
}, []).sort();
+ if (options.useCurrent && !options.keepInvalid) {
+ var tries = 0;
+ while (!isValid(date, 'd')) {
+ date.add(1, 'd');
+ if (tries === 7) {
+ throw 'Tried 7 times to find a valid date';
+ }
+ tries++;
+ }
+ setValue(date);
+ }
update();
return picker;
};
picker.maxDate = function (maxDate) {
@@ -1416,11 +1624,11 @@
}
if (options.minDate && parsedDate.isBefore(options.minDate)) {
throw new TypeError('maxDate() date parameter is before options.minDate: ' + parsedDate.format(actualFormat));
}
options.maxDate = parsedDate;
- if (options.maxDate.isBefore(maxDate)) {
+ if (options.useCurrent && !options.keepInvalid && date.isAfter(maxDate)) {
setValue(options.maxDate);
}
if (viewDate.isAfter(parsedDate)) {
viewDate = parsedDate.clone();
}
@@ -1452,21 +1660,29 @@
}
if (options.maxDate && parsedDate.isAfter(options.maxDate)) {
throw new TypeError('minDate() date parameter is after options.maxDate: ' + parsedDate.format(actualFormat));
}
options.minDate = parsedDate;
- if (options.minDate.isAfter(minDate)) {
+ if (options.useCurrent && !options.keepInvalid && date.isBefore(minDate)) {
setValue(options.minDate);
}
if (viewDate.isBefore(parsedDate)) {
viewDate = parsedDate.clone();
}
update();
return picker;
};
picker.defaultDate = function (defaultDate) {
+ ///<signature helpKeyword="$.fn.datetimepicker.defaultDate">
+ ///<summary>Returns a moment with the options.defaultDate option configuration or false if not set</summary>
+ ///<returns type="Moment">date.clone()</returns>
+ ///</signature>
+ ///<signature>
+ ///<summary>Will set the picker's inital date. If a boolean:false value is passed the options.defaultDate parameter is cleared.</summary>
+ ///<param name="defaultDate" locid="$.fn.datetimepicker.defaultDate_p:defaultDate">Takes a string, Date, moment, boolean:false</param>
+ ///</signature>
if (arguments.length === 0) {
return options.defaultDate ? options.defaultDate.clone() : options.defaultDate;
}
if (!defaultDate) {
options.defaultDate = false;
@@ -1487,11 +1703,11 @@
throw new TypeError('defaultDate() date passed is invalid according to component setup validations');
}
options.defaultDate = parsedDate;
- if (options.defaultDate && input.val().trim() === '' && input.attr('placeholder') === undefined) {
+ if (options.defaultDate && options.inline || (input.val().trim() === '' && input.attr('placeholder') === undefined)) {
setValue(options.defaultDate);
}
return picker;
};
@@ -1762,10 +1978,23 @@
options.keepOpen = keepOpen;
return picker;
};
+ picker.focusOnShow = function (focusOnShow) {
+ if (arguments.length === 0) {
+ return options.focusOnShow;
+ }
+
+ if (typeof focusOnShow !== 'boolean') {
+ throw new TypeError('focusOnShow() expects a boolean parameter');
+ }
+
+ options.focusOnShow = focusOnShow;
+ return picker;
+ };
+
picker.inline = function (inline) {
if (arguments.length === 0) {
return options.inline;
}
@@ -1794,10 +2023,23 @@
options.debug = debug;
return picker;
};
+ picker.allowInputToggle = function (allowInputToggle) {
+ if (arguments.length === 0) {
+ return options.allowInputToggle;
+ }
+
+ if (typeof allowInputToggle !== 'boolean') {
+ throw new TypeError('allowInputToggle() expects a boolean parameter');
+ }
+
+ options.allowInputToggle = allowInputToggle;
+ return picker;
+ };
+
picker.showClose = function (showClose) {
if (arguments.length === 0) {
return options.showClose;
}
@@ -1832,10 +2074,155 @@
options.datepickerInput = datepickerInput;
return picker;
};
+ picker.parseInputDate = function (parseInputDate) {
+ if (arguments.length === 0) {
+ return options.parseInputDate;
+ }
+
+ if (typeof parseInputDate !== 'function') {
+ throw new TypeError('parseInputDate() sholud be as function');
+ }
+
+ options.parseInputDate = parseInputDate;
+
+ return picker;
+ };
+
+ picker.disabledTimeIntervals = function (disabledTimeIntervals) {
+ ///<signature helpKeyword="$.fn.datetimepicker.disabledTimeIntervals">
+ ///<summary>Returns an array with the currently set disabled dates on the component.</summary>
+ ///<returns type="array">options.disabledTimeIntervals</returns>
+ ///</signature>
+ ///<signature>
+ ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of
+ ///options.enabledDates if such exist.</summary>
+ ///<param name="dates" locid="$.fn.datetimepicker.disabledTimeIntervals_p:dates">Takes an [ string or Date or moment ] of values and allows the user to select only from those days.</param>
+ ///</signature>
+ if (arguments.length === 0) {
+ return (options.disabledTimeIntervals ? $.extend({}, options.disabledTimeIntervals) : options.disabledTimeIntervals);
+ }
+
+ if (!disabledTimeIntervals) {
+ options.disabledTimeIntervals = false;
+ update();
+ return picker;
+ }
+ if (!(disabledTimeIntervals instanceof Array)) {
+ throw new TypeError('disabledTimeIntervals() expects an array parameter');
+ }
+ options.disabledTimeIntervals = disabledTimeIntervals;
+ update();
+ return picker;
+ };
+
+ picker.disabledHours = function (hours) {
+ ///<signature helpKeyword="$.fn.datetimepicker.disabledHours">
+ ///<summary>Returns an array with the currently set disabled hours on the component.</summary>
+ ///<returns type="array">options.disabledHours</returns>
+ ///</signature>
+ ///<signature>
+ ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of
+ ///options.enabledHours if such exist.</summary>
+ ///<param name="hours" locid="$.fn.datetimepicker.disabledHours_p:hours">Takes an [ int ] of values and disallows the user to select only from those hours.</param>
+ ///</signature>
+ if (arguments.length === 0) {
+ return (options.disabledHours ? $.extend({}, options.disabledHours) : options.disabledHours);
+ }
+
+ if (!hours) {
+ options.disabledHours = false;
+ update();
+ return picker;
+ }
+ if (!(hours instanceof Array)) {
+ throw new TypeError('disabledHours() expects an array parameter');
+ }
+ options.disabledHours = indexGivenHours(hours);
+ options.enabledHours = false;
+ if (options.useCurrent && !options.keepInvalid) {
+ var tries = 0;
+ while (!isValid(date, 'h')) {
+ date.add(1, 'h');
+ if (tries === 24) {
+ throw 'Tried 24 times to find a valid date';
+ }
+ tries++;
+ }
+ setValue(date);
+ }
+ update();
+ return picker;
+ };
+
+ picker.enabledHours = function (hours) {
+ ///<signature helpKeyword="$.fn.datetimepicker.enabledHours">
+ ///<summary>Returns an array with the currently set enabled hours on the component.</summary>
+ ///<returns type="array">options.enabledHours</returns>
+ ///</signature>
+ ///<signature>
+ ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of options.disabledHours if such exist.</summary>
+ ///<param name="hours" locid="$.fn.datetimepicker.enabledHours_p:hours">Takes an [ int ] of values and allows the user to select only from those hours.</param>
+ ///</signature>
+ if (arguments.length === 0) {
+ return (options.enabledHours ? $.extend({}, options.enabledHours) : options.enabledHours);
+ }
+
+ if (!hours) {
+ options.enabledHours = false;
+ update();
+ return picker;
+ }
+ if (!(hours instanceof Array)) {
+ throw new TypeError('enabledHours() expects an array parameter');
+ }
+ options.enabledHours = indexGivenHours(hours);
+ options.disabledHours = false;
+ if (options.useCurrent && !options.keepInvalid) {
+ var tries = 0;
+ while (!isValid(date, 'h')) {
+ date.add(1, 'h');
+ if (tries === 24) {
+ throw 'Tried 24 times to find a valid date';
+ }
+ tries++;
+ }
+ setValue(date);
+ }
+ update();
+ return picker;
+ };
+
+ picker.viewDate = function (newDate) {
+ ///<signature helpKeyword="$.fn.datetimepicker.viewDate">
+ ///<summary>Returns the component's model current viewDate, a moment object or null if not set.</summary>
+ ///<returns type="Moment">viewDate.clone()</returns>
+ ///</signature>
+ ///<signature>
+ ///<summary>Sets the components model current moment to it. Passing a null value unsets the components model current moment. Parsing of the newDate parameter is made using moment library with the options.format and options.useStrict components configuration.</summary>
+ ///<param name="newDate" locid="$.fn.datetimepicker.date_p:newDate">Takes string, viewDate, moment, null parameter.</param>
+ ///</signature>
+ if (arguments.length === 0) {
+ return viewDate.clone();
+ }
+
+ if (!newDate) {
+ viewDate = date.clone();
+ return picker;
+ }
+
+ if (typeof newDate !== 'string' && !moment.isMoment(newDate) && !(newDate instanceof Date)) {
+ throw new TypeError('viewDate() parameter must be one of [string, moment or Date]');
+ }
+
+ viewDate = parseInputDate(newDate);
+ viewUpdate();
+ return picker;
+ };
+
// initializing element and component attributes
if (element.is('input')) {
input = element;
} else {
input = element.find(options.datepickerInput);
@@ -1923,11 +2310,11 @@
clear: 'glyphicon glyphicon-trash',
close: 'glyphicon glyphicon-remove'
},
useStrict: false,
sideBySide: false,
- daysOfWeekDisabled: [],
+ daysOfWeekDisabled: false,
calendarWeeks: false,
viewMode: 'days',
toolbarPlacement: 'default',
showTodayButton: false,
showClear: false,
@@ -1937,10 +2324,11 @@
vertical: 'auto'
},
widgetParent: null,
ignoreReadonly: false,
keepOpen: false,
+ focusOnShow: true,
inline: false,
keepInvalid: false,
datepickerInput: '.datepickerinput',
keyBinds: {
up: function (widget) {
@@ -2044,8 +2432,13 @@
},
'delete': function () {
this.clear();
}
},
- debug: false
+ debug: false,
+ allowInputToggle: false,
+ disabledTimeIntervals: false,
+ disabledHours: false,
+ enabledHours: false,
+ viewDate: false
};
}));