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

Commit e6f3b87

Browse files
committed
feat(progressbar): add aria-labelledby support
- Add `aria-labelledby` support for accessibility Closes #4350 Resolves #4347
1 parent 9bdb32e commit e6f3b87

File tree

6 files changed

+60
-13
lines changed

6 files changed

+60
-13
lines changed

Diff for: src/progressbar/docs/readme.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,11 @@ It supports multiple (stacked) bars into the same `<uib-progress>` element or a
2222
_(Default: true)_ :
2323
Whether bars use transitions to achieve the width change.
2424

25+
* `title`
26+
_(Default: progressbar)_ :
27+
Title to use as label (for accessibility)
2528

2629
### Stacked ###
2730

2831
Place multiple `<uib-bar>`s into the same `<uib-progress>` element to stack them.
29-
`<uib-progress>` supports `max` and `animate` & `<uib-bar>` supports `value` and `type` attributes.
32+
`<uib-progress>` supports `max`, `animate`, and `title` & `<uib-bar>` supports `value`, `title`, and `type` attributes.

Diff for: src/progressbar/progressbar.js

+6-4
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,15 @@ angular.module('ui.bootstrap.progressbar', [])
1414
this.bars = [];
1515
$scope.max = angular.isDefined($scope.max) ? $scope.max : progressConfig.max;
1616

17-
this.addBar = function(bar, element) {
17+
this.addBar = function(bar, element, attrs) {
1818
if (!animate) {
1919
element.css({'transition': 'none'});
2020
}
2121

2222
this.bars.push(bar);
2323

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

2627
bar.$watch('value', function(value) {
2728
bar.recalculatePercentage();
@@ -79,7 +80,8 @@ angular.module('ui.bootstrap.progressbar', [])
7980
controller: 'ProgressController',
8081
require: 'progress',
8182
scope: {
82-
max: '=?'
83+
max: '=?',
84+
title: '@?'
8385
},
8486
templateUrl: 'template/progressbar/progress.html',
8587
link: function() {
@@ -102,7 +104,7 @@ angular.module('ui.bootstrap.progressbar', [])
102104
},
103105
templateUrl: 'template/progressbar/bar.html',
104106
link: function(scope, element, attrs, progressCtrl) {
105-
progressCtrl.addBar(scope, element);
107+
progressCtrl.addBar(scope, element, attrs);
106108
}
107109
};
108110
})
@@ -140,7 +142,7 @@ angular.module('ui.bootstrap.progressbar', [])
140142
},
141143
templateUrl: 'template/progressbar/progressbar.html',
142144
link: function(scope, element, attrs, progressCtrl) {
143-
progressCtrl.addBar(scope, angular.element(element.children()[0]));
145+
progressCtrl.addBar(scope, angular.element(element.children()[0]), {title: attrs.title});
144146
}
145147
};
146148
});

Diff for: src/progressbar/test/progressbar.spec.js

+47-5
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ describe('progressbar directive', function() {
5151
$compile = _$compile_;
5252
$rootScope = _$rootScope_;
5353
$rootScope.value = 22;
54-
element = $compile('<progressbar animate="false" value="value">{{value}} %</progressbar>')($rootScope);
54+
element = $compile('<progressbar animate="false" value="value" title="foo">{{value}} %</progressbar>')($rootScope);
5555
$rootScope.$digest();
5656
}));
5757

@@ -81,6 +81,14 @@ describe('progressbar directive', function() {
8181
expect(bar.attr('aria-valuemax')).toBe('100');
8282
expect(bar.attr('aria-valuenow')).toBe('22');
8383
expect(bar.attr('aria-valuetext')).toBe('22%');
84+
expect(bar.attr('aria-labelledby')).toBe('foo');
85+
});
86+
87+
it('has the default aria-labelledby value of `progressbar`', function() {
88+
element = $compile('<progressbar animate="false" value="value">{{value}} %</progressbar>')($rootScope);
89+
$rootScope.$digest();
90+
var bar = getBar(0);
91+
expect(bar.attr('aria-labelledby')).toBe('progressbar');
8492
});
8593

8694
it('transcludes "bar" text', function() {
@@ -197,11 +205,11 @@ describe('progressbar directive', function() {
197205
describe('stacked', function() {
198206
beforeEach(inject(function() {
199207
$rootScope.objects = [
200-
{ value: 10, type: 'success' },
201-
{ value: 50, type: 'warning' },
202-
{ value: 20 }
208+
{ value: 10, title: 'foo', type: 'success' },
209+
{ value: 50, title: 'bar', type: 'warning' },
210+
{ value: 20, title: 'baz' }
203211
];
204-
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);
212+
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);
205213
$rootScope.$digest();
206214
}));
207215

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

272+
it('should have the correct aria markup', function() {
273+
expect(getBar(0).attr('aria-valuenow')).toBe('10');
274+
expect(getBar(0).attr('aria-valuemin')).toBe('0');
275+
expect(getBar(0).attr('aria-valuemax')).toBe('100');
276+
expect(getBar(0).attr('aria-valuetext')).toBe('10%');
277+
expect(getBar(0).attr('aria-labelledby')).toBe('foo');
278+
279+
expect(getBar(1).attr('aria-valuenow')).toBe('50');
280+
expect(getBar(1).attr('aria-valuemin')).toBe('0');
281+
expect(getBar(1).attr('aria-valuemax')).toBe('100');
282+
expect(getBar(1).attr('aria-valuetext')).toBe('50%');
283+
expect(getBar(1).attr('aria-labelledby')).toBe('bar');
284+
285+
expect(getBar(2).attr('aria-valuenow')).toBe('20');
286+
expect(getBar(2).attr('aria-valuemin')).toBe('0');
287+
expect(getBar(2).attr('aria-valuemax')).toBe('100');
288+
expect(getBar(2).attr('aria-valuetext')).toBe('20%');
289+
expect(getBar(2).attr('aria-labelledby')).toBe('baz');
290+
});
291+
292+
it('should default to `progressbar`', function() {
293+
$rootScope.objects = [
294+
{ value: 10, title: 'foo', type: 'success' },
295+
{ value: 50, title: 'bar', type: 'warning' },
296+
{ value: 20, title: 'baz' }
297+
];
298+
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);
299+
$rootScope.$digest();
300+
301+
expect(getBar(0).attr('aria-labelledby')).toBe('progressbar');
302+
expect(getBar(1).attr('aria-labelledby')).toBe('progressbar');
303+
expect(getBar(2).attr('aria-labelledby')).toBe('progressbar');
304+
});
305+
264306
describe('"max" attribute', function() {
265307
beforeEach(inject(function() {
266308
$rootScope.max = 200;

Diff for: template/progressbar/bar.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +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>
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}}%" aria-labelledby="{{::title}}" style="min-width: 0;" ng-transclude></div>

Diff for: template/progressbar/progress.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<div class="progress" ng-transclude></div>
1+
<div class="progress" ng-transclude aria-labelledby="{{::title}}"></div>

Diff for: template/progressbar/progressbar.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
<div class="progress">
2-
<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>
2+
<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>
33
</div>

0 commit comments

Comments
 (0)