├── .github ├── CODEOWNERS └── ISSUE_TEMPLATE.md ├── .gitignore ├── formatconfig.json ├── .npmignore ├── bower.json ├── wct.conf.json ├── manifest.json ├── test ├── index.html └── iron-a11y-announcer.html ├── package.json ├── demo ├── x-announces.js └── index.html ├── iron-a11y-announcer.d.ts ├── .travis.yml ├── CONTRIBUTING.md ├── iron-a11y-announcer.js └── README.md /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @e111077 2 | /.travis.yml @azakus 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bower_components* 2 | bower-*.json 3 | node_modules 4 | *.tgz 5 | -------------------------------------------------------------------------------- /formatconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "style": { 3 | "ReflowComments": false 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | *.tgz 2 | .github 3 | .travis.yml 4 | formatconfig.json 5 | gen-tsd.json 6 | test/ 7 | wct.conf.json 8 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "iron-a11y-announcer", 3 | "license": "http://polymer.github.io/LICENSE.txt" 4 | } 5 | -------------------------------------------------------------------------------- /wct.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": { 3 | "local": { 4 | "browserOptions": { 5 | "chrome": [ 6 | "no-sandbox", 7 | "headless", 8 | "disable-gpu" 9 | ], 10 | "firefox": [ 11 | "-headless" 12 | ] 13 | } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": { 3 | "iron-a11y-announcer.html": { 4 | "convertedUrl": "iron-a11y-announcer.js", 5 | "exports": { 6 | "Polymer.IronA11yAnnouncer": "IronA11yAnnouncer" 7 | } 8 | }, 9 | "index.html": { 10 | "convertedUrl": "index.html", 11 | "exports": {} 12 | }, 13 | "demo/index.html": { 14 | "convertedUrl": "demo/index.html", 15 | "exports": {} 16 | }, 17 | "demo/x-announces.html": { 18 | "convertedUrl": "demo/x-announces.js", 19 | "exports": {} 20 | }, 21 | "test/index.html": { 22 | "convertedUrl": "test/index.html", 23 | "exports": {} 24 | }, 25 | "test/iron-a11y-announcer.html": { 26 | "convertedUrl": "test/iron-a11y-announcer.html", 27 | "exports": {} 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | ### Description 3 | 4 | 5 | ### Expected outcome 6 | 7 | 8 | 9 | ### Actual outcome 10 | 11 | 12 | 13 | ### Live Demo 14 | 15 | 16 | ### Steps to reproduce 17 | 18 | 23 | 24 | ### Browsers Affected 25 | 26 | - [ ] Chrome 27 | - [ ] Firefox 28 | - [ ] Safari 9 29 | - [ ] Safari 8 30 | - [ ] Safari 7 31 | - [ ] Edge 32 | - [ ] IE 11 33 | - [ ] IE 10 34 | -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | 10 | 11 | iron-a11y-announcer tests 12 | 13 | 14 | 15 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "A singleton element that simplifies announcing text to screen readers.", 3 | "keywords": [ 4 | "web-components", 5 | "polymer", 6 | "a11y", 7 | "live" 8 | ], 9 | "repository": { 10 | "type": "git", 11 | "url": "git://github.com/PolymerElements/iron-a11y-announcer.git" 12 | }, 13 | "name": "@polymer/iron-a11y-announcer", 14 | "license": "BSD-3-Clause", 15 | "devDependencies": { 16 | "@polymer/iron-demo-helpers": "^3.0.1", 17 | "@polymer/iron-test-helpers": "^3.0.0-pre.26", 18 | "@polymer/paper-button": "^3.0.0-pre.26", 19 | "@polymer/test-fixture": "^4.0.1", 20 | "@webcomponents/webcomponentsjs": "^2.0.0", 21 | "wct-browser-legacy": "^1.0.1", 22 | "webmat": "^0.2.0" 23 | }, 24 | "scripts": { 25 | "format": "webmat" 26 | }, 27 | "version": "3.2.0", 28 | "main": "iron-a11y-announcer.js", 29 | "author": "The Polymer Authors", 30 | "dependencies": { 31 | "@polymer/polymer": "^3.0.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /demo/x-announces.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 The Polymer Project Authors. All rights reserved. 3 | This code may only be used under the BSD style license found at 4 | http://polymer.github.io/LICENSE The complete set of authors may be found at 5 | http://polymer.github.io/AUTHORS The complete set of contributors may be found 6 | at http://polymer.github.io/CONTRIBUTORS Code distributed by Google as part of 7 | the polymer project is also subject to an additional IP rights grant found at 8 | http://polymer.github.io/PATENTS 9 | */ 10 | import '@polymer/polymer/polymer-legacy.js'; 11 | import '@polymer/paper-button/paper-button.js'; 12 | 13 | import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js'; 14 | import {html} from '@polymer/polymer/lib/utils/html-tag.js'; 15 | 16 | import {IronA11yAnnouncer} from '../iron-a11y-announcer.js'; 17 | 18 | Polymer({ 19 | _template: html` 20 | 27 | 28 | [[message]] 29 | Announce 30 | `, 31 | 32 | is: 'x-announces', 33 | hostAttributes: {'aria-hidden': 'true'}, 34 | properties: {message: {type: String}}, 35 | 36 | attached: function() { 37 | IronA11yAnnouncer.requestAvailability(); 38 | }, 39 | 40 | _onTapAnnounce: function() { 41 | this.fire('iron-announce', {text: this.message.trim()}, {bubbles: true}); 42 | } 43 | }); 44 | -------------------------------------------------------------------------------- /iron-a11y-announcer.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * DO NOT EDIT 3 | * 4 | * This file was automatically generated by 5 | * https://github.com/Polymer/tools/tree/master/packages/gen-typescript-declarations 6 | * 7 | * To modify these typings, edit the source file(s): 8 | * iron-a11y-announcer.js 9 | */ 10 | 11 | import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js'; 12 | 13 | import {html} from '@polymer/polymer/lib/utils/html-tag.js'; 14 | 15 | export {IronA11yAnnouncer}; 16 | 17 | import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js'; 18 | 19 | declare class IronA11yAnnouncer { 20 | 21 | /** 22 | * The value of mode is used to set the `aria-live` attribute 23 | * for the element that will be announced. Valid values are: `off`, 24 | * `polite` and `assertive`. 25 | */ 26 | mode: string|null|undefined; 27 | 28 | /** 29 | * The timeout on refreshing the announcement text. Larger timeouts are 30 | * needed for certain screen readers to re-announce the same message. 31 | */ 32 | timeout: number|null|undefined; 33 | _text: string|null|undefined; 34 | created(): void; 35 | 36 | /** 37 | * Cause a text string to be announced by screen readers. 38 | * 39 | * @param text The text that should be announced. 40 | */ 41 | announce(text: string): void; 42 | _onIronAnnounce(event: any): void; 43 | static requestAvailability(): void; 44 | } 45 | 46 | interface IronA11yAnnouncer extends LegacyElementMixin, HTMLElement { 47 | } 48 | 49 | declare global { 50 | 51 | interface HTMLElementTagNameMap { 52 | "iron-a11y-announcer": IronA11yAnnouncer; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /test/iron-a11y-announcer.html: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | iron-a11y-announcer 15 | 16 | 17 | 18 | 19 | 20 | 21 | 24 | 25 | 26 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | sudo: 'false' 3 | before_script: 4 | - npm install -g npm@6 5 | - npm install -g polymer-cli 6 | - git checkout package-lock.json 7 | - >- 8 | npm run format && git diff --exit-code || (echo -e '\n\033[31mERROR:\033[0m 9 | Project is not formatted. Please run "npm run format".' && false) 10 | env: 11 | global: 12 | - secure: >- 13 | XQbLITIT7rqBNEMyMfq6HzasmHHlm46klpzJ9heLzJiX7j83ZTV3c/01XSM/1lSt+Y7uyGkZtNSYL+F7pFlBuegnw6XVlkOqTmnbKaN0h2M71TVu/mzW7w3u4yXen2wR2Yzl+zvfXGEz5fxQq9nyJs0+mVQaXWgze0a1QuyBhU9O6+x3iv1eR3baenf+5L8Zct3f8Npgg70+6OLQUKd8/mKeDI3/trDEsyKlmiwQobZ/nnwi5sOBBR3f3KqpREsUBclJdqiHmC+tir00ngGTjqdtnyuiUZAGJwtk/YU02lTtsTAg8AevBRa7NDapKr08V1Sudy1cWvCen8LaHPIzReRZ6SmWANQws1kczIiOYnLWC5NUHQBfifjvCrtm01Xao9rxT/cgvfYCnZryVZzQbKBdp6M2JiE9GSkFajeVR6IweZyJglEllGYOkx8HNRPPmW/cclamnxPO8veDjuoqudXRlKGpCSax7HblRgCDz+XEVy2oDDPEQR6lgClJLD50WpQ9DLLJ2AlsiWf61So0BXAGKrdafBnOsfBeiU/Pw/qcCM3ItlZqSsn8KR7MdkgDvjHMDEmOoGOShmJR9x3Sr3Z57YCLIIHdS0Xxx8XkDomRC298/lWpUy3OPtBLtywq2W+5+rv2c6CNxMjfP7k8GN6z78f65XCrM9V2JzgWBxA= 14 | - secure: >- 15 | jwWIuEuiycRtT7OY/HGiEmVGdhdXLfoOHy9ssYhxJ3fy1muCCFrjK8845cd7X8mGuSINxVnEdFJyl3ujoXklW63g7k3x9o1WG7h6B/6JRi1w6VMT0QfyL7UQ2PokRV2aiuzbjE35fJzKXMZtAeKnUPbIzv1A0RH0Gpo9z4D7eG4CQ2j1QAcPguRBgWeAbFXThFfL8oKGgsapTONatZmX+3i4HCltfSuQKqXPfCPVpQsNPejlagFno8dZjEJ+nl/UsuVVeal7/IFSFBX+mKErsN+xsw1pu/MX0kd1fsNGL7X5SQvzeqkBGWmZbno5OY/KZ3e7Dt1syNtVsE87FkWgM+8gg/F9kqXZ8X241CDmctNNwBvD2+TrqiPCH3ORDI8aTE+MofVtatOPu6oBXGp9i8TggymwdCOpUkqvXHJ8EbiisTNlY+cR+8LJfaEZZgMr/P5n1oRwwSixDfIWz+Kxm0yDRodHPkQV+9LWE4K2PFATp3apz+w5+W68OIHIeNY2OPL39+cQ5xH1E8/Np+GgkyGVbrRoC7cPrKyA1F6zlL7mRJWWCmvVYJitm72VENpr+9KFcLCB3N36O9FKXKUU7aOfkTHfDE85rN7f3fhDPnKlJ39mROD84rxUlfYq+Lj37kzCOPPJH32HgQWdTWnQIu60bJckUK1MLK6YO6VjylI= 16 | node_js: node 17 | addons: 18 | firefox: latest 19 | chrome: stable 20 | script: 21 | - xvfb-run polymer test --module-resolution=node --npm 22 | - >- 23 | if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then polymer test 24 | --module-resolution=node --npm -s 'default'; fi 25 | dist: xenial 26 | cache: 27 | directories: 28 | - node_modules 29 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | 13 | 14 | # Polymer Elements 15 | ## Guide for Contributors 16 | 17 | Polymer Elements are built in the open, and the Polymer authors eagerly encourage any and all forms of community contribution. When contributing, please follow these guidelines: 18 | 19 | ### Filing Issues 20 | 21 | **If you are filing an issue to request a feature**, please provide a clear description of the feature. It can be helpful to describe answers to the following questions: 22 | 23 | 1. **Who will use the feature?** _“As someone filling out a form…”_ 24 | 2. **When will they use the feature?** _“When I enter an invalid value…”_ 25 | 3. **What is the user’s goal?** _“I want to be visually notified that the value needs to be corrected…”_ 26 | 27 | **If you are filing an issue to report a bug**, please provide: 28 | 29 | 1. **A clear description of the bug and related expectations.** Consider using the following example template for reporting a bug: 30 | 31 | ```markdown 32 | The `paper-foo` element causes the page to turn pink when clicked. 33 | 34 | ## Expected outcome 35 | 36 | The page stays the same color. 37 | 38 | ## Actual outcome 39 | 40 | The page turns pink. 41 | 42 | ## Steps to reproduce 43 | 44 | 1. Put a `paper-foo` element in the page. 45 | 2. Open the page in a web browser. 46 | 3. Click the `paper-foo` element. 47 | ``` 48 | 49 | 2. **A reduced test case that demonstrates the problem.** If possible, please include the test case as a JSBin. Start with this template to easily import and use relevant Polymer Elements: [https://jsbin.com/cagaye/edit?html,output](https://jsbin.com/cagaye/edit?html,output). 50 | 51 | 3. **A list of browsers where the problem occurs.** This can be skipped if the problem is the same across all browsers. 52 | 53 | ### Submitting Pull Requests 54 | 55 | **Before creating a pull request**, please ensure that an issue exists for the corresponding change in the pull request that you intend to make. **If an issue does not exist, please create one per the guidelines above**. The goal is to discuss the design and necessity of the proposed change with Polymer authors and community before diving into a pull request. 56 | 57 | When submitting pull requests, please provide: 58 | 59 | 1. **A reference to the corresponding issue** or issues that will be closed by the pull request. Please refer to these issues in the pull request description using the following syntax: 60 | 61 | ```markdown 62 | (For a single issue) 63 | Fixes #20 64 | 65 | (For multiple issues) 66 | Fixes #32, fixes #40 67 | ``` 68 | 69 | 2. **A succinct description of the design** used to fix any related issues. For example: 70 | 71 | ```markdown 72 | This fixes #20 by removing styles that leaked which would cause the page to turn pink whenever `paper-foo` is clicked. 73 | ``` 74 | 75 | 3. **At least one test for each bug fixed or feature added** as part of the pull request. Pull requests that fix bugs or add features without accompanying tests will not be considered. 76 | 77 | If a proposed change contains multiple commits, please [squash commits](https://www.google.com/url?q=http://blog.steveklabnik.com/posts/2012-11-08-how-to-squash-commits-in-a-github-pull-request) to as few as is necessary to succinctly express the change. A Polymer author can help you squash commits, so don’t be afraid to ask us if you need help with that! 78 | -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | iron-a11y-announcer demo 20 | 21 | 22 | 23 | 42 | 43 | 44 |
45 |

Note: in order to hear the announcements, be sure to turn on your favorite screen reader!

46 | 47 |

Announcer used directly on the main document

48 | 49 | 70 | 71 | 72 |

Announcer used inside a custom element

73 | 74 | 79 | 80 |
81 | 82 | 85 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /iron-a11y-announcer.js: -------------------------------------------------------------------------------- 1 | /** 2 | @license 3 | Copyright (c) 2015 The Polymer Project Authors. All rights reserved. 4 | This code may only be used under the BSD style license found at 5 | http://polymer.github.io/LICENSE.txt The complete set of authors may be found at 6 | http://polymer.github.io/AUTHORS.txt The complete set of contributors may be 7 | found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as 8 | part of the polymer project is also subject to an additional IP rights grant 9 | found at http://polymer.github.io/PATENTS.txt 10 | */ 11 | import '@polymer/polymer/polymer-legacy.js'; 12 | 13 | import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js'; 14 | import {html} from '@polymer/polymer/lib/utils/html-tag.js'; 15 | 16 | /** 17 | `iron-a11y-announcer` is a singleton element that is intended to add a11y 18 | to features that require on-demand announcement from screen readers. In 19 | order to make use of the announcer, it is best to request its availability 20 | in the announcing element. 21 | 22 | Example: 23 | 24 | Polymer({ 25 | 26 | is: 'x-chatty', 27 | 28 | attached: function() { 29 | // This will create the singleton element if it has not 30 | // been created yet: 31 | Polymer.IronA11yAnnouncer.requestAvailability(); 32 | } 33 | }); 34 | 35 | After the `iron-a11y-announcer` has been made available, elements can 36 | make announces by firing bubbling `iron-announce` events. 37 | 38 | Example: 39 | 40 | this.fire('iron-announce', { 41 | text: 'This is an announcement!' 42 | }, { bubbles: true }); 43 | 44 | Note: announcements are only audible if you have a screen reader enabled. 45 | 46 | @demo demo/index.html 47 | */ 48 | export const IronA11yAnnouncer = Polymer({ 49 | /** @override */ 50 | _template: html` 51 | 58 |
[[_text]]
59 | `, 60 | 61 | is: 'iron-a11y-announcer', 62 | 63 | properties: { 64 | 65 | /** 66 | * The value of mode is used to set the `aria-live` attribute 67 | * for the element that will be announced. Valid values are: `off`, 68 | * `polite` and `assertive`. 69 | */ 70 | mode: {type: String, value: 'polite'}, 71 | 72 | /** 73 | * The timeout on refreshing the announcement text. Larger timeouts are 74 | * needed for certain screen readers to re-announce the same message. 75 | */ 76 | timeout: {type: Number, value: 150}, 77 | 78 | _text: {type: String, value: ''}, 79 | }, 80 | 81 | /** @override */ 82 | created: function() { 83 | if (!IronA11yAnnouncer.instance) { 84 | IronA11yAnnouncer.instance = this; 85 | } 86 | 87 | document.addEventListener('iron-announce', this._onIronAnnounce.bind(this)); 88 | }, 89 | 90 | /** 91 | * Cause a text string to be announced by screen readers. 92 | * 93 | * @param {string} text The text that should be announced. 94 | */ 95 | announce: function(text) { 96 | this._text = ''; 97 | this.async(function() { 98 | this._text = text; 99 | }, this.timeout); 100 | }, 101 | 102 | _onIronAnnounce: function(event) { 103 | if (event.detail && event.detail.text) { 104 | this.announce(event.detail.text); 105 | } 106 | } 107 | }); 108 | 109 | IronA11yAnnouncer.instance = null; 110 | 111 | IronA11yAnnouncer.requestAvailability = function() { 112 | if (!IronA11yAnnouncer.instance) { 113 | IronA11yAnnouncer.instance = document.createElement('iron-a11y-announcer'); 114 | } 115 | 116 | if (document.body) { 117 | document.body.appendChild(IronA11yAnnouncer.instance); 118 | } else { 119 | document.addEventListener('load', function() { 120 | document.body.appendChild(IronA11yAnnouncer.instance); 121 | }); 122 | } 123 | }; 124 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 14 | [![Published on NPM](https://img.shields.io/npm/v/@polymer/iron-a11y-announcer.svg)](https://www.npmjs.com/package/@polymer/iron-a11y-announcer) 15 | [![Build status](https://travis-ci.org/PolymerElements/iron-a11y-announcer.svg?branch=master)](https://travis-ci.org/PolymerElements/iron-a11y-announcer) 16 | [![Published on webcomponents.org](https://img.shields.io/badge/webcomponents.org-published-blue.svg)](https://webcomponents.org/element/@polymer/iron-a11y-announcer) 17 | 18 | ## <iron-a11y-announcer> 19 | 20 | `iron-a11y-announcer` is a singleton element that is intended to add a11y 21 | to features that require on-demand announcement from screen readers. In 22 | order to make use of the announcer, it is best to request its availability 23 | in the announcing element. 24 | Note: announcements are only audible if you have a screen reader enabled. 25 | 26 | See: [Documentation](https://www.webcomponents.org/element/@polymer/iron-a11y-announcer), 27 | [Demo](https://www.webcomponents.org/element/@polymer/iron-a11y-announcer/demo/demo/index.html) 28 | 29 | ## Usage 30 | 31 | ### Installation 32 | ``` 33 | npm install --save @polymer/iron-a11y-announcer 34 | ``` 35 | 36 | ### In an html file 37 | ```html 38 | 39 | 40 | 49 | 50 | 51 | ``` 52 | 53 | ### In a Polymer 3 element 54 | ```js 55 | import {PolymerElement, html} from '@polymer/polymer'; 56 | import {IronA11yAnnouncer} from '@polymer/iron-a11y-announcer/iron-a11y-announcer.js'; 57 | 58 | class SampleElement extends PolymerElement { 59 | static get template() { 60 | return html` 61 | 62 | `; 63 | } 64 | function attached() { 65 | IronA11yAnnouncer.requestAvailability(); 66 | } 67 | 68 | // After the `iron-a11y-announcer` has been made available, elements can 69 | // make announces by firing bubbling `iron-announce` events. 70 | // Note: announcements are only audible if you have a screen reader enabled. 71 | function announce() { 72 | IronA11yAnnouncer.instance.fire('iron-announce', 73 | {text: 'Hello there!'}, {bubbles: true}); 74 | } 75 | } 76 | customElements.define('sample-element', SampleElement); 77 | ``` 78 | 79 | ## Contributing 80 | If you want to send a PR to this element, here are 81 | the instructions for running the tests and demo locally: 82 | 83 | ### Installation 84 | ```sh 85 | git clone https://github.com/PolymerElements/iron-a11y-announcer 86 | cd iron-a11y-announcer 87 | npm install 88 | npm install -g polymer-cli 89 | ``` 90 | 91 | ### Running the demo locally 92 | ```sh 93 | polymer serve --npm 94 | open http://127.0.0.1:/demo/ 95 | ``` 96 | 97 | ### Running the tests 98 | ```sh 99 | polymer test --npm 100 | ``` 101 | 102 | ## Known Issues 103 | This element doesn't work on Firefox (it doesn't read anything in Voice Over), since 104 | `aria-live` has been broken since the Quantum redesign (see the [MDN docs demo](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions)) 105 | -- we tested it on Firefox 60, but it doesn't look like a regression, so 106 | it's probably broken on older versions as well. 107 | --------------------------------------------------------------------------------