Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

Commit

Permalink
feat(progressbar): add aria-labelledby support
Browse files Browse the repository at this point in the history
- Add `aria-labelledby` support for accessibility

Closes #4350
Resolves #4347
  • Loading branch information
wesleycho committed Sep 9, 2015
1 parent 9bdb32e commit e6f3b87
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 13 deletions.
5 changes: 4 additions & 1 deletion src/progressbar/docs/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@ It supports multiple (stacked) bars into the same `<uib-progress>` element or a
_(Default: true)_ :
Whether bars use transitions to achieve the width change.

* `title`
_(Default: progressbar)_ :
Title to use as label (for accessibility)

### Stacked ###

Place multiple `<uib-bar>`s into the same `<uib-progress>` element to stack them.
`<uib-progress>` supports `max` and `animate` & `<uib-bar>` supports `value` and `type` attributes.
`<uib-progress>` supports `max`, `animate`, and `title` & `<uib-bar>` supports `value`, `title`, and `type` attributes.
10 changes: 6 additions & 4 deletions src/progressbar/progressbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ angular.module('ui.bootstrap.progressbar', [])
this.bars = [];
$scope.max = angular.isDefined($scope.max) ? $scope.max : progressConfig.max;

this.addBar = function(bar, element) {
this.addBar = function(bar, element, attrs) {
if (!animate) {
element.css({'transition': 'none'});
}

this.bars.push(bar);

bar.max = $scope.max;
bar.title = attrs && angular.isDefined(attrs.title) ? attrs.title : 'progressbar';

bar.$watch('value', function(value) {
bar.recalculatePercentage();
Expand Down Expand Up @@ -79,7 +80,8 @@ angular.module('ui.bootstrap.progressbar', [])
controller: 'ProgressController',
require: 'progress',
scope: {
max: '=?'
max: '=?',
title: '@?'
},
templateUrl: 'template/progressbar/progress.html',
link: function() {
Expand All @@ -102,7 +104,7 @@ angular.module('ui.bootstrap.progressbar', [])
},
templateUrl: 'template/progressbar/bar.html',
link: function(scope, element, attrs, progressCtrl) {
progressCtrl.addBar(scope, element);
progressCtrl.addBar(scope, element, attrs);
}
};
})
Expand Down Expand Up @@ -140,7 +142,7 @@ angular.module('ui.bootstrap.progressbar', [])
},
templateUrl: 'template/progressbar/progressbar.html',
link: function(scope, element, attrs, progressCtrl) {
progressCtrl.addBar(scope, angular.element(element.children()[0]));
progressCtrl.addBar(scope, angular.element(element.children()[0]), {title: attrs.title});
}
};
});
52 changes: 47 additions & 5 deletions src/progressbar/test/progressbar.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ describe('progressbar directive', function() {
$compile = _$compile_;
$rootScope = _$rootScope_;
$rootScope.value = 22;
element = $compile('<progressbar animate="false" value="value">{{value}} %</progressbar>')($rootScope);
element = $compile('<progressbar animate="false" value="value" title="foo">{{value}} %</progressbar>')($rootScope);
$rootScope.$digest();
}));

Expand Down Expand Up @@ -81,6 +81,14 @@ describe('progressbar directive', function() {
expect(bar.attr('aria-valuemax')).toBe('100');
expect(bar.attr('aria-valuenow')).toBe('22');
expect(bar.attr('aria-valuetext')).toBe('22%');
expect(bar.attr('aria-labelledby')).toBe('foo');
});

it('has the default aria-labelledby value of `progressbar`', function() {
element = $compile('<progressbar animate="false" value="value">{{value}} %</progressbar>')($rootScope);
$rootScope.$digest();
var bar = getBar(0);
expect(bar.attr('aria-labelledby')).toBe('progressbar');
});

