123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- 'use strict';
- import $ from 'jquery';
- import { Motion } from './foundation.util.motion';
- import { Plugin } from './foundation.core.plugin';
- import { RegExpEscape } from './foundation.core.utils';
- import { Triggers } from './foundation.util.triggers';
- /**
- * Toggler module.
- * @module foundation.toggler
- * @requires foundation.util.motion
- * @requires foundation.util.triggers
- */
- class Toggler extends Plugin {
- /**
- * Creates a new instance of Toggler.
- * @class
- * @name Toggler
- * @fires Toggler#init
- * @param {Object} element - jQuery object to add the trigger to.
- * @param {Object} options - Overrides to the default plugin settings.
- */
- _setup(element, options) {
- this.$element = element;
- this.options = $.extend({}, Toggler.defaults, element.data(), options);
- this.className = '';
- this.className = 'Toggler'; // ie9 back compat
- // Triggers init is idempotent, just need to make sure it is initialized
- Triggers.init($);
- this._init();
- this._events();
- }
- /**
- * Initializes the Toggler plugin by parsing the toggle class from data-toggler, or animation classes from data-animate.
- * @function
- * @private
- */
- _init() {
- var input;
- // Parse animation classes if they were set
- if (this.options.animate) {
- input = this.options.animate.split(' ');
- this.animationIn = input[0];
- this.animationOut = input[1] || null;
- }
- // Otherwise, parse toggle class
- else {
- input = this.$element.data('toggler');
- // Allow for a . at the beginning of the string
- this.className = input[0] === '.' ? input.slice(1) : input;
- }
- // Add ARIA attributes to triggers:
- var id = this.$element[0].id,
- $triggers = $(`[data-open~="${id}"], [data-close~="${id}"], [data-toggle~="${id}"]`);
- // - aria-expanded: according to the element visibility.
- $triggers.attr('aria-expanded', !this.$element.is(':hidden'));
- // - aria-controls: adding the element id to it if not already in it.
- $triggers.each((index, trigger) => {
- const $trigger = $(trigger);
- const controls = $trigger.attr('aria-controls') || '';
- const containsId = new RegExp(`\\b${RegExpEscape(id)}\\b`).test(controls);
- if (!containsId) $trigger.attr('aria-controls', controls ? `${controls} ${id}` : id);
- });
- }
- /**
- * Initializes events for the toggle trigger.
- * @function
- * @private
- */
- _events() {
- this.$element.off('toggle.zf.trigger').on('toggle.zf.trigger', this.toggle.bind(this));
- }
- /**
- * Toggles the target class on the target element. An event is fired from the original trigger depending on if the resultant state was "on" or "off".
- * @function
- * @fires Toggler#on
- * @fires Toggler#off
- */
- toggle() {
- this[ this.options.animate ? '_toggleAnimate' : '_toggleClass']();
- }
- _toggleClass() {
- this.$element.toggleClass(this.className);
- var isOn = this.$element.hasClass(this.className);
- if (isOn) {
- /**
- * Fires if the target element has the class after a toggle.
- * @event Toggler#on
- */
- this.$element.trigger('on.zf.toggler');
- }
- else {
- /**
- * Fires if the target element does not have the class after a toggle.
- * @event Toggler#off
- */
- this.$element.trigger('off.zf.toggler');
- }
- this._updateARIA(isOn);
- this.$element.find('[data-mutate]').trigger('mutateme.zf.trigger');
- }
- _toggleAnimate() {
- var _this = this;
- if (this.$element.is(':hidden')) {
- Motion.animateIn(this.$element, this.animationIn, function() {
- _this._updateARIA(true);
- this.trigger('on.zf.toggler');
- this.find('[data-mutate]').trigger('mutateme.zf.trigger');
- });
- }
- else {
- Motion.animateOut(this.$element, this.animationOut, function() {
- _this._updateARIA(false);
- this.trigger('off.zf.toggler');
- this.find('[data-mutate]').trigger('mutateme.zf.trigger');
- });
- }
- }
- _updateARIA(isOn) {
- var id = this.$element[0].id;
- $(`[data-open="${id}"], [data-close="${id}"], [data-toggle="${id}"]`)
- .attr({
- 'aria-expanded': isOn ? true : false
- });
- }
- /**
- * Destroys the instance of Toggler on the element.
- * @function
- */
- _destroy() {
- this.$element.off('.zf.toggler');
- }
- }
- Toggler.defaults = {
- /**
- * Tells the plugin if the element should animated when toggled.
- * @option
- * @type {boolean}
- * @default false
- */
- animate: false
- };
- export {Toggler};
|