UNPKG

4.26 kBJavaScriptView Raw
1'use strict';
2
3import $ from 'jquery';
4
5import { MediaQuery } from './foundation.util.mediaQuery';
6import { GetYoDigits } from './foundation.util.core';
7import { Plugin } from './foundation.plugin';
8
9import { DropdownMenu } from './foundation.dropdownMenu';
10import { Drilldown } from './foundation.drilldown';
11import { AccordionMenu } from './foundation.accordionMenu';
12
13let MenuPlugins = {
14 dropdown: {
15 cssClass: 'dropdown',
16 plugin: DropdownMenu
17 },
18 drilldown: {
19 cssClass: 'drilldown',
20 plugin: Drilldown
21 },
22 accordion: {
23 cssClass: 'accordion-menu',
24 plugin: AccordionMenu
25 }
26};
27
28 // import "foundation.util.triggers.js";
29
30
31/**
32 * ResponsiveMenu module.
33 * @module foundation.responsiveMenu
34 * @requires foundation.util.triggers
35 * @requires foundation.util.mediaQuery
36 */
37
38class ResponsiveMenu extends Plugin {
39 /**
40 * Creates a new instance of a responsive menu.
41 * @class
42 * @name ResponsiveMenu
43 * @fires ResponsiveMenu#init
44 * @param {jQuery} element - jQuery object to make into a dropdown menu.
45 * @param {Object} options - Overrides to the default plugin settings.
46 */
47 _setup(element, options) {
48 this.$element = $(element);
49 this.rules = this.$element.data('responsive-menu');
50 this.currentMq = null;
51 this.currentPlugin = null;
52 this.className = 'ResponsiveMenu'; // ie9 back compat
53
54 this._init();
55 this._events();
56 }
57
58 /**
59 * Initializes the Menu by parsing the classes from the 'data-ResponsiveMenu' attribute on the element.
60 * @function
61 * @private
62 */
63 _init() {
64
65 MediaQuery._init();
66 // The first time an Interchange plugin is initialized, this.rules is converted from a string of "classes" to an object of rules
67 if (typeof this.rules === 'string') {
68 let rulesTree = {};
69
70 // Parse rules from "classes" pulled from data attribute
71 let rules = this.rules.split(' ');
72
73 // Iterate through every rule found
74 for (let i = 0; i < rules.length; i++) {
75 let rule = rules[i].split('-');
76 let ruleSize = rule.length > 1 ? rule[0] : 'small';
77 let rulePlugin = rule.length > 1 ? rule[1] : rule[0];
78
79 if (MenuPlugins[rulePlugin] !== null) {
80 rulesTree[ruleSize] = MenuPlugins[rulePlugin];
81 }
82 }
83
84 this.rules = rulesTree;
85 }
86
87 if (!$.isEmptyObject(this.rules)) {
88 this._checkMediaQueries();
89 }
90 // Add data-mutate since children may need it.
91 this.$element.attr('data-mutate', (this.$element.attr('data-mutate') || GetYoDigits(6, 'responsive-menu')));
92 }
93
94 /**
95 * Initializes events for the Menu.
96 * @function
97 * @private
98 */
99 _events() {
100 var _this = this;
101
102 $(window).on('changed.zf.mediaquery', function() {
103 _this._checkMediaQueries();
104 });
105 // $(window).on('resize.zf.ResponsiveMenu', function() {
106 // _this._checkMediaQueries();
107 // });
108 }
109
110 /**
111 * 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.
112 * @function
113 * @private
114 */
115 _checkMediaQueries() {
116 var matchedMq, _this = this;
117 // Iterate through each rule and find the last matching rule
118 $.each(this.rules, function(key) {
119 if (MediaQuery.atLeast(key)) {
120 matchedMq = key;
121 }
122 });
123
124 // No match? No dice
125 if (!matchedMq) return;
126
127 // Plugin already initialized? We good
128 if (this.currentPlugin instanceof this.rules[matchedMq].plugin) return;
129
130 // Remove existing plugin-specific CSS classes
131 $.each(MenuPlugins, function(key, value) {
132 _this.$element.removeClass(value.cssClass);
133 });
134
135 // Add the CSS class for the new plugin
136 this.$element.addClass(this.rules[matchedMq].cssClass);
137
138 // Create an instance of the new plugin
139 if (this.currentPlugin) this.currentPlugin.destroy();
140 this.currentPlugin = new this.rules[matchedMq].plugin(this.$element, {});
141 }
142
143 /**
144 * Destroys the instance of the current plugin on this element, as well as the window resize handler that switches the plugins out.
145 * @function
146 */
147 _destroy() {
148 this.currentPlugin.destroy();
149 $(window).off('.zf.ResponsiveMenu');
150 }
151}
152
153ResponsiveMenu.defaults = {};
154
155export {ResponsiveMenu};