'use strict'; // https://www.jqueryscript.net/demo/Multi-level-Side-Menu-Plugin-jQuery/# 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"); } } // TODO: make this library agnostic // TODO: document the events (function ($) { var PLUGIN_NAME = 'slideMenu'; var DEFAULT_OPTIONS = { position: 'right', showBackLink: true, keycodeOpen: null, keycodeClose: 27, //esc submenuLinkBefore: '', submenuLinkAfter: '', backLinkBefore: '', backLinkAfter: '' }; var SlideMenu = function () { function SlideMenu(options) { _classCallCheck(this, SlideMenu); this.options = options; this._menu = options.elem; // Add wrapper this._menu.find('ul:first').wrap('
'); this._anchors = this._menu.find('a'); this._slider = this._menu.find('.slider:first'); this._level = 0; this._isOpen = false; this._isAnimating = false; this._hasMenu = this._anchors.length > 0; this._lastAction = null; this._setupEventHandlers(); this._setupMenu(); if (this._hasMenu) this._setupSubmenus(); } /** * Toggle the menu * @param {boolean|null} open * @param {boolean} animate */ _createClass(SlideMenu, [{ key: 'toggle', value: function toggle() { var open = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; var animate = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; var offset = void 0; if (open === null) { if (this._isOpen) { this.close(); } else { this.open(); } return; } else if (open) { offset = 0; this._isOpen = true; } else { offset = this.options.position === 'left' ? '-100%' : '100%'; this._isOpen = false; } this._triggerEvent(); if (animate) this._triggerAnimation(this._menu, offset);else { this._pauseAnimations(this._triggerAnimation.bind(this, this._menu, offset)); this._isAnimating = false; } } /** * Open the menu * @param {boolean} animate Use CSS transitions */ }, { key: 'open', value: function open() { var animate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; $('.slide-darker').show(); $('body').css('overflow', 'hidden'); this._lastAction = 'open'; this.toggle(true, animate); } /** * Close the menu * @param {boolean} animate Use CSS transitions */ }, { key: 'close', value: function close() { var animate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; $('.slide-darker').hide(); $('body').css('overflow', 'auto'); this._lastAction = 'close'; this.toggle(false, animate); } /** * Navigate one menu hierarchy back if possible */ }, { key: 'back', value: function back() { this._lastAction = 'back'; this._navigate(null, -1); } /** * Navigate to a specific link on any level (useful to open the correct hierarchy directly) * @param {string|object} target A string selector a plain DOM object or a jQuery instance */ }, { key: 'navigateTo', value: function navigateTo(target) { var _this = this; target = this._menu.find($(target)).first(); if (!target.length) return false; var parents = target.parents('ul'); var level = parents.length - 1; if (level === 0) return false; this._pauseAnimations(function () { _this._level = level; parents.show().first().addClass('active'); _this._triggerAnimation(_this._slider, -_this._level * 100); }); } /** * Set up all event handlers * @private */ }, { key: '_setupEventHandlers', value: function _setupEventHandlers() { var _this2 = this; if (this._hasMenu) { this._anchors.click(function (event) { var anchor = $(event.target).is('a') ? $(event.target) : $(event.target).parents('a:first'); _this2._navigate(anchor); }); } $(this._menu.add(this._slider)).on('transitionend msTransitionEnd', function () { _this2._isAnimating = false; _this2._triggerEvent(true); }); $(document).keydown(function (e) { switch (e.which) { case _this2.options.keycodeClose: _this2.close(); break; case _this2.options.keycodeOpen: _this2.open(); break; default: return; } e.preventDefault(); }); this._menu.on('sm.back-after', function () { var lastActiveUl = 'ul ' + '.active '.repeat(_this2._level + 1); _this2._menu.find(lastActiveUl).removeClass('active').hide(); }); } /** * Trigger a custom event to support callbacks * @param {boolean} afterAnimation Mark this event as `before` or `after` callback * @private */ }, { key: '_triggerEvent', value: function _triggerEvent() { var afterAnimation = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; var eventName = 'sm.' + this._lastAction; if (afterAnimation) eventName += '-after'; this._menu.trigger(eventName); } /** * Navigate the _menu - that is slide it one step left or right * @param {jQuery} anchor The clicked anchor or button element * @param {int} dir Navigation direction: 1 = forward, 0 = backwards * @private */ }, { key: '_navigate', value: function _navigate(anchor) { var dir = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; // Abort if an animation is still running if (this._isAnimating) { return; } var offset = (this._level + dir) * -100; if (dir > 0) { if (!anchor.next('ul').length) return; anchor.next('ul').addClass('active').show(); } else if (this._level === 0) { return; } this._lastAction = dir > 0 ? 'forward' : 'back'; this._level = this._level + dir; this._triggerAnimation(this._slider, offset); } /** * Start the animation (the CSS transition) * @param elem * @param offset * @private */ }, { key: '_triggerAnimation', value: function _triggerAnimation(elem, offset) { this._triggerEvent(); if (!(String(offset).indexOf('%') !== -1)) offset += '%'; elem.css('transform', 'translateX(' + offset + ')'); this._isAnimating = true; } /** * Initialize the menu * @private */ }, { key: '_setupMenu', value: function _setupMenu() { var _this3 = this; this._pauseAnimations(function () { switch (_this3.options.position) { case 'left': _this3._menu.css({ left: 0, right: 'auto', transform: 'translateX(-100%)' }); break; default: _this3._menu.css({ left: 'auto', right: 0 }); break; } _this3._menu.show(); }); } /** * Pause the CSS transitions, to apply CSS changes directly without an animation * @param work * @private */ }, { key: '_pauseAnimations', value: function _pauseAnimations(work) { this._menu.addClass('no-transition'); work(); this._menu[0].offsetHeight; // trigger a reflow, flushing the CSS changes this._menu.removeClass('no-transition'); } /** * Enhance the markup of menu items which contain a submenu * @private */ }, { key: '_setupSubmenus', value: function _setupSubmenus() { var _this4 = this; this._anchors.each(function (i, anchor) { anchor = $(anchor); if (anchor.next('ul').length) { // prevent default behaviour (use link just to navigate) anchor.click(function (ev) { ev.preventDefault(); }); // add `before` and `after` text var anchorTitle = anchor.text(); anchor.html(_this4.options.submenuLinkBefore + anchorTitle + _this4.options.submenuLinkAfter); // add a back button if (_this4.options.showBackLink) { var backLink = $('' + anchorTitle + ''); backLink.html(_this4.options.backLinkBefore + backLink.text() + _this4.options.backLinkAfter); anchor.next('ul').prepend($('
  • ').append(backLink)); } } }); } }]); return SlideMenu; }(); // Link control buttons with the API $('body').on('click', '.slide-menu-control', function (e) { var menu = void 0; var target = $(this).data('target'); $(this).toggleClass('collapsed'); if (!target || target === 'this') { menu = $(this).parents('.slide-menu:first'); } else { menu = $('#' + target); } if (!menu.length) return; var instance = menu.data(PLUGIN_NAME); var action = $(this).data('action'); if (instance && typeof instance[action] === 'function') { instance[action](); } return false; }); // Register the jQuery plugin $.fn[PLUGIN_NAME] = function (options) { if (!$(this).length) { console.warn('Slide Menu: Unable to find menu DOM element. Maybe a typo?'); return; } options = $.extend({}, DEFAULT_OPTIONS, options); options.elem = $(this); var instance = new SlideMenu(options); $(this).data(PLUGIN_NAME, instance); return instance; }; })(jQuery);