]> git.ipfire.org Git - thirdparty/foundation/foundation-sites.git/commitdiff
Create _showMenu method to open any (sub)menu in a drilldown
authorSassNinja <kai.falkowski@gmail.com>
Sat, 5 Aug 2017 14:52:25 +0000 (16:52 +0200)
committerSassNinja <kai.falkowski@gmail.com>
Sat, 5 Aug 2017 14:52:25 +0000 (16:52 +0200)
js/foundation.drilldown.js
test/visual/drilldown/drilldown-show-menu.html [new file with mode: 0644]

index 80a3dbf6e8442ab1e3fc4f6c47f065934e2a8c9e..e8b7a6186b1e211f89c7654f85c52aba42f0d0fa 100644 (file)
@@ -342,6 +342,88 @@ class Drilldown extends Plugin {
       });
   }
 
+  /**
+   * Sets the CSS classes for submenu to show it.
+   * @function
+   * @private
+   * @param {jQuery} $elem - the target submenu (`ul` tag)
+   * @param {boolean} trigger - trigger drilldown event
+   */
+  _setShowSubMenuClasses($elem, trigger) {
+    $elem.addClass('is-active').removeClass('invisible').attr('aria-hidden', false);
+    $elem.parent('li').attr('aria-expanded', true);
+    if (trigger === true) {
+      this.$element.trigger('open.zf.drilldown', [$elem]);
+    }
+  }
+
+  /**
+   * Sets the CSS classes for submenu to hide it.
+   * @function
+   * @private
+   * @param {jQuery} $elem - the target submenu (`ul` tag)
+   * @param {boolean} trigger - trigger drilldown event
+   */
+  _setHideSubMenuClasses($elem, trigger) {
+    $elem.removeClass('is-active').addClass('invisible').attr('aria-hidden', true);
+    $elem.parent('li').attr('aria-expanded', false);
+    if (trigger === true) {
+      $elem.trigger('hide.zf.drilldown', [$elem]);
+    }
+  }
+
+  /**
+   * Opens a specific drilldown (sub)menu no matter which (sub)menu in it is currently visible.
+   * Compared to _show() this lets you jump into any submenu without clicking through every submenu on the way to it.
+   * @function
+   * @fires Drilldown#open
+   * @param {jQuery} $elem - the target (sub)menu (`ul` tag)
+   * @param {boolean} autoFocus - if false the first link in the target (sub)menu won't get auto focused
+   */
+  _showMenu($elem, autoFocus) {
+
+    var _this = this;
+
+    // Reset drilldown
+    var $expandedSubmenus = this.$element.find('li[aria-expanded="true"] > ul[data-submenu]');
+    $expandedSubmenus.each(function(index) {
+      _this._setHideSubMenuClasses($(this));
+    });
+
+    // If target menu is root, focus first link & exit
+    if ($elem.is('[data-drilldown]')) {
+      if (autoFocus !== false) $elem.find('li[role="treeitem"] > a').first().focus();
+      if (this.options.autoHeight) this.$wrapper.css('height', $elem.data('calcHeight'));
+      return;
+    }
+
+    // Find all submenus on way to root incl. the element itself
+    var $submenus = $elem.children().first().parentsUntil('[data-drilldown]', '[data-submenu]');
+
+    // Open target menu and all submenus on its way to root
+    $submenus.each(function(index) {
+
+      // Update height of first child (target menu) if autoHeight option true
+      if (index === 0 && _this.options.autoHeight) {
+        _this.$wrapper.css('height', $(this).data('calcHeight'));
+      }
+
+      var isLastChild = index == $submenus.length - 1;
+
+      // Add transitionsend listener to last child (root due to reverse order) to open target menu's first link
+      // Last child makes sure the event gets always triggered even if going through several menus
+      if (isLastChild === true) {
+        $(this).one(transitionend($(this)), () => {
+          if (autoFocus !== false) {
+            $elem.find('li[role="treeitem"] > a').first().focus();
+          }
+        });
+      }
+
+      _this._setShowSubMenuClasses($(this), isLastChild);
+    });
+  }
+
   /**
    * Opens a submenu.
    * @function
@@ -357,7 +439,7 @@ class Drilldown extends Plugin {
      * @event Drilldown#open
      */
     this.$element.trigger('open.zf.drilldown', [$elem]);
