By default, pressing spacebar causes the browser to scroll down.
However, when a native button is focused, the button is clicked instead.
`ngAria`'s `ngClick` directive, sets elements up to behave like buttons.
For example, it adds `role="button"` and forwards `ENTER` and `SPACEBAR`
keypresses to the `click` handler (to emulate the behavior of native
buttons).
Yet, pressing spacebar on such an element, still invokes the default
browser behavior of scrolling down.
This commit fixes this, by calling `preventDefault()` on the keyboard
event, thus preventing the default scrolling behavior and making custom
buttons behave closer to native ones.
Closes#14665Closes#16604
This fixes a error found by @edclements using the Google Accessibility Developer Tools audit.
Input fields of type hidden shouldn't have aria attributes.
https://www.w3.org/TR/html-aria/#allowed-aria-roles-states-and-properties-1Closes#15113Closes#16367
BREAKING CHANGE:
ngAria no longer sets aria-* attributes on input[type="hidden"] with ngModel.
This can affect apps that test for the presence of aria attributes on hidden inputs.
To migrate, remove these assertions.
In actual apps, this should not have a user-facing effect, as the previous behavior
was incorrect, and the new behavior is correct for accessibility.
The quotes rule had to be disabled for e2e tests generated from ngdoc
because dgeni templates use double quotes as string delimiters.
Since we can't have guarantees that dgeni template wrappers will follow
the same JS code style the Angular 1 repo uses, we should find a way
to enforce our ESLint setup only for the parts in this repo, perhaps
via prepending a generated `/* eslint-enable OUR_RULES */` pragma.
Closes#15011
Previously, `ngAria` would overwrite the default `ngModelController.$isEmpty()` method for custom
`checkbox`-shaped controls (e.g. `role="checkbox"` or `role="menuitemcheckbox"`), using the same
implementation as `input[checkbox]` (i.e. `value === false`). While this makes sense for
`input[checkbox]` which also defines a custom parser, it doesn't make sense for a custom `checkbox`
out-of-the-box. For example, an unintialized value (`undefined`) would make the checkbox appear as
"checked".
If the user wants to provide a custom parser (e.g. setting falsy values to `false`), then they
should also provide a custom `$isEmpty()` method.
As a side effect, this commit solves issue #14621. (We could have solved it in different ways.)
Fixes#14621Closes#14625
BREAKING CHANGE:
Custom `checkbox`-shaped controls (e.g. checkboxes, menuitemcheckboxes), no longer have a custom
`$isEmpty()` method on their `NgModelController` that checks for `value === false`. Unless
overwritten, the default `$isEmpty()` method will be used, which treats `undefined`, `null`, `NaN`
and `''` as "empty".
**Note:** The `$isEmpty()` method is used to determine if the checkbox is checked ("not empty" means
"checked") and thus it can indirectly affect other things, such as the control's validity
with respect to the `required` validator (e.g. "empty" + "required" --> "invalid").
Before:
```js
var template = '<my-checkbox role="checkbox" ng-model="value"></my-checkbox>';
var customCheckbox = $compile(template)(scope);
var ctrl = customCheckbox.controller('ngModel');
scope.$apply('value = false');
console.log(ctrl.$isEmpty()); //--> true
scope.$apply('value = true');
console.log(ctrl.$isEmpty()); //--> false
scope.$apply('value = undefined'/* or null or NaN or '' */);
console.log(ctrl.$isEmpty()); //--> false
```
After:
```js
var template = '<my-checkbox role="checkbox" ng-model="value"></my-checkbox>';
var customCheckbox = $compile(template)(scope);
var ctrl = customCheckbox.controller('ngModel');
scope.$apply('value = false');
console.log(ctrl.$isEmpty()); //--> false
scope.$apply('value = true');
console.log(ctrl.$isEmpty()); //--> false
scope.$apply('value = undefined'/* or null or NaN or '' */);
console.log(ctrl.$isEmpty()); //--> true
```
--
If you want to have a custom `$isEmpty()` method, you need to overwrite the default. For example:
```js
.directive('myCheckbox', function myCheckboxDirective() {
return {
require: 'ngModel',
link: function myCheckboxPostLink(scope, elem, attrs, ngModelCtrl) {
ngModelCtrl.$isEmpty = function myCheckboxIsEmpty(value) {
return !value; // Any falsy value means "empty"
// Or to restore the previous behavior:
// return value === false;
};
}
};
})
```
Previously, `ngAria` would provide keyboard support for non-native buttons (via `ngClick`), by
binding the `ngClick` handler to the `keypress` event. In an attempt to better emulate the behavior
of native buttons, `ngAria` will now bind to the `keydown` event (instead of `keypress`).
The configuration flag for this feature has been renamed from `bindKeypress` to `bindKeydown`, to
closer describe the underlying behavior.
Fixes#14063Closes#14065
BREAKING CHANGE:
If you were explicitly setting the value of the `bindKeypress` flag, you need to change your code to
use `bindKeydown` instead.
Before: `$ariaProvider.config({bindKeypress: xyz})`
After: `$ariaProvider.config({bindKeydown: xyz})`
**Note:**
If the element already has any of the `ngKeydown`/`ngKeyup`/`ngKeypress` directives, `ngAria` will
_not_ bind to the `keydown` event, since it assumes that the developer has already taken care of
keyboard interaction for that element.
Although it is not expected to affect many applications, it might be desirable to keep the previous
behavior of binding to the `keypress` event instead of the `keydown`. In that case, you need to
manually use the `ngKeypress` directive (in addition to `ngClick`).
Before:
```html
<div ng-click="onClick()">
I respond to `click` and `keypress` (not `keydown`)
</div>
```
After:
```html
<div ng-click="onClick()" ng-keypress="onClick()">
I respond to `click` and `keypress` (not `keydown`)
</div>
<!-- OR -->
<div ng-click="onClick()">
I respond to `click` and `keydown` (not `keypress`)
</div>
```
Finally, it is possible that this change affects your unit or end-to-end tests. If you are currently
expecting your custom buttons to automatically respond to the `keypress` event (due to `ngAria`),
you need to change the tests to trigger `keydown` events instead.
prevent ngAria from attaching roles to textarea, button, select, summary, details, a, and input
Closes #14076Closes#14145
BREAKING CHANGE:
ngAria will no longer add the "role" attribute to native control elements
(textarea, button, select, summary, details, a, and input). Previously, "role" was not added to
input, but all others in the list.
This should not affect accessibility, because native inputs are accessible by default, but it might
affect applications that relied on the "role" attribute being present (e.g. for styling or as
directive attributes).
Highlights:
New mechanism to run async tests as Jasmine 2 removed `runs`, `waits` and `waitsFor`
The functions `iit`, `ddescribe` and `tthey` were renamed `fit`, `fdescribe` and
`fthey` as the originals came from Karma, Karma no longer bundles Jasmine and the
new function name comes from Jasmine.
Closes#14226
BREAKING CHANGE: Where appropriate, ngAria now applies ARIA to custom controls only, not native inputs. Because of this, support for `aria-multiline` on textareas has been removed.
New support added for ngValue, ngChecked, and ngRequired, along with updated documentation.
Closes#13078Closes#11374Closes#11830Closes#13483
Previously, when using ngAria with the ng-hide directive,
and the value passed to ng-hide was not boolean,
the aria-hidden attribute was set to this non-boolean value.
Closes#11865Closes#11998
In Firefox, keyboard events for printable characters (e.g. space) do not use event.keyCode.
Use event.which if it is provided before falling back to event.keyCode.
Closes#11340
Make sure the checked attribute is set correctly for:
- checkboxes with string and integer models using ngTrueValue /
ngFalseValue
- radios with integer models
- radios with boolean models using ngValue
Fixes#10389Fixes#10212
Minor improvement to ng-click directive from ngAria. Now, if bindings are updated
during the click handler, the DOM will be updated as well. Additionally, the $event
object is passed in to the expression via locals, as is done for core event directives.
Closes#10442Closes#10443Closes#10447
By including the `ngAria` module, `ngMessages` will automatically include the aria-live
attribute with an assertive voice, allowing validation messages to be spoken throuhg a
screenreader.
Closes#9834
Conditionally adds various aria attributes to the built in directives.
This module currently hooks into ng-show/hide, input, textarea and
button as a basic level of support for a11y.
Closes#5486 and #1600