it('transcludes "bar" text', function() {
Expand Down Expand Up @@ -197,11 +205,11 @@ describe('progressbar directive', function() {
describe('stacked', function() {
beforeEach(inject(function() {
$rootScope.objects = [
{ value: 10, type: 'success' },
{ value: 50, type: 'warning' },
{ value: 20 }
{ value: 10, title: 'foo', type: 'success' },
{ value: 50, title: 'bar', type: 'warning' },
{ value: 20, title: 'baz' }
];
element = $compile('<uib-progress animate="false"><uib-bar ng-repeat="o in objects" value="o.value" type="{{o.type}}">{{o.value}}</uib-bar></uib-progress>')($rootScope);
element = $compile('<uib-progress animate="false"><uib-bar ng-repeat="o in objects" value="o.value" type="{{o.type}}" title="{{o.title}}">{{o.value}}</uib-bar></uib-progress>')($rootScope);
$rootScope.$digest();
}));

Expand Down Expand Up @@ -261,6 +269,40 @@ describe('progressbar directive', function() {
expect(getBar(0)).not.toHaveClass(BAR_CLASS + '-warning');
});

it('should have the correct aria markup', function() {
expect(getBar(0).attr('aria-valuenow')).toBe('10');
expect(getBar(0).attr('aria-valuemin')).toBe('0');
expect(getBar(0).attr('aria-valuemax')).toBe('100');
expect(getBar(0).attr('aria-valuetext')).toBe('10%');
expect(getBar(0).attr('aria-labelledby')).toBe('foo');

expect(getBar(1).attr('aria-valuenow')).toBe('50');
expect(getBar(1).attr('aria-valuemin')).toBe('0');
expect(getBar(1).attr('aria-valuemax')).toBe('100');
expect(getBar(1).attr('aria-valuetext')).toBe('50%');
expect(getBar(1).attr('aria-labelledby')).toBe('bar');

expect(getBar(2).attr('aria-valuenow')).toBe('20');
expect(getBar(2).attr('aria-valuemin')).toBe('0');
expect(getBar(2).attr('aria-valuemax')).toBe('100');
expect(getBar(2).attr('aria-valuetext')).toBe('20%');
expect(getBar(2).attr('aria-labelledby')).toBe('baz');
});

it('should default to `progressbar`', function() {
$rootScope.objects = [
{ value: 10, title: 'foo', type: 'success' },
{ value: 50, title: 'bar', type: 'warning' },
{ value: 20, title: 'baz' }
];
element = $compile('<uib-progress animate="false"><uib-bar ng-repeat="o in objects" value="o.value" type="{{o.type}}">{{o.value}}</uib-bar></uib-progress>')($rootScope);
$rootScope.$digest();

expect(getBar(0).attr('aria-labelledby')).toBe('progressbar');
expect(getBar(1).attr('aria-labelledby')).toBe('progressbar');
expect(getBar(2).attr('aria-labelledby')).toBe('progressbar');
});

describe('"max" attribute', function() {
beforeEach(inject(function() {
$rootScope.max = 200;
Expand Down
2 changes: 1 addition & 1 deletion template/progressbar/bar.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<div class="progress-bar" ng-class="type && 'progress-bar-' + type" role="progressbar" aria-valuenow="{{value}}" aria-valuemin="0" aria-valuemax="{{max}}" ng-style="{width: (percent < 100 ? percent : 100) + '%'}" aria-valuetext="{{percent | number:0}}%" style="min-width: 0;" ng-transclude></div>
<div class="progress-bar" ng-class="type && 'progress-bar-' + type" role="progressbar" aria-valuenow="{{value}}" aria-valuemin="0" aria-valuemax="{{max}}" ng-style="{width: (percent < 100 ? percent : 100) + '%'}" aria-valuetext="{{percent | number:0}}%" aria-labelledby="{{::title}}" style="min-width: 0;" ng-transclude></div>
2 changes: 1 addition & 1 deletion template/progressbar/progress.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<div class="progress" ng-transclude></div>
<div class="progress" ng-transclude aria-labelledby="{{::title}}"></div>
2 changes: 1 addition & 1 deletion template/progressbar/progressbar.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<div class="progress">
<div class="progress-bar" ng-class="type && 'progress-bar-' + type" role="progressbar" aria-valuenow="{{value}}" aria-valuemin="0" aria-valuemax="{{max}}" ng-style="{width: (percent < 100 ? percent : 100) + '%'}" aria-valuetext="{{percent | number:0}}%" style="min-width: 0;" ng-transclude></div>
<div class="progress-bar" ng-class="type && 'progress-bar-' + type" role="progressbar" aria-valuenow="{{value}}" aria-valuemin="0" aria-valuemax="{{max}}" ng-style="{width: (percent < 100 ? percent : 100) + '%'}" aria-valuetext="{{percent | number:0}}%" aria-labelledby="{{::title}}" style="min-width: 0;" ng-transclude></div>
</div>

0 comments on commit e6f3b87

Please sign in to comment.