vendor/assets/javascripts/bootstrap-datetimepicker.js in bootstrap3-datetimepicker-rails-4.17.37 vs vendor/assets/javascripts/bootstrap-datetimepicker.js in bootstrap3-datetimepicker-rails-4.17.42
- old
+ new
@@ -1,6 +1,6 @@
-/*! version : 4.17.37
+/*! version : 4.17.42
=========================================================
bootstrap-datetimejs
https://github.com/Eonasdan/bootstrap-datetimepicker
Copyright (c) 2015 Jonathan Peterson
=========================================================
@@ -37,11 +37,11 @@
'use strict';
if (typeof define === 'function' && define.amd) {
// AMD is used - Register as an anonymous module.
define(['jquery', 'moment'], factory);
} else if (typeof exports === 'object') {
- factory(require('jquery'), require('moment'));
+ module.exports = factory(require('jquery'), require('moment'));
} else {
// Neither AMD nor CommonJS used. Use global variables.
if (typeof jQuery === 'undefined') {
throw 'bootstrap-datetimepicker requires jQuery to be loaded first';
}
@@ -130,44 +130,34 @@
/********************************************************************************
*
* Private functions
*
********************************************************************************/
+
+ hasTimeZone = function () {
+ return moment.tz !== undefined && options.timeZone !== undefined && options.timeZone !== null && options.timeZone !== '';
+ },
+
getMoment = function (d) {
- var tzEnabled = false,
- returnMoment,
- currentZoneOffset,
- incomingZoneOffset,
- timeZoneIndicator,
- dateWithTimeZoneInfo;
+ var returnMoment;
- if (moment.tz !== undefined && options.timeZone !== undefined && options.timeZone !== null && options.timeZone !== '') {
- tzEnabled = true;
- }
if (d === undefined || d === null) {
- if (tzEnabled) {
- returnMoment = moment().tz(options.timeZone).startOf('d');
- } else {
- returnMoment = moment().startOf('d');
- }
+ returnMoment = moment(); //TODO should this use format? and locale?
+ } else if (hasTimeZone()) { // There is a string to parse and a default time zone
+ // parse with the tz function which takes a default time zone if it is not in the format string
+ returnMoment = moment.tz(d, parseFormats, options.useStrict, options.timeZone);
} else {
- if (tzEnabled) {
- currentZoneOffset = moment().tz(options.timeZone).utcOffset();
- incomingZoneOffset = moment(d, parseFormats, options.useStrict).utcOffset();
- if (incomingZoneOffset !== currentZoneOffset) {
- timeZoneIndicator = moment().tz(options.timeZone).format('Z');
- dateWithTimeZoneInfo = moment(d, parseFormats, options.useStrict).format('YYYY-MM-DD[T]HH:mm:ss') + timeZoneIndicator;
- returnMoment = moment(dateWithTimeZoneInfo, parseFormats, options.useStrict).tz(options.timeZone);
- } else {
- returnMoment = moment(d, parseFormats, options.useStrict).tz(options.timeZone);
- }
- } else {
- returnMoment = moment(d, parseFormats, options.useStrict);
- }
+ returnMoment = moment(d, parseFormats, options.useStrict);
}
+
+ if (hasTimeZone()) {
+ returnMoment.tz(options.timeZone);
+ }
+
return returnMoment;
},
+
isEnabled = function (granularity) {
if (typeof granularity !== 'string' || granularity.length > 1) {
throw new TypeError('isEnabled expects a single character string parameter');
}
switch (granularity) {
@@ -186,10 +176,11 @@
return actualFormat.indexOf('s') !== -1;
default:
return false;
}
},
+
hasTime = function () {
return (isEnabled('h') || isEnabled('m') || isEnabled('s'));
},
hasDate = function () {
@@ -241,53 +232,51 @@
middleRow = $('<tr>'),
bottomRow = $('<tr>');
if (isEnabled('h')) {
topRow.append($('<td>')
- .append($('<a>').attr({href: '#', tabindex: '-1', 'title': options.tooltips.incrementHour}).addClass('btn').attr('data-action', 'incrementHours')
- .append($('<span>').addClass(options.icons.up))));
+ .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.incrementHour }).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', 'title': options.tooltips.pickHour}).attr('data-action', 'showHours')));
+ .append($('<span>').addClass('timepicker-hour').attr({ 'data-time-component': 'hours', 'title': options.tooltips.pickHour }).attr('data-action', 'showHours')));
bottomRow.append($('<td>')
- .append($('<a>').attr({href: '#', tabindex: '-1', 'title': options.tooltips.decrementHour}).addClass('btn').attr('data-action', 'decrementHours')
- .append($('<span>').addClass(options.icons.down))));
+ .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.decrementHour }).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', 'title': options.tooltips.incrementMinute}).addClass('btn').attr('data-action', 'incrementMinutes')
+ .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.incrementMinute }).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', 'title': options.tooltips.pickMinute}).attr('data-action', 'showMinutes')));
+ .append($('<span>').addClass('timepicker-minute').attr({ 'data-time-component': 'minutes', 'title': options.tooltips.pickMinute }).attr('data-action', 'showMinutes')));
bottomRow.append($('<td>')
- .append($('<a>').attr({href: '#', tabindex: '-1', 'title': options.tooltips.decrementMinute}).addClass('btn').attr('data-action', 'decrementMinutes')
+ .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.decrementMinute }).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', 'title': options.tooltips.incrementSecond}).addClass('btn').attr('data-action', 'incrementSeconds')
+ .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.incrementSecond }).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', 'title': options.tooltips.pickSecond}).attr('data-action', 'showSeconds')));
+ .append($('<span>').addClass('timepicker-second').attr({ 'data-time-component': 'seconds', 'title': options.tooltips.pickSecond }).attr('data-action', 'showSeconds')));
bottomRow.append($('<td>')
- .append($('<a>').attr({href: '#', tabindex: '-1', 'title': options.tooltips.decrementSecond}).addClass('btn').attr('data-action', 'decrementSeconds')
+ .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.decrementSecond }).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', tabindex: '-1', 'title': options.tooltips.togglePeriod})));
+ .append($('<button>').addClass('btn btn-primary').attr({ 'data-action': 'togglePeriod', tabindex: '-1', 'title': options.tooltips.togglePeriod })));
bottomRow.append($('<td>').addClass('separator'));
}
return $('<div>').addClass('timepicker-picker')
.append($('<table>').addClass('table-condensed')
@@ -317,20 +306,20 @@
},
getToolbar = function () {
var row = [];
if (options.showTodayButton) {
- row.push($('<td>').append($('<a>').attr({'data-action':'today', 'title': options.tooltips.today}).append($('<span>').addClass(options.icons.today))));
+ row.push($('<td>').append($('<a>').attr({ 'data-action': 'today', 'title': options.tooltips.today }).append($('<span>').addClass(options.icons.today))));
}
if (!options.sideBySide && hasDate() && hasTime()) {
- row.push($('<td>').append($('<a>').attr({'data-action':'togglePicker', 'title': options.tooltips.selectTime}).append($('<span>').addClass(options.icons.time))));
+ row.push($('<td>').append($('<a>').attr({ 'data-action': 'togglePicker', 'title': options.tooltips.selectTime }).append($('<span>').addClass(options.icons.time))));
}
if (options.showClear) {
- row.push($('<td>').append($('<a>').attr({'data-action':'clear', 'title': options.tooltips.clear}).append($('<span>').addClass(options.icons.clear))));
+ row.push($('<td>').append($('<a>').attr({ 'data-action': 'clear', 'title': options.tooltips.clear }).append($('<span>').addClass(options.icons.clear))));
}
if (options.showClose) {
- row.push($('<td>').append($('<a>').attr({'data-action':'close', 'title': options.tooltips.close}).append($('<span>').addClass(options.icons.close))));
+ row.push($('<td>').append($('<a>').attr({ 'data-action': 'close', 'title': options.tooltips.close }).append($('<span>').addClass(options.icons.close))));
}
return $('<table>').addClass('table-condensed').append($('<tbody>').append($('<tr>').append(row)));
},
getTemplate = function () {
@@ -470,11 +459,11 @@
throw new Error('datetimepicker component should be placed within a relative positioned container');
}
widget.css({
top: vertical === 'top' ? 'auto' : position.top + element.outerHeight(),
- bottom: vertical === 'top' ? position.top + element.outerHeight() : 'auto',
+ bottom: vertical === 'top' ? parent.outerHeight() - (parent === element ? 0 : position.top) : 'auto',
left: horizontal === 'left' ? (parent === element ? 0 : position.left) : 'auto',
right: horizontal === 'left' ? 'auto' : parent.outerWidth() - element.outerWidth() - (parent === element ? 0 : position.left)
});
},
@@ -652,33 +641,39 @@
},
updateDecades = function () {
var decadesView = widget.find('.datepicker-decades'),
decadesViewHeader = decadesView.find('th'),
- startDecade = moment({y: viewDate.year() - (viewDate.year() % 100) - 1}),
+ startDecade = moment({ y: viewDate.year() - (viewDate.year() % 100) - 1 }),
endDecade = startDecade.clone().add(100, 'y'),
startedAt = startDecade.clone(),
+ minDateDecade = false,
+ maxDateDecade = false,
+ endDecadeYear,
html = '';
decadesViewHeader.eq(0).find('span').attr('title', options.tooltips.prevCentury);
decadesViewHeader.eq(2).find('span').attr('title', options.tooltips.nextCentury);
decadesView.find('.disabled').removeClass('disabled');
- if (startDecade.isSame(moment({y: 1900})) || (options.minDate && options.minDate.isAfter(startDecade, 'y'))) {
+ 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'))) {
+ 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>';
+ endDecadeYear = startDecade.year() + 12;
+ minDateDecade = options.minDate && options.minDate.isAfter(startDecade, 'y') && options.minDate.year() <= endDecadeYear;
+ maxDateDecade = options.maxDate && options.maxDate.isAfter(startDecade, 'y') && options.maxDate.year() <= endDecadeYear;
+ html += '<span data-action="selectDecade" class="decade' + (date.isAfter(startDecade) && date.year() <= endDecadeYear ? ' active' : '') +
+ (!isValid(startDecade, 'y') && !minDateDecade && !maxDateDecade ? ' 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);
@@ -859,17 +854,21 @@
return;
}
targetMoment = targetMoment.clone().locale(options.locale);
+ if (hasTimeZone()) {
+ targetMoment.tz(options.timeZone);
+ }
+
if (options.stepping !== 1) {
- targetMoment.minutes((Math.round(targetMoment.minutes() / options.stepping) * options.stepping) % 60).seconds(0);
+ targetMoment.minutes((Math.round(targetMoment.minutes() / options.stepping) * options.stepping)).seconds(0);
}
if (isValid(targetMoment)) {
date = targetMoment;
- viewDate = date.clone();
+ //viewDate = date.clone(); // TODO this doesn't work right on first use
input.val(date.format(actualFormat));
element.data('date', date.format(actualFormat));
unset = false;
update();
notifyEvent({
@@ -878,20 +877,29 @@
oldDate: oldDate
});
} else {
if (!options.keepInvalid) {
input.val(unset ? '' : date.format(actualFormat));
+ } else {
+ notifyEvent({
+ type: 'dp.change',
+ date: targetMoment,
+ oldDate: oldDate
+ });
}
notifyEvent({
type: 'dp.error',
- date: targetMoment
+ date: targetMoment,
+ oldDate: oldDate
});
}
},
+ /**
+ * Hides the widget. Possibly will emit dp.hide
+ */
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
@@ -923,17 +931,32 @@
date: date.clone()
});
input.blur();
+ currentViewMode = 0;
+ viewDate = date.clone();
+
return picker;
},
clear = function () {
setValue(null);
},
+ parseInputDate = function (inputDate) {
+ if (options.parseInputDate === undefined) {
+ if (!moment.isMoment(inputDate)) {
+ inputDate = getMoment(inputDate);
+ }
+ } else {
+ inputDate = options.parseInputDate(inputDate);
+ }
+ //inputDate.locale(options.locale);
+ return inputDate;
+ },
+
/********************************************************************************
*
* Widget UI interaction functions
*
********************************************************************************/
@@ -1159,12 +1182,14 @@
}
actions[$(e.currentTarget).data('action')].apply(picker, arguments);
return false;
},
+ /**
+ * Shows the widget. Possibly will emit dp.show and dp.change
+ */
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);
},
@@ -1185,18 +1210,17 @@
if (input.prop('disabled') || (!options.ignoreReadonly && input.prop('readonly')) || widget) {
return picker;
}
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)) {
+ } else if (unset && options.useCurrent && (options.inline || (input.is('input') && input.val().trim().length === 0))) {
currentMoment = getMoment();
if (typeof options.useCurrent === 'string') {
currentMoment = useCurrentGranularity[options.useCurrent](currentMoment);
}
setValue(currentMoment);
}
-
widget = getTemplate();
fillDow();
fillMonths();
@@ -1212,42 +1236,29 @@
widget.on('mousedown', false);
if (component && component.hasClass('btn')) {
component.toggleClass('active');
}
- widget.show();
place();
-
+ widget.show();
if (options.focusOnShow && !input.is(':focus')) {
input.focus();
}
notifyEvent({
type: 'dp.show'
});
return picker;
},
+ /**
+ * Shows or hides the widget
+ */
toggle = function () {
- /// <summary>Shows or hides the widget</summary>
return (widget ? hide() : show());
},
- parseInputDate = function (inputDate) {
- if (options.parseInputDate === undefined) {
- if (moment.isMoment(inputDate) || inputDate instanceof Date) {
- inputDate = moment(inputDate);
- } else {
- inputDate = getMoment(inputDate);
- }
- } else {
- inputDate = options.parseInputDate(inputDate);
- }
- inputDate.locale(options.locale);
- return inputDate;
- },
-
keydown = function (e) {
var handler = null,
index,
index2,
pressedKeys = [],
@@ -1511,11 +1522,11 @@
if (arguments.length === 0) {
return options.format;
}
if ((typeof newFormat !== 'string') && ((typeof newFormat !== 'boolean') || (newFormat !== false))) {
- throw new TypeError('format() expects a sting or boolean:false parameter ' + newFormat);
+ throw new TypeError('format() expects a string or boolean:false parameter ' + newFormat);
}
options.format = newFormat;
if (actualFormat) {
initFormatting(); // reinit formatting
@@ -1526,10 +1537,14 @@
picker.timeZone = function (newZone) {
if (arguments.length === 0) {
return options.timeZone;
}
+ if (typeof newZone !== 'string') {
+ throw new TypeError('newZone() expects a string parameter');
+ }
+
options.timeZone = newZone;
return picker;
};
@@ -1643,12 +1658,12 @@
}, []).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';
+ if (tries === 31) {
+ throw 'Tried 31 times to find a valid date';
}
tries++;
}
setValue(date);
}
@@ -1746,10 +1761,12 @@
}
if (typeof defaultDate === 'string') {
if (defaultDate === 'now' || defaultDate === 'moment') {
defaultDate = getMoment();
+ } else {
+ defaultDate = getMoment(defaultDate);
}
}
var parsedDate = parseInputDate(defaultDate);
if (!parsedDate.isValid()) {
@@ -2082,10 +2099,14 @@
clear();
return picker;
};
picker.keyBinds = function (keyBinds) {
+ if (arguments.length === 0) {
+ return options.keyBinds;
+ }
+
options.keyBinds = keyBinds;
return picker;
};
picker.getMoment = function (d) {
@@ -2267,20 +2288,16 @@
setValue(date);
}
update();
return picker;
};
-
+ /**
+ * Returns the component's model current viewDate, a moment object or null if not set. 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.
+ * @param {Takes string, viewDate, moment, null parameter.} newDate
+ * @returns {viewDate.clone()}
+ */
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) {
@@ -2300,20 +2317,20 @@
// initializing element and component attributes
if (element.is('input')) {
input = element;
} else {
input = element.find(options.datepickerInput);
- if (input.size() === 0) {
+ if (input.length === 0) {
input = element.find('input');
} else if (!input.is('input')) {
throw new Error('CSS class "' + options.datepickerInput + '" cannot be applied to non input element');
}
}
if (element.hasClass('input-group')) {
// in case there is more then one 'input-group-addon' Issue #48
- if (element.find('.datepickerbutton').size() === 0) {
+ if (element.find('.datepickerbutton').length === 0) {
component = element.find('.input-group-addon');
} else {
component = element.find('.datepickerbutton');
}
}
@@ -2353,23 +2370,71 @@
*
* jQuery plugin constructor and defaults object
*
********************************************************************************/
+ /**
+ * See (http://jquery.com/).
+ * @name jQuery
+ * @class
+ * See the jQuery Library (http://jquery.com/) for full details. This just
+ * documents the function and classes that are added to jQuery by this plug-in.
+ */
+ /**
+ * See (http://jquery.com/)
+ * @name fn
+ * @class
+ * See the jQuery Library (http://jquery.com/) for full details. This just
+ * documents the function and classes that are added to jQuery by this plug-in.
+ * @memberOf jQuery
+ */
+ /**
+ * Show comments
+ * @class datetimepicker
+ * @memberOf jQuery.fn
+ */
$.fn.datetimepicker = function (options) {
- return this.each(function () {
- var $this = $(this);
- if (!$this.data('DateTimePicker')) {
- // create a private copy of the defaults object
- options = $.extend(true, {}, $.fn.datetimepicker.defaults, options);
- $this.data('DateTimePicker', dateTimePicker($this, options));
+ options = options || {};
+
+ var args = Array.prototype.slice.call(arguments, 1),
+ isInstance = true,
+ thisMethods = ['destroy', 'hide', 'show', 'toggle'],
+ returnValue;
+
+ if (typeof options === 'object') {
+ return this.each(function () {
+ var $this = $(this);
+ if (!$this.data('DateTimePicker')) {
+ // create a private copy of the defaults object
+ options = $.extend(true, {}, $.fn.datetimepicker.defaults, options);
+ $this.data('DateTimePicker', dateTimePicker($this, options));
+ }
+ });
+ } else if (typeof options === 'string') {
+ this.each(function () {
+ var $this = $(this),
+ instance = $this.data('DateTimePicker');
+ if (!instance) {
+ throw new Error('bootstrap-datetimepicker("' + options + '") method was called on an element that is not using DateTimePicker');
+ }
+
+ returnValue = instance[options].apply(instance, args);
+ isInstance = returnValue === instance;
+ });
+
+ if (isInstance || $.inArray(options, thisMethods) > -1) {
+ return this;
}
- });
+
+ return returnValue;
+ }
+
+ throw new TypeError('Invalid arguments for DateTimePicker: ' + options);
};
$.fn.datetimepicker.defaults = {
- timeZone: 'Etc/UTC',
+ timeZone: '',
format: false,
dayViewHeaderFormat: 'MMMM YYYY',
extraFormats: false,
stepping: 1,
minDate: false,
@@ -2529,10 +2594,13 @@
//tab: function (widget) { //this break the flow of the form. disabling for now
// var toggle = widget.find('.picker-switch a[data-action="togglePicker"]');
// if(toggle.length > 0) toggle.click();
//},
'control space': function (widget) {
+ if (!widget) {
+ return;
+ }
if (widget.find('.timepicker').is(':visible')) {
widget.find('.btn[data-action="togglePeriod"]').click();
}
},
t: function () {
@@ -2547,6 +2615,9 @@
disabledTimeIntervals: false,
disabledHours: false,
enabledHours: false,
viewDate: false
};
+ if (typeof module !== 'undefined') {
+ module.exports = $.fn.datetimepicker;
+ }
}));