'use strict'; import $ from 'jquery'; import { MediaQuery } from './foundation.util.mediaQuery'; import { GetYoDigits } from './foundation.core.utils'; import { Plugin } from './foundation.core.plugin'; import { DropdownMenu } from './foundation.dropdownMenu'; import { Drilldown } from './foundation.drilldown'; import { AccordionMenu } from './foundation.accordionMenu'; let MenuPlugins = { dropdown: { cssClass: 'dropdown', plugin: DropdownMenu }, drilldown: { cssClass: 'drilldown', plugin: Drilldown }, accordion: { cssClass: 'accordion-menu', plugin: AccordionMenu } }; // import "foundation.util.triggers.js"; /** * ResponsiveMenu module. * @module foundation.responsiveMenu * @requires foundation.util.triggers * @requires foundation.util.mediaQuery */ class ResponsiveMenu extends Plugin { /** * Creates a new instance of a responsive menu. * @class * @name ResponsiveMenu * @fires ResponsiveMenu#init * @param {jQuery} element - jQuery object to make into a dropdown menu. * @param {Object} options - Overrides to the default plugin settings. */ _setup(element, options) { this.$element = $(element); this.rules = this.$element.data('responsive-menu'); this.currentMq = null; this.currentPlugin = null; this.className = 'ResponsiveMenu'; // ie9 back compat this._init(); this._events(); } /** * Initializes the Menu by parsing the classes from the 'data-ResponsiveMenu' attribute on the element. * @function * @private */ _init() { MediaQuery._init(); // The first time an Interchange plugin is initialized, this.rules is converted from a string of "classes" to an object of rules if (typeof this.rules === 'string') { let rulesTree = {}; // Parse rules from "classes" pulled from data attribute let rules = this.rules.split(' '); // Iterate through every rule found for (let i = 0; i < rules.length; i++) { let rule = rules[i].split('-'); let ruleSize = rule.length > 1 ? rule[0] : 'small'; let rulePlugin = rule.length > 1 ? rule[1] : rule[0]; if (MenuPlugins[rulePlugin] !== null) { rulesTree[ruleSize] = MenuPlugins[rulePlugin]; } } this.rules = rulesTree; } if (!$.isEmptyObject(this.rules)) { this._checkMediaQueries(); } // Add data-mutate since children may need it. this.$element.attr('data-mutate', (this.$element.attr('data-mutate') || GetYoDigits(6, 'responsive-menu'))); } /** * Initializes events for the Menu. * @function * @private */ _events() { var _this = this; $(window).on('changed.zf.mediaquery', function() { _this._checkMediaQueries(); }); // $(window).on('resize.zf.ResponsiveMenu', function() { // _this._checkMediaQueries(); // }); } /** * Checks the current screen width against available media queries. If the media query has changed, and the plugin needed has changed, the plugins will swap out. * @function * @private */ _checkMediaQueries() { var matchedMq, _this = this; // Iterate through each rule and find the last matching rule $.each(this.rules, function(key) { if (MediaQuery.atLeast(key)) { matchedMq = key; } }); // No match? No dice if (!matchedMq) return; // Plugin already initialized? We good if (this.currentPlugin instanceof this.rules[matchedMq].plugin) return; // Remove existing plugin-specific CSS classes $.each(MenuPlugins, function(key, value) { _this.$element.removeClass(value.cssClass); }); // Add the CSS class for the new plugin this.$element.addClass(this.rules[matchedMq].cssClass); // Create an instance of the new plugin if (this.currentPlugin) this.currentPlugin.destroy(); this.currentPlugin = new this.rules[matchedMq].plugin(this.$element, {}); } /** * Destroys the instance of the current plugin on this element, as well as the window resize handler that switches the plugins out. * @function */ _destroy() { this.currentPlugin.destroy(); $(window).off('.zf.ResponsiveMenu'); } } ResponsiveMenu.defaults = {}; export {ResponsiveMenu};