From 2b78dd16abd7e09846fa484331b5c35ece6619a2 Mon Sep 17 00:00:00 2001 From: tbekos Date: Tue, 14 May 2013 13:37:18 +0300 Subject: [PATCH] feat(tabs): support disabled state --- src/tabs/docs/demo.html | 14 ++++---- src/tabs/docs/demo.js | 2 +- src/tabs/docs/readme.md | 2 +- src/tabs/tabs.js | 17 +++++++-- src/tabs/test/tabsSpec.js | 76 +++++++++++++++++++++++++++++++++++++++ template/tabs/tab.html | 2 +- 6 files changed, 100 insertions(+), 13 deletions(-) diff --git a/src/tabs/docs/demo.html b/src/tabs/docs/demo.html index a2ea432981..f910358aab 100644 --- a/src/tabs/docs/demo.html +++ b/src/tabs/docs/demo.html @@ -1,16 +1,14 @@
Select a tab by setting active binding to true:
- - -

+ + + +
+ Static content - + {{tab.content}} diff --git a/src/tabs/docs/demo.js b/src/tabs/docs/demo.js index e68cd8e2dc..5df7826cb7 100644 --- a/src/tabs/docs/demo.js +++ b/src/tabs/docs/demo.js @@ -1,7 +1,7 @@ var TabsDemoCtrl = function ($scope) { $scope.tabs = [ { title:"Dynamic Title 1", content:"Dynamic content 1" }, - { title:"Dynamic Title 2", content:"Dynamic content 2" } + { title:"Dynamic Title 2", content:"Dynamic content 2", disabled: true } ]; $scope.alertMe = function() { diff --git a/src/tabs/docs/readme.md b/src/tabs/docs/readme.md index 620b63045e..150856c5fe 100644 --- a/src/tabs/docs/readme.md +++ b/src/tabs/docs/readme.md @@ -1,5 +1,5 @@ AngularJS version of the tabs directive. -Allows a `select` callback attribute, and `active` binding attribute. +Allows a `select` callback attribute, `active` binding attribute and `disabled` binding attribute. Allows either `heading` text-heading as an attribute, or a `` element inside as the heading. diff --git a/src/tabs/tabs.js b/src/tabs/tabs.js index 2d3d0a5c62..e47a7ab48d 100644 --- a/src/tabs/tabs.js +++ b/src/tabs/tabs.js @@ -71,7 +71,11 @@ function($parse, $http, $templateCache, $compile) { getActive = $parse(attrs.active); setActive = getActive.assign; scope.$parent.$watch(getActive, function updateActive(value) { - scope.active = !!value; + if ( !!value && scope.disabled ) { + setActive(scope.$parent, false); // Prevent active assignment + } else { + scope.active = !!value; + } }); } else { setActive = getActive = angular.noop; @@ -85,8 +89,17 @@ function($parse, $http, $templateCache, $compile) { } }); + scope.disabled = false; + if ( attrs.disabled ) { + scope.$parent.$watch($parse(attrs.disabled), function(value) { + scope.disabled = !! value; + }); + } + scope.select = function() { - scope.active = true; + if ( ! scope.disabled ) { + scope.active = true; + } }; tabsetCtrl.addTab(scope); diff --git a/src/tabs/test/tabsSpec.js b/src/tabs/test/tabsSpec.js index 74002e152f..3ca08ac9f9 100644 --- a/src/tabs/test/tabsSpec.js +++ b/src/tabs/test/tabsSpec.js @@ -378,4 +378,80 @@ describe('tabs', function() { expect(contents().eq(2)).toHaveClass('active'); })); }); + + describe('disabled', function() { + beforeEach(inject(function($compile, $rootScope) { + scope = $rootScope.$new(); + + function makeTab(disabled) { + return { + active: false, + select: jasmine.createSpy(), + disabled: disabled + }; + } + scope.tabs = [ + makeTab(false), makeTab(true), makeTab(false), makeTab(true) + ]; + elm = $compile([ + '', + ' ', + ' heading {{index}}', + ' content {{$index}}', + ' ', + '' + ].join('\n'))(scope); + scope.$apply(); + })); + + function titles() { + return elm.find('ul.nav-tabs li'); + } + function contents() { + return elm.find('div.tab-content div.tab-pane'); + } + + function expectTabActive(activeTab) { + var _titles = titles(); + angular.forEach(scope.tabs, function(tab, i) { + if (activeTab === tab) { + expect(tab.active).toBe(true); + expect(tab.select.callCount).toBe( (tab.disabled) ? 0 : 1 ); + expect(_titles.eq(i)).toHaveClass('active'); + expect(contents().eq(i).text().trim()).toBe('content ' + i); + expect(contents().eq(i)).toHaveClass('active'); + } else { + expect(tab.active).toBe(false); + expect(_titles.eq(i)).not.toHaveClass('active'); + } + }); + } + + it('should not switch active when clicking on title', function() { + titles().eq(2).find('a').click(); + expectTabActive(scope.tabs[2]); + + titles().eq(3).find('a').click(); + expectTabActive(scope.tabs[2]); + }); + + it('should not switch active when setting active=true', function() { + scope.$apply('tabs[2].active = true'); + expectTabActive(scope.tabs[2]); + + scope.$apply('tabs[3].active = true'); + expectTabActive(scope.tabs[2]); + }); + + it('should toggle between states', function() { + expect(titles().eq(3)).toHaveClass('disabled'); + scope.$apply('tabs[3].disabled = false'); + expect(titles().eq(3)).not.toHaveClass('disabled'); + + expect(titles().eq(2)).not.toHaveClass('disabled'); + scope.$apply('tabs[2].disabled = true'); + expect(titles().eq(2)).toHaveClass('disabled'); + }); + }); + }); diff --git a/template/tabs/tab.html b/template/tabs/tab.html index d8b06452e5..aedd7ef379 100644 --- a/template/tabs/tab.html +++ b/template/tabs/tab.html @@ -1,3 +1,3 @@ -
  • +
  • {{heading}}