From 6223a21ce206b36306c86d20c50522222872b304 Mon Sep 17 00:00:00 2001 From: Evan Yamanishi Date: Mon, 21 May 2018 14:21:28 -0400 Subject: [PATCH 01/31] make room for alertdialog.html --- examples/alert/{index.html => alert.html} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/alert/{index.html => alert.html} (100%) diff --git a/examples/alert/index.html b/examples/alert/alert.html similarity index 100% rename from examples/alert/index.html rename to examples/alert/alert.html From 07ba6d6cdced7f2ece516790dc8e6afddbf881a8 Mon Sep 17 00:00:00 2001 From: Evan Yamanishi Date: Mon, 21 May 2018 14:21:56 -0400 Subject: [PATCH 02/31] initial alertdialog --- examples/alert/alert-dialog.html | 73 +++++++++++++++++++++++++++++++ examples/alert/css/alert.css | 24 ++++++++++ examples/alert/js/alert-dialog.js | 51 +++++++++++++++++++++ 3 files changed, 148 insertions(+) create mode 100644 examples/alert/alert-dialog.html create mode 100644 examples/alert/js/alert-dialog.js diff --git a/examples/alert/alert-dialog.html b/examples/alert/alert-dialog.html new file mode 100644 index 0000000000..604d55dcb7 --- /dev/null +++ b/examples/alert/alert-dialog.html @@ -0,0 +1,73 @@ + + + + + Alert and Message Dialogs Example | WAI-ARIA Authoring Practices 1.1 + + + + + + + + + + + + + + + + + +
+

Alert Dialog Example

+

The below example demonstrates the design pattern for an alert dialog. The design pattern for an alert is also demonstrated to allow the user to experience the difference between the two patterns.

+

In this example, the "notes" <textarea> contains editable text that you are encouraged to modify. Pressing the "discard notes" button will trigger a confirmation dialog, but only if the notes field contains text. Clicking "yes" will remove all contents of the notes field, while clicking "no" or pressing escape will simply close the dialog. If the notes field does not contain any text, pressing the "discard nodes" button will trigger an alert notification that there is nothing to discard. This notification appears for 3 seconds, and then disappears, a pattern commonly referred to as a "toast notification."

+
+

Example

+ +
+ +
+ + + +
+ +
+
+
+

Accessibility Features

+

Note that this example uses code from the modal dialog example to handle the behavior of the alertdialog. As such, referencing that example may be useful.

+
    +
  1. The accessible label for the alert dialog is set to its heading ("Confirmation").
  2. +
  3. The dialog's prompt ("Are you sure...?") is referenced via aria-describedby to ensure that the user is immediately aware of the prompt.
  4. +
  5. Focus is automatically set to the first focusable element inside the dialog, which is the "No" button. This is the least destructive action, and will prevent the user from accidentally confirming the dialog.
  6. +
  7. The user can dismiss the dialog with Escape at any time, or by selecting the "No" button.
  8. +
  9. Once the user has removed the contents of the notes textarea, clicking the "discard notes" button cannot do anything. To communicate this to the user, an alert with role="alert" is triggered.
  10. +
+
+
+ + diff --git a/examples/alert/css/alert.css b/examples/alert/css/alert.css index b11f1faa42..3669537a79 100644 --- a/examples/alert/css/alert.css +++ b/examples/alert/css/alert.css @@ -8,3 +8,27 @@ [role="alert"]:empty { display: none; } + +/* styling for alert-dialog example */ +.notes { + display: block; + font-size: 1rem; + line-height: 1.3; + min-width: 400px; + max-width: 100%; + width: 33%; +} + +[role="alert"].toast { + background-color: rgba(0, 0, 0, 0.7); + color: #fff; + padding: 1rem; + border: none; + border-radius: 0.25rem; + box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23); + + position: absolute; + bottom: 1rem; + left: 50%; + transform: translateX(-50%); +} diff --git a/examples/alert/js/alert-dialog.js b/examples/alert/js/alert-dialog.js new file mode 100644 index 0000000000..8f61437671 --- /dev/null +++ b/examples/alert/js/alert-dialog.js @@ -0,0 +1,51 @@ +function initAlertDialog () { + function discardInput (closeButton, inputId) { + var input = document.getElementById(inputId); + input.value = ''; + closeDialog(closeButton); + } + + function triggerAlert (alertId) { + return new Promise(function (resolve, reject) { + try { + var alert = document.getElementById(alertId); + alert.classList.remove('hidden'); + setTimeout(function () { + alert.classList.add('hidden'); + resolve(); + }, 3000); + } + catch (err) { + reject(err); + } + }); + } + + function openAlertDialog (dialogId, focusAfterClosed, focusFirst) { + var target = document.getElementById(focusAfterClosed.getAttribute('aria-controls')); + if (target && target.value) { + var dialog = document.getElementById(dialogId); + var desc = document.getElementById(dialog.getAttribute('aria-describedby')); + var wordCount = document.getElementById('word_count'); + if (!wordCount) { + wordCount = document.createElement('p'); + wordCount.id = 'word_count'; + desc.appendChild(wordCount); + } + var count = target.value.split(/\s/).length; + var frag = (count > 1) ? 'words' : 'word'; + wordCount.textContent = count + ' ' + frag + ' will be deleted.'; + openDialog(dialogId, focusAfterClosed, focusFirst); + } + else { + triggerAlert('alert_toast').then(function () { + // optionally do something on notification end + }); + } + } + + window.openAlertDialog = openAlertDialog; + window.discardInput = discardInput; +} + +document.addEventListener('DOMContentLoaded', initAlertDialog); From 3c92514ea87384de39285818e37163199b84c611 Mon Sep 17 00:00:00 2001 From: Evan Yamanishi Date: Mon, 21 May 2018 14:22:25 -0400 Subject: [PATCH 03/31] editorial: fix fragment sentence --- examples/dialog-modal/dialog.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/dialog-modal/dialog.html b/examples/dialog-modal/dialog.html index 209fe0ff28..340e9e6444 100644 --- a/examples/dialog-modal/dialog.html +++ b/examples/dialog-modal/dialog.html @@ -316,7 +316,7 @@

Verification Result

  • The larger a focusable element is, the more difficult it is to visually identify the location of focus, especially for users with a narrow field of view.
  • -
  • The dialog has a visual boarder. So creating a clear visual indicator of focus +
  • The dialog has a visual border, so creating a clear visual indicator of focus when the entire dialog has focus is not very feasible.
  • Screen readers read the label and content of focusable elements. The dialog contains its label and a lot of content! If a dialog like this one has focus, the From ac5502f1a484c1fa6a8f604149e4425865c84413 Mon Sep 17 00:00:00 2001 From: Evan Yamanishi Date: Mon, 21 May 2018 14:22:46 -0400 Subject: [PATCH 04/31] target labels directly --- examples/dialog-modal/css/dialog.css | 4 ++-- examples/dialog-modal/dialog.html | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/dialog-modal/css/dialog.css b/examples/dialog-modal/css/dialog.css index d5be27a5c6..35c9490819 100644 --- a/examples/dialog-modal/css/dialog.css +++ b/examples/dialog-modal/css/dialog.css @@ -69,8 +69,8 @@ body:not(.toc-inline) #main_content main, body:not(.toc-inline) #main_content na } } -[role="dialog"] h2:first-of-type { - text-align:center; +.dialog_label { + text-align: center; } .dialog_form { diff --git a/examples/dialog-modal/dialog.html b/examples/dialog-modal/dialog.html index 340e9e6444..ae7fff9578 100644 --- a/examples/dialog-modal/dialog.html +++ b/examples/dialog-modal/dialog.html @@ -234,7 +234,7 @@

    HTML Source Code

  • The accessible label for the alert dialog is set to its heading ("Confirmation").
  • The dialog's prompt ("Are you sure...?") is referenced via aria-describedby to ensure that the user is immediately aware of the prompt.
  • Focus is automatically set to the first focusable element inside the dialog, which is the "No" button. This is the least destructive action, and will prevent the user from accidentally confirming the dialog.
  • -
  • The user can dismiss the dialog with Escape at any time, or by selecting the "No" button.
  • +
  • The user can dismiss the dialog with Escape at any time, or by clicking the "No" button.
  • Once the user has removed the contents of the notes textarea, clicking the "discard notes" button cannot do anything. To communicate this to the user, an alert with role="alert" is triggered.
  • From b2692e09ef005c021d1dcf02a39ee99896ad4616 Mon Sep 17 00:00:00 2001 From: Evan Yamanishi Date: Fri, 1 Jun 2018 16:36:13 -0400 Subject: [PATCH 22/31] be more consistent about gt/lt usage --- examples/dialog-modal/alertdialog.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/dialog-modal/alertdialog.html b/examples/dialog-modal/alertdialog.html index d1bb51a0d4..9f3adb380e 100644 --- a/examples/dialog-modal/alertdialog.html +++ b/examples/dialog-modal/alertdialog.html @@ -30,7 +30,7 @@

    Alert Dialog Example

    The below example demonstrates the design pattern for an alert dialog. The design pattern for an alert is also demonstrated to allow the user to experience the difference between the two patterns.

    -

    In this example, the "notes" <textarea> contains editable text that you are encouraged to modify. Pressing the "discard notes" button will trigger a confirmation dialog, but only if the notes field contains text. Clicking "yes" will remove all contents of the notes field, while clicking "no" or pressing escape will simply close the dialog. If the notes field does not contain any text, pressing the "discard nodes" button will trigger an alert notification that there is nothing to discard. This notification appears for 3 seconds, and then disappears, a pattern commonly referred to as a "toast notification."

    +

    In this example, the "notes" textarea contains editable text that you are encouraged to modify. Pressing the "discard notes" button will trigger a confirmation dialog, but only if the notes field contains text. Clicking "yes" will remove all contents of the notes field, while clicking "no" or pressing escape will simply close the dialog. If the notes field does not contain any text, pressing the "discard nodes" button will trigger an alert notification that there is nothing to discard. This notification appears for 3 seconds, and then disappears, a pattern commonly referred to as a "toast notification."

    Similar examples include:

    • Alert: a basic alert.
    • From 0ba27b065b88d3ac7e8c60ccf69d833376e28a7c Mon Sep 17 00:00:00 2001 From: Evan Yamanishi Date: Fri, 1 Jun 2018 16:53:43 -0400 Subject: [PATCH 23/31] =?UTF-8?q?vnu:=20The=20=E2=80=9Ctype=E2=80=9D=20att?= =?UTF-8?q?ribute=20is=20unnecessary=20for=20JavaScript=20resources.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/dialog-modal/alertdialog.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/dialog-modal/alertdialog.html b/examples/dialog-modal/alertdialog.html index 9f3adb380e..602b75c051 100644 --- a/examples/dialog-modal/alertdialog.html +++ b/examples/dialog-modal/alertdialog.html @@ -10,11 +10,11 @@ - - + + - + From d61ceb0155b2a0ab39ad48d3acae5acef5b2ddec Mon Sep 17 00:00:00 2001 From: Evan Yamanishi Date: Fri, 1 Jun 2018 16:54:27 -0400 Subject: [PATCH 24/31] serialize the interaction features for easier readability --- examples/dialog-modal/alertdialog.html | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/examples/dialog-modal/alertdialog.html b/examples/dialog-modal/alertdialog.html index 602b75c051..06de6720ba 100644 --- a/examples/dialog-modal/alertdialog.html +++ b/examples/dialog-modal/alertdialog.html @@ -30,7 +30,13 @@

      Alert Dialog Example

      The below example demonstrates the design pattern for an alert dialog. The design pattern for an alert is also demonstrated to allow the user to experience the difference between the two patterns.

      -

      In this example, the "notes" textarea contains editable text that you are encouraged to modify. Pressing the "discard notes" button will trigger a confirmation dialog, but only if the notes field contains text. Clicking "yes" will remove all contents of the notes field, while clicking "no" or pressing escape will simply close the dialog. If the notes field does not contain any text, pressing the "discard nodes" button will trigger an alert notification that there is nothing to discard. This notification appears for 3 seconds, and then disappears, a pattern commonly referred to as a "toast notification."

      +

      User interactions for this interactive include:

      +
        +
      • The "notes" textarea contains editable text that you are encouraged to modify.
      • +
      • Pressing the "discard notes" button will trigger a confirmation dialog, but only if the notes field contains text.
      • +
      • Clicking "yes" will remove all contents of the notes field, while clicking "no" or pressing escape will simply close the dialog.
      • +
      • If the notes field does not contain any text, pressing the "discard nodes" button will trigger an alert, notifying the user that there is nothing to discard. This notification appears for 3 seconds, and then disappears, a pattern commonly referred to as a "toast notification."
      • +

      Similar examples include:

      • Alert: a basic alert.
      • From 312fcc752eb4904b1591403d61c7eae8f106e995 Mon Sep 17 00:00:00 2001 From: Evan Yamanishi Date: Fri, 1 Jun 2018 16:58:34 -0400 Subject: [PATCH 25/31] more consistent code highlighting --- examples/dialog-modal/alertdialog.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/dialog-modal/alertdialog.html b/examples/dialog-modal/alertdialog.html index 06de6720ba..a0212eb21c 100644 --- a/examples/dialog-modal/alertdialog.html +++ b/examples/dialog-modal/alertdialog.html @@ -71,9 +71,9 @@

        Accessibility Features

        1. The accessible label for the alert dialog is set to its heading ("Confirmation").
        2. The dialog's prompt ("Are you sure...?") is referenced via aria-describedby to ensure that the user is immediately aware of the prompt.
        3. -
        4. Focus is automatically set to the first focusable element inside the dialog, which is the "No" button. This is the least destructive action, and will prevent the user from accidentally confirming the dialog.
        5. -
        6. The user can dismiss the dialog with Escape at any time, or by clicking the "No" button.
        7. -
        8. Once the user has removed the contents of the notes textarea, clicking the "discard notes" button cannot do anything. To communicate this to the user, an alert with role="alert" is triggered.
        9. +
        10. Focus is automatically set to the first focusable element inside the dialog, which is the "No" button. This is the least destructive action, and will prevent the user from accidentally confirming the dialog.
        11. +
        12. The user can dismiss the dialog with Escape at any time, or by clicking the "No" button.
        13. +
        14. Once the user has removed the contents of the notes textarea, clicking the "discard notes" button cannot do anything. To communicate this to the user, an alert with role="alert" is triggered.
        From f88cf4d4efe2bd9bd11f7981994d9907d7a3914c Mon Sep 17 00:00:00 2001 From: Evan Yamanishi Date: Fri, 1 Jun 2018 16:59:09 -0400 Subject: [PATCH 26/31] add a space --- examples/dialog-modal/alertdialog.html | 2 +- examples/dialog-modal/dialog.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/dialog-modal/alertdialog.html b/examples/dialog-modal/alertdialog.html index a0212eb21c..7fb987941b 100644 --- a/examples/dialog-modal/alertdialog.html +++ b/examples/dialog-modal/alertdialog.html @@ -159,7 +159,7 @@

        Role, Property, State, and Tabindex Attributes

        -

        Notes on aria-modaland aria-hidden

        +

        Notes on aria-modal and aria-hidden

        1. The aria-modal property was introduced in ARIA 1.1. diff --git a/examples/dialog-modal/dialog.html b/examples/dialog-modal/dialog.html index ceb739689d..734e06f5eb 100644 --- a/examples/dialog-modal/dialog.html +++ b/examples/dialog-modal/dialog.html @@ -184,7 +184,7 @@

          Role, Property, State, and Tabindex Attributes

          -

          Notes on aria-modaland aria-hidden

          +

          Notes on aria-modal and aria-hidden

          1. The aria-modal property was introduced in ARIA 1.1. From 9cc53ae827066276b9f501db281c3dda9d805b59 Mon Sep 17 00:00:00 2001 From: Evan Yamanishi Date: Fri, 1 Jun 2018 17:01:40 -0400 Subject: [PATCH 27/31] formatting --- examples/dialog-modal/alertdialog.html | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/examples/dialog-modal/alertdialog.html b/examples/dialog-modal/alertdialog.html index 7fb987941b..d68e75ec16 100644 --- a/examples/dialog-modal/alertdialog.html +++ b/examples/dialog-modal/alertdialog.html @@ -29,13 +29,19 @@

            Alert Dialog Example

            -

            The below example demonstrates the design pattern for an alert dialog. The design pattern for an alert is also demonstrated to allow the user to experience the difference between the two patterns.

            +

            + The below example demonstrates the design pattern for an alert dialog. + The design pattern for an alert is also demonstrated to allow the user to experience the difference between the two patterns. +

            User interactions for this interactive include:

            • The "notes" textarea contains editable text that you are encouraged to modify.
            • Pressing the "discard notes" button will trigger a confirmation dialog, but only if the notes field contains text.
            • Clicking "yes" will remove all contents of the notes field, while clicking "no" or pressing escape will simply close the dialog.
            • -
            • If the notes field does not contain any text, pressing the "discard nodes" button will trigger an alert, notifying the user that there is nothing to discard. This notification appears for 3 seconds, and then disappears, a pattern commonly referred to as a "toast notification."
            • +
            • + If the notes field does not contain any text, pressing the "discard nodes" button will trigger an alert, notifying the user that there is nothing to discard. + This notification appears for 3 seconds, and then disappears, a pattern commonly referred to as a "toast notification." +

            Similar examples include:

              @@ -67,13 +73,22 @@

              Confirmation

        Accessibility Features

        -

        Note that this example uses code from the modal dialog example to handle the behavior of the alertdialog. Referencing that example may also be useful.

        +

        + Note that this example uses code from the modal dialog example to handle the behavior of the alertdialog. + Referencing that example may also be useful. +

        1. The accessible label for the alert dialog is set to its heading ("Confirmation").
        2. The dialog's prompt ("Are you sure...?") is referenced via aria-describedby to ensure that the user is immediately aware of the prompt.
        3. -
        4. Focus is automatically set to the first focusable element inside the dialog, which is the "No" button. This is the least destructive action, and will prevent the user from accidentally confirming the dialog.
        5. +
        6. + Focus is automatically set to the first focusable element inside the dialog, which is the "No" button. + This is the least destructive action, and will prevent the user from accidentally confirming the dialog. +
        7. The user can dismiss the dialog with Escape at any time, or by clicking the "No" button.
        8. -
        9. Once the user has removed the contents of the notes textarea, clicking the "discard notes" button cannot do anything. To communicate this to the user, an alert with role="alert" is triggered.
        10. +
        11. + Once the user has removed the contents of the notes textarea, clicking the "discard notes" button cannot do anything. + To communicate this to the user, an alert with role="alert" is triggered. +
        From 239696f6b91c360fac6da252ea0aadf89c068c90 Mon Sep 17 00:00:00 2001 From: Evan Yamanishi Date: Fri, 1 Jun 2018 17:03:25 -0400 Subject: [PATCH 28/31] more consistent language --- examples/dialog-modal/alertdialog.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/dialog-modal/alertdialog.html b/examples/dialog-modal/alertdialog.html index d68e75ec16..2b57b805a2 100644 --- a/examples/dialog-modal/alertdialog.html +++ b/examples/dialog-modal/alertdialog.html @@ -143,7 +143,7 @@

        Role, Property, State, and Tabindex Attributes

        div - Identifies the element that serves as the alertdialog container. + Identifies the element that serves as the alert dialog container. From 7e1d8add6140289e87cf79e6ba4c9bba0b974ac2 Mon Sep 17 00:00:00 2001 From: Evan Yamanishi Date: Mon, 18 Jun 2018 12:52:07 -0400 Subject: [PATCH 29/31] remove redundant li --- examples/dialog-modal/alertdialog.html | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/dialog-modal/alertdialog.html b/examples/dialog-modal/alertdialog.html index 2b57b805a2..aa9f83d4cb 100644 --- a/examples/dialog-modal/alertdialog.html +++ b/examples/dialog-modal/alertdialog.html @@ -159,9 +159,7 @@

        Role, Property, State, and Tabindex Attributes

        aria-describedby=IDREF div -
          -
        • Gives the alertdialog an accessible description by referring to the dialog content that describes the primary message or purpose of the dialog.
        • -
        + Gives the alertdialog an accessible description by referring to the dialog content that describes the primary message or purpose of the dialog. From 60bca35493034eb81d525bfd9d900562c9e1247c Mon Sep 17 00:00:00 2001 From: Evan Yamanishi Date: Mon, 18 Jun 2018 12:52:53 -0400 Subject: [PATCH 30/31] treat the alert like a notification that slides in on the top right --- examples/dialog-modal/css/dialog.css | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/examples/dialog-modal/css/dialog.css b/examples/dialog-modal/css/dialog.css index d32a7a2449..e27e5e6854 100644 --- a/examples/dialog-modal/css/dialog.css +++ b/examples/dialog-modal/css/dialog.css @@ -151,7 +151,12 @@ box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23); position: fixed; - bottom: 50%; - left: 50%; - transform: translate(-50%); + top: 1rem; + right: 1rem; + transform: translateY(-150%); + transition: transform 225ms cubic-bezier(0.4, 0.0, 0.2, 1); +} + +.toast.active { + transform: translateY(0); } From e739b6f009cac504280a2fcd87a074f0cee6d530 Mon Sep 17 00:00:00 2001 From: Evan Yamanishi Date: Mon, 18 Jun 2018 12:59:14 -0400 Subject: [PATCH 31/31] redesign: implement save via local storage; repurpose alert for save --- examples/dialog-modal/alertdialog.html | 46 +++-- examples/dialog-modal/js/alertdialog.js | 219 +++++++++++++++++++----- 2 files changed, 209 insertions(+), 56 deletions(-) diff --git a/examples/dialog-modal/alertdialog.html b/examples/dialog-modal/alertdialog.html index aa9f83d4cb..f125e997dd 100644 --- a/examples/dialog-modal/alertdialog.html +++ b/examples/dialog-modal/alertdialog.html @@ -36,11 +36,20 @@

        Alert Dialog Example

        User interactions for this interactive include:

        • The "notes" textarea contains editable text that you are encouraged to modify.
        • -
        • Pressing the "discard notes" button will trigger a confirmation dialog, but only if the notes field contains text.
        • -
        • Clicking "yes" will remove all contents of the notes field, while clicking "no" or pressing escape will simply close the dialog.
        • - If the notes field does not contain any text, pressing the "discard nodes" button will trigger an alert, notifying the user that there is nothing to discard. - This notification appears for 3 seconds, and then disappears, a pattern commonly referred to as a "toast notification." + The "discard" button triggers a confirmation dialog. +
            +
          • Clicking "yes" will remove all contents of both the notes field and the user's local storage
          • +
          • Clicking "no" or pressing escape will simply close the dialog.
          • +
          • The "discard" button is disabled if the notes field does not contain any text.
          • +
          +
        • +
        • + The "save" button saves the contents of the "notes" textarea to your local storage. +
            +
          • A successful save will trigger a short [role="alert"] to notify you that your notes have been saved.
          • +
          • The "save" button is disabled if the user's local storage value is the same as the textarea value.
          • +

        Similar examples include:

        @@ -54,7 +63,8 @@

        Example

        - + +
        - - + +
        @@ -123,6 +133,14 @@

        Keyboard Support

        Escape Closes the dialog. + + Command + S + (Mac only) Save the contents of the notes textarea when focused. + + + Control + S + (Windows only) Save the contents of the notes textarea when focused. +
        @@ -151,7 +169,7 @@

        Role, Property, State, and Tabindex Attributes

        aria-labelledby=IDREF div - Gives the dialog an accessible name by referring to the element that provides the dialog title. + Gives the alert dialog an accessible name by referring to the element that provides the alert dialog title. @@ -159,7 +177,7 @@

        Role, Property, State, and Tabindex Attributes

        aria-describedby=IDREF div - Gives the alertdialog an accessible description by referring to the dialog content that describes the primary message or purpose of the dialog. + Gives the alert dialog an accessible description by referring to the alert dialog content that describes the primary message or purpose of the alert dialog. @@ -167,9 +185,17 @@

        Role, Property, State, and Tabindex Attributes

        aria-modal=true div - Tells assistive technologies that the windows underneath the current dialog are not available for interaction (inert). + Tells assistive technologies that the windows underneath the current alert dialog are not available for interaction (inert). + + alert + + div + + Identifies the element that serves as the alert notification. + +

        Notes on aria-modal and aria-hidden

        diff --git a/examples/dialog-modal/js/alertdialog.js b/examples/dialog-modal/js/alertdialog.js index 8f61437671..2865595594 100644 --- a/examples/dialog-modal/js/alertdialog.js +++ b/examples/dialog-modal/js/alertdialog.js @@ -1,51 +1,178 @@ -function initAlertDialog () { - function discardInput (closeButton, inputId) { - var input = document.getElementById(inputId); - input.value = ''; - closeDialog(closeButton); - } - - function triggerAlert (alertId) { - return new Promise(function (resolve, reject) { - try { - var alert = document.getElementById(alertId); - alert.classList.remove('hidden'); - setTimeout(function () { - alert.classList.add('hidden'); - resolve(); - }, 3000); - } - catch (err) { - reject(err); - } - }); - } - - function openAlertDialog (dialogId, focusAfterClosed, focusFirst) { - var target = document.getElementById(focusAfterClosed.getAttribute('aria-controls')); - if (target && target.value) { - var dialog = document.getElementById(dialogId); - var desc = document.getElementById(dialog.getAttribute('aria-describedby')); - var wordCount = document.getElementById('word_count'); - if (!wordCount) { - wordCount = document.createElement('p'); - wordCount.id = 'word_count'; - desc.appendChild(wordCount); - } - var count = target.value.split(/\s/).length; - var frag = (count > 1) ? 'words' : 'word'; - wordCount.textContent = count + ' ' + frag + ' will be deleted.'; - openDialog(dialogId, focusAfterClosed, focusFirst); +var aria = aria || {}; + +aria.Utils = aria.Utils || {}; + +aria.Utils.disableCtrl = function (ctrl) { + ctrl.setAttribute('disabled', true); +}; + +aria.Utils.enableCtrl = function (ctrl) { + ctrl.removeAttribute('disabled'); +}; + +aria.Utils.triggerAlert = function (alertEl, content) { + return new Promise(function (resolve, reject) { + try { + alertEl.textContent = content || null; + alertEl.classList.remove('hidden'); + alertEl.addEventListener('transitionend', function (e) { + if (!this.classList.contains('active')) { + this.classList.add('hidden'); + } + }, true); + setTimeout(function () { + alertEl.classList.add('active'); + }, 1); + setTimeout(function () { + alertEl.classList.remove('active'); + resolve(); + }, 3000); + } + catch (err) { + reject(err); + } + }); +}; + +aria.Notes = function Notes (notesId, saveId, discardId, localStorageKey) { + this.notesInput = document.getElementById(notesId); + this.saveBtn = document.getElementById(saveId); + this.discardBtn = document.getElementById(discardId); + this.localStorageKey = localStorageKey || 'alertdialog-notes'; + this.initialized = false; + + Object.defineProperty(this, 'controls', { + get: function () { + return document.querySelectorAll('[aria-controls=' + this.notesInput.id + ']'); + } + }); + Object.defineProperty(this, 'hasContent', { + get: function () { + return this.notesInput.value.length > 0; } - else { - triggerAlert('alert_toast').then(function () { - // optionally do something on notification end - }); + }); + Object.defineProperty(this, 'savedValue', { + get: function () { + return JSON.parse(localStorage.getItem(this.localStorageKey)); + }, + set: function (val) { + this.save(val); } + }); + Object.defineProperty(this, 'isCurrent', { + get: function () { + return this.notesInput.value === this.savedValue; + } + }); + Object.defineProperty(this, 'oninput', { + get: function () { + return this.notesInput.oninput; + }, + set: function (fn) { + if (typeof fn !== 'function') { + throw new TypeError('oninput must be a function'); + } + this.notesInput.addEventListener('input', fn); + } + }); + + if (this.saveBtn && this.discardBtn) { + this.init(); } +}; - window.openAlertDialog = openAlertDialog; - window.discardInput = discardInput; -} +aria.Notes.prototype.save = function (val) { + if (this.alert && !this.isCurrent) { + aria.Utils.triggerAlert(this.alert, 'Saved'); + } + localStorage.setItem(this.localStorageKey, JSON.stringify(val || this.notesInput.value)); + aria.Utils.disableCtrl(this.saveBtn); +}; -document.addEventListener('DOMContentLoaded', initAlertDialog); +aria.Notes.prototype.loadSaved = function () { + if (this.savedValue) { + this.notesInput.value = this.savedValue; + } +}; + +aria.Notes.prototype.discard = function () { + localStorage.clear(); + this.notesInput.value = ''; + this.toggleCtrls(); +}; + +aria.Notes.prototype.disableCtrls = function () { + this.controls.forEach(aria.Utils.disableCtrl); +}; + +aria.Notes.prototype.enableCtrls = function () { + this.controls.forEach(aria.Utils.enableCtrl); +}; + +aria.Notes.prototype.toggleCtrls = function () { + if (this.hasContent) { + this.enableCtrls(); + } + else { + this.disableCtrls(); + } +}; + +aria.Notes.prototype.toggleCurrent = function () { + if (!this.isCurrent) { + this.notesInput.classList.remove('can-save'); + aria.Utils.enableCtrl(this.saveBtn); + } + else { + this.notesInput.classList.add('can-save'); + aria.Utils.disableCtrl(this.saveBtn); + } +}; + +aria.Notes.prototype.keydownHandler = function (e) { + var mod = (navigator.userAgent.includes('Mac')) ? e.metaKey : e.ctrlKey; + if (e.key === 's' & mod) { + e.preventDefault(); + this.save(); + } +}; + +aria.Notes.prototype.init = function () { + if (!this.initialized) { + this.loadSaved(); + this.toggleCurrent(); + this.saveBtn.addEventListener('click', this.save.bind(this, undefined)); + this.discardBtn.addEventListener('click', this.discard.bind(this)); + this.notesInput.addEventListener('input', this.toggleCtrls.bind(this)); + this.notesInput.addEventListener('input', this.toggleCurrent.bind(this)); + this.notesInput.addEventListener('keydown', this.keydownHandler.bind(this)); + this.initialized = true; + } +}; + +/** initialization */ +document.addEventListener('DOMContentLoaded', function initAlertDialog () { + var notes = new aria.Notes('notes', 'notes_save', 'notes_confirm'); + notes.alert = document.getElementById('alert_toast'); + + window.discardInput = function (closeBtn) { + notes.discard.call(notes); + closeDialog(closeBtn); + }; + + window.openAlertDialog = function (dialogId, triggerBtn, focusFirst) { + var target = document.getElementById(triggerBtn.getAttribute('aria-controls')); + var dialog = document.getElementById(dialogId); + var desc = document.getElementById(dialog.getAttribute('aria-describedby')); + var wordCount = document.getElementById('word_count'); + if (!wordCount) { + wordCount = document.createElement('p'); + wordCount.id = 'word_count'; + desc.appendChild(wordCount); + } + var count = target.value.split(/\s/).length; + var frag = (count > 1) ? 'words' : 'word'; + wordCount.textContent = count + ' ' + frag + ' will be deleted.'; + openDialog(dialogId, target, focusFirst); + }; +});