Roles dynamically added with ngAria #10318

Closed
wants to merge 2 commits into
from

Projects

None yet
@marcysutton
Member

To communicate the purpose of custom inputs with a type of range, checkbox or radio, ngAria now dynamically adds roles to custom radio buttons, checkboxes and sliders.

It also adds a role of button to any element with ngClick that is not a button, anchor, input or textarea (such as a div). This feature comes on the heels of #10288, which binds the keypress event for ngClick. With these two changes together, users of assistive technologies will know what they are focused on and be able to operate controls with the keyboard (this is important because ngAria dynamically adds tabIndex="0" with ngClick). However, not all uses of ngClick are used for buttons–sometimes developers bind ng-click on the document. In this scenario, a role can be overridden by the developer if button does not match expected behavior.

Note: This change does not implement any kind of flag allowing the user to opt out of roles being set.

Closes #9254 and #10012.

@googlebot

CLAs look good, thanks!

@googlebot googlebot added the cla: yes label Dec 4, 2014
@gkalpak
Member
gkalpak commented Dec 4, 2014

I know it is unrelated to this PR, but I was wondering (with regard to line 209):

((type || role) === 'checkbox' ...

What if the element has both a type and a role (and they are different) ?
Is it even a "legitimate" use-case ?

@marcysutton
Member

@gkalpak not for checkbox. <input type="range"> and role="slider" is a use case, and there may be others....but they'd have to be looked at on a case by case basis. I'll keep it in mind though.

@gkalpak
Member
gkalpak commented Dec 5, 2014

@marcysutton: Aha, thx. So, if I interpret your answer correctly, in the "general" case each attribute (type, role) should be checked separately:

((type === 'xyz') || (role === 'xyz') || ...)

But for checkboxes and radios, type and role (if set) will be the same, so it is OK to write:

((type || role) === 'xyz')

(which will essentially ignore role if type is defined, but this is OK because role shouldn't be checkbox/radio unless type is checkbox/radio as well.)

Is my thinking correct ?

@caitp caitp commented on an outdated diff Dec 5, 2014
test/ngAria/ariaSpec.js
@@ -136,6 +140,50 @@ describe('$aria', function() {
});
});
+ describe('roles for custom inputs', function() {
+ beforeEach(injectScopeAndCompiler);
+
+ it('should add missing role="button" to custom input', function() {
+ compileInput('<div ng-click="someFunction()"></div>');
+ expect(element.attr('role')).toBe('button');
+ });
+ it('should not add role="button" to anchor', function() {
@caitp
caitp Dec 5, 2014 Contributor

nit: 2 empty lines between each suite/spec/block

@caitp caitp and 1 other commented on an outdated diff Dec 5, 2014
test/ngAria/ariaSpec.js
@@ -136,6 +140,50 @@ describe('$aria', function() {
});
});
+ describe('roles for custom inputs', function() {
+ beforeEach(injectScopeAndCompiler);
+
+ it('should add missing role="button" to custom input', function() {
+ compileInput('<div ng-click="someFunction()"></div>');
@caitp
caitp Dec 5, 2014 Contributor

why are we calling this compileInput ? there's no input here =)

@marcysutton
marcysutton Dec 5, 2014 Member

Good point! This is fixed.

@caitp caitp added this to the 1.3.7 milestone Dec 5, 2014
@caitp caitp and 1 other commented on an outdated diff Dec 5, 2014
src/ngAria/aria.js
@@ -319,6 +329,10 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
}
});
}
+
+ if (!elem.attr('role') && (elem[0].nodeName !== 'BUTTON') && (elem[0].nodeName !== 'A')) {
@caitp
caitp Dec 5, 2014 Contributor

I wonder if it would be more readable to have something like && !IsNodeOneOf(elem, "BUTTON", "A") or something. I don't think it's problematic like this, but if there was one extra condition added it would be really hard to read.

@marcysutton
marcysutton Dec 5, 2014 Member

Great point. That conditional is a little awkward in its current form.

@marcysutton
Member

@gkalpak there is no "generic" case. ngAria is checking for specific scenarios to add the right attributes. type || role applies correctly to each case where it is being used.

@gkalpak
Member
gkalpak commented Dec 5, 2014

OK, thx ! I get it (I think :))

@caitp caitp modified the milestone: 1.3.7, 1.3.8 Dec 9, 2014
@pkozlowski-opensource pkozlowski-opensource modified the milestone: 1.3.8, 1.3.7 Dec 9, 2014
@petebacondarwin petebacondarwin modified the milestone: 1.3.7, 1.3.8 Dec 15, 2014
@btford btford modified the milestone: 1.3.8, 1.3.9 Dec 19, 2014
@dylanb dylanb and 1 other commented on an outdated diff Feb 7, 2015
src/ngAria/aria.js
@@ -310,6 +320,9 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
return true;
}
}
+ if (!elem.attr('role') && !isNodeOneOf(elem, ['BUTTON', 'A'])) {
@dylanb
dylanb Feb 7, 2015

blacklist should include INPUT and TEXTAREA

@marcysutton
marcysutton Feb 7, 2015 Member

Good call. But do people put ng-click on those? shudder

@dylanb
dylanb Feb 7, 2015

input type=image, type=submit, type=button will all commonly have ng-click attributes applied

@marcysutton
marcysutton Feb 7, 2015 Member

Great point. I updated the blacklist and added it to the dynamic keypress binding so there would be more consistency.

@marcysutton
Member

@caitp I rebased this branch with the recently merged ngAria changes. The code now uses a node blacklist to add roles and bind keypress events.

@marcysutton
Member

@Narretz @petebacondarwin can you take a look at this PR for adding roles dynamically? It's the last ngAria change that would be great to have in the 1.4 release. Thank you!

@gkalpak gkalpak and 1 other commented on an outdated diff Feb 16, 2015
test/ngAria/ariaSpec.js
@@ -136,6 +140,56 @@ describe('$aria', function() {
});
});
+ describe('roles for custom inputs', function() {
+ beforeEach(injectScopeAndCompiler);
+
+ it('should add missing role="button" to custom input', function() {
+ compileElement('<div ng-click="someFunction()"></div>');
+ expect(element.attr('role')).toBe('button');
+ });
+
+ it('should not add role="button" to anchor', function() {
+ compileElement('<a ng-click="someFunction()"></a>');
+ expect(element.attr('role')).not.toBe('button');
+ });
+
+ it('should add missing role="checkbox" to custom input', function() {
+ scope.$apply('val = true');
@gkalpak
gkalpak Feb 16, 2015 Member

What is the purpose of this line ?

@marcysutton
marcysutton Feb 17, 2015 Member

It was unnecessary. Cleaned up!

Marcy Sutton added some commits Dec 4, 2014
Marcy Sutton feat(ngAria): Roles added to custom inputs
Adds missing roles: slider, radio, checkbox
Closes #10012
3894b95
Marcy Sutton feat(ngAria): Adds button role to ng-click
Closes #9254
7fafdf9
@petebacondarwin
Member

LGTM

@andrewaustin
Contributor

Would love to see this in 1.3.x. We have some tags that are clickable and are currently having to do some extra work with ng-keypress to make them fully accessible. Having a blacklist rather than the current div & li whitelist would be extremely useful.

@ginader
ginader commented Feb 27, 2015

👍

@petebacondarwin petebacondarwin added a commit that closed this pull request Mar 2, 2015
@petebacondarwin Marcy Sutton + petebacondarwin feat(ngAria): add roles to custom inputs
This change adds the missing roles: `slider`, `radio`, `checkbox`

Closes #10012
Closes #10318
29cdaee
@petebacondarwin petebacondarwin added a commit that referenced this pull request Mar 2, 2015
@petebacondarwin Marcy Sutton + petebacondarwin feat(ngAria): add `button` role to `ngClick`
Closes #9254
Closes #10318
bb36507
@petebacondarwin petebacondarwin added a commit that referenced this pull request Mar 2, 2015
@petebacondarwin Marcy Sutton + petebacondarwin feat(ngAria): add roles to custom inputs
This change adds the missing roles: `slider`, `radio`, `checkbox`

Closes #10012
Closes #10318
2136994
@petebacondarwin petebacondarwin added a commit that referenced this pull request Mar 2, 2015
@petebacondarwin Marcy Sutton + petebacondarwin feat(ngAria): add `button` role to `ngClick`
Closes #9254
Closes #10318
b9ad91c
@petebacondarwin
Member

Landed in master and cherry picked to 1.3.x for good measure.

@marcysutton
Member

Woohoo! Thanks @petebacondarwin! 🎉

@hansmaad hansmaad pushed a commit to hansmaad/angular.js that referenced this pull request Mar 10, 2015
Marcy Sutton + hansmaad feat(ngAria): add roles to custom inputs
This change adds the missing roles: `slider`, `radio`, `checkbox`

Closes #10012
Closes #10318
cfefbc0
@hansmaad hansmaad pushed a commit to hansmaad/angular.js that referenced this pull request Mar 10, 2015
Marcy Sutton + hansmaad feat(ngAria): add `button` role to `ngClick`
Closes #9254
Closes #10318
e4dd239
@marcysutton marcysutton deleted the marcysutton:ngaria-roles branch Apr 11, 2015
@netman92 netman92 added a commit to netman92/angular.js that referenced this pull request Aug 8, 2015
@netman92 Marcy Sutton + netman92 feat(ngAria): add roles to custom inputs
This change adds the missing roles: `slider`, `radio`, `checkbox`

Closes #10012
Closes #10318
b4ddeb0
@netman92 netman92 added a commit to netman92/angular.js that referenced this pull request Aug 8, 2015
@netman92 Marcy Sutton + netman92 feat(ngAria): add `button` role to `ngClick`
Closes #9254
Closes #10318
a3a8bc8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment