diff --git a/src/dateparser/dateparser.js b/src/dateparser/dateparser.js index fa3004533b..eb323623b6 100644 --- a/src/dateparser/dateparser.js +++ b/src/dateparser/dateparser.js @@ -106,7 +106,7 @@ angular.module('ui.bootstrap.dateparser', []) }; } - this.parse = function(input, format) { + this.parse = function(input, format, baseDate) { if ( !angular.isString(input) || !format ) { return input; } @@ -124,7 +124,20 @@ angular.module('ui.bootstrap.dateparser', []) results = input.match(regex); if ( results && results.length ) { - var fields = { year: 1900, month: 0, date: 1, hours: 0, minutes: 0, seconds: 0, milliseconds: 0 }, dt; + var fields, dt; + if (baseDate) { + fields = { + year: baseDate.getFullYear(), + month: baseDate.getMonth(), + date: baseDate.getDate(), + hours: baseDate.getHours(), + minutes: baseDate.getMinutes(), + seconds: baseDate.getSeconds(), + milliseconds: baseDate.getMilliseconds() + }; + } else { + fields = { year: 1900, month: 0, date: 1, hours: 0, minutes: 0, seconds: 0, milliseconds: 0 }; + } for( var i = 1, n = results.length; i < n; i++ ) { var mapper = map[i-1]; @@ -134,7 +147,8 @@ angular.module('ui.bootstrap.dateparser', []) } if ( isValid(fields.year, fields.month, fields.date) ) { - dt = new Date(fields.year, fields.month, fields.date, fields.hours, fields.minutes, fields.seconds, fields.milliseconds); + dt = new Date(fields.year, fields.month, fields.date, fields.hours, fields.minutes, fields.seconds, + fields.milliseconds || 0); } return dt; diff --git a/src/datepicker/datepicker.js b/src/datepicker/datepicker.js index 830edb2f8d..d18c86d944 100644 --- a/src/datepicker/datepicker.js +++ b/src/datepicker/datepicker.js @@ -444,6 +444,11 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst .constant('datepickerPopupConfig', { datepickerPopup: 'yyyy-MM-dd', + html5Types: { + date: 'yyyy-MM-dd', + 'datetime-local': 'yyyy-MM-ddTHH:mm:ss.sss', + 'month': 'yyyy-MM' + }, currentText: 'Today', clearText: 'Clear', closeText: 'Done', @@ -476,16 +481,34 @@ function ($compile, $parse, $document, $position, dateFilter, dateParser, datepi return scope[key + 'Text'] || datepickerPopupConfig[key + 'Text']; }; - dateFormat = attrs.datepickerPopup || datepickerPopupConfig.datepickerPopup; - attrs.$observe('datepickerPopup', function(value, oldValue) { - var newDateFormat = value || datepickerPopupConfig.datepickerPopup; - // Invalidate the $modelValue to ensure that formatters re-run - // FIXME: Refactor when PR is merged: https://github.com/angular/angular.js/pull/10764 - if (newDateFormat !== dateFormat) { - dateFormat = newDateFormat; - ngModel.$modelValue = null; - } - }); + var isHtml5DateInput = false; + if (datepickerPopupConfig.html5Types[attrs.type]) { + dateFormat = datepickerPopupConfig.html5Types[attrs.type]; + isHtml5DateInput = true; + } else { + dateFormat = attrs.datepickerPopup || datepickerPopupConfig.datepickerPopup; + attrs.$observe('datepickerPopup', function(value, oldValue) { + var newDateFormat = value || datepickerPopupConfig.datepickerPopup; + // Invalidate the $modelValue to ensure that formatters re-run + // FIXME: Refactor when PR is merged: https://github.com/angular/angular.js/pull/10764 + if (newDateFormat !== dateFormat) { + dateFormat = newDateFormat; + ngModel.$modelValue = null; + + if (!dateFormat) { + throw new Error('datepickerPopup must have a date format specified.'); + } + } + }); + } + + if (!dateFormat) { + throw new Error('datepickerPopup must have a date format specified.'); + } + + if (isHtml5DateInput && attrs.datepickerPopup) { + throw new Error('HTML5 date input types do not support custom formats.'); + } // popup element used to display calendar var popupEl = angular.element('
+ + + + +
+