@@ -12,14 +12,23 @@ assistive technologies used by persons with disabilities.
12
12
13
13
##Including ngAria
14
14
15
- Using ngAria is as simple as requiring the ngAria module in your application. ngAria hooks into
15
+ Using {@link ngAria ngAria} is as simple as requiring the ngAria module in your application. ngAria hooks into
16
16
standard AngularJS directives and quietly injects accessibility support into your application
17
17
at runtime.
18
18
19
19
```js
20
20
angular.module('myApp', ['ngAria'])...
21
21
```
22
22
23
+ ###Using ngAria
24
+ Most of what ngAria does is only visible "under the hood". To see the module in action, once you've
25
+ added it as a dependency, you can test a few things:
26
+ * Using your favorite element inspector, look for ngAria attributes in your own code.
27
+ * Test using your keyboard to ensure `tabindex` is used correctly.
28
+ * Fire up a screen reader such as VoiceOver to listen for ARIA support.
29
+ [Helpful screen reader tips.](http://webaim.org/articles/screenreader_testing/)
30
+
31
+ ##Supported directives
23
32
Currently, ngAria interfaces with the following directives:
24
33
25
34
* <a href="#ngmodel">ngModel</a>
@@ -31,7 +40,7 @@ Currently, ngAria interfaces with the following directives:
31
40
32
41
<h2 id="ngmodel">ngModel</h2>
33
42
34
- Most of ngAria's heavy lifting happens in the [ ngModel](https://docs.angularjs.org/api/ng/directive/ ngModel)
43
+ Most of ngAria's heavy lifting happens in the {@link ngModel ngModel}
35
44
directive. For elements using ngModel, special attention is paid by ngAria if that element also
36
45
has a a role or type of `checkbox`, `radio`, `range` or `textbox`.
37
46
@@ -47,15 +56,41 @@ attributes (if they have not been explicitly specified by the developer):
47
56
48
57
###Example
49
58
50
- ```html
51
- <md-checkbox ng-model="val" required>
52
- ```
53
-
54
- Becomes:
55
-
56
- ```html
57
- <md-checkbox ng-model="val" required aria-required="true" tabIndex="0">
58
- ```
59
+ <example module="ngAria_ngModelExample" deps="angular-aria.js">
60
+ <file name="index.html">
61
+ <style>
62
+ some-checkbox {
63
+ background-color: black;
64
+ color: white;
65
+ }
66
+ </style>
67
+ <div print-markup>
68
+ <form>
69
+ <some-checkbox ng-model="user.subscribe" required>
70
+ Fake Checkbox
71
+ </some-checkbox>
72
+ </form>
73
+ </div>
74
+ <script>
75
+ var app = angular.module('ngAria_ngModelExample', ['ngAria']);
76
+
77
+ app.directive('printMarkup', function() {
78
+ return {
79
+ restrict: 'A',
80
+ link: function($scope, $el, $attrs) {
81
+ var el = $el[0].querySelector('form');
82
+ var newEl = document.createElement('div');
83
+ var output = 'Becomes: <pre><code>' +
84
+ el.innerHTML.replace(/&/g, '&').replace(/</g, '<') +
85
+ '</code></pre>';
86
+ newEl.innerHTML = output;
87
+ el.parentNode.insertBefore(newEl, el.nextSibling);
88
+ }
89
+ }
90
+ });
91
+ </script>
92
+ </file>
93
+ </example>
59
94
60
95
ngAria will also add `tabIndex`, ensuring custom elements with these roles will be reachable from
61
96
the keyboard. It is still up to **you** as a developer to **ensure custom controls will be
@@ -106,6 +141,24 @@ screen reader users won't accidentally focus on "mystery elements". Managing tab
106
141
child control can be complex and affect performance, so it’s best to just stick with the default
107
142
`display: none` CSS. See the [fourth rule of ARIA use](http://www.w3.org/TR/aria-in-html/#fourth-rule-of-aria-use).
108
143
144
+ ###Example
145
+ ```css
146
+ .ng-hide {
147
+ display: block;
148
+ opacity: 0;
149
+ }
150
+ ```
151
+ ```html
152
+ <div ng-show="false" class="ng-hide" aria-hidden="true"></div>
153
+ ```
154
+
155
+ Becomes:
156
+
157
+ ```html
158
+ <div ng-show="true" aria-hidden="false"></div>
159
+ ```
160
+ *Note: Child links, buttons or other interactive controls must also be removed from the tab order.*
161
+
109
162
<h2 id="nghide">ngHide</h2>
110
163
111
164
>The [ngHide](https://docs.angularjs.org/api/ng/directive/ngHide) directive shows or hides the
@@ -116,33 +169,86 @@ The default CSS for `ngHide`, the inverse method to `ngShow`, makes ngAria redun
116
169
`aria-hidden` on the directive when it is hidden or shown, but the content is already hidden with
117
170
`display: none`. See explanation for <a href="#ngshow">ngShow</a> when overriding the default CSS.
118
171
119
- <h2 id="ngclick">ngClick and ngDblClick</h2>
120
- If `ngClick` or `ngDblClick` is encountered, ngAria will add `tabIndex` if it isn't there already.
121
- Even with this, you must currently still add `ng-keypress` to non-interactive elements such as
122
- `<div>` or `<taco-button>` to enable keyboard access. Conversation is
123
- [currently ongoing](https://github.com/angular/angular.js/issues/9254) about whether ngAria
124
- should also bind `ng-keypress` to be more useful.
172
+ <h2 id="ngclick">ngClick and ngDblclick</h2>
173
+ If `ng-click` or `ng-dblclick` is encountered, ngAria will add `tabindex` if it isn't there already.
174
+ Even with this, you must currently still add `ng-keypress` to non-interactive elements such as `div`
175
+ or `taco-button` to enable keyboard access. Conversation is currently ongoing about whether ngAria
176
+ should also bind `ng-keypress`.
177
+
178
+ ###Example
179
+ ```html
180
+ <div ng-click="toggleMenu()"></div>
181
+ ```
182
+
183
+ Becomes:
184
+ ```html
185
+ <div ng-click="toggleMenu()" tabindex="0"></div>
186
+ ```
187
+ *Note: ngAria still requires `ng-keypress` to be added manually to non-native controls like divs.*
125
188
126
189
<h2 id="ngmessages">ngMessages</h2>
127
190
128
191
The new ngMessages module makes it easy to display form validation or other messages with priority
129
192
sequencing and animation. To expose these visual messages to screen readers,
130
193
ngAria injects `aria-live="polite"`, causing them to be read aloud any time a message is shown,
131
194
regardless of the user's focus location.
195
+ ###Example
132
196
133
- * * *
197
+ ```html
198
+ <div ng-messages="myForm.myName.$error">
199
+ <div ng-message="required">You did not enter a field</div>
200
+ <div ng-message="maxlength">Your field is too long</div>
201
+ </div>
202
+ ```
134
203
135
- ##Disabling attributes
136
- The attribute magic of ngAria may not work for every scenario. To disable individual attributes,
137
- you can use the {@link ngAria.$ariaProvider#config config} method:
204
+ Becomes:
138
205
206
+ ```html
207
+ <div ng-messages="myForm.myName.$error" aria-live="polite">
208
+ <div ng-message="required">You did not enter a field</div>
209
+ <div ng-message="maxlength">Your field is too long</div>
210
+ </div>
139
211
```
140
- angular.module('myApp', ['ngAria'], function config($ariaProvider) {
141
- $ariaProvider.config({
142
- tabindex: false
212
+
213
+ ##Disabling attributes
214
+ The attribute magic of ngAria may not work for every scenario. To disable individual attributes,
215
+ you can use the {@link ngAria.$ariaProvider#config config} method. Just keep in mind this will
216
+ tell ngAria to ignore the attribute globally.
217
+
218
+ <example module="ngAria_ngDisabledExample" deps="angular-aria.js">
219
+ <file name="index.html">
220
+ <form>
221
+ <div ng-model="someModel" show-attrs>
222
+ Div with ngModel, aria-invalid and tabindex disabled
223
+ </div>
224
+ </form>
225
+ <script>
226
+ angular.module('ngAria_ngDisabledExample', ['ngAria'], function config($ariaProvider) {
227
+ $ariaProvider.config({
228
+ ariaInvalid: false,
229
+ tabindex: false
230
+ });
231
+ })
232
+ .directive('showAttrs', function() {
233
+ return function(scope, el, attrs) {
234
+ var pre = document.createElement('pre');
235
+ el.after(pre);
236
+ scope.$watch(function() {
237
+ var attrs = {};
238
+ Array.prototype.slice.call(el[0].attributes, 0).forEach(function(item) {
239
+ if (item.name !== 'show-attrs') {
240
+ attrs[item.name] = item.value;
241
+ }
242
+ });
243
+ return attrs;
244
+ }, function(newAttrs, oldAttrs) {
245
+ pre.innerText = JSON.stringify(newAttrs, null, 2);
246
+ }, true);
247
+ }
143
248
});
144
- });
145
- ```
249
+ </script>
250
+ </file>
251
+ </example>
146
252
147
253
##Common Accessibility Patterns
148
254
@@ -171,6 +277,7 @@ Accessibility best practices that apply to web apps in general also apply to Ang
171
277
172
278
* [Using ARIA in HTML](http://www.w3.org/TR/aria-in-html/)
173
279
* [AngularJS Accessibility at ngEurope](https://www.youtube.com/watch?v=dmYDggEgU-s&list=UUEGUP3TJJfMsEM_1y8iviSQ)
280
+ * [Testing with Screen Readers](http://webaim.org/articles/screenreader_testing/)
174
281
* [Chrome Accessibility Developer Tools](https://chrome.google.com/webstore/detail/accessibility-developer-t/fpkknkljclfencbdbgkenhalefipecmb?hl=en)
175
282
* [W3C Accessibility Testing](http://www.w3.org/wiki/Accessibility_testing)
176
283
* [WebAIM](http://webaim.org)
0 commit comments