]> git.ipfire.org Git - thirdparty/foundation/foundation-sites.git/commitdiff
#8680 Refactoring Accordion code to use "Tree" related accessibility.
authorsethk <sethk@criticalmass.com>
Tue, 12 Jul 2016 03:08:19 +0000 (22:08 -0500)
committersethk <sethk@criticalmass.com>
Tue, 12 Jul 2016 03:08:19 +0000 (22:08 -0500)
docs/pages/accordion-menu.md
js/foundation.accordionMenu.js
js/foundation.util.tree.js [new file with mode: 0644]
scss/components/_accordion-menu.scss
scss/components/_menu.scss

index f271fe06f3c3fcb76df4a680f0f547fa77325f0d..e7113ece88de18b52fd221d45f3032cfd6afc7dc 100644 (file)
@@ -20,10 +20,10 @@ Any `<a>` will behave like a standard link. However, any `<a>` paired with a nes
 </div>
 
 ```html
-<ul class="vertical menu" data-accordion-menu>
+<ul class="vertical tree" data-accordion-menu>
   <li>
     <a href="#">Item 1</a>
-    <ul class="menu vertical nested">
+    <ul class="tree vertical nested">
       <li><a href="#">Item 1A</a></li>
       <li><a href="#">Item 1B</a></li>
     </ul>
@@ -32,28 +32,28 @@ Any `<a>` will behave like a standard link. However, any `<a>` paired with a nes
 </ul>
 ```
 
-<ul class="vertical menu" data-accordion-menu>
+<ul class="vertical tree" data-accordion-menu>
   <li>
-    <a href="#">Item 1</a>
-    <ul class="menu vertical nested">
+    <span>Item 1</span>
+    <ul class="tree vertical nested">
       <li>
-        <a href="#">Item 1A</a>
-        <ul class="menu vertical nested">
-          <li><a href="#">Item 1Ai</a></li>
-          <li><a href="#">Item 1Aii</a></li>
-          <li><a href="#">Item 1Aiii</a></li>
+        <span>Item 1A</span>
+        <ul class="tree vertical nested">
+          <li><span>Item 1Ai</span></li>
+          <li><a href="http://www.sony.com">Item 1Aii</a></li>
+          <li><span>Item 1Aiii</span></li>
         </ul>
       </li>
-      <li><a href="#">Item 1B</a></li>
-      <li><a href="#">Item 1C</a></li>
+      <li><span>Item 1B</span></li>
+      <li><span>Item 1C</span></li>
     </ul>
   </li>
   <li>
-    <a href="#">Item 2</a>
-    <ul class="menu vertical nested">
-      <li><a href="#">Item 2A</a></li>
-      <li><a href="#">Item 2B</a></li>
+    <span>Item 2</span>
+    <ul class="tree vertical nested">
+      <li><span>Item 2A</a></li>
+      <li><span>Item 2B</a></li>
     </ul>
   </li>
-  <li><a href="#">Item 3</a></li>
+  <li><a href="http://www.nike.com">Item 3</a></li>
 </ul>
index 663a9819b9564b7aec025d0d56217a71898f9bc1..74769b9be851a707d589dbaf5d3eec64fd852111 100644 (file)
@@ -9,7 +9,7 @@
  * @requires foundation.util.motion
  * @requires foundation.util.nest
  */
