metisMenu.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. /*!
  2. * metismenu https://github.com/onokumus/metismenu#readme
  3. * A jQuery menu plugin
  4. * @version 3.0.6
  5. * @author Osman Nuri Okumus <onokumus@gmail.com> (https://github.com/onokumus)
  6. * @license: MIT
  7. */
  8. (function (global, factory) {
  9. typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery')) :
  10. typeof define === 'function' && define.amd ? define(['jquery'], factory) :
  11. (global = global || self, global.metisMenu = factory(global.jQuery));
  12. }(this, (function ($) { 'use strict';
  13. $ = $ && Object.prototype.hasOwnProperty.call($, 'default') ? $['default'] : $;
  14. function _extends() {
  15. _extends = Object.assign || function (target) {
  16. for (var i = 1; i < arguments.length; i++) {
  17. var source = arguments[i];
  18. for (var key in source) {
  19. if (Object.prototype.hasOwnProperty.call(source, key)) {
  20. target[key] = source[key];
  21. }
  22. }
  23. }
  24. return target;
  25. };
  26. return _extends.apply(this, arguments);
  27. }
  28. var Util = function ($) {
  29. // eslint-disable-line no-shadow
  30. var TRANSITION_END = 'transitionend';
  31. var Util = {
  32. // eslint-disable-line no-shadow
  33. TRANSITION_END: 'mmTransitionEnd',
  34. triggerTransitionEnd: function triggerTransitionEnd(element) {
  35. $(element).trigger(TRANSITION_END);
  36. },
  37. supportsTransitionEnd: function supportsTransitionEnd() {
  38. return Boolean(TRANSITION_END);
  39. }
  40. };
  41. function getSpecialTransitionEndEvent() {
  42. return {
  43. bindType: TRANSITION_END,
  44. delegateType: TRANSITION_END,
  45. handle: function handle(event) {
  46. if ($(event.target).is(this)) {
  47. return event.handleObj.handler.apply(this, arguments); // eslint-disable-line prefer-rest-params
  48. }
  49. return undefined;
  50. }
  51. };
  52. }
  53. function transitionEndEmulator(duration) {
  54. var _this = this;
  55. var called = false;
  56. $(this).one(Util.TRANSITION_END, function () {
  57. called = true;
  58. });
  59. setTimeout(function () {
  60. if (!called) {
  61. Util.triggerTransitionEnd(_this);
  62. }
  63. }, duration);
  64. return this;
  65. }
  66. function setTransitionEndSupport() {
  67. $.fn.mmEmulateTransitionEnd = transitionEndEmulator; // eslint-disable-line no-param-reassign
  68. // eslint-disable-next-line no-param-reassign
  69. $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent();
  70. }
  71. setTransitionEndSupport();
  72. return Util;
  73. }($);
  74. var NAME = 'metisMenu';
  75. var DATA_KEY = 'metisMenu';
  76. var EVENT_KEY = "." + DATA_KEY;
  77. var DATA_API_KEY = '.data-api';
  78. var JQUERY_NO_CONFLICT = $.fn[NAME];
  79. var TRANSITION_DURATION = 350;
  80. var Default = {
  81. toggle: true,
  82. preventDefault: true,
  83. triggerElement: 'a',
  84. parentTrigger: 'li',
  85. subMenu: 'ul'
  86. };
  87. var Event = {
  88. SHOW: "show" + EVENT_KEY,
  89. SHOWN: "shown" + EVENT_KEY,
  90. HIDE: "hide" + EVENT_KEY,
  91. HIDDEN: "hidden" + EVENT_KEY,
  92. CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY
  93. };
  94. var ClassName = {
  95. METIS: 'metismenu',
  96. ACTIVE: 'mm-active',
  97. SHOW: 'mm-show',
  98. COLLAPSE: 'mm-collapse',
  99. COLLAPSING: 'mm-collapsing',
  100. COLLAPSED: 'mm-collapsed'
  101. };
  102. var MetisMenu = /*#__PURE__*/function () {
  103. // eslint-disable-line no-shadow
  104. function MetisMenu(element, config) {
  105. this.element = element;
  106. this.config = _extends({}, Default, {}, config);
  107. this.transitioning = null;
  108. this.init();
  109. }
  110. var _proto = MetisMenu.prototype;
  111. _proto.init = function init() {
  112. var self = this;
  113. var conf = this.config;
  114. var el = $(this.element);
  115. el.addClass(ClassName.METIS); // add metismenu class to element
  116. el.find(conf.parentTrigger + "." + ClassName.ACTIVE).children(conf.triggerElement).attr('aria-expanded', 'true'); // add attribute aria-expanded=true the trigger element
  117. el.find(conf.parentTrigger + "." + ClassName.ACTIVE).parents(conf.parentTrigger).addClass(ClassName.ACTIVE);
  118. el.find(conf.parentTrigger + "." + ClassName.ACTIVE).parents(conf.parentTrigger).children(conf.triggerElement).attr('aria-expanded', 'true'); // add attribute aria-expanded=true the triggers of all parents
  119. el.find(conf.parentTrigger + "." + ClassName.ACTIVE).has(conf.subMenu).children(conf.subMenu).addClass(ClassName.COLLAPSE + " " + ClassName.SHOW);
  120. el.find(conf.parentTrigger).not("." + ClassName.ACTIVE).has(conf.subMenu).children(conf.subMenu).addClass(ClassName.COLLAPSE);
  121. el.find(conf.parentTrigger) // .has(conf.subMenu)
  122. .children(conf.triggerElement).on(Event.CLICK_DATA_API, function (e) {
  123. // eslint-disable-line func-names
  124. var eTar = $(this);
  125. if (eTar.attr('aria-disabled') === 'true') {
  126. return;
  127. }
  128. if (conf.preventDefault && eTar.attr('href') === '#') {
  129. e.preventDefault();
  130. }
  131. var paRent = eTar.parent(conf.parentTrigger);
  132. var sibLi = paRent.siblings(conf.parentTrigger);
  133. var sibTrigger = sibLi.children(conf.triggerElement);
  134. if (paRent.hasClass(ClassName.ACTIVE)) {
  135. eTar.attr('aria-expanded', 'false');
  136. self.removeActive(paRent);
  137. } else {
  138. eTar.attr('aria-expanded', 'true');
  139. self.setActive(paRent);
  140. if (conf.toggle) {
  141. self.removeActive(sibLi);
  142. sibTrigger.attr('aria-expanded', 'false');
  143. }
  144. }
  145. if (conf.onTransitionStart) {
  146. conf.onTransitionStart(e);
  147. }
  148. });
  149. };
  150. _proto.setActive = function setActive(li) {
  151. $(li).addClass(ClassName.ACTIVE);
  152. var ul = $(li).children(this.config.subMenu);
  153. if (ul.length > 0 && !ul.hasClass(ClassName.SHOW)) {
  154. this.show(ul);
  155. }
  156. };
  157. _proto.removeActive = function removeActive(li) {
  158. $(li).removeClass(ClassName.ACTIVE);
  159. var ul = $(li).children(this.config.subMenu + "." + ClassName.SHOW);
  160. if (ul.length > 0) {
  161. this.hide(ul);
  162. }
  163. };
  164. _proto.show = function show(element) {
  165. var _this = this;
  166. if (this.transitioning || $(element).hasClass(ClassName.COLLAPSING)) {
  167. return;
  168. }
  169. var elem = $(element);
  170. var startEvent = $.Event(Event.SHOW);
  171. elem.trigger(startEvent);
  172. if (startEvent.isDefaultPrevented()) {
  173. return;
  174. }
  175. elem.parent(this.config.parentTrigger).addClass(ClassName.ACTIVE);
  176. if (this.config.toggle) {
  177. var toggleElem = elem.parent(this.config.parentTrigger).siblings().children(this.config.subMenu + "." + ClassName.SHOW);
  178. this.hide(toggleElem);
  179. }
  180. elem.removeClass(ClassName.COLLAPSE).addClass(ClassName.COLLAPSING).height(0);
  181. this.setTransitioning(true);
  182. var complete = function complete() {
  183. // check if disposed
  184. if (!_this.config || !_this.element) {
  185. return;
  186. }
  187. elem.removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE + " " + ClassName.SHOW).height('');
  188. _this.setTransitioning(false);
  189. elem.trigger(Event.SHOWN);
  190. };
  191. elem.height(element[0].scrollHeight).one(Util.TRANSITION_END, complete).mmEmulateTransitionEnd(TRANSITION_DURATION);
  192. };
  193. _proto.hide = function hide(element) {
  194. var _this2 = this;
  195. if (this.transitioning || !$(element).hasClass(ClassName.SHOW)) {
  196. return;
  197. }
  198. var elem = $(element);
  199. var startEvent = $.Event(Event.HIDE);
  200. elem.trigger(startEvent);
  201. if (startEvent.isDefaultPrevented()) {
  202. return;
  203. }
  204. elem.parent(this.config.parentTrigger).removeClass(ClassName.ACTIVE); // eslint-disable-next-line no-unused-expressions
  205. elem.height(elem.height())[0].offsetHeight;
  206. elem.addClass(ClassName.COLLAPSING).removeClass(ClassName.COLLAPSE).removeClass(ClassName.SHOW);
  207. this.setTransitioning(true);
  208. var complete = function complete() {
  209. // check if disposed
  210. if (!_this2.config || !_this2.element) {
  211. return;
  212. }
  213. if (_this2.transitioning && _this2.config.onTransitionEnd) {
  214. _this2.config.onTransitionEnd();
  215. }
  216. _this2.setTransitioning(false);
  217. elem.trigger(Event.HIDDEN);
  218. elem.removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE);
  219. };
  220. if (elem.height() === 0 || elem.css('display') === 'none') {
  221. complete();
  222. } else {
  223. elem.height(0).one(Util.TRANSITION_END, complete).mmEmulateTransitionEnd(TRANSITION_DURATION);
  224. }
  225. };
  226. _proto.setTransitioning = function setTransitioning(isTransitioning) {
  227. this.transitioning = isTransitioning;
  228. };
  229. _proto.dispose = function dispose() {
  230. $.removeData(this.element, DATA_KEY);
  231. $(this.element).find(this.config.parentTrigger) // .has(this.config.subMenu)
  232. .children(this.config.triggerElement).off(Event.CLICK_DATA_API);
  233. this.transitioning = null;
  234. this.config = null;
  235. this.element = null;
  236. };
  237. MetisMenu.jQueryInterface = function jQueryInterface(config) {
  238. // eslint-disable-next-line func-names
  239. return this.each(function () {
  240. var $this = $(this);
  241. var data = $this.data(DATA_KEY);
  242. var conf = _extends({}, Default, {}, $this.data(), {}, typeof config === 'object' && config ? config : {});
  243. if (!data) {
  244. data = new MetisMenu(this, conf);
  245. $this.data(DATA_KEY, data);
  246. }
  247. if (typeof config === 'string') {
  248. if (data[config] === undefined) {
  249. throw new Error("No method named \"" + config + "\"");
  250. }
  251. data[config]();
  252. }
  253. });
  254. };
  255. return MetisMenu;
  256. }();
  257. /**
  258. * ------------------------------------------------------------------------
  259. * jQuery
  260. * ------------------------------------------------------------------------
  261. */
  262. $.fn[NAME] = MetisMenu.jQueryInterface; // eslint-disable-line no-param-reassign
  263. $.fn[NAME].Constructor = MetisMenu; // eslint-disable-line no-param-reassign
  264. $.fn[NAME].noConflict = function () {
  265. // eslint-disable-line no-param-reassign
  266. $.fn[NAME] = JQUERY_NO_CONFLICT; // eslint-disable-line no-param-reassign
  267. return MetisMenu.jQueryInterface;
  268. };
  269. return MetisMenu;
  270. })));
  271. //# sourceMappingURL=metisMenu.js.map