From 44354f67e55c571df28b09e26a314a845a3b7397 Mon Sep 17 00:00:00 2001 From: Wesley Cho Date: Fri, 2 Oct 2015 15:14:25 -0700 Subject: [PATCH] feat(datepicker): add uib- prefix Closes #4509 --- src/datepicker/datepicker.js | 1158 ++++++++++++++---------- src/datepicker/docs/demo.html | 6 +- src/datepicker/test/datepicker.spec.js | 284 +++--- template/datepicker/datepicker.html | 6 +- 4 files changed, 856 insertions(+), 598 deletions(-) diff --git a/src/datepicker/datepicker.js b/src/datepicker/datepicker.js index 463b6a73b8..784b568754 100644 --- a/src/datepicker/datepicker.js +++ b/src/datepicker/datepicker.js @@ -2,7 +2,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst .value('$datepickerSuppressError', false) -.constant('datepickerConfig', { +.constant('uibDatepickerConfig', { formatDay: 'dd', formatMonth: 'MMMM', formatYear: 'yyyy', @@ -20,7 +20,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst shortcutPropagation: false }) -.controller('DatepickerController', ['$scope', '$attrs', '$parse', '$interpolate', '$log', 'dateFilter', 'datepickerConfig', '$datepickerSuppressError', function($scope, $attrs, $parse, $interpolate, $log, dateFilter, datepickerConfig, $datepickerSuppressError) { +.controller('UibDatepickerController', ['$scope', '$attrs', '$parse', '$interpolate', '$log', 'dateFilter', 'uibDatepickerConfig', '$datepickerSuppressError', function($scope, $attrs, $parse, $interpolate, $log, dateFilter, datepickerConfig, $datepickerSuppressError) { var self = this, ngModelCtrl = { $setViewValue: angular.noop }; // nullModelCtrl; @@ -191,7 +191,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst }; // Listen for focus requests from popup directive - $scope.$on('datepicker.focus', focusElement); + $scope.$on('uib:datepicker.focus', focusElement); $scope.keydown = function(evt) { var key = $scope.keys[evt.which]; @@ -219,262 +219,289 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst }; }]) -.directive('datepicker', function() { - return { - restrict: 'EA', - replace: true, - templateUrl: function(element, attrs) { - return attrs.templateUrl || 'template/datepicker/datepicker.html'; - }, - scope: { - datepickerMode: '=?', - dateDisabled: '&', - customClass: '&', - shortcutPropagation: '&?' - }, - require: ['datepicker', '^ngModel'], - controller: 'DatepickerController', - controllerAs: 'datepicker', - link: function(scope, element, attrs, ctrls) { - var datepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1]; +.controller('UibDaypickerController', ['$scope', '$element', 'dateFilter', function(scope, $element, dateFilter) { + var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; - datepickerCtrl.init(ngModelCtrl); + this.step = { months: 1 }; + this.element = $element; + function getDaysInMonth(year, month) { + return ((month === 1) && (year % 4 === 0) && ((year % 100 !== 0) || (year % 400 === 0))) ? 29 : DAYS_IN_MONTH[month]; + } + + this.init = function(ctrl) { + angular.extend(ctrl, this); + scope.showWeeks = ctrl.showWeeks; + ctrl.refreshView(); + }; + + this.getDates = function(startDate, n) { + var dates = new Array(n), current = new Date(startDate), i = 0, date; + while (i < n) { + date = new Date(current); + this.fixTimeZone(date); + dates[i++] = date; + current.setDate(current.getDate() + 1); } + return dates; }; -}) -.directive('daypicker', ['dateFilter', function(dateFilter) { - return { - restrict: 'EA', - replace: true, - templateUrl: 'template/datepicker/day.html', - require: '^datepicker', - link: function(scope, element, attrs, ctrl) { - scope.showWeeks = ctrl.showWeeks; + this._refreshView = function() { + var year = this.activeDate.getFullYear(), + month = this.activeDate.getMonth(), + firstDayOfMonth = new Date(year, month, 1), + difference = this.startingDay - firstDayOfMonth.getDay(), + numDisplayedFromPreviousMonth = (difference > 0) ? 7 - difference : - difference, + firstDate = new Date(firstDayOfMonth); - ctrl.step = { months: 1 }; - ctrl.element = element; + if (numDisplayedFromPreviousMonth > 0) { + firstDate.setDate(-numDisplayedFromPreviousMonth + 1); + } - var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; - function getDaysInMonth(year, month) { - return ((month === 1) && (year % 4 === 0) && ((year % 100 !== 0) || (year % 400 === 0))) ? 29 : DAYS_IN_MONTH[month]; - } + // 42 is the number of days on a six-month calendar + var days = this.getDates(firstDate, 42); + for (var i = 0; i < 42; i ++) { + days[i] = angular.extend(this.createDateObject(days[i], this.formatDay), { + secondary: days[i].getMonth() !== month, + uid: scope.uniqueId + '-' + i + }); + } - function getDates(startDate, n) { - var dates = new Array(n), current = new Date(startDate), i = 0, date; - while (i < n) { - date = new Date(current); - ctrl.fixTimeZone(date); - dates[i++] = date; - current.setDate(current.getDate() + 1); - } - return dates; + scope.labels = new Array(7); + for (var j = 0; j < 7; j++) { + scope.labels[j] = { + abbr: dateFilter(days[j].date, this.formatDayHeader), + full: dateFilter(days[j].date, 'EEEE') + }; + } + + scope.title = dateFilter(this.activeDate, this.formatDayTitle); + scope.rows = this.split(days, 7); + + if (scope.showWeeks) { + scope.weekNumbers = []; + var thursdayIndex = (4 + 7 - this.startingDay) % 7, + numWeeks = scope.rows.length; + for (var curWeek = 0; curWeek < numWeeks; curWeek++) { + scope.weekNumbers.push( + getISO8601WeekNumber(scope.rows[curWeek][thursdayIndex].date)); } + } + }; - ctrl._refreshView = function() { - var year = ctrl.activeDate.getFullYear(), - month = ctrl.activeDate.getMonth(), - firstDayOfMonth = new Date(year, month, 1), - difference = ctrl.startingDay - firstDayOfMonth.getDay(), - numDisplayedFromPreviousMonth = (difference > 0) ? 7 - difference : - difference, - firstDate = new Date(firstDayOfMonth); + this.compare = function(date1, date2) { + return (new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate())); + }; - if (numDisplayedFromPreviousMonth > 0) { - firstDate.setDate(-numDisplayedFromPreviousMonth + 1); - } + function getISO8601WeekNumber(date) { + var checkDate = new Date(date); + checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); // Thursday + var time = checkDate.getTime(); + checkDate.setMonth(0); // Compare with Jan 1 + checkDate.setDate(1); + return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; + } - // 42 is the number of days on a six-month calendar - var days = getDates(firstDate, 42); - for (var i = 0; i < 42; i ++) { - days[i] = angular.extend(ctrl.createDateObject(days[i], ctrl.formatDay), { - secondary: days[i].getMonth() !== month, - uid: scope.uniqueId + '-' + i - }); - } + this.handleKeyDown = function(key, evt) { + var date = this.activeDate.getDate(); + + if (key === 'left') { + date = date - 1; // up + } else if (key === 'up') { + date = date - 7; // down + } else if (key === 'right') { + date = date + 1; // down + } else if (key === 'down') { + date = date + 7; + } else if (key === 'pageup' || key === 'pagedown') { + var month = this.activeDate.getMonth() + (key === 'pageup' ? - 1 : 1); + this.activeDate.setMonth(month, 1); + date = Math.min(getDaysInMonth(this.activeDate.getFullYear(), this.activeDate.getMonth()), date); + } else if (key === 'home') { + date = 1; + } else if (key === 'end') { + date = getDaysInMonth(this.activeDate.getFullYear(), this.activeDate.getMonth()); + } + this.activeDate.setDate(date); + }; +}]) - scope.labels = new Array(7); - for (var j = 0; j < 7; j++) { - scope.labels[j] = { - abbr: dateFilter(days[j].date, ctrl.formatDayHeader), - full: dateFilter(days[j].date, 'EEEE') - }; - } +.controller('UibMonthpickerController', ['$scope', '$element', 'dateFilter', function(scope, $element, dateFilter) { + this.step = { years: 1 }; + this.element = $element; - scope.title = dateFilter(ctrl.activeDate, ctrl.formatDayTitle); - scope.rows = ctrl.split(days, 7); + this.init = function(ctrl) { + angular.extend(ctrl, this); + ctrl.refreshView(); + }; - if (scope.showWeeks) { - scope.weekNumbers = []; - var thursdayIndex = (4 + 7 - ctrl.startingDay) % 7, - numWeeks = scope.rows.length; - for (var curWeek = 0; curWeek < numWeeks; curWeek++) { - scope.weekNumbers.push( - getISO8601WeekNumber(scope.rows[curWeek][thursdayIndex].date)); - } - } - }; + this._refreshView = function() { + var months = new Array(12), + year = this.activeDate.getFullYear(), + date; - ctrl.compare = function(date1, date2) { - return (new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate())); - }; + for (var i = 0; i < 12; i++) { + date = new Date(year, i, 1); + this.fixTimeZone(date); + months[i] = angular.extend(this.createDateObject(date, this.formatMonth), { + uid: scope.uniqueId + '-' + i + }); + } - function getISO8601WeekNumber(date) { - var checkDate = new Date(date); - checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); // Thursday - var time = checkDate.getTime(); - checkDate.setMonth(0); // Compare with Jan 1 - checkDate.setDate(1); - return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; - } + scope.title = dateFilter(this.activeDate, this.formatMonthTitle); + scope.rows = this.split(months, 3); + }; - ctrl.handleKeyDown = function(key, evt) { - var date = ctrl.activeDate.getDate(); - - if (key === 'left') { - date = date - 1; // up - } else if (key === 'up') { - date = date - 7; // down - } else if (key === 'right') { - date = date + 1; // down - } else if (key === 'down') { - date = date + 7; - } else if (key === 'pageup' || key === 'pagedown') { - var month = ctrl.activeDate.getMonth() + (key === 'pageup' ? - 1 : 1); - ctrl.activeDate.setMonth(month, 1); - date = Math.min(getDaysInMonth(ctrl.activeDate.getFullYear(), ctrl.activeDate.getMonth()), date); - } else if (key === 'home') { - date = 1; - } else if (key === 'end') { - date = getDaysInMonth(ctrl.activeDate.getFullYear(), ctrl.activeDate.getMonth()); - } - ctrl.activeDate.setDate(date); - }; + this.compare = function(date1, date2) { + return new Date(date1.getFullYear(), date1.getMonth()) - new Date(date2.getFullYear(), date2.getMonth()); + }; - ctrl.refreshView(); + this.handleKeyDown = function(key, evt) { + var date = this.activeDate.getMonth(); + + if (key === 'left') { + date = date - 1; // up + } else if (key === 'up') { + date = date - 3; // down + } else if (key === 'right') { + date = date + 1; // down + } else if (key === 'down') { + date = date + 3; + } else if (key === 'pageup' || key === 'pagedown') { + var year = this.activeDate.getFullYear() + (key === 'pageup' ? - 1 : 1); + this.activeDate.setFullYear(year); + } else if (key === 'home') { + date = 0; + } else if (key === 'end') { + date = 11; } + this.activeDate.setMonth(date); }; }]) -.directive('monthpicker', ['dateFilter', function(dateFilter) { - return { - restrict: 'EA', - replace: true, - templateUrl: 'template/datepicker/month.html', - require: '^datepicker', - link: function(scope, element, attrs, ctrl) { - ctrl.step = { years: 1 }; - ctrl.element = element; - - ctrl._refreshView = function() { - var months = new Array(12), - year = ctrl.activeDate.getFullYear(), - date; - - for (var i = 0; i < 12; i++) { - date = new Date(year, i, 1); - ctrl.fixTimeZone(date); - months[i] = angular.extend(ctrl.createDateObject(date, ctrl.formatMonth), { - uid: scope.uniqueId + '-' + i - }); - } +.controller('UibYearpickerController', ['$scope', '$element', 'dateFilter', function(scope, $element, dateFilter) { + var range; + this.element = $element; - scope.title = dateFilter(ctrl.activeDate, ctrl.formatMonthTitle); - scope.rows = ctrl.split(months, 3); - }; + function getStartingYear(year) { + return parseInt((year - 1) / range, 10) * range + 1; + } - ctrl.compare = function(date1, date2) { - return new Date(date1.getFullYear(), date1.getMonth()) - new Date(date2.getFullYear(), date2.getMonth()); - }; + this.yearpickerInit = function() { + range = this.yearRange; + this.step = { years: range }; + }; - ctrl.handleKeyDown = function(key, evt) { - var date = ctrl.activeDate.getMonth(); - - if (key === 'left') { - date = date - 1; // up - } else if (key === 'up') { - date = date - 3; // down - } else if (key === 'right') { - date = date + 1; // down - } else if (key === 'down') { - date = date + 3; - } else if (key === 'pageup' || key === 'pagedown') { - var year = ctrl.activeDate.getFullYear() + (key === 'pageup' ? - 1 : 1); - ctrl.activeDate.setFullYear(year); - } else if (key === 'home') { - date = 0; - } else if (key === 'end') { - date = 11; - } - ctrl.activeDate.setMonth(date); - }; + this._refreshView = function() { + var years = new Array(range), date; - ctrl.refreshView(); + for (var i = 0, start = getStartingYear(this.activeDate.getFullYear()); i < range; i++) { + date = new Date(start + i, 0, 1); + this.fixTimeZone(date); + years[i] = angular.extend(this.createDateObject(date, this.formatYear), { + uid: scope.uniqueId + '-' + i + }); } + + scope.title = [years[0].label, years[range - 1].label].join(' - '); + scope.rows = this.split(years, 5); + }; + + this.compare = function(date1, date2) { + return date1.getFullYear() - date2.getFullYear(); + }; + + this.handleKeyDown = function(key, evt) { + var date = this.activeDate.getFullYear(); + + if (key === 'left') { + date = date - 1; // up + } else if (key === 'up') { + date = date - 5; // down + } else if (key === 'right') { + date = date + 1; // down + } else if (key === 'down') { + date = date + 5; + } else if (key === 'pageup' || key === 'pagedown') { + date += (key === 'pageup' ? - 1 : 1) * this.step.years; + } else if (key === 'home') { + date = getStartingYear(this.activeDate.getFullYear()); + } else if (key === 'end') { + date = getStartingYear(this.activeDate.getFullYear()) + range - 1; + } + this.activeDate.setFullYear(date); }; }]) -.directive('yearpicker', ['dateFilter', function(dateFilter) { +.directive('uibDatepicker', function() { return { - restrict: 'EA', replace: true, - templateUrl: 'template/datepicker/year.html', - require: '^datepicker', - link: function(scope, element, attrs, ctrl) { - var range = ctrl.yearRange; - - ctrl.step = { years: range }; - ctrl.element = element; + templateUrl: function(element, attrs) { + return attrs.templateUrl || 'template/datepicker/datepicker.html'; + }, + scope: { + datepickerMode: '=?', + dateDisabled: '&', + customClass: '&', + shortcutPropagation: '&?' + }, + require: ['uibDatepicker', '^ngModel'], + controller: 'UibDatepickerController', + controllerAs: 'datepicker', + link: function(scope, element, attrs, ctrls) { + var datepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1]; - function getStartingYear( year ) { - return parseInt((year - 1) / range, 10) * range + 1; - } + datepickerCtrl.init(ngModelCtrl); + } + }; +}) - ctrl._refreshView = function() { - var years = new Array(range), date; +.directive('uibDaypicker', function() { + return { + replace: true, + templateUrl: 'template/datepicker/day.html', + require: ['^?uibDatepicker', 'uibDaypicker', '^?datepicker'], + controller: 'UibDaypickerController', + link: function(scope, element, attrs, ctrls) { + var datepickerCtrl = ctrls[0] || ctrls[2], + daypickerCtrl = ctrls[1]; - for (var i = 0, start = getStartingYear(ctrl.activeDate.getFullYear()); i < range; i++) { - date = new Date(start + i, 0, 1); - ctrl.fixTimeZone(date); - years[i] = angular.extend(ctrl.createDateObject(date, ctrl.formatYear), { - uid: scope.uniqueId + '-' + i - }); - } + daypickerCtrl.init(datepickerCtrl); + } + }; +}) - scope.title = [years[0].label, years[range - 1].label].join(' - '); - scope.rows = ctrl.split(years, 5); - }; +.directive('uibMonthpicker', function() { + return { + replace: true, + templateUrl: 'template/datepicker/month.html', + require: ['^?uibDatepicker', 'uibMonthpicker', '^?datepicker'], + controller: 'UibMonthpickerController', + link: function(scope, element, attrs, ctrls) { + var datepickerCtrl = ctrls[0] || ctrls[2], + monthpickerCtrl = ctrls[1]; - ctrl.compare = function(date1, date2) { - return date1.getFullYear() - date2.getFullYear(); - }; + monthpickerCtrl.init(datepickerCtrl); + } + }; +}) - ctrl.handleKeyDown = function(key, evt) { - var date = ctrl.activeDate.getFullYear(); - - if (key === 'left') { - date = date - 1; // up - } else if (key === 'up') { - date = date - 5; // down - } else if (key === 'right') { - date = date + 1; // down - } else if (key === 'down') { - date = date + 5; - } else if (key === 'pageup' || key === 'pagedown') { - date += (key === 'pageup' ? - 1 : 1) * ctrl.step.years; - } else if (key === 'home') { - date = getStartingYear(ctrl.activeDate.getFullYear()); - } else if (key === 'end') { - date = getStartingYear(ctrl.activeDate.getFullYear()) + range - 1; - } - ctrl.activeDate.setFullYear(date); - }; +.directive('uibYearpicker', function() { + return { + replace: true, + templateUrl: 'template/datepicker/year.html', + require: ['^?uibDatepicker', 'uibYearpicker', '^?datepicker'], + controller: 'UibYearpickerController', + link: function(scope, element, attrs, ctrls) { + var ctrl = ctrls[0] || ctrls[2]; + angular.extend(ctrl, ctrls[1]); + ctrl.yearpickerInit(); ctrl.refreshView(); } }; -}]) +}) -.constant('datepickerPopupConfig', { +.constant('uibDatepickerPopupConfig', { datepickerPopup: 'yyyy-MM-dd', datepickerPopupTemplateUrl: 'template/datepicker/popup.html', datepickerTemplateUrl: 'template/datepicker/datepicker.html', @@ -492,332 +519,489 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst onOpenFocus: true }) -.directive('datepickerPopup', ['$compile', '$parse', '$document', '$rootScope', '$uibPosition', 'dateFilter', 'uibDateParser', 'datepickerPopupConfig', '$timeout', -function($compile, $parse, $document, $rootScope, $position, dateFilter, dateParser, datepickerPopupConfig, $timeout) { - return { - restrict: 'EA', - require: 'ngModel', - scope: { - isOpen: '=?', - currentText: '@', - clearText: '@', - closeText: '@', - dateDisabled: '&', - customClass: '&' - }, - link: function(scope, element, attrs, ngModel) { - var dateFormat, - closeOnDateSelection = angular.isDefined(attrs.closeOnDateSelection) ? scope.$parent.$eval(attrs.closeOnDateSelection) : datepickerPopupConfig.closeOnDateSelection, - appendToBody = angular.isDefined(attrs.datepickerAppendToBody) ? scope.$parent.$eval(attrs.datepickerAppendToBody) : datepickerPopupConfig.appendToBody, - onOpenFocus = angular.isDefined(attrs.onOpenFocus) ? scope.$parent.$eval(attrs.onOpenFocus) : datepickerPopupConfig.onOpenFocus, - datepickerPopupTemplateUrl = angular.isDefined(attrs.datepickerPopupTemplateUrl) ? attrs.datepickerPopupTemplateUrl : datepickerPopupConfig.datepickerPopupTemplateUrl, - datepickerTemplateUrl = angular.isDefined(attrs.datepickerTemplateUrl) ? attrs.datepickerTemplateUrl : datepickerPopupConfig.datepickerTemplateUrl, - cache = {}; - - scope.showButtonBar = angular.isDefined(attrs.showButtonBar) ? scope.$parent.$eval(attrs.showButtonBar) : datepickerPopupConfig.showButtonBar; - - scope.getText = function(key) { - return scope[key + 'Text'] || datepickerPopupConfig[key + 'Text']; - }; +.controller('UibDatepickerPopupController', ['$scope', '$element', '$attrs', '$compile', '$parse', '$document', '$rootScope', '$uibPosition', 'dateFilter', 'uibDateParser', 'uibDatepickerPopupConfig', '$timeout', +function(scope, element, attrs, $compile, $parse, $document, $rootScope, $position, dateFilter, dateParser, datepickerPopupConfig, $timeout) { + var self = this; + var cache = {}, + isHtml5DateInput = false; + var dateFormat, closeOnDateSelection, appendToBody, onOpenFocus, + datepickerPopupTemplateUrl, datepickerTemplateUrl, popupEl, datepickerEl, + ngModel, $popup; + + scope.watchData = {}; + + this.init = function(_ngModel_) { + ngModel = _ngModel_; + closeOnDateSelection = angular.isDefined(attrs.closeOnDateSelection) ? scope.$parent.$eval(attrs.closeOnDateSelection) : datepickerPopupConfig.closeOnDateSelection; + appendToBody = angular.isDefined(attrs.datepickerAppendToBody) ? scope.$parent.$eval(attrs.datepickerAppendToBody) : datepickerPopupConfig.appendToBody; + onOpenFocus = angular.isDefined(attrs.onOpenFocus) ? scope.$parent.$eval(attrs.onOpenFocus) : datepickerPopupConfig.onOpenFocus; + datepickerPopupTemplateUrl = angular.isDefined(attrs.datepickerPopupTemplateUrl) ? attrs.datepickerPopupTemplateUrl : datepickerPopupConfig.datepickerPopupTemplateUrl; + datepickerTemplateUrl = angular.isDefined(attrs.datepickerTemplateUrl) ? attrs.datepickerTemplateUrl : datepickerPopupConfig.datepickerTemplateUrl; + + scope.showButtonBar = angular.isDefined(attrs.showButtonBar) ? scope.$parent.$eval(attrs.showButtonBar) : datepickerPopupConfig.showButtonBar; + + if (datepickerPopupConfig.html5Types[attrs.type]) { + dateFormat = datepickerPopupConfig.html5Types[attrs.type]; + isHtml5DateInput = true; + } else { + dateFormat = attrs.datepickerPopup || datepickerPopupConfig.datepickerPopup; + attrs.$observe('uibDatepickerPopup', 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('uibDatepickerPopup must have a date format specified.'); + } + } + }); + } - scope.isDisabled = function(date) { - if (date === 'today') { - date = new Date(); - } + if (!dateFormat) { + throw new Error('uibDatepickerPopup must have a date format specified.'); + } - return ((scope.watchData.minDate && scope.compare(date, cache.minDate) < 0) || - (scope.watchData.maxDate && scope.compare(date, cache.maxDate) > 0)); - }; + if (isHtml5DateInput && attrs.datepickerPopup) { + throw new Error('HTML5 date input types do not support custom formats.'); + } - scope.compare = function(date1, date2) { - return (new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate())); - }; + // popup element used to display calendar + popupEl = angular.element('
'); + popupEl.attr({ + 'ng-model': 'date', + 'ng-change': 'dateSelection(date)', + 'template-url': datepickerPopupTemplateUrl + }); - 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.'); - } - } - }); + // datepicker element + datepickerEl = angular.element(popupEl.children()[0]); + datepickerEl.attr('template-url', datepickerTemplateUrl); + + if (isHtml5DateInput) { + if (attrs.type === 'month') { + datepickerEl.attr('datepicker-mode', '"month"'); + datepickerEl.attr('min-mode', 'month'); } + } - if (!dateFormat) { - throw new Error('datepickerPopup must have a date format specified.'); + if (attrs.datepickerOptions) { + var options = scope.$parent.$eval(attrs.datepickerOptions); + if (options && options.initDate) { + scope.initDate = options.initDate; + datepickerEl.attr('init-date', 'initDate'); + delete options.initDate; } + angular.forEach(options, function(value, option) { + datepickerEl.attr(cameltoDash(option), value); + }); + } - if (isHtml5DateInput && attrs.datepickerPopup) { - throw new Error('HTML5 date input types do not support custom formats.'); + angular.forEach(['minMode', 'maxMode', 'minDate', 'maxDate', 'datepickerMode', 'initDate', 'shortcutPropagation'], function(key) { + if (attrs[key]) { + var getAttribute = $parse(attrs[key]); + scope.$parent.$watch(getAttribute, function(value) { + scope.watchData[key] = value; + if (key === 'minDate' || key === 'maxDate') { + cache[key] = new Date(value); + } + }); + datepickerEl.attr(cameltoDash(key), 'watchData.' + key); + + // Propagate changes from datepicker to outside + if (key === 'datepickerMode') { + var setAttribute = getAttribute.assign; + scope.$watch('watchData.' + key, function(value, oldvalue) { + if (angular.isFunction(setAttribute) && value !== oldvalue) { + setAttribute(scope.$parent, value); + } + }); + } } + }); + if (attrs.dateDisabled) { + datepickerEl.attr('date-disabled', 'dateDisabled({ date: date, mode: mode })'); + } - // popup element used to display calendar - var popupEl = angular.element('
'); - popupEl.attr({ - 'ng-model': 'date', - 'ng-change': 'dateSelection(date)', - 'template-url': datepickerPopupTemplateUrl + if (attrs.showWeeks) { + datepickerEl.attr('show-weeks', attrs.showWeeks); + } + + if (attrs.customClass) { + datepickerEl.attr('custom-class', 'customClass({ date: date, mode: mode })'); + } + + if (!isHtml5DateInput) { + // Internal API to maintain the correct ng-invalid-[key] class + ngModel.$$parserName = 'date'; + ngModel.$validators.date = validator; + ngModel.$parsers.unshift(parseDate); + ngModel.$formatters.push(function(value) { + scope.date = value; + return ngModel.$isEmpty(value) ? value : dateFilter(value, dateFormat); + }); + } else { + ngModel.$formatters.push(function(value) { + scope.date = value; + return value; }); + } - function cameltoDash(string) { - return string.replace(/([A-Z])/g, function($1) { return '-' + $1.toLowerCase(); }); - } + // Detect changes in the view from the text box + ngModel.$viewChangeListeners.push(function() { + scope.date = dateParser.parse(ngModel.$viewValue, dateFormat, scope.date); + }); - // datepicker element - var datepickerEl = angular.element(popupEl.children()[0]); - datepickerEl.attr('template-url', datepickerTemplateUrl); + element.bind('keydown', inputKeydownBind); - if (isHtml5DateInput) { - if (attrs.type === 'month') { - datepickerEl.attr('datepicker-mode', '"month"'); - datepickerEl.attr('min-mode', 'month'); - } - } + $popup = $compile(popupEl)(scope); + // Prevent jQuery cache memory leak (template is now redundant after linking) + popupEl.remove(); - if (attrs.datepickerOptions) { - var options = scope.$parent.$eval(attrs.datepickerOptions); - if (options && options.initDate) { - scope.initDate = options.initDate; - datepickerEl.attr('init-date', 'initDate'); - delete options.initDate; - } - angular.forEach(options, function(value, option) { - datepickerEl.attr(cameltoDash(option), value); - }); - } + if (appendToBody) { + $document.find('body').append($popup); + } else { + element.after($popup); + } - scope.watchData = {}; - angular.forEach(['minMode', 'maxMode', 'minDate', 'maxDate', 'datepickerMode', 'initDate', 'shortcutPropagation'], function(key) { - if (attrs[key]) { - var getAttribute = $parse(attrs[key]); - scope.$parent.$watch(getAttribute, function(value) { - scope.watchData[key] = value; - if (key === 'minDate' || key === 'maxDate') { - cache[key] = new Date(value); - } + scope.$on('$destroy', function() { + if (scope.isOpen === true) { + if (!$rootScope.$$phase) { + scope.$apply(function() { + scope.isOpen = false; }); - datepickerEl.attr(cameltoDash(key), 'watchData.' + key); - - // Propagate changes from datepicker to outside - if (key === 'datepickerMode') { - var setAttribute = getAttribute.assign; - scope.$watch('watchData.' + key, function(value, oldvalue) { - if (angular.isFunction(setAttribute) && value !== oldvalue) { - setAttribute(scope.$parent, value); - } - }); - } } - }); - if (attrs.dateDisabled) { - datepickerEl.attr('date-disabled', 'dateDisabled({ date: date, mode: mode })'); } - if (attrs.showWeeks) { - datepickerEl.attr('show-weeks', attrs.showWeeks); - } + $popup.remove(); + element.unbind('keydown', inputKeydownBind); + $document.unbind('click', documentClickBind); + }); + }; - if (attrs.customClass) { - datepickerEl.attr('custom-class', 'customClass({ date: date, mode: mode })'); - } + scope.getText = function(key) { + return scope[key + 'Text'] || datepickerPopupConfig[key + 'Text']; + }; - function parseDate(viewValue) { - if (angular.isNumber(viewValue)) { - // presumably timestamp to date object - viewValue = new Date(viewValue); - } + scope.isDisabled = function(date) { + if (date === 'today') { + date = new Date(); + } - if (!viewValue) { - return null; - } else if (angular.isDate(viewValue) && !isNaN(viewValue)) { - return viewValue; - } else if (angular.isString(viewValue)) { - var date = dateParser.parse(viewValue, dateFormat, scope.date); - if (isNaN(date)) { - return undefined; - } else { - return date; - } - } else { - return undefined; - } + return ((scope.watchData.minDate && scope.compare(date, cache.minDate) < 0) || + (scope.watchData.maxDate && scope.compare(date, cache.maxDate) > 0)); + }; + + scope.compare = function(date1, date2) { + return (new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate())); + }; + + // Inner change + scope.dateSelection = function(dt) { + if (angular.isDefined(dt)) { + scope.date = dt; + } + var date = scope.date ? dateFilter(scope.date, dateFormat) : null; // Setting to NULL is necessary for form validators to function + element.val(date); + ngModel.$setViewValue(date); + + if (closeOnDateSelection) { + scope.isOpen = false; + element[0].focus(); + } + }; + + scope.keydown = function(evt) { + if (evt.which === 27) { + scope.isOpen = false; + element[0].focus(); + } + }; + + scope.select = function(date) { + if (date === 'today') { + var today = new Date(); + if (angular.isDate(scope.date)) { + date = new Date(scope.date); + date.setFullYear(today.getFullYear(), today.getMonth(), today.getDate()); + } else { + date = new Date(today.setHours(0, 0, 0, 0)); } + } + scope.dateSelection(date); + }; - function validator(modelValue, viewValue) { - var value = modelValue || viewValue; + scope.close = function() { + scope.isOpen = false; + element[0].focus(); + }; - if (!attrs.ngRequired && !value) { - return true; - } + scope.$watch('isOpen', function(value) { + if (value) { + scope.position = appendToBody ? $position.offset(element) : $position.position(element); + scope.position.top = scope.position.top + element.prop('offsetHeight'); - if (angular.isNumber(value)) { - value = new Date(value); - } - if (!value) { - return true; - } else if (angular.isDate(value) && !isNaN(value)) { - return true; - } else if (angular.isString(value)) { - var date = dateParser.parse(value, dateFormat); - return !isNaN(date); - } else { - return false; + $timeout(function() { + if (onOpenFocus) { + scope.$broadcast('uib:datepicker.focus'); } - } + $document.bind('click', documentClickBind); + }, 0, false); + } else { + $document.unbind('click', documentClickBind); + } + }); - if (!isHtml5DateInput) { - // Internal API to maintain the correct ng-invalid-[key] class - ngModel.$$parserName = 'date'; - ngModel.$validators.date = validator; - ngModel.$parsers.unshift(parseDate); - ngModel.$formatters.push(function(value) { - scope.date = value; - return ngModel.$isEmpty(value) ? value : dateFilter(value, dateFormat); - }); + function cameltoDash(string) { + return string.replace(/([A-Z])/g, function($1) { return '-' + $1.toLowerCase(); }); + } + + function parseDate(viewValue) { + if (angular.isNumber(viewValue)) { + // presumably timestamp to date object + viewValue = new Date(viewValue); + } + + if (!viewValue) { + return null; + } else if (angular.isDate(viewValue) && !isNaN(viewValue)) { + return viewValue; + } else if (angular.isString(viewValue)) { + var date = dateParser.parse(viewValue, dateFormat, scope.date); + if (isNaN(date)) { + return undefined; } else { - ngModel.$formatters.push(function(value) { - scope.date = value; - return value; - }); + return date; } + } else { + return undefined; + } + } - // Inner change - scope.dateSelection = function(dt) { - if (angular.isDefined(dt)) { - scope.date = dt; - } - var date = scope.date ? dateFilter(scope.date, dateFormat) : null; // Setting to NULL is necessary for form validators to function - element.val(date); - ngModel.$setViewValue(date); + function validator(modelValue, viewValue) { + var value = modelValue || viewValue; - if (closeOnDateSelection) { - scope.isOpen = false; - element[0].focus(); - } - }; + if (!attrs.ngRequired && !value) { + return true; + } - // Detect changes in the view from the text box - ngModel.$viewChangeListeners.push(function() { - scope.date = dateParser.parse(ngModel.$viewValue, dateFormat, scope.date); + if (angular.isNumber(value)) { + value = new Date(value); + } + if (!value) { + return true; + } else if (angular.isDate(value) && !isNaN(value)) { + return true; + } else if (angular.isString(value)) { + var date = dateParser.parse(value, dateFormat); + return !isNaN(date); + } else { + return false; + } + } + + function documentClickBind(event) { + var popup = $popup[0]; + var dpContainsTarget = element[0].contains(event.target); + // The popup node may not be an element node + // In some browsers (IE) only element nodes have the 'contains' function + var popupContainsTarget = popup.contains !== undefined && popup.contains(event.target); + if (scope.isOpen && !(dpContainsTarget || popupContainsTarget)) { + scope.$apply(function() { + scope.isOpen = false; }); + } + } - var documentClickBind = function(event) { - var popup = $popup[0]; - var dpContainsTarget = element[0].contains(event.target); - // The popup node may not be an element node - // In some browsers (IE) only element nodes have the 'contains' function - var popupContainsTarget = popup.contains !== undefined && popup.contains(event.target); - if (scope.isOpen && !(dpContainsTarget || popupContainsTarget)) { - scope.$apply(function() { - scope.isOpen = false; - }); - } - }; + function inputKeydownBind(evt) { + if (evt.which === 27 && scope.isOpen) { + evt.preventDefault(); + evt.stopPropagation(); + scope.$apply(function() { + scope.isOpen = false; + }); + element[0].focus(); + } else if (evt.which === 40 && !scope.isOpen) { + evt.preventDefault(); + evt.stopPropagation(); + scope.$apply(function() { + scope.isOpen = true; + }); + } + } +}]) - var inputKeydownBind = function(evt) { - if (evt.which === 27 && scope.isOpen) { - evt.preventDefault(); - evt.stopPropagation(); - scope.$apply(function() { - scope.isOpen = false; - }); - element[0].focus(); - } else if (evt.which === 40 && !scope.isOpen) { - evt.preventDefault(); - evt.stopPropagation(); - scope.$apply(function() { - scope.isOpen = true; - }); - } - }; - element.bind('keydown', inputKeydownBind); +.directive('uibDatepickerPopup', function() { + return { + require: ['ngModel', 'uibDatepickerPopup'], + controller: 'UibDatepickerPopupController', + scope: { + isOpen: '=?', + currentText: '@', + clearText: '@', + closeText: '@', + dateDisabled: '&', + customClass: '&' + }, + link: function(scope, element, attrs, ctrls) { + var ngModel = ctrls[0], + ctrl = ctrls[1]; - scope.keydown = function(evt) { - if (evt.which === 27) { - scope.isOpen = false; - element[0].focus(); - } - }; + ctrl.init(ngModel); + } + }; +}) - scope.$watch('isOpen', function(value) { - if (value) { - scope.position = appendToBody ? $position.offset(element) : $position.position(element); - scope.position.top = scope.position.top + element.prop('offsetHeight'); +.directive('uibDatepickerPopupWrap', function() { + return { + replace: true, + transclude: true, + templateUrl: function(element, attrs) { + return attrs.templateUrl || 'template/datepicker/popup.html'; + } + }; +}); - $timeout(function() { - if (onOpenFocus) { - scope.$broadcast('datepicker.focus'); - } - $document.bind('click', documentClickBind); - }, 0, false); - } else { - $document.unbind('click', documentClickBind); - } - }); +/* Deprecated datepicker below */ - scope.select = function(date) { - if (date === 'today') { - var today = new Date(); - if (angular.isDate(scope.date)) { - date = new Date(scope.date); - date.setFullYear(today.getFullYear(), today.getMonth(), today.getDate()); - } else { - date = new Date(today.setHours(0, 0, 0, 0)); - } - } - scope.dateSelection(date); - }; +angular.module('ui.bootstrap.datepicker') - scope.close = function() { - scope.isOpen = false; - element[0].focus(); - }; +.value('$datepickerSuppressWarning', false) - var $popup = $compile(popupEl)(scope); - // Prevent jQuery cache memory leak (template is now redundant after linking) - popupEl.remove(); +.controller('DatepickerController', ['$scope', '$attrs', '$log', '$datepickerSuppressWarning', '$controller', function($scope, $attrs, $log, $datepickerSuppressWarning, $controller) { + if (!$datepickerSuppressWarning) { + $log.warn('DatepickerController is now deprecated. Use UibDatepickerController instead.'); + } - if (appendToBody) { - $document.find('body').append($popup); - } else { - element.after($popup); + return $controller('UibDatepickerController', { + $scope: $scope, + $attrs: $attrs + }); +}]) + +.directive('datepicker', ['$log', '$datepickerSuppressWarning', function($log, $datepickerSuppressWarning) { + return { + replace: true, + templateUrl: function(element, attrs) { + return attrs.templateUrl || 'template/datepicker/datepicker.html'; + }, + scope: { + datepickerMode: '=?', + dateDisabled: '&', + customClass: '&', + shortcutPropagation: '&?' + }, + require: ['datepicker', '^ngModel'], + controller: 'DatepickerController', + controllerAs: 'datepicker', + link: function(scope, element, attrs, ctrls) { + if (!$datepickerSuppressWarning) { + $log.warn('datepicker is now deprecated. Use uib-datepicker instead.'); } - scope.$on('$destroy', function() { - if (scope.isOpen === true) { - if (!$rootScope.$$phase) { - scope.$apply(function() { - scope.isOpen = false; - }); - } - } + var datepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1]; - $popup.remove(); - element.unbind('keydown', inputKeydownBind); - $document.unbind('click', documentClickBind); - }); + datepickerCtrl.init(ngModelCtrl); + } + }; +}]) + +.directive('daypicker', ['$log', '$datepickerSuppressWarning', function($log, $datepickerSuppressWarning) { + return { + replace: true, + templateUrl: 'template/datepicker/day.html', + require: ['^datepicker', 'daypicker'], + controller: 'UibDaypickerController', + link: function(scope, element, attrs, ctrls) { + if (!$datepickerSuppressWarning) { + $log.warn('daypicker is now deprecated. Use uib-daypicker instead.'); + } + + var datepickerCtrl = ctrls[0], + daypickerCtrl = ctrls[1]; + + daypickerCtrl.init(datepickerCtrl); } }; }]) -.directive('datepickerPopupWrap', function() { +.directive('monthpicker', ['$log', '$datepickerSuppressWarning', function($log, $datepickerSuppressWarning) { + return { + replace: true, + templateUrl: 'template/datepicker/month.html', + require: ['^datepicker', 'monthpicker'], + controller: 'UibMonthpickerController', + link: function(scope, element, attrs, ctrls) { + if (!$datepickerSuppressWarning) { + $log.warn('monthpicker is now deprecated. Use uib-monthpicker instead.'); + } + + var datepickerCtrl = ctrls[0], + monthpickerCtrl = ctrls[1]; + + monthpickerCtrl.init(datepickerCtrl); + } + }; +}]) + +.directive('yearpicker', ['$log', '$datepickerSuppressWarning', function($log, $datepickerSuppressWarning) { + return { + replace: true, + templateUrl: 'template/datepicker/year.html', + require: ['^datepicker', 'yearpicker'], + controller: 'UibYearpickerController', + link: function(scope, element, attrs, ctrls) { + if (!$datepickerSuppressWarning) { + $log.warn('yearpicker is now deprecated. Use uib-yearpicker instead.'); + } + + var ctrl = ctrls[0]; + angular.extend(ctrl, ctrls[1]); + ctrl.yearpickerInit(); + + ctrl.refreshView(); + } + }; +}]) + +.directive('datepickerPopup', ['$log', '$datepickerSuppressWarning', function($log, $datepickerSuppressWarning) { + return { + require: ['ngModel', 'datepickerPopup'], + controller: 'UibDatepickerPopupController', + scope: { + isOpen: '=?', + currentText: '@', + clearText: '@', + closeText: '@', + dateDisabled: '&', + customClass: '&' + }, + link: function(scope, element, attrs, ctrls) { + if (!$datepickerSuppressWarning) { + $log.warn('datepicker-popup is now deprecated. Use uib-datepicker-popup instead.'); + } + + var ngModel = ctrls[0], + ctrl = ctrls[1]; + + ctrl.init(ngModel); + } + }; +}]) + +.directive('datepickerPopupWrap', ['$log', '$datepickerSuppressWarning', function($log, $datepickerSuppressWarning) { return { - restrict:'EA', replace: true, transclude: true, templateUrl: function(element, attrs) { return attrs.templateUrl || 'template/datepicker/popup.html'; + }, + link: function() { + if (!$datepickerSuppressWarning) { + $log.warn('datepicker-popup-wrap is now deprecated. Use uib-datepicker-popup-wrap instead.'); + } } }; -}); +}]); diff --git a/src/datepicker/docs/demo.html b/src/datepicker/docs/demo.html index 8806077f6a..4248413079 100644 --- a/src/datepicker/docs/demo.html +++ b/src/datepicker/docs/demo.html @@ -15,14 +15,14 @@