-
+var donkey;
 class AccordionMenu {
   /**
    * Creates a new instance of an accordion menu.
@@ -22,7 +22,7 @@ class AccordionMenu {
     this.$element = element;
     this.options = $.extend({}, AccordionMenu.defaults, this.$element.data(), options);
 
-    Foundation.Nest.Feather(this.$element, 'accordion');
+    Foundation.Tree.Feather(this.$element, 'accordion');
 
     this._init();
 
@@ -35,8 +35,8 @@ class AccordionMenu {
       'ARROW_DOWN': 'down',
       'ARROW_LEFT': 'close',
       'ESCAPE': 'closeAll',
-      'TAB': 'down',
-      'SHIFT_TAB': 'up'
+      //'TAB': 'down',
+      //'SHIFT_TAB': 'up'
     });
   }
 
@@ -49,7 +49,7 @@ class AccordionMenu {
   _init() {
     this.$element.find('[data-submenu]').not('.is-active').slideUp(0);//.find('a').css('padding-left', '1rem');
     this.$element.attr({
-      'role': 'tablist',
+      'role': 'tree',
       'aria-multiselectable': this.options.multiOpen
     });
 
@@ -63,13 +63,13 @@ class AccordionMenu {
       $elem.attr({
         'aria-controls': subId,
         'aria-expanded': isActive,
-        'role': 'tab',
+        'role': 'treeitem',
         'id': linkId
       });
       $sub.attr({
         'aria-labelledby': linkId,
         'aria-hidden': !isActive,
-        'role': 'tabpanel',
+        'role': 'group',
         'id': subId
       });
     });
@@ -94,7 +94,7 @@ class AccordionMenu {
       var $submenu = $(this).children('[data-submenu]');
 
       if ($submenu.length) {
-        $(this).children('a').off('click.zf.accordionMenu').on('click.zf.accordionMenu', function(e) {
+        $(this).children('span').off('click.zf.accordionMenu').on('click.zf.accordionMenu', function(e) {
           e.preventDefault();
 
           _this.toggle($submenu);
@@ -109,19 +109,19 @@ class AccordionMenu {
 
       $elements.each(function(i) {
         if ($(this).is($element)) {
-          $prevElement = $elements.eq(Math.max(0, i-1)).find('a').first();
-          $nextElement = $elements.eq(Math.min(i+1, $elements.length-1)).find('a').first();
+          $prevElement = $elements.eq(Math.max(0, i-1)).first();
+          $nextElement = $elements.eq(Math.min(i+1, $elements.length-1)).first();
 
           if ($(this).children('[data-submenu]:visible').length) { // has open sub menu
-            $nextElement = $element.find('li:first-child').find('a').first();
+            $nextElement = $element.find('li:first-child').first();
           }
           if ($(this).is(':first-child')) { // is first element of sub menu
-            $prevElement = $element.parents('li').first().find('a').first();
+            $prevElement = $element.parents('li').first();
           } else if ($prevElement.children('[data-submenu]:visible').length) { // if previous element has open sub menu
-            $prevElement = $prevElement.find('li:last-child').find('a').first();
+            $prevElement = $prevElement.find('li:last-child');
           }
           if ($(this).is(':last-child')) { // is last element of sub menu
-            $nextElement = $element.parents('li').first().next('li').find('a').first();
+            $nextElement = $element.parents('li').first().next('li').first();
           }
 
           return;
@@ -131,7 +131,7 @@ class AccordionMenu {
         open: function() {
           if ($target.is(':hidden')) {
             _this.down($target);
-            $target.find('li').first().find('a').first().focus();
+            //$target.find('li').first().first().focus();
           }
         },
         close: function() {
@@ -139,11 +139,15 @@ class AccordionMenu {
             _this.up($target);
           } else if ($element.parent('[data-submenu]').length) { // close currently open sub
             _this.up($element.parent('[data-submenu]'));
-            $element.parents('li').first().find('a').first().focus();
+            $element.parents('li').first().first().focus();
           }
         },
         up: function() {
-          $prevElement.attr('tabindex', -1).focus();
+          if( $prevElement.attr('tabindex') ){
+            $prevElement.focus();
+          } else {
+            $prevElement.attr('tabindex', -1).focus();
+          }
           return true;
         },
         down: function() {
@@ -153,6 +157,10 @@ class AccordionMenu {
         toggle: function() {
           if ($element.children('[data-submenu]').length) {
             _this.toggle($element.children('[data-submenu]'));
+          } else {
+            if( $element.find('a:first').attr('href') ){
+              window.location = $element.find('a:first').attr('href');
+            }
           }
         },
         closeAll: function() {
@@ -174,6 +182,7 @@ class AccordionMenu {
    */
   hideAll() {
     this.$element.find('[data-submenu]').slideUp(this.options.slideSpeed);
+    this.$element.find('li:first')[0].focus();
   }
 
   /**
diff --git a/js/foundation.util.tree.js b/js/foundation.util.tree.js
new file mode 100644 (file)
index 0000000..b149062
--- /dev/null
@@ -0,0 +1,79 @@
+'use strict';
+
+!function($) {
+
+const Tree = {
+  Feather(menu, type = 'zf') {
+
+    var items = menu.find('li').attr({'role': 'treeitem'}),
+        subMenuClass = `is-${type}-submenu`,
+        subItemClass = `${subMenuClass}-item`,
+        hasSubClass = `is-${type}-submenu-parent`,
+        noSubClass = `is-${type}-submenu-none`;
+
+    menu.find('li:first').attr('tabindex', 0);
+
+    items.each(function() {
+      var $item = $(this),
+          $sub = $item.children('ul');
+
+      if ($sub.length) {
+        $item
+          .addClass(hasSubClass)
+          .attr({
+            'aria-haspopup': true,
+            'aria-expanded': false,
+            'aria-label': $item.children('span:first').text()
+          });
+
+        $sub
+          .addClass(`submenu ${subMenuClass}`)
+          .attr({
+            'data-submenu': '',
+            'aria-hidden': true,
+            'role': 'menu'
+          });
+      }  else {
+        $item.addClass(noSubClass).find('a').attr('tabindex',-1);
+      }
+
+
+      if ($item.parent('[data-submenu]').length) {
+        $item.addClass(`is-submenu-item ${subItemClass}`);
+      }
+    });
+
+    return;
+  },
+
+  Burn(menu, type) {
+    var items = menu.find('li').removeAttr('tabindex'),
+        subMenuClass = `is-${type}-submenu`,
+        subItemClass = `${subMenuClass}-item`,
+        hasSubClass = `is-${type}-submenu-parent`;
+
+    menu
+      .find('*')
+      .removeClass(`${subMenuClass} ${subItemClass} ${hasSubClass} is-submenu-item submenu is-active`)
+      .removeAttr('data-submenu').css('display', '');
+
+    // console.log(      menu.find('.' + subMenuClass + ', .' + subItemClass + ', .has-submenu, .is-submenu-item, .submenu, [data-submenu]')
+    //           .removeClass(subMenuClass + ' ' + subItemClass + ' has-submenu is-submenu-item submenu')
+    //           .removeAttr('data-submenu'));
+    // items.each(function(){
+    //   var $item = $(this),
+    //       $sub = $item.children('ul');
+    //   if($item.parent('[data-submenu]').length){
+    //     $item.removeClass('is-submenu-item ' + subItemClass);
+    //   }
+    //   if($sub.length){
+    //     $item.removeClass('has-submenu');
+    //     $sub.removeClass('submenu ' + subMenuClass).removeAttr('data-submenu');
+    //   }
+    // });
+  }
+}
+
+Foundation.Tree = Tree;
+
+}(jQuery);
index 0241030cfcb934f592b04356ea277a047d3a5726..ec65144707edf1ddba3c4cbaf056dce43083896b 100644 (file)
@@ -11,9 +11,22 @@ $accordionmenu-arrows: true !default;
 $accordionmenu-arrow-color: $primary-color !default;
 
 @mixin foundation-accordion-menu {
+  .tree{
+    .is-accordion-submenu-none > a{
+      padding: 0;
+      line-height: $list-lineheight;
+    }
+  }
   @if $accordionmenu-arrows {
-    .is-accordion-submenu-parent > a {
+    .is-accordion-submenu-parent > span {
       position: relative;
+      display: block;
+      cursor: pointer;
+      color: $anchor-color;
+
+      &:hover{
+        color: $anchor-color-hover;
+      }
 
       &::after {
         @include css-triangle(6px, $accordionmenu-arrow-color, down);
@@ -24,7 +37,7 @@ $accordionmenu-arrow-color: $primary-color !default;
       }
     }
 
-    .is-accordion-submenu-parent[aria-expanded='true'] > a::after {
+    .is-accordion-submenu-parent[aria-expanded='true'] > span::after {
       transform-origin: 50% 50%;
       transform: scaleY(-1);
     }
index 566cef122176ccbfd174dc223c61a0d8fb5de89d..e115cf719a3f68d548ced05652e2ad235ae46f57 100644 (file)
@@ -62,6 +62,7 @@ $menu-icon-spacing: 0.25rem !default;
     line-height: 1;
   }
 
+
   // Reset styles of inner elements
   input,
   a,
@@ -224,7 +225,7 @@ $menu-icon-spacing: 0.25rem !default;
 }
 
 @mixin foundation-menu {
-  .menu {
+  .menu, .tree {
     @include menu-base;
     @include menu-icons;