Skip to content

Instantly share code, notes, and snippets.

@garretthyder
Last active June 8, 2017 20:44

Revisions

  1. Garrett Hyder revised this gist Jun 8, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion foundation.accordion.js
    Original file line number Diff line number Diff line change
    @@ -120,7 +120,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
    * Fires when the zplugin has deeplinked at pageload
    * @event Accordion#deeplink
    */
    // Note: I don't believe this target is right because this.$lement could be the first accordion and not the one that was deeplinked to. May need to use $target to determine $element/accordion.
    // Note: I don't believe this target is right because this.$element could be the first accordion and not the one that was deeplinked to. May need to use $target to determine $element/accordion.
    _this2.$element.trigger('deeplink.zf.accordion', [$target, $anchor]);
    }
    }
  2. Garrett Hyder revised this gist Jun 8, 2017. 1 changed file with 317 additions and 292 deletions.
    609 changes: 317 additions & 292 deletions foundation.accordion.js
    Original file line number Diff line number Diff line change
    @@ -1,335 +1,360 @@
    'use strict';

    !function($) {

    // Custom Window Loaded Check
    window.loaded = false;
    $(window).load(function() {
    window.loaded = true;
    });

    /**
    * Accordion module.
    * @module foundation.accordion
    * @requires foundation.util.keyboard
    * @requires foundation.util.motion
    */

    class Accordion {
    /**
    * Creates a new instance of an accordion.
    * @class
    * @fires Accordion#init
    * @param {jQuery} element - jQuery object to make into an accordion.
    * @param {Object} options - a plain object with settings to override the default options.
    */
    constructor(element, options) {
    this.$element = element;
    this.options = $.extend({}, Accordion.defaults, this.$element.data(), options);
    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; }; }();

    function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

    this._init();
    !function ($) {

    Foundation.registerPlugin(this, 'Accordion');
    Foundation.Keyboard.register('Accordion', {
    'ENTER': 'toggle',
    'SPACE': 'toggle',
    'ARROW_DOWN': 'next',
    'ARROW_UP': 'previous'
    });
    }
    // Custom Window Loaded Check
    window.loaded = false;
    $(window).load(function() {
    window.loaded = true;
    });

    /**
    * Initializes the accordion by animating the preset active pane(s).
    * @private
    * Accordion module.
    * @module foundation.accordion
    * @requires foundation.util.keyboard
    * @requires foundation.util.motion
    */
    _init() {
    this.$element.attr('role', 'tablist');
    this.$tabs = this.$element.children('[data-accordion-item]');

    this.$tabs.each(function(idx, el) {
    var $el = $(el),
    $content = $el.children('[data-tab-content]'),
    id = $content[0].id || Foundation.GetYoDigits(6, 'accordion'),
    linkId = el.id || `${id}-label`;

    $el.find('a:first').attr({
    'aria-controls': id,
    'role': 'tab',
    'id': linkId,
    'aria-expanded': false,
    'aria-selected': false
    });

    $content.attr({'role': 'tabpanel', 'aria-labelledby': linkId, 'aria-hidden': true, 'id': id});
    });
    var $initActive = this.$element.find('.is-active').children('[data-tab-content]');
    this.firstTimeInit = true;
    if($initActive.length){
    this.down($initActive, this.firstTimeInit);
    this.firstTimeInit = false;
    var Accordion = function () {
    /**
    * Creates a new instance of an accordion.
    * @class
    * @fires Accordion#init
    * @param {jQuery} element - jQuery object to make into an accordion.
    * @param {Object} options - a plain object with settings to override the default options.
    */
    function Accordion(element, options) {
    _classCallCheck(this, Accordion);

    this.$element = element;
    this.options = $.extend({}, Accordion.defaults, this.$element.data(), options);

    this._init();

    Foundation.registerPlugin(this, 'Accordion');
    Foundation.Keyboard.register('Accordion', {
    'ENTER': 'toggle',
    'SPACE': 'toggle',
    'ARROW_DOWN': 'next',
    'ARROW_UP': 'previous'
    });
    }

    this._checkDeepLink = () => {
    var anchor = window.location.hash;
    //need a hash and a relevant anchor in this tabset
    if(anchor.length) {
    var $target = $('.accordion-title[href$="'+anchor+'"]'),
    $anchor = $(anchor);

    if ($target.length && $anchor) {
    // Close the right accordion stuff
    if (!this.options.multiExpand && !this.firstTimeInit) {
    var $activeSibling = $target.closest('[data-accordion]').find('.is-active').find('[data-tab-content]').not($anchor);
    if ($activeSibling.length) {
    this.up($activeSibling.not($anchor));
    }
    }
    /**
    * Initializes the accordion by animating the preset active pane(s).
    * @private
    */

    if (!$target.parent('[data-accordion-item]').hasClass('is-active')) {
    this.down($anchor, this.firstTimeInit);
    this.firstTimeInit = false;
    };

    //roll up a little to show the titles
    if (this.options.deepLinkSmudge) {
    if (window.loaded) {
    var offset = $target.offset();
    $('html, body').animate({ scrollTop: offset.top }, this.options.deepLinkSmudgeDelay);
    } else {
    var _this = this;
    $(window).load(function () {
    var offset = $target.offset();
    $('html, body').animate({ scrollTop: offset.top }, _this.options.deepLinkSmudgeDelay);
    });
    }

    _createClass(Accordion, [{
    key: '_init',
    value: function _init() {
    var _this2 = this;

    this.$element.attr('role', 'tablist');
    this.$tabs = this.$element.children('[data-accordion-item]');

    this.$tabs.each(function (idx, el) {
    var $el = $(el),
    $content = $el.children('[data-tab-content]'),
    id = $content[0].id || Foundation.GetYoDigits(6, 'accordion'),
    linkId = el.id || id + '-label';

    $el.find('a:first').attr({
    'aria-controls': id,
    'role': 'tab',
    'id': linkId,
    'aria-expanded': false,
    'aria-selected': false
    });

    $content.attr({ 'role': 'tabpanel', 'aria-labelledby': linkId, 'aria-hidden': true, 'id': id });
    });
    var $initActive = this.$element.find('.is-active').children('[data-tab-content]');
    this.firstTimeInit = true;
    if ($initActive.length) {
    this.down($initActive, this.firstTimeInit);
    this.firstTimeInit = false;
    }

    this._checkDeepLink = function () {
    var anchor = window.location.hash;
    //need a hash and a relevant anchor in this tabset
    if (anchor.length) {
    var $target = $('.accordion-title[href$="'+anchor+'"]'),
    $anchor = $(anchor);

    if ($target.length && $anchor) {
    // Close the right accordion stuff
    if (!_this2.options.multiExpand && !_this2.firstTimeInit) {
    var $activeSibling = $target.closest('[data-accordion]').find('.is-active').find('[data-tab-content]').not($anchor);
    if ($activeSibling.length) {
    _this2.up($activeSibling.not($anchor));
    }
    }

    if (!$target.parent('[data-accordion-item]').hasClass('is-active')) {
    _this2.down($anchor, _this2.firstTimeInit);
    _this2.firstTimeInit = false;
    };

    //roll up a little to show the titles
    if (_this2.options.deepLinkSmudge) {
    var _this = _this2;
    if (window.loaded) {
    var offset = $target.offset();
    $('html, body').animate({ scrollTop: offset.top }, _this.options.deepLinkSmudgeDelay);
    } else {
    $(window).load(function () {
    var offset = $target.offset();
    $('html, body').animate({ scrollTop: offset.top }, _this.options.deepLinkSmudgeDelay);
    });
    }
    }

    /**
    * Fires when the zplugin has deeplinked at pageload
    * @event Accordion#deeplink
    */
    // Note: I don't believe this target is right because this.$lement could be the first accordion and not the one that was deeplinked to. May need to use $target to determine $element/accordion.
    _this2.$element.trigger('deeplink.zf.accordion', [$target, $anchor]);
    }
    }
    };

    /**
    * Fires when the zplugin has deeplinked at pageload
    * @event Accordion#deeplink
    */
    this.$element.trigger('deeplink.zf.accordion', [$target, $anchor]);
    //use browser to open a tab, if it exists in this tabset
    if (this.options.deepLink) {
    this._checkDeepLink();
    }

    this._events();
    }
    }

    //use browser to open a tab, if it exists in this tabset
    if (this.options.deepLink) {
    this._checkDeepLink();
    }
    /**
    * Adds event handlers for items within the accordion.
    * @private
    */

    this._events();
    }
    }, {
    key: '_events',
    value: function _events() {
    var _this = this;

    /**
    * Adds event handlers for items within the accordion.
    * @private
    */
    _events() {
    var _this = this;

    this.$tabs.each(function() {
    var $elem = $(this);
    var $tabContent = $elem.children('[data-tab-content]');
    if ($tabContent.length) {
    $elem.children('a').off('click.zf.accordion keydown.zf.accordion')
    .on('click.zf.accordion', function(e) {
    e.preventDefault();
    _this.toggle($tabContent);
    }).on('keydown.zf.accordion', function(e){
    Foundation.Keyboard.handleKey(e, 'Accordion', {
    toggle: function() {
    _this.toggle($tabContent);
    },
    next: function() {
    var $a = $elem.next().find('a').focus();
    if (!_this.options.multiExpand) {
    $a.trigger('click.zf.accordion')
    }
    },
    previous: function() {
    var $a = $elem.prev().find('a').focus();
    if (!_this.options.multiExpand) {
    $a.trigger('click.zf.accordion')
    }
    },
    handled: function() {
    this.$tabs.each(function () {
    var $elem = $(this);
    var $tabContent = $elem.children('[data-tab-content]');
    if ($tabContent.length) {
    $elem.children('a').off('click.zf.accordion keydown.zf.accordion').on('click.zf.accordion', function (e) {
    e.preventDefault();
    e.stopPropagation();
    }
    });
    _this.toggle($tabContent);
    }).on('keydown.zf.accordion', function (e) {
    Foundation.Keyboard.handleKey(e, 'Accordion', {
    toggle: function () {
    _this.toggle($tabContent);
    },
    next: function () {
    var $a = $elem.next().find('a').focus();
    if (!_this.options.multiExpand) {
    $a.trigger('click.zf.accordion');
    }
    },
    previous: function () {
    var $a = $elem.prev().find('a').focus();
    if (!_this.options.multiExpand) {
    $a.trigger('click.zf.accordion');
    }
    },
    handled: function () {
    e.preventDefault();
    e.stopPropagation();
    }
    });
    });
    }
    });
    if (this.options.deepLink) {
    $(window).on('popstate', this._checkDeepLink);
    }
    }
    });
    if(this.options.deepLink) {
    $(window).on('popstate', this._checkDeepLink);
    }
    }

    /**
    * Toggles the selected content pane's open/close state.
    * @param {jQuery} $target - jQuery object of the pane to toggle (`.accordion-content`).
    * @function
    */
    toggle($target) {
    if($target.parent().hasClass('is-active')) {
    this.up($target);
    } else {
    this.down($target);
    }
    //either replace or update browser history
    if (this.options.deepLink) {
    var anchor = $target.prev('a').attr('href');

    if (this.options.updateHistory) {
    history.pushState({}, '', anchor);
    } else {
    history.replaceState({}, '', anchor);
    }
    }
    }
    /**
    * Toggles the selected content pane's open/close state.
    * @param {jQuery} $target - jQuery object of the pane to toggle (`.accordion-content`).
    * @function
    */

    /**
    * Opens the accordion tab defined by `$target`.
    * @param {jQuery} $target - Accordion pane to open (`.accordion-content`).
    * @param {Boolean} firstTime - flag to determine if reflow should happen.
    * @fires Accordion#down
    * @function
    */
    down($target, firstTime) {
    $target
    .attr('aria-hidden', false)
    .parent('[data-tab-content]')
    .addBack()
    .parent().addClass('is-active');

    if (!this.options.multiExpand && !firstTime) {
    var $currentActive = $target.closest('[data-accordion]').find('.is-active').find('[data-tab-content]').not($target);
    if ($currentActive.length) {
    this.up($currentActive.not($target));
    }, {
    key: 'toggle',
    value: function toggle($target) {
    if ($target.parent().hasClass('is-active')) {
    this.up($target);
    } else {
    this.down($target);
    }
    //either replace or update browser history
    if (this.options.deepLink) {
    var anchor = $target.prev('a').attr('href');

    if (this.options.updateHistory) {
    history.pushState({}, '', anchor);
    } else {
    history.replaceState({}, '', anchor);
    }
    }
    }
    }

    $target.slideDown(this.options.slideSpeed, () => {
    /**
    * Fires when the tab is done opening.
    * @event Accordion#down
    * Opens the accordion tab defined by `$target`.
    * @param {jQuery} $target - Accordion pane to open (`.accordion-content`).
    * @param {Boolean} firstTime - flag to determine if reflow should happen.
    * @fires Accordion#down
    * @function
    */
    this.$element.trigger('down.zf.accordion', [$target]);
    });

    $(`#${$target.attr('aria-labelledby')}`).attr({
    'aria-expanded': true,
    'aria-selected': true
    });
    }
    }, {
    key: 'down',
    value: function down($target, firstTime) {
    var _this3 = this;

    /**
    * Closes the tab defined by `$target`.
    * @param {jQuery} $target - Accordion tab to close (`.accordion-content`).
    * @fires Accordion#up
    * @function
    */
    up($target) {
    var $aunts = $target.parent().siblings(),
    _this = this;
    $target.attr('aria-hidden', false).parent('[data-tab-content]').addBack().parent().addClass('is-active');

    if((!this.options.allowAllClosed && !$aunts.hasClass('is-active')) || !$target.parent().hasClass('is-active')) {
    return;
    }
    if (!this.options.multiExpand && !firstTime) {
    var $currentActive = $target.closest('[data-accordion]').find('.is-active').find('[data-tab-content]').not($target);
    if ($currentActive.length) {
    this.up($currentActive.not($target));
    }
    }

    // Foundation.Move(this.options.slideSpeed, $target, function(){
    $target.slideUp(_this.options.slideSpeed, function () {
    /**
    * Fires when the tab is done collapsing up.
    * @event Accordion#up
    */
    _this.$element.trigger('up.zf.accordion', [$target]);
    });
    // });
    $target.slideDown(this.options.slideSpeed, function () {
    /**
    * Fires when the tab is done opening.
    * @event Accordion#down
    */
    _this3.$element.trigger('down.zf.accordion', [$target]);
    });

    $target.attr('aria-hidden', true)
    .parent().removeClass('is-active');
    $('#' + $target.attr('aria-labelledby')).attr({
    'aria-expanded': true,
    'aria-selected': true
    });
    }

    $(`#${$target.attr('aria-labelledby')}`).attr({
    'aria-expanded': false,
    'aria-selected': false
    });
    }
    /**
    * Closes the tab defined by `$target`.
    * @param {jQuery} $target - Accordion tab to close (`.accordion-content`).
    * @fires Accordion#up
    * @function
    */

    /**
    * Destroys an instance of an accordion.
    * @fires Accordion#destroyed
    * @function
    */
    destroy() {
    this.$element.find('[data-tab-content]').stop(true).slideUp(0).css('display', '');
    this.$element.find('a').off('.zf.accordion');
    if(this.options.deepLink) {
    $(window).off('popstate', this._checkDeepLink);
    }
    }, {
    key: 'up',
    value: function up($target) {
    var $aunts = $target.parent().siblings(),
    _this = this;

    Foundation.unregisterPlugin(this);
    }
    }
    if (!this.options.allowAllClosed && !$aunts.hasClass('is-active') || !$target.parent().hasClass('is-active')) {
    return;
    }

    Accordion.defaults = {
    /**
    * Amount of time to animate the opening of an accordion pane.
    * @option
    * @type {number}
    * @default 250
    */
    slideSpeed: 250,
    /**
    * Allow the accordion to have multiple open panes.
    * @option
    * @type {boolean}
    * @default false
    */
    multiExpand: false,
    /**
    * Allow the accordion to close all panes.
    * @option
    * @type {boolean}
    * @default false
    */
    allowAllClosed: false,
    /**
    * Allows the window to scroll to content of pane specified by hash anchor
    * @option
    * @type {boolean}
    * @default false
    */
    deepLink: false,
    // Foundation.Move(this.options.slideSpeed, $target, function(){
    $target.slideUp(_this.options.slideSpeed, function () {
    /**
    * Fires when the tab is done collapsing up.
    * @event Accordion#up
    */
    _this.$element.trigger('up.zf.accordion', [$target]);
    });
    // });

    /**
    * Adjust the deep link scroll to make sure the top of the accordion panel is visible
    * @option
    * @type {boolean}
    * @default false
    */
    deepLinkSmudge: false,
    $target.attr('aria-hidden', true).parent().removeClass('is-active');

    /**
    * Animation time (ms) for the deep link adjustment
    * @option
    * @type {number}
    * @default 300
    */
    deepLinkSmudgeDelay: 300,
    $('#' + $target.attr('aria-labelledby')).attr({
    'aria-expanded': false,
    'aria-selected': false
    });
    }

    /**
    * Update the browser history with the open accordion
    * @option
    * @type {boolean}
    * @default false
    */
    updateHistory: false
    };
    /**
    * Destroys an instance of an accordion.
    * @fires Accordion#destroyed
    * @function
    */

    // Window exports
    Foundation.plugin(Accordion, 'Accordion');
    }, {
    key: 'destroy',
    value: function destroy() {
    this.$element.find('[data-tab-content]').stop(true).slideUp(0).css('display', '');
    this.$element.find('a').off('.zf.accordion');
    if (this.options.deepLink) {
    $(window).off('popstate', this._checkDeepLink);
    }

    Foundation.unregisterPlugin(this);
    }
    }]);

    return Accordion;
    }();

    Accordion.defaults = {
    /**
    * Amount of time to animate the opening of an accordion pane.
    * @option
    * @type {number}
    * @default 250
    */
    slideSpeed: 250,
    /**
    * Allow the accordion to have multiple open panes.
    * @option
    * @type {boolean}
    * @default false
    */
    multiExpand: false,
    /**
    * Allow the accordion to close all panes.
    * @option
    * @type {boolean}
    * @default false
    */
    allowAllClosed: false,
    /**
    * Allows the window to scroll to content of pane specified by hash anchor
    * @option
    * @type {boolean}
    * @default false
    */
    deepLink: false,

    /**
    * Adjust the deep link scroll to make sure the top of the accordion panel is visible
    * @option
    * @type {boolean}
    * @default false
    */
    deepLinkSmudge: false,

    /**
    * Animation time (ms) for the deep link adjustment
    * @option
    * @type {number}
    * @default 300
    */
    deepLinkSmudgeDelay: 300,

    /**
    * Update the browser history with the open accordion
    * @option
    * @type {boolean}
    * @default false
    */
    updateHistory: false
    };

    // Window exports
    Foundation.plugin(Accordion, 'Accordion');
    }(jQuery);
  3. Garrett Hyder revised this gist Jun 7, 2017. 1 changed file with 22 additions and 7 deletions.
    29 changes: 22 additions & 7 deletions foundation.accordion.js
    Original file line number Diff line number Diff line change
    @@ -2,6 +2,12 @@

    !function($) {

    // Custom Window Loaded Check
    window.loaded = false;
    $(window).load(function() {
    window.loaded = true;
    });

    /**
    * Accordion module.
    * @module foundation.accordion
    @@ -67,34 +73,43 @@ class Accordion {
    var anchor = window.location.hash;
    //need a hash and a relevant anchor in this tabset
    if(anchor.length) {
    var $link = $('.accordion-title[href$="'+anchor+'"]'),
    var $target = $('.accordion-title[href$="'+anchor+'"]'),
    $anchor = $(anchor);

    if ($link.length && $anchor) {
    if ($target.length && $anchor) {
    // Close the right accordion stuff
    if (!this.options.multiExpand && !this.firstTimeInit) {
    var $activeSibling = $link.closest('[data-accordion]').find('.is-active').find('[data-tab-content]').not($anchor);
    var $activeSibling = $target.closest('[data-accordion]').find('.is-active').find('[data-tab-content]').not($anchor);
    if ($activeSibling.length) {
    this.up($activeSibling.not($anchor));
    }
    }

    if (!$link.parent('[data-accordion-item]').hasClass('is-active')) {
    if (!$target.parent('[data-accordion-item]').hasClass('is-active')) {
    this.down($anchor, this.firstTimeInit);
    this.firstTimeInit = false;
    };

    //roll up a little to show the titles
    if (this.options.deepLinkSmudge) {
    var offset = $link.closest('[data-accordion]').offset();
    if (window.loaded) {
    var offset = $target.offset();
    $('html, body').animate({ scrollTop: offset.top }, this.options.deepLinkSmudgeDelay);
    } else {
    var _this = this;
    $(window).load(function () {
    var offset = $target.offset();
    $('html, body').animate({ scrollTop: offset.top }, _this.options.deepLinkSmudgeDelay);
    });
    }

    }

    /**
    * Fires when the zplugin has deeplinked at pageload
    * @event Accordion#deeplink
    */
    this.$element.trigger('deeplink.zf.accordion', [$link, $anchor]);
    this.$element.trigger('deeplink.zf.accordion', [$target, $anchor]);
    }
    }
    }
    @@ -317,4 +332,4 @@ Accordion.defaults = {
    // Window exports
    Foundation.plugin(Accordion, 'Accordion');

    }(jQuery);
    }(jQuery);
  4. Garrett Hyder created this gist Jun 7, 2017.
    320 changes: 320 additions & 0 deletions foundation.accordion.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,320 @@
    'use strict';

    !function($) {

    /**
    * Accordion module.
    * @module foundation.accordion
    * @requires foundation.util.keyboard
    * @requires foundation.util.motion
    */

    class Accordion {
    /**
    * Creates a new instance of an accordion.
    * @class
    * @fires Accordion#init
    * @param {jQuery} element - jQuery object to make into an accordion.
    * @param {Object} options - a plain object with settings to override the default options.
    */
    constructor(element, options) {
    this.$element = element;
    this.options = $.extend({}, Accordion.defaults, this.$element.data(), options);

    this._init();

    Foundation.registerPlugin(this, 'Accordion');
    Foundation.Keyboard.register('Accordion', {
    'ENTER': 'toggle',
    'SPACE': 'toggle',
    'ARROW_DOWN': 'next',
    'ARROW_UP': 'previous'
    });
    }

    /**
    * Initializes the accordion by animating the preset active pane(s).
    * @private
    */
    _init() {
    this.$element.attr('role', 'tablist');
    this.$tabs = this.$element.children('[data-accordion-item]');

    this.$tabs.each(function(idx, el) {
    var $el = $(el),
    $content = $el.children('[data-tab-content]'),
    id = $content[0].id || Foundation.GetYoDigits(6, 'accordion'),
    linkId = el.id || `${id}-label`;

    $el.find('a:first').attr({
    'aria-controls': id,
    'role': 'tab',
    'id': linkId,
    'aria-expanded': false,
    'aria-selected': false
    });

    $content.attr({'role': 'tabpanel', 'aria-labelledby': linkId, 'aria-hidden': true, 'id': id});
    });
    var $initActive = this.$element.find('.is-active').children('[data-tab-content]');
    this.firstTimeInit = true;
    if($initActive.length){
    this.down($initActive, this.firstTimeInit);
    this.firstTimeInit = false;
    }

    this._checkDeepLink = () => {
    var anchor = window.location.hash;
    //need a hash and a relevant anchor in this tabset
    if(anchor.length) {
    var $link = $('.accordion-title[href$="'+anchor+'"]'),
    $anchor = $(anchor);

    if ($link.length && $anchor) {
    // Close the right accordion stuff
    if (!this.options.multiExpand && !this.firstTimeInit) {
    var $activeSibling = $link.closest('[data-accordion]').find('.is-active').find('[data-tab-content]').not($anchor);
    if ($activeSibling.length) {
    this.up($activeSibling.not($anchor));
    }
    }

    if (!$link.parent('[data-accordion-item]').hasClass('is-active')) {
    this.down($anchor, this.firstTimeInit);
    this.firstTimeInit = false;
    };

    //roll up a little to show the titles
    if (this.options.deepLinkSmudge) {
    var offset = $link.closest('[data-accordion]').offset();
    $('html, body').animate({ scrollTop: offset.top }, this.options.deepLinkSmudgeDelay);
    }

    /**
    * Fires when the zplugin has deeplinked at pageload
    * @event Accordion#deeplink
    */
    this.$element.trigger('deeplink.zf.accordion', [$link, $anchor]);
    }
    }
    }

    //use browser to open a tab, if it exists in this tabset
    if (this.options.deepLink) {
    this._checkDeepLink();
    }

    this._events();
    }

    /**
    * Adds event handlers for items within the accordion.
    * @private
    */
    _events() {
    var _this = this;

    this.$tabs.each(function() {
    var $elem = $(this);
    var $tabContent = $elem.children('[data-tab-content]');
    if ($tabContent.length) {
    $elem.children('a').off('click.zf.accordion keydown.zf.accordion')
    .on('click.zf.accordion', function(e) {
    e.preventDefault();
    _this.toggle($tabContent);
    }).on('keydown.zf.accordion', function(e){
    Foundation.Keyboard.handleKey(e, 'Accordion', {
    toggle: function() {
    _this.toggle($tabContent);
    },
    next: function() {
    var $a = $elem.next().find('a').focus();
    if (!_this.options.multiExpand) {
    $a.trigger('click.zf.accordion')
    }
    },
    previous: function() {
    var $a = $elem.prev().find('a').focus();
    if (!_this.options.multiExpand) {
    $a.trigger('click.zf.accordion')
    }
    },
    handled: function() {
    e.preventDefault();
    e.stopPropagation();
    }
    });
    });
    }
    });
    if(this.options.deepLink) {
    $(window).on('popstate', this._checkDeepLink);
    }
    }

    /**
    * Toggles the selected content pane's open/close state.
    * @param {jQuery} $target - jQuery object of the pane to toggle (`.accordion-content`).
    * @function
    */
    toggle($target) {
    if($target.parent().hasClass('is-active')) {
    this.up($target);
    } else {
    this.down($target);
    }
    //either replace or update browser history
    if (this.options.deepLink) {
    var anchor = $target.prev('a').attr('href');

    if (this.options.updateHistory) {
    history.pushState({}, '', anchor);
    } else {
    history.replaceState({}, '', anchor);
    }
    }
    }

    /**
    * Opens the accordion tab defined by `$target`.
    * @param {jQuery} $target - Accordion pane to open (`.accordion-content`).
    * @param {Boolean} firstTime - flag to determine if reflow should happen.
    * @fires Accordion#down
    * @function
    */
    down($target, firstTime) {
    $target
    .attr('aria-hidden', false)
    .parent('[data-tab-content]')
    .addBack()
    .parent().addClass('is-active');

    if (!this.options.multiExpand && !firstTime) {
    var $currentActive = $target.closest('[data-accordion]').find('.is-active').find('[data-tab-content]').not($target);
    if ($currentActive.length) {
    this.up($currentActive.not($target));
    }
    }

    $target.slideDown(this.options.slideSpeed, () => {
    /**
    * Fires when the tab is done opening.
    * @event Accordion#down
    */
    this.$element.trigger('down.zf.accordion', [$target]);
    });

    $(`#${$target.attr('aria-labelledby')}`).attr({
    'aria-expanded': true,
    'aria-selected': true
    });
    }

    /**
    * Closes the tab defined by `$target`.
    * @param {jQuery} $target - Accordion tab to close (`.accordion-content`).
    * @fires Accordion#up
    * @function
    */
    up($target) {
    var $aunts = $target.parent().siblings(),
    _this = this;

    if((!this.options.allowAllClosed && !$aunts.hasClass('is-active')) || !$target.parent().hasClass('is-active')) {
    return;
    }

    // Foundation.Move(this.options.slideSpeed, $target, function(){
    $target.slideUp(_this.options.slideSpeed, function () {
    /**
    * Fires when the tab is done collapsing up.
    * @event Accordion#up
    */
    _this.$element.trigger('up.zf.accordion', [$target]);
    });
    // });

    $target.attr('aria-hidden', true)
    .parent().removeClass('is-active');

    $(`#${$target.attr('aria-labelledby')}`).attr({
    'aria-expanded': false,
    'aria-selected': false
    });
    }

    /**
    * Destroys an instance of an accordion.
    * @fires Accordion#destroyed
    * @function
    */
    destroy() {
    this.$element.find('[data-tab-content]').stop(true).slideUp(0).css('display', '');
    this.$element.find('a').off('.zf.accordion');
    if(this.options.deepLink) {
    $(window).off('popstate', this._checkDeepLink);
    }

    Foundation.unregisterPlugin(this);
    }
    }

    Accordion.defaults = {
    /**
    * Amount of time to animate the opening of an accordion pane.
    * @option
    * @type {number}
    * @default 250
    */
    slideSpeed: 250,
    /**
    * Allow the accordion to have multiple open panes.
    * @option
    * @type {boolean}
    * @default false
    */
    multiExpand: false,
    /**
    * Allow the accordion to close all panes.
    * @option
    * @type {boolean}
    * @default false
    */
    allowAllClosed: false,
    /**
    * Allows the window to scroll to content of pane specified by hash anchor
    * @option
    * @type {boolean}
    * @default false
    */
    deepLink: false,

    /**
    * Adjust the deep link scroll to make sure the top of the accordion panel is visible
    * @option
    * @type {boolean}
    * @default false
    */
    deepLinkSmudge: false,

    /**
    * Animation time (ms) for the deep link adjustment
    * @option
    * @type {number}
    * @default 300
    */
    deepLinkSmudgeDelay: 300,

    /**
    * Update the browser history with the open accordion
    * @option
    * @type {boolean}
    * @default false
    */
    updateHistory: false
    };

    // Window exports
    Foundation.plugin(Accordion, 'Accordion');

    }(jQuery);