diff --git a/src/datepicker/datepicker.js b/src/datepicker/datepicker.js index 05d15468de..eb51ef2312 100644 --- a/src/datepicker/datepicker.js +++ b/src/datepicker/datepicker.js @@ -75,6 +75,14 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst this.activeDate = new Date(); } + $scope.disabled = angular.isDefined($attrs.disabled) || false; + if (angular.isDefined($attrs.ngDisabled)) { + $scope.$parent.$watch($parse($attrs.ngDisabled), function(disabled) { + $scope.disabled = disabled; + self.refreshView(); + }); + } + $scope.isActive = function(dateObject) { if (self.compare(dateObject.date, self.activeDate) === 0) { $scope.activeDateId = dateObject.uid; @@ -127,7 +135,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst }; this.isDisabled = function(date) { - return ((this.minDate && this.compare(date, this.minDate) < 0) || (this.maxDate && this.compare(date, this.maxDate) > 0) || ($attrs.dateDisabled && $scope.dateDisabled({date: date, mode: $scope.datepickerMode}))); + return $scope.disabled || ((this.minDate && this.compare(date, this.minDate) < 0) || (this.maxDate && this.compare(date, this.maxDate) > 0) || ($attrs.dateDisabled && $scope.dateDisabled({date: date, mode: $scope.datepickerMode}))); }; this.customClass = function(date) { @@ -185,7 +193,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst $scope.keydown = function(evt) { var key = $scope.keys[evt.which]; - if (!key || evt.shiftKey || evt.altKey) { + if (!key || evt.shiftKey || evt.altKey || $scope.disabled) { return; } @@ -626,6 +634,7 @@ function(scope, element, attrs, $compile, $parse, $document, $rootScope, $positi } } }); + if (attrs.dateDisabled) { datepickerEl.attr('date-disabled', 'dateDisabled({ date: date, mode: mode })'); } @@ -743,17 +752,28 @@ function(scope, element, attrs, $compile, $parse, $document, $rootScope, $positi element[0].focus(); }; + scope.disabled = angular.isDefined(attrs.disabled) || false; + if (attrs.ngDisabled) { + scope.$parent.$watch($parse(attrs.ngDisabled), function(disabled) { + scope.disabled = disabled; + }); + } + 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 (!scope.disabled) { + scope.position = appendToBody ? $position.offset(element) : $position.position(element); + scope.position.top = scope.position.top + element.prop('offsetHeight'); - $timeout(function() { - if (onOpenFocus) { - scope.$broadcast('uib:datepicker.focus'); - } - $document.bind('click', documentClickBind); - }, 0, false); + $timeout(function() { + if (onOpenFocus) { + scope.$broadcast('uib:datepicker.focus'); + } + $document.bind('click', documentClickBind); + }, 0, false); + } else { + scope.isOpen = false; + } } else { $document.unbind('click', documentClickBind); } @@ -808,6 +828,10 @@ function(scope, element, attrs, $compile, $parse, $document, $rootScope, $positi } function documentClickBind(event) { + if (!scope.isOpen && scope.disabled) { + return; + } + var popup = $popup[0]; var dpContainsTarget = element[0].contains(event.target); // The popup node may not be an element node diff --git a/src/datepicker/test/datepicker.spec.js b/src/datepicker/test/datepicker.spec.js index b2fe50336d..e709bbf82d 100644 --- a/src/datepicker/test/datepicker.spec.js +++ b/src/datepicker/test/datepicker.spec.js @@ -1226,6 +1226,47 @@ describe('datepicker directive', function() { }); }); + describe('disabled', function() { + beforeEach(function() { + element = $compile('')($rootScope); + $rootScope.$digest(); + }); + + it('should have all dates disabled', function() { + element.find('.uib-day button').each(function(idx, elem) { + expect($(elem).prop('disabled')).toBe(true); + }); + }); + }); + + describe('ng-disabled', function() { + beforeEach(function() { + $rootScope.disabled = false; + element = $compile('')($rootScope); + $rootScope.$digest(); + }); + + it('should toggle disabled state with value of ng-disabled', function() { + element.find('.uib-day button').each(function(idx, elem) { + expect($(elem).prop('disabled')).toBe(false); + }); + + $rootScope.disabled = true; + $rootScope.$digest(); + + element.find('.uib-day button').each(function(idx, elem) { + expect($(elem).prop('disabled')).toBe(true); + }); + + $rootScope.disabled = false; + $rootScope.$digest(); + + element.find('.uib-day button').each(function(idx, elem) { + expect($(elem).prop('disabled')).toBe(false); + }); + }); + }); + describe('setting datepickerPopupConfig', function() { var originalConfig = {}; beforeEach(inject(function(uibDatepickerPopupConfig) { @@ -2040,6 +2081,63 @@ describe('datepicker directive', function() { }); }); + describe('with disabled', function() { + var wrapElement; + + beforeEach(function() { + $rootScope.isOpen = false; + wrapElement = $compile('
')($rootScope); + $rootScope.$digest(); + }); + + it('should not open the popup', function() { + $rootScope.isOpen = true; + $rootScope.$digest(); + + expect($rootScope.isOpen).toBe(false); + expect(wrapElement.find('ul').length).toBe(0); + }); + }); + + describe('with ng-disabled', function() { + var wrapElement; + + beforeEach(function() { + $rootScope.disabled = false; + $rootScope.isOpen = false; + wrapElement = $compile('
')($rootScope); + $rootScope.$digest(); + }); + + it('should not open the popup when disabled', function() { + $rootScope.isOpen = true; + $rootScope.$digest(); + + expect($rootScope.isOpen).toBe(true); + expect(wrapElement.find('ul').length).toBe(1); + + $rootScope.isOpen = false; + $rootScope.$digest(); + + expect($rootScope.isOpen).toBe(false); + expect(wrapElement.find('ul').length).toBe(0); + + $rootScope.disabled = true; + $rootScope.isOpen = true; + $rootScope.$digest(); + + expect($rootScope.isOpen).toBe(false); + expect(wrapElement.find('ul').length).toBe(0); + + $rootScope.disabled = false; + $rootScope.isOpen = true; + $rootScope.$digest(); + + expect($rootScope.isOpen).toBe(true); + expect(wrapElement.find('ul').length).toBe(1); + }); + }); + describe('with datepicker-popup-template-url', function() { beforeEach(function() { $rootScope.date = new Date();