PageRenderTime 42ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/files/foundation/6.1.2/js/foundation.accordion.js

https://gitlab.com/Mirros/jsdelivr
JavaScript | 231 lines | 136 code | 20 blank | 75 comment | 17 complexity | 7fefbae0db38ef0be0cfb80935db8193 MD5 | raw file
  1. /**
  2. * Accordion module.
  3. * @module foundation.accordion
  4. * @requires foundation.util.keyboard
  5. * @requires foundation.util.motion
  6. */
  7. !function($, Foundation) {
  8. 'use strict';
  9. /**
  10. * Creates a new instance of an accordion.
  11. * @class
  12. * @fires Accordion#init
  13. * @param {jQuery} element - jQuery object to make into an accordion.
  14. * @param {Object} options - a plain object with settings to override the default options.
  15. */
  16. function Accordion(element, options){
  17. this.$element = element;
  18. this.options = $.extend({}, Accordion.defaults, this.$element.data(), options);
  19. this._init();
  20. Foundation.registerPlugin(this, 'Accordion');
  21. Foundation.Keyboard.register('Accordion', {
  22. 'ENTER': 'toggle',
  23. 'SPACE': 'toggle',
  24. 'ARROW_DOWN': 'next',
  25. 'ARROW_UP': 'previous'
  26. });
  27. }
  28. Accordion.defaults = {
  29. /**
  30. * Amount of time to animate the opening of an accordion pane.
  31. * @option
  32. * @example 250
  33. */
  34. slideSpeed: 250,
  35. /**
  36. * Allow the accordion to have multiple open panes.
  37. * @option
  38. * @example false
  39. */
  40. multiExpand: false,
  41. /**
  42. * Allow the accordion to close all panes.
  43. * @option
  44. * @example false
  45. */
  46. allowAllClosed: false
  47. };
  48. /**
  49. * Initializes the accordion by animating the preset active pane(s).
  50. * @private
  51. */
  52. Accordion.prototype._init = function() {
  53. this.$element.attr('role', 'tablist');
  54. this.$tabs = this.$element.children('li');
  55. if (this.$tabs.length === 0) {
  56. this.$tabs = this.$element.children('[data-accordion-item]');
  57. }
  58. this.$tabs.each(function(idx, el){
  59. var $el = $(el),
  60. $content = $el.find('[data-tab-content]'),
  61. id = $content[0].id || Foundation.GetYoDigits(6, 'accordion'),
  62. linkId = el.id || id + '-label';
  63. $el.find('a:first').attr({
  64. 'aria-controls': id,
  65. 'role': 'tab',
  66. 'id': linkId,
  67. 'aria-expanded': false,
  68. 'aria-selected': false
  69. });
  70. $content.attr({'role': 'tabpanel', 'aria-labelledby': linkId, 'aria-hidden': true, 'id': id});
  71. });
  72. var $initActive = this.$element.find('.is-active').children('[data-tab-content]');
  73. if($initActive.length){
  74. this.down($initActive, true);
  75. }
  76. this._events();
  77. };
  78. /**
  79. * Adds event handlers for items within the accordion.
  80. * @private
  81. */
  82. Accordion.prototype._events = function() {
  83. var _this = this;
  84. this.$tabs.each(function(){
  85. var $elem = $(this);
  86. var $tabContent = $elem.children('[data-tab-content]');
  87. if ($tabContent.length) {
  88. $elem.children('a').off('click.zf.accordion keydown.zf.accordion')
  89. .on('click.zf.accordion', function(e){
  90. // $(this).children('a').on('click.zf.accordion', function(e) {
  91. e.preventDefault();
  92. if ($elem.hasClass('is-active')) {
  93. if(_this.options.allowAllClosed || $elem.siblings().hasClass('is-active')){
  94. _this.up($tabContent);
  95. }
  96. }
  97. else {
  98. _this.down($tabContent);
  99. }
  100. }).on('keydown.zf.accordion', function(e){
  101. Foundation.Keyboard.handleKey(e, 'Accordion', {
  102. toggle: function() {
  103. _this.toggle($tabContent);
  104. },
  105. next: function() {
  106. $elem.next().find('a').focus().trigger('click.zf.accordion');
  107. },
  108. previous: function() {
  109. $elem.prev().find('a').focus().trigger('click.zf.accordion');
  110. },
  111. handled: function() {
  112. e.preventDefault();
  113. e.stopPropagation();
  114. }
  115. });
  116. });
  117. }
  118. });
  119. };
  120. /**
  121. * Toggles the selected content pane's open/close state.
  122. * @param {jQuery} $target - jQuery object of the pane to toggle.
  123. * @function
  124. */
  125. Accordion.prototype.toggle = function($target){
  126. if($target.parent().hasClass('is-active')){
  127. if(this.options.allowAllClosed || $target.parent().siblings().hasClass('is-active')){
  128. this.up($target);
  129. }else{ return; }
  130. }else{
  131. this.down($target);
  132. }
  133. };
  134. /**
  135. * Opens the accordion tab defined by `$target`.
  136. * @param {jQuery} $target - Accordion pane to open.
  137. * @param {Boolean} firstTime - flag to determine if reflow should happen.
  138. * @fires Accordion#down
  139. * @function
  140. */
  141. Accordion.prototype.down = function($target, firstTime) {
  142. var _this = this;
  143. if(!this.options.multiExpand && !firstTime){
  144. var $currentActive = this.$element.find('.is-active').children('[data-tab-content]');
  145. if($currentActive.length){
  146. this.up($currentActive);
  147. }
  148. }
  149. $target
  150. .attr('aria-hidden', false)
  151. .parent('[data-tab-content]')
  152. .addBack()
  153. .parent().addClass('is-active');
  154. // Foundation.Move(_this.options.slideSpeed, $target, function(){
  155. $target.slideDown(_this.options.slideSpeed, function () {
  156. /**
  157. * Fires when the tab is done opening.
  158. * @event Accordion#down
  159. */
  160. _this.$element.trigger('down.zf.accordion', [$target]);
  161. });
  162. // });
  163. // if(!firstTime){
  164. // Foundation._reflow(this.$element.attr('data-accordion'));
  165. // }
  166. $('#' + $target.attr('aria-labelledby')).attr({
  167. 'aria-expanded': true,
  168. 'aria-selected': true
  169. });
  170. };
  171. /**
  172. * Closes the tab defined by `$target`.
  173. * @param {jQuery} $target - Accordion tab to close.
  174. * @fires Accordion#up
  175. * @function
  176. */
  177. Accordion.prototype.up = function($target) {
  178. var $aunts = $target.parent().siblings(),
  179. _this = this;
  180. var canClose = this.options.multiExpand ? $aunts.hasClass('is-active') : $target.parent().hasClass('is-active');
  181. if(!this.options.allowAllClosed && !canClose){
  182. return;
  183. }
  184. // Foundation.Move(this.options.slideSpeed, $target, function(){
  185. $target.slideUp(_this.options.slideSpeed, function () {
  186. /**
  187. * Fires when the tab is done collapsing up.
  188. * @event Accordion#up
  189. */
  190. _this.$element.trigger('up.zf.accordion', [$target]);
  191. });
  192. // });
  193. $target.attr('aria-hidden', true)
  194. .parent().removeClass('is-active');
  195. $('#' + $target.attr('aria-labelledby')).attr({
  196. 'aria-expanded': false,
  197. 'aria-selected': false
  198. });
  199. };
  200. /**
  201. * Destroys an instance of an accordion.
  202. * @fires Accordion#destroyed
  203. * @function
  204. */
  205. Accordion.prototype.destroy = function() {
  206. this.$element.find('[data-tab-content]').slideUp(0).css('display', '');
  207. this.$element.find('a').off('.zf.accordion');
  208. Foundation.unregisterPlugin(this);
  209. };
  210. Foundation.plugin(Accordion, 'Accordion');
  211. }(jQuery, window.Foundation);