PageRenderTime 56ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/foundation-sites/dist/js/plugins/foundation.accordionMenu.js

https://gitlab.com/infogenix/foundation-wp
JavaScript | 318 lines | 195 code | 43 blank | 80 comment | 27 complexity | 5b53d53328b480f50519d0f2f79a43e9 MD5 | raw file
  1. 'use strict';
  2. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  3. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  4. !function ($) {
  5. /**
  6. * AccordionMenu module.
  7. * @module foundation.accordionMenu
  8. * @requires foundation.util.keyboard
  9. * @requires foundation.util.motion
  10. * @requires foundation.util.nest
  11. */
  12. var AccordionMenu = function () {
  13. /**
  14. * Creates a new instance of an accordion menu.
  15. * @class
  16. * @fires AccordionMenu#init
  17. * @param {jQuery} element - jQuery object to make into an accordion menu.
  18. * @param {Object} options - Overrides to the default plugin settings.
  19. */
  20. function AccordionMenu(element, options) {
  21. _classCallCheck(this, AccordionMenu);
  22. this.$element = element;
  23. this.options = $.extend({}, AccordionMenu.defaults, this.$element.data(), options);
  24. Foundation.Nest.Feather(this.$element, 'accordion');
  25. this._init();
  26. Foundation.registerPlugin(this, 'AccordionMenu');
  27. Foundation.Keyboard.register('AccordionMenu', {
  28. 'ENTER': 'toggle',
  29. 'SPACE': 'toggle',
  30. 'ARROW_RIGHT': 'open',
  31. 'ARROW_UP': 'up',
  32. 'ARROW_DOWN': 'down',
  33. 'ARROW_LEFT': 'close',
  34. 'ESCAPE': 'closeAll'
  35. });
  36. }
  37. /**
  38. * Initializes the accordion menu by hiding all nested menus.
  39. * @private
  40. */
  41. _createClass(AccordionMenu, [{
  42. key: '_init',
  43. value: function _init() {
  44. this.$element.find('[data-submenu]').not('.is-active').slideUp(0); //.find('a').css('padding-left', '1rem');
  45. this.$element.attr({
  46. 'role': 'menu',
  47. 'aria-multiselectable': this.options.multiOpen
  48. });
  49. this.$menuLinks = this.$element.find('.is-accordion-submenu-parent');
  50. this.$menuLinks.each(function () {
  51. var linkId = this.id || Foundation.GetYoDigits(6, 'acc-menu-link'),
  52. $elem = $(this),
  53. $sub = $elem.children('[data-submenu]'),
  54. subId = $sub[0].id || Foundation.GetYoDigits(6, 'acc-menu'),
  55. isActive = $sub.hasClass('is-active');
  56. $elem.attr({
  57. 'aria-controls': subId,
  58. 'aria-expanded': isActive,
  59. 'role': 'menuitem',
  60. 'id': linkId
  61. });
  62. $sub.attr({
  63. 'aria-labelledby': linkId,
  64. 'aria-hidden': !isActive,
  65. 'role': 'menu',
  66. 'id': subId
  67. });
  68. });
  69. var initPanes = this.$element.find('.is-active');
  70. if (initPanes.length) {
  71. var _this = this;
  72. initPanes.each(function () {
  73. _this.down($(this));
  74. });
  75. }
  76. this._events();
  77. }
  78. /**
  79. * Adds event handlers for items within the menu.
  80. * @private
  81. */
  82. }, {
  83. key: '_events',
  84. value: function _events() {
  85. var _this = this;
  86. this.$element.find('li').each(function () {
  87. var $submenu = $(this).children('[data-submenu]');
  88. if ($submenu.length) {
  89. $(this).children('a').off('click.zf.accordionMenu').on('click.zf.accordionMenu', function (e) {
  90. e.preventDefault();
  91. _this.toggle($submenu);
  92. });
  93. }
  94. }).on('keydown.zf.accordionmenu', function (e) {
  95. var $element = $(this),
  96. $elements = $element.parent('ul').children('li'),
  97. $prevElement,
  98. $nextElement,
  99. $target = $element.children('[data-submenu]');
  100. $elements.each(function (i) {
  101. if ($(this).is($element)) {
  102. $prevElement = $elements.eq(Math.max(0, i - 1)).find('a').first();
  103. $nextElement = $elements.eq(Math.min(i + 1, $elements.length - 1)).find('a').first();
  104. if ($(this).children('[data-submenu]:visible').length) {
  105. // has open sub menu
  106. $nextElement = $element.find('li:first-child').find('a').first();
  107. }
  108. if ($(this).is(':first-child')) {
  109. // is first element of sub menu
  110. $prevElement = $element.parents('li').first().find('a').first();
  111. } else if ($prevElement.parents('li').first().children('[data-submenu]:visible').length) {
  112. // if previous element has open sub menu
  113. $prevElement = $prevElement.parents('li').find('li:last-child').find('a').first();
  114. }
  115. if ($(this).is(':last-child')) {
  116. // is last element of sub menu
  117. $nextElement = $element.parents('li').first().next('li').find('a').first();
  118. }
  119. return;
  120. }
  121. });
  122. Foundation.Keyboard.handleKey(e, 'AccordionMenu', {
  123. open: function () {
  124. if ($target.is(':hidden')) {
  125. _this.down($target);
  126. $target.find('li').first().find('a').first().focus();
  127. }
  128. },
  129. close: function () {
  130. if ($target.length && !$target.is(':hidden')) {
  131. // close active sub of this item
  132. _this.up($target);
  133. } else if ($element.parent('[data-submenu]').length) {
  134. // close currently open sub
  135. _this.up($element.parent('[data-submenu]'));
  136. $element.parents('li').first().find('a').first().focus();
  137. }
  138. },
  139. up: function () {
  140. $prevElement.focus();
  141. return true;
  142. },
  143. down: function () {
  144. $nextElement.focus();
  145. return true;
  146. },
  147. toggle: function () {
  148. if ($element.children('[data-submenu]').length) {
  149. _this.toggle($element.children('[data-submenu]'));
  150. }
  151. },
  152. closeAll: function () {
  153. _this.hideAll();
  154. },
  155. handled: function (preventDefault) {
  156. if (preventDefault) {
  157. e.preventDefault();
  158. }
  159. e.stopImmediatePropagation();
  160. }
  161. });
  162. }); //.attr('tabindex', 0);
  163. }
  164. /**
  165. * Closes all panes of the menu.
  166. * @function
  167. */
  168. }, {
  169. key: 'hideAll',
  170. value: function hideAll() {
  171. this.up(this.$element.find('[data-submenu]'));
  172. }
  173. /**
  174. * Opens all panes of the menu.
  175. * @function
  176. */
  177. }, {
  178. key: 'showAll',
  179. value: function showAll() {
  180. this.down(this.$element.find('[data-submenu]'));
  181. }
  182. /**
  183. * Toggles the open/close state of a submenu.
  184. * @function
  185. * @param {jQuery} $target - the submenu to toggle
  186. */
  187. }, {
  188. key: 'toggle',
  189. value: function toggle($target) {
  190. if (!$target.is(':animated')) {
  191. if (!$target.is(':hidden')) {
  192. this.up($target);
  193. } else {
  194. this.down($target);
  195. }
  196. }
  197. }
  198. /**
  199. * Opens the sub-menu defined by `$target`.
  200. * @param {jQuery} $target - Sub-menu to open.
  201. * @fires AccordionMenu#down
  202. */
  203. }, {
  204. key: 'down',
  205. value: function down($target) {
  206. var _this = this;
  207. if (!this.options.multiOpen) {
  208. this.up(this.$element.find('.is-active').not($target.parentsUntil(this.$element).add($target)));
  209. }
  210. $target.addClass('is-active').attr({ 'aria-hidden': false }).parent('.is-accordion-submenu-parent').attr({ 'aria-expanded': true });
  211. //Foundation.Move(this.options.slideSpeed, $target, function() {
  212. $target.slideDown(_this.options.slideSpeed, function () {
  213. /**
  214. * Fires when the menu is done opening.
  215. * @event AccordionMenu#down
  216. */
  217. _this.$element.trigger('down.zf.accordionMenu', [$target]);
  218. });
  219. //});
  220. }
  221. /**
  222. * Closes the sub-menu defined by `$target`. All sub-menus inside the target will be closed as well.
  223. * @param {jQuery} $target - Sub-menu to close.
  224. * @fires AccordionMenu#up
  225. */
  226. }, {
  227. key: 'up',
  228. value: function up($target) {
  229. var _this = this;
  230. //Foundation.Move(this.options.slideSpeed, $target, function(){
  231. $target.slideUp(_this.options.slideSpeed, function () {
  232. /**
  233. * Fires when the menu is done collapsing up.
  234. * @event AccordionMenu#up
  235. */
  236. _this.$element.trigger('up.zf.accordionMenu', [$target]);
  237. });
  238. //});
  239. var $menus = $target.find('[data-submenu]').slideUp(0).addBack().attr('aria-hidden', true);
  240. $menus.parent('.is-accordion-submenu-parent').attr('aria-expanded', false);
  241. }
  242. /**
  243. * Destroys an instance of accordion menu.
  244. * @fires AccordionMenu#destroyed
  245. */
  246. }, {
  247. key: 'destroy',
  248. value: function destroy() {
  249. this.$element.find('[data-submenu]').slideDown(0).css('display', '');
  250. this.$element.find('a').off('click.zf.accordionMenu');
  251. Foundation.Nest.Burn(this.$element, 'accordion');
  252. Foundation.unregisterPlugin(this);
  253. }
  254. }]);
  255. return AccordionMenu;
  256. }();
  257. AccordionMenu.defaults = {
  258. /**
  259. * Amount of time to animate the opening of a submenu in ms.
  260. * @option
  261. * @type {number}
  262. * @default 250
  263. */
  264. slideSpeed: 250,
  265. /**
  266. * Allow the menu to have multiple open panes.
  267. * @option
  268. * @type {boolean}
  269. * @default true
  270. */
  271. multiOpen: true
  272. };
  273. // Window exports
  274. Foundation.plugin(AccordionMenu, 'AccordionMenu');
  275. }(jQuery);