├── .editorconfig ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── 0-new-issue.yml │ ├── 1-new-feature.yml │ └── config.yml └── workflows │ └── build.yml ├── .gitignore ├── .pr-preview.json ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── PULL_REQUEST_TEMPLATE.md ├── README.md ├── notifications.bs └── review-drafts ├── 2018-07.bs ├── 2019-01.bs ├── 2020-01.bs ├── 2021-01.bs ├── 2021-07.bs ├── 2022-01.bs ├── 2023-01.bs ├── 2023-07.bs └── 2025-01.bs /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | charset = utf-8 7 | indent_size = 2 8 | indent_style = space 9 | trim_trailing_whitespace = true 10 | max_line_length = 100 11 | 12 | [Makefile] 13 | indent_style = tab 14 | 15 | [*.md] 16 | max_line_length = off 17 | 18 | [*.bs] 19 | indent_size = 1 20 | 21 | [*.py] 22 | indent_size = 4 23 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.bs diff=html linguist-language=HTML 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/0-new-issue.yml: -------------------------------------------------------------------------------- 1 | name: New issue 2 | description: File a new issue against the Notifications API Standard. 3 | body: 4 | - type: markdown 5 | attributes: 6 | value: | 7 | Before filling out this form, please familiarize yourself with the [Code of Conduct](https://whatwg.org/code-of-conduct). You might also find the [FAQ](https://whatwg.org/faq) and [Working Mode](https://whatwg.org/working-mode) useful. 8 | 9 | If at any point you have questions, please reach out to us on [Chat](https://whatwg.org/chat). 10 | - type: textarea 11 | attributes: 12 | label: "What is the issue with the Notifications API Standard?" 13 | validations: 14 | required: true 15 | - type: markdown 16 | attributes: 17 | value: "Thank you for taking the time to improve the Notifications API Standard!" 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/1-new-feature.yml: -------------------------------------------------------------------------------- 1 | name: New feature 2 | description: Request a new feature in the Notifications API Standard. 3 | labels: ["addition/proposal", "needs implementer interest"] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | Before filling out this form, please familiarize yourself with the [Code of Conduct](https://whatwg.org/code-of-conduct), [FAQ](https://whatwg.org/faq), and [Working Mode](https://whatwg.org/working-mode). They help with setting expectations and making sure you know what is required. The FAQ ["How should I go about proposing new features to WHATWG standards?"](https://whatwg.org/faq#adding-new-features) is especially relevant. 9 | 10 | If at any point you have questions, please reach out to us on [Chat](https://whatwg.org/chat). 11 | - type: textarea 12 | attributes: 13 | label: "What problem are you trying to solve?" 14 | validations: 15 | required: true 16 | - type: textarea 17 | attributes: 18 | label: "What solutions exist today?" 19 | - type: textarea 20 | attributes: 21 | label: "How would you solve it?" 22 | - type: textarea 23 | attributes: 24 | label: "Anything else?" 25 | - type: markdown 26 | attributes: 27 | value: "Thank you for taking the time to improve the Notifications API Standard!" 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Chat 4 | url: https://whatwg.org/chat 5 | about: Please do reach out with questions and feedback! 6 | - name: Stack Overflow 7 | url: https://stackoverflow.com/ 8 | about: If you're having trouble building a web page, this is not the right repository. Consider asking your question on Stack Overflow instead. 9 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | push: 8 | branches: 9 | - main 10 | workflow_dispatch: 11 | 12 | jobs: 13 | build: 14 | name: Build 15 | runs-on: ubuntu-22.04 16 | steps: 17 | - uses: actions/checkout@v4 18 | with: 19 | fetch-depth: 2 20 | - uses: actions/setup-python@v5 21 | with: 22 | python-version: "3.11" 23 | - run: pip install bikeshed && bikeshed update 24 | # Note: `make deploy` will do a deploy dry run on PRs. 25 | - run: make deploy 26 | env: 27 | SERVER: ${{ secrets.MARQUEE_SERVER }} 28 | SERVER_PUBLIC_KEY: ${{ secrets.MARQUEE_PUBLIC_KEY }} 29 | SERVER_DEPLOY_KEY: ${{ secrets.MARQUEE_DEPLOY_KEY }} 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /notifications.spec.whatwg.org/ 2 | /deploy.sh 3 | /notifications.html 4 | -------------------------------------------------------------------------------- /.pr-preview.json: -------------------------------------------------------------------------------- 1 | { 2 | "src_file": "notifications.bs", 3 | "type": "bikeshed", 4 | "params": { 5 | "force": 1, 6 | "md-status": "LS-PR", 7 | "md-Text-Macro": "PR-NUMBER {{ pull_request.number }}" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Please see the [WHATWG Contributor Guidelines](https://github.com/whatwg/meta/blob/main/CONTRIBUTING.md). 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © WHATWG (Apple, Google, Mozilla, Microsoft). 2 | 3 | This work is licensed under a Creative Commons Attribution 4.0 International 4 | License. To the extent portions of it are incorporated into source code, 5 | such portions in the source code are licensed under the BSD 3-Clause License instead. 6 | 7 | - - - - 8 | 9 | Creative Commons Attribution 4.0 International Public License 10 | 11 | By exercising the Licensed Rights (defined below), You accept and agree 12 | to be bound by the terms and conditions of this Creative Commons 13 | Attribution 4.0 International Public License ("Public License"). To the 14 | extent this Public License may be interpreted as a contract, You are 15 | granted the Licensed Rights in consideration of Your acceptance of 16 | these terms and conditions, and the Licensor grants You such rights in 17 | consideration of benefits the Licensor receives from making the 18 | Licensed Material available under these terms and conditions. 19 | 20 | 21 | Section 1 -- Definitions. 22 | 23 | a. Adapted Material means material subject to Copyright and Similar 24 | Rights that is derived from or based upon the Licensed Material 25 | and in which the Licensed Material is translated, altered, 26 | arranged, transformed, or otherwise modified in a manner requiring 27 | permission under the Copyright and Similar Rights held by the 28 | Licensor. For purposes of this Public License, where the Licensed 29 | Material is a musical work, performance, or sound recording, 30 | Adapted Material is always produced where the Licensed Material is 31 | synched in timed relation with a moving image. 32 | 33 | b. Adapter's License means the license You apply to Your Copyright 34 | and Similar Rights in Your contributions to Adapted Material in 35 | accordance with the terms and conditions of this Public License. 36 | 37 | c. Copyright and Similar Rights means copyright and/or similar rights 38 | closely related to copyright including, without limitation, 39 | performance, broadcast, sound recording, and Sui Generis Database 40 | Rights, without regard to how the rights are labeled or 41 | categorized. For purposes of this Public License, the rights 42 | specified in Section 2(b)(1)-(2) are not Copyright and Similar 43 | Rights. 44 | 45 | d. Effective Technological Measures means those measures that, in the 46 | absence of proper authority, may not be circumvented under laws 47 | fulfilling obligations under Article 11 of the WIPO Copyright 48 | Treaty adopted on December 20, 1996, and/or similar international 49 | agreements. 50 | 51 | e. Exceptions and Limitations means fair use, fair dealing, and/or 52 | any other exception or limitation to Copyright and Similar Rights 53 | that applies to Your use of the Licensed Material. 54 | 55 | f. Licensed Material means the artistic or literary work, database, 56 | or other material to which the Licensor applied this Public 57 | License. 58 | 59 | g. Licensed Rights means the rights granted to You subject to the 60 | terms and conditions of this Public License, which are limited to 61 | all Copyright and Similar Rights that apply to Your use of the 62 | Licensed Material and that the Licensor has authority to license. 63 | 64 | h. Licensor means the individual(s) or entity(ies) granting rights 65 | under this Public License. 66 | 67 | i. Share means to provide material to the public by any means or 68 | process that requires permission under the Licensed Rights, such 69 | as reproduction, public display, public performance, distribution, 70 | dissemination, communication, or importation, and to make material 71 | available to the public including in ways that members of the 72 | public may access the material from a place and at a time 73 | individually chosen by them. 74 | 75 | j. Sui Generis Database Rights means rights other than copyright 76 | resulting from Directive 96/9/EC of the European Parliament and of 77 | the Council of 11 March 1996 on the legal protection of databases, 78 | as amended and/or succeeded, as well as other essentially 79 | equivalent rights anywhere in the world. 80 | 81 | k. You means the individual or entity exercising the Licensed Rights 82 | under this Public License. Your has a corresponding meaning. 83 | 84 | 85 | Section 2 -- Scope. 86 | 87 | a. License grant. 88 | 89 | 1. Subject to the terms and conditions of this Public License, 90 | the Licensor hereby grants You a worldwide, royalty-free, 91 | non-sublicensable, non-exclusive, irrevocable license to 92 | exercise the Licensed Rights in the Licensed Material to: 93 | 94 | a. reproduce and Share the Licensed Material, in whole or 95 | in part; and 96 | 97 | b. produce, reproduce, and Share Adapted Material. 98 | 99 | 2. Exceptions and Limitations. For the avoidance of doubt, where 100 | Exceptions and Limitations apply to Your use, this Public 101 | License does not apply, and You do not need to comply with 102 | its terms and conditions. 103 | 104 | 3. Term. The term of this Public License is specified in Section 105 | 6(a). 106 | 107 | 4. Media and formats; technical modifications allowed. The 108 | Licensor authorizes You to exercise the Licensed Rights in 109 | all media and formats whether now known or hereafter created, 110 | and to make technical modifications necessary to do so. The 111 | Licensor waives and/or agrees not to assert any right or 112 | authority to forbid You from making technical modifications 113 | necessary to exercise the Licensed Rights, including 114 | technical modifications necessary to circumvent Effective 115 | Technological Measures. For purposes of this Public License, 116 | simply making modifications authorized by this Section 2(a) 117 | (4) never produces Adapted Material. 118 | 119 | 5. Downstream recipients. 120 | 121 | a. Offer from the Licensor -- Licensed Material. Every 122 | recipient of the Licensed Material automatically 123 | receives an offer from the Licensor to exercise the 124 | Licensed Rights under the terms and conditions of this 125 | Public License. 126 | 127 | b. No downstream restrictions. You may not offer or impose 128 | any additional or different terms or conditions on, or 129 | apply any Effective Technological Measures to, the 130 | Licensed Material if doing so restricts exercise of the 131 | Licensed Rights by any recipient of the Licensed 132 | Material. 133 | 134 | 6. No endorsement. Nothing in this Public License constitutes or 135 | may be construed as permission to assert or imply that You 136 | are, or that Your use of the Licensed Material is, connected 137 | with, or sponsored, endorsed, or granted official status by, 138 | the Licensor or others designated to receive attribution as 139 | provided in Section 3(a)(1)(A)(i). 140 | 141 | b. Other rights. 142 | 143 | 1. Moral rights, such as the right of integrity, are not 144 | licensed under this Public License, nor are publicity, 145 | privacy, and/or other similar personality rights; however, to 146 | the extent possible, the Licensor waives and/or agrees not to 147 | assert any such rights held by the Licensor to the limited 148 | extent necessary to allow You to exercise the Licensed 149 | Rights, but not otherwise. 150 | 151 | 2. Patent and trademark rights are not licensed under this 152 | Public License. 153 | 154 | 3. To the extent possible, the Licensor waives any right to 155 | collect royalties from You for the exercise of the Licensed 156 | Rights, whether directly or through a collecting society 157 | under any voluntary or waivable statutory or compulsory 158 | licensing scheme. In all other cases the Licensor expressly 159 | reserves any right to collect such royalties. 160 | 161 | 162 | Section 3 -- License Conditions. 163 | 164 | Your exercise of the Licensed Rights is expressly made subject to the 165 | following conditions. 166 | 167 | a. Attribution. 168 | 169 | 1. If You Share the Licensed Material (including in modified 170 | form), You must: 171 | 172 | a. retain the following if it is supplied by the Licensor 173 | with the Licensed Material: 174 | 175 | i. identification of the creator(s) of the Licensed 176 | Material and any others designated to receive 177 | attribution, in any reasonable manner requested by 178 | the Licensor (including by pseudonym if 179 | designated); 180 | 181 | ii. a copyright notice; 182 | 183 | iii. a notice that refers to this Public License; 184 | 185 | iv. a notice that refers to the disclaimer of 186 | warranties; 187 | 188 | v. a URI or hyperlink to the Licensed Material to the 189 | extent reasonably practicable; 190 | 191 | b. indicate if You modified the Licensed Material and 192 | retain an indication of any previous modifications; and 193 | 194 | c. indicate the Licensed Material is licensed under this 195 | Public License, and include the text of, or the URI or 196 | hyperlink to, this Public License. 197 | 198 | 2. You may satisfy the conditions in Section 3(a)(1) in any 199 | reasonable manner based on the medium, means, and context in 200 | which You Share the Licensed Material. For example, it may be 201 | reasonable to satisfy the conditions by providing a URI or 202 | hyperlink to a resource that includes the required 203 | information. 204 | 205 | 3. If requested by the Licensor, You must remove any of the 206 | information required by Section 3(a)(1)(A) to the extent 207 | reasonably practicable. 208 | 209 | 4. If You Share Adapted Material You produce, the Adapter's 210 | License You apply must not prevent recipients of the Adapted 211 | Material from complying with this Public License. 212 | 213 | 214 | Section 4 -- Sui Generis Database Rights. 215 | 216 | Where the Licensed Rights include Sui Generis Database Rights that 217 | apply to Your use of the Licensed Material: 218 | 219 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right 220 | to extract, reuse, reproduce, and Share all or a substantial 221 | portion of the contents of the database; 222 | 223 | b. if You include all or a substantial portion of the database 224 | contents in a database in which You have Sui Generis Database 225 | Rights, then the database in which You have Sui Generis Database 226 | Rights (but not its individual contents) is Adapted Material; and 227 | 228 | c. You must comply with the conditions in Section 3(a) if You Share 229 | all or a substantial portion of the contents of the database. 230 | 231 | For the avoidance of doubt, this Section 4 supplements and does not 232 | replace Your obligations under this Public License where the Licensed 233 | Rights include other Copyright and Similar Rights. 234 | 235 | 236 | Section 5 -- Disclaimer of Warranties and Limitation of Liability. 237 | 238 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE 239 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS 240 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF 241 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, 242 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, 243 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR 244 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, 245 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT 246 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT 247 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. 248 | 249 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE 250 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, 251 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, 252 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, 253 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR 254 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN 255 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR 256 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR 257 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. 258 | 259 | c. The disclaimer of warranties and limitation of liability provided 260 | above shall be interpreted in a manner that, to the extent 261 | possible, most closely approximates an absolute disclaimer and 262 | waiver of all liability. 263 | 264 | 265 | Section 6 -- Term and Termination. 266 | 267 | a. This Public License applies for the term of the Copyright and 268 | Similar Rights licensed here. However, if You fail to comply with 269 | this Public License, then Your rights under this Public License 270 | terminate automatically. 271 | 272 | b. Where Your right to use the Licensed Material has terminated under 273 | Section 6(a), it reinstates: 274 | 275 | 1. automatically as of the date the violation is cured, provided 276 | it is cured within 30 days of Your discovery of the 277 | violation; or 278 | 279 | 2. upon express reinstatement by the Licensor. 280 | 281 | For the avoidance of doubt, this Section 6(b) does not affect any 282 | right the Licensor may have to seek remedies for Your violations 283 | of this Public License. 284 | 285 | c. For the avoidance of doubt, the Licensor may also offer the 286 | Licensed Material under separate terms or conditions or stop 287 | distributing the Licensed Material at any time; however, doing so 288 | will not terminate this Public License. 289 | 290 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public 291 | License. 292 | 293 | 294 | Section 7 -- Other Terms and Conditions. 295 | 296 | a. The Licensor shall not be bound by any additional or different 297 | terms or conditions communicated by You unless expressly agreed. 298 | 299 | b. Any arrangements, understandings, or agreements regarding the 300 | Licensed Material not stated herein are separate from and 301 | independent of the terms and conditions of this Public License. 302 | 303 | 304 | Section 8 -- Interpretation. 305 | 306 | a. For the avoidance of doubt, this Public License does not, and 307 | shall not be interpreted to, reduce, limit, restrict, or impose 308 | conditions on any use of the Licensed Material that could lawfully 309 | be made without permission under this Public License. 310 | 311 | b. To the extent possible, if any provision of this Public License is 312 | deemed unenforceable, it shall be automatically reformed to the 313 | minimum extent necessary to make it enforceable. If the provision 314 | cannot be reformed, it shall be severed from this Public License 315 | without affecting the enforceability of the remaining terms and 316 | conditions. 317 | 318 | c. No term or condition of this Public License will be waived and no 319 | failure to comply consented to unless expressly agreed to by the 320 | Licensor. 321 | 322 | d. Nothing in this Public License constitutes or may be interpreted 323 | as a limitation upon, or waiver of, any privileges and immunities 324 | that apply to the Licensor or You, including from the legal 325 | processes of any jurisdiction or authority. 326 | 327 | - - - - 328 | 329 | BSD 3-Clause License 330 | 331 | Redistribution and use in source and binary forms, with or without 332 | modification, are permitted provided that the following conditions are met: 333 | 334 | 1. Redistributions of source code must retain the above copyright notice, this 335 | list of conditions and the following disclaimer. 336 | 337 | 2. Redistributions in binary form must reproduce the above copyright notice, 338 | this list of conditions and the following disclaimer in the documentation 339 | and/or other materials provided with the distribution. 340 | 341 | 3. Neither the name of the copyright holder nor the names of its 342 | contributors may be used to endorse or promote products derived from 343 | this software without specific prior written permission. 344 | 345 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 346 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 347 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 348 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 349 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 350 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 351 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 352 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 353 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 354 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 355 | 356 | - - - - 357 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL=/bin/bash -o pipefail 2 | .PHONY: local remote deploy 3 | 4 | remote: notifications.bs 5 | @ (HTTP_STATUS=$$(curl https://api.csswg.org/bikeshed/ \ 6 | --output notifications.html \ 7 | --write-out "%{http_code}" \ 8 | --header "Accept: text/plain, text/html" \ 9 | -F die-on=warning \ 10 | -F md-Text-Macro="COMMIT-SHA LOCAL COPY" \ 11 | -F file=@notifications.bs) && \ 12 | [[ "$$HTTP_STATUS" -eq "200" ]]) || ( \ 13 | echo ""; cat notifications.html; echo ""; \ 14 | rm -f notifications.html; \ 15 | exit 22 \ 16 | ); 17 | 18 | local: notifications.bs 19 | bikeshed spec notifications.bs notifications.html --md-Text-Macro="COMMIT-SHA LOCAL-COPY" 20 | 21 | deploy: notifications.bs 22 | curl --remote-name --fail https://resources.whatwg.org/build/deploy.sh 23 | bash ./deploy.sh 24 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 8 | 9 | - [ ] At least two implementers are interested (and none opposed): 10 | * … 11 | * … 12 | - [ ] [Tests](https://github.com/web-platform-tests/wpt) are written and can be reviewed and commented upon at: 13 | * … 14 | - [ ] [Implementation bugs](https://github.com/whatwg/meta/blob/main/MAINTAINERS.md#handling-pull-requests) are filed: 15 | * Chromium: … 16 | * Gecko: … 17 | * WebKit: … 18 | - [ ] [MDN issue](https://github.com/whatwg/meta/blob/main/MAINTAINERS.md#handling-pull-requests) is filed: … 19 | - [ ] The top of this comment includes a [clear commit message](https://github.com/whatwg/meta/blob/main/COMMITTING.md) to use. 20 | 21 | (See [WHATWG Working Mode: Changes](https://whatwg.org/working-mode#changes) for more details.) 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This repository hosts the [Notifications API Standard](https://notifications.spec.whatwg.org/). 2 | 3 | ## Code of conduct 4 | 5 | We are committed to providing a friendly, safe, and welcoming environment for all. Please read and respect the [Code of Conduct](https://whatwg.org/code-of-conduct). 6 | 7 | ## Contribution opportunities 8 | 9 | Folks notice minor and larger issues with the Notifications API Standard all the time and we'd love your help fixing those. Pull requests for typographical and grammar errors are also most welcome. 10 | 11 | Issues labeled ["good first issue"](https://github.com/whatwg/notifications/labels/good%20first%20issue) are a good place to get a taste for editing the Notifications API Standard. Note that we don't assign issues and there's no reason to ask for availability either, just provide a pull request. 12 | 13 | If you are thinking of suggesting a new feature, read through the [FAQ](https://whatwg.org/faq) and [Working Mode](https://whatwg.org/working-mode) documents to get yourself familiarized with the process. 14 | 15 | We'd be happy to help you with all of this [on Chat](https://whatwg.org/chat). 16 | 17 | ## Pull requests 18 | 19 | In short, change `notifications.bs` and submit your patch, with a [good commit message](https://github.com/whatwg/meta/blob/main/COMMITTING.md). 20 | 21 | Please add your name to the Acknowledgments section in your first pull request, even for trivial fixes. The names are sorted lexicographically. 22 | 23 | To ensure your patch meets all the necessary requirements, please also see the [Contributor Guidelines](https://github.com/whatwg/meta/blob/main/CONTRIBUTING.md). Editors of the Notifications API Standard are expected to follow the [Maintainer Guidelines](https://github.com/whatwg/meta/blob/main/MAINTAINERS.md). 24 | 25 | ## Tests 26 | 27 | Tests are an essential part of the standardization process and will need to be created or adjusted as changes to the standard are made. Tests for the Notifications API Standard can be found in the `notifications/` directory of [`web-platform-tests/wpt`](https://github.com/web-platform-tests/wpt). 28 | 29 | A dashboard showing the tests running against browser engines can be seen at [wpt.fyi/results/notifications](https://wpt.fyi/results/notifications). 30 | 31 | ## Building "locally" 32 | 33 | For quick local iteration, run `make`; this will use a web service to build the standard, so that you don't have to install anything. See more in the [Contributor Guidelines](https://github.com/whatwg/meta/blob/main/CONTRIBUTING.md#building). 34 | 35 | ## Formatting 36 | 37 | Use a column width of 100 characters. 38 | 39 | Do not use newlines inside "inline" elements, even if that means exceeding the column width requirement. 40 | ```html 41 |
The
42 | remove(tokens…)
43 | method, when invoked, must run these steps:
44 | ```
45 | is okay and
46 | ```html
47 |
The remove(tokens…)
method, when
49 | invoked, must run these steps:
50 | ```
51 | is not.
52 |
53 | Using newlines between "inline" element tag names and their content is also forbidden. (This actually alters the content, by adding spaces.) That is
54 | ```html
55 | token
56 | ```
57 | is fine and
58 | ```html
59 | token
60 |
61 | ```
62 | is not.
63 |
64 | An `
` element inside it, unless it's a child of `
For each token in tokens, in given order, that is not in 71 | tokens, append token to tokens. 72 | ``` 73 | is not indented, but 74 | ```html 75 |
For each token in tokens, run these substeps: 78 | 79 |
If token is the empty string, throw a {{SyntaxError}} exception. 81 | ``` 82 | is. 83 | 84 | End tags may be included (if done consistently) and attributes may be quoted (using double quotes), though the prevalent theme is to omit end tags and not quote attributes (unless they contain a space). 85 | 86 | Place one newline between paragraphs (including list elements). Place three newlines before `
Do not place a newline above. 90 | 91 |
Place a newline above. 92 |
Place a newline above. 95 | 96 | 97 |
A request has an associated 107 | redirect mode,... 108 | ``` 109 | ```html 110 |
Let redirectMode be request's redirect mode. 111 | ``` 112 | -------------------------------------------------------------------------------- /review-drafts/2019-01.bs: -------------------------------------------------------------------------------- 1 |
2 | Group: WHATWG 3 | Date: 2019-01-23 4 | H1: Notifications API 5 | Shortname: notifications 6 | Text Macro: TWITTER notifyapi 7 | Abstract: This standard defines an API to display notifications to the end user, typically outside the top-level browsing context's viewport. It is designed to be compatible with existing notification systems, while remaining platform-independent. 8 | Translation: ja https://triple-underscore.github.io/notifications-ja.html 9 | Translation: zh-cn https://w3c-html-ig-zh.github.io/notifications/whatwg/ 10 |11 | 12 |
This specification depends on the Infra Standard. [[!INFRA]] 15 | 16 |
Some terms used in this specification are defined in the DOM, Fetch, HTML, IDL, Service Workers, 17 | URL, and Vibration API Standards. 18 | [[!DOM]] 19 | [[!FETCH]] 20 | [[!HTML]] 21 | [[!WEBIDL]] 22 | [[!SERVICE-WORKERS]] 23 | [[!URL]] 24 | [[!VIBRATION]] 25 | 26 | 27 |
A notification is an abstract 30 | representation of something that happened, such as the delivery of a message. 31 | 32 |
A notification can have an associated 33 | service worker registration. 34 | 35 |
A notification has an associated 36 | title which is a DOMString. 37 | 38 |
A notification has an associated 39 | body which is a DOMString. 40 | 41 |
A notification has an associated 42 | direction which is one of 43 | auto, ltr, and rtl. 44 | 45 |
A notification has an associated 46 | language which is a DOMString 47 | representing either a valid BCP 47 language tag or the empty string. 48 | 49 |
A notification has an associated 50 | tag which is a DOMString. 51 | 52 |
A notification has an associated 53 | data. 54 | 55 |
A notification has an associated timestamp which 56 | is a {{DOMTimeStamp}} representing the time, in milliseconds since 00:00:00 UTC on 1 January 1970, 57 | of the event for which the notification was created. 58 | 59 |
Timestamps can be used to indicate the time at which a notification 60 | is actual. For example, this could be in the past when a notification is used for 61 | a message that couldn't immediately be delivered because the device was offline, 62 | or in the future for a meeting that is about to start. 63 | 64 |
A notification has an associated 65 | origin. 66 | 67 |
A notification has an associated 68 | renotify preference flag which is initially 69 | unset. When set indicates that the end user should be alerted after the show steps have run 70 | with a new notification that has the same tag as an existing notification. 71 | 72 |
A notification has an associated 73 | silent preference flag which is initially 74 | unset. When set indicates that no sounds or vibrations should be made. 75 | 76 |
A notification has an associated 77 | require interaction preference flag 78 | which is initially unset. When set, indicates that on devices with a sufficiently large screen, the 79 | notification should remain readily available until the user activates or dismisses the notification. 80 | 81 |
A notification can have these associated graphics: an 82 | image URL, 83 | icon URL, and 84 | badge URL; and their corresponding 85 | image resource, icon resource, and 86 | badge resource. 87 | 88 |
An image resource is a picture shown as part of the 89 | content of the notification, and should be displayed with higher visual priority than the 90 | icon resource and badge resource, though it may be 91 | displayed in fewer circumstances. 92 | 93 |
An icon resource is an image that reinforces the 94 | notification (such as an icon, or a photo of the sender). 95 | 96 |
A badge resource is an icon representing the web 97 | application, or the category of the notification if the web application sends a wide variety 98 | of notifications. It may be used to represent the notification when there is 99 | not enough space to display the notification itself. It may also be displayed inside 100 | the notification, but then it should have less visual priority than the 101 | image resource and icon resource. 102 | 103 |
A notification can have a 104 | vibration pattern. 105 | 106 |
Developers are encouraged to not convey information through an 107 | image, icon, 108 | badge, or vibration pattern that 109 | is not otherwise accessible to the end user, especially since notification platforms that do not 110 | support these features might ignore them. 111 | 112 |
A notification has an associated list of 113 | zero or more actions. Each 114 | action has an associated 115 | title and name and 116 | can have an associated icon URL and 117 | icon resource. Users may activate actions, as alternatives to 118 | activating the notification itself. The user agent must determine the 119 | maximum number of actions supported, within the constraints of the 120 | notification platform. 121 | 122 |
Since display of actions is platform-dependent, developers are 123 | encouraged to make sure that any action a user can invoke from a notification is 124 | also available within the web application. 125 | 126 |
Some platforms might modify an icon resource to better 127 | match the platform's visual style before displaying it to the user, for example by rounding the 128 | corners or painting it in a specific color. Developers are encouraged to use an icon that handles 129 | such cases gracefully and does not lose important information through, e.g., loss of color or 130 | clipped corners. 131 | 132 |
A non-persistent notification is a 133 | notification without an associated 134 | service worker registration. 135 | 136 |
A persistent notification is a 137 | notification with an associated 138 | service worker registration. 139 | 140 | 141 | 142 |
To create a notification, given a 145 | title, options, and optionally a serviceWorkerRegistration, run 146 | these steps: 147 | 148 |
Let notification be a new 150 | notification. 151 | 152 |
If a serviceWorkerRegistration was provided, set 153 | notification's service worker registration to 154 | serviceWorkerRegistration. 155 | 156 |
If a serviceWorkerRegistration was not provided and
157 | options's actions
is not empty, throw a
158 | TypeError
exception.
159 |
160 |
Actions are only currently supported for 161 | persistent notifications. 162 | 163 |
If options's silent
is true and options's
164 | vibrate
is present, throw a TypeError
165 | exception.
166 |
167 |
If options's renotify
is true and
168 | options's tag
is the empty string, throw a
169 | TypeError
exception.
170 |
171 |
Set notification's data to
172 | StructuredSerializeForStorage(options's data
). Rethrow
173 | any exceptions.
174 |
175 |
Set notification's title to title. 176 | 177 |
Set notification's
178 | direction to options's
179 | dir
.
180 |
181 |
Set notification's language to
182 | options's lang
.
183 |
184 |
Set notification's origin to the 185 | entry settings object's origin. 186 | 187 |
Set notification's body to options's
188 | body
.
189 |
190 |
Set notification's tag to options's
191 | tag
.
192 |
193 |
Let baseURL be the API base URL specified by the 194 | entry settings object. Or incumbent? 195 | 196 |
If options's image
is present,
197 | parse it using baseURL, and if that does not
198 | return failure, set notification's image URL to the return
199 | value. (Otherwise image URL is not set.)
200 |
201 |
If options's icon
is present,
202 | parse it using baseURL, and if that does not
203 | return failure, set notification's icon URL to the return
204 | value. (Otherwise icon URL is not set.)
205 |
206 |
If options's badge
is present,
207 | parse it using baseURL, and if that does not
208 | return failure, set notification's badge URL to the return
209 | value. (Otherwise badge URL is not set.)
210 |
211 |
If options's vibrate
is present,
212 | validate and normalize it and set notification's
213 | vibration pattern to the return value. (Otherwise
214 | vibration pattern is not set.)
215 |
216 |
If options's timestamp
is present, set
217 | notification's timestamp to the value. Otherwise, set
218 | notification's timestamp to the number of milliseconds that
219 | passed between 00:00:00 UTC on 1 January 1970 and the time at which the
220 | Notification
constructor was called.
221 |
222 |
If options's renotify
is true, set
223 | notification's renotify preference flag.
224 |
225 |
If options's silent
is true, set
226 | notification's silent preference flag.
227 |
228 |
If options's requireInteraction
is true, set
229 | notification's require interaction preference flag.
230 |
231 |
Set notification's list of actions to an empty list,
232 | then for each entry in options's actions
,
233 | up to the maximum number of actions supported (skip any excess
234 | entries), perform the following steps:
235 |
236 |
Let action be a new action. 238 | 239 |
Set action's name to the entry's
240 | action
.
241 |
242 |
Set action's title to the
243 | entry's title
.
244 |
245 |
If entry's icon
is present,
246 | parse it using baseURL, and if that does
247 | not return failure, set action's icon URL to the
248 | return value. (Otherwise icon URL is not set.)
249 |
250 |
Append action to notification's list of 251 | actions. 252 |
Return notification. 255 |
The user agent must keep a list of notifications, which is a list of zero 261 | or more notifications. 262 | 263 |
User agents should run the close steps for a 264 | non-persistent notification a couple of seconds after they have been 265 | created. 266 | 267 |
User agents should not display non-persistent notification in a 268 | platform's "notification center" (if available). 269 | 270 |
User agents should persist persistent notifications until they are 271 | removed from the list of notifications. 272 | 273 |
A persistent notification could have the 274 | {{Notification/close()}} method invoked of one of its {{Notification}} objects. 275 | 276 |
User agents should display persistent notifications in a platform's 277 | "notification center" (if available). 278 | 279 | 280 |
Notifications can only be displayed if the 283 | user (or user agent on behalf of the user) has granted permission. 284 | The permission to show notifications 285 | for a given origin is one of three strings: 286 | 287 |
default
"
289 | This is equivalent to "denied
", but the user has made no
290 | explicit choice thus far.
291 |
292 |
denied
"
293 | This means the user does not want 294 | notifications. 295 | 296 |
granted
"
297 | This means notifications can be 298 | displayed. 299 |
There is no equivalent to "default
"
302 | meaning "granted
". In that case
303 | "granted
" is simply returned as there would be no reason
304 | for the application to ask for permission.
305 |
306 |
307 |
This section is written in terms equivalent to those used in the Rendering 310 | section of HTML. [[!HTML]] 311 | 312 | 314 | 315 |
User agents are expected to honor the Unicode semantics of the text of a
316 | notification's title, body, and the
317 | title of each of its actions. Each is expected
318 | to be treated as an independent set of one or more bidirectional algorithm
319 | paragraphs when displayed, as defined by the bidirectional algorithm's rules P1,
320 | P2, and P3, including, for instance, supporting the paragraph-breaking behavior
321 | of U+000A LINE FEED (LF) characters. For each paragraph of the
322 | title, body and the
323 | title of each of the actions, the
324 | notification's
325 | direction provides the higher-level override of
326 | rules P2 and P3 if it has a value other than "auto
". [[!BIDI]]
327 |
328 |
The notification's direction also determines the relative order in 329 | which the notification's actions should be displayed to the user, if 330 | the notification platform displays them side by side. 331 | 332 | 333 |
The notification's language specifies the primary language for the 339 | notification's title, body and the 340 | title of each of its actions. Its value is a string. 341 | The empty string indicates that the primary language is unknown. Any other string must be 342 | interpreted as a language tag. Validity or well-formedness are not enforced. [[!LANG]] 343 | 344 |
Developers are encouraged to only use valid language tags. 345 | 346 | 347 |
The fetch steps for a given 350 | notification notification are: 351 | 352 |
If the notification platform supports images, fetch 356 | notification's image URL, if image URL is set. 357 | 358 |
The intent is to fetch this resource similar to an
359 | <img>
,
360 | but this needs abstracting.
361 |
362 |
Then, in parallel: 363 | 364 |
Wait for the response. 366 | 367 |
If the response's internal response's type is
368 | "default
", then attempt to decode the resource as image.
369 |
370 |
If the image format is supported, set notification's 371 | image resource to the decoded resource. (Otherwise 372 | notification has no image resource.) 373 |
If the notification platform supports icons, fetch 377 | notification's icon URL, if icon URL 378 | is set. 379 | 380 |
The intent is to fetch this resource similar to an
381 | <img>
,
382 | but this needs abstracting.
383 |
384 |
Then, in parallel: 385 | 386 |
Wait for the response. 388 | 389 |
If the response's internal response's type is
390 | "default
", then attempt to decode the resource as image.
391 |
392 |
If the image format is supported, set notification's 393 | icon resource to the decoded resource. (Otherwise 394 | notification has no icon resource.) 395 |
If the notification platform supports badges, fetch notification's 400 | badge URL, if badge URL is set. 401 | 402 |
The intent is to fetch this resource similar to an
403 | <img>
,
404 | but this needs abstracting.
405 |
406 |
Then, in parallel: 407 | 408 |
Wait for the response. 410 | 411 |
If the response's internal response's type is
412 | "default
", then attempt to decode the resource as image.
413 |
414 |
If the image format is supported, set notification's 415 | badge resource to the decoded resource. (Otherwise 416 | notification has no badge resource.) 417 |
If the notification platform supports actions and action icons, then for each action 422 | in notification's list of actions fetch action's 423 | icon URL, if icon URL is set. 424 | 425 |
The intent is to fetch this resource similar to an
426 | <img>
,
427 | but this needs abstracting.
428 |
429 |
Then, in parallel: 430 | 431 |
Wait for the response. 433 | 434 |
If the response's internal response's type is
435 | "default
", then attempt to decode the resource as image.
436 |
437 |
If the image format is supported, set action's 438 | icon resource to the decoded resource. (Otherwise 439 | action has no icon resource.) 440 |
The show steps for a given 448 | notification notification are: 449 | 450 | 451 |
Wait for any fetches to complete and notification's 453 | image resource icon resource, and 454 | badge resource to be set (if any), as well as the 455 | icon resources for the notification's actions 456 | (if any). 457 | 458 |
Let shown be false. 459 | 460 |
Let oldNotification be the notification in the 461 | list of notifications whose tag is not the empty string and is 462 | notification's tag, and whose origin is 463 | same origin with notification's origin, if any, and null 464 | otherwise. 465 | 466 |
If oldNotification is non-null, then: 468 | 469 |
Handle close events with oldNotification. 471 | 472 |
If the notification platform supports replacement, then: 474 | 475 |
Replace oldNotification with notification, in the 477 | list of notifications. 478 | 479 |
Set shown to true. 480 |
Notification platforms are strongly encouraged to support native 483 | replacement as it leads to a better user experience. 484 | 485 |
Otherwise, remove oldNotification from the 486 | list of notifications. 487 |
If shown is false, then: 491 | 492 |
Append notification to the list of notifications. 494 | 495 |
Display notification on the device (e.g., by calling the appropriate 496 | notification platform API). 497 |
If shown is false or oldNotification is non-null and 500 | notification's renotify preference flag has been set, then run 501 | the alert steps for notification. 502 | 503 |
If notification is a non-persistent notification, then queue a task
504 | to fire an event named show
on the {{Notification}} object representing
505 | notification.
506 |
When a notification notification, 512 | or one of its actions, is activated by the user, assuming the underlying 513 | notification platform supports activation, the user agent must (unless otherwise 514 | specified) run these steps: 515 | 516 |
If notification is a persistent notification, then: 519 | 520 |
Let action be the empty string. 522 | 523 |
If one of notification's actions was activated by the 524 | user, then set action to that action's name. 525 | 526 |
notificationclick
" given
527 | notification and action.
528 | Otherwise, queue a task to run these steps: 532 | 533 |
Let intoFocus be the result of firing an event named
536 | click
on the {{Notification}} object representing notification, with its
537 | {{Event/cancelable}} attribute initialized to true.
538 |
539 |
User agents are encouraged to make {{Window/focus()}} work from within the event
540 | listener for the event named click
.
541 |
542 |
If intoFocus is true, then the user agent should bring the 543 | notification's related browsing context's viewport into focus. 544 |
Throughout the web platform "activate" is intentionally misnamed as "click". 548 | 549 | 550 |
When a notification is closed, either by the 553 | underlying notification platform or by the user, the close steps for it 554 | must be run. 555 | 556 |
The close steps for a given notification are: 557 | 558 |
If the list of notifications does not contain 560 | notification, then abort these steps. 561 | 562 |
Handle close events with notification. 563 | 564 |
Remove notification from the list of notifications. 565 |
To handle close events given a notification, run these steps: 568 | 569 |
If notification is a persistent notification and notification
571 | was closed by the user, then fire a service worker notification event named
572 | "notificationclose
" given notification.
573 |
574 |
If notification is a non-persistent notification, then queue a task
575 | to fire an event named close
on the {{Notification}} object representing
576 | notification.
577 |
The alert steps for alerting the user about a given 583 | notification are: 584 | 585 |
Perform vibration using notification's 587 | vibration pattern, if any. 588 |
594 | [Constructor(DOMString title, optional NotificationOptions options), 595 | Exposed=(Window,Worker)] 596 | interface Notification : EventTarget { 597 | static readonly attribute NotificationPermission permission; 598 | [Exposed=Window] static Promise<NotificationPermission> requestPermission(optional NotificationPermissionCallback deprecatedCallback); 599 | 600 | static readonly attribute unsigned long maxActions; 601 | 602 | attribute EventHandler onclick; 603 | attribute EventHandler onshow; 604 | attribute EventHandler onerror; 605 | attribute EventHandler onclose; 606 | 607 | readonly attribute DOMString title; 608 | readonly attribute NotificationDirection dir; 609 | readonly attribute DOMString lang; 610 | readonly attribute DOMString body; 611 | readonly attribute DOMString tag; 612 | readonly attribute USVString image; 613 | readonly attribute USVString icon; 614 | readonly attribute USVString badge; 615 | [SameObject] readonly attribute FrozenArray<unsigned long> vibrate; 616 | readonly attribute DOMTimeStamp timestamp; 617 | readonly attribute boolean renotify; 618 | readonly attribute boolean silent; 619 | readonly attribute boolean requireInteraction; 620 | [SameObject] readonly attribute any data; 621 | [SameObject] readonly attribute FrozenArray<NotificationAction> actions; 622 | 623 | void close(); 624 | }; 625 | 626 | dictionary NotificationOptions { 627 | NotificationDirection dir = "auto"; 628 | DOMString lang = ""; 629 | DOMString body = ""; 630 | DOMString tag = ""; 631 | USVString image; 632 | USVString icon; 633 | USVString badge; 634 | VibratePattern vibrate; 635 | DOMTimeStamp timestamp; 636 | boolean renotify = false; 637 | boolean silent = false; 638 | boolean requireInteraction = false; 639 | any data = null; 640 | sequence<NotificationAction> actions = []; 641 | }; 642 | 643 | enum NotificationPermission { 644 | "default", 645 | "denied", 646 | "granted" 647 | }; 648 | 649 | enum NotificationDirection { 650 | "auto", 651 | "ltr", 652 | "rtl" 653 | }; 654 | 655 | dictionary NotificationAction { 656 | required DOMString action; 657 | required DOMString title; 658 | USVString icon; 659 | }; 660 | 661 | callback NotificationPermissionCallback = void (NotificationPermission permission); 662 |663 | 664 |
A non-persistent notification is represented by one {{Notification}} 665 | object and can be created through {{Notification}}'s 666 | constructor. 667 | 668 |
A persistent notification is represented by zero or more 669 | {{Notification}} objects and can be created through the 670 | {{ServiceWorkerRegistration/showNotification()}} method. 671 | 672 | 673 |
A {{Notification}} object must not be garbage collected while the list of notifications
676 | contains its corresponding notification and it has an
677 | event listener whose type is click
, show
,
678 | close
, or error
.
679 |
680 |
681 |
The Notification(title, options)
684 | constructor, when invoked, must run these steps:
685 |
686 |
If the current global object is a {{ServiceWorkerGlobalScope}} object, then
688 | throw a TypeError
exception.
689 |
690 |
Let notification be the result of creating a notification given 691 | title and options. Rethrow any exceptions. 692 | 693 |
Let n be a new {{Notification}} object associated with 694 | notification. 695 | 696 |
Run these steps in parallel: 697 | 698 |
If permission for notification's origin is not
700 | "granted
", then queue a task to fire an event named
701 | error
on n, and abort these steps.
702 |
703 |
Run the fetch steps for notification. 704 | 705 |
Run the show steps for notification. 706 |
Return n. 709 |
The static permission
715 | attribute's getter must return permission for the
716 | entry settings object's origin.
717 |
718 |
If you edit standards please refrain from copying the above. Synchronous 719 | permissions are like synchronous IO, a bad idea. 720 | 721 |
The static
722 | requestPermission(deprecatedCallback)
723 | method, when invoked, must run these steps:
724 |
725 |
Let promise be a new promise. 727 | 728 |
Run these steps in parallel: 730 | 731 |
Let permission be permission for 733 | entry settings object's origin. 734 | 735 | 736 |
If permission is "default
", ask the user whether showing
737 | notifications for the entry settings object's
738 | origin is acceptable. If it is, set
739 | permission to "granted
", and "denied
" otherwise.
740 |
741 |
Queue a task to run these steps: 743 | 744 |
Set permission for the entry settings object's 746 | origin to permission. 747 | 748 |
If deprecatedCallback is given, invoke 749 | deprecatedCallback with permission as single argument. If this 750 | throws an exception, report the exception. 751 | 752 |
Fullfil promise with permission. 753 |
Return promise. 757 |
Notifications are the one instance thus far where asking the 760 | user upfront makes sense. Specifications for other APIs should not use this 761 | pattern and instead employ one of the 762 | 763 | many more suitable alternatives. 764 | 765 |
The static maxActions
766 | attribute's getter must return the maximum number of actions supported.
767 |
768 |
The following are the event handlers (and their corresponding 771 | event handler event types) that must be supported as attributes by the 772 | {{Notification}} object. 773 | 774 |
event handler 778 | | event handler event type 779 | |
---|---|
onclick
782 | | click
783 | |
onshow
785 | | show
786 | |
onerror
788 | | error
789 | |
onclose
791 | | close
792 | |
The close()
method, when
795 | invoked, must run the close steps for the
796 | notification.
797 |
798 |
The title
attribute's getter must return the
799 | notification's title.
800 |
801 |
The dir
attribute's getter must return the
802 | notification's direction.
803 |
804 |
The lang
attribute's getter must return the
805 | notification's language.
806 |
807 |
The body
attribute's getter must return the
808 | notification's body.
809 |
810 |
The tag
attribute's getter must return the
811 | notification's tag.
812 |
813 |
The image
attribute's getter must return
814 | the notification's image URL, serialized,
815 | and the empty string if there is no notification's image URL
816 | otherwise.
817 |
818 |
The icon
attribute's getter must return the
819 | notification's icon URL, serialized, and
820 | the empty string if there is no notification's icon URL otherwise.
821 |
822 |
The badge
attribute's getter must return the
823 | notification's badge URL, serialized, and
824 | the empty string if there is no notification's badge URL otherwise.
825 |
826 |
The vibrate
attribute's getter must return the
827 | notification's vibration pattern, if any, and the empty list
828 | otherwise.
829 |
830 |
The timestamp
attribute's getter must return
831 | the notification's timestamp.
832 |
833 |
The renotify
attribute's getter must return
834 | the notification's renotify preference flag.
835 |
836 |
The silent
attribute's getter must return the
837 | notification's silent preference flag.
838 |
839 |
The requireInteraction
attribute's getter must
840 | return the notification's require interaction preference flag.
841 |
842 |
The data
attribute's getter must return
843 | StructuredDeserialize(notification's data,
844 | context object's relevant Realm). If this throws an exception, then return null.
845 |
846 |
847 |
The actions
attribute's getter must return the
848 | result of the following steps:
849 |
850 |
Let frozenActions be an empty list of type {{NotificationAction}}. 852 | 853 |
For each entry in the notification's list of 854 | actions, perform the following steps: 855 | 856 |
Let action be a new {{NotificationAction}}. 858 | 859 |
Set action's {{NotificationAction/action}} to 860 | entry's name. 861 | 862 |
Set action's {{NotificationAction/title}} to 863 | entry's title. 864 | 865 |
Set action's {{NotificationAction/icon}} to 866 | entry's icon URL. 867 | 868 | 873 |
Call Object.freeze on action, to 874 | prevent accidental mutation by scripts. 875 | 876 |
Append action to frozenActions. 877 |
Create a frozen array from frozenActions. 880 |
Non-persistent {{Notification}} 887 | objects dispatch events during their lifecycle, which developers can use to 888 | generate desired behaviors. 889 | 890 |
The click
event dispatches when the user activates a
891 | notification.
892 |
893 |
894 | var not = new Notification("Gebrünn Gebrünn by Paul Kalkbrenner", { icon: "newsong.svg", tag: "song" }); 895 | not.onclick = function() { displaySong(this); };896 | 897 | 898 |
Persistent notifications fire
901 | notificationclick
events on the {{ServiceWorkerGlobalScope}}.
902 |
903 |
Here a service worker shows a notification with a single "Archive" 904 | action, allowing users to perform this common task from the 905 | notification without having to open the website (for example the notification 906 | platform might show a button on the notification). The user can also activate 907 | the main body of the notification to open their inbox. 908 | 909 |
910 | self.registration.showNotification("New mail from Alice", { 911 | actions: [{action: 'archive', title: "Archive"}] 912 | }); 913 | 914 | self.addEventListener('notificationclick', function(event) { 915 | event.notification.close(); 916 | if (event.action === 'archive') { 917 | silentlyArchiveEmail(); 918 | } else { 919 | clients.openWindow("/inbox"); 920 | } 921 | }, false);922 | 923 | 924 |
tag
member for multiple instancesWeb applications frequently operate concurrently in multiple instances, such
927 | as when a user opens a mail application in multiple browser tabs. Since the
928 | desktop is a shared resource, the notifications API provides a way for these
929 | instances to easily coordinate, by using the tag
member.
930 |
931 |
Notifications which represent the same conceptual event can be tagged in the 932 | same way, and when both are shown, the user will only receive one notification. 933 | 934 |
935 | Instance 1 | Instance 2 936 | | 937 | // Instance notices there is new mail. | 938 | new Notification("New mail from John Doe", | 939 | { tag: 'message1' }); | 940 | | 941 | | // Slightly later, this instance notices 942 | | // there is new mail. 943 | | new Notification("New mail from John Doe", 944 | | { tag: 'message1' });945 | 946 |
The result of this situation, if the user agent follows the algorithms here, is a 947 | single notification "New mail from John Doe". 948 | 949 | 950 |
tag
member for a single instanceThe tag
member can also be used by a single instance of an
953 | application to keep its notifications as current as possible as state changes.
954 |
955 |
For example, if Alice is using a chat application with Bob, and Bob sends 956 | multiple messages while Alice is idle, the application may prefer that Alice not 957 | see a desktop notification for each message. 958 | 959 |
960 | // Bob says "Hi" 961 | new Notification("Bob: Hi", { tag: 'chat_Bob' }); 962 | 963 | // Bob says "Are you free this afternoon?" 964 | new Notification("Bob: Hi / Are you free this afternoon?", { tag: 'chat_Bob' });965 | 966 |
The result of this situation is a single notification; the second one 967 | replaces the first having the same tag. In a platform that queues notifications 968 | (first-in-first-out), using the tag allows the notification to also maintain its 969 | position in the queue. Platforms where the newest notifications are shown first, 970 | a similar result could be achieved using the {{Notification/close()}} method. 971 | 972 | 973 |
976 | dictionary GetNotificationOptions { 977 | DOMString tag = ""; 978 | }; 979 | 980 | partial interface ServiceWorkerRegistration { 981 | Promise<void> showNotification(DOMString title, optional NotificationOptions options); 982 | Promise<sequence<Notification>> getNotifications(optional GetNotificationOptions filter); 983 | }; 984 | 985 | [Constructor(DOMString type, NotificationEventInit eventInitDict), 986 | Exposed=ServiceWorker] 987 | interface NotificationEvent : ExtendableEvent { 988 | readonly attribute Notification notification; 989 | readonly attribute DOMString action; 990 | }; 991 | 992 | dictionary NotificationEventInit : ExtendableEventInit { 993 | required Notification notification; 994 | DOMString action = ""; 995 | }; 996 | 997 | partial interface ServiceWorkerGlobalScope { 998 | attribute EventHandler onnotificationclick; 999 | attribute EventHandler onnotificationclose; 1000 | }; 1001 |1002 | 1003 |
The
1004 | showNotification(title, options)
1005 | method, when invoked, must run these steps:
1006 |
1007 |
Let promise be a new promise. 1009 | 1010 |
If the context object's active worker is
1011 | null, then reject promise with a TypeError
exception and return
1012 | promise.
1013 |
1014 |
Let serviceWorkerRegistration be the context object. 1015 | 1016 |
Let notification be the result of creating a notification given 1017 | title, options, and serviceWorkerRegistration. If this threw an 1018 | exception, reject promise with that exception and return promise. 1019 | 1020 |
Run these steps in parallel: 1021 | 1022 |
If permission for notification's origin is not
1024 | "granted
", then reject promise with a TypeError
exception,
1025 | and abort these steps.
1026 |
1027 |
Run the fetch steps for notification. 1028 | 1029 |
Run the show steps for notification. 1030 | 1031 |
Resolve promise with undefined. 1032 |
Return promise. 1035 |
The
1038 | getNotifications(filter)
1039 | method, when invoked, must run these steps:
1040 |
1041 |
Let promise be a new promise. 1043 | 1044 |
Run these steps in parallel: 1045 | 1046 |
Let tag be filter's tag
.
1048 |
1049 |
Let notifications be a list of all notifications in the 1050 | list of notifications whose origin is the 1051 | entry settings object's origin, whose 1052 | service worker registration is the context object, and whose 1053 | tag, if tag is not the empty string, is tag. 1054 | 1055 |
Let objects be an empty JavaScript array. 1056 | 1057 |
For each notification in 1058 | notifications, in creation order, create a new {{Notification}} 1059 | object representing notification and push 1060 | that object to objects. 1061 | 1062 |
Resolve promise with objects. 1063 |
Return promise. 1066 |
This method returns zero or more new {{Notification}} objects which might represent 1069 | the same underlying notification of {{Notification}} objects already in existence. 1070 | 1071 |
To fire a service worker notification event named name given 1074 | notification (a notification), and an optional action (a DOMString, 1075 | defaulting to the empty string), Fire Functional Event name using 1076 | {{NotificationEvent}} on notification's 1077 | service worker registration with the following properties: 1078 | 1079 |
The {{NotificationEvent/notification}} attribute's getter must return the 1087 | value it was initialized to. 1088 | 1089 |
The {{NotificationEvent/action}} attribute's getter must return the value it 1090 | was initialized to. 1091 | 1092 |
The following is the event handler (and its corresponding 1093 | event handler event type) that must be supported as attribute by the 1094 | {{ServiceWorkerGlobalScope}} object: 1095 | 1096 |
event handler 1100 | | event handler event type 1101 | |
---|---|
onnotificationclick
1104 | | notificationclick
1105 | |
onnotificationclose
1107 | | notificationclose
1108 | |
Thanks to 1114 | Addison Phillips, 1115 | Aharon (Vladimir) Lanin, 1116 | Alex Russell, 1117 | Anssi Kostiainen, 1118 | Arkadiusz Michalski, 1119 | Boris Zbarsky, 1120 | David Håsäther, 1121 | Doug Turner, 1122 | Drew Wilson, 1123 | Ehsan Akhgari, 1124 | Frederick Hirsch, 1125 | Ian Hickson, 1126 | Jake Archibald, 1127 | James Graham, 1128 | John Mellor, 1129 | Jon Lee, 1130 | Jonas Sicking, 1131 | Michael Cooper, 1132 | Michael Henretty, 1133 | Michael™ Smith, 1134 | Michael van Ouwerkerk, 1135 | Nicolás Satragno, 1136 | Olli Pettay, 1137 | Peter Beverloo, 1138 | Philip Jägenstedt, 1139 | Reuben Morais, 1140 | Rich Tibbett, 1141 | Robert Bindar, 1142 | 박상현 (Sanghyun Park), 1143 | Simon Pieters, 1144 | Theresa O'Connor, 1145 | timeless, and 1146 | triple-underscore 1147 | for being awesome. 1148 | 1149 |
This standard is written by 1150 | Anne van Kesteren 1151 | (Mozilla, 1152 | annevk@annevk.nl). An earlier iteration was written 1153 | by John Gregg (Google, 1154 | johnnyg@google.com). 1155 | 1156 |
1157 | urlPrefix: https://html.spec.whatwg.org/multipage/ 1158 | urlPrefix: webappapis.html; type: dfn 1159 | text: entry settings object 1160 | urlPrefix: https://w3c.github.io/vibration/ 1161 | urlPrefix: #dfn-; type: dfn 1162 | text: perform vibration 1163 | text: validate and normalize 1164 | urlPrefix: #idl-def-; type: interface 1165 | text: VibratePattern; url: vibratepattern 1166 | urlPrefix: https://tc39.github.io/ecma262/#sec-object.; type: dfn 1167 | text: freeze 1168 |1169 | 1170 |
1171 | { 1172 | "LANG": { 1173 | "aliasOf" : "BCP47" 1174 | } 1175 | } 1176 |1177 | -------------------------------------------------------------------------------- /review-drafts/2020-01.bs: -------------------------------------------------------------------------------- 1 |
2 | Group: WHATWG 3 | Date: 2020-01-29 4 | H1: Notifications API 5 | Shortname: notifications 6 | Text Macro: TWITTER notifyapi 7 | Abstract: This standard defines an API to display notifications to the end user, typically outside the top-level browsing context's viewport. It is designed to be compatible with existing notification systems, while remaining platform-independent. 8 | Translation: ja https://triple-underscore.github.io/notifications-ja.html 9 | Translation: zh-cn https://w3c-html-ig-zh.github.io/notifications/whatwg/ 10 |11 | 12 |
This specification depends on the Infra Standard. [[!INFRA]] 15 | 16 |
Some terms used in this specification are defined in the DOM, Fetch, HTML, IDL, Service Workers, 17 | URL, and Vibration API Standards. 18 | [[!DOM]] 19 | [[!FETCH]] 20 | [[!HTML]] 21 | [[!WEBIDL]] 22 | [[!SERVICE-WORKERS]] 23 | [[!URL]] 24 | [[!VIBRATION]] 25 | 26 | 27 |
A notification is an abstract 30 | representation of something that happened, such as the delivery of a message. 31 | 32 |
A notification can have an associated 33 | service worker registration. 34 | 35 |
A notification has an associated 36 | title which is a DOMString. 37 | 38 |
A notification has an associated 39 | body which is a DOMString. 40 | 41 |
A notification has an associated 42 | direction which is one of 43 | auto, ltr, and rtl. 44 | 45 |
A notification has an associated 46 | language which is a DOMString 47 | representing either a valid BCP 47 language tag or the empty string. 48 | 49 |
A notification has an associated 50 | tag which is a DOMString. 51 | 52 |
A notification has an associated 53 | data. 54 | 55 |
A notification has an associated timestamp which 56 | is a {{DOMTimeStamp}} representing the time, in milliseconds since 00:00:00 UTC on 1 January 1970, 57 | of the event for which the notification was created. 58 | 59 |
Timestamps can be used to indicate the time at which a notification 60 | is actual. For example, this could be in the past when a notification is used for 61 | a message that couldn't immediately be delivered because the device was offline, 62 | or in the future for a meeting that is about to start. 63 | 64 |
A notification has an associated 65 | origin. 66 | 67 |
A notification has an associated 68 | renotify preference flag which is initially 69 | unset. When set indicates that the end user should be alerted after the show steps have run 70 | with a new notification that has the same tag as an existing notification. 71 | 72 |
A notification has an associated 73 | silent preference flag which is initially 74 | unset. When set indicates that no sounds or vibrations should be made. 75 | 76 |
A notification has an associated 77 | require interaction preference flag 78 | which is initially unset. When set, indicates that on devices with a sufficiently large screen, the 79 | notification should remain readily available until the user activates or dismisses the notification. 80 | 81 |
A notification can have these associated graphics: an 82 | image URL, 83 | icon URL, and 84 | badge URL; and their corresponding 85 | image resource, icon resource, and 86 | badge resource. 87 | 88 |
An image resource is a picture shown as part of the 89 | content of the notification, and should be displayed with higher visual priority than the 90 | icon resource and badge resource, though it may be 91 | displayed in fewer circumstances. 92 | 93 |
An icon resource is an image that reinforces the 94 | notification (such as an icon, or a photo of the sender). 95 | 96 |
A badge resource is an icon representing the web 97 | application, or the category of the notification if the web application sends a wide variety 98 | of notifications. It may be used to represent the notification when there is 99 | not enough space to display the notification itself. It may also be displayed inside 100 | the notification, but then it should have less visual priority than the 101 | image resource and icon resource. 102 | 103 |
A notification can have a 104 | vibration pattern. 105 | 106 |
Developers are encouraged to not convey information through an 107 | image, icon, 108 | badge, or vibration pattern that 109 | is not otherwise accessible to the end user, especially since notification platforms that do not 110 | support these features might ignore them. 111 | 112 |
A notification has an associated list of 113 | zero or more actions. Each 114 | action has an associated 115 | title and name and 116 | can have an associated icon URL and 117 | icon resource. Users may activate actions, as alternatives to 118 | activating the notification itself. The user agent must determine the 119 | maximum number of actions supported, within the constraints of the 120 | notification platform. 121 | 122 |
Since display of actions is platform-dependent, developers are 123 | encouraged to make sure that any action a user can invoke from a notification is 124 | also available within the web application. 125 | 126 |
Some platforms might modify an icon resource to better 127 | match the platform's visual style before displaying it to the user, for example by rounding the 128 | corners or painting it in a specific color. Developers are encouraged to use an icon that handles 129 | such cases gracefully and does not lose important information through, e.g., loss of color or 130 | clipped corners. 131 | 132 |
A non-persistent notification is a 133 | notification without an associated 134 | service worker registration. 135 | 136 |
A persistent notification is a 137 | notification with an associated 138 | service worker registration. 139 | 140 | 141 | 142 |
To create a notification, given a 145 | title, options, and optionally a serviceWorkerRegistration, run 146 | these steps: 147 | 148 |
Let notification be a new 150 | notification. 151 | 152 |
If a serviceWorkerRegistration was provided, set 153 | notification's service worker registration to 154 | serviceWorkerRegistration. 155 | 156 |
If a serviceWorkerRegistration was not provided and
157 | options's actions
is not empty, throw a
158 | TypeError
exception.
159 |
160 |
Actions are only currently supported for 161 | persistent notifications. 162 | 163 |
If options's silent
is true and options's
164 | vibrate
is present, throw a TypeError
165 | exception.
166 |
167 |
If options's renotify
is true and
168 | options's tag
is the empty string, throw a
169 | TypeError
exception.
170 |
171 |
Set notification's data to
172 | StructuredSerializeForStorage(options's data
). Rethrow
173 | any exceptions.
174 |
175 |
Set notification's title to title. 176 | 177 |
Set notification's
178 | direction to options's
179 | dir
.
180 |
181 |
Set notification's language to
182 | options's lang
.
183 |
184 |
Set notification's origin to the 185 | entry settings object's origin. 186 | 187 |
Set notification's body to options's
188 | body
.
189 |
190 |
Set notification's tag to options's
191 | tag
.
192 |
193 |
Let baseURL be the API base URL specified by the 194 | entry settings object. Or incumbent? 195 | 196 |
If options's image
is present,
197 | parse it using baseURL, and if that does not
198 | return failure, set notification's image URL to the return
199 | value. (Otherwise image URL is not set.)
200 |
201 |
If options's icon
is present,
202 | parse it using baseURL, and if that does not
203 | return failure, set notification's icon URL to the return
204 | value. (Otherwise icon URL is not set.)
205 |
206 |
If options's badge
is present,
207 | parse it using baseURL, and if that does not
208 | return failure, set notification's badge URL to the return
209 | value. (Otherwise badge URL is not set.)
210 |
211 |
If options's vibrate
is present,
212 | validate and normalize it and set notification's
213 | vibration pattern to the return value. (Otherwise
214 | vibration pattern is not set.)
215 |
216 |
If options's timestamp
is present, set
217 | notification's timestamp to the value. Otherwise, set
218 | notification's timestamp to the number of milliseconds that
219 | passed between 00:00:00 UTC on 1 January 1970 and the time at which the
220 | Notification
constructor was called.
221 |
222 |
If options's renotify
is true, set
223 | notification's renotify preference flag.
224 |
225 |
If options's silent
is true, set
226 | notification's silent preference flag.
227 |
228 |
If options's requireInteraction
is true, set
229 | notification's require interaction preference flag.
230 |
231 |
Set notification's list of actions to an empty list,
232 | then for each entry in options's actions
,
233 | up to the maximum number of actions supported (skip any excess
234 | entries), perform the following steps:
235 |
236 |
Let action be a new action. 238 | 239 |
Set action's name to the entry's
240 | action
.
241 |
242 |
Set action's title to the
243 | entry's title
.
244 |
245 |
If entry's icon
is present,
246 | parse it using baseURL, and if that does
247 | not return failure, set action's icon URL to the
248 | return value. (Otherwise icon URL is not set.)
249 |
250 |
Append action to notification's list of 251 | actions. 252 |
Return notification. 255 |
The user agent must keep a list of notifications, which is a list of zero 261 | or more notifications. 262 | 263 |
User agents should run the close steps for a 264 | non-persistent notification a couple of seconds after they have been 265 | created. 266 | 267 |
User agents should not display non-persistent notification in a 268 | platform's "notification center" (if available). 269 | 270 |
User agents should persist persistent notifications until they are 271 | removed from the list of notifications. 272 | 273 |
A persistent notification could have the 274 | {{Notification/close()}} method invoked of one of its {{Notification}} objects. 275 | 276 |
User agents should display persistent notifications in a platform's 277 | "notification center" (if available). 278 | 279 | 280 |
Notifications can only be displayed if the 283 | user (or user agent on behalf of the user) has granted permission. 284 | The permission to show notifications 285 | for a given origin is one of three strings: 286 | 287 |
default
"
289 | This is equivalent to "denied
", but the user has made no
290 | explicit choice thus far.
291 |
292 |
denied
"
293 | This means the user does not want 294 | notifications. 295 | 296 |
granted
"
297 | This means notifications can be 298 | displayed. 299 |
There is no equivalent to "default
"
302 | meaning "granted
". In that case
303 | "granted
" is simply returned as there would be no reason
304 | for the application to ask for permission.
305 |
306 |
307 |
This section is written in terms equivalent to those used in the Rendering 310 | section of HTML. [[!HTML]] 311 | 312 | 314 | 315 |
User agents are expected to honor the Unicode semantics of the text of a
316 | notification's title, body, and the
317 | title of each of its actions. Each is expected
318 | to be treated as an independent set of one or more bidirectional algorithm
319 | paragraphs when displayed, as defined by the bidirectional algorithm's rules P1,
320 | P2, and P3, including, for instance, supporting the paragraph-breaking behavior
321 | of U+000A LINE FEED (LF) characters. For each paragraph of the
322 | title, body and the
323 | title of each of the actions, the
324 | notification's
325 | direction provides the higher-level override of
326 | rules P2 and P3 if it has a value other than "auto
". [[!BIDI]]
327 |
328 |
The notification's direction also determines the relative order in 329 | which the notification's actions should be displayed to the user, if 330 | the notification platform displays them side by side. 331 | 332 | 333 |
The notification's language specifies the primary language for the 339 | notification's title, body and the 340 | title of each of its actions. Its value is a string. 341 | The empty string indicates that the primary language is unknown. Any other string must be 342 | interpreted as a language tag. Validity or well-formedness are not enforced. [[!LANG]] 343 | 344 |
Developers are encouraged to only use valid language tags. 345 | 346 | 347 |
The fetch steps for a given 350 | notification notification are: 351 | 352 |
If the notification platform supports images, fetch 356 | notification's image URL, if image URL is set. 357 | 358 |
The intent is to fetch this resource similar to an
359 | <img>
,
360 | but this needs abstracting.
361 |
362 |
Then, in parallel: 363 | 364 |
Wait for the response. 366 | 367 |
If the response's internal response's type is
368 | "default
", then attempt to decode the resource as image.
369 |
370 |
If the image format is supported, set notification's 371 | image resource to the decoded resource. (Otherwise 372 | notification has no image resource.) 373 |
If the notification platform supports icons, fetch 377 | notification's icon URL, if icon URL 378 | is set. 379 | 380 |
The intent is to fetch this resource similar to an
381 | <img>
,
382 | but this needs abstracting.
383 |
384 |
Then, in parallel: 385 | 386 |
Wait for the response. 388 | 389 |
If the response's internal response's type is
390 | "default
", then attempt to decode the resource as image.
391 |
392 |
If the image format is supported, set notification's 393 | icon resource to the decoded resource. (Otherwise 394 | notification has no icon resource.) 395 |
If the notification platform supports badges, fetch notification's 400 | badge URL, if badge URL is set. 401 | 402 |
The intent is to fetch this resource similar to an
403 | <img>
,
404 | but this needs abstracting.
405 |
406 |
Then, in parallel: 407 | 408 |
Wait for the response. 410 | 411 |
If the response's internal response's type is
412 | "default
", then attempt to decode the resource as image.
413 |
414 |
If the image format is supported, set notification's 415 | badge resource to the decoded resource. (Otherwise 416 | notification has no badge resource.) 417 |
If the notification platform supports actions and action icons, then for each action 422 | in notification's list of actions fetch action's 423 | icon URL, if icon URL is set. 424 | 425 |
The intent is to fetch this resource similar to an
426 | <img>
,
427 | but this needs abstracting.
428 |
429 |
Then, in parallel: 430 | 431 |
Wait for the response. 433 | 434 |
If the response's internal response's type is
435 | "default
", then attempt to decode the resource as image.
436 |
437 |
If the image format is supported, set action's 438 | icon resource to the decoded resource. (Otherwise 439 | action has no icon resource.) 440 |
The show steps for a given 448 | notification notification are: 449 | 450 | 451 |
Wait for any fetches to complete and notification's 453 | image resource icon resource, and 454 | badge resource to be set (if any), as well as the 455 | icon resources for the notification's actions 456 | (if any). 457 | 458 |
Let shown be false. 459 | 460 |
Let oldNotification be the notification in the 461 | list of notifications whose tag is not the empty string and is 462 | notification's tag, and whose origin is 463 | same origin with notification's origin, if any, and null 464 | otherwise. 465 | 466 |
If oldNotification is non-null, then: 468 | 469 |
Handle close events with oldNotification. 471 | 472 |
If the notification platform supports replacement, then: 474 | 475 |
Replace oldNotification with notification, in the 477 | list of notifications. 478 | 479 |
Set shown to true. 480 |
Notification platforms are strongly encouraged to support native 483 | replacement as it leads to a better user experience. 484 | 485 |
Otherwise, remove oldNotification from the 486 | list of notifications. 487 |
If shown is false, then: 491 | 492 |
Append notification to the list of notifications. 494 | 495 |
Display notification on the device (e.g., by calling the appropriate 496 | notification platform API). 497 |
If shown is false or oldNotification is non-null and 500 | notification's renotify preference flag has been set, then run 501 | the alert steps for notification. 502 | 503 |
If notification is a non-persistent notification, then queue a task
504 | to fire an event named show
on the {{Notification}} object representing
505 | notification.
506 |
When a notification notification, 512 | or one of its actions, is activated by the user, assuming the underlying 513 | notification platform supports activation, the user agent must (unless otherwise 514 | specified) run these steps: 515 | 516 |
If notification is a persistent notification, then: 519 | 520 |
Let action be the empty string. 522 | 523 |
If one of notification's actions was activated by the 524 | user, then set action to that action's name. 525 | 526 |
notificationclick
" given
527 | notification and action.
528 | Otherwise, queue a task to run these steps: 532 | 533 |
Let intoFocus be the result of firing an event named
536 | click
on the {{Notification}} object representing notification, with its
537 | {{Event/cancelable}} attribute initialized to true.
538 |
539 |
User agents are encouraged to make {{Window/focus()}} work from within the event
540 | listener for the event named click
.
541 |
542 |
If intoFocus is true, then the user agent should bring the 543 | notification's related browsing context's viewport into focus. 544 |
Throughout the web platform "activate" is intentionally misnamed as "click". 548 | 549 | 550 |
When a notification is closed, either by the 553 | underlying notification platform or by the user, the close steps for it 554 | must be run. 555 | 556 |
The close steps for a given notification are: 557 | 558 |
If the list of notifications does not contain 560 | notification, then abort these steps. 561 | 562 |
Handle close events with notification. 563 | 564 |
Remove notification from the list of notifications. 565 |
To handle close events given a notification, run these steps: 568 | 569 |
If notification is a persistent notification and notification
571 | was closed by the user, then fire a service worker notification event named
572 | "notificationclose
" given notification.
573 |
574 |
If notification is a non-persistent notification, then queue a task
575 | to fire an event named close
on the {{Notification}} object representing
576 | notification.
577 |
The alert steps for alerting the user about a given 583 | notification are: 584 | 585 |
Perform vibration using notification's 587 | vibration pattern, if any. 588 |
594 | [Exposed=(Window,Worker)] 595 | interface Notification : EventTarget { 596 | constructor(DOMString title, optional NotificationOptions options = {}); 597 | 598 | static readonly attribute NotificationPermission permission; 599 | [Exposed=Window] static Promise<NotificationPermission> requestPermission(optional NotificationPermissionCallback deprecatedCallback); 600 | 601 | static readonly attribute unsigned long maxActions; 602 | 603 | attribute EventHandler onclick; 604 | attribute EventHandler onshow; 605 | attribute EventHandler onerror; 606 | attribute EventHandler onclose; 607 | 608 | readonly attribute DOMString title; 609 | readonly attribute NotificationDirection dir; 610 | readonly attribute DOMString lang; 611 | readonly attribute DOMString body; 612 | readonly attribute DOMString tag; 613 | readonly attribute USVString image; 614 | readonly attribute USVString icon; 615 | readonly attribute USVString badge; 616 | [SameObject] readonly attribute FrozenArray<unsigned long> vibrate; 617 | readonly attribute DOMTimeStamp timestamp; 618 | readonly attribute boolean renotify; 619 | readonly attribute boolean silent; 620 | readonly attribute boolean requireInteraction; 621 | [SameObject] readonly attribute any data; 622 | [SameObject] readonly attribute FrozenArray<NotificationAction> actions; 623 | 624 | void close(); 625 | }; 626 | 627 | dictionary NotificationOptions { 628 | NotificationDirection dir = "auto"; 629 | DOMString lang = ""; 630 | DOMString body = ""; 631 | DOMString tag = ""; 632 | USVString image; 633 | USVString icon; 634 | USVString badge; 635 | VibratePattern vibrate; 636 | DOMTimeStamp timestamp; 637 | boolean renotify = false; 638 | boolean silent = false; 639 | boolean requireInteraction = false; 640 | any data = null; 641 | sequence<NotificationAction> actions = []; 642 | }; 643 | 644 | enum NotificationPermission { 645 | "default", 646 | "denied", 647 | "granted" 648 | }; 649 | 650 | enum NotificationDirection { 651 | "auto", 652 | "ltr", 653 | "rtl" 654 | }; 655 | 656 | dictionary NotificationAction { 657 | required DOMString action; 658 | required DOMString title; 659 | USVString icon; 660 | }; 661 | 662 | callback NotificationPermissionCallback = void (NotificationPermission permission); 663 |664 | 665 |
A non-persistent notification is represented by one {{Notification}} 666 | object and can be created through {{Notification}}'s 667 | constructor. 668 | 669 |
A persistent notification is represented by zero or more 670 | {{Notification}} objects and can be created through the 671 | {{ServiceWorkerRegistration/showNotification()}} method. 672 | 673 | 674 |
A {{Notification}} object must not be garbage collected while the list of notifications
677 | contains its corresponding notification and it has an
678 | event listener whose type is click
, show
,
679 | close
, or error
.
680 |
681 |
682 |
The Notification(title, options)
685 | constructor, when invoked, must run these steps:
686 |
687 |
If the current global object is a {{ServiceWorkerGlobalScope}} object, then
689 | throw a TypeError
exception.
690 |
691 |
Let notification be the result of creating a notification given 692 | title and options. Rethrow any exceptions. 693 | 694 |
Let n be a new {{Notification}} object associated with 695 | notification. 696 | 697 |
Run these steps in parallel: 698 | 699 |
If permission for notification's origin is not
701 | "granted
", then queue a task to fire an event named
702 | error
on n, and abort these steps.
703 |
704 |
Run the fetch steps for notification. 705 | 706 |
Run the show steps for notification. 707 |
Return n. 710 |
The static permission
716 | attribute's getter must return permission for the
717 | entry settings object's origin.
718 |
719 |
If you edit standards please refrain from copying the above. Synchronous 720 | permissions are like synchronous IO, a bad idea. 721 | 722 |
The static
723 | requestPermission(deprecatedCallback)
724 | method, when invoked, must run these steps:
725 |
726 |
Let promise be a new promise. 728 | 729 |
Run these steps in parallel: 731 | 732 |
Let permission be permission for 734 | entry settings object's origin. 735 | 736 | 737 |
If permission is "default
", ask the user whether showing
738 | notifications for the entry settings object's
739 | origin is acceptable. If it is, set
740 | permission to "granted
", and "denied
" otherwise.
741 |
742 |
Queue a task to run these steps: 744 | 745 |
Set permission for the entry settings object's 747 | origin to permission. 748 | 749 |
If deprecatedCallback is given, invoke 750 | deprecatedCallback with permission as single argument. If this 751 | throws an exception, report the exception. 752 | 753 |
Fullfil promise with permission. 754 |
Return promise. 758 |
Notifications are the one instance thus far where asking the 761 | user upfront makes sense. Specifications for other APIs should not use this 762 | pattern and instead employ one of the 763 | 764 | many more suitable alternatives. 765 | 766 |
The static maxActions
767 | attribute's getter must return the maximum number of actions supported.
768 |
769 |
The following are the event handlers (and their corresponding 772 | event handler event types) that must be supported as attributes by the 773 | {{Notification}} object. 774 | 775 |
event handler 779 | | event handler event type 780 | |
---|---|
onclick
783 | | click
784 | |
onshow
786 | | show
787 | |
onerror
789 | | error
790 | |
onclose
792 | | close
793 | |
The close()
method, when
796 | invoked, must run the close steps for the
797 | notification.
798 |
799 |
The title
attribute's getter must return the
800 | notification's title.
801 |
802 |
The dir
attribute's getter must return the
803 | notification's direction.
804 |
805 |
The lang
attribute's getter must return the
806 | notification's language.
807 |
808 |
The body
attribute's getter must return the
809 | notification's body.
810 |
811 |
The tag
attribute's getter must return the
812 | notification's tag.
813 |
814 |
The image
attribute's getter must return
815 | the notification's image URL, serialized,
816 | and the empty string if there is no notification's image URL
817 | otherwise.
818 |
819 |
The icon
attribute's getter must return the
820 | notification's icon URL, serialized, and
821 | the empty string if there is no notification's icon URL otherwise.
822 |
823 |
The badge
attribute's getter must return the
824 | notification's badge URL, serialized, and
825 | the empty string if there is no notification's badge URL otherwise.
826 |
827 |
The vibrate
attribute's getter must return the
828 | notification's vibration pattern, if any, and the empty list
829 | otherwise.
830 |
831 |
The timestamp
attribute's getter must return
832 | the notification's timestamp.
833 |
834 |
The renotify
attribute's getter must return
835 | the notification's renotify preference flag.
836 |
837 |
The silent
attribute's getter must return the
838 | notification's silent preference flag.
839 |
840 |
The requireInteraction
attribute's getter must
841 | return the notification's require interaction preference flag.
842 |
843 |
The data
attribute's getter must return
844 | StructuredDeserialize(notification's data,
845 | context object's relevant Realm). If this throws an exception, then return null.
846 |
847 |
848 |
The actions
attribute's getter must return the
849 | result of the following steps:
850 |
851 |
Let frozenActions be an empty list of type {{NotificationAction}}. 853 | 854 |
For each entry in the notification's list of 855 | actions, perform the following steps: 856 | 857 |
Let action be a new {{NotificationAction}}. 859 | 860 |
Set action's {{NotificationAction/action}} to 861 | entry's name. 862 | 863 |
Set action's {{NotificationAction/title}} to 864 | entry's title. 865 | 866 |
Set action's {{NotificationAction/icon}} to 867 | entry's icon URL. 868 | 869 | 874 |
Call Object.freeze on action, to 875 | prevent accidental mutation by scripts. 876 | 877 |
Append action to frozenActions. 878 |
Create a frozen array from frozenActions. 881 |
Non-persistent {{Notification}} 888 | objects dispatch events during their lifecycle, which developers can use to 889 | generate desired behaviors. 890 | 891 |
The click
event dispatches when the user activates a
892 | notification.
893 |
894 |
895 | var not = new Notification("Gebrünn Gebrünn by Paul Kalkbrenner", { icon: "newsong.svg", tag: "song" }); 896 | not.onclick = function() { displaySong(this); };897 | 898 | 899 |
Persistent notifications fire
902 | notificationclick
events on the {{ServiceWorkerGlobalScope}}.
903 |
904 |
Here a service worker shows a notification with a single "Archive" 905 | action, allowing users to perform this common task from the 906 | notification without having to open the website (for example the notification 907 | platform might show a button on the notification). The user can also activate 908 | the main body of the notification to open their inbox. 909 | 910 |
911 | self.registration.showNotification("New mail from Alice", { 912 | actions: [{action: 'archive', title: "Archive"}] 913 | }); 914 | 915 | self.addEventListener('notificationclick', function(event) { 916 | event.notification.close(); 917 | if (event.action === 'archive') { 918 | silentlyArchiveEmail(); 919 | } else { 920 | clients.openWindow("/inbox"); 921 | } 922 | }, false);923 | 924 | 925 |
tag
member for multiple instancesWeb applications frequently operate concurrently in multiple instances, such
928 | as when a user opens a mail application in multiple browser tabs. Since the
929 | desktop is a shared resource, the notifications API provides a way for these
930 | instances to easily coordinate, by using the tag
member.
931 |
932 |
Notifications which represent the same conceptual event can be tagged in the 933 | same way, and when both are shown, the user will only receive one notification. 934 | 935 |
936 | Instance 1 | Instance 2 937 | | 938 | // Instance notices there is new mail. | 939 | new Notification("New mail from John Doe", | 940 | { tag: 'message1' }); | 941 | | 942 | | // Slightly later, this instance notices 943 | | // there is new mail. 944 | | new Notification("New mail from John Doe", 945 | | { tag: 'message1' });946 | 947 |
The result of this situation, if the user agent follows the algorithms here, is a 948 | single notification "New mail from John Doe". 949 | 950 | 951 |
tag
member for a single instanceThe tag
member can also be used by a single instance of an
954 | application to keep its notifications as current as possible as state changes.
955 |
956 |
For example, if Alice is using a chat application with Bob, and Bob sends 957 | multiple messages while Alice is idle, the application may prefer that Alice not 958 | see a desktop notification for each message. 959 | 960 |
961 | // Bob says "Hi" 962 | new Notification("Bob: Hi", { tag: 'chat_Bob' }); 963 | 964 | // Bob says "Are you free this afternoon?" 965 | new Notification("Bob: Hi / Are you free this afternoon?", { tag: 'chat_Bob' });966 | 967 |
The result of this situation is a single notification; the second one 968 | replaces the first having the same tag. In a platform that queues notifications 969 | (first-in-first-out), using the tag allows the notification to also maintain its 970 | position in the queue. Platforms where the newest notifications are shown first, 971 | a similar result could be achieved using the {{Notification/close()}} method. 972 | 973 | 974 |
977 | dictionary GetNotificationOptions { 978 | DOMString tag = ""; 979 | }; 980 | 981 | partial interface ServiceWorkerRegistration { 982 | Promise<void> showNotification(DOMString title, optional NotificationOptions options = {}); 983 | Promise<sequence<Notification>> getNotifications(optional GetNotificationOptions filter = {}); 984 | }; 985 | 986 | [Exposed=ServiceWorker] 987 | interface NotificationEvent : ExtendableEvent { 988 | constructor(DOMString type, NotificationEventInit eventInitDict); 989 | 990 | readonly attribute Notification notification; 991 | readonly attribute DOMString action; 992 | }; 993 | 994 | dictionary NotificationEventInit : ExtendableEventInit { 995 | required Notification notification; 996 | DOMString action = ""; 997 | }; 998 | 999 | partial interface ServiceWorkerGlobalScope { 1000 | attribute EventHandler onnotificationclick; 1001 | attribute EventHandler onnotificationclose; 1002 | }; 1003 |1004 | 1005 |
The
1006 | showNotification(title, options)
1007 | method, when invoked, must run these steps:
1008 |
1009 |
Let promise be a new promise. 1011 | 1012 |
If the context object's active worker is
1013 | null, then reject promise with a TypeError
exception and return
1014 | promise.
1015 |
1016 |
Let serviceWorkerRegistration be the context object. 1017 | 1018 |
Let notification be the result of creating a notification given 1019 | title, options, and serviceWorkerRegistration. If this threw an 1020 | exception, reject promise with that exception and return promise. 1021 | 1022 |
Run these steps in parallel: 1023 | 1024 |
If permission for notification's origin is not
1026 | "granted
", then reject promise with a TypeError
exception,
1027 | and abort these steps.
1028 |
1029 |
Run the fetch steps for notification. 1030 | 1031 |
Run the show steps for notification. 1032 | 1033 |
Resolve promise with undefined. 1034 |
Return promise. 1037 |
The
1040 | getNotifications(filter)
1041 | method, when invoked, must run these steps:
1042 |
1043 |
Let promise be a new promise. 1045 | 1046 |
Run these steps in parallel: 1047 | 1048 |
Let tag be filter's tag
.
1050 |
1051 |
Let notifications be a list of all notifications in the 1052 | list of notifications whose origin is the 1053 | entry settings object's origin, whose 1054 | service worker registration is the context object, and whose 1055 | tag, if tag is not the empty string, is tag. 1056 | 1057 |
Let objects be an empty JavaScript array. 1058 | 1059 |
For each notification in 1060 | notifications, in creation order, create a new {{Notification}} 1061 | object representing notification and push 1062 | that object to objects. 1063 | 1064 |
Resolve promise with objects. 1065 |
Return promise. 1068 |
This method returns zero or more new {{Notification}} objects which might represent 1071 | the same underlying notification of {{Notification}} objects already in existence. 1072 | 1073 |
To fire a service worker notification event named name given 1076 | notification (a notification), and an optional action (a DOMString, 1077 | defaulting to the empty string), Fire Functional Event name using 1078 | {{NotificationEvent}} on notification's 1079 | service worker registration with the following properties: 1080 | 1081 |
The {{NotificationEvent/notification}} attribute's getter must return the 1089 | value it was initialized to. 1090 | 1091 |
The {{NotificationEvent/action}} attribute's getter must return the value it 1092 | was initialized to. 1093 | 1094 |
The following is the event handler (and its corresponding 1095 | event handler event type) that must be supported as attribute by the 1096 | {{ServiceWorkerGlobalScope}} object: 1097 | 1098 |
event handler 1102 | | event handler event type 1103 | |
---|---|
onnotificationclick
1106 | | notificationclick
1107 | |
onnotificationclose
1109 | | notificationclose
1110 | |
Thanks to 1116 | Addison Phillips, 1117 | Aharon (Vladimir) Lanin, 1118 | Alex Russell, 1119 | Anssi Kostiainen, 1120 | Arkadiusz Michalski, 1121 | Boris Zbarsky, 1122 | David Håsäther, 1123 | Doug Turner, 1124 | Drew Wilson, 1125 | Ehsan Akhgari, 1126 | Frederick Hirsch, 1127 | Ian Hickson, 1128 | Jake Archibald, 1129 | James Graham, 1130 | John Mellor, 1131 | Jon Lee, 1132 | Jonas Sicking, 1133 | Michael Cooper, 1134 | Michael Henretty, 1135 | Michael™ Smith, 1136 | Michael van Ouwerkerk, 1137 | Nicolás Satragno, 1138 | Olli Pettay, 1139 | Peter Beverloo, 1140 | Philip Jägenstedt, 1141 | Reuben Morais, 1142 | Rich Tibbett, 1143 | Robert Bindar, 1144 | 박상현 (Sanghyun Park), 1145 | Simon Pieters, 1146 | Theresa O'Connor, 1147 | timeless, and 1148 | triple-underscore 1149 | for being awesome. 1150 | 1151 |
This standard is written by 1152 | Anne van Kesteren 1153 | (Mozilla, 1154 | annevk@annevk.nl). An earlier iteration was written 1155 | by John Gregg (Google, 1156 | johnnyg@google.com). 1157 | 1158 |
1159 | urlPrefix: https://html.spec.whatwg.org/multipage/ 1160 | urlPrefix: webappapis.html; type: dfn 1161 | text: entry settings object 1162 | urlPrefix: https://w3c.github.io/vibration/ 1163 | urlPrefix: #dfn-; type: dfn 1164 | text: perform vibration 1165 | text: validate and normalize 1166 | urlPrefix: #idl-def-; type: interface 1167 | text: VibratePattern; url: vibratepattern 1168 | urlPrefix: https://tc39.github.io/ecma262/#sec-object.; type: dfn 1169 | text: freeze 1170 |1171 | 1172 |
1173 | { 1174 | "LANG": { 1175 | "aliasOf" : "BCP47" 1176 | } 1177 | } 1178 |1179 | -------------------------------------------------------------------------------- /review-drafts/2021-01.bs: -------------------------------------------------------------------------------- 1 |
2 | Group: WHATWG 3 | Date: 2021-01-18 4 | H1: Notifications API 5 | Shortname: notifications 6 | Text Macro: TWITTER notifyapi 7 | Text Macro: LATESTRD 2021-01 8 | Abstract: This standard defines an API to display notifications to the end user, typically outside the top-level browsing context's viewport. It is designed to be compatible with existing notification systems, while remaining platform-independent. 9 | Translation: ja https://triple-underscore.github.io/notifications-ja.html 10 | Translation: zh-cn https://w3c-html-ig-zh.github.io/notifications/whatwg/ 11 |12 | 13 |
This specification depends on the Infra Standard. [[!INFRA]] 16 | 17 |
Some terms used in this specification are defined in the DOM, Fetch, HTML, IDL, Service Workers, 18 | URL, and Vibration API Standards. 19 | [[!DOM]] 20 | [[!FETCH]] 21 | [[!HTML]] 22 | [[!WEBIDL]] 23 | [[!SERVICE-WORKERS]] 24 | [[!URL]] 25 | [[!VIBRATION]] 26 | 27 | 28 |
A notification is an abstract 31 | representation of something that happened, such as the delivery of a message. 32 | 33 |
A notification can have an associated 34 | service worker registration. 35 | 36 |
A notification has an associated 37 | title which is a DOMString. 38 | 39 |
A notification has an associated 40 | body which is a DOMString. 41 | 42 |
A notification has an associated 43 | direction which is one of 44 | auto, ltr, and rtl. 45 | 46 |
A notification has an associated 47 | language which is a DOMString 48 | representing either a valid BCP 47 language tag or the empty string. 49 | 50 |
A notification has an associated 51 | tag which is a DOMString. 52 | 53 |
A notification has an associated 54 | data. 55 | 56 |
A notification has an associated timestamp which 57 | is a {{DOMTimeStamp}} representing the time, in milliseconds since 00:00:00 UTC on 1 January 1970, 58 | of the event for which the notification was created. 59 | 60 |
Timestamps can be used to indicate the time at which a notification 61 | is actual. For example, this could be in the past when a notification is used for 62 | a message that couldn't immediately be delivered because the device was offline, 63 | or in the future for a meeting that is about to start. 64 | 65 |
A notification has an associated 66 | origin. 67 | 68 |
A notification has an associated 69 | renotify preference flag which is initially 70 | unset. When set indicates that the end user should be alerted after the show steps have run 71 | with a new notification that has the same tag as an existing notification. 72 | 73 |
A notification has an associated 74 | silent preference flag which is initially 75 | unset. When set indicates that no sounds or vibrations should be made. 76 | 77 |
A notification has an associated 78 | require interaction preference flag 79 | which is initially unset. When set, indicates that on devices with a sufficiently large screen, the 80 | notification should remain readily available until the user activates or dismisses the notification. 81 | 82 |
A notification can have these associated graphics: an 83 | image URL, 84 | icon URL, and 85 | badge URL; and their corresponding 86 | image resource, icon resource, and 87 | badge resource. 88 | 89 |
An image resource is a picture shown as part of the 90 | content of the notification, and should be displayed with higher visual priority than the 91 | icon resource and badge resource, though it may be 92 | displayed in fewer circumstances. 93 | 94 |
An icon resource is an image that reinforces the 95 | notification (such as an icon, or a photo of the sender). 96 | 97 |
A badge resource is an icon representing the web 98 | application, or the category of the notification if the web application sends a wide variety 99 | of notifications. It may be used to represent the notification when there is 100 | not enough space to display the notification itself. It may also be displayed inside 101 | the notification, but then it should have less visual priority than the 102 | image resource and icon resource. 103 | 104 |
A notification can have a 105 | vibration pattern. 106 | 107 |
Developers are encouraged to not convey information through an 108 | image, icon, 109 | badge, or vibration pattern that 110 | is not otherwise accessible to the end user, especially since notification platforms that do not 111 | support these features might ignore them. 112 | 113 |
A notification has an associated list of 114 | zero or more actions. Each 115 | action has an associated 116 | title and name and 117 | can have an associated icon URL and 118 | icon resource. Users may activate actions, as alternatives to 119 | activating the notification itself. The user agent must determine the 120 | maximum number of actions supported, within the constraints of the 121 | notification platform. 122 | 123 |
Since display of actions is platform-dependent, developers are 124 | encouraged to make sure that any action a user can invoke from a notification is 125 | also available within the web application. 126 | 127 |
Some platforms might modify an icon resource to better 128 | match the platform's visual style before displaying it to the user, for example by rounding the 129 | corners or painting it in a specific color. Developers are encouraged to use an icon that handles 130 | such cases gracefully and does not lose important information through, e.g., loss of color or 131 | clipped corners. 132 | 133 |
A non-persistent notification is a 134 | notification without an associated 135 | service worker registration. 136 | 137 |
A persistent notification is a 138 | notification with an associated 139 | service worker registration. 140 | 141 | 142 | 143 |
To create a notification, given a 146 | title, options, and optionally a serviceWorkerRegistration, run 147 | these steps: 148 | 149 |
Let notification be a new 151 | notification. 152 | 153 |
If a serviceWorkerRegistration was provided, set 154 | notification's service worker registration to 155 | serviceWorkerRegistration. 156 | 157 |
If a serviceWorkerRegistration was not provided and
158 | options's actions
is not empty, throw a
159 | TypeError
exception.
160 |
161 |
Actions are only currently supported for 162 | persistent notifications. 163 | 164 |
If options's silent
is true and options's
165 | vibrate
is present, throw a TypeError
166 | exception.
167 |
168 |
If options's renotify
is true and
169 | options's tag
is the empty string, throw a
170 | TypeError
exception.
171 |
172 |
Set notification's data to
173 | StructuredSerializeForStorage(options's data
). Rethrow
174 | any exceptions.
175 |
176 |
Set notification's title to title. 177 | 178 |
Set notification's
179 | direction to options's
180 | dir
.
181 |
182 |
Set notification's language to
183 | options's lang
.
184 |
185 |
Set notification's origin to the 186 | entry settings object's origin. 187 | 188 |
Set notification's body to options's
189 | body
.
190 |
191 |
Set notification's tag to options's
192 | tag
.
193 |
194 |
Let baseURL be the API base URL specified by the 195 | entry settings object. Or incumbent? 196 | 197 |
If options's image
is present,
198 | parse it using baseURL, and if that does not
199 | return failure, set notification's image URL to the return
200 | value. (Otherwise image URL is not set.)
201 |
202 |
If options's icon
is present,
203 | parse it using baseURL, and if that does not
204 | return failure, set notification's icon URL to the return
205 | value. (Otherwise icon URL is not set.)
206 |
207 |
If options's badge
is present,
208 | parse it using baseURL, and if that does not
209 | return failure, set notification's badge URL to the return
210 | value. (Otherwise badge URL is not set.)
211 |
212 |
If options's vibrate
is present,
213 | validate and normalize it and set notification's
214 | vibration pattern to the return value. (Otherwise
215 | vibration pattern is not set.)
216 |
217 |
If options's timestamp
is present, set
218 | notification's timestamp to the value. Otherwise, set
219 | notification's timestamp to the number of milliseconds that
220 | passed between 00:00:00 UTC on 1 January 1970 and the time at which the
221 | Notification
constructor was called.
222 |
223 |
If options's renotify
is true, set
224 | notification's renotify preference flag.
225 |
226 |
If options's silent
is true, set
227 | notification's silent preference flag.
228 |
229 |
If options's requireInteraction
is true, set
230 | notification's require interaction preference flag.
231 |
232 |
Set notification's list of actions to an empty list,
233 | then for each entry in options's actions
,
234 | up to the maximum number of actions supported (skip any excess
235 | entries), perform the following steps:
236 |
237 |
Let action be a new action. 239 | 240 |
Set action's name to the entry's
241 | action
.
242 |
243 |
Set action's title to the
244 | entry's title
.
245 |
246 |
If entry's icon
is present,
247 | parse it using baseURL, and if that does
248 | not return failure, set action's icon URL to the
249 | return value. (Otherwise icon URL is not set.)
250 |
251 |
Append action to notification's list of 252 | actions. 253 |
Return notification. 256 |
The user agent must keep a list of notifications, which is a list of zero 262 | or more notifications. 263 | 264 |
User agents should run the close steps for a 265 | non-persistent notification a couple of seconds after they have been 266 | created. 267 | 268 |
User agents should not display non-persistent notification in a 269 | platform's "notification center" (if available). 270 | 271 |
User agents should persist persistent notifications until they are 272 | removed from the list of notifications. 273 | 274 |
A persistent notification could have the 275 | {{Notification/close()}} method invoked of one of its {{Notification}} objects. 276 | 277 |
User agents should display persistent notifications in a platform's 278 | "notification center" (if available). 279 | 280 | 281 |
Notifications can only be displayed if the 284 | user (or user agent on behalf of the user) has granted permission. 285 | The permission to show notifications 286 | for a given origin is one of three strings: 287 | 288 |
default
"
290 | This is equivalent to "denied
", but the user has made no
291 | explicit choice thus far.
292 |
293 |
denied
"
294 | This means the user does not want 295 | notifications. 296 | 297 |
granted
"
298 | This means notifications can be 299 | displayed. 300 |
There is no equivalent to "default
"
303 | meaning "granted
". In that case
304 | "granted
" is simply returned as there would be no reason
305 | for the application to ask for permission.
306 |
307 |
308 |
This section is written in terms equivalent to those used in the Rendering 311 | section of HTML. [[!HTML]] 312 | 313 | 315 | 316 |
User agents are expected to honor the Unicode semantics of the text of a
317 | notification's title, body, and the
318 | title of each of its actions. Each is expected
319 | to be treated as an independent set of one or more bidirectional algorithm
320 | paragraphs when displayed, as defined by the bidirectional algorithm's rules P1,
321 | P2, and P3, including, for instance, supporting the paragraph-breaking behavior
322 | of U+000A LINE FEED (LF) characters. For each paragraph of the
323 | title, body and the
324 | title of each of the actions, the
325 | notification's
326 | direction provides the higher-level override of
327 | rules P2 and P3 if it has a value other than "auto
". [[!BIDI]]
328 |
329 |
The notification's direction also determines the relative order in 330 | which the notification's actions should be displayed to the user, if 331 | the notification platform displays them side by side. 332 | 333 | 334 |
The notification's language specifies the primary language for the 340 | notification's title, body and the 341 | title of each of its actions. Its value is a string. 342 | The empty string indicates that the primary language is unknown. Any other string must be 343 | interpreted as a language tag. Validity or well-formedness are not enforced. [[!LANG]] 344 | 345 |
Developers are encouraged to only use valid language tags. 346 | 347 | 348 |
The fetch steps for a given 351 | notification notification are: 352 | 353 |
If the notification platform supports images, fetch 357 | notification's image URL, if image URL is set. 358 | 359 |
The intent is to fetch this resource similar to an
360 | <img>
,
361 | but this needs abstracting.
362 |
363 |
Then, in parallel: 364 | 365 |
Wait for the response. 367 | 368 |
If the response's internal response's type is
369 | "default
", then attempt to decode the resource as image.
370 |
371 |
If the image format is supported, set notification's 372 | image resource to the decoded resource. (Otherwise 373 | notification has no image resource.) 374 |
If the notification platform supports icons, fetch 378 | notification's icon URL, if icon URL 379 | is set. 380 | 381 |
The intent is to fetch this resource similar to an
382 | <img>
,
383 | but this needs abstracting.
384 |
385 |
Then, in parallel: 386 | 387 |
Wait for the response. 389 | 390 |
If the response's internal response's type is
391 | "default
", then attempt to decode the resource as image.
392 |
393 |
If the image format is supported, set notification's 394 | icon resource to the decoded resource. (Otherwise 395 | notification has no icon resource.) 396 |
If the notification platform supports badges, fetch notification's 401 | badge URL, if badge URL is set. 402 | 403 |
The intent is to fetch this resource similar to an
404 | <img>
,
405 | but this needs abstracting.
406 |
407 |
Then, in parallel: 408 | 409 |
Wait for the response. 411 | 412 |
If the response's internal response's type is
413 | "default
", then attempt to decode the resource as image.
414 |
415 |
If the image format is supported, set notification's 416 | badge resource to the decoded resource. (Otherwise 417 | notification has no badge resource.) 418 |
If the notification platform supports actions and action icons, then for each action 423 | in notification's list of actions fetch action's 424 | icon URL, if icon URL is set. 425 | 426 |
The intent is to fetch this resource similar to an
427 | <img>
,
428 | but this needs abstracting.
429 |
430 |
Then, in parallel: 431 | 432 |
Wait for the response. 434 | 435 |
If the response's internal response's type is
436 | "default
", then attempt to decode the resource as image.
437 |
438 |
If the image format is supported, set action's 439 | icon resource to the decoded resource. (Otherwise 440 | action has no icon resource.) 441 |
The show steps for a given 449 | notification notification are: 450 | 451 | 452 |
Wait for any fetches to complete and notification's 454 | image resource icon resource, and 455 | badge resource to be set (if any), as well as the 456 | icon resources for the notification's actions 457 | (if any). 458 | 459 |
Let shown be false. 460 | 461 |
Let oldNotification be the notification in the 462 | list of notifications whose tag is not the empty string and is 463 | notification's tag, and whose origin is 464 | same origin with notification's origin, if any, and null 465 | otherwise. 466 | 467 |
If oldNotification is non-null, then: 469 | 470 |
Handle close events with oldNotification. 472 | 473 |
If the notification platform supports replacement, then: 475 | 476 |
Replace oldNotification with notification, in the 478 | list of notifications. 479 | 480 |
Set shown to true. 481 |
Notification platforms are strongly encouraged to support native 484 | replacement as it leads to a better user experience. 485 | 486 |
Otherwise, remove oldNotification from the 487 | list of notifications. 488 |
If shown is false, then: 492 | 493 |
Append notification to the list of notifications. 495 | 496 |
Display notification on the device (e.g., by calling the appropriate 497 | notification platform API). 498 |
If shown is false or oldNotification is non-null and 501 | notification's renotify preference flag has been set, then run 502 | the alert steps for notification. 503 | 504 |
If notification is a non-persistent notification, then queue a task
505 | to fire an event named show
on the {{Notification}} object representing
506 | notification.
507 |
When a notification notification, 513 | or one of its actions, is activated by the user, assuming the underlying 514 | notification platform supports activation, the user agent must (unless otherwise 515 | specified) run these steps: 516 | 517 |
If notification is a persistent notification, then: 520 | 521 |
Let action be the empty string. 523 | 524 |
If one of notification's actions was activated by the 525 | user, then set action to that action's name. 526 | 527 |
notificationclick
" given
528 | notification and action.
529 | Otherwise, queue a task to run these steps: 533 | 534 |
Let intoFocus be the result of firing an event named
537 | click
on the {{Notification}} object representing notification, with its
538 | {{Event/cancelable}} attribute initialized to true.
539 |
540 |
User agents are encouraged to make {{Window/focus()}} work from within the event
541 | listener for the event named click
.
542 |
543 |
If intoFocus is true, then the user agent should bring the 544 | notification's related browsing context's viewport into focus. 545 |
Throughout the web platform "activate" is intentionally misnamed as "click". 549 | 550 | 551 |
When a notification is closed, either by the 554 | underlying notification platform or by the user, the close steps for it 555 | must be run. 556 | 557 |
The close steps for a given notification are: 558 | 559 |
If the list of notifications does not contain 561 | notification, then abort these steps. 562 | 563 |
Handle close events with notification. 564 | 565 |
Remove notification from the list of notifications. 566 |
To handle close events given a notification, run these steps: 569 | 570 |
If notification is a persistent notification and notification
572 | was closed by the user, then fire a service worker notification event named
573 | "notificationclose
" given notification.
574 |
575 |
If notification is a non-persistent notification, then queue a task
576 | to fire an event named close
on the {{Notification}} object representing
577 | notification.
578 |
The alert steps for alerting the user about a given 584 | notification are: 585 | 586 |
Perform vibration using notification's 588 | vibration pattern, if any. 589 |
595 | [Exposed=(Window,Worker)] 596 | interface Notification : EventTarget { 597 | constructor(DOMString title, optional NotificationOptions options = {}); 598 | 599 | static readonly attribute NotificationPermission permission; 600 | [Exposed=Window] static Promise<NotificationPermission> requestPermission(optional NotificationPermissionCallback deprecatedCallback); 601 | 602 | static readonly attribute unsigned long maxActions; 603 | 604 | attribute EventHandler onclick; 605 | attribute EventHandler onshow; 606 | attribute EventHandler onerror; 607 | attribute EventHandler onclose; 608 | 609 | readonly attribute DOMString title; 610 | readonly attribute NotificationDirection dir; 611 | readonly attribute DOMString lang; 612 | readonly attribute DOMString body; 613 | readonly attribute DOMString tag; 614 | readonly attribute USVString image; 615 | readonly attribute USVString icon; 616 | readonly attribute USVString badge; 617 | [SameObject] readonly attribute FrozenArray<unsigned long> vibrate; 618 | readonly attribute DOMTimeStamp timestamp; 619 | readonly attribute boolean renotify; 620 | readonly attribute boolean silent; 621 | readonly attribute boolean requireInteraction; 622 | [SameObject] readonly attribute any data; 623 | [SameObject] readonly attribute FrozenArray<NotificationAction> actions; 624 | 625 | undefined close(); 626 | }; 627 | 628 | dictionary NotificationOptions { 629 | NotificationDirection dir = "auto"; 630 | DOMString lang = ""; 631 | DOMString body = ""; 632 | DOMString tag = ""; 633 | USVString image; 634 | USVString icon; 635 | USVString badge; 636 | VibratePattern vibrate; 637 | DOMTimeStamp timestamp; 638 | boolean renotify = false; 639 | boolean silent = false; 640 | boolean requireInteraction = false; 641 | any data = null; 642 | sequence<NotificationAction> actions = []; 643 | }; 644 | 645 | enum NotificationPermission { 646 | "default", 647 | "denied", 648 | "granted" 649 | }; 650 | 651 | enum NotificationDirection { 652 | "auto", 653 | "ltr", 654 | "rtl" 655 | }; 656 | 657 | dictionary NotificationAction { 658 | required DOMString action; 659 | required DOMString title; 660 | USVString icon; 661 | }; 662 | 663 | callback NotificationPermissionCallback = undefined (NotificationPermission permission); 664 |665 | 666 |
A non-persistent notification is represented by one {{Notification}} 667 | object and can be created through {{Notification}}'s 668 | constructor. 669 | 670 |
A persistent notification is represented by zero or more 671 | {{Notification}} objects and can be created through the 672 | {{ServiceWorkerRegistration/showNotification()}} method. 673 | 674 | 675 |
A {{Notification}} object must not be garbage collected while the list of notifications
678 | contains its corresponding notification and it has an
679 | event listener whose type is click
, show
,
680 | close
, or error
.
681 |
682 |
683 |
The Notification(title, options)
686 | constructor, when invoked, must run these steps:
687 |
688 |
If the current global object is a {{ServiceWorkerGlobalScope}} object, then
690 | throw a TypeError
exception.
691 |
692 |
Let notification be the result of creating a notification given 693 | title and options. Rethrow any exceptions. 694 | 695 |
Let n be a new {{Notification}} object associated with 696 | notification. 697 | 698 |
Run these steps in parallel: 699 | 700 |
If permission for notification's origin is not
702 | "granted
", then queue a task to fire an event named
703 | error
on n, and abort these steps.
704 |
705 |
Run the fetch steps for notification. 706 | 707 |
Run the show steps for notification. 708 |
Return n. 711 |
The static permission
717 | attribute's getter must return permission for the
718 | entry settings object's origin.
719 |
720 |
If you edit standards please refrain from copying the above. Synchronous 721 | permissions are like synchronous IO, a bad idea. 722 | 723 |
The static
724 | requestPermission(deprecatedCallback)
725 | method, when invoked, must run these steps:
726 |
727 |
Let promise be a new promise. 729 | 730 |
Run these steps in parallel: 732 | 733 |
Let permission be permission for 735 | entry settings object's origin. 736 | 737 | 738 |
If permission is "default
", ask the user whether showing
739 | notifications for the entry settings object's
740 | origin is acceptable. If it is, set
741 | permission to "granted
", and "denied
" otherwise.
742 |
743 |
Queue a task to run these steps: 745 | 746 |
Set permission for the entry settings object's 748 | origin to permission. 749 | 750 |
If deprecatedCallback is given, invoke 751 | deprecatedCallback with permission as single argument. If this 752 | throws an exception, report the exception. 753 | 754 |
Fullfil promise with permission. 755 |
Return promise. 759 |
Notifications are the one instance thus far where asking the 762 | user upfront makes sense. Specifications for other APIs should not use this 763 | pattern and instead employ one of the 764 | 765 | many more suitable alternatives. 766 | 767 |
The static maxActions
768 | attribute's getter must return the maximum number of actions supported.
769 |
770 |
The following are the event handlers (and their corresponding 773 | event handler event types) that must be supported as attributes by the 774 | {{Notification}} object. 775 | 776 |
event handler 780 | | event handler event type 781 | |
---|---|
onclick
784 | | click
785 | |
onshow
787 | | show
788 | |
onerror
790 | | error
791 | |
onclose
793 | | close
794 | |
The close()
method, when
797 | invoked, must run the close steps for the
798 | notification.
799 |
800 |
The title
attribute's getter must return the
801 | notification's title.
802 |
803 |
The dir
attribute's getter must return the
804 | notification's direction.
805 |
806 |
The lang
attribute's getter must return the
807 | notification's language.
808 |
809 |
The body
attribute's getter must return the
810 | notification's body.
811 |
812 |
The tag
attribute's getter must return the
813 | notification's tag.
814 |
815 |
The image
attribute's getter must return
816 | the notification's image URL, serialized,
817 | and the empty string if there is no notification's image URL
818 | otherwise.
819 |
820 |
The icon
attribute's getter must return the
821 | notification's icon URL, serialized, and
822 | the empty string if there is no notification's icon URL otherwise.
823 |
824 |
The badge
attribute's getter must return the
825 | notification's badge URL, serialized, and
826 | the empty string if there is no notification's badge URL otherwise.
827 |
828 |
The vibrate
attribute's getter must return the
829 | notification's vibration pattern, if any, and the empty list
830 | otherwise.
831 |
832 |
The timestamp
attribute's getter must return
833 | the notification's timestamp.
834 |
835 |
The renotify
attribute's getter must return
836 | the notification's renotify preference flag.
837 |
838 |
The silent
attribute's getter must return the
839 | notification's silent preference flag.
840 |
841 |
The requireInteraction
attribute's getter must
842 | return the notification's require interaction preference flag.
843 |
844 |
The data
attribute's getter must return
845 | StructuredDeserialize(notification's data,
846 | context object's relevant Realm). If this throws an exception, then return null.
847 |
848 |
849 |
The actions
attribute's getter must return the
850 | result of the following steps:
851 |
852 |
Let frozenActions be an empty list of type {{NotificationAction}}. 854 | 855 |
For each entry in the notification's list of 856 | actions, perform the following steps: 857 | 858 |
Let action be a new {{NotificationAction}}. 860 | 861 |
Set action's {{NotificationAction/action}} to 862 | entry's name. 863 | 864 |
Set action's {{NotificationAction/title}} to 865 | entry's title. 866 | 867 |
Set action's {{NotificationAction/icon}} to 868 | entry's icon URL. 869 | 870 | 875 |
Call Object.freeze on action, to 876 | prevent accidental mutation by scripts. 877 | 878 |
Append action to frozenActions. 879 |
Create a frozen array from frozenActions. 882 |
Non-persistent {{Notification}} 889 | objects dispatch events during their lifecycle, which developers can use to 890 | generate desired behaviors. 891 | 892 |
The click
event dispatches when the user activates a
893 | notification.
894 |
895 |
896 | var not = new Notification("Gebrünn Gebrünn by Paul Kalkbrenner", { icon: "newsong.svg", tag: "song" }); 897 | not.onclick = function() { displaySong(this); };898 | 899 | 900 |
Persistent notifications fire
903 | notificationclick
events on the {{ServiceWorkerGlobalScope}}.
904 |
905 |
Here a service worker shows a notification with a single "Archive" 906 | action, allowing users to perform this common task from the 907 | notification without having to open the website (for example the notification 908 | platform might show a button on the notification). The user can also activate 909 | the main body of the notification to open their inbox. 910 | 911 |
912 | self.registration.showNotification("New mail from Alice", { 913 | actions: [{action: 'archive', title: "Archive"}] 914 | }); 915 | 916 | self.addEventListener('notificationclick', function(event) { 917 | event.notification.close(); 918 | if (event.action === 'archive') { 919 | silentlyArchiveEmail(); 920 | } else { 921 | clients.openWindow("/inbox"); 922 | } 923 | }, false);924 | 925 | 926 |
tag
member for multiple instancesWeb applications frequently operate concurrently in multiple instances, such
929 | as when a user opens a mail application in multiple browser tabs. Since the
930 | desktop is a shared resource, the notifications API provides a way for these
931 | instances to easily coordinate, by using the tag
member.
932 |
933 |
Notifications which represent the same conceptual event can be tagged in the 934 | same way, and when both are shown, the user will only receive one notification. 935 | 936 |
937 | Instance 1 | Instance 2 938 | | 939 | // Instance notices there is new mail. | 940 | new Notification("New mail from John Doe", | 941 | { tag: 'message1' }); | 942 | | 943 | | // Slightly later, this instance notices 944 | | // there is new mail. 945 | | new Notification("New mail from John Doe", 946 | | { tag: 'message1' });947 | 948 |
The result of this situation, if the user agent follows the algorithms here, is a 949 | single notification "New mail from John Doe". 950 | 951 | 952 |
tag
member for a single instanceThe tag
member can also be used by a single instance of an
955 | application to keep its notifications as current as possible as state changes.
956 |
957 |
For example, if Alice is using a chat application with Bob, and Bob sends 958 | multiple messages while Alice is idle, the application may prefer that Alice not 959 | see a desktop notification for each message. 960 | 961 |
962 | // Bob says "Hi" 963 | new Notification("Bob: Hi", { tag: 'chat_Bob' }); 964 | 965 | // Bob says "Are you free this afternoon?" 966 | new Notification("Bob: Hi / Are you free this afternoon?", { tag: 'chat_Bob' });967 | 968 |
The result of this situation is a single notification; the second one 969 | replaces the first having the same tag. In a platform that queues notifications 970 | (first-in-first-out), using the tag allows the notification to also maintain its 971 | position in the queue. Platforms where the newest notifications are shown first, 972 | a similar result could be achieved using the {{Notification/close()}} method. 973 | 974 | 975 |
978 | dictionary GetNotificationOptions { 979 | DOMString tag = ""; 980 | }; 981 | 982 | partial interface ServiceWorkerRegistration { 983 | Promise<undefined> showNotification(DOMString title, optional NotificationOptions options = {}); 984 | Promise<sequence<Notification>> getNotifications(optional GetNotificationOptions filter = {}); 985 | }; 986 | 987 | [Exposed=ServiceWorker] 988 | interface NotificationEvent : ExtendableEvent { 989 | constructor(DOMString type, NotificationEventInit eventInitDict); 990 | 991 | readonly attribute Notification notification; 992 | readonly attribute DOMString action; 993 | }; 994 | 995 | dictionary NotificationEventInit : ExtendableEventInit { 996 | required Notification notification; 997 | DOMString action = ""; 998 | }; 999 | 1000 | partial interface ServiceWorkerGlobalScope { 1001 | attribute EventHandler onnotificationclick; 1002 | attribute EventHandler onnotificationclose; 1003 | }; 1004 |1005 | 1006 |
The
1007 | showNotification(title, options)
1008 | method, when invoked, must run these steps:
1009 |
1010 |
Let promise be a new promise. 1012 | 1013 |
If the context object's active worker is
1014 | null, then reject promise with a TypeError
exception and return
1015 | promise.
1016 |
1017 |
Let serviceWorkerRegistration be the context object. 1018 | 1019 |
Let notification be the result of creating a notification given 1020 | title, options, and serviceWorkerRegistration. If this threw an 1021 | exception, reject promise with that exception and return promise. 1022 | 1023 |
Run these steps in parallel: 1024 | 1025 |
If permission for notification's origin is not
1027 | "granted
", then reject promise with a TypeError
exception,
1028 | and abort these steps.
1029 |
1030 |
Run the fetch steps for notification. 1031 | 1032 |
Run the show steps for notification. 1033 | 1034 |
Resolve promise with undefined. 1035 |
Return promise. 1038 |
The
1041 | getNotifications(filter)
1042 | method, when invoked, must run these steps:
1043 |
1044 |
Let promise be a new promise. 1046 | 1047 |
Run these steps in parallel: 1048 | 1049 |
Let tag be filter's tag
.
1051 |
1052 |
Let notifications be a list of all notifications in the 1053 | list of notifications whose origin is the 1054 | entry settings object's origin, whose 1055 | service worker registration is the context object, and whose 1056 | tag, if tag is not the empty string, is tag. 1057 | 1058 |
Let objects be an empty JavaScript array. 1059 | 1060 |
For each notification in 1061 | notifications, in creation order, create a new {{Notification}} 1062 | object representing notification and push 1063 | that object to objects. 1064 | 1065 |
Resolve promise with objects. 1066 |
Return promise. 1069 |
This method returns zero or more new {{Notification}} objects which might represent 1072 | the same underlying notification of {{Notification}} objects already in existence. 1073 | 1074 |
To fire a service worker notification event named name given 1077 | notification (a notification), and an optional action (a DOMString, 1078 | defaulting to the empty string), Fire Functional Event name using 1079 | {{NotificationEvent}} on notification's 1080 | service worker registration with the following properties: 1081 | 1082 |
The {{NotificationEvent/notification}} attribute's getter must return the 1090 | value it was initialized to. 1091 | 1092 |
The {{NotificationEvent/action}} attribute's getter must return the value it 1093 | was initialized to. 1094 | 1095 |
The following is the event handler (and its corresponding 1096 | event handler event type) that must be supported as attribute by the 1097 | {{ServiceWorkerGlobalScope}} object: 1098 | 1099 |
event handler 1103 | | event handler event type 1104 | |
---|---|
onnotificationclick
1107 | | notificationclick
1108 | |
onnotificationclose
1110 | | notificationclose
1111 | |
Thanks to 1117 | Addison Phillips, 1118 | Aharon (Vladimir) Lanin, 1119 | Alex Russell, 1120 | Anssi Kostiainen, 1121 | Arkadiusz Michalski, 1122 | Boris Zbarsky, 1123 | David Håsäther, 1124 | Doug Turner, 1125 | Drew Wilson, 1126 | Ehsan Akhgari, 1127 | Frederick Hirsch, 1128 | Ian Hickson, 1129 | Jake Archibald, 1130 | James Graham, 1131 | John Mellor, 1132 | Jon Lee, 1133 | Jonas Sicking, 1134 | Michael Cooper, 1135 | Michael Henretty, 1136 | Michael™ Smith, 1137 | Michael van Ouwerkerk, 1138 | Nicolás Satragno, 1139 | Olli Pettay, 1140 | Peter Beverloo, 1141 | Philip Jägenstedt, 1142 | Reuben Morais, 1143 | Rich Tibbett, 1144 | Robert Bindar, 1145 | 박상현 (Sanghyun Park), 1146 | Simon Pieters, 1147 | Theresa O'Connor, 1148 | timeless, and 1149 | triple-underscore 1150 | for being awesome. 1151 | 1152 |
This standard is written by 1153 | Anne van Kesteren 1154 | (Mozilla, 1155 | annevk@annevk.nl). An earlier iteration was written 1156 | by John Gregg (Google, 1157 | johnnyg@google.com). 1158 | 1159 |
1160 | urlPrefix: https://html.spec.whatwg.org/multipage/ 1161 | urlPrefix: webappapis.html; type: dfn 1162 | text: entry settings object 1163 | urlPrefix: https://w3c.github.io/vibration/ 1164 | urlPrefix: #dfn-; type: dfn 1165 | text: perform vibration 1166 | text: validate and normalize 1167 | urlPrefix: #idl-def-; type: interface 1168 | text: VibratePattern; url: vibratepattern 1169 | urlPrefix: https://tc39.github.io/ecma262/#sec-object.; type: dfn 1170 | text: freeze 1171 |1172 | 1173 |
1174 | { 1175 | "LANG": { 1176 | "aliasOf" : "BCP47" 1177 | } 1178 | } 1179 |1180 | --------------------------------------------------------------------------------