Inline

- +

Popup

- + @@ -31,7 +31,7 @@

Popup

- + diff --git a/src/datepicker/test/datepicker.spec.js b/src/datepicker/test/datepicker.spec.js index e42e7c2fcb..7fce2492b6 100644 --- a/src/datepicker/test/datepicker.spec.js +++ b/src/datepicker/test/datepicker.spec.js @@ -58,7 +58,7 @@ describe('datepicker directive', function() { var els = getLabelsRow().find('th'), labels = []; for (var i = dayMode ? 1 : 0, n = els.length; i < n; i++) { - labels.push( els.eq(i).text() ); + labels.push(els.eq(i).text()); } return labels; } @@ -67,7 +67,7 @@ describe('datepicker directive', function() { var rows = element.find('tbody').find('tr'), weeks = []; for (var i = 0, n = rows.length; i < n; i++) { - weeks.push( rows.eq(i).find('td').eq(0).first().text() ); + weeks.push(rows.eq(i).find('td').eq(0).first().text()); } return weeks; } @@ -79,7 +79,7 @@ describe('datepicker directive', function() { for (var j = 0, numRows = tr.length; j < numRows; j++) { var cols = tr.eq(j).find('td'), days = []; for (var i = dayMode ? 1 : 0, n = cols.length; i < n; i++) { - days.push( cols.eq(i).find('button').text() ); + days.push(cols.eq(i).find('button').text()); } rows.push(days); } @@ -106,7 +106,7 @@ describe('datepicker directive', function() { function expectSelectedElement(index) { var buttons = getAllOptionsEl(); angular.forEach( buttons, function(button, idx) { - expect(angular.element(button).hasClass('btn-info')).toBe( idx === index ); + expect(angular.element(button).hasClass('btn-info')).toBe(idx === index); }); } @@ -145,7 +145,7 @@ describe('datepicker directive', function() { }); spyOn($log, 'error'); - element = $compile('')($scope); + element = $compile('')($scope); $scope.locals = { date: 'lalala' @@ -166,7 +166,7 @@ describe('datepicker directive', function() { }); spyOn($log, 'error'); - element = $compile('')($scope); + element = $compile('')($scope); $scope.locals = { date: 'lalala' @@ -187,7 +187,7 @@ describe('datepicker directive', function() { }); spyOn($log, 'error'); - element = $compile('')($scope); + element = $compile('')($scope); $scope.locals = { date: 'lalala' @@ -208,7 +208,7 @@ describe('datepicker directive', function() { describe('', function() { beforeEach(function() { - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); }); @@ -322,12 +322,12 @@ describe('datepicker directive', function() { clickNextButton(); expect($rootScope.date).toEqual(new Date('September 30, 2010 15:30:00')); - clickOption( 17 ); + clickOption(17); expect($rootScope.date).toEqual(new Date('October 13, 2010 15:30:00')); }); it('updates the calendar when a day of another month is selected', function() { - clickOption( 33 ); + clickOption(33); expect($rootScope.date).toEqual(new Date('October 01, 2010 15:30:00')); expect(getTitle()).toBe('October 2010'); expect(getLabels(true)).toEqual(['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']); @@ -356,7 +356,7 @@ describe('datepicker directive', function() { it('should support custom templates', function() { $templateCache.put('foo/bar.html', '

baz
'); - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); expect(element.html()).toBe('baz'); @@ -365,10 +365,10 @@ describe('datepicker directive', function() { it('should expose the controller in the template', function() { $templateCache.put('template/datepicker/datepicker.html', '
{{datepicker.text}}
'); - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); - var ctrl = element.controller('datepicker'); + var ctrl = element.controller('uib-datepicker'); expect(ctrl).toBeDefined(); expect(element.html()).toBe(''); @@ -381,7 +381,7 @@ describe('datepicker directive', function() { // issue #3079 describe('time zone bug', function() { it('should deal with time zone bug', function() { - var ctrl = element.controller('datepicker'), + var ctrl = element.controller('uib-datepicker'), date = new Date('January 1, 2014'); spyOn(date, 'getHours').and.returnValue(23); spyOn(date, 'setHours').and.returnValue(); @@ -392,7 +392,7 @@ describe('datepicker directive', function() { }); it('should not change hours if time zone bug does not occur', function() { - var ctrl = element.controller('datepicker'), + var ctrl = element.controller('uib-datepicker'), date = new Date('January 1, 2014'); spyOn(date, 'getHours').and.returnValue(0); spyOn(date, 'setHours').and.returnValue(); @@ -437,7 +437,6 @@ describe('datepicker directive', function() { }); describe('not to a Date object', function() { - it('to a Number, it updates calendar', function() { $rootScope.date = parseInt((new Date('November 7, 2005 23:30:00')).getTime(), 10); $rootScope.$digest(); @@ -846,7 +845,7 @@ describe('datepicker directive', function() { describe('attribute `starting-day`', function () { beforeEach(function() { $rootScope.startingDay = 1; - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); }); @@ -873,7 +872,7 @@ describe('datepicker directive', function() { describe('attribute `show-weeks`', function() { beforeEach(function() { $rootScope.showWeeks = false; - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); }); @@ -889,7 +888,7 @@ describe('datepicker directive', function() { describe('`min-date` attribute', function () { beforeEach(function() { $rootScope.mindate = new Date('September 12, 2010'); - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); }); @@ -977,7 +976,7 @@ describe('datepicker directive', function() { describe('`max-date` attribute', function() { beforeEach(function() { $rootScope.maxdate = new Date('September 25, 2010'); - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); }); @@ -1060,7 +1059,7 @@ describe('datepicker directive', function() { describe('date-disabled expression', function () { beforeEach(function() { $rootScope.dateDisabledHandler = jasmine.createSpy('dateDisabledHandler'); - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); }); @@ -1085,7 +1084,7 @@ describe('datepicker directive', function() { describe('custom-class expression', function() { beforeEach(function() { $rootScope.customClassHandler = jasmine.createSpy('customClassHandler'); - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); }); @@ -1110,14 +1109,14 @@ describe('datepicker directive', function() { describe('formatting', function() { beforeEach(function() { $rootScope.dayTitle = 'MMMM, yy'; - element = $compile('')($rootScope); + 'year-range="10">')($rootScope); $rootScope.$digest(); }); @@ -1166,24 +1165,24 @@ describe('datepicker directive', function() { describe('setting datepickerConfig', function() { var originalConfig = {}; - beforeEach(inject(function(datepickerConfig) { - angular.extend(originalConfig, datepickerConfig); - datepickerConfig.formatDay = 'd'; - datepickerConfig.formatMonth = 'MMM'; - datepickerConfig.formatYear = 'yy'; - datepickerConfig.formatDayHeader = 'EEEE'; - datepickerConfig.formatDayTitle = 'MMM, yy'; - datepickerConfig.formatMonthTitle = 'yy'; - datepickerConfig.showWeeks = false; - datepickerConfig.yearRange = 10; - datepickerConfig.startingDay = 6; - - element = $compile('')($rootScope); + beforeEach(inject(function(uibDatepickerConfig) { + angular.extend(originalConfig, uibDatepickerConfig); + uibDatepickerConfig.formatDay = 'd'; + uibDatepickerConfig.formatMonth = 'MMM'; + uibDatepickerConfig.formatYear = 'yy'; + uibDatepickerConfig.formatDayHeader = 'EEEE'; + uibDatepickerConfig.formatDayTitle = 'MMM, yy'; + uibDatepickerConfig.formatMonthTitle = 'yy'; + uibDatepickerConfig.showWeeks = false; + uibDatepickerConfig.yearRange = 10; + uibDatepickerConfig.startingDay = 6; + + element = $compile('')($rootScope); $rootScope.$digest(); })); - afterEach(inject(function(datepickerConfig) { + afterEach(inject(function(uibDatepickerConfig) { // return it to the original state - angular.extend(datepickerConfig, originalConfig); + angular.extend(uibDatepickerConfig, originalConfig); })); it('changes the title format in `day` mode', function() { @@ -1237,16 +1236,16 @@ describe('datepicker directive', function() { describe('setting datepickerPopupConfig', function() { var originalConfig = {}; - beforeEach(inject(function(datepickerPopupConfig) { - angular.extend(originalConfig, datepickerPopupConfig); - datepickerPopupConfig.datepickerPopup = 'MM-dd-yyyy'; + beforeEach(inject(function(uibDatepickerPopupConfig) { + angular.extend(originalConfig, uibDatepickerPopupConfig); + uibDatepickerPopupConfig.datepickerPopup = 'MM-dd-yyyy'; - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); })); - afterEach(inject(function(datepickerPopupConfig) { + afterEach(inject(function(uibDatepickerPopupConfig) { // return it to the original state - angular.extend(datepickerPopupConfig, originalConfig); + angular.extend(uibDatepickerPopupConfig, originalConfig); })); it('changes date format', function() { @@ -1257,16 +1256,16 @@ describe('datepicker directive', function() { describe('setting datepickerPopupConfig inside ng-if', function() { var originalConfig = {}; - beforeEach(inject(function (datepickerPopupConfig) { - angular.extend(originalConfig, datepickerPopupConfig); - datepickerPopupConfig.datepickerPopup = 'MM-dd-yyyy'; + beforeEach(inject(function (uibDatepickerPopupConfig) { + angular.extend(originalConfig, uibDatepickerPopupConfig); + uibDatepickerPopupConfig.datepickerPopup = 'MM-dd-yyyy'; - element = $compile('
')($rootScope); + element = $compile('
')($rootScope); $rootScope.$digest(); })); - afterEach(inject(function (datepickerPopupConfig) { + afterEach(inject(function (uibDatepickerPopupConfig) { // return it to the original state - angular.extend(datepickerPopupConfig, originalConfig); + angular.extend(uibDatepickerPopupConfig, originalConfig); })); it('changes date format', function () { @@ -1295,7 +1294,7 @@ describe('datepicker directive', function() { $sniffer = _$sniffer_; $rootScope.isopen = true; $rootScope.date = new Date('September 30, 2010 15:30:00'); - var wrapElement = $compile('
')($rootScope); + var wrapElement = $compile('
')($rootScope); $rootScope.$digest(); assignElements(wrapElement); })); @@ -1318,7 +1317,7 @@ describe('datepicker directive', function() { $timeout = _$timeout_; $rootScope.isopen = true; $rootScope.date = new Date('September 30, 2010 15:30:00'); - wrapElement = $compile('
')($rootScope); + wrapElement = $compile('
')($rootScope); $rootScope.$digest(); assignElements(wrapElement); })); @@ -1474,7 +1473,7 @@ describe('datepicker directive', function() { $rootScope.date = new Date('September 30, 2010 15:30:00'); var wrapElement = $compile('
')($rootScope); + 'uib-datepicker-popup is-open="isopen">
')($rootScope); $rootScope.$digest(); assignElements(wrapElement); })); @@ -1599,7 +1598,7 @@ describe('datepicker directive', function() { function setupInputWithType(type) { var wrapElement = $compile('
')($rootScope); + type + '" ng-model="date" uib-datepicker-popup is-open="isopen">
')($rootScope); $rootScope.$digest(); assignElements(wrapElement); } @@ -1613,7 +1612,7 @@ describe('datepicker directive', function() { $rootScope.opts = { 'show-weeks': false }; - var wrapElement = $compile('
')($rootScope); + var wrapElement = $compile('
')($rootScope); $rootScope.$digest(); assignElements(wrapElement); }); @@ -1633,7 +1632,7 @@ describe('datepicker directive', function() { $rootScope.opts = { 'initDate': new Date('November 9, 1980') }; - var wrapElement = $compile('
')($rootScope); + var wrapElement = $compile('
')($rootScope); $rootScope.$digest(); assignElements(wrapElement); }); @@ -1656,7 +1655,7 @@ describe('datepicker directive', function() { describe('when initially set', function() { beforeEach(function() { - var wrapElement = $compile('
')($rootScope); + var wrapElement = $compile('
')($rootScope); $rootScope.$digest(); assignElements(wrapElement); }); @@ -1672,7 +1671,7 @@ describe('datepicker directive', function() { describe('when modified before date selected.', function() { beforeEach(function() { - var wrapElement = $compile('
')($rootScope); + var wrapElement = $compile('
')($rootScope); $rootScope.$digest(); assignElements(wrapElement); @@ -1691,7 +1690,7 @@ describe('datepicker directive', function() { describe('when modified after date selected.', function() { beforeEach(function() { - var wrapElement = $compile('
')($rootScope); + var wrapElement = $compile('
')($rootScope); $rootScope.$digest(); assignElements(wrapElement); $rootScope.date = new Date('April 1, 1982'); @@ -1714,7 +1713,7 @@ describe('datepicker directive', function() { beforeEach(inject(function() { $rootScope.open = true; - wrapElement = $compile('
')($rootScope); + wrapElement = $compile('
')($rootScope); $rootScope.$digest(); assignElements(wrapElement); })); @@ -1739,7 +1738,7 @@ describe('datepicker directive', function() { describe('custom format', function() { beforeEach(inject(function() { - var wrapElement = $compile('
')($rootScope); + var wrapElement = $compile('
')($rootScope); $rootScope.$digest(); assignElements(wrapElement); })); @@ -1764,7 +1763,7 @@ describe('datepicker directive', function() { describe('dynamic custom format', function() { beforeEach(inject(function() { $rootScope.format = 'dd-MMMM-yyyy'; - var wrapElement = $compile('
')($rootScope); + var wrapElement = $compile('
')($rootScope); $rootScope.$digest(); assignElements(wrapElement); })); @@ -1794,7 +1793,7 @@ describe('datepicker directive', function() { describe('european format', function() { it('dd.MM.yyyy', function() { - var wrapElement = $compile('
')($rootScope); + var wrapElement = $compile('
')($rootScope); $rootScope.$digest(); assignElements(wrapElement); @@ -1809,7 +1808,7 @@ describe('datepicker directive', function() { var wrapElement; beforeEach(inject(function() { $rootScope.close = false; - wrapElement = $compile('
')($rootScope); + wrapElement = $compile('
')($rootScope); $rootScope.$digest(); assignElements(wrapElement); })); @@ -1834,7 +1833,7 @@ describe('datepicker directive', function() { beforeEach(inject(function() { $rootScope.isopen = true; - wrapElement = $compile('
')($rootScope); + wrapElement = $compile('
')($rootScope); $rootScope.$digest(); assignElements(wrapElement); assignButtonBar(); @@ -1896,7 +1895,7 @@ describe('datepicker directive', function() { it('should change text from attributes', function() { $rootScope.clearText = 'Null it!'; $rootScope.close = 'Close'; - var wrapElement = $compile('
')($rootScope); + var wrapElement = $compile('
')($rootScope); $rootScope.$digest(); assignElements(wrapElement); assignButtonBar(); @@ -1908,7 +1907,7 @@ describe('datepicker directive', function() { it('should disable today button if before min date', function() { $rootScope.minDate = new Date().setDate(new Date().getDate() + 1); - var wrapElement = $compile('
')($rootScope); + var wrapElement = $compile('
')($rootScope); $rootScope.$digest(); assignElements(wrapElement); assignButtonBar(); @@ -1918,7 +1917,7 @@ describe('datepicker directive', function() { it('should disable today button if after max date', function() { $rootScope.maxDate = new Date().setDate(new Date().getDate() - 2); - var wrapElement = $compile('
')($rootScope); + var wrapElement = $compile('
')($rootScope); $rootScope.$digest(); assignElements(wrapElement); assignButtonBar(); @@ -1928,14 +1927,14 @@ describe('datepicker directive', function() { it('should remove bar', function() { $rootScope.showBar = false; - var wrapElement = $compile('
')($rootScope); + var wrapElement = $compile('
')($rootScope); $rootScope.$digest(); assignElements(wrapElement); expect(dropdownEl.find('li').length).toBe(1); }); it('should hide weeks column on popup', function() { - var wrapElement = $compile('
')($rootScope); + var wrapElement = $compile('
')($rootScope); $rootScope.$digest(); assignElements(wrapElement); @@ -1947,7 +1946,7 @@ describe('datepicker directive', function() { }); it('should show weeks column on popup', function() { - var wrapElement = $compile('
')($rootScope); + var wrapElement = $compile('
')($rootScope); $rootScope.$digest(); assignElements(wrapElement); @@ -1962,7 +1961,7 @@ describe('datepicker directive', function() { describe('`ng-change`', function() { beforeEach(inject(function() { $rootScope.changeHandler = jasmine.createSpy('changeHandler'); - var wrapElement = $compile('
')($rootScope); + var wrapElement = $compile('
')($rootScope); $rootScope.$digest(); assignElements(wrapElement); assignButtonBar(); @@ -1989,7 +1988,7 @@ describe('datepicker directive', function() { describe('`ng-required is true`', function() { beforeEach(inject(function() { $rootScope.date = ''; - var wrapElement = $compile('
')($rootScope); + var wrapElement = $compile('
')($rootScope); $rootScope.$digest(); assignElements(wrapElement); })); @@ -2013,7 +2012,7 @@ describe('datepicker directive', function() { describe('`ng-required is false`', function() { beforeEach(inject(function() { $rootScope.date = ''; - var wrapElement = $compile('
')($rootScope); + var wrapElement = $compile('
')($rootScope); $rootScope.$digest(); assignElements(wrapElement); })); @@ -2028,7 +2027,7 @@ describe('datepicker directive', function() { beforeEach(inject(function() { $rootScope.changeHandler = jasmine.createSpy('changeHandler'); $rootScope.date = new Date('09/16/2010'); - var wrapElement = $compile('
')($rootScope); + var wrapElement = $compile('
')($rootScope); $rootScope.$digest(); assignElements(wrapElement); })); @@ -2061,7 +2060,7 @@ describe('datepicker directive', function() { it('should allow custom templates for the popup', function() { $templateCache.put('foo/bar.html', '
baz
'); - var elm = angular.element('
'); + var elm = angular.element('
'); $compile(elm)($rootScope); $rootScope.$digest(); @@ -2082,12 +2081,12 @@ describe('datepicker directive', function() { it('should allow custom templates for the datepicker', function() { $templateCache.put('foo/bar.html', '
baz
'); - var elm = angular.element('
'); + var elm = angular.element('
'); $compile(elm)($rootScope); $rootScope.$digest(); - var datepicker = elm.find('[datepicker]'); + var datepicker = elm.find('[uib-datepicker]'); expect(datepicker.html()).toBe('baz'); }); @@ -2106,7 +2105,7 @@ describe('datepicker directive', function() { var $body = $document.find('body'), bodyLength = $body.children().length, elm = angular.element( - '
' + '
' ); $compile(elm)($rootScope); $rootScope.$digest(); @@ -2119,7 +2118,7 @@ describe('datepicker directive', function() { bodyLength = $body.children().length, isolatedScope = $rootScope.$new(), elm = angular.element( - '' + '' ); $compile(elm)(isolatedScope); isolatedScope.$digest(); @@ -2131,17 +2130,17 @@ describe('datepicker directive', function() { describe('with setting datepickerConfig.showWeeks to false', function() { var originalConfig = {}; - beforeEach(inject(function(datepickerConfig) { - angular.extend(originalConfig, datepickerConfig); - datepickerConfig.showWeeks = false; + beforeEach(inject(function(uibDatepickerConfig) { + angular.extend(originalConfig, uibDatepickerConfig); + uibDatepickerConfig.showWeeks = false; - var wrapElement = $compile('
')($rootScope); + var wrapElement = $compile('
')($rootScope); $rootScope.$digest(); assignElements(wrapElement); })); - afterEach(inject(function(datepickerConfig) { + afterEach(inject(function(uibDatepickerConfig) { // return it to the original state - angular.extend(datepickerConfig, originalConfig); + angular.extend(uibDatepickerConfig, originalConfig); })); it('changes initial visibility for weeks', function() { @@ -2157,7 +2156,7 @@ describe('datepicker directive', function() { beforeEach(inject(function() { $rootScope.date = new Date('August 11, 2013'); $rootScope.mode = 'month'; - var wrapElement = $compile('
')($rootScope); + var wrapElement = $compile('
')($rootScope); $rootScope.$digest(); assignElements(wrapElement); })); @@ -2177,7 +2176,7 @@ describe('datepicker directive', function() { beforeEach(function() { $rootScope.date = null; $rootScope.initDate = new Date('November 9, 1980'); - var wrapElement = $compile('
')($rootScope); + var wrapElement = $compile('
')($rootScope); $rootScope.$digest(); assignElements(wrapElement); }); @@ -2195,7 +2194,7 @@ describe('datepicker directive', function() { beforeEach(function() { $rootScope.date = null; $rootScope.isopen = false; - var wrapElement = $compile('
')($rootScope); + var wrapElement = $compile('
')($rootScope); $rootScope.$digest(); assignElements(wrapElement); }); @@ -2220,7 +2219,7 @@ describe('datepicker directive', function() { describe('with empty initial state', function() { beforeEach(inject(function() { $rootScope.date = null; - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); })); @@ -2247,7 +2246,7 @@ describe('datepicker directive', function() { beforeEach(inject(function() { $rootScope.date = null; $rootScope.initDate = new Date('November 9, 1980'); - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); })); @@ -2264,7 +2263,7 @@ describe('datepicker directive', function() { beforeEach(inject(function() { $rootScope.date = new Date('August 11, 2013'); $rootScope.mode = 'month'; - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); })); @@ -2283,7 +2282,7 @@ describe('datepicker directive', function() { $rootScope.date = new Date('August 11, 2013'); $rootScope.mode = 'month'; $rootScope.minMode = 'month'; - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); })); @@ -2311,7 +2310,7 @@ describe('datepicker directive', function() { beforeEach(inject(function() { $rootScope.date = new Date('August 11, 2013'); $rootScope.maxMode = 'month'; - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); })); @@ -2359,7 +2358,7 @@ describe('datepicker directive', function() { // Use dateModel directive to add formatters and parsers to the // ngModelController that translate the custom date object. - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); })); @@ -2378,14 +2377,13 @@ describe('datepicker directive', function() { }); }); - describe('thurdays determine week count', function() { - + describe('thursdays determine week count', function() { beforeEach(inject(function() { $rootScope.date = new Date('June 07, 2014'); })); it('with the default starting day (sunday)', function() { - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); expect(getWeeks()).toEqual(['23', '24', '25', '26', '27', '28']); @@ -2393,21 +2391,21 @@ describe('datepicker directive', function() { describe('when starting date', function() { it('is monday', function() { - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); expect(getWeeks()).toEqual(['22', '23', '24', '25', '26', '27']); }); it('is thursday', function() { - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); expect(getWeeks()).toEqual(['22', '23', '24', '25', '26', '27']); }); it('is saturday', function() { - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); expect(getWeeks()).toEqual(['23', '24', '25', '26', '27', '28']); @@ -2417,7 +2415,7 @@ describe('datepicker directive', function() { describe('first week in january', function() { it('in current year', function() { $rootScope.date = new Date('January 07, 2014'); - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); expect(getWeeks()).toEqual(['1', '2', '3', '4', '5', '6']); @@ -2425,7 +2423,7 @@ describe('datepicker directive', function() { it('in last year', function() { $rootScope.date = new Date('January 07, 2010'); - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); expect(getWeeks()).toEqual(['53', '1', '2', '3', '4', '5']); @@ -2438,7 +2436,7 @@ describe('datepicker directive', function() { })); it('in next year', function() { - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); expect(getWeeks()).toEqual(['49', '50', '51', '52', '1', '2']); @@ -2447,3 +2445,79 @@ describe('datepicker directive', function() { }); }); }); + +/* deprecation tests below */ + +describe('datepicker deprecation', function() { + beforeEach(module('ui.bootstrap.datepicker')); + beforeEach(module('template/datepicker/datepicker.html')); + beforeEach(module('template/datepicker/day.html')); + beforeEach(module('template/datepicker/month.html')); + beforeEach(module('template/datepicker/year.html')); + beforeEach(module('template/datepicker/popup.html')); + + it('should suppress warning', function() { + module(function($provide) { + $provide.value('$datepickerSuppressWarning', true); + }); + + inject(function($compile, $log, $rootScope) { + spyOn($log, 'warn'); + + var element = $compile('')($rootScope); + $rootScope.$digest(); + expect($log.warn.calls.count()).toBe(0); + }); + }); + + it('should give warning by default', inject(function($log) { + spyOn($log, 'warn'); + + inject(function($compile, $templateCache, $rootScope) { + var datepickerTemplate = + '
' + + '' + + '' + + ' ' + + '
'; + $templateCache.put('template/datepicker/datepicker.html', datepickerTemplate); + + var element = $compile('')($rootScope); + $rootScope.$digest(); + + expect($log.warn.calls.count()).toBe(3); + expect($log.warn.calls.argsFor(0)).toEqual(['DatepickerController is now deprecated. Use UibDatepickerController instead.']); + expect($log.warn.calls.argsFor(1)).toEqual(['datepicker is now deprecated. Use uib-datepicker instead.']); + expect($log.warn.calls.argsFor(2)).toEqual(['daypicker is now deprecated. Use uib-daypicker instead.']); + + $log.warn.calls.reset(); + + element = $compile('')($rootScope); + $rootScope.$digest(); + + expect($log.warn.calls.count()).toBe(3); + expect($log.warn.calls.argsFor(0)).toEqual(['DatepickerController is now deprecated. Use UibDatepickerController instead.']); + expect($log.warn.calls.argsFor(1)).toEqual(['datepicker is now deprecated. Use uib-datepicker instead.']); + expect($log.warn.calls.argsFor(2)).toEqual(['monthpicker is now deprecated. Use uib-monthpicker instead.']); + + $log.warn.calls.reset(); + + element = $compile('')($rootScope); + $rootScope.$digest(); + + expect($log.warn.calls.count()).toBe(3); + expect($log.warn.calls.argsFor(0)).toEqual(['DatepickerController is now deprecated. Use UibDatepickerController instead.']); + expect($log.warn.calls.argsFor(1)).toEqual(['datepicker is now deprecated. Use uib-datepicker instead.']); + expect($log.warn.calls.argsFor(2)).toEqual(['yearpicker is now deprecated. Use uib-yearpicker instead.']); + + $log.warn.calls.reset(); + + + element = $compile('')($rootScope); + $rootScope.$digest(); + + expect($log.warn.calls.count()).toBe(1); + expect($log.warn.calls.argsFor(0)).toEqual(['datepicker-popup is now deprecated. Use uib-datepicker-popup instead.']); + }); + })); +}); diff --git a/template/datepicker/datepicker.html b/template/datepicker/datepicker.html index 1ecb3c50b4..d515832e53 100644 --- a/template/datepicker/datepicker.html +++ b/template/datepicker/datepicker.html @@ -1,5 +1,5 @@
- - - + + +
\ No newline at end of file