-  };
+  }
 
   /**
    * Hides a submenu
@@ -369,7 +451,7 @@ class Drilldown extends Plugin {
     if(this.options.autoHeight) this.$wrapper.css({height:$elem.parent().closest('ul').data('calcHeight')});
     var _this = this;
     $elem.parent('li').attr('aria-expanded', false);
-    $elem.attr('aria-hidden', true).addClass('is-closing')
+    $elem.attr('aria-hidden', true);
     $elem.addClass('is-closing')
          .one(transitionend($elem), function(){
            $elem.removeClass('is-active is-closing');
diff --git a/test/visual/drilldown/drilldown-show-menu.html b/test/visual/drilldown/drilldown-show-menu.html
new file mode 100644 (file)
index 0000000..883d98e
--- /dev/null
@@ -0,0 +1,111 @@
+<!doctype html>
+<!--[if IE 9]><html class="lt-ie10" lang="en" > <![endif]-->
+<html class="no-js" lang="en" dir="ltr">
+  <head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
+    <title>Foundation for Sites Testing</title>
+    <link href="../assets/css/foundation.css" rel="stylesheet">
+    <style>
+      #menu-a a { background: rgb(255,230,230); }
+      #menu-b a { background: rgb(230,255,230); }
+      #menu-c a { background: rgb(230,230,255); }
+      #menu-x a { background: rgb(255,115,0); }
+      label { display: inline-block; margin-right: 20px; cursor: pointer; }
+      label > input[type="radio"] { margin-right: 5px; }
+      .is-drilldown { margin-bottom: 10px; }
+    </style>
+  </head>
+  <body>
+    <div class="grid-container">
+      <div class="grid-x grid-padding-x">
+        <div class="auto cell"></div>
+        <div class="medium-6 cell">
+          <div class="callout">
+            <p>should be possible to open any drilldown (sub)menu via JS</p>
+            <div class="expanded button-group">
+              <button type="button" class="button" data-show-menu="menu-a">Show A</button>
+              <button type="button" class="button" data-show-menu="menu-b">Show B</button>
+              <button type="button" class="button" data-show-menu="menu-c">Show C</button>
+              <button type="button" class="button" data-show-menu="menu-x">Show X</button>
+            </div>
+            <div>
+              <form>
+                <label><input type="radio" name="comparison-switch" value="new" checked> Use new showMenu</label>
+                <label><input type="radio" name="comparison-switch" value="old"> Use current show</label>
+              </form>
+            </div>
+          </div>
+          <ul class="vertical menu drilldown" data-drilldown data-auto-height="true" id="menu-a">
+            <li>
+              <a href="#">Item A1</a>
+              <ul class="vertical menu nested" id="menu-b">
+                <li><a href="#">Item B1</a></li>
+                <li><a href="#">Item B2</a></li>
+                <li><a href="#">Item B3</a></li>
+                <li>
+                  <a href="#">Item B4</a>
+                  <ul class="vertical menu nested" id="menu-c">
+                    <li><a href="#">Item C1</a></li>
+                    <li><a href="#">Item C2</a></li>
+                    <li><a href="#">Item C3</a></li>
+                  </ul>
+                </li>
+                <li><a href="#">Item B5</a></li>
+              </ul>
+            </li>
+            <li><a href="#">Item A2</a></li>
+            <li>
+              <a href="#">Item A3</a>
+              <ul class="vertical menu nested" id="menu-x">
+                <li><a href="#">Item X1</a></li>
+                <li><a href="#">Item X2</a></li>
+              </ul>
+            </li>
+            <li><a href="#">Item A4</a></li>
+          </ul>
+          <p>
+            Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ratione id accusantium dolore sequi architecto at soluta, nulla nam? Nemo magnam repellendus iure, ut recusandae voluptatibus, dolores pariatur facere illo! Sapiente.
+          </p>
+        </div>
+        <div class="auto cell"></div>
+      </div>
+    </div>
+
+    <script src="../assets/js/vendor.js"></script>
+    <script src="../assets/js/foundation.js"></script>
+    <script>
+      $(document).foundation();
+
+      var demoType;
+
+      $(document).on('click', '[data-show-menu]', function(e){
+
+        e.preventDefault();
+
+        var $menu = $('#'+$(this).data('showMenu'));
+
+        if (demoType == 'old') {
+
+          if ($menu.is('[data-drilldown]')) {
+            // No possibility to show root except of hide all
+            $('[data-drilldown]').foundation('_hideAll');
+          } else {
+            $('[data-drilldown]').foundation('_show', $menu.parent('li'));
+          }
+
+        } else {
+
+          $('[data-drilldown]').foundation('_showMenu', $menu);
+
+        }
+      });
+
+      $(document).on('change', 'input[name="comparison-switch"]', function(){
+        demoType = $('input[name="comparison-switch"]:checked').val();
+        console.log('swtiched to ['+demoType+']');
+      });
+    </script>
+  </body>
+</html>