diff --git a/daterangepicker.js b/daterangepicker.js index 5f7d304b..b329376e 100644 --- a/daterangepicker.js +++ b/daterangepicker.js @@ -1,10 +1,10 @@ /** -* @version: 3.1 -* @author: Dan Grossman http://www.dangrossman.info/ -* @copyright: Copyright (c) 2012-2019 Dan Grossman. All rights reserved. -* @license: Licensed under the MIT license. See http://www.opensource.org/licenses/mit-license.php -* @website: http://www.daterangepicker.com/ -*/ + * @version: 3.1 + * @author: Dan Grossman http://www.dangrossman.info/ + * @copyright: Copyright (c) 2012-2019 Dan Grossman. All rights reserved. + * @license: Licensed under the MIT license. See http://www.opensource.org/licenses/mit-license.php + * @website: http://www.daterangepicker.com/ + */ // Following the UMD template https://github.com/umdjs/umd/blob/master/templates/returnExportsGlobal.js (function (root, factory) { if (typeof define === 'function' && define.amd) { @@ -54,7 +54,9 @@ this.linkedCalendars = true; this.autoUpdateInput = true; this.alwaysShowCalendars = false; + this.strictFormat = false; this.ranges = {}; + this.onChangeValidState = function () { } this.opens = 'right'; if (this.element.hasClass('pull-right')) @@ -99,22 +101,22 @@ //html template for the picker UI if (typeof options.template !== 'string' && !(options.template instanceof $)) options.template = - '
' + + '
' + '
' + '
' + - '
' + - '
' + + '
' + + '
' + '
' + '
' + - '
' + - '
' + + '
' + + '
' + '
' + '
' + - '' + - '' + - ' ' + + '' + + '' + + ' ' + '
' + - '
'; + '
'; this.parentEl = (options.parentEl && $(options.parentEl).length) ? $(options.parentEl) : $(this.parentEl); this.container = $(options.template).appendTo(this.parentEl); @@ -138,19 +140,19 @@ this.locale.daysOfWeek = options.locale.daysOfWeek.slice(); if (typeof options.locale.monthNames === 'object') - this.locale.monthNames = options.locale.monthNames.slice(); + this.locale.monthNames = options.locale.monthNames.slice(); if (typeof options.locale.firstDay === 'number') - this.locale.firstDay = options.locale.firstDay; + this.locale.firstDay = options.locale.firstDay; if (typeof options.locale.applyLabel === 'string') - this.locale.applyLabel = options.locale.applyLabel; + this.locale.applyLabel = options.locale.applyLabel; if (typeof options.locale.cancelLabel === 'string') - this.locale.cancelLabel = options.locale.cancelLabel; + this.locale.cancelLabel = options.locale.cancelLabel; if (typeof options.locale.weekLabel === 'string') - this.locale.weekLabel = options.locale.weekLabel; + this.locale.weekLabel = options.locale.weekLabel; if (typeof options.locale.customRangeLabel === 'string'){ //Support unicode chars in the custom range name. @@ -278,6 +280,12 @@ if (typeof options.alwaysShowCalendars === 'boolean') this.alwaysShowCalendars = options.alwaysShowCalendars; + if (typeof options.onChangeValidState === 'function') + this.onChangeValidState = options.onChangeValidState; + + if (typeof options.strictFormat === 'boolean') + this.strictFormat = options.strictFormat; + // update day names order to firstDay if (this.locale.firstDay != 0) { var iterator = this.locale.firstDay; @@ -338,7 +346,7 @@ // If the end of the range is before the minimum or the start of the range is // after the maximum, don't display this range option at all. if ((this.minDate && end.isBefore(this.minDate, this.timepicker ? 'minute' : 'day')) - || (maxDate && start.isAfter(maxDate, this.timepicker ? 'minute' : 'day'))) + || (maxDate && start.isAfter(maxDate, this.timepicker ? 'minute' : 'day'))) continue; //Support unicode chars in the range names. @@ -443,7 +451,7 @@ // this.updateElement(); - + this.inputValidState = true; }; DateRangePicker.prototype = { @@ -475,6 +483,9 @@ this.startDate.minute(Math.floor(this.startDate.minute() / this.timePickerIncrement) * this.timePickerIncrement); } + this.container.find('.drp-selected').html(this.startDate.format(this.locale.format) + this.locale.separator + + this.container.find('.drp-selected').html().split(this.locale.separator)[1]); + if (!this.isShowing) this.updateElement(); @@ -546,7 +557,7 @@ (this.startDate.format('YYYY-MM') == this.leftCalendar.month.format('YYYY-MM') || this.startDate.format('YYYY-MM') == this.rightCalendar.month.format('YYYY-MM')) && (this.endDate.format('YYYY-MM') == this.leftCalendar.month.format('YYYY-MM') || this.endDate.format('YYYY-MM') == this.rightCalendar.month.format('YYYY-MM')) - ) { + ) { return; } @@ -564,8 +575,8 @@ } } if (this.maxDate && this.linkedCalendars && !this.singleDatePicker && this.rightCalendar.month > this.maxDate) { - this.rightCalendar.month = this.maxDate.clone().date(2); - this.leftCalendar.month = this.maxDate.clone().date(2).subtract(1, 'month'); + this.rightCalendar.month = this.maxDate.clone().date(2); + this.leftCalendar.month = this.maxDate.clone().date(2).subtract(1, 'month'); } }, @@ -1036,26 +1047,26 @@ } switch (drops) { - case 'auto': - containerTop = this.element.offset().top + this.element.outerHeight() - parentOffset.top; - if (containerTop + this.container.outerHeight() >= this.parentEl[0].scrollHeight) { + case 'auto': + containerTop = this.element.offset().top + this.element.outerHeight() - parentOffset.top; + if (containerTop + this.container.outerHeight() >= this.parentEl[0].scrollHeight) { + containerTop = this.element.offset().top - this.container.outerHeight() - parentOffset.top; + drops = 'up'; + } + break; + case 'up': containerTop = this.element.offset().top - this.container.outerHeight() - parentOffset.top; - drops = 'up'; - } - break; - case 'up': - containerTop = this.element.offset().top - this.container.outerHeight() - parentOffset.top; - break; - default: - containerTop = this.element.offset().top + this.element.outerHeight() - parentOffset.top; - break; + break; + default: + containerTop = this.element.offset().top + this.element.outerHeight() - parentOffset.top; + break; } // Force the container to it's actual width this.container.css({ - top: 0, - left: 0, - right: 'auto' + top: 0, + left: 0, + right: 'auto' }); var containerWidth = this.container.outerWidth(); @@ -1078,7 +1089,7 @@ } } else if (this.opens == 'center') { var containerLeft = this.element.offset().left - parentOffset.left + this.element.outerWidth() / 2 - - containerWidth / 2; + - containerWidth / 2; if (containerLeft < 0) { this.container.css({ top: containerTop, @@ -1124,13 +1135,13 @@ // Bind global datepicker mousedown for hiding and $(document) - .on('mousedown.daterangepicker', this._outsideClickProxy) - // also support mobile devices - .on('touchend.daterangepicker', this._outsideClickProxy) - // also explicitly play nice with Bootstrap dropdowns, which stopPropagation when clicking them - .on('click.daterangepicker', '[data-toggle=dropdown]', this._outsideClickProxy) - // and also close when focus changes to outside the picker (eg. tabbing between controls) - .on('focusin.daterangepicker', this._outsideClickProxy); + .on('mousedown.daterangepicker', this._outsideClickProxy) + // also support mobile devices + .on('touchend.daterangepicker', this._outsideClickProxy) + // also explicitly play nice with Bootstrap dropdowns, which stopPropagation when clicking them + .on('click.daterangepicker', '[data-toggle=dropdown]', this._outsideClickProxy) + // and also close when focus changes to outside the picker (eg. tabbing between controls) + .on('focusin.daterangepicker', this._outsideClickProxy); // Reposition the picker if the window is resized while it's open $(window).on('resize.daterangepicker', $.proxy(function(e) { this.move(e); }, this)); @@ -1167,6 +1178,8 @@ this.container.hide(); this.element.trigger('hide.daterangepicker', this); this.isShowing = false; + this.inputValidState = true; + this.onChangeValidState(this, this.inputValidState) }, toggle: function(e) { @@ -1187,7 +1200,7 @@ target.closest(this.element).length || target.closest(this.container).length || target.closest('.calendar-table').length - ) return; + ) return; this.hide(); this.element.trigger('outsideClick.daterangepicker', this); }, @@ -1347,8 +1360,8 @@ } this.setEndDate(date.clone()); if (this.autoApply) { - this.calculateChosenLabel(); - this.clickApply(); + this.calculateChosenLabel(); + this.clickApply(); } } @@ -1369,7 +1382,7 @@ var customRange = true; var i = 0; for (var range in this.ranges) { - if (this.timePicker) { + if (this.timePicker) { var format = this.timePickerSeconds ? "YYYY-MM-DD HH:mm:ss" : "YYYY-MM-DD HH:mm"; //ignore times when comparing dates if time picker seconds is not enabled if (this.startDate.format(format) == this.ranges[range][0].format(format) && this.endDate.format(format) == this.ranges[range][1].format(format)) { @@ -1511,16 +1524,27 @@ end = null; if (dateString.length === 2) { - start = moment(dateString[0], this.locale.format); - end = moment(dateString[1], this.locale.format); + start = moment(dateString[0], this.locale.format, this.strictFormat); + end = moment(dateString[1], this.locale.format, this.strictFormat); } if (this.singleDatePicker || start === null || end === null) { - start = moment(this.element.val(), this.locale.format); + start = moment(this.element.val(), this.locale.format, this.strictFormat); end = start; } - if (!start.isValid() || !end.isValid()) return; + if (!start.isValid() || !end.isValid()) { + if (this.inputValidState) { + this.inputValidState = false; + this.onChangeValidState(this, this.inputValidState); + } + return; + } + + if (!this.inputValidState) { + this.inputValidState = true; + this.onChangeValidState(this, this.inputValidState); + } this.setStartDate(start); this.setEndDate(end); diff --git a/package.json b/package.json index bb8a6216..0cb40550 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "daterangepicker", - "version": "3.1.0", + "version": "3.1.1", "description": "Date range picker component for Bootstrap", "main": "daterangepicker.js", "style": "daterangepicker.css",