diff --git a/src/components/button/button.js b/src/components/button/button.js index d7346e3e7f3..9211d85746b 100644 --- a/src/components/button/button.js +++ b/src/components/button/button.js @@ -59,11 +59,9 @@ function MdButtonDirective($mdInkRipple, $mdTheming, $mdAria) { } function getTemplate(element, attr) { - if (isAnchor(attr)) { - return ''; - } else { - return ''; - } + return isAnchor(attr) ? + '' : + ''; } function postLink(scope, element, attr) { @@ -78,8 +76,8 @@ function MdButtonDirective($mdInkRipple, $mdTheming, $mdAria) { // For anchor elements, we have to set tabindex manually when the // element is disabled - if (isAnchor(attr)) { - scope.$watch(function() {return attr.ngDisabled;}, function(isDisabled) { + if (isAnchor(attr) && angular.isDefined(attr.ngDisabled) ) { + scope.$watch(attr.ngDisabled, function(isDisabled) { element.attr('tabindex', isDisabled ? -1 : 0); }); } diff --git a/src/components/button/button.spec.js b/src/components/button/button.spec.js index 31e9b58f259..614504d0184 100644 --- a/src/components/button/button.spec.js +++ b/src/components/button/button.spec.js @@ -3,23 +3,20 @@ describe('md-button', function() { beforeEach(TestUtil.mockRaf); beforeEach(module('material.components.button')); - it('should be anchor if href attr', inject(function($compile, $rootScope) { - var button = $compile('')($rootScope.$new()); + it('should convert attributes on an md-button to attributes on the generated button', inject(function($compile, $rootScope) { + var button = $compile('')($rootScope); $rootScope.$apply(); - expect(button[0].tagName.toLowerCase()).toEqual('a'); + expect(button[0].hasAttribute('hide')).toBe(true); + expect(button[0].hasAttribute('hide-sm')).toBe(true); })); - it('should be anchor if ng-href attr', inject(function($compile, $rootScope) { - var button = $compile('')($rootScope.$new()); - $rootScope.$apply(); - expect(button[0].tagName.toLowerCase()).toEqual('a'); + it('should only have one ripple container when a custom ripple color is set', inject(function ($compile, $rootScope, $timeout) { + var button = $compile('button')($rootScope); + var scope = button.eq(0).scope(); + scope._onInput({ isFirst: true, eventType: Hammer.INPUT_START, center: { x: 0, y: 0 } }); + expect(button[0].getElementsByClassName('md-ripple-container').length).toBe(1); })); - it('should be button otherwise', inject(function($compile, $rootScope) { - var button = $compile('')($rootScope.$new()); - $rootScope.$apply(); - expect(button[0].tagName.toLowerCase()).toEqual('button'); - })); it('should expect an aria-label if element has no text', inject(function($compile, $rootScope, $log) { spyOn($log, 'warn'); @@ -33,18 +30,62 @@ describe('md-button', function() { expect($log.warn).not.toHaveBeenCalled(); })); - it('should convert attributes on an md-button to attributes on the generated button', inject(function($compile, $rootScope) { - var button = $compile('')($rootScope); - $rootScope.$apply(); - expect(button[0].hasAttribute('hide')).toBe(true); - expect(button[0].hasAttribute('hide-sm')).toBe(true); - })); - it('should only have one ripple container when a custom ripple color is set', inject(function ($compile, $rootScope, $timeout) { - var button = $compile('button')($rootScope); - var scope = button.eq(0).scope(); - scope._onInput({ isFirst: true, eventType: Hammer.INPUT_START, center: { x: 0, y: 0 } }); - expect(button[0].getElementsByClassName('md-ripple-container').length).toBe(1); - })); + describe('with href or ng-href', function() { + + it('should be anchor if href attr', inject(function($compile, $rootScope) { + var button = $compile('')($rootScope.$new()); + $rootScope.$apply(); + expect(button[0].tagName.toLowerCase()).toEqual('a'); + })); + + it('should be anchor if ng-href attr', inject(function($compile, $rootScope) { + var button = $compile('')($rootScope.$new()); + $rootScope.$apply(); + expect(button[0].tagName.toLowerCase()).toEqual('a'); + })); + + it('should be button otherwise', inject(function($compile, $rootScope) { + var button = $compile('')($rootScope.$new()); + $rootScope.$apply(); + expect(button[0].tagName.toLowerCase()).toEqual('button'); + })); + + }); + + + describe('with ng-disabled', function() { + + it('should not set `tabindex` when used without anchor attributes', inject(function ($compile, $rootScope, $timeout) { + var scope = angular.extend( $rootScope.$new(), { isDisabled : true } ); + var button = $compile('button')(scope); + $rootScope.$apply(); + + expect(button[0].hasAttribute('tabindex')).toBe(false); + })); + + it('should set `tabindex == -1` when used with href', inject(function ($compile, $rootScope, $timeout) { + var scope = angular.extend( $rootScope.$new(), { isDisabled : true } ); + var button = $compile('button')(scope); + + $rootScope.$apply(); + expect(button.attr('tabindex')).toBe("-1"); + + $rootScope.$apply(function(){ + scope.isDisabled = false; + }); + expect(button.attr('tabindex')).toBe("0"); + + })); + + it('should set `tabindex == -1` when used with ng-href', inject(function ($compile, $rootScope, $timeout) { + var scope = angular.extend( $rootScope.$new(), { isDisabled : true, url : "http://material.angularjs.org" }); + var button = $compile('button')(scope); + $rootScope.$apply(); + + expect(button.attr('tabindex')).toBe("-1"); + })); + + }) });