Skip to content
This repository has been archived by the owner on Sep 5, 2024. It is now read-only.

Commit

Permalink
fix(select): expose and preserve aria-label
Browse files Browse the repository at this point in the history
Fixes #1893. Closes #2672
  • Loading branch information
Marcy Sutton authored and ThomasBurleson committed May 3, 2015
1 parent f737fb0 commit bd3d8fb
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 12 deletions.
23 changes: 17 additions & 6 deletions src/components/select/select.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,11 @@ angular.module('material.components.select', [
* @param {expression} ng-model The model!
* @param {boolean=} multiple Whether it's multiple.
* @param {string=} placeholder Placeholder hint text.
* @param {string=} aria-label Optional label for accessibility. Only necessary if no placeholder or
* explicit label is present.
*
* @usage
* With a placeholder (label is added dynamically)
* With a placeholder (label and aria-label are added dynamically)
* <hljs lang="html">
* <md-select
* ng-model="someModel"
Expand All @@ -63,7 +65,7 @@ angular.module('material.components.select', [
* </md-select>
* </hljs>
*/
function SelectDirective($mdSelect, $mdUtil, $mdTheming, $interpolate, $compile, $parse) {
function SelectDirective($mdSelect, $mdUtil, $mdTheming, $mdAria, $interpolate, $compile, $parse) {
var intStart = $interpolate.startSymbol();
var intEnd = $interpolate.endSymbol();

Expand Down Expand Up @@ -197,7 +199,18 @@ function SelectDirective($mdSelect, $mdUtil, $mdTheming, $interpolate, $compile,
val ? labelEl.addClass('md-placeholder') : labelEl.removeClass('md-placeholder');
};

scope.$$postDigest(syncLabelText);
scope.$$postDigest(function() {
setAriaLabel();
syncLabelText();
});

function setAriaLabel() {
var labelText = element.attr('placeholder');
if (!labelText) {
labelText = element.find('md-select-label').text();
}
$mdAria.expect(element, 'aria-label', labelText);
}

function syncLabelText() {
if (selectContainer) {
Expand Down Expand Up @@ -258,8 +271,7 @@ function SelectDirective($mdSelect, $mdUtil, $mdTheming, $interpolate, $compile,
element.attr({
'role': 'combobox',
'id': 'select_' + $mdUtil.nextUid(),
'aria-expanded': 'false',
'aria-labelledby': labelEl.attr('id')
'aria-expanded': 'false'
});

scope.$on('$destroy', function() {
Expand Down Expand Up @@ -760,7 +772,6 @@ function SelectProvider($$interimElementProvider) {
return $mdUtil.transitionEndPromise(opts.selectEl, {timeout: 350});

function configureAria() {
opts.selectEl.attr('aria-labelledby', opts.target.attr('id'));
opts.target.attr('aria-expanded', 'true');
}

Expand Down
51 changes: 45 additions & 6 deletions src/components/select/select.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -586,13 +586,52 @@ describe('<md-select-menu>', function() {
selectMenus.remove();
}));

it('sets up the aria-labeledby attribute', inject(function($document) {
openSelect(el);
var selectId = el.attr('id');
var selectMenu = $document.find('md-select-menu');
expect(selectId.length).toBeTruthy();
expect(selectMenu.attr('aria-labelledby')).toBe(selectId);
it('adds an aria-label from placeholder', function() {
var select = setupSelect('ng-model="someVal", placeholder="Hello world"');
expect(select.attr('aria-label')).toBe('Hello world');
});

it('adds aria-label from label element', inject(function($rootScope, $compile) {
var select = $compile('<md-select ng-model="val">' +
'<md-select-label>{{"Pick"}}</md-select-label>' +
'<md-option value="1">One</md-option>' +
'<md-option value="2">Two</md-option>' +
'<md-option value="3">Three</md-option>' +
'</md-select>')($rootScope);
$rootScope.$digest();
expect(select.attr('aria-label')).toBe('Pick');
}));

it('preserves aria-label on value change', inject(function($rootScope, $compile) {
var select = $compile('<md-select ng-model="val">' +
'<md-select-label>Pick</md-select-label>' +
'<md-option value="1">One</md-option>' +
'<md-option value="2">Two</md-option>' +
'<md-option value="3">Three</md-option>' +
'</md-select>')($rootScope);
$rootScope.$apply('model = 1');
$rootScope.$digest();

expect(select.attr('aria-label')).toBe('Pick');
}));

it('preserves existing aria-label', inject(function($rootScope) {
var select = setupSelect('ng-model="someVal", aria-label="Hello world", placeholder="Pick"');
expect(select.attr('aria-label')).toBe('Hello world');
}));

it('should expect an aria-label if none is present', inject(function($compile, $rootScope, $log) {
spyOn($log, 'warn');
var select = setupSelect('ng-model="someVal"');
$rootScope.$apply();
expect($log.warn).toHaveBeenCalled();

$log.warn.calls.reset();
select = setupSelect('ng-model="someVal", aria-label="Hello world"');
$rootScope.$apply();
expect($log.warn).not.toHaveBeenCalled();
}));

it('sets up the aria-expanded attribute', inject(function($document) {
expect(el.attr('aria-expanded')).toBe('false');
openSelect(el);
Expand Down

0 comments on commit bd3d8fb

Please sign in to comment.