diff --git a/src/datepicker/datepicker.js b/src/datepicker/datepicker.js
index 0d9d078294..3cc489d22f 100644
--- a/src/datepicker/datepicker.js
+++ b/src/datepicker/datepicker.js
@@ -14,6 +14,26 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.position'])
maxDate: null
})
+.service('DatepickerService', ['datepickerConfig', function(datepickerConfig) {
+ var WATCHABLE_KEYS = ['showWeeks', 'minDate', 'maxDate'];
+
+ function styleHyphenFormat(propertyName) {
+ function upperToHyphenLower(match) {
+ return '-' + match.toLowerCase();
+ }
+ return propertyName.replace(/[A-Z]/g, upperToHyphenLower);
+ }
+
+ this.collectConfigAttributes = function(attrs, callback) {
+ var currentKey;
+ for (currentKey in attrs) {
+ if (datepickerConfig.hasOwnProperty(currentKey)) {
+ callback(attrs[currentKey], currentKey, styleHyphenFormat(currentKey), WATCHABLE_KEYS.indexOf(currentKey) !== -1);
+ }
+ }
+ };
+}])
+
.controller('DatepickerController', ['$scope', '$attrs', 'dateFilter', 'datepickerConfig', function($scope, $attrs, dateFilter, dtConfig) {
var format = {
day: getValue($attrs.dayFormat, dtConfig.dayFormat),
@@ -134,7 +154,8 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.position'])
require: ['datepicker', '?^ngModel'],
controller: 'DatepickerController',
link: function(scope, element, attrs, ctrls) {
- var datepickerCtrl = ctrls[0], ngModel = ctrls[1];
+ var datepickerCtrl = ctrls[0], ngModel = ctrls[1],
+ minDate = attrs.min || attrs.minDate, maxDate = attrs.max || attrs.maxDate;
if (!ngModel) {
return; // do nothing if no ng-model
@@ -152,14 +173,14 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.position'])
updateShowWeekNumbers();
}
- if (attrs.min) {
- scope.$parent.$watch($parse(attrs.min), function(value) {
+ if (minDate) {
+ scope.$parent.$watch($parse(minDate), function(value) {
datepickerCtrl.minDate = value ? new Date(value) : null;
refill();
});
}
- if (attrs.max) {
- scope.$parent.$watch($parse(attrs.max), function(value) {
+ if (maxDate) {
+ scope.$parent.$watch($parse(maxDate), function(value) {
datepickerCtrl.maxDate = value ? new Date(value) : null;
refill();
});
@@ -260,8 +281,8 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.position'])
closeOnDateSelection: true
})
-.directive('datepickerPopup', ['$compile', '$parse', '$document', '$position', 'dateFilter', 'datepickerPopupConfig',
-function ($compile, $parse, $document, $position, dateFilter, datepickerPopupConfig) {
+.directive('datepickerPopup', ['$compile', '$parse', '$document', '$position', 'dateFilter', 'datepickerPopupConfig', 'DatepickerService',
+function ($compile, $parse, $document, $position, dateFilter, datepickerPopupConfig, DatepickerService) {
return {
restrict: 'EA',
require: 'ngModel',
@@ -397,14 +418,23 @@ function ($compile, $parse, $document, $position, dateFilter, datepickerPopupCon
datepickerEl.attr(datepickerAttribute || scopeProperty, scopeProperty);
}
}
- addWatchableAttribute(attrs.min, 'min');
- addWatchableAttribute(attrs.max, 'max');
- if (attrs.showWeeks) {
- addWatchableAttribute(attrs.showWeeks, 'showWeeks', 'show-weeks');
- } else {
- scope.showWeeks = true;
- datepickerEl.attr('show-weeks', 'showWeeks');
+
+ DatepickerService.collectConfigAttributes(attrs, function(attribute, scopeProperty, datepickerAttribute, watchable) {
+ if (watchable) {
+ addWatchableAttribute(attribute, scopeProperty, datepickerAttribute);
+ } else {
+ datepickerEl.attr(datepickerAttribute, attribute);
+ }
+ });
+
+ if (!datepickerEl.attr('min-date') && attrs.min) {
+ addWatchableAttribute(attrs.min, 'min');
}
+
+ if (!datepickerEl.attr('max-date') && attrs.max) {
+ addWatchableAttribute(attrs.max, 'max');
+ }
+
if (attrs.dateDisabled) {
datepickerEl.attr('date-disabled', attrs.dateDisabled);
}
diff --git a/src/datepicker/test/datepicker.spec.js b/src/datepicker/test/datepicker.spec.js
index baf3415e0f..7aeffd89ab 100644
--- a/src/datepicker/test/datepicker.spec.js
+++ b/src/datepicker/test/datepicker.spec.js
@@ -1240,6 +1240,204 @@ describe('datepicker directive', function () {
expect(inputEl.val()).toBe('pizza');
});
});
+
+ describe('with `show-weeks` attribute', function() {
+ beforeEach(inject(function () {
+ $rootScope.showWeeks = false;
+ var wrapElement = $compile('
')($rootScope);
+ $rootScope.$digest();
+ assignElements(wrapElement);
+ }));
+
+ it('to hide weeks column', function() {
+ expect(getWeeks()).toEqual(['', '', '', '', '']);
+ });
+ it('to show weeks column', function() {
+ $rootScope.showWeeks = true;
+ $rootScope.$digest();
+ expect(getWeeks()).toEqual(["34", "35", "36", "37", "38"]);
+ });
+ });
+
+ describe('with `min` attribute', function() {
+ beforeEach(function () {
+ $rootScope.mindate = new Date("September 12, 2010");
+ element = $compile('
')($rootScope);
+ $rootScope.$digest();
+ });
+
+ it('disables appropriate days in current month', function () {
+ for (var i = 0; i < 5; i++) {
+ for (var j = 0; j < 7; j++) {
+ expect(isDisabledOption(i, j)).toBe((i < 2));
+ }
+ }
+ });
+
+ it('disables appropriate days when min date changes', function() {
+ $rootScope.mindate = new Date("September 5, 2010");
+ $rootScope.$digest();
+ for (var i = 0; i < 5; i ++) {
+ for (var j = 0; j < 7; j ++) {
+ expect(isDisabledOption(i, j)).toBe( (i < 1) );
+ }
+ }
+ });
+ });
+
+ describe('with `minDate` attribute', function() {
+ beforeEach(function () {
+ $rootScope.mindate = new Date("September 12, 2010");
+ element = $compile('
')($rootScope);
+ $rootScope.$digest();
+ });
+
+ it('disables appropriate days in current month', function () {
+ for (var i = 0; i < 5; i++) {
+ for (var j = 0; j < 7; j++) {
+ expect(isDisabledOption(i, j)).toBe((i < 2));
+ }
+ }
+ });
+
+ it('disables appropriate days when min date changes', function() {
+ $rootScope.mindate = new Date("September 5, 2010");
+ $rootScope.$digest();
+ for (var i = 0; i < 5; i ++) {
+ for (var j = 0; j < 7; j ++) {
+ expect(isDisabledOption(i, j)).toBe( (i < 1) );
+ }
+ }
+ });
+ });
+
+ describe('with `max` attribute', function() {
+ beforeEach(function() {
+ $rootScope.maxdate = new Date("September 25, 2010");
+ element = $compile('
')($rootScope);
+ $rootScope.$digest();
+ });
+
+ it('disables appropriate days in current month', function() {
+ for (var i = 0; i < 5; i ++) {
+ for (var j = 0; j < 7; j ++) {
+ expect(isDisabledOption(i, j)).toBe( (i === 4) );
+ }
+ }
+ });
+
+ it('disables appropriate days when max date changes', function() {
+ $rootScope.maxdate = new Date("September 18, 2010");
+ $rootScope.$digest();
+ for (var i = 0; i < 5; i ++) {
+ for (var j = 0; j < 7; j ++) {
+ expect(isDisabledOption(i, j)).toBe( (i > 2) );
+ }
+ }
+ });
+ });
+
+ describe('with `maxDate` attribute', function() {
+ beforeEach(function() {
+ $rootScope.maxdate = new Date("September 25, 2010");
+ element = $compile('
')($rootScope);
+ $rootScope.$digest();
+ });
+
+ it('disables appropriate days in current month', function() {
+ for (var i = 0; i < 5; i ++) {
+ for (var j = 0; j < 7; j ++) {
+ expect(isDisabledOption(i, j)).toBe( (i === 4) );
+ }
+ }
+ });
+
+ it('disables appropriate days when max date changes', function() {
+ $rootScope.maxdate = new Date("September 18, 2010");
+ $rootScope.$digest();
+ for (var i = 0; i < 5; i ++) {
+ for (var j = 0; j < 7; j ++) {
+ expect(isDisabledOption(i, j)).toBe( (i > 2) );
+ }
+ }
+ });
+ });
+
+ describe('with `day-title-format` attribute', function() {
+ beforeEach(function() {
+ $rootScope.maxdate = new Date("September 25, 2010");
+ element = $compile('
')($rootScope);
+ $rootScope.$digest();
+ });
+
+ it('changes the title format in `day` mode', function() {
+ expect(getTitle()).toBe('September, 10');
+ });
+ });
+
+ describe('with datepickerOptions', function() {
+ beforeEach(inject(function() {
+ $rootScope.datepickerOptions = {
+ 'starting-day': 6,
+ 'show-weeks': false,
+ 'day-format': "'d'",
+ 'month-format': "'MMM'",
+ 'year-format': "'yy'",
+ 'year-range': 10,
+ 'day-header-format': "'EEEE'",
+ 'day-title-format': "'MMMM, yy'",
+ 'month-title-format': "'yy'"
+ };
+
+ element = $compile('
')($rootScope);
+ $rootScope.$digest();
+ }));
+
+ it('changes the title format in `day` mode', function() {
+ expect(getTitle()).toBe('September, 10');
+ });
+
+ it('changes the title & months format in `month` mode', function() {
+ clickTitleButton();
+
+ expect(getTitle()).toBe('10');
+ expect(getOptions()).toEqual([
+ ['Jan', 'Feb', 'Mar'],
+ ['Apr', 'May', 'Jun'],
+ ['Jul', 'Aug', 'Sep'],
+ ['Oct', 'Nov', 'Dec']
+ ]);
+ });
+
+ it('changes the title, year format & range in `year` mode', function() {
+ clickTitleButton(2);
+
+ expect(getTitle()).toBe('01 - 10');
+ expect(getOptions()).toEqual([
+ ['01', '02', '03', '04', '05'],
+ ['06', '07', '08', '09', '10']
+ ]);
+ });
+
+ it('changes the `starting-day` & day headers & format', function() {
+ expect(getLabels()).toEqual(['Saturday', 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']);
+ expect(getOptions()).toEqual([
+ ['28', '29', '30', '31', '1', '2', '3'],
+ ['4', '5', '6', '7', '8', '9', '10'],
+ ['11', '12', '13', '14', '15', '16', '17'],
+ ['18', '19', '20', '21', '22', '23', '24'],
+ ['25', '26', '27', '28', '29', '30', '1']
+ ]);
+ });
+
+ it('changes initial visibility for weeks', function() {
+ expect(getLabelsRow().find('th').eq(0).css('display')).toBe('none');
+ var tr = element.find('tbody').find('tr');
+ for (var i = 0; i < 5; i++) {
+ expect(tr.eq(i).find('td').eq(0).css('display')).toBe('none');
+ }
+ });
+ });
});
});