PHP Classes

File: engine/modules/contrib/foundation/js/plugins/foundation.dropdownMenu.js

Recommend this page to a friend!
  Classes of Aldo Tripiciano   Quanta CMS   engine/modules/contrib/foundation/js/plugins/foundation.dropdownMenu.js   Download  
File: engine/modules/contrib/foundation/js/plugins/foundation.dropdownMenu.js
Role: Auxiliary data
Content type: text/plain
Description: Auxiliary data
Class: Quanta CMS
Manage content that works without a database
Author: By
Last change:
Date: 5 years ago
Size: 16,002 bytes
 

Contents

Class file image Download
'use strict'; 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"); } } !function ($) { /** * DropdownMenu module. * @module foundation.dropdown-menu * @requires foundation.util.keyboard * @requires foundation.util.box * @requires foundation.util.nest */ var DropdownMenu = function () { /** * Creates a new instance of DropdownMenu. * @class * @fires DropdownMenu#init * @param {jQuery} element - jQuery object to make into a dropdown menu. * @param {Object} options - Overrides to the default plugin settings. */ function DropdownMenu(element, options) { _classCallCheck(this, DropdownMenu); this.$element = element; this.options = $.extend({}, DropdownMenu.defaults, this.$element.data(), options); Foundation.Nest.Feather(this.$element, 'dropdown'); this._init(); Foundation.registerPlugin(this, 'DropdownMenu'); Foundation.Keyboard.register('DropdownMenu', { 'ENTER': 'open', 'SPACE': 'open', 'ARROW_RIGHT': 'next', 'ARROW_UP': 'up', 'ARROW_DOWN': 'down', 'ARROW_LEFT': 'previous', 'ESCAPE': 'close' }); } /** * Initializes the plugin, and calls _prepareMenu * @private * @function */ _createClass(DropdownMenu, [{ key: '_init', value: function _init() { var subs = this.$element.find('li.is-dropdown-submenu-parent'); this.$element.children('.is-dropdown-submenu-parent').children('.is-dropdown-submenu').addClass('first-sub'); this.$menuItems = this.$element.find('[role="menuitem"]'); this.$tabs = this.$element.children('[role="menuitem"]'); this.$tabs.find('ul.is-dropdown-submenu').addClass(this.options.verticalClass); if (this.$element.hasClass(this.options.rightClass) || this.options.alignment === 'right' || Foundation.rtl() || this.$element.parents('.top-bar-right').is('*')) { this.options.alignment = 'right'; subs.addClass('opens-left'); } else { subs.addClass('opens-right'); } this.changed = false; this._events(); } }, { key: '_isVertical', value: function _isVertical() { return this.$tabs.css('display') === 'block'; } /** * Adds event listeners to elements within the menu * @private * @function */ }, { key: '_events', value: function _events() { var _this = this, hasTouch = 'ontouchstart' in window || typeof window.ontouchstart !== 'undefined', parClass = 'is-dropdown-submenu-parent'; // used for onClick and in the keyboard handlers var handleClickFn = function (e) { var $elem = $(e.target).parentsUntil('ul', '.' + parClass), hasSub = $elem.hasClass(parClass), hasClicked = $elem.attr('data-is-click') === 'true', $sub = $elem.children('.is-dropdown-submenu'); if (hasSub) { if (hasClicked) { if (!_this.options.closeOnClick || !_this.options.clickOpen && !hasTouch || _this.options.forceFollow && hasTouch) { return; } else { e.stopImmediatePropagation(); e.preventDefault(); _this._hide($elem); } } else { e.preventDefault(); e.stopImmediatePropagation(); _this._show($sub); $elem.add($elem.parentsUntil(_this.$element, '.' + parClass)).attr('data-is-click', true); } } }; if (this.options.clickOpen || hasTouch) { this.$menuItems.on('click.zf.dropdownmenu touchstart.zf.dropdownmenu', handleClickFn); } // Handle Leaf element Clicks if (_this.options.closeOnClickInside) { this.$menuItems.on('click.zf.dropdownmenu touchend.zf.dropdownmenu', function (e) { var $elem = $(this), hasSub = $elem.hasClass(parClass); if (!hasSub) { _this._hide(); } }); } if (!this.options.disableHover) { this.$menuItems.on('mouseenter.zf.dropdownmenu', function (e) { var $elem = $(this), hasSub = $elem.hasClass(parClass); if (hasSub) { clearTimeout($elem.data('_delay')); $elem.data('_delay', setTimeout(function () { _this._show($elem.children('.is-dropdown-submenu')); }, _this.options.hoverDelay)); } }).on('mouseleave.zf.dropdownmenu', function (e) { var $elem = $(this), hasSub = $elem.hasClass(parClass); if (hasSub && _this.options.autoclose) { if ($elem.attr('data-is-click') === 'true' && _this.options.clickOpen) { return false; } clearTimeout($elem.data('_delay')); $elem.data('_delay', setTimeout(function () { _this._hide($elem); }, _this.options.closingTime)); } }); } this.$menuItems.on('keydown.zf.dropdownmenu', function (e) { var $element = $(e.target).parentsUntil('ul', '[role="menuitem"]'), isTab = _this.$tabs.index($element) > -1, $elements = isTab ? _this.$tabs : $element.siblings('li').add($element), $prevElement, $nextElement; $elements.each(function (i) { if ($(this).is($element)) { $prevElement = $elements.eq(i - 1); $nextElement = $elements.eq(i + 1); return; } }); var nextSibling = function () { if (!$element.is(':last-child')) { $nextElement.children('a:first').focus(); e.preventDefault(); } }, prevSibling = function () { $prevElement.children('a:first').focus(); e.preventDefault(); }, openSub = function () { var $sub = $element.children('ul.is-dropdown-submenu'); if ($sub.length) { _this._show($sub); $element.find('li > a:first').focus(); e.preventDefault(); } else { return; } }, closeSub = function () { //if ($element.is(':first-child')) { var close = $element.parent('ul').parent('li'); close.children('a:first').focus(); _this._hide(close); e.preventDefault(); //} }; var functions = { open: openSub, close: function () { _this._hide(_this.$element); _this.$menuItems.find('a:first').focus(); // focus to first element e.preventDefault(); }, handled: function () { e.stopImmediatePropagation(); } }; if (isTab) { if (_this._isVertical()) { // vertical menu if (Foundation.rtl()) { // right aligned $.extend(functions, { down: nextSibling, up: prevSibling, next: closeSub, previous: openSub }); } else { // left aligned $.extend(functions, { down: nextSibling, up: prevSibling, next: openSub, previous: closeSub }); } } else { // horizontal menu if (Foundation.rtl()) { // right aligned $.extend(functions, { next: prevSibling, previous: nextSibling, down: openSub, up: closeSub }); } else { // left aligned $.extend(functions, { next: nextSibling, previous: prevSibling, down: openSub, up: closeSub }); } } } else { // not tabs -> one sub if (Foundation.rtl()) { // right aligned $.extend(functions, { next: closeSub, previous: openSub, down: nextSibling, up: prevSibling }); } else { // left aligned $.extend(functions, { next: openSub, previous: closeSub, down: nextSibling, up: prevSibling }); } } Foundation.Keyboard.handleKey(e, 'DropdownMenu', functions); }); } /** * Adds an event handler to the body to close any dropdowns on a click. * @function * @private */ }, { key: '_addBodyHandler', value: function _addBodyHandler() { var $body = $(document.body), _this = this; $body.off('mouseup.zf.dropdownmenu touchend.zf.dropdownmenu').on('mouseup.zf.dropdownmenu touchend.zf.dropdownmenu', function (e) { var $link = _this.$element.find(e.target); if ($link.length) { return; } _this._hide(); $body.off('mouseup.zf.dropdownmenu touchend.zf.dropdownmenu'); }); } /** * Opens a dropdown pane, and checks for collisions first. * @param {jQuery} $sub - ul element that is a submenu to show * @function * @private * @fires DropdownMenu#show */ }, { key: '_show', value: function _show($sub) { var idx = this.$tabs.index(this.$tabs.filter(function (i, el) { return $(el).find($sub).length > 0; })); var $sibs = $sub.parent('li.is-dropdown-submenu-parent').siblings('li.is-dropdown-submenu-parent'); this._hide($sibs, idx); $sub.css('visibility', 'hidden').addClass('js-dropdown-active').parent('li.is-dropdown-submenu-parent').addClass('is-active'); var clear = Foundation.Box.ImNotTouchingYou($sub, null, true); if (!clear) { var oldClass = this.options.alignment === 'left' ? '-right' : '-left', $parentLi = $sub.parent('.is-dropdown-submenu-parent'); $parentLi.removeClass('opens' + oldClass).addClass('opens-' + this.options.alignment); clear = Foundation.Box.ImNotTouchingYou($sub, null, true); if (!clear) { $parentLi.removeClass('opens-' + this.options.alignment).addClass('opens-inner'); } this.changed = true; } $sub.css('visibility', ''); if (this.options.closeOnClick) { this._addBodyHandler(); } /** * Fires when the new dropdown pane is visible. * @event DropdownMenu#show */ this.$element.trigger('show.zf.dropdownmenu', [$sub]); } /** * Hides a single, currently open dropdown pane, if passed a parameter, otherwise, hides everything. * @function * @param {jQuery} $elem - element with a submenu to hide * @param {Number} idx - index of the $tabs collection to hide * @private */ }, { key: '_hide', value: function _hide($elem, idx) { var $toClose; if ($elem && $elem.length) { $toClose = $elem; } else if (idx !== undefined) { $toClose = this.$tabs.not(function (i, el) { return i === idx; }); } else { $toClose = this.$element; } var somethingToClose = $toClose.hasClass('is-active') || $toClose.find('.is-active').length > 0; if (somethingToClose) { $toClose.find('li.is-active').add($toClose).attr({ 'data-is-click': false }).removeClass('is-active'); $toClose.find('ul.js-dropdown-active').removeClass('js-dropdown-active'); if (this.changed || $toClose.find('opens-inner').length) { var oldClass = this.options.alignment === 'left' ? 'right' : 'left'; $toClose.find('li.is-dropdown-submenu-parent').add($toClose).removeClass('opens-inner opens-' + this.options.alignment).addClass('opens-' + oldClass); this.changed = false; } /** * Fires when the open menus are closed. * @event DropdownMenu#hide */ this.$element.trigger('hide.zf.dropdownmenu', [$toClose]); } } /** * Destroys the plugin. * @function */ }, { key: 'destroy', value: function destroy() { this.$menuItems.off('.zf.dropdownmenu').removeAttr('data-is-click').removeClass('is-right-arrow is-left-arrow is-down-arrow opens-right opens-left opens-inner'); $(document.body).off('.zf.dropdownmenu'); Foundation.Nest.Burn(this.$element, 'dropdown'); Foundation.unregisterPlugin(this); } }]); return DropdownMenu; }(); /** * Default settings for plugin */ DropdownMenu.defaults = { /** * Disallows hover events from opening submenus * @option * @example false */ disableHover: false, /** * Allow a submenu to automatically close on a mouseleave event, if not clicked open. * @option * @example true */ autoclose: true, /** * Amount of time to delay opening a submenu on hover event. * @option * @example 50 */ hoverDelay: 50, /** * Allow a submenu to open/remain open on parent click event. Allows cursor to move away from menu. * @option * @example true */ clickOpen: false, /** * Amount of time to delay closing a submenu on a mouseleave event. * @option * @example 500 */ closingTime: 500, /** * Position of the menu relative to what direction the submenus should open. Handled by JS. * @option * @example 'left' */ alignment: 'left', /** * Allow clicks on the body to close any open submenus. * @option * @example true */ closeOnClick: true, /** * Allow clicks on leaf anchor links to close any open submenus. * @option * @example true */ closeOnClickInside: true, /** * Class applied to vertical oriented menus, Foundation default is `vertical`. Update this if using your own class. * @option * @example 'vertical' */ verticalClass: 'vertical', /** * Class applied to right-side oriented menus, Foundation default is `align-right`. Update this if using your own class. * @option * @example 'align-right' */ rightClass: 'align-right', /** * Boolean to force overide the clicking of links to perform default action, on second touch event for mobile. * @option * @example false */ forceFollow: true }; // Window exports Foundation.plugin(DropdownMenu, 'DropdownMenu'); }(jQuery);