From 22053b34be1b7703ff2f817ce5197d6d21f5a7cf Mon Sep 17 00:00:00 2001 From: Marius Olbertz Date: Mon, 28 Mar 2016 16:38:23 +0200 Subject: [PATCH] Fix keyboard access for drilldown Mainly I changed the focused elements to be the `a` tags rather than the `li` tags. I also added anchors to the menu links in the docs, so it is possible to actually click/space/enter the links to open a new page (or at least change their window's location). The fact that the links within the menus had only pure `#`es in their `href` did not cover the real-life menu purposes and made proper testing a bit hard. --- docs/pages/drilldown-menu.md | 46 ++++++++++++++--------------- js/foundation.drilldown.js | 56 ++++++++++++++++++++++-------------- 2 files changed, 58 insertions(+), 44 deletions(-) diff --git a/docs/pages/drilldown-menu.md b/docs/pages/drilldown-menu.md index 57c9d9d2c..0e223dbba 100644 --- a/docs/pages/drilldown-menu.md +++ b/docs/pages/drilldown-menu.md @@ -16,13 +16,13 @@ Any `` without a submenu will function like a normal link. ```html ``` @@ -37,40 +37,40 @@ Any `` without a submenu will function like a normal link.
  • Item 1A
  • -
  • Item 1B
  • -
  • Item 1C
  • -
  • Item 1D
  • -
  • Item 1E
  • +
  • Item 1B
  • +
  • Item 1C
  • +
  • Item 1D
  • +
  • Item 1E
  • Item 2
  • Item 3
  • -
  • Item 4
  • +
  • Item 4
  • --- diff --git a/js/foundation.drilldown.js b/js/foundation.drilldown.js index ee55085bc..f716f7efe 100644 --- a/js/foundation.drilldown.js +++ b/js/foundation.drilldown.js @@ -44,9 +44,9 @@ class Drilldown { * @private */ _init() { - this.$submenuAnchors = this.$element.find('li.is-drilldown-submenu-parent'); - this.$submenus = this.$submenuAnchors.children('[data-submenu]'); - this.$menuItems = this.$element.find('li').not('.js-drilldown-back').attr('role', 'menuitem'); + this.$submenuAnchors = this.$element.find('li.is-drilldown-submenu-parent').children('a'); + this.$submenus = this.$submenuAnchors.parent('li').children('[data-submenu]'); + this.$menuItems = this.$element.find('li').not('.js-drilldown-back').attr('role', 'menuitem').find('a'); this._prepareMenu(); @@ -113,7 +113,7 @@ class Drilldown { // if(e.target !== e.currentTarget.firstElementChild){ // return false; // } - _this._show($elem); + _this._show($elem.parent('li')); if(_this.options.closeOnClick){ var $body = $('body').not(_this.$wrapper); @@ -132,9 +132,11 @@ class Drilldown { */ _keyboardEvents() { var _this = this; - this.$menuItems.add(this.$element.find('.js-drilldown-back')).on('keydown.zf.drilldown', function(e){ + + this.$menuItems.add(this.$element.find('.js-drilldown-back > a')).on('keydown.zf.drilldown', function(e){ + var $element = $(this), - $elements = $element.parent('ul').children('li'), + $elements = $element.parent('li').parent('ul').children('li').children('a'), $prevElement, $nextElement; @@ -145,28 +147,33 @@ class Drilldown { return; } }); + Foundation.Keyboard.handleKey(e, 'Drilldown', { next: function() { if ($element.is(_this.$submenuAnchors)) { - _this._show($element); - $element.on(Foundation.transitionend($element), function(){ - $element.find('ul li').filter(_this.$menuItems).first().focus(); + _this._show($element.parent('li')); + $element.parent('li').one(Foundation.transitionend($element), function(){ + $element.parent('li').find('ul li a').filter(_this.$menuItems).first().focus(); }); + e.preventDefault(); } }, previous: function() { - _this._hide($element.parent('ul')); - $element.parent('ul').on(Foundation.transitionend($element), function(){ + _this._hide($element.parent('li').parent('ul')); + $element.parent('li').parent('ul').one(Foundation.transitionend($element), function(){ setTimeout(function() { - $element.parent('ul').parent('li').focus(); + $element.parent('li').parent('ul').parent('li').children('a').first().focus(); }, 1); }); + e.preventDefault(); }, up: function() { $prevElement.focus(); + e.preventDefault(); }, down: function() { $nextElement.focus(); + e.preventDefault(); }, close: function() { _this._back(); @@ -174,15 +181,22 @@ class Drilldown { }, open: function() { if (!$element.is(_this.$menuItems)) { // not menu item means back button - _this._hide($element.parent('ul')); - setTimeout(function(){$element.parent('ul').parent('li').focus();}, 1); + _this._hide($element.parent('li').parent('ul')); + $element.parent('li').parent('ul').one(Foundation.transitionend($element), function(){ + setTimeout(function() { + $element.parent('li').parent('ul').parent('li').children('a').first().focus(); + }, 1); + }); + e.preventDefault(); } else if ($element.is(_this.$submenuAnchors)) { - _this._show($element); - setTimeout(function(){$element.find('ul li').filter(_this.$menuItems).first().focus();}, 1); + _this._show($element.parent('li')); + $element.parent('li').one(Foundation.transitionend($element), function(){ + $element.parent('li').find('ul li a').filter(_this.$menuItems).first().focus(); + }); + e.preventDefault(); } }, handled: function() { - e.preventDefault(); e.stopImmediatePropagation(); } }); @@ -244,7 +258,7 @@ class Drilldown { * Opens a submenu. * @function * @fires Drilldown#open - * @param {jQuery} $elem - the current element with a submenu to open. + * @param {jQuery} $elem - the current element with a submenu to open, i.e. the `li` tag. */ _show($elem) { $elem.children('[data-submenu]').addClass('is-active'); @@ -256,7 +270,7 @@ class Drilldown { * Hides a submenu * @function * @fires Drilldown#hide - * @param {jQuery} $elem - the current sub-menu to hide. + * @param {jQuery} $elem - the current sub-menu to hide, i.e. the `ul` tag. */ _hide($elem) { var _this = this; @@ -319,7 +333,7 @@ Drilldown.defaults = { * @option * @example '<\li><\a>Back<\/a><\/li>' */ - backButton: '
  • Back
  • ', + backButton: '
  • Back
  • ', /** * Markup used to wrap drilldown menu. Use a class name for independent styling; the JS applied class: `is-drilldown` is required. Remove the backslash (`\`) if copy and pasting. * @option @@ -344,4 +358,4 @@ Drilldown.defaults = { // Window exports Foundation.plugin(Drilldown, 'Drilldown'); -}(jQuery); +}(jQuery); \ No newline at end of file -- 2.47.2