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

Commit 1c30ecd

Browse files
author
Jean Ducrot
committed
fix(a11y): add live region to datepicker
1 parent 1f97c99 commit 1c30ecd

File tree

7 files changed

+86
-203
lines changed

7 files changed

+86
-203
lines changed

README.md

+14-188
Original file line numberDiff line numberDiff line change
@@ -5,191 +5,17 @@ We thank you for all your contributions over the years and hope you've enjoyed u
55

66
---
77

8-
### UI Bootstrap - [AngularJS](http://angularjs.org/) directives specific to [Bootstrap](http://getbootstrap.com)
9-
10-
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/angular-ui/bootstrap?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
11-
[![Build Status](https://secure.travis-ci.org/angular-ui/bootstrap.svg)](http://travis-ci.org/angular-ui/bootstrap)
12-
[![devDependency Status](https://david-dm.org/angular-ui/bootstrap/dev-status.svg?branch=master)](https://david-dm.org/angular-ui/bootstrap#info=devDependencies)
13-
[![CDNJS](https://img.shields.io/cdnjs/v/angular-ui-bootstrap.svg)](https://cdnjs.com/libraries/angular-ui-bootstrap/)
14-
15-
### Quick links
16-
- [Demo](#demo)
17-
- [Angular 2](#angular-2)
18-
- [Installation](#installation)
19-
- [NPM](#install-with-npm)
20-
- [Bower](#install-with-bower)
21-
- [NuGet](#install-with-nuget)
22-
- [Custom](#custom-build)
23-
- [Manual](#manual-download)
24-
- [Webpack / JSPM](#webpack--jspm)
25-
- [Support](#support)
26-
- [FAQ](#faq)
27-
- [Code of Conduct](#code-of-conduct)
28-
- [PREFIX MIGRATION GUIDE](#prefix-migration-guide)
29-
- [Supported browsers](#supported-browsers)
30-
- [Need help?](#need-help)
31-
- [Found a bug?](#found-a-bug)
32-
- [Contributing to the project](#contributing-to-the-project)
33-
- [Development, meeting minutes, roadmap and more.](#development-meeting-minutes-roadmap-and-more)
34-
35-
36-
# Demo
37-
38-
Do you want to see directives in action? Visit https://angular-ui.github.io/bootstrap/!
39-
40-
# Angular 2
41-
42-
Are you interested in Angular 2? We are on our way! Check out [ng-bootstrap](https://github.com/ui-bootstrap/core).
43-
44-
# Installation
45-
46-
Installation is easy as UI Bootstrap has minimal dependencies - only the AngularJS and Twitter Bootstrap's CSS are required.
47-
*Notes:*
48-
* Since version 0.13.0, UI Bootstrap depends on [ngAnimate](https://docs.angularjs.org/api/ngAnimate) for transitions and animations, such as the accordion, carousel, etc. Include `ngAnimate` in the module dependencies for your app in order to enable animation.
49-
* UI Bootstrap depends on [ngTouch](https://docs.angularjs.org/api/ngTouch) for swipe actions. Include `ngTouch` in the module dependencies for your app in order to enable swiping.
50-
51-
## Angular Requirements
52-
* UI Bootstrap 1.0 and higher _requires_ Angular 1.4.x or higher and it has been tested with Angular 1.4.8.
53-
* UI Bootstrap 0.14.3 is the _last_ version that supports Angular 1.3.x.
54-
* UI Bootstrap 0.12.0 is the _last_ version that supports Angular 1.2.x.
55-
56-
## Bootstrap Requirements
57-
* UI Bootstrap requires Bootstrap CSS version 3.x or higher and it has been tested with Bootstrap CSS 3.3.6.
58-
* UI Bootstrap 0.8 is the _last_ version that supports Bootstrap CSS 2.3.x.
59-
60-
#### Install with NPM
61-
62-
```sh
63-
$ npm install angular-ui-bootstrap
64-
```
65-
66-
This will install AngularJS and Bootstrap NPM packages.
67-
68-
#### Install with Bower
69-
```sh
70-
$ bower install angular-bootstrap
71-
```
72-
73-
Note: do not install 'angular-ui-bootstrap'. A separate repository - [bootstrap-bower](https://github.com/angular-ui/bootstrap-bower) - hosts the compiled javascript file and bower.json.
74-
75-
#### Install with NuGet
76-
To install AngularJS UI Bootstrap, run the following command in the Package Manager Console
77-
78-
```sh
79-
PM> Install-Package Angular.UI.Bootstrap
80-
```
81-
82-
#### Custom build
83-
84-
Head over to https://angular-ui.github.io/bootstrap/ and hit the *Custom build* button to create your own custom UI Bootstrap build, just the way you like it.
85-
86-
#### Manual download
87-
88-
After downloading dependencies (or better yet, referencing them from your favorite CDN) you need to download build version of this project. All the files and their purposes are described here:
89-
https://github.com/angular-ui/bootstrap/tree/gh-pages#build-files
90-
Don't worry, if you are not sure which file to take, opt for `ui-bootstrap-tpls-[version].min.js`.
91-
92-
### Adding dependency to your project
93-
94-
When you are done downloading all the dependencies and project files the only remaining part is to add dependencies on the `ui.bootstrap` AngularJS module:
95-
96-
```js
97-
angular.module('myModule', ['ui.bootstrap']);
98-
```
99-
100-
# Webpack / JSPM
101-
102-
To use this project with webpack, follow the [NPM](#install-with-npm) instructions.
103-
Now, if you want to use only the accordion, you can do:
104-
105-
```js
106-
import accordion from 'angular-ui-bootstrap/src/accordion';
107-
108-
angular.module('myModule', [accordion]);
109-
```
110-
111-
You can import all the pieces you need in the same way:
112-
113-
```js
114-
import accordion from 'angular-ui-bootstrap/src/accordion';
115-
import datepicker from 'angular-ui-bootstrap/src/datepicker';
116-
117-
angular.module('myModule', [accordion, datepicker]);
118-
```
119-
120-
This will load all the dependencies (if any) and also the templates (if any).
121-
122-
Be sure to have a loader able to process `css` files like `css-loader`.
123-
124-
If you would prefer not to load your css through your JavaScript file loader/bundler, you can choose to import the `index-nocss.js` file instead, which is available for the modules:
125-
* carousel
126-
* datepicker
127-
* datepickerPopup
128-
* dropdown
129-
* modal
130-
* popover
131-
* position
132-
* timepicker
133-
* tooltip
134-
* typeahead
135-
136-
The other modules, such as `accordion` in the example below, do not have CSS resources to load, so you should continue to import them as normal:
137-
138-
```js
139-
import accordion from 'angular-ui-bootstrap/src/accordion';
140-
import typeahead from 'angular-ui-bootstrap/src/typeahead/index-nocss.js';
141-
142-
angular.module('myModule', [accordion, typeahead]);
143-
```
144-
145-
# Versioning
146-
147-
Pre-2.0.0 does not follow a particular versioning system. 2.0.0 and onwards follows [semantic versioning](http://semver.org/). All release changes can be viewed on our [changelog](CHANGELOG.md).
148-
149-
# Support
150-
151-
## FAQ
152-
153-
https://github.com/angular-ui/bootstrap/wiki/FAQ
154-
155-
# Code of Conduct
156-
157-
Take a moment to read our [Code of Conduct](CODE_OF_CONDUCT.md)
158-
159-
## PREFIX MIGRATION GUIDE
160-
161-
If you're updating your application to use prefixes, please check the [migration guide](https://github.com/angular-ui/bootstrap/wiki/Migration-guide-for-prefixes).
162-
163-
## Supported browsers
164-
165-
Directives from this repository are automatically tested with the following browsers:
166-
* Chrome (stable and canary channel)
167-
* Firefox
168-
* IE 9 and 10
169-
* Opera
170-
* Safari
171-
172-
Modern mobile browsers should work without problems.
173-
174-
## Need help?
175-
Need help using UI Bootstrap?
176-
177-
* Live help in the IRC (`#angularjs` channel at the `freenode` network). Use this [webchat](https://webchat.freenode.net/) or your own IRC client.
178-
* Ask a question in [StackOverflow](http://stackoverflow.com/) under the [angular-ui-bootstrap](http://stackoverflow.com/questions/tagged/angular-ui-bootstrap) tag.
179-
180-
**Please do not create new issues in this repository to ask questions about using UI Bootstrap**
181-
182-
## Found a bug?
183-
Please take a look at [CONTRIBUTING.md](CONTRIBUTING.md#you-think-youve-found-a-bug) and submit your issue [here](https://github.com/angular-ui/bootstrap/issues/new).
184-
185-
186-
----
187-
188-
189-
# Contributing to the project
190-
191-
We are always looking for the quality contributions! Please check the [CONTRIBUTING.md](CONTRIBUTING.md) for the contribution guidelines.
192-
193-
# Development, meeting minutes, roadmap and more.
194-
195-
Head over to the [Wiki](https://github.com/angular-ui/bootstrap/wiki) for notes on development for UI Bootstrap, meeting minutes from the UI Bootstrap team, roadmap plans, project philosophy and more.
8+
### UI Bootstrap - For Interfolio Devs
9+
Here are the steps you need to take to modify this library:
10+
11+
1 Clone the Interfolio angular-ui-bootstrap repo
12+
2 Install local packages `npm install`
13+
3 Install grunt if you don't already have it `npm i -g grunt-cli`
14+
4 CD into the MC directory of the FE you're working with
15+
5 Remove the local angular-ui-bootstrap directory `rm -rf node_modules/angular-ui-bootstrap`
16+
6 Create a symlink to your local angular-ui-bootstrap `ln -s ~/Interfolio/angular-ui-bootstrap node_modules/angular-ui-bootstrap`
17+
7 Go back to the angular-ui-bootstrap repo,
18+
8 To compile JS you will need to run `grunt build`
19+
8 To compile HTML you will need to run `grunt before-test build` and recompile your FE as templates get cached
20+
10 To run the build once you are done making all your changes, just use the default task `grunt`. This will run all the UTs and all the build process.
21+
12 You will need to create a tarball of the project before deploying it to GemFury.

src/datepicker/datepicker.css

+7
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,10 @@
99
.uib-left, .uib-right {
1010
width: 100%
1111
}
12+
13+
.sr-only-liveregion {
14+
position: absolute;
15+
clip: rect(0, 0, 0, 0);
16+
white-space: nowrap;
17+
border: 0;
18+
}

src/datepicker/datepicker.js

+11-3
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
144144
$scope.uniqueId = 'datepicker-' + $scope.$id + '-' + Math.floor(Math.random() * 10000);
145145

146146
$scope.disabled = angular.isDefined($attrs.disabled) || false;
147+
147148
if (angular.isDefined($attrs.ngDisabled)) {
148149
watchListeners.push($scope.$parent.$watch($attrs.ngDisabled, function(disabled) {
149150
$scope.disabled = disabled;
@@ -154,6 +155,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
154155
$scope.isActive = function(dateObject) {
155156
if (self.compare(dateObject.date, self.activeDate) === 0) {
156157
$scope.activeDateId = dateObject.uid;
158+
$("#"+$scope.uniqueId+"-liveregion").text(dateObject['long']);
157159
return true;
158160
}
159161
return false;
@@ -268,7 +270,9 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
268270

269271
$scope.select = function(date) {
270272
if ($scope.datepickerMode === self.minMode) {
271-
var dt = ngModelCtrl.$viewValue ? dateParser.fromTimezone(new Date(ngModelCtrl.$viewValue), ngModelOptions.getOption('timezone')) : new Date(0, 0, 0, 0, 0, 0, 0);
273+
var dt = ngModelCtrl.$viewValue ?
274+
dateParser.fromTimezone(new Date(ngModelCtrl.$viewValue), ngModelOptions.getOption('timezone')) :
275+
new Date(0, 0, 0, 0, 0, 0, 0);
272276
dt.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
273277
dt = dateParser.toTimezone(dt, ngModelOptions.getOption('timezone'));
274278
ngModelCtrl.$setViewValue(dt);
@@ -278,6 +282,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
278282
setMode(self.modes[self.modes.indexOf($scope.datepickerMode) - 1]);
279283
$scope.$emit('uib:datepicker.mode');
280284
}
285+
281286
$scope.$broadcast('uib:datepicker.focus');
282287
};
283288

@@ -307,7 +312,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
307312
35: 'end',
308313
36: 'home',
309314
37: 'left',
310-
8: 'up',
315+
38: 'up',
311316
39: 'right',
312317
40: 'down'
313318
};
@@ -404,7 +409,9 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
404409

405410
function getDaysInMonth(year, month) {
406411
return month === 1 && year % 4 === 0 &&
407-
(year % 100 !== 0 || year % 400 === 0) ? 29 : DAYS_IN_MONTH[month];
412+
(year % 100 !== 0 || year % 400 === 0) ?
413+
29 :
414+
DAYS_IN_MONTH[month];
408415
}
409416

410417
this.init = function(ctrl) {
@@ -487,6 +494,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
487494

488495
this.handleKeyDown = function(key, evt) {
489496
var date = this.activeDate.getDate();
497+
490498
if (key === 'left') {
491499
date = date - 1;
492500
} else if (key === 'up') {

template/datepicker/datepicker.html

+25-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,27 @@
11
<div ng-switch="datepickerMode">
2-
<div uib-daypicker ng-switch-when="day" tabindex="0" class="uib-daypicker"></div>
3-
<div uib-monthpicker ng-switch-when="month" tabindex="0" class="uib-monthpicker"></div>
4-
<div uib-yearpicker ng-switch-when="year" tabindex="0" class="uib-yearpicker"></div>
2+
<div
3+
uib-daypicker
4+
ng-switch-when="day"
5+
tabindex="0"
6+
class="uib-daypicker"
7+
></div>
8+
<div
9+
uib-monthpicker
10+
ng-switch-when="month"
11+
tabindex="0"
12+
class="uib-monthpicker"
13+
></div>
14+
<div
15+
uib-yearpicker
16+
ng-switch-when="year"
17+
tabindex="0"
18+
class="uib-yearpicker"
19+
></div>
20+
<div
21+
class="sr-only-liveregion"
22+
role="region"
23+
id="{{::uniqueId}}-liveregion"
24+
aria-live="assertive"
25+
aria-atomic="true"
26+
></div>
527
</div>

template/datepicker/day.html

+1-3
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,7 @@
8787
>
8888
<button
8989
class="btn btn-default btn-sm"
90-
ng-attr-aria-atomic="{{isActive(dt) && 'true' || undefined }}"
91-
ng-attr-aria-label="{{isActive(dt) && dt.long || undefined}}"
92-
ng-attr-aria-live="{{isActive(dt) && 'assertive' || undefined}}"
90+
ng-attr-aria-label="{{isActive(dt) && dt.long}}"
9391
ng-click="select(dt.date)"
9492
ng-disabled="::dt.disabled"
9593
tabindex="-1"

template/datepicker/month.html

-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
</th>
2222
<th colspan="{{::yearHeaderColspan}}">
2323
<button
24-
name="helloWorld"
2524
id="{{::uniqueId}}-title"
2625
aria-live="assertive"
2726
aria-atomic="true"

template/datepickerPopup/popup.html

+28-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,33 @@
1-
<ul role="presentation" class="uib-datepicker-popup dropdown-menu uib-position-measure" dropdown-nested ng-if="isOpen" ng-keydown="keydown($event)" ng-click="$event.stopPropagation()">
1+
<ul
2+
role="presentation"
3+
class="uib-datepicker-popup dropdown-menu uib-position-measure"
4+
dropdown-nested
5+
ng-if="isOpen"
6+
ng-keydown="keydown($event)"
7+
ng-click="$event.stopPropagation()"
8+
>
29
<li ng-transclude></li>
3-
<li ng-if="showButtonBar" class="uib-button-bar">
10+
<li
11+
ng-if="showButtonBar"
12+
class="uib-button-bar"
13+
>
414
<span class="btn-group pull-left">
5-
<button type="button" class="btn btn-sm btn-info uib-datepicker-current" ng-click="select('today', $event)" ng-disabled="isDisabled('today')">{{ getText('current') }}</button>
6-
<button type="button" class="btn btn-sm btn-danger uib-clear" ng-click="select(null, $event)">{{ getText('clear') }}</button>
15+
<button
16+
type="button"
17+
class="btn btn-sm btn-info uib-datepicker-current"
18+
ng-click="select('today', $event)"
19+
ng-disabled="isDisabled('today')"
20+
>{{ getText('current') }}</button>
21+
<button
22+
type="button"
23+
class="btn btn-sm btn-danger uib-clear"
24+
ng-click="select(null, $event)"
25+
>{{ getText('clear') }}</button>
726
</span>
8-
<button type="button" class="btn btn-sm btn-success pull-right uib-close" ng-click="close($event)">{{ getText('close') }}</button>
27+
<button
28+
type="button"
29+
class="btn btn-sm btn-success pull-right uib-close"
30+
ng-click="close($event)"
31+
>{{ getText('close') }}</button>
932
</li>
1033
</ul>

0 commit comments

Comments
 (0)