]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 1280397 - [a11y] Make the component, product, and other latches accessible
authorDavid Lawrence <dkl@mozilla.com>
Fri, 17 Feb 2017 17:08:17 +0000 (17:08 +0000)
committerDavid Lawrence <dkl@mozilla.com>
Fri, 17 Feb 2017 17:08:17 +0000 (17:08 +0000)
extensions/BugModal/template/en/default/bug_modal/edit.html.tmpl
extensions/BugModal/web/bug_modal.js

index ef2922181dff90876d3a88f979b148cbc00ff249..a33cc541a1b7a4204dd8556230c12334bc45ebe3 100644 (file)
         hide_on_edit = can_edit_product
         help         = "describecomponents.cgi?product=$filtered_product"
     %]
-      <span class="spin-latch" id="product-latch" data-latch="#product-latch" data-for="#product-info">&#9656;</span>
-      <div class="spin-toggle" data-latch="#product-latch" data-for="#product-info">
-        [% bug.product FILTER html %]
-      </div>
-      <div id="product-info" style="display:none">
-        [% bug.product_obj.description FILTER html_light %]
-      </div>
+      <span aria-owns="product-name product-latch">
+        <span role="button" aria-label="show product information" aria-expanded="false" tabindex="0"
+              class="spin-latch" id="product-latch" data-latch="product" data-for="product">&#9656;</span>
+        <div title="show product information" tabindex="0" class="spin-toggle"
+             id="product-name" data-latch="product" data-for="product">
+          [% bug.product FILTER html %]
+        </div>
+        <div id="product-info" style="display:none">
+          [% bug.product_obj.description FILTER html_light %]
+        </div>
+      </span>
     [% END %]
     [% WRAPPER bug_modal/field.html.tmpl
         field          = bug_fields.product
         help       = "describecomponents.cgi?product=$filtered_product&component=$filtered_component#$filtered_component"
 
     %]
-      <span class="spin-latch" id="component-latch" data-latch="#component-latch" data-for="#component-info">&#9656;</span>
-      <div class="spin-toggle" data-latch="#component-latch" data-for="#component-info">
-        [% bug.component FILTER html %]
-      </div>
-      <div id="component-info" style="display:none">
-        <div>[% bug.component_obj.description FILTER html_light %]</div>
-        <a href="buglist.cgi?component=[% bug.component FILTER uri %]&amp;
-                [%~ %]product=[% bug.product FILTER uri %]&amp;
-                [%~ %]bug_status=__open__" target="_blank">Other [% terms.Bugs %]</a>
-      </div>
+      <span aria-owns="component-name component-latch">
+        <span role="button" aria-label="show component description" aria-expanded="false" tabindex="0"
+              class="spin-latch" id="component-latch" data-latch="component" data-for="component">&#9656;</span>
+        <div title="show component information" tabindex="0" class="spin-toggle" id="component-name"
+             data-latch="#component-latch" data-for="component">
+            [% bug.component FILTER html %]
+        </div>
+        <div id="component-info" style="display:none">
+          <div>[% bug.component_obj.description FILTER html_light %]</div>
+          <a href="buglist.cgi?component=[% bug.component FILTER uri %]&amp;
+                  [%~ %]product=[% bug.product FILTER uri %]&amp;
+                  [%~ %]bug_status=__open__" target="_blank">Other [% terms.Bugs %]</a>
+        </div>
+      </span>
     [% END %]
 
     [%# importance %]
       [% END %]
 
       [% IF bug.cc && bug.cc.size %]
-        [% IF user.id %]
-          <input type="hidden" name="removecc" id="removecc">
-          <span id="cc-latch">&#9656;</span>
-        [% END %]
-        <span id="cc-summary" data-count="[% bug.cc.size FILTER none %]">
-          [%
-            IF bug.cc.size == 1;
-              is_cced ? "Just you" : "1 person";
-            ELSE;
-              bug.cc.size _ " people";
-            END;
-          %]
+        <span aria-owns="cc-summary cc-latch">
+          [% IF user.id %]
+            <input type="hidden" name="removecc" id="removecc">
+            <span role="button" aria-label="show cc list" tabindex="0" id="cc-latch">&#9656;</span>
+          [% END %]
+          <span role="button" tabindex="0" id="cc-summary" data-count="[% bug.cc.size FILTER none %]">
+            [%
+              IF bug.cc.size == 1;
+                is_cced ? "Just you" : "1 person";
+              ELSE;
+                bug.cc.size _ " people";
+              END;
+            %]
+          </span>
         </span>
       [% ELSE %]
         <i>Nobody</i>
index 8d908873e22e738736a6258a1ebc7598df2d8778..25a9d1a73615a9addf2db3b82fa60422eb139d1a 100644 (file)
@@ -163,20 +163,38 @@ $(function() {
     // product/component info
     $('.spin-toggle, #product-latch, #component-latch')
         .click(function(event) {
-            event.preventDefault();
-            var latch = $($(event.target).data('latch'));
-            var el_for = $($(event.target).data('for'));
-
-            if (latch.data('expanded')) {
-                latch.data('expanded', false).html('&#9656;');
-                el_for.hide();
-            }
-            else {
-                latch.data('expanded', true).html('&#9662;');
-                el_for.show();
+            spin_toggle(event);
+        }).keydown(function(event) {
+            // allow space or enter to toggle visibility
+            if (event.keyCode == 13 || event.keyCode == 32) {
+                spin_toggle(event);
             }
         });
 
+    function spin_toggle(event) {
+        event.preventDefault();
+        var type  = $(event.target).data('for');
+        var latch = $('#' + type + '-latch');
+        var name  = $('#' + type + '-name');
+        var info  = $('#' + type + '-info');
+        var label = latch.attr('aria-label');
+
+        if (latch.data('expanded')) {
+            label = label.replace(/^hide/, 'show');
+            latch.data('expanded', false).html('&#9656;');
+            latch.attr('aria-expanded', false);
+            info.hide();
+        }
+        else {
+            label = label.replace(/^show/, 'hide');
+            latch.data('expanded', true).html('&#9662;');
+            latch.attr('aria-expanded', true);
+            info.show();
+        }
+        latch.attr('aria-label', label);
+        name.attr('title', label);
+    }
+
     // cc list
 
     function ccListLoading() {
@@ -230,24 +248,37 @@ $(function() {
         $('#cc-summary').addClass('cc-loadable');
         $('#cc-latch, #cc-summary')
             .click(function(event) {
-                event.preventDefault();
-                var latch = $('#cc-latch');
-
-                if (latch.data('expanded')) {
-                    latch.data('expanded', false).html('&#9656;');
-                    $('#cc-list').hide();
-                }
-                else {
-                    latch.data('expanded', true).html('&#9662;');
-                    $('#cc-list').show();
-                    if (!latch.data('fetched')) {
-                        ccListLoading();
-                        ccListUpdate();
-                    }
+                cc_toggle(event);
+            }).keydown(function(event) {
+                // allow space or enter to toggle visibility
+                if (event.keyCode == 13 || event.keyCode == 32) {
+                    cc_toggle(event);
                 }
             });
     }
 
+    function cc_toggle(event) {
+        event.preventDefault();
+        var latch = $('#cc-latch');
+        var label = latch.attr('aria-label');
+        if (latch.data('expanded')) {
+            label = label.replace(/^hide/, 'show');
+            latch.data('expanded', false).html('&#9656;');
+            $('#cc-list').hide();
+        }
+        else {
+            latch.data('expanded', true).html('&#9662;');
+            label = label.replace(/^show/, 'hide');
+            $('#cc-list').show();
+            if (!latch.data('fetched')) {
+                ccListLoading();
+                ccListUpdate();
+            }
+        }
+        latch.attr('aria-label', label);
+        $('#cc-summary').attr('aria-label', label);
+    }
+
     // copy summary to clipboard
 
     function clipboardSummary() {