metismenu.min.js 10 KB

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