├── .eslintignore ├── .eslintrc.json ├── .gitattributes ├── .github ├── FUNDING.yml ├── contributing.md └── issue_template.md ├── .gitignore ├── .versions ├── LICENSE ├── README.md ├── changelog.md ├── composer.json ├── dist ├── metisMenu.css ├── metisMenu.css.map ├── metisMenu.esm.js ├── metisMenu.esm.js.map ├── metisMenu.esm.min.js ├── metisMenu.esm.min.js.map ├── metisMenu.js ├── metisMenu.js.map ├── metisMenu.min.css ├── metisMenu.min.css.map ├── metisMenu.min.js └── metisMenu.min.js.map ├── docs ├── ajax-1.html ├── ajax-2.html ├── ajax-3.html ├── ajax-4.html ├── ajax-5.html ├── assets │ ├── css │ │ ├── app.css │ │ ├── metisMenu.css │ │ ├── metisMenu.css.map │ │ ├── mini.css │ │ ├── mm-faq.css │ │ ├── mm-folder.css │ │ ├── mm-horizontal.css │ │ ├── mm-vertical-hover.css │ │ └── mm-vertical.css │ └── js │ │ ├── metisMenu.js │ │ ├── metisMenu.js.map │ │ ├── mm-ajax.js │ │ ├── mm-animate.js │ │ ├── mm-bs-card.js │ │ ├── mm-dispose.js │ │ ├── mm-event.js │ │ ├── mm-event2.js │ │ ├── mm-faq.js │ │ ├── mm-folder.js │ │ ├── mm-horizontal.js │ │ ├── mm-vertical-hover.js │ │ └── mm-vertical.js ├── demo-ajax.html ├── index.html ├── mm-ajax.html ├── mm-animate.html ├── mm-bs-card.html ├── mm-dispose.html ├── mm-docs.html ├── mm-event.html ├── mm-event2.html ├── mm-faq.html ├── mm-folder.html ├── mm-horizontal.html ├── mm-vertical-hover.html └── mm-vertical.html ├── package-lock.json ├── package.js ├── package.json ├── rollup.config.js ├── src ├── index.js ├── metisMenu.scss └── util.js └── types └── metismenu.d.ts /.eslintignore: -------------------------------------------------------------------------------- 1 | /dist 2 | /docs 3 | /node_modules 4 | package.js -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "env": { 4 | "browser": true, 5 | "commonjs": true, 6 | "es6": true, 7 | "jquery": true 8 | }, 9 | "rules": { 10 | "import/no-unresolved": ["error", { "ignore": ["jquery"] }], 11 | "import/extensions": ["error", { "jquery": "never" }] 12 | }, 13 | "extends": "airbnb-base" 14 | } 15 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Enforce Unix newlines 2 | *.* text eol=lf 3 | *.css text eol=lf 4 | *.html text eol=lf 5 | *.js text eol=lf 6 | *.json text eol=lf 7 | *.less text eol=lf 8 | *.md text eol=lf 9 | *.yml text eol=lf 10 | 11 | *.jpg binary 12 | *.gif binary 13 | *.png binary 14 | *.jpeg binary -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [onokumus] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 12 | polar: # Replace with a single Polar username 13 | buy_me_a_coffee: # Replace with a single Buy Me a Coffee username 14 | thanks_dev: # Replace with a single thanks.dev username 15 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 16 | -------------------------------------------------------------------------------- /.github/contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing to metismenu 2 | 3 | First and foremost, thank you! We appreciate that you want to contribute to metismenu, your time is valuable, and your contributions mean a lot to us. 4 | 5 | **What does "contributing" mean?** 6 | 7 | Creating an issue is the simplest form of contributing to a project. But there are many ways to contribute, including the following: 8 | 9 | - Updating or correcting documentation 10 | - Feature requests 11 | - Bug reports 12 | 13 | If you'd like to learn more about contributing in general, the [Guide to Idiomatic Contributing](https://github.com/jonschlinkert/idiomatic-contributing) has a lot of useful information. 14 | 15 | **Showing support for metismenu** 16 | 17 | Please keep in mind that open source software is built by people like you, who spend their free time creating things the rest the community can use. 18 | 19 | Don't have time to contribute? No worries, here are some other ways to show your support for metismenu: 20 | 21 | - star the [project](https://github.com/onokumus/metismenu) 22 | - tweet your support for metismenu 23 | 24 | ## Issues 25 | 26 | ### Before creating an issue 27 | 28 | Please try to determine if the issue is caused by an underlying library, and if so, create the issue there. Sometimes this is difficult to know. We only ask that you attempt to give a reasonable attempt to find out. Oftentimes the readme will have advice about where to go to create issues. 29 | 30 | Try to follow these guidelines 31 | 32 | - **Investigate the issue**: 33 | - **Check the readme** - oftentimes you will find notes about creating issues, and where to go depending on the type of issue. 34 | - Create the issue in the appropriate repository. 35 | 36 | ### Creating an issue 37 | 38 | Please be as descriptive as possible when creating an issue. Give us the information we need to successfully answer your question or address your issue by answering the following in your issue: 39 | 40 | - **version**: please note the version of metismenu are you using 41 | - **extensions, plugins, helpers, etc** (if applicable): please list any extensions you're using 42 | - **error messages**: please paste any error messages into the issue, or a [gist](https://gist.github.com/) 43 | 44 | ## Above and beyond 45 | 46 | Here are some tips for creating idiomatic issues. Taking just a little bit extra time will make your issue easier to read, easier to resolve, more likely to be found by others who have the same or similar issue in the future. 47 | 48 | - read the [Guide to Idiomatic Contributing](https://github.com/jonschlinkert/idiomatic-contributing) 49 | - take some time to learn basic markdown. This [markdown cheatsheet](https://gist.github.com/jonschlinkert/5854601) is super helpful, as is the GitHub guide to [basic markdown](https://help.github.com/articles/markdown-basics/). 50 | - Learn about [GitHub Flavored Markdown](https://help.github.com/articles/github-flavored-markdown/). And if you want to really go above and beyond, read [mastering markdown](https://guides.github.com/features/mastering-markdown/). 51 | - use backticks to wrap code. This ensures that code will retain its format, making it much more readable to others 52 | - use syntax highlighting by adding the correct language name after the first "code fence" 53 | 54 | 55 | [node-glob]: https://github.com/isaacs/node-glob 56 | [micromatch]: https://github.com/jonschlinkert/micromatch 57 | [so]: http://stackoverflow.com/questions/tagged/metismenulk 58 | -------------------------------------------------------------------------------- /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | Welcome to the metismenu issues! 2 | 3 | Please take a moment to: 4 | 5 | - Read the Contributing Guide (found at https://github.com/onokumus/metismenu/tree/master/.github/contributing.md) 6 | - Review the project readme (you might find advice about creating new issues) 7 | 8 | 9 | Once have reviewed both documents, please delete everything up to and including this line and provide the following details. 10 | 11 | 12 | ## Version 13 | 14 | _(note the version of metismenu you were using when you experienced the issue (this is **required** for bug reports) 15 | 16 | **version**: 17 | 18 | ## Description 19 | 20 | 21 | 22 | ## Error message 23 | 24 | ```sh 25 | # please paste any error messages here 26 | ``` 27 | 28 | ## metisMenu.js 29 | 30 | ```js 31 | // Please paste contents of metisMenu.js here, or in a gist. 32 | // Be sure to include any additional comments that might help 33 | // us resolve the issue. 34 | ``` 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Numerous always-ignore extensions 2 | *.csv 3 | *.dat 4 | *.diff 5 | *.err 6 | *.gz 7 | *.log 8 | *.orig 9 | *.out 10 | *.pid 11 | *.rej 12 | *.seed 13 | *.swo 14 | *.swp 15 | *.vi 16 | *.yo-rc.json 17 | *.zip 18 | *~ 19 | .ruby-version 20 | lib-cov 21 | 22 | # OS or Editor folders 23 | *.esproj 24 | *.sublime-project 25 | *.sublime-workspace 26 | ._* 27 | .cache 28 | .DS_Store 29 | .idea 30 | .project 31 | .settings 32 | .tmproj 33 | .directory 34 | nbproject 35 | backup 36 | Thumbs.db 37 | .tmp 38 | 39 | # Komodo 40 | *.komodoproject 41 | .komodotools 42 | 43 | # grunt-html-validation 44 | validation-status.json 45 | validation-report.json 46 | 47 | # Vendor packages 48 | node_modules 49 | bower_components 50 | vendor 51 | templates/partials/ads.hbs 52 | templates/partials/ga.hbs 53 | 54 | 55 | # General folders and files to ignore 56 | _gh_pages 57 | tmp 58 | temp 59 | TODO.md 60 | -------------------------------------------------------------------------------- /.versions: -------------------------------------------------------------------------------- 1 | jquery@1.11.4 2 | meteor@1.1.10 3 | onokumus:metismenu@3.0.6 4 | underscore@1.0.4 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2021 Osman Nuri Okumuş 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # metismenu [![NPM version](https://img.shields.io/npm/v/metismenu.svg?style=flat)](https://www.npmjs.com/package/metismenu) [![NPM monthly downloads](https://img.shields.io/npm/dm/metismenu.svg?style=flat)](https://npmjs.org/package/metismenu) [![NPM total downloads](https://img.shields.io/npm/dt/metismenu.svg?style=flat)](https://npmjs.org/package/metismenu) 2 | 3 | 4 | > A collapsible jQuery menu plugin 5 | > 6 | > This version does not support any version of IE browser. 7 | 8 | - [Getting started](#getting-started) 9 | * [Install](#install) 10 | * [Download](#download) 11 | - [Usage](#usage) 12 | * [Stopping list opening on certain elements](#stopping-list-opening-on-certain-elements) 13 | + [toggle](#toggle) 14 | + [dispose](#dispose) 15 | + [preventDefault](#preventdefault) 16 | + [triggerElement](#triggerelement) 17 | + [parentTrigger](#parenttrigger) 18 | + [subMenu](#submenu) 19 | - [Events](#events) 20 | - [Migrating to v3 from v2](#migrating-to-v3-from-v2) 21 | - [Demo](#demo) 22 | - [About](#about) 23 | * [Related projects](#related-projects) 24 | * [Contributors](#contributors) 25 | * [Contributing](#contributing) 26 | * [Release History](#release-history) 27 | * [Author](#author) 28 | * [License](#license) 29 | 30 | 31 | ## Getting started 32 | 33 | ### Install 34 | 35 | Install with [npm](https://www.npmjs.com/): 36 | 37 | ```sh 38 | npm install --save metismenu 39 | ``` 40 | 41 | Install with [yarn](https://yarnpkg.com): 42 | 43 | ```sh 44 | yarn add metismenu 45 | ``` 46 | 47 | Install with [composer](https://getcomposer.org/) 48 | 49 | ```sh 50 | composer require onokumus/metismenu:dev-master 51 | ``` 52 | 53 | ### Download 54 | 55 | [download](https://github.com/onokumus/metisMenu/archive/master.zip) 56 | 57 | ## Usage 58 | 59 | 1. Include metismenu StyleSheet 60 | 61 | ```html 62 | 63 | 64 | 65 | ``` 66 | 67 | 1. Include jQuery 68 | 69 | ```html 70 | 71 | 72 | 73 | ``` 74 | 75 | 1. Include metisMenu plugin's code 76 | 77 | ```html 78 | 79 | 80 | 81 | ``` 82 | 83 | 1. Add id attribute to unordered list 84 | 85 | ```html 86 | 89 | ``` 90 | 91 | 1. Make expand/collapse controls accessible 92 | 93 | > Be sure to add `aria-expanded` to the element `a`. This attribute explicitly defines the current state of the collapsible element to screen readers and similar assistive technologies. If the collapsible element is closed by default, it should have a value of `aria-expanded="false"`. If you've set the collapsible element's parent `li` element to be open by default using the `mm-active` class, set `aria-expanded="true"` on the control instead. The plugin will automatically toggle this attribute based on whether or not the collapsible element has been opened or closed. 94 | 95 | ```html 96 | 111 | ``` 112 | 113 | 1. Arrow Options 114 | 115 | > add `has-arrow` class to `a` element 116 | 117 | ```html 118 | 133 | ``` 134 | 135 | 1. Call the plugin: 136 | 137 | ```javascript 138 | $("#metismenu").metisMenu(); 139 | ``` 140 | 141 | ### Stopping list opening on certain elements 142 | 143 | Setting aria-disabled="true" in the `` element as shown will stop metisMenu opening the menu for that particular list. This can be changed dynamically and will be obeyed correctly: 144 | 145 | ```html 146 | 147 | ``` 148 | 149 | #### toggle 150 | 151 | Type: `Boolean` 152 | Default: `true` 153 | 154 | For auto collapse support. 155 | 156 | ```javascript 157 | $("#metismenu").metisMenu({ 158 | toggle: false 159 | }); 160 | ``` 161 | 162 | #### dispose 163 | 164 | Type: `String` 165 | Default: `null` 166 | 167 | For stop and destroy metisMenu. 168 | 169 | ```javascript 170 | $("#metismenu").metisMenu('dispose'); 171 | ``` 172 | 173 | #### preventDefault 174 | 175 | Type: `Boolean` 176 | Default: `true` 177 | 178 | > Prevents or allows dropdowns' onclick events after expanding/collapsing. 179 | 180 | ```javascript 181 | $("#menu").metisMenu({ 182 | preventDefault: false 183 | }); 184 | ``` 185 | 186 | _since from version 2.7.0_ 187 | 188 | #### triggerElement 189 | 190 | Type: `jQuery selector` 191 | Default: `a` 192 | 193 | ```javascript 194 | $("#metismenu").metisMenu({ 195 | triggerElement: '.nav-link' // bootstrap 5 196 | }); 197 | ``` 198 | 199 | #### parentTrigger 200 | 201 | Type: `jQuery selector` 202 | Default: `li` 203 | 204 | ```javascript 205 | $("#metismenu").metisMenu({ 206 | parentTrigger: '.nav-item' // bootstrap 5 207 | }); 208 | ``` 209 | 210 | #### subMenu 211 | 212 | Type: `jQuery selector` 213 | Default: `ul` 214 | 215 | ```javascript 216 | $("#metismenu").metisMenu({ 217 | subMenu: '.nav.flex-column' // bootstrap 5 218 | }); 219 | ``` 220 | 221 | ## Events 222 | 223 | |**Event Type** |**Description**| 224 | |--------------|--------------| 225 | |show.metisMenu |This event fires immediately when the `_show` instance method is called.| 226 | |shown.metisMenu |This event is fired when a collapse `ul` element has been made visible to the user (will wait for CSS transitions to complete).| 227 | |hide.metisMenu |This event is fired immediately when the `_hide` method has been called. | 228 | |hidden.metisMenu |This event is fired when a collapse `ul` element has been hidden from the user (will wait for CSS transitions to complete).| 229 | 230 | ## Migrating to v3 from v2 231 | 232 | * Update `metisMenu.js` & `metisMenu.css` files 233 | * Change `active` class to `mm-active` 234 | 235 | ## Demo 236 | 237 | [http://mm.onokumus.com](http://mm.onokumus.com) 238 | 239 | Contains a simple HTML file to demonstrate metisMenu plugin. 240 | 241 | ## About 242 | 243 | ### Related projects 244 | 245 | * [@metismenu/react](https://www.npmjs.com/package/@metismenu/react): react component for MetisMenu | [homepage](https://github.com/onokumus/metismenu-react#readme "react component for MetisMenu") 246 | * [metismenujs](https://www.npmjs.com/package/metismenujs): MetisMenu with Vanilla-JS | [homepage](https://github.com/onokumus/metismenujs#readme "MetisMenu with Vanilla-JS") 247 | 248 | ### Contributors 249 | 250 | | **Contributor** | 251 | | --- | 252 | |[onokumus](https://github.com/onokumus) | 253 | | [diegozhu](https://github.com/diegozhu) | 254 | | [sinabs](https://github.com/sinabs) | 255 | |[DrugoLebowski](https://github.com/DrugoLebowski) | 256 | | [BurkovBA](https://github.com/BurkovBA) | 257 | | [arthurtalkgoal](https://github.com/arthurtalkgoal) | 258 | | [mrdziuban](https://github.com/mrdziuban) | 259 | | [nicolasigot](https://github.com/nicolasigot) | 260 | | [PeterDaveHello](https://github.com/PeterDaveHello) | 261 | | [kalidema](https://github.com/kalidema) | 262 | | [AndrewEastwood](https://github.com/AndrewEastwood) | 263 | | [rgnevashev](https://github.com/rgnevashev) | 264 | | [719media](https://github.com/719media) | 265 | | [chriswiggins](https://github.com/chriswiggins) | 266 | | [jmagnusson](https://github.com/jmagnusson) | 267 | | [LukasDrgon](https://github.com/LukasDrgon) | 268 | | [Cediddi](https://github.com/Cediddi) | 269 | | [WoMayr](https://github.com/WoMayr) | 270 | | [capynet](https://github.com/capynet) | 271 | 272 | ### Contributing 273 | 274 | Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). 275 | 276 | Please read the [contributing guide](.github/contributing.md) for advice on opening issues, pull requests, and coding standards. 277 | 278 | ### Release History 279 | 280 | |**DATE** |**VERSION** |**CHANGES**| 281 | |--------------|--------------|-----------| 282 | |2021-05-16 |v3.0.7 |sass support| 283 | |2020-03-22 |v3.0.6 |fix security vulnerabilities| 284 | |2019-12-28 |v3.0.5 |Fix dispose to be similar to init (adding event) [#184](https://github.com/onokumus/metismenu/pull/184)| 285 | |2019-03-07 |v3.0.4 |fix| 286 | |2018-10-05 |v3.0.3 |fix| 287 | |2018-10-05 |v3.0.2 |fix| 288 | |2018-10-05 |v3.0.1 |fix| 289 | |2018-10-05 |v3.0.0 |more functionally| 290 | |2018-10-05 |v2.7.9.1 |Fix dispose option [#173](https://github.com/onokumus/metismenu/pull/173)| 291 | |2018-06-28 |v2.7.9 |Make jquery a peer dependency| 292 | |2018-06-14 |v2.7.8 |remove aria-expanded attribute & remove transitionend check| 293 | |2018-02-14 |v2.7.4 |jQuery -> $ in src/metisMenu.js to fix import. [#158](https://github.com/onokumus/metismenu/pull/158)| 294 | |2018-02-14 |v2.7.3 |window might not be defined in node.js environment [#156](https://github.com/onokumus/metismenu/pull/156)| 295 | |2017-12-31 |v2.7.2 |isolate against bootstrap changes, remove old legacy ie9 code [#154](https://github.com/onokumus/metismenu/pull/154)| 296 | |2017-10-30 |v2.7.1 |added check in complete()-callback to break when menu was disposed [#150](https://github.com/onokumus/metismenu/pull/150)| 297 | |2017-03-08 |v2.7.0 |fixed `has-arrow` class border color & added new 3 options| 298 | |2017-02-23 |v2.6.3 |fixed #129| 299 | |2017-02-02 |v2.6.2 |doubleTapToGo option is deprecated| 300 | |2016-12-06 |v2.6.1 |fix require.js| 301 | |2016-11-29 |v2.6.0 |dispose support| 302 | |2016-05-06 |v2.5.2 |fix Menu failed to remove collapsing class| 303 | |2016-05-06 |v2.5.1 |fixed bootstrap conflict| 304 | |2016-03-31 |v2.5.0 |Event support| 305 | |2016-03-11 |v2.4.3 |create meteor package| 306 | |2016-03-04 |v2.4.2 |back to version 2.4.0| 307 | |2016-03-03 |v2.4.1 |Transition element passed to methods (removed)| 308 | |2016-01-25 |v2.4.0 |Support AMD / Node / CommonJS| 309 | |2016-01-08 |v2.3.0 |Adding aria-disabled=true to the link element prevents the dropdown from opening| 310 | |2015-09-27 |v2.2.0 |Events supported & added preventDefault options| 311 | |2015-08-06 |v2.1.0 |RTL & `aria-expanded` attribute & TypeScript type definitions support| 312 | |2015-07-25 |v2.0.3 |When the active item has doubleTapToGo should not collapse| 313 | |2015-05-23 |v2.0.2 |[fixed](https://github.com/onokumus/metisMenu/issues/34#issuecomment-104656754)| 314 | |2015-05-22 |v2.0.1 |changeable classname support| 315 | |2015-04-03 |v2.0.0 |Remove Bootstrap dependency| 316 | |2015-03-24 |v1.1.3 |composer support| 317 | |2014-11-01 |v1.1.3 |Bootstrap 3.3.0| 318 | |2014-07-07 |v1.1.0 |Add double tap functionality| 319 | |2014-06-24 |v1.0.3 |cdnjs support & rename plugin| 320 | |2014-06-18 |v1.0.3 |Create grunt task| 321 | |2014-06-10 |v1.0.2 |Fixed for IE8 & IE9| 322 | 323 | ### Author 324 | 325 | **Osman Nuri Okumus** 326 | 327 | * [GitHub Profile](https://github.com/onokumus) 328 | * [Twitter Profile](https://twitter.com/onokumus) 329 | * [LinkedIn Profile](https://linkedin.com/in/onokumus) 330 | 331 | ### License 332 | 333 | Copyright © 2021, [Osman Nuri Okumus](https://github.com/onokumus). 334 | Released under the [MIT License](LICENSE). 335 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | #### key 2 | 3 | Changelog entries are classified using the following labels _(from [keep-a-changelog][]_): 4 | 5 | - `added`: for new features 6 | - `changed`: for changes in existing functionality 7 | - `deprecated`: for once-stable features removed in upcoming releases 8 | - `removed`: for deprecated features removed in this release 9 | - `fixed`: for any bug fixes 10 | 11 | Custom labels used in this changelog: 12 | 13 | * `dependencies`: bumps dependencies 14 | * `housekeeping`: code re-organization, minor edits, or other changes that don't fit in one of the other categories. 15 | 16 | ### [0.0.1] - 2017-02-13 17 | 18 | **added** 19 | 20 | - initial release 21 | 22 | [keep-a-changelog]: https://github.com/olivierlacan/keep-a-changelog 23 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "onokumus/metismenu", 3 | "description": "A jQuery menu plugin", 4 | "keywords": [ 5 | "menu", 6 | "plugin", 7 | "jquery", 8 | "web", 9 | "css", 10 | "js", 11 | "bootstrap" 12 | ], 13 | "homepage": "https://github.com/onokumus/metisMenu", 14 | "authors": [ 15 | { 16 | "name": "Osman Nuri Okumus", 17 | "email": "onokumus@gmail.com", 18 | "homepage": "https://onokumus.com" 19 | } 20 | ], 21 | "support": { 22 | "issues": "https://github.com/onokumus/metisMenu/issues" 23 | }, 24 | "license": "MIT", 25 | "suggest": { 26 | "components/jquery": ">=1.9" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /dist/metisMenu.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | /*! 3 | * metismenu https://github.com/onokumus/metismenu#readme 4 | * A collapsible jQuery menu plugin 5 | * @version 3.0.7 6 | * @author Osman Nuri Okumus (https://github.com/onokumus) 7 | * @license: MIT 8 | */ 9 | .metismenu .arrow { 10 | float: right; 11 | line-height: 1.42857; 12 | } 13 | 14 | *[dir=rtl] .metismenu .arrow { 15 | float: left; 16 | } 17 | 18 | /* 19 | * Require Bootstrap 3.x 20 | * https://github.com/twbs/bootstrap 21 | */ 22 | .metismenu .glyphicon.arrow:before { 23 | content: ""; 24 | } 25 | 26 | .metismenu .mm-active > a > .glyphicon.arrow:before { 27 | content: ""; 28 | } 29 | 30 | /* 31 | * Require Font-Awesome 32 | * http://fortawesome.github.io/Font-Awesome/ 33 | */ 34 | .metismenu .fa.arrow:before { 35 | content: ""; 36 | } 37 | 38 | .metismenu .mm-active > a > .fa.arrow:before { 39 | content: ""; 40 | } 41 | 42 | /* 43 | * Require Ionicons 44 | * http://ionicons.com/ 45 | */ 46 | .metismenu .ion.arrow:before { 47 | content: ""; 48 | } 49 | 50 | .metismenu .mm-active > a > .ion.arrow:before { 51 | content: ""; 52 | } 53 | 54 | .metismenu .plus-times { 55 | float: right; 56 | } 57 | 58 | *[dir=rtl] .metismenu .plus-times { 59 | float: left; 60 | } 61 | 62 | .metismenu .fa.plus-times:before { 63 | content: ""; 64 | } 65 | 66 | .metismenu .mm-active > a > .fa.plus-times { 67 | transform: rotate(45deg); 68 | } 69 | 70 | .metismenu .plus-minus { 71 | float: right; 72 | } 73 | 74 | *[dir=rtl] .metismenu .plus-minus { 75 | float: left; 76 | } 77 | 78 | .metismenu .fa.plus-minus:before { 79 | content: ""; 80 | } 81 | 82 | .metismenu .mm-active > a > .fa.plus-minus:before { 83 | content: ""; 84 | } 85 | 86 | .metismenu .mm-collapse:not(.mm-show) { 87 | display: none; 88 | } 89 | 90 | .metismenu .mm-collapsing { 91 | position: relative; 92 | height: 0; 93 | overflow: hidden; 94 | transition-timing-function: ease; 95 | transition-duration: 0.35s; 96 | transition-property: height, visibility; 97 | } 98 | 99 | .metismenu .has-arrow { 100 | position: relative; 101 | } 102 | 103 | .metismenu .has-arrow::after { 104 | position: absolute; 105 | content: ""; 106 | width: 0.5em; 107 | height: 0.5em; 108 | border-width: 1px 0 0 1px; 109 | border-style: solid; 110 | border-color: initial; 111 | right: 1em; 112 | transform: rotate(-45deg) translate(0, -50%); 113 | transform-origin: top; 114 | top: 50%; 115 | transition: all 0.3s ease-out; 116 | } 117 | 118 | *[dir=rtl] .metismenu .has-arrow::after { 119 | right: auto; 120 | left: 1em; 121 | transform: rotate(135deg) translate(0, -50%); 122 | } 123 | 124 | .metismenu .mm-active > .has-arrow::after, 125 | .metismenu .has-arrow[aria-expanded=true]::after { 126 | transform: rotate(-135deg) translate(0, -50%); 127 | } 128 | 129 | *[dir=rtl] .metismenu .mm-active > .has-arrow::after, 130 | *[dir=rtl] .metismenu .has-arrow[aria-expanded=true]::after { 131 | transform: rotate(225deg) translate(0, -50%); 132 | } 133 | 134 | /*# sourceMappingURL=metisMenu.css.map */ 135 | -------------------------------------------------------------------------------- /dist/metisMenu.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sourceRoot":"","sources":["../src/metisMenu.scss"],"names":[],"mappings":";AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA;EACE;EACA;;;AAEF;EACE;;;AAGF;AAAA;AAAA;AAAA;AAKA;EACE;;;AAEF;EACE;;;AAGF;AAAA;AAAA;AAAA;AAKA;EACE;;;AAEF;EACE;;;AAGF;AAAA;AAAA;AAAA;AAKA;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;AAAA;EAEE;;;AAGF;AAAA;EAEE","file":"metisMenu.css"} -------------------------------------------------------------------------------- /dist/metisMenu.esm.js: -------------------------------------------------------------------------------- 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 (https://github.com/onokumus) 6 | * @license: MIT 7 | */ 8 | import $ from 'jquery'; 9 | 10 | const Util = (($) => { // eslint-disable-line no-shadow 11 | const TRANSITION_END = 'transitionend'; 12 | 13 | const Util = { // eslint-disable-line no-shadow 14 | TRANSITION_END: 'mmTransitionEnd', 15 | 16 | triggerTransitionEnd(element) { 17 | $(element).trigger(TRANSITION_END); 18 | }, 19 | 20 | supportsTransitionEnd() { 21 | return Boolean(TRANSITION_END); 22 | }, 23 | }; 24 | 25 | function getSpecialTransitionEndEvent() { 26 | return { 27 | bindType: TRANSITION_END, 28 | delegateType: TRANSITION_END, 29 | handle(event) { 30 | if ($(event.target).is(this)) { 31 | return event 32 | .handleObj 33 | .handler 34 | .apply(this, arguments); // eslint-disable-line prefer-rest-params 35 | } 36 | return undefined; 37 | }, 38 | }; 39 | } 40 | 41 | function transitionEndEmulator(duration) { 42 | let called = false; 43 | 44 | $(this).one(Util.TRANSITION_END, () => { 45 | called = true; 46 | }); 47 | 48 | setTimeout(() => { 49 | if (!called) { 50 | Util.triggerTransitionEnd(this); 51 | } 52 | }, duration); 53 | 54 | return this; 55 | } 56 | 57 | function setTransitionEndSupport() { 58 | $.fn.mmEmulateTransitionEnd = transitionEndEmulator; // eslint-disable-line no-param-reassign 59 | // eslint-disable-next-line no-param-reassign 60 | $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent(); 61 | } 62 | 63 | setTransitionEndSupport(); 64 | 65 | return Util; 66 | })($); 67 | 68 | const NAME = 'metisMenu'; 69 | const DATA_KEY = 'metisMenu'; 70 | const EVENT_KEY = `.${DATA_KEY}`; 71 | const DATA_API_KEY = '.data-api'; 72 | const JQUERY_NO_CONFLICT = $.fn[NAME]; 73 | const TRANSITION_DURATION = 350; 74 | 75 | const Default = { 76 | toggle: true, 77 | preventDefault: true, 78 | triggerElement: 'a', 79 | parentTrigger: 'li', 80 | subMenu: 'ul', 81 | }; 82 | 83 | const Event = { 84 | SHOW: `show${EVENT_KEY}`, 85 | SHOWN: `shown${EVENT_KEY}`, 86 | HIDE: `hide${EVENT_KEY}`, 87 | HIDDEN: `hidden${EVENT_KEY}`, 88 | CLICK_DATA_API: `click${EVENT_KEY}${DATA_API_KEY}`, 89 | }; 90 | 91 | const ClassName = { 92 | METIS: 'metismenu', 93 | ACTIVE: 'mm-active', 94 | SHOW: 'mm-show', 95 | COLLAPSE: 'mm-collapse', 96 | COLLAPSING: 'mm-collapsing', 97 | COLLAPSED: 'mm-collapsed', 98 | }; 99 | 100 | class MetisMenu { 101 | // eslint-disable-line no-shadow 102 | constructor(element, config) { 103 | this.element = element; 104 | this.config = { 105 | ...Default, 106 | ...config, 107 | }; 108 | this.transitioning = null; 109 | 110 | this.init(); 111 | } 112 | 113 | init() { 114 | const self = this; 115 | const conf = this.config; 116 | const el = $(this.element); 117 | 118 | el.addClass(ClassName.METIS); // add metismenu class to element 119 | 120 | el.find(`${conf.parentTrigger}.${ClassName.ACTIVE}`) 121 | .children(conf.triggerElement) 122 | .attr('aria-expanded', 'true'); // add attribute aria-expanded=true the trigger element 123 | 124 | el.find(`${conf.parentTrigger}.${ClassName.ACTIVE}`) 125 | .parents(conf.parentTrigger) 126 | .addClass(ClassName.ACTIVE); 127 | 128 | el.find(`${conf.parentTrigger}.${ClassName.ACTIVE}`) 129 | .parents(conf.parentTrigger) 130 | .children(conf.triggerElement) 131 | .attr('aria-expanded', 'true'); // add attribute aria-expanded=true the triggers of all parents 132 | 133 | el.find(`${conf.parentTrigger}.${ClassName.ACTIVE}`) 134 | .has(conf.subMenu) 135 | .children(conf.subMenu) 136 | .addClass(`${ClassName.COLLAPSE} ${ClassName.SHOW}`); 137 | 138 | el 139 | .find(conf.parentTrigger) 140 | .not(`.${ClassName.ACTIVE}`) 141 | .has(conf.subMenu) 142 | .children(conf.subMenu) 143 | .addClass(ClassName.COLLAPSE); 144 | 145 | el 146 | .find(conf.parentTrigger) 147 | // .has(conf.subMenu) 148 | .children(conf.triggerElement) 149 | .on(Event.CLICK_DATA_API, function (e) { // eslint-disable-line func-names 150 | const eTar = $(this); 151 | 152 | if (eTar.attr('aria-disabled') === 'true') { 153 | return; 154 | } 155 | 156 | if (conf.preventDefault && eTar.attr('href') === '#') { 157 | e.preventDefault(); 158 | } 159 | 160 | const paRent = eTar.parent(conf.parentTrigger); 161 | const sibLi = paRent.siblings(conf.parentTrigger); 162 | const sibTrigger = sibLi.children(conf.triggerElement); 163 | 164 | if (paRent.hasClass(ClassName.ACTIVE)) { 165 | eTar.attr('aria-expanded', 'false'); 166 | self.removeActive(paRent); 167 | } else { 168 | eTar.attr('aria-expanded', 'true'); 169 | self.setActive(paRent); 170 | if (conf.toggle) { 171 | self.removeActive(sibLi); 172 | sibTrigger.attr('aria-expanded', 'false'); 173 | } 174 | } 175 | 176 | if (conf.onTransitionStart) { 177 | conf.onTransitionStart(e); 178 | } 179 | }); 180 | } 181 | 182 | setActive(li) { 183 | $(li).addClass(ClassName.ACTIVE); 184 | const ul = $(li).children(this.config.subMenu); 185 | if (ul.length > 0 && !ul.hasClass(ClassName.SHOW)) { 186 | this.show(ul); 187 | } 188 | } 189 | 190 | removeActive(li) { 191 | $(li).removeClass(ClassName.ACTIVE); 192 | const ul = $(li).children(`${this.config.subMenu}.${ClassName.SHOW}`); 193 | if (ul.length > 0) { 194 | this.hide(ul); 195 | } 196 | } 197 | 198 | show(element) { 199 | if (this.transitioning || $(element).hasClass(ClassName.COLLAPSING)) { 200 | return; 201 | } 202 | const elem = $(element); 203 | 204 | const startEvent = $.Event(Event.SHOW); 205 | elem.trigger(startEvent); 206 | 207 | if (startEvent.isDefaultPrevented()) { 208 | return; 209 | } 210 | 211 | elem.parent(this.config.parentTrigger).addClass(ClassName.ACTIVE); 212 | 213 | if (this.config.toggle) { 214 | const toggleElem = elem.parent(this.config.parentTrigger).siblings().children(`${this.config.subMenu}.${ClassName.SHOW}`); 215 | this.hide(toggleElem); 216 | } 217 | 218 | elem 219 | .removeClass(ClassName.COLLAPSE) 220 | .addClass(ClassName.COLLAPSING) 221 | .height(0); 222 | 223 | this.setTransitioning(true); 224 | 225 | const complete = () => { 226 | // check if disposed 227 | if (!this.config || !this.element) { 228 | return; 229 | } 230 | elem 231 | .removeClass(ClassName.COLLAPSING) 232 | .addClass(`${ClassName.COLLAPSE} ${ClassName.SHOW}`) 233 | .height(''); 234 | 235 | this.setTransitioning(false); 236 | 237 | elem.trigger(Event.SHOWN); 238 | }; 239 | 240 | elem 241 | .height(element[0].scrollHeight) 242 | .one(Util.TRANSITION_END, complete) 243 | .mmEmulateTransitionEnd(TRANSITION_DURATION); 244 | } 245 | 246 | hide(element) { 247 | if ( 248 | this.transitioning || !$(element).hasClass(ClassName.SHOW) 249 | ) { 250 | return; 251 | } 252 | 253 | const elem = $(element); 254 | 255 | const startEvent = $.Event(Event.HIDE); 256 | elem.trigger(startEvent); 257 | 258 | if (startEvent.isDefaultPrevented()) { 259 | return; 260 | } 261 | 262 | elem.parent(this.config.parentTrigger).removeClass(ClassName.ACTIVE); 263 | // eslint-disable-next-line no-unused-expressions 264 | elem.height(elem.height())[0].offsetHeight; 265 | 266 | elem 267 | .addClass(ClassName.COLLAPSING) 268 | .removeClass(ClassName.COLLAPSE) 269 | .removeClass(ClassName.SHOW); 270 | 271 | this.setTransitioning(true); 272 | 273 | const complete = () => { 274 | // check if disposed 275 | if (!this.config || !this.element) { 276 | return; 277 | } 278 | if (this.transitioning && this.config.onTransitionEnd) { 279 | this.config.onTransitionEnd(); 280 | } 281 | 282 | this.setTransitioning(false); 283 | elem.trigger(Event.HIDDEN); 284 | 285 | elem 286 | .removeClass(ClassName.COLLAPSING) 287 | .addClass(ClassName.COLLAPSE); 288 | }; 289 | 290 | if (elem.height() === 0 || elem.css('display') === 'none') { 291 | complete(); 292 | } else { 293 | elem 294 | .height(0) 295 | .one(Util.TRANSITION_END, complete) 296 | .mmEmulateTransitionEnd(TRANSITION_DURATION); 297 | } 298 | } 299 | 300 | setTransitioning(isTransitioning) { 301 | this.transitioning = isTransitioning; 302 | } 303 | 304 | dispose() { 305 | $.removeData(this.element, DATA_KEY); 306 | 307 | $(this.element) 308 | .find(this.config.parentTrigger) 309 | // .has(this.config.subMenu) 310 | .children(this.config.triggerElement) 311 | .off(Event.CLICK_DATA_API); 312 | 313 | this.transitioning = null; 314 | this.config = null; 315 | this.element = null; 316 | } 317 | 318 | static jQueryInterface(config) { 319 | // eslint-disable-next-line func-names 320 | return this.each(function () { 321 | const $this = $(this); 322 | let data = $this.data(DATA_KEY); 323 | const conf = { 324 | ...Default, 325 | ...$this.data(), 326 | ...(typeof config === 'object' && config ? config : {}), 327 | }; 328 | 329 | if (!data) { 330 | data = new MetisMenu(this, conf); 331 | $this.data(DATA_KEY, data); 332 | } 333 | 334 | if (typeof config === 'string') { 335 | if (data[config] === undefined) { 336 | throw new Error(`No method named "${config}"`); 337 | } 338 | data[config](); 339 | } 340 | }); 341 | } 342 | } 343 | /** 344 | * ------------------------------------------------------------------------ 345 | * jQuery 346 | * ------------------------------------------------------------------------ 347 | */ 348 | 349 | $.fn[NAME] = MetisMenu.jQueryInterface; // eslint-disable-line no-param-reassign 350 | $.fn[NAME].Constructor = MetisMenu; // eslint-disable-line no-param-reassign 351 | $.fn[NAME].noConflict = () => { 352 | // eslint-disable-line no-param-reassign 353 | $.fn[NAME] = JQUERY_NO_CONFLICT; // eslint-disable-line no-param-reassign 354 | return MetisMenu.jQueryInterface; 355 | }; 356 | 357 | export default MetisMenu; 358 | //# sourceMappingURL=metisMenu.esm.js.map 359 | -------------------------------------------------------------------------------- /dist/metisMenu.esm.min.js: -------------------------------------------------------------------------------- 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 (https://github.com/onokumus) 6 | * @license: MIT 7 | */ 8 | import $ from"jquery";const Util=(e=>{const t="transitionend",s={TRANSITION_END:"mmTransitionEnd",triggerTransitionEnd(s){e(s).trigger(t)},supportsTransitionEnd:()=>Boolean(t)};function n(t){let n=!1;return e(this).one(s.TRANSITION_END,(()=>{n=!0})),setTimeout((()=>{n||s.triggerTransitionEnd(this)}),t),this}return e.fn.mmEmulateTransitionEnd=n,e.event.special[s.TRANSITION_END]={bindType:t,delegateType:t,handle(t){if(e(t.target).is(this))return t.handleObj.handler.apply(this,arguments)}},s})($),NAME="metisMenu",DATA_KEY="metisMenu",EVENT_KEY=".metisMenu",DATA_API_KEY=".data-api",JQUERY_NO_CONFLICT=$.fn[NAME],TRANSITION_DURATION=350,Default={toggle:!0,preventDefault:!0,triggerElement:"a",parentTrigger:"li",subMenu:"ul"},Event={SHOW:"show.metisMenu",SHOWN:"shown.metisMenu",HIDE:"hide.metisMenu",HIDDEN:"hidden.metisMenu",CLICK_DATA_API:"click.metisMenu.data-api"},ClassName={METIS:"metismenu",ACTIVE:"mm-active",SHOW:"mm-show",COLLAPSE:"mm-collapse",COLLAPSING:"mm-collapsing",COLLAPSED:"mm-collapsed"};class MetisMenu{constructor(e,t){this.element=e,this.config={...Default,...t},this.transitioning=null,this.init()}init(){const e=this,t=this.config,s=$(this.element);s.addClass(ClassName.METIS),s.find(`${t.parentTrigger}.${ClassName.ACTIVE}`).children(t.triggerElement).attr("aria-expanded","true"),s.find(`${t.parentTrigger}.${ClassName.ACTIVE}`).parents(t.parentTrigger).addClass(ClassName.ACTIVE),s.find(`${t.parentTrigger}.${ClassName.ACTIVE}`).parents(t.parentTrigger).children(t.triggerElement).attr("aria-expanded","true"),s.find(`${t.parentTrigger}.${ClassName.ACTIVE}`).has(t.subMenu).children(t.subMenu).addClass(`${ClassName.COLLAPSE} ${ClassName.SHOW}`),s.find(t.parentTrigger).not(`.${ClassName.ACTIVE}`).has(t.subMenu).children(t.subMenu).addClass(ClassName.COLLAPSE),s.find(t.parentTrigger).children(t.triggerElement).on(Event.CLICK_DATA_API,(function(s){const n=$(this);if("true"===n.attr("aria-disabled"))return;t.preventDefault&&"#"===n.attr("href")&&s.preventDefault();const i=n.parent(t.parentTrigger),a=i.siblings(t.parentTrigger),r=a.children(t.triggerElement);i.hasClass(ClassName.ACTIVE)?(n.attr("aria-expanded","false"),e.removeActive(i)):(n.attr("aria-expanded","true"),e.setActive(i),t.toggle&&(e.removeActive(a),r.attr("aria-expanded","false"))),t.onTransitionStart&&t.onTransitionStart(s)}))}setActive(e){$(e).addClass(ClassName.ACTIVE);const t=$(e).children(this.config.subMenu);t.length>0&&!t.hasClass(ClassName.SHOW)&&this.show(t)}removeActive(e){$(e).removeClass(ClassName.ACTIVE);const t=$(e).children(`${this.config.subMenu}.${ClassName.SHOW}`);t.length>0&&this.hide(t)}show(e){if(this.transitioning||$(e).hasClass(ClassName.COLLAPSING))return;const t=$(e),s=$.Event(Event.SHOW);if(t.trigger(s),s.isDefaultPrevented())return;if(t.parent(this.config.parentTrigger).addClass(ClassName.ACTIVE),this.config.toggle){const e=t.parent(this.config.parentTrigger).siblings().children(`${this.config.subMenu}.${ClassName.SHOW}`);this.hide(e)}t.removeClass(ClassName.COLLAPSE).addClass(ClassName.COLLAPSING).height(0),this.setTransitioning(!0);t.height(e[0].scrollHeight).one(Util.TRANSITION_END,(()=>{this.config&&this.element&&(t.removeClass(ClassName.COLLAPSING).addClass(`${ClassName.COLLAPSE} ${ClassName.SHOW}`).height(""),this.setTransitioning(!1),t.trigger(Event.SHOWN))})).mmEmulateTransitionEnd(350)}hide(e){if(this.transitioning||!$(e).hasClass(ClassName.SHOW))return;const t=$(e),s=$.Event(Event.HIDE);if(t.trigger(s),s.isDefaultPrevented())return;t.parent(this.config.parentTrigger).removeClass(ClassName.ACTIVE),t.height(t.height())[0].offsetHeight,t.addClass(ClassName.COLLAPSING).removeClass(ClassName.COLLAPSE).removeClass(ClassName.SHOW),this.setTransitioning(!0);const n=()=>{this.config&&this.element&&(this.transitioning&&this.config.onTransitionEnd&&this.config.onTransitionEnd(),this.setTransitioning(!1),t.trigger(Event.HIDDEN),t.removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE))};0===t.height()||"none"===t.css("display")?n():t.height(0).one(Util.TRANSITION_END,n).mmEmulateTransitionEnd(350)}setTransitioning(e){this.transitioning=e}dispose(){$.removeData(this.element,DATA_KEY),$(this.element).find(this.config.parentTrigger).children(this.config.triggerElement).off(Event.CLICK_DATA_API),this.transitioning=null,this.config=null,this.element=null}static jQueryInterface(e){return this.each((function(){const t=$(this);let s=t.data(DATA_KEY);const n={...Default,...t.data(),..."object"==typeof e&&e?e:{}};if(s||(s=new MetisMenu(this,n),t.data(DATA_KEY,s)),"string"==typeof e){if(void 0===s[e])throw new Error(`No method named "${e}"`);s[e]()}}))}}$.fn[NAME]=MetisMenu.jQueryInterface,$.fn[NAME].Constructor=MetisMenu,$.fn[NAME].noConflict=()=>($.fn[NAME]=JQUERY_NO_CONFLICT,MetisMenu.jQueryInterface);export default MetisMenu; 9 | //# sourceMappingURL=metisMenu.esm.min.js.map -------------------------------------------------------------------------------- /dist/metisMenu.esm.min.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["../src/util.js","../src/index.js"],"names":["Util","$","TRANSITION_END","[object Object]","element","trigger","supportsTransitionEnd","Boolean","transitionEndEmulator","duration","called","this","one","setTimeout","triggerTransitionEnd","fn","mmEmulateTransitionEnd","event","special","bindType","delegateType","target","is","handleObj","handler","apply","arguments","NAME","DATA_KEY","EVENT_KEY","DATA_API_KEY","JQUERY_NO_CONFLICT","TRANSITION_DURATION","Default","toggle","preventDefault","triggerElement","parentTrigger","subMenu","Event","SHOW","SHOWN","HIDE","HIDDEN","CLICK_DATA_API","ClassName","METIS","ACTIVE","COLLAPSE","COLLAPSING","COLLAPSED","MetisMenu","config","transitioning","init","self","conf","el","addClass","find","children","attr","parents","has","not","on","e","eTar","paRent","parent","sibLi","siblings","sibTrigger","hasClass","removeActive","setActive","onTransitionStart","li","ul","length","show","removeClass","hide","elem","startEvent","isDefaultPrevented","toggleElem","height","setTransitioning","scrollHeight","offsetHeight","complete","onTransitionEnd","css","isTransitioning","removeData","off","each","$this","data","undefined","Error","jQueryInterface","Constructor","noConflict"],"mappings":"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","sourcesContent":["import $ from 'jquery';\n\nconst Util = (($) => { // eslint-disable-line no-shadow\n const TRANSITION_END = 'transitionend';\n\n const Util = { // eslint-disable-line no-shadow\n TRANSITION_END: 'mmTransitionEnd',\n\n triggerTransitionEnd(element) {\n $(element).trigger(TRANSITION_END);\n },\n\n supportsTransitionEnd() {\n return Boolean(TRANSITION_END);\n },\n };\n\n function getSpecialTransitionEndEvent() {\n return {\n bindType: TRANSITION_END,\n delegateType: TRANSITION_END,\n handle(event) {\n if ($(event.target).is(this)) {\n return event\n .handleObj\n .handler\n .apply(this, arguments); // eslint-disable-line prefer-rest-params\n }\n return undefined;\n },\n };\n }\n\n function transitionEndEmulator(duration) {\n let called = false;\n\n $(this).one(Util.TRANSITION_END, () => {\n called = true;\n });\n\n setTimeout(() => {\n if (!called) {\n Util.triggerTransitionEnd(this);\n }\n }, duration);\n\n return this;\n }\n\n function setTransitionEndSupport() {\n $.fn.mmEmulateTransitionEnd = transitionEndEmulator; // eslint-disable-line no-param-reassign\n // eslint-disable-next-line no-param-reassign\n $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent();\n }\n\n setTransitionEndSupport();\n\n return Util;\n})($);\n\nexport default Util;\n","import $ from 'jquery';\nimport Util from './util';\n\nconst NAME = 'metisMenu';\nconst DATA_KEY = 'metisMenu';\nconst EVENT_KEY = `.${DATA_KEY}`;\nconst DATA_API_KEY = '.data-api';\nconst JQUERY_NO_CONFLICT = $.fn[NAME];\nconst TRANSITION_DURATION = 350;\n\nconst Default = {\n toggle: true,\n preventDefault: true,\n triggerElement: 'a',\n parentTrigger: 'li',\n subMenu: 'ul',\n};\n\nconst Event = {\n SHOW: `show${EVENT_KEY}`,\n SHOWN: `shown${EVENT_KEY}`,\n HIDE: `hide${EVENT_KEY}`,\n HIDDEN: `hidden${EVENT_KEY}`,\n CLICK_DATA_API: `click${EVENT_KEY}${DATA_API_KEY}`,\n};\n\nconst ClassName = {\n METIS: 'metismenu',\n ACTIVE: 'mm-active',\n SHOW: 'mm-show',\n COLLAPSE: 'mm-collapse',\n COLLAPSING: 'mm-collapsing',\n COLLAPSED: 'mm-collapsed',\n};\n\nclass MetisMenu {\n // eslint-disable-line no-shadow\n constructor(element, config) {\n this.element = element;\n this.config = {\n ...Default,\n ...config,\n };\n this.transitioning = null;\n\n this.init();\n }\n\n init() {\n const self = this;\n const conf = this.config;\n const el = $(this.element);\n\n el.addClass(ClassName.METIS); // add metismenu class to element\n\n el.find(`${conf.parentTrigger}.${ClassName.ACTIVE}`)\n .children(conf.triggerElement)\n .attr('aria-expanded', 'true'); // add attribute aria-expanded=true the trigger element\n\n el.find(`${conf.parentTrigger}.${ClassName.ACTIVE}`)\n .parents(conf.parentTrigger)\n .addClass(ClassName.ACTIVE);\n\n el.find(`${conf.parentTrigger}.${ClassName.ACTIVE}`)\n .parents(conf.parentTrigger)\n .children(conf.triggerElement)\n .attr('aria-expanded', 'true'); // add attribute aria-expanded=true the triggers of all parents\n\n el.find(`${conf.parentTrigger}.${ClassName.ACTIVE}`)\n .has(conf.subMenu)\n .children(conf.subMenu)\n .addClass(`${ClassName.COLLAPSE} ${ClassName.SHOW}`);\n\n el\n .find(conf.parentTrigger)\n .not(`.${ClassName.ACTIVE}`)\n .has(conf.subMenu)\n .children(conf.subMenu)\n .addClass(ClassName.COLLAPSE);\n\n el\n .find(conf.parentTrigger)\n // .has(conf.subMenu)\n .children(conf.triggerElement)\n .on(Event.CLICK_DATA_API, function (e) { // eslint-disable-line func-names\n const eTar = $(this);\n\n if (eTar.attr('aria-disabled') === 'true') {\n return;\n }\n\n if (conf.preventDefault && eTar.attr('href') === '#') {\n e.preventDefault();\n }\n\n const paRent = eTar.parent(conf.parentTrigger);\n const sibLi = paRent.siblings(conf.parentTrigger);\n const sibTrigger = sibLi.children(conf.triggerElement);\n\n if (paRent.hasClass(ClassName.ACTIVE)) {\n eTar.attr('aria-expanded', 'false');\n self.removeActive(paRent);\n } else {\n eTar.attr('aria-expanded', 'true');\n self.setActive(paRent);\n if (conf.toggle) {\n self.removeActive(sibLi);\n sibTrigger.attr('aria-expanded', 'false');\n }\n }\n\n if (conf.onTransitionStart) {\n conf.onTransitionStart(e);\n }\n });\n }\n\n setActive(li) {\n $(li).addClass(ClassName.ACTIVE);\n const ul = $(li).children(this.config.subMenu);\n if (ul.length > 0 && !ul.hasClass(ClassName.SHOW)) {\n this.show(ul);\n }\n }\n\n removeActive(li) {\n $(li).removeClass(ClassName.ACTIVE);\n const ul = $(li).children(`${this.config.subMenu}.${ClassName.SHOW}`);\n if (ul.length > 0) {\n this.hide(ul);\n }\n }\n\n show(element) {\n if (this.transitioning || $(element).hasClass(ClassName.COLLAPSING)) {\n return;\n }\n const elem = $(element);\n\n const startEvent = $.Event(Event.SHOW);\n elem.trigger(startEvent);\n\n if (startEvent.isDefaultPrevented()) {\n return;\n }\n\n elem.parent(this.config.parentTrigger).addClass(ClassName.ACTIVE);\n\n if (this.config.toggle) {\n const toggleElem = elem.parent(this.config.parentTrigger).siblings().children(`${this.config.subMenu}.${ClassName.SHOW}`);\n this.hide(toggleElem);\n }\n\n elem\n .removeClass(ClassName.COLLAPSE)\n .addClass(ClassName.COLLAPSING)\n .height(0);\n\n this.setTransitioning(true);\n\n const complete = () => {\n // check if disposed\n if (!this.config || !this.element) {\n return;\n }\n elem\n .removeClass(ClassName.COLLAPSING)\n .addClass(`${ClassName.COLLAPSE} ${ClassName.SHOW}`)\n .height('');\n\n this.setTransitioning(false);\n\n elem.trigger(Event.SHOWN);\n };\n\n elem\n .height(element[0].scrollHeight)\n .one(Util.TRANSITION_END, complete)\n .mmEmulateTransitionEnd(TRANSITION_DURATION);\n }\n\n hide(element) {\n if (\n this.transitioning || !$(element).hasClass(ClassName.SHOW)\n ) {\n return;\n }\n\n const elem = $(element);\n\n const startEvent = $.Event(Event.HIDE);\n elem.trigger(startEvent);\n\n if (startEvent.isDefaultPrevented()) {\n return;\n }\n\n elem.parent(this.config.parentTrigger).removeClass(ClassName.ACTIVE);\n // eslint-disable-next-line no-unused-expressions\n elem.height(elem.height())[0].offsetHeight;\n\n elem\n .addClass(ClassName.COLLAPSING)\n .removeClass(ClassName.COLLAPSE)\n .removeClass(ClassName.SHOW);\n\n this.setTransitioning(true);\n\n const complete = () => {\n // check if disposed\n if (!this.config || !this.element) {\n return;\n }\n if (this.transitioning && this.config.onTransitionEnd) {\n this.config.onTransitionEnd();\n }\n\n this.setTransitioning(false);\n elem.trigger(Event.HIDDEN);\n\n elem\n .removeClass(ClassName.COLLAPSING)\n .addClass(ClassName.COLLAPSE);\n };\n\n if (elem.height() === 0 || elem.css('display') === 'none') {\n complete();\n } else {\n elem\n .height(0)\n .one(Util.TRANSITION_END, complete)\n .mmEmulateTransitionEnd(TRANSITION_DURATION);\n }\n }\n\n setTransitioning(isTransitioning) {\n this.transitioning = isTransitioning;\n }\n\n dispose() {\n $.removeData(this.element, DATA_KEY);\n\n $(this.element)\n .find(this.config.parentTrigger)\n // .has(this.config.subMenu)\n .children(this.config.triggerElement)\n .off(Event.CLICK_DATA_API);\n\n this.transitioning = null;\n this.config = null;\n this.element = null;\n }\n\n static jQueryInterface(config) {\n // eslint-disable-next-line func-names\n return this.each(function () {\n const $this = $(this);\n let data = $this.data(DATA_KEY);\n const conf = {\n ...Default,\n ...$this.data(),\n ...(typeof config === 'object' && config ? config : {}),\n };\n\n if (!data) {\n data = new MetisMenu(this, conf);\n $this.data(DATA_KEY, data);\n }\n\n if (typeof config === 'string') {\n if (data[config] === undefined) {\n throw new Error(`No method named \"${config}\"`);\n }\n data[config]();\n }\n });\n }\n}\n/**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n$.fn[NAME] = MetisMenu.jQueryInterface; // eslint-disable-line no-param-reassign\n$.fn[NAME].Constructor = MetisMenu; // eslint-disable-line no-param-reassign\n$.fn[NAME].noConflict = () => {\n // eslint-disable-line no-param-reassign\n $.fn[NAME] = JQUERY_NO_CONFLICT; // eslint-disable-line no-param-reassign\n return MetisMenu.jQueryInterface;\n};\n\nexport default MetisMenu;\n"]} -------------------------------------------------------------------------------- /dist/metisMenu.js: -------------------------------------------------------------------------------- 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 (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 | 14 | function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } 15 | 16 | var $__default = /*#__PURE__*/_interopDefaultLegacy($); 17 | 18 | const Util = (($) => { // eslint-disable-line no-shadow 19 | const TRANSITION_END = 'transitionend'; 20 | 21 | const Util = { // eslint-disable-line no-shadow 22 | TRANSITION_END: 'mmTransitionEnd', 23 | 24 | triggerTransitionEnd(element) { 25 | $(element).trigger(TRANSITION_END); 26 | }, 27 | 28 | supportsTransitionEnd() { 29 | return Boolean(TRANSITION_END); 30 | }, 31 | }; 32 | 33 | function getSpecialTransitionEndEvent() { 34 | return { 35 | bindType: TRANSITION_END, 36 | delegateType: TRANSITION_END, 37 | handle(event) { 38 | if ($(event.target).is(this)) { 39 | return event 40 | .handleObj 41 | .handler 42 | .apply(this, arguments); // eslint-disable-line prefer-rest-params 43 | } 44 | return undefined; 45 | }, 46 | }; 47 | } 48 | 49 | function transitionEndEmulator(duration) { 50 | let called = false; 51 | 52 | $(this).one(Util.TRANSITION_END, () => { 53 | called = true; 54 | }); 55 | 56 | setTimeout(() => { 57 | if (!called) { 58 | Util.triggerTransitionEnd(this); 59 | } 60 | }, duration); 61 | 62 | return this; 63 | } 64 | 65 | function setTransitionEndSupport() { 66 | $.fn.mmEmulateTransitionEnd = transitionEndEmulator; // eslint-disable-line no-param-reassign 67 | // eslint-disable-next-line no-param-reassign 68 | $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent(); 69 | } 70 | 71 | setTransitionEndSupport(); 72 | 73 | return Util; 74 | })($__default['default']); 75 | 76 | const NAME = 'metisMenu'; 77 | const DATA_KEY = 'metisMenu'; 78 | const EVENT_KEY = `.${DATA_KEY}`; 79 | const DATA_API_KEY = '.data-api'; 80 | const JQUERY_NO_CONFLICT = $__default['default'].fn[NAME]; 81 | const TRANSITION_DURATION = 350; 82 | 83 | const Default = { 84 | toggle: true, 85 | preventDefault: true, 86 | triggerElement: 'a', 87 | parentTrigger: 'li', 88 | subMenu: 'ul', 89 | }; 90 | 91 | const Event = { 92 | SHOW: `show${EVENT_KEY}`, 93 | SHOWN: `shown${EVENT_KEY}`, 94 | HIDE: `hide${EVENT_KEY}`, 95 | HIDDEN: `hidden${EVENT_KEY}`, 96 | CLICK_DATA_API: `click${EVENT_KEY}${DATA_API_KEY}`, 97 | }; 98 | 99 | const ClassName = { 100 | METIS: 'metismenu', 101 | ACTIVE: 'mm-active', 102 | SHOW: 'mm-show', 103 | COLLAPSE: 'mm-collapse', 104 | COLLAPSING: 'mm-collapsing', 105 | COLLAPSED: 'mm-collapsed', 106 | }; 107 | 108 | class MetisMenu { 109 | // eslint-disable-line no-shadow 110 | constructor(element, config) { 111 | this.element = element; 112 | this.config = { 113 | ...Default, 114 | ...config, 115 | }; 116 | this.transitioning = null; 117 | 118 | this.init(); 119 | } 120 | 121 | init() { 122 | const self = this; 123 | const conf = this.config; 124 | const el = $__default['default'](this.element); 125 | 126 | el.addClass(ClassName.METIS); // add metismenu class to element 127 | 128 | el.find(`${conf.parentTrigger}.${ClassName.ACTIVE}`) 129 | .children(conf.triggerElement) 130 | .attr('aria-expanded', 'true'); // add attribute aria-expanded=true the trigger element 131 | 132 | el.find(`${conf.parentTrigger}.${ClassName.ACTIVE}`) 133 | .parents(conf.parentTrigger) 134 | .addClass(ClassName.ACTIVE); 135 | 136 | el.find(`${conf.parentTrigger}.${ClassName.ACTIVE}`) 137 | .parents(conf.parentTrigger) 138 | .children(conf.triggerElement) 139 | .attr('aria-expanded', 'true'); // add attribute aria-expanded=true the triggers of all parents 140 | 141 | el.find(`${conf.parentTrigger}.${ClassName.ACTIVE}`) 142 | .has(conf.subMenu) 143 | .children(conf.subMenu) 144 | .addClass(`${ClassName.COLLAPSE} ${ClassName.SHOW}`); 145 | 146 | el 147 | .find(conf.parentTrigger) 148 | .not(`.${ClassName.ACTIVE}`) 149 | .has(conf.subMenu) 150 | .children(conf.subMenu) 151 | .addClass(ClassName.COLLAPSE); 152 | 153 | el 154 | .find(conf.parentTrigger) 155 | // .has(conf.subMenu) 156 | .children(conf.triggerElement) 157 | .on(Event.CLICK_DATA_API, function (e) { // eslint-disable-line func-names 158 | const eTar = $__default['default'](this); 159 | 160 | if (eTar.attr('aria-disabled') === 'true') { 161 | return; 162 | } 163 | 164 | if (conf.preventDefault && eTar.attr('href') === '#') { 165 | e.preventDefault(); 166 | } 167 | 168 | const paRent = eTar.parent(conf.parentTrigger); 169 | const sibLi = paRent.siblings(conf.parentTrigger); 170 | const sibTrigger = sibLi.children(conf.triggerElement); 171 | 172 | if (paRent.hasClass(ClassName.ACTIVE)) { 173 | eTar.attr('aria-expanded', 'false'); 174 | self.removeActive(paRent); 175 | } else { 176 | eTar.attr('aria-expanded', 'true'); 177 | self.setActive(paRent); 178 | if (conf.toggle) { 179 | self.removeActive(sibLi); 180 | sibTrigger.attr('aria-expanded', 'false'); 181 | } 182 | } 183 | 184 | if (conf.onTransitionStart) { 185 | conf.onTransitionStart(e); 186 | } 187 | }); 188 | } 189 | 190 | setActive(li) { 191 | $__default['default'](li).addClass(ClassName.ACTIVE); 192 | const ul = $__default['default'](li).children(this.config.subMenu); 193 | if (ul.length > 0 && !ul.hasClass(ClassName.SHOW)) { 194 | this.show(ul); 195 | } 196 | } 197 | 198 | removeActive(li) { 199 | $__default['default'](li).removeClass(ClassName.ACTIVE); 200 | const ul = $__default['default'](li).children(`${this.config.subMenu}.${ClassName.SHOW}`); 201 | if (ul.length > 0) { 202 | this.hide(ul); 203 | } 204 | } 205 | 206 | show(element) { 207 | if (this.transitioning || $__default['default'](element).hasClass(ClassName.COLLAPSING)) { 208 | return; 209 | } 210 | const elem = $__default['default'](element); 211 | 212 | const startEvent = $__default['default'].Event(Event.SHOW); 213 | elem.trigger(startEvent); 214 | 215 | if (startEvent.isDefaultPrevented()) { 216 | return; 217 | } 218 | 219 | elem.parent(this.config.parentTrigger).addClass(ClassName.ACTIVE); 220 | 221 | if (this.config.toggle) { 222 | const toggleElem = elem.parent(this.config.parentTrigger).siblings().children(`${this.config.subMenu}.${ClassName.SHOW}`); 223 | this.hide(toggleElem); 224 | } 225 | 226 | elem 227 | .removeClass(ClassName.COLLAPSE) 228 | .addClass(ClassName.COLLAPSING) 229 | .height(0); 230 | 231 | this.setTransitioning(true); 232 | 233 | const complete = () => { 234 | // check if disposed 235 | if (!this.config || !this.element) { 236 | return; 237 | } 238 | elem 239 | .removeClass(ClassName.COLLAPSING) 240 | .addClass(`${ClassName.COLLAPSE} ${ClassName.SHOW}`) 241 | .height(''); 242 | 243 | this.setTransitioning(false); 244 | 245 | elem.trigger(Event.SHOWN); 246 | }; 247 | 248 | elem 249 | .height(element[0].scrollHeight) 250 | .one(Util.TRANSITION_END, complete) 251 | .mmEmulateTransitionEnd(TRANSITION_DURATION); 252 | } 253 | 254 | hide(element) { 255 | if ( 256 | this.transitioning || !$__default['default'](element).hasClass(ClassName.SHOW) 257 | ) { 258 | return; 259 | } 260 | 261 | const elem = $__default['default'](element); 262 | 263 | const startEvent = $__default['default'].Event(Event.HIDE); 264 | elem.trigger(startEvent); 265 | 266 | if (startEvent.isDefaultPrevented()) { 267 | return; 268 | } 269 | 270 | elem.parent(this.config.parentTrigger).removeClass(ClassName.ACTIVE); 271 | // eslint-disable-next-line no-unused-expressions 272 | elem.height(elem.height())[0].offsetHeight; 273 | 274 | elem 275 | .addClass(ClassName.COLLAPSING) 276 | .removeClass(ClassName.COLLAPSE) 277 | .removeClass(ClassName.SHOW); 278 | 279 | this.setTransitioning(true); 280 | 281 | const complete = () => { 282 | // check if disposed 283 | if (!this.config || !this.element) { 284 | return; 285 | } 286 | if (this.transitioning && this.config.onTransitionEnd) { 287 | this.config.onTransitionEnd(); 288 | } 289 | 290 | this.setTransitioning(false); 291 | elem.trigger(Event.HIDDEN); 292 | 293 | elem 294 | .removeClass(ClassName.COLLAPSING) 295 | .addClass(ClassName.COLLAPSE); 296 | }; 297 | 298 | if (elem.height() === 0 || elem.css('display') === 'none') { 299 | complete(); 300 | } else { 301 | elem 302 | .height(0) 303 | .one(Util.TRANSITION_END, complete) 304 | .mmEmulateTransitionEnd(TRANSITION_DURATION); 305 | } 306 | } 307 | 308 | setTransitioning(isTransitioning) { 309 | this.transitioning = isTransitioning; 310 | } 311 | 312 | dispose() { 313 | $__default['default'].removeData(this.element, DATA_KEY); 314 | 315 | $__default['default'](this.element) 316 | .find(this.config.parentTrigger) 317 | // .has(this.config.subMenu) 318 | .children(this.config.triggerElement) 319 | .off(Event.CLICK_DATA_API); 320 | 321 | this.transitioning = null; 322 | this.config = null; 323 | this.element = null; 324 | } 325 | 326 | static jQueryInterface(config) { 327 | // eslint-disable-next-line func-names 328 | return this.each(function () { 329 | const $this = $__default['default'](this); 330 | let data = $this.data(DATA_KEY); 331 | const conf = { 332 | ...Default, 333 | ...$this.data(), 334 | ...(typeof config === 'object' && config ? config : {}), 335 | }; 336 | 337 | if (!data) { 338 | data = new MetisMenu(this, conf); 339 | $this.data(DATA_KEY, data); 340 | } 341 | 342 | if (typeof config === 'string') { 343 | if (data[config] === undefined) { 344 | throw new Error(`No method named "${config}"`); 345 | } 346 | data[config](); 347 | } 348 | }); 349 | } 350 | } 351 | /** 352 | * ------------------------------------------------------------------------ 353 | * jQuery 354 | * ------------------------------------------------------------------------ 355 | */ 356 | 357 | $__default['default'].fn[NAME] = MetisMenu.jQueryInterface; // eslint-disable-line no-param-reassign 358 | $__default['default'].fn[NAME].Constructor = MetisMenu; // eslint-disable-line no-param-reassign 359 | $__default['default'].fn[NAME].noConflict = () => { 360 | // eslint-disable-line no-param-reassign 361 | $__default['default'].fn[NAME] = JQUERY_NO_CONFLICT; // eslint-disable-line no-param-reassign 362 | return MetisMenu.jQueryInterface; 363 | }; 364 | 365 | return MetisMenu; 366 | 367 | }))); 368 | //# sourceMappingURL=metisMenu.js.map 369 | -------------------------------------------------------------------------------- /dist/metisMenu.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * metismenu https://github.com/onokumus/metismenu#readme 3 | * A collapsible jQuery menu plugin 4 | * @version 3.0.6 5 | * @author Osman Nuri Okumus (https://github.com/onokumus) 6 | * @license: MIT 7 | */.metismenu .arrow{float:right;line-height:1.42857}*[dir=rtl] .metismenu .arrow{float:left}.metismenu .glyphicon.arrow:before{content:""}.metismenu .mm-active>a>.glyphicon.arrow:before{content:""}.metismenu .fa.arrow:before{content:""}.metismenu .mm-active>a>.fa.arrow:before{content:""}.metismenu .ion.arrow:before{content:""}.metismenu .mm-active>a>.ion.arrow:before{content:""}.metismenu .plus-times{float:right}*[dir=rtl] .metismenu .plus-times{float:left}.metismenu .fa.plus-times:before{content:""}.metismenu .mm-active>a>.fa.plus-times{transform:rotate(45deg)}.metismenu .plus-minus{float:right}*[dir=rtl] .metismenu .plus-minus{float:left}.metismenu .fa.plus-minus:before{content:""}.metismenu .mm-active>a>.fa.plus-minus:before{content:""}.metismenu .mm-collapse:not(.mm-show){display:none}.metismenu .mm-collapsing{position:relative;height:0;overflow:hidden;transition-timing-function:ease;transition-duration:.35s;transition-property:height,visibility}.metismenu .has-arrow{position:relative}.metismenu .has-arrow::after{position:absolute;content:"";width:.5em;height:.5em;border-width:1px 0 0 1px;border-style:solid;border-color:initial;right:1em;transform:rotate(-45deg) translate(0, -50%);transform-origin:top;top:50%;transition:all .3s ease-out}*[dir=rtl] .metismenu .has-arrow::after{right:auto;left:1em;transform:rotate(135deg) translate(0, -50%)}.metismenu .mm-active>.has-arrow::after,.metismenu .has-arrow[aria-expanded=true]::after{transform:rotate(-135deg) translate(0, -50%)}*[dir=rtl] .metismenu .mm-active>.has-arrow::after,*[dir=rtl] .metismenu .has-arrow[aria-expanded=true]::after{transform:rotate(225deg) translate(0, -50%)}/*# sourceMappingURL=metisMenu.min.css.map */ 8 | -------------------------------------------------------------------------------- /dist/metisMenu.min.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sourceRoot":"","sources":["../src/metisMenu.scss"],"names":[],"mappings":"CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,kBACE,YACA,oBAEF,6BACE,WAQF,mCACE,YAEF,gDACE,YAQF,4BACE,YAEF,yCACE,YAQF,6BACE,YAEF,0CACE,YAEF,uBACE,YAEF,kCACE,WAEF,iCACE,YAEF,uCACE,wBAEF,uBACE,YAEF,kCACE,WAEF,iCACE,YAEF,8CACE,YAEF,sCACE,aAGF,0BACE,kBACA,SACA,gBACA,gCACA,yBACA,sCAGF,sBACE,kBAGF,6BACE,kBACA,WACA,WACA,YACA,yBACA,mBACA,qBACA,UACA,4CACA,qBACA,QACA,4BAGF,wCACE,WACA,SACA,4CAGF,yFAEE,6CAGF,+GAEE","file":"metisMenu.min.css"} -------------------------------------------------------------------------------- /dist/metisMenu.min.js: -------------------------------------------------------------------------------- 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 (https://github.com/onokumus) 6 | * @license: MIT 7 | */ 8 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("jquery")):"function"==typeof define&&define.amd?define(["jquery"],t):(e="undefined"!=typeof globalThis?globalThis:e||self).metisMenu=t(e.$)}(this,(function(e){"use strict";function t(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var n=t(e);const i=(e=>{const t="transitionend",n={TRANSITION_END:"mmTransitionEnd",triggerTransitionEnd(n){e(n).trigger(t)},supportsTransitionEnd:()=>Boolean(t)};function i(t){let i=!1;return e(this).one(n.TRANSITION_END,(()=>{i=!0})),setTimeout((()=>{i||n.triggerTransitionEnd(this)}),t),this}return e.fn.mmEmulateTransitionEnd=i,e.event.special[n.TRANSITION_END]={bindType:t,delegateType:t,handle(t){if(e(t.target).is(this))return t.handleObj.handler.apply(this,arguments)}},n})(n.default),s="metisMenu",r="metisMenu",a=n.default.fn[s],o={toggle:!0,preventDefault:!0,triggerElement:"a",parentTrigger:"li",subMenu:"ul"},l={SHOW:"show.metisMenu",SHOWN:"shown.metisMenu",HIDE:"hide.metisMenu",HIDDEN:"hidden.metisMenu",CLICK_DATA_API:"click.metisMenu.data-api"},d="metismenu",g="mm-active",h="mm-show",u="mm-collapse",f="mm-collapsing";class c{constructor(e,t){this.element=e,this.config={...o,...t},this.transitioning=null,this.init()}init(){const e=this,t=this.config,i=n.default(this.element);i.addClass(d),i.find(`${t.parentTrigger}.${g}`).children(t.triggerElement).attr("aria-expanded","true"),i.find(`${t.parentTrigger}.${g}`).parents(t.parentTrigger).addClass(g),i.find(`${t.parentTrigger}.${g}`).parents(t.parentTrigger).children(t.triggerElement).attr("aria-expanded","true"),i.find(`${t.parentTrigger}.${g}`).has(t.subMenu).children(t.subMenu).addClass(`${u} ${h}`),i.find(t.parentTrigger).not(`.${g}`).has(t.subMenu).children(t.subMenu).addClass(u),i.find(t.parentTrigger).children(t.triggerElement).on(l.CLICK_DATA_API,(function(i){const s=n.default(this);if("true"===s.attr("aria-disabled"))return;t.preventDefault&&"#"===s.attr("href")&&i.preventDefault();const r=s.parent(t.parentTrigger),a=r.siblings(t.parentTrigger),o=a.children(t.triggerElement);r.hasClass(g)?(s.attr("aria-expanded","false"),e.removeActive(r)):(s.attr("aria-expanded","true"),e.setActive(r),t.toggle&&(e.removeActive(a),o.attr("aria-expanded","false"))),t.onTransitionStart&&t.onTransitionStart(i)}))}setActive(e){n.default(e).addClass(g);const t=n.default(e).children(this.config.subMenu);t.length>0&&!t.hasClass(h)&&this.show(t)}removeActive(e){n.default(e).removeClass(g);const t=n.default(e).children(`${this.config.subMenu}.${h}`);t.length>0&&this.hide(t)}show(e){if(this.transitioning||n.default(e).hasClass(f))return;const t=n.default(e),s=n.default.Event(l.SHOW);if(t.trigger(s),s.isDefaultPrevented())return;if(t.parent(this.config.parentTrigger).addClass(g),this.config.toggle){const e=t.parent(this.config.parentTrigger).siblings().children(`${this.config.subMenu}.${h}`);this.hide(e)}t.removeClass(u).addClass(f).height(0),this.setTransitioning(!0);t.height(e[0].scrollHeight).one(i.TRANSITION_END,(()=>{this.config&&this.element&&(t.removeClass(f).addClass(`${u} ${h}`).height(""),this.setTransitioning(!1),t.trigger(l.SHOWN))})).mmEmulateTransitionEnd(350)}hide(e){if(this.transitioning||!n.default(e).hasClass(h))return;const t=n.default(e),s=n.default.Event(l.HIDE);if(t.trigger(s),s.isDefaultPrevented())return;t.parent(this.config.parentTrigger).removeClass(g),t.height(t.height())[0].offsetHeight,t.addClass(f).removeClass(u).removeClass(h),this.setTransitioning(!0);const r=()=>{this.config&&this.element&&(this.transitioning&&this.config.onTransitionEnd&&this.config.onTransitionEnd(),this.setTransitioning(!1),t.trigger(l.HIDDEN),t.removeClass(f).addClass(u))};0===t.height()||"none"===t.css("display")?r():t.height(0).one(i.TRANSITION_END,r).mmEmulateTransitionEnd(350)}setTransitioning(e){this.transitioning=e}dispose(){n.default.removeData(this.element,r),n.default(this.element).find(this.config.parentTrigger).children(this.config.triggerElement).off(l.CLICK_DATA_API),this.transitioning=null,this.config=null,this.element=null}static jQueryInterface(e){return this.each((function(){const t=n.default(this);let i=t.data(r);const s={...o,...t.data(),..."object"==typeof e&&e?e:{}};if(i||(i=new c(this,s),t.data(r,i)),"string"==typeof e){if(void 0===i[e])throw new Error(`No method named "${e}"`);i[e]()}}))}}return n.default.fn[s]=c.jQueryInterface,n.default.fn[s].Constructor=c,n.default.fn[s].noConflict=()=>(n.default.fn[s]=a,c.jQueryInterface),c})); 9 | //# sourceMappingURL=metisMenu.min.js.map -------------------------------------------------------------------------------- /dist/metisMenu.min.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["../src/util.js","../src/index.js"],"names":["Util","$","TRANSITION_END","[object Object]","element","trigger","supportsTransitionEnd","Boolean","transitionEndEmulator","duration","called","this","one","setTimeout","triggerTransitionEnd","fn","mmEmulateTransitionEnd","event","special","bindType","delegateType","target","is","handleObj","handler","apply","arguments","NAME","DATA_KEY","JQUERY_NO_CONFLICT","Default","toggle","preventDefault","triggerElement","parentTrigger","subMenu","Event","SHOW","SHOWN","HIDE","HIDDEN","CLICK_DATA_API","ClassName","MetisMenu","config","transitioning","init","self","conf","el","addClass","find","children","attr","parents","has","not","on","e","eTar","paRent","parent","sibLi","siblings","sibTrigger","hasClass","removeActive","setActive","onTransitionStart","li","ul","length","show","removeClass","hide","elem","startEvent","isDefaultPrevented","toggleElem","height","setTransitioning","scrollHeight","offsetHeight","complete","onTransitionEnd","css","isTransitioning","removeData","off","each","$this","data","undefined","Error","jQueryInterface","Constructor","noConflict"],"mappings":";;;;;;;6VAEA,MAAMA,EAAO,CAAEC,IACb,MAAMC,EAAiB,gBAEjBF,EAAO,CACXE,eAAgB,kBAEhBC,qBAAqBC,GACnBH,EAAEG,GAASC,QAAQH,IAGrBI,sBAAqB,IACZC,QAAQL,IAoBnB,SAASM,EAAsBC,GAC7B,IAAIC,GAAS,EAYb,OAVAT,EAAEU,MAAMC,IAAIZ,EAAKE,gBAAgB,KAC/BQ,GAAS,KAGXG,YAAW,KACJH,GACHV,EAAKc,qBAAqBH,QAE3BF,GAEIE,KAWT,OAPEV,EAAEc,GAAGC,uBAAyBR,EAE9BP,EAAEgB,MAAMC,QAAQlB,EAAKE,gBAlCd,CACLiB,SAAUjB,EACVkB,aAAclB,EACdC,OAAOc,GACL,GAAIhB,EAAEgB,EAAMI,QAAQC,GAAGX,MACrB,OAAOM,EACJM,UACAC,QACAC,MAAMd,KAAMe,aA+BhB1B,GAvDI,CAwDVC,EAAAA,SCvDG0B,EAAO,YACPC,EAAW,YAGXC,EAAqB5B,EAAAA,QAAEc,GAAGY,GAG1BG,EAAU,CACdC,QAAQ,EACRC,gBAAgB,EAChBC,eAAgB,IAChBC,cAAe,KACfC,QAAS,MAGLC,EAAQ,CACZC,KAAM,iBACNC,MAAO,kBACPC,KAAM,iBACNC,OAAQ,mBACRC,eAAgB,4BAGZC,EACG,YADHA,EAEI,YAFJA,EAGE,UAHFA,EAIM,cAJNA,EAKQ,gBAId,MAAMC,EAEJxC,YAAYC,EAASwC,GACnBjC,KAAKP,QAAUA,EACfO,KAAKiC,OAAS,IACTd,KACAc,GAELjC,KAAKkC,cAAgB,KAErBlC,KAAKmC,OAGP3C,OACE,MAAM4C,EAAOpC,KACPqC,EAAOrC,KAAKiC,OACZK,EAAKhD,EAAAA,QAAEU,KAAKP,SAElB6C,EAAGC,SAASR,GAEZO,EAAGE,KAAK,GAAGH,EAAKd,iBAAiBQ,KAC9BU,SAASJ,EAAKf,gBACdoB,KAAK,gBAAiB,QAEzBJ,EAAGE,KAAK,GAAGH,EAAKd,iBAAiBQ,KAC9BY,QAAQN,EAAKd,eACbgB,SAASR,GAEZO,EAAGE,KAAK,GAAGH,EAAKd,iBAAiBQ,KAC9BY,QAAQN,EAAKd,eACbkB,SAASJ,EAAKf,gBACdoB,KAAK,gBAAiB,QAEzBJ,EAAGE,KAAK,GAAGH,EAAKd,iBAAiBQ,KAC9Ba,IAAIP,EAAKb,SACTiB,SAASJ,EAAKb,SACde,SAAS,GAAGR,KAAsBA,KAErCO,EACGE,KAAKH,EAAKd,eACVsB,IAAI,IAAId,KACRa,IAAIP,EAAKb,SACTiB,SAASJ,EAAKb,SACde,SAASR,GAEZO,EACGE,KAAKH,EAAKd,eAEVkB,SAASJ,EAAKf,gBACdwB,GAAGrB,EAAMK,gBAAgB,SAAUiB,GAClC,MAAMC,EAAO1D,EAAAA,QAAEU,MAEf,GAAmC,SAA/BgD,EAAKN,KAAK,iBACZ,OAGEL,EAAKhB,gBAAwC,MAAtB2B,EAAKN,KAAK,SACnCK,EAAE1B,iBAGJ,MAAM4B,EAASD,EAAKE,OAAOb,EAAKd,eAC1B4B,EAAQF,EAAOG,SAASf,EAAKd,eAC7B8B,EAAaF,EAAMV,SAASJ,EAAKf,gBAEnC2B,EAAOK,SAASvB,IAClBiB,EAAKN,KAAK,gBAAiB,SAC3BN,EAAKmB,aAAaN,KAElBD,EAAKN,KAAK,gBAAiB,QAC3BN,EAAKoB,UAAUP,GACXZ,EAAKjB,SACPgB,EAAKmB,aAAaJ,GAClBE,EAAWX,KAAK,gBAAiB,WAIjCL,EAAKoB,mBACPpB,EAAKoB,kBAAkBV,MAK/BvD,UAAUkE,GACRpE,EAAAA,QAAEoE,GAAInB,SAASR,GACf,MAAM4B,EAAKrE,EAAAA,QAAEoE,GAAIjB,SAASzC,KAAKiC,OAAOT,SAClCmC,EAAGC,OAAS,IAAMD,EAAGL,SAASvB,IAChC/B,KAAK6D,KAAKF,GAIdnE,aAAakE,GACXpE,EAAAA,QAAEoE,GAAII,YAAY/B,GAClB,MAAM4B,EAAKrE,EAAAA,QAAEoE,GAAIjB,SAAS,GAAGzC,KAAKiC,OAAOT,WAAWO,KAChD4B,EAAGC,OAAS,GACd5D,KAAK+D,KAAKJ,GAIdnE,KAAKC,GACH,GAAIO,KAAKkC,eAAiB5C,EAAAA,QAAEG,GAAS6D,SAASvB,GAC5C,OAEF,MAAMiC,EAAO1E,EAAAA,QAAEG,GAETwE,EAAa3E,EAAAA,QAAEmC,MAAMA,EAAMC,MAGjC,GAFAsC,EAAKtE,QAAQuE,GAETA,EAAWC,qBACb,OAKF,GAFAF,EAAKd,OAAOlD,KAAKiC,OAAOV,eAAegB,SAASR,GAE5C/B,KAAKiC,OAAOb,OAAQ,CACtB,MAAM+C,EAAaH,EAAKd,OAAOlD,KAAKiC,OAAOV,eAAe6B,WAAWX,SAAS,GAAGzC,KAAKiC,OAAOT,WAAWO,KACxG/B,KAAK+D,KAAKI,GAGZH,EACGF,YAAY/B,GACZQ,SAASR,GACTqC,OAAO,GAEVpE,KAAKqE,kBAAiB,GAiBtBL,EACGI,OAAO3E,EAAQ,GAAG6E,cAClBrE,IAAIZ,EAAKE,gBAjBK,KAEVS,KAAKiC,QAAWjC,KAAKP,UAG1BuE,EACGF,YAAY/B,GACZQ,SAAS,GAAGR,KAAsBA,KAClCqC,OAAO,IAEVpE,KAAKqE,kBAAiB,GAEtBL,EAAKtE,QAAQ+B,EAAME,WAMlBtB,uBA1KqB,KA6K1Bb,KAAKC,GACH,GACEO,KAAKkC,gBAAkB5C,EAAAA,QAAEG,GAAS6D,SAASvB,GAE3C,OAGF,MAAMiC,EAAO1E,EAAAA,QAAEG,GAETwE,EAAa3E,EAAAA,QAAEmC,MAAMA,EAAMG,MAGjC,GAFAoC,EAAKtE,QAAQuE,GAETA,EAAWC,qBACb,OAGFF,EAAKd,OAAOlD,KAAKiC,OAAOV,eAAeuC,YAAY/B,GAEnDiC,EAAKI,OAAOJ,EAAKI,UAAU,GAAGG,aAE9BP,EACGzB,SAASR,GACT+B,YAAY/B,GACZ+B,YAAY/B,GAEf/B,KAAKqE,kBAAiB,GAEtB,MAAMG,EAAW,KAEVxE,KAAKiC,QAAWjC,KAAKP,UAGtBO,KAAKkC,eAAiBlC,KAAKiC,OAAOwC,iBACpCzE,KAAKiC,OAAOwC,kBAGdzE,KAAKqE,kBAAiB,GACtBL,EAAKtE,QAAQ+B,EAAMI,QAEnBmC,EACGF,YAAY/B,GACZQ,SAASR,KAGQ,IAAlBiC,EAAKI,UAA0C,SAAxBJ,EAAKU,IAAI,WAClCF,IAEAR,EACGI,OAAO,GACPnE,IAAIZ,EAAKE,eAAgBiF,GACzBnE,uBA/NmB,KAmO1Bb,iBAAiBmF,GACf3E,KAAKkC,cAAgByC,EAGvBnF,UACEF,EAAAA,QAAEsF,WAAW5E,KAAKP,QAASwB,GAE3B3B,EAAAA,QAAEU,KAAKP,SACJ+C,KAAKxC,KAAKiC,OAAOV,eAEjBkB,SAASzC,KAAKiC,OAAOX,gBACrBuD,IAAIpD,EAAMK,gBAEb9B,KAAKkC,cAAgB,KACrBlC,KAAKiC,OAAS,KACdjC,KAAKP,QAAU,KAGjBD,uBAAuByC,GAErB,OAAOjC,KAAK8E,MAAK,WACf,MAAMC,EAAQzF,EAAAA,QAAEU,MAChB,IAAIgF,EAAOD,EAAMC,KAAK/D,GACtB,MAAMoB,EAAO,IACRlB,KACA4D,EAAMC,UACa,iBAAX/C,GAAuBA,EAASA,EAAS,IAQtD,GALK+C,IACHA,EAAO,IAAIhD,EAAUhC,KAAMqC,GAC3B0C,EAAMC,KAAK/D,EAAU+D,IAGD,iBAAX/C,EAAqB,CAC9B,QAAqBgD,IAAjBD,EAAK/C,GACP,MAAM,IAAIiD,MAAM,oBAAoBjD,MAEtC+C,EAAK/C,iBAWb3C,EAAAA,QAAEc,GAAGY,GAAQgB,EAAUmD,gBACvB7F,EAAAA,QAAEc,GAAGY,GAAMoE,YAAcpD,EACzB1C,EAAAA,QAAEc,GAAGY,GAAMqE,WAAa,KAEtB/F,EAAAA,QAAEc,GAAGY,GAAQE,EACNc,EAAUmD","sourcesContent":["import $ from 'jquery';\n\nconst Util = (($) => { // eslint-disable-line no-shadow\n const TRANSITION_END = 'transitionend';\n\n const Util = { // eslint-disable-line no-shadow\n TRANSITION_END: 'mmTransitionEnd',\n\n triggerTransitionEnd(element) {\n $(element).trigger(TRANSITION_END);\n },\n\n supportsTransitionEnd() {\n return Boolean(TRANSITION_END);\n },\n };\n\n function getSpecialTransitionEndEvent() {\n return {\n bindType: TRANSITION_END,\n delegateType: TRANSITION_END,\n handle(event) {\n if ($(event.target).is(this)) {\n return event\n .handleObj\n .handler\n .apply(this, arguments); // eslint-disable-line prefer-rest-params\n }\n return undefined;\n },\n };\n }\n\n function transitionEndEmulator(duration) {\n let called = false;\n\n $(this).one(Util.TRANSITION_END, () => {\n called = true;\n });\n\n setTimeout(() => {\n if (!called) {\n Util.triggerTransitionEnd(this);\n }\n }, duration);\n\n return this;\n }\n\n function setTransitionEndSupport() {\n $.fn.mmEmulateTransitionEnd = transitionEndEmulator; // eslint-disable-line no-param-reassign\n // eslint-disable-next-line no-param-reassign\n $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent();\n }\n\n setTransitionEndSupport();\n\n return Util;\n})($);\n\nexport default Util;\n","import $ from 'jquery';\nimport Util from './util';\n\nconst NAME = 'metisMenu';\nconst DATA_KEY = 'metisMenu';\nconst EVENT_KEY = `.${DATA_KEY}`;\nconst DATA_API_KEY = '.data-api';\nconst JQUERY_NO_CONFLICT = $.fn[NAME];\nconst TRANSITION_DURATION = 350;\n\nconst Default = {\n toggle: true,\n preventDefault: true,\n triggerElement: 'a',\n parentTrigger: 'li',\n subMenu: 'ul',\n};\n\nconst Event = {\n SHOW: `show${EVENT_KEY}`,\n SHOWN: `shown${EVENT_KEY}`,\n HIDE: `hide${EVENT_KEY}`,\n HIDDEN: `hidden${EVENT_KEY}`,\n CLICK_DATA_API: `click${EVENT_KEY}${DATA_API_KEY}`,\n};\n\nconst ClassName = {\n METIS: 'metismenu',\n ACTIVE: 'mm-active',\n SHOW: 'mm-show',\n COLLAPSE: 'mm-collapse',\n COLLAPSING: 'mm-collapsing',\n COLLAPSED: 'mm-collapsed',\n};\n\nclass MetisMenu {\n // eslint-disable-line no-shadow\n constructor(element, config) {\n this.element = element;\n this.config = {\n ...Default,\n ...config,\n };\n this.transitioning = null;\n\n this.init();\n }\n\n init() {\n const self = this;\n const conf = this.config;\n const el = $(this.element);\n\n el.addClass(ClassName.METIS); // add metismenu class to element\n\n el.find(`${conf.parentTrigger}.${ClassName.ACTIVE}`)\n .children(conf.triggerElement)\n .attr('aria-expanded', 'true'); // add attribute aria-expanded=true the trigger element\n\n el.find(`${conf.parentTrigger}.${ClassName.ACTIVE}`)\n .parents(conf.parentTrigger)\n .addClass(ClassName.ACTIVE);\n\n el.find(`${conf.parentTrigger}.${ClassName.ACTIVE}`)\n .parents(conf.parentTrigger)\n .children(conf.triggerElement)\n .attr('aria-expanded', 'true'); // add attribute aria-expanded=true the triggers of all parents\n\n el.find(`${conf.parentTrigger}.${ClassName.ACTIVE}`)\n .has(conf.subMenu)\n .children(conf.subMenu)\n .addClass(`${ClassName.COLLAPSE} ${ClassName.SHOW}`);\n\n el\n .find(conf.parentTrigger)\n .not(`.${ClassName.ACTIVE}`)\n .has(conf.subMenu)\n .children(conf.subMenu)\n .addClass(ClassName.COLLAPSE);\n\n el\n .find(conf.parentTrigger)\n // .has(conf.subMenu)\n .children(conf.triggerElement)\n .on(Event.CLICK_DATA_API, function (e) { // eslint-disable-line func-names\n const eTar = $(this);\n\n if (eTar.attr('aria-disabled') === 'true') {\n return;\n }\n\n if (conf.preventDefault && eTar.attr('href') === '#') {\n e.preventDefault();\n }\n\n const paRent = eTar.parent(conf.parentTrigger);\n const sibLi = paRent.siblings(conf.parentTrigger);\n const sibTrigger = sibLi.children(conf.triggerElement);\n\n if (paRent.hasClass(ClassName.ACTIVE)) {\n eTar.attr('aria-expanded', 'false');\n self.removeActive(paRent);\n } else {\n eTar.attr('aria-expanded', 'true');\n self.setActive(paRent);\n if (conf.toggle) {\n self.removeActive(sibLi);\n sibTrigger.attr('aria-expanded', 'false');\n }\n }\n\n if (conf.onTransitionStart) {\n conf.onTransitionStart(e);\n }\n });\n }\n\n setActive(li) {\n $(li).addClass(ClassName.ACTIVE);\n const ul = $(li).children(this.config.subMenu);\n if (ul.length > 0 && !ul.hasClass(ClassName.SHOW)) {\n this.show(ul);\n }\n }\n\n removeActive(li) {\n $(li).removeClass(ClassName.ACTIVE);\n const ul = $(li).children(`${this.config.subMenu}.${ClassName.SHOW}`);\n if (ul.length > 0) {\n this.hide(ul);\n }\n }\n\n show(element) {\n if (this.transitioning || $(element).hasClass(ClassName.COLLAPSING)) {\n return;\n }\n const elem = $(element);\n\n const startEvent = $.Event(Event.SHOW);\n elem.trigger(startEvent);\n\n if (startEvent.isDefaultPrevented()) {\n return;\n }\n\n elem.parent(this.config.parentTrigger).addClass(ClassName.ACTIVE);\n\n if (this.config.toggle) {\n const toggleElem = elem.parent(this.config.parentTrigger).siblings().children(`${this.config.subMenu}.${ClassName.SHOW}`);\n this.hide(toggleElem);\n }\n\n elem\n .removeClass(ClassName.COLLAPSE)\n .addClass(ClassName.COLLAPSING)\n .height(0);\n\n this.setTransitioning(true);\n\n const complete = () => {\n // check if disposed\n if (!this.config || !this.element) {\n return;\n }\n elem\n .removeClass(ClassName.COLLAPSING)\n .addClass(`${ClassName.COLLAPSE} ${ClassName.SHOW}`)\n .height('');\n\n this.setTransitioning(false);\n\n elem.trigger(Event.SHOWN);\n };\n\n elem\n .height(element[0].scrollHeight)\n .one(Util.TRANSITION_END, complete)\n .mmEmulateTransitionEnd(TRANSITION_DURATION);\n }\n\n hide(element) {\n if (\n this.transitioning || !$(element).hasClass(ClassName.SHOW)\n ) {\n return;\n }\n\n const elem = $(element);\n\n const startEvent = $.Event(Event.HIDE);\n elem.trigger(startEvent);\n\n if (startEvent.isDefaultPrevented()) {\n return;\n }\n\n elem.parent(this.config.parentTrigger).removeClass(ClassName.ACTIVE);\n // eslint-disable-next-line no-unused-expressions\n elem.height(elem.height())[0].offsetHeight;\n\n elem\n .addClass(ClassName.COLLAPSING)\n .removeClass(ClassName.COLLAPSE)\n .removeClass(ClassName.SHOW);\n\n this.setTransitioning(true);\n\n const complete = () => {\n // check if disposed\n if (!this.config || !this.element) {\n return;\n }\n if (this.transitioning && this.config.onTransitionEnd) {\n this.config.onTransitionEnd();\n }\n\n this.setTransitioning(false);\n elem.trigger(Event.HIDDEN);\n\n elem\n .removeClass(ClassName.COLLAPSING)\n .addClass(ClassName.COLLAPSE);\n };\n\n if (elem.height() === 0 || elem.css('display') === 'none') {\n complete();\n } else {\n elem\n .height(0)\n .one(Util.TRANSITION_END, complete)\n .mmEmulateTransitionEnd(TRANSITION_DURATION);\n }\n }\n\n setTransitioning(isTransitioning) {\n this.transitioning = isTransitioning;\n }\n\n dispose() {\n $.removeData(this.element, DATA_KEY);\n\n $(this.element)\n .find(this.config.parentTrigger)\n // .has(this.config.subMenu)\n .children(this.config.triggerElement)\n .off(Event.CLICK_DATA_API);\n\n this.transitioning = null;\n this.config = null;\n this.element = null;\n }\n\n static jQueryInterface(config) {\n // eslint-disable-next-line func-names\n return this.each(function () {\n const $this = $(this);\n let data = $this.data(DATA_KEY);\n const conf = {\n ...Default,\n ...$this.data(),\n ...(typeof config === 'object' && config ? config : {}),\n };\n\n if (!data) {\n data = new MetisMenu(this, conf);\n $this.data(DATA_KEY, data);\n }\n\n if (typeof config === 'string') {\n if (data[config] === undefined) {\n throw new Error(`No method named \"${config}\"`);\n }\n data[config]();\n }\n });\n }\n}\n/**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n$.fn[NAME] = MetisMenu.jQueryInterface; // eslint-disable-line no-param-reassign\n$.fn[NAME].Constructor = MetisMenu; // eslint-disable-line no-param-reassign\n$.fn[NAME].noConflict = () => {\n // eslint-disable-line no-param-reassign\n $.fn[NAME] = JQUERY_NO_CONFLICT; // eslint-disable-line no-param-reassign\n return MetisMenu.jQueryInterface;\n};\n\nexport default MetisMenu;\n"]} -------------------------------------------------------------------------------- /docs/ajax-1.html: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /docs/ajax-2.html: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /docs/ajax-3.html: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /docs/ajax-4.html: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /docs/ajax-5.html: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /docs/assets/css/app.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --jumbotron-padding-y: 3rem; 3 | } 4 | 5 | .jumbotron { 6 | padding-top: var(--jumbotron-padding-y); 7 | padding-bottom: var(--jumbotron-padding-y); 8 | margin-bottom: 0; 9 | background-color: #fff; 10 | } 11 | @media (min-width: 768px) { 12 | .jumbotron { 13 | padding-top: calc(var(--jumbotron-padding-y) * 2); 14 | padding-bottom: calc(var(--jumbotron-padding-y) * 2); 15 | } 16 | } 17 | 18 | .jumbotron p:last-child { 19 | margin-bottom: 0; 20 | } 21 | 22 | .jumbotron-heading { 23 | font-weight: 300; 24 | } 25 | 26 | .jumbotron .container { 27 | max-width: 40rem; 28 | } 29 | 30 | footer { 31 | padding-top: 3rem; 32 | padding-bottom: 3rem; 33 | } 34 | 35 | footer p { 36 | margin-bottom: .25rem; 37 | } 38 | 39 | .box-shadow { box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05); } 40 | 41 | #rtlh3 small { 42 | transform: rotateY(180deg); 43 | display: inline-block; 44 | } 45 | -------------------------------------------------------------------------------- /docs/assets/css/metisMenu.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | /*! 3 | * metismenu https://github.com/onokumus/metismenu#readme 4 | * A collapsible jQuery menu plugin 5 | * @version 3.1.0 6 | * @author Osman Nuri Okumus (https://github.com/onokumus) 7 | * @license: MIT 8 | */ 9 | .metismenu .arrow { 10 | float: right; 11 | line-height: 1.42857; 12 | } 13 | 14 | *[dir=rtl] .metismenu .arrow { 15 | float: left; 16 | } 17 | 18 | /* 19 | * Require Bootstrap 3.x 20 | * https://github.com/twbs/bootstrap 21 | */ 22 | .metismenu .glyphicon.arrow:before { 23 | content: ""; 24 | } 25 | 26 | .metismenu .mm-active > a > .glyphicon.arrow:before { 27 | content: ""; 28 | } 29 | 30 | /* 31 | * Require Font-Awesome 32 | * http://fortawesome.github.io/Font-Awesome/ 33 | */ 34 | .metismenu .fa.arrow:before { 35 | content: ""; 36 | } 37 | 38 | .metismenu .mm-active > a > .fa.arrow:before { 39 | content: ""; 40 | } 41 | 42 | /* 43 | * Require Ionicons 44 | * http://ionicons.com/ 45 | */ 46 | .metismenu .ion.arrow:before { 47 | content: ""; 48 | } 49 | 50 | .metismenu .mm-active > a > .ion.arrow:before { 51 | content: ""; 52 | } 53 | 54 | .metismenu .plus-times { 55 | float: right; 56 | } 57 | 58 | *[dir=rtl] .metismenu .plus-times { 59 | float: left; 60 | } 61 | 62 | .metismenu .fa.plus-times:before { 63 | content: ""; 64 | } 65 | 66 | .metismenu .mm-active > a > .fa.plus-times { 67 | transform: rotate(45deg); 68 | } 69 | 70 | .metismenu .plus-minus { 71 | float: right; 72 | } 73 | 74 | *[dir=rtl] .metismenu .plus-minus { 75 | float: left; 76 | } 77 | 78 | .metismenu .fa.plus-minus:before { 79 | content: ""; 80 | } 81 | 82 | .metismenu .mm-active > a > .fa.plus-minus:before { 83 | content: ""; 84 | } 85 | 86 | .metismenu .mm-collapse:not(.mm-show) { 87 | display: none; 88 | } 89 | 90 | .metismenu .mm-collapsing { 91 | position: relative; 92 | height: 0; 93 | overflow: hidden; 94 | transition-timing-function: ease; 95 | transition-duration: 0.35s; 96 | transition-property: height, visibility; 97 | } 98 | 99 | .metismenu .has-arrow { 100 | position: relative; 101 | } 102 | 103 | .metismenu .has-arrow::after { 104 | position: absolute; 105 | content: ""; 106 | width: 0.5em; 107 | height: 0.5em; 108 | border-width: 1px 0 0 1px; 109 | border-style: solid; 110 | border-color: initial; 111 | right: 1em; 112 | transform: rotate(-45deg) translate(0, -50%); 113 | transform-origin: top; 114 | top: 50%; 115 | transition: all 0.3s ease-out; 116 | } 117 | 118 | *[dir=rtl] .metismenu .has-arrow::after { 119 | right: auto; 120 | left: 1em; 121 | transform: rotate(135deg) translate(0, -50%); 122 | } 123 | 124 | .metismenu .mm-active > .has-arrow::after, 125 | .metismenu .has-arrow[aria-expanded=true]::after { 126 | transform: rotate(-135deg) translate(0, -50%); 127 | } 128 | 129 | *[dir=rtl] .metismenu .mm-active > .has-arrow::after, 130 | *[dir=rtl] .metismenu .has-arrow[aria-expanded=true]::after { 131 | transform: rotate(225deg) translate(0, -50%); 132 | } 133 | 134 | /*# sourceMappingURL=metisMenu.css.map */ 135 | -------------------------------------------------------------------------------- /docs/assets/css/metisMenu.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sourceRoot":"","sources":["../src/metisMenu.scss"],"names":[],"mappings":";AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA;EACE;EACA;;;AAEF;EACE;;;AAGF;AAAA;AAAA;AAAA;AAKA;EACE;;;AAEF;EACE;;;AAGF;AAAA;AAAA;AAAA;AAKA;EACE;;;AAEF;EACE;;;AAGF;AAAA;AAAA;AAAA;AAKA;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;AAAA;EAEE;;;AAGF;AAAA;EAEE","file":"metisMenu.css"} -------------------------------------------------------------------------------- /docs/assets/css/mini.css: -------------------------------------------------------------------------------- 1 | .wrap { 2 | margin: 0 auto; 3 | width: 100%; 4 | position: relative; 5 | } 6 | .sidebar { 7 | position: absolute; 8 | top: 0; 9 | left: 0; 10 | bottom: 0; 11 | border-right: 1px solid #b5b5b5; 12 | } 13 | .nav-mini { 14 | width: 50px; 15 | } 16 | .nav-mini ul { 17 | padding: 0; 18 | margin: 0; 19 | list-style: none; 20 | background: #fbfbfb; 21 | } 22 | .nav-mini li { 23 | position: relative; 24 | } 25 | .nav-mini li, .nav-mini a { 26 | display: block; 27 | } 28 | .nav-mini a { 29 | padding: 10px 5px; 30 | text-decoration: none; 31 | color: #808080; 32 | } 33 | .nav-mini a .title { 34 | display: none; 35 | } 36 | .nav-mini .metismenu .collapse, .nav-mini .metismenu .collapsing { 37 | position: absolute; 38 | top: 0; 39 | left: 100%; 40 | min-width: 160px; 41 | } 42 | .nav-mini .metismenu .collapse .collapse, .nav-mini .metismenu .collapse .collapsing { 43 | left: 0; 44 | top: auto; 45 | } 46 | .nav-mini .metismenu > li { 47 | border-bottom: 1px solid #b5b5b5; 48 | } 49 | .nav-mini .metismenu > li > a { 50 | text-align: center; 51 | } 52 | .content { 53 | padding-left: 60px; 54 | background: #fff; 55 | } 56 | -------------------------------------------------------------------------------- /docs/assets/css/mm-faq.css: -------------------------------------------------------------------------------- 1 | .faq-link { 2 | cursor: pointer; 3 | padding: 15px; 4 | color: #212529; 5 | } 6 | 7 | .faq-item.mm-active>.faq-link { 8 | background: #e7f1ff; 9 | border-radius: 3px; 10 | color: #0c63e4; 11 | } 12 | -------------------------------------------------------------------------------- /docs/assets/css/mm-folder.css: -------------------------------------------------------------------------------- 1 | .metisFolder { 2 | padding-left: 0; 3 | } 4 | .metisFolder, .metisFolder ul { 5 | list-style: none; 6 | } 7 | .metisFolder li { 8 | position: relative; 9 | } 10 | .metisFolder li a { 11 | display: block; 12 | padding-top: 5px; 13 | padding-bottom: 5px; 14 | color: #333; 15 | text-decoration: none; 16 | outline: 0 none; 17 | } 18 | .metisFolder ul:before { 19 | position: absolute; 20 | border-left: 1px dotted #333; 21 | content: ""; 22 | width: 30px; 23 | top: 25px; 24 | left: 5px; 25 | bottom: 17px; 26 | } 27 | .metisFolder ul > li:before { 28 | position: absolute; 29 | border-top: 1px dotted #333; 30 | content: ""; 31 | width: 30px; 32 | top: 13px; 33 | left: -26px; 34 | } 35 | li.active > a > span.fa-folder-o:before { 36 | content: "\f115" !important; 37 | } 38 | -------------------------------------------------------------------------------- /docs/assets/css/mm-horizontal.css: -------------------------------------------------------------------------------- 1 | .topbar-nav ul { 2 | padding: 0; 3 | margin: 0; 4 | list-style: none; 5 | } 6 | .topbar-nav .metismenu { 7 | display: flex; 8 | flex-direction: column; 9 | } 10 | .topbar-nav .metismenu > li { 11 | flex: 1 1 0%; 12 | display: flex; 13 | flex-direction: column; 14 | position: relative; 15 | } 16 | 17 | .topbar-nav .metismenu a { 18 | text-decoration: none; 19 | position: relative; 20 | display: block; 21 | padding: 15px; 22 | color: #212529; 23 | outline-width: 0; 24 | transition: all 0.3s ease-out; 25 | } 26 | 27 | .topbar-nav .metismenu a:hover, 28 | .topbar-nav .metismenu a:focus, 29 | .topbar-nav .metismenu a:active { 30 | color: #0c63e4; 31 | text-decoration: none; 32 | } 33 | 34 | @media (min-width: 992px) { 35 | .topbar-nav .metismenu { 36 | flex-direction: row; 37 | } 38 | .topbar-nav .metismenu > li { 39 | flex-direction: column; 40 | } 41 | .topbar-nav .metismenu > li > ul { 42 | position: absolute; 43 | top: 100%; 44 | min-width: 100%; 45 | z-index: 1001; 46 | background: #fff; 47 | border: 1px solid #e7f1ff; 48 | } 49 | .topbar-nav.is-hoverable .metismenu > li > ul { 50 | height: auto !important; 51 | } 52 | .topbar-nav.is-hoverable .metismenu > li:hover > ul { 53 | display: block; 54 | } 55 | .topbar-nav.is-hoverable .metismenu > li:hover > a.has-arrow:after { 56 | transform: rotate(-135deg); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /docs/assets/css/mm-vertical-hover.css: -------------------------------------------------------------------------------- 1 | 2 | .sidebar-nav ul { 3 | padding: 0; 4 | margin: 0; 5 | list-style: none; 6 | } 7 | 8 | .sidebar-nav .metismenu { 9 | display: flex; 10 | flex-direction: column; 11 | } 12 | 13 | .sidebar-nav .metismenu > li { 14 | display: flex; 15 | flex-direction: column; 16 | position: relative; 17 | } 18 | 19 | .sidebar-nav .metismenu > li > ul { 20 | background: #fff; 21 | border: 1px solid #e7f1ff; 22 | } 23 | 24 | .sidebar-nav .metismenu a { 25 | text-decoration: none; 26 | position: relative; 27 | display: block; 28 | padding: 15px; 29 | color: #212529; 30 | outline-width: 0; 31 | transition: all 0.3s ease-out; 32 | } 33 | 34 | .sidebar-nav .metismenu a:hover, 35 | .sidebar-nav .metismenu a:focus, 36 | .sidebar-nav .metismenu a:active { 37 | color: #0c63e4; 38 | text-decoration: none; 39 | } 40 | 41 | @media (min-width: 992px) { 42 | .sidebar-nav .metismenu li { 43 | position: relative; 44 | } 45 | .sidebar-nav .metismenu > li > ul { 46 | position: absolute; 47 | left: 100%; 48 | top: 0; 49 | min-width: 200px; 50 | z-index: 1001; 51 | } 52 | .sidebar-nav .metismenu > li:hover > ul { 53 | height: auto !important; 54 | } 55 | .sidebar-nav .metismenu > li:hover > ul, 56 | .sidebar-nav .metismenu > li:hover > ul.collapse { 57 | display: block; 58 | } 59 | 60 | .sidebar-nav .metismenu > li:hover > a.has-arrow:after { 61 | transform: rotate(135deg); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /docs/assets/css/mm-vertical.css: -------------------------------------------------------------------------------- 1 | .sidebar-nav ul { 2 | padding: 0; 3 | margin: 0; 4 | list-style: none; 5 | } 6 | 7 | .sidebar-nav .metismenu { 8 | display: flex; 9 | flex-direction: column; 10 | } 11 | 12 | .sidebar-nav .metismenu li + li { 13 | margin-top: 5px; 14 | } 15 | 16 | .sidebar-nav .metismenu li:first-child { 17 | margin-top: 5px; 18 | } 19 | .sidebar-nav .metismenu li:last-child { 20 | margin-bottom: 5px; 21 | } 22 | 23 | .sidebar-nav .metismenu > li { 24 | display: flex; 25 | flex-direction: column; 26 | position: relative; 27 | } 28 | .sidebar-nav .metismenu a { 29 | position: relative; 30 | display: block; 31 | padding: 13px 15px; 32 | color: #212529; 33 | transition: all 0.3s ease-out; 34 | text-decoration: none; 35 | } 36 | 37 | .sidebar-nav .metismenu ul a { 38 | padding: 10px 15px 10px 30px; 39 | } 40 | 41 | .sidebar-nav .metismenu ul ul a { 42 | padding: 10px 15px 10px 45px; 43 | } 44 | 45 | .sidebar-nav .metismenu a:hover, 46 | .sidebar-nav .metismenu a:focus, 47 | .sidebar-nav .metismenu a:active, 48 | .sidebar-nav .metismenu .mm-active > a { 49 | color: #0c63e4; 50 | text-decoration: none; 51 | } 52 | 53 | .sidebar-nav .metismenu .mm-active > a { 54 | background: #e7f1ff; 55 | border-radius: 3px; 56 | } 57 | -------------------------------------------------------------------------------- /docs/assets/js/metisMenu.js: -------------------------------------------------------------------------------- 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 (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 | 14 | function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } 15 | 16 | var $__default = /*#__PURE__*/_interopDefaultLegacy($); 17 | 18 | const Util = (($) => { // eslint-disable-line no-shadow 19 | const TRANSITION_END = 'transitionend'; 20 | 21 | const Util = { // eslint-disable-line no-shadow 22 | TRANSITION_END: 'mmTransitionEnd', 23 | 24 | triggerTransitionEnd(element) { 25 | $(element).trigger(TRANSITION_END); 26 | }, 27 | 28 | supportsTransitionEnd() { 29 | return Boolean(TRANSITION_END); 30 | }, 31 | }; 32 | 33 | function getSpecialTransitionEndEvent() { 34 | return { 35 | bindType: TRANSITION_END, 36 | delegateType: TRANSITION_END, 37 | handle(event) { 38 | if ($(event.target).is(this)) { 39 | return event 40 | .handleObj 41 | .handler 42 | .apply(this, arguments); // eslint-disable-line prefer-rest-params 43 | } 44 | return undefined; 45 | }, 46 | }; 47 | } 48 | 49 | function transitionEndEmulator(duration) { 50 | let called = false; 51 | 52 | $(this).one(Util.TRANSITION_END, () => { 53 | called = true; 54 | }); 55 | 56 | setTimeout(() => { 57 | if (!called) { 58 | Util.triggerTransitionEnd(this); 59 | } 60 | }, duration); 61 | 62 | return this; 63 | } 64 | 65 | function setTransitionEndSupport() { 66 | $.fn.mmEmulateTransitionEnd = transitionEndEmulator; // eslint-disable-line no-param-reassign 67 | // eslint-disable-next-line no-param-reassign 68 | $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent(); 69 | } 70 | 71 | setTransitionEndSupport(); 72 | 73 | return Util; 74 | })($__default['default']); 75 | 76 | const NAME = 'metisMenu'; 77 | const DATA_KEY = 'metisMenu'; 78 | const EVENT_KEY = `.${DATA_KEY}`; 79 | const DATA_API_KEY = '.data-api'; 80 | const JQUERY_NO_CONFLICT = $__default['default'].fn[NAME]; 81 | const TRANSITION_DURATION = 350; 82 | 83 | const Default = { 84 | toggle: true, 85 | preventDefault: true, 86 | triggerElement: 'a', 87 | parentTrigger: 'li', 88 | subMenu: 'ul', 89 | }; 90 | 91 | const Event = { 92 | SHOW: `show${EVENT_KEY}`, 93 | SHOWN: `shown${EVENT_KEY}`, 94 | HIDE: `hide${EVENT_KEY}`, 95 | HIDDEN: `hidden${EVENT_KEY}`, 96 | CLICK_DATA_API: `click${EVENT_KEY}${DATA_API_KEY}`, 97 | }; 98 | 99 | const ClassName = { 100 | METIS: 'metismenu', 101 | ACTIVE: 'mm-active', 102 | SHOW: 'mm-show', 103 | COLLAPSE: 'mm-collapse', 104 | COLLAPSING: 'mm-collapsing', 105 | COLLAPSED: 'mm-collapsed', 106 | }; 107 | 108 | class MetisMenu { 109 | // eslint-disable-line no-shadow 110 | constructor(element, config) { 111 | this.element = element; 112 | this.config = { 113 | ...Default, 114 | ...config, 115 | }; 116 | this.transitioning = null; 117 | 118 | this.init(); 119 | } 120 | 121 | init() { 122 | const self = this; 123 | const conf = this.config; 124 | const el = $__default['default'](this.element); 125 | 126 | el.addClass(ClassName.METIS); // add metismenu class to element 127 | 128 | el.find(`${conf.parentTrigger}.${ClassName.ACTIVE}`) 129 | .children(conf.triggerElement) 130 | .attr('aria-expanded', 'true'); // add attribute aria-expanded=true the trigger element 131 | 132 | el.find(`${conf.parentTrigger}.${ClassName.ACTIVE}`) 133 | .parents(conf.parentTrigger) 134 | .addClass(ClassName.ACTIVE); 135 | 136 | el.find(`${conf.parentTrigger}.${ClassName.ACTIVE}`) 137 | .parents(conf.parentTrigger) 138 | .children(conf.triggerElement) 139 | .attr('aria-expanded', 'true'); // add attribute aria-expanded=true the triggers of all parents 140 | 141 | el.find(`${conf.parentTrigger}.${ClassName.ACTIVE}`) 142 | .has(conf.subMenu) 143 | .children(conf.subMenu) 144 | .addClass(`${ClassName.COLLAPSE} ${ClassName.SHOW}`); 145 | 146 | el 147 | .find(conf.parentTrigger) 148 | .not(`.${ClassName.ACTIVE}`) 149 | .has(conf.subMenu) 150 | .children(conf.subMenu) 151 | .addClass(ClassName.COLLAPSE); 152 | 153 | el 154 | .find(conf.parentTrigger) 155 | // .has(conf.subMenu) 156 | .children(conf.triggerElement) 157 | .on(Event.CLICK_DATA_API, function (e) { // eslint-disable-line func-names 158 | const eTar = $__default['default'](this); 159 | 160 | if (eTar.attr('aria-disabled') === 'true') { 161 | return; 162 | } 163 | 164 | if (conf.preventDefault && eTar.attr('href') === '#') { 165 | e.preventDefault(); 166 | } 167 | 168 | const paRent = eTar.parent(conf.parentTrigger); 169 | const sibLi = paRent.siblings(conf.parentTrigger); 170 | const sibTrigger = sibLi.children(conf.triggerElement); 171 | 172 | if (paRent.hasClass(ClassName.ACTIVE)) { 173 | eTar.attr('aria-expanded', 'false'); 174 | self.removeActive(paRent); 175 | } else { 176 | eTar.attr('aria-expanded', 'true'); 177 | self.setActive(paRent); 178 | if (conf.toggle) { 179 | self.removeActive(sibLi); 180 | sibTrigger.attr('aria-expanded', 'false'); 181 | } 182 | } 183 | 184 | if (conf.onTransitionStart) { 185 | conf.onTransitionStart(e); 186 | } 187 | }); 188 | } 189 | 190 | setActive(li) { 191 | $__default['default'](li).addClass(ClassName.ACTIVE); 192 | const ul = $__default['default'](li).children(this.config.subMenu); 193 | if (ul.length > 0 && !ul.hasClass(ClassName.SHOW)) { 194 | this.show(ul); 195 | } 196 | } 197 | 198 | removeActive(li) { 199 | $__default['default'](li).removeClass(ClassName.ACTIVE); 200 | const ul = $__default['default'](li).children(`${this.config.subMenu}.${ClassName.SHOW}`); 201 | if (ul.length > 0) { 202 | this.hide(ul); 203 | } 204 | } 205 | 206 | show(element) { 207 | if (this.transitioning || $__default['default'](element).hasClass(ClassName.COLLAPSING)) { 208 | return; 209 | } 210 | const elem = $__default['default'](element); 211 | 212 | const startEvent = $__default['default'].Event(Event.SHOW); 213 | elem.trigger(startEvent); 214 | 215 | if (startEvent.isDefaultPrevented()) { 216 | return; 217 | } 218 | 219 | elem.parent(this.config.parentTrigger).addClass(ClassName.ACTIVE); 220 | 221 | if (this.config.toggle) { 222 | const toggleElem = elem.parent(this.config.parentTrigger).siblings().children(`${this.config.subMenu}.${ClassName.SHOW}`); 223 | this.hide(toggleElem); 224 | } 225 | 226 | elem 227 | .removeClass(ClassName.COLLAPSE) 228 | .addClass(ClassName.COLLAPSING) 229 | .height(0); 230 | 231 | this.setTransitioning(true); 232 | 233 | const complete = () => { 234 | // check if disposed 235 | if (!this.config || !this.element) { 236 | return; 237 | } 238 | elem 239 | .removeClass(ClassName.COLLAPSING) 240 | .addClass(`${ClassName.COLLAPSE} ${ClassName.SHOW}`) 241 | .height(''); 242 | 243 | this.setTransitioning(false); 244 | 245 | elem.trigger(Event.SHOWN); 246 | }; 247 | 248 | elem 249 | .height(element[0].scrollHeight) 250 | .one(Util.TRANSITION_END, complete) 251 | .mmEmulateTransitionEnd(TRANSITION_DURATION); 252 | } 253 | 254 | hide(element) { 255 | if ( 256 | this.transitioning || !$__default['default'](element).hasClass(ClassName.SHOW) 257 | ) { 258 | return; 259 | } 260 | 261 | const elem = $__default['default'](element); 262 | 263 | const startEvent = $__default['default'].Event(Event.HIDE); 264 | elem.trigger(startEvent); 265 | 266 | if (startEvent.isDefaultPrevented()) { 267 | return; 268 | } 269 | 270 | elem.parent(this.config.parentTrigger).removeClass(ClassName.ACTIVE); 271 | // eslint-disable-next-line no-unused-expressions 272 | elem.height(elem.height())[0].offsetHeight; 273 | 274 | elem 275 | .addClass(ClassName.COLLAPSING) 276 | .removeClass(ClassName.COLLAPSE) 277 | .removeClass(ClassName.SHOW); 278 | 279 | this.setTransitioning(true); 280 | 281 | const complete = () => { 282 | // check if disposed 283 | if (!this.config || !this.element) { 284 | return; 285 | } 286 | if (this.transitioning && this.config.onTransitionEnd) { 287 | this.config.onTransitionEnd(); 288 | } 289 | 290 | this.setTransitioning(false); 291 | elem.trigger(Event.HIDDEN); 292 | 293 | elem 294 | .removeClass(ClassName.COLLAPSING) 295 | .addClass(ClassName.COLLAPSE); 296 | }; 297 | 298 | if (elem.height() === 0 || elem.css('display') === 'none') { 299 | complete(); 300 | } else { 301 | elem 302 | .height(0) 303 | .one(Util.TRANSITION_END, complete) 304 | .mmEmulateTransitionEnd(TRANSITION_DURATION); 305 | } 306 | } 307 | 308 | setTransitioning(isTransitioning) { 309 | this.transitioning = isTransitioning; 310 | } 311 | 312 | dispose() { 313 | $__default['default'].removeData(this.element, DATA_KEY); 314 | 315 | $__default['default'](this.element) 316 | .find(this.config.parentTrigger) 317 | // .has(this.config.subMenu) 318 | .children(this.config.triggerElement) 319 | .off(Event.CLICK_DATA_API); 320 | 321 | this.transitioning = null; 322 | this.config = null; 323 | this.element = null; 324 | } 325 | 326 | static jQueryInterface(config) { 327 | // eslint-disable-next-line func-names 328 | return this.each(function () { 329 | const $this = $__default['default'](this); 330 | let data = $this.data(DATA_KEY); 331 | const conf = { 332 | ...Default, 333 | ...$this.data(), 334 | ...(typeof config === 'object' && config ? config : {}), 335 | }; 336 | 337 | if (!data) { 338 | data = new MetisMenu(this, conf); 339 | $this.data(DATA_KEY, data); 340 | } 341 | 342 | if (typeof config === 'string') { 343 | if (data[config] === undefined) { 344 | throw new Error(`No method named "${config}"`); 345 | } 346 | data[config](); 347 | } 348 | }); 349 | } 350 | } 351 | /** 352 | * ------------------------------------------------------------------------ 353 | * jQuery 354 | * ------------------------------------------------------------------------ 355 | */ 356 | 357 | $__default['default'].fn[NAME] = MetisMenu.jQueryInterface; // eslint-disable-line no-param-reassign 358 | $__default['default'].fn[NAME].Constructor = MetisMenu; // eslint-disable-line no-param-reassign 359 | $__default['default'].fn[NAME].noConflict = () => { 360 | // eslint-disable-line no-param-reassign 361 | $__default['default'].fn[NAME] = JQUERY_NO_CONFLICT; // eslint-disable-line no-param-reassign 362 | return MetisMenu.jQueryInterface; 363 | }; 364 | 365 | return MetisMenu; 366 | 367 | }))); 368 | //# sourceMappingURL=metisMenu.js.map 369 | -------------------------------------------------------------------------------- /docs/assets/js/mm-ajax.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | $('#menu').metisMenu(); 4 | 5 | $("#ajaxButton").one('click', function() { 6 | var $this = $(this); 7 | $.ajax({ 8 | url: "demo-ajax.html", 9 | success: function(result) { 10 | 11 | $('#menu').metisMenu('dispose'); 12 | $("#menu").append(result); 13 | 14 | new Noty({ 15 | text: 'ajax menu appended to menu', 16 | layout: 'topRight', 17 | type: 'success', 18 | theme: 'relax', 19 | progressBar: true, 20 | timeout: 2000 21 | }).show(); 22 | 23 | $('#menu').metisMenu(); 24 | $this.attr('disabled', 'disabled'); 25 | } 26 | }); 27 | }); 28 | 29 | $('#menu2').metisMenu(); 30 | 31 | $("[data-url]").each(function(){ 32 | $(this).one('click', function(event){ 33 | event.preventDefault(); 34 | var $this = $(this); 35 | var url = $this.attr('data-url'); 36 | console.log(url); 37 | 38 | $.ajax({ 39 | url: url, 40 | success: function(result) { 41 | 42 | $('#menu2').metisMenu('dispose'); 43 | $this.parent('li').append(result); 44 | 45 | $('#menu2').metisMenu(); 46 | 47 | $this.click(); 48 | } 49 | }); 50 | 51 | }); 52 | }); 53 | 54 | }); 55 | -------------------------------------------------------------------------------- /docs/assets/js/mm-animate.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | 3 | $('#menu').metisMenu(); 4 | 5 | }); 6 | -------------------------------------------------------------------------------- /docs/assets/js/mm-bs-card.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | $('.metismenu').metisMenu({ 4 | toggle: false, 5 | triggerElement: '.card-header', 6 | parentTrigger: '.card', 7 | subMenu: '.card-body' 8 | }); 9 | 10 | }); 11 | -------------------------------------------------------------------------------- /docs/assets/js/mm-dispose.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | $('#menu').metisMenu(); 4 | 5 | $('#stopMm').on('click', function(event) { 6 | $('#menu').metisMenu('dispose'); 7 | new Noty({ 8 | text: 'metisMenu stopped', 9 | layout: 'topRight', 10 | type: 'error', 11 | theme: 'relax', 12 | progressBar: true, 13 | timeout: 2000 14 | }).show(); 15 | }); 16 | 17 | $('#startMm').on('click', function(event) { 18 | $('#menu').metisMenu(); 19 | new Noty({ 20 | text: 'metisMenu restarted', 21 | layout: 'topRight', 22 | type: 'success', 23 | theme: 'relax', 24 | progressBar: true, 25 | timeout: 2000 26 | }).show(); 27 | }); 28 | 29 | $('#menu1').metisMenu(); 30 | $('#deleteElem').one('click', function(event) { 31 | $(this).removeClass('btn-danger').addClass('btn-success').html('Menu 1 removed').attr('disabled', 'disabled'); 32 | $('#menu1').metisMenu('dispose'); 33 | 34 | $('#menu1 #removable').remove(); 35 | new Noty({ 36 | text: 'Menu 1 removed', 37 | layout: 'topRight', 38 | type: 'information', 39 | theme: 'relax', 40 | progressBar: true, 41 | timeout: 2000 42 | }).show(); 43 | 44 | $('#menu1').metisMenu(); 45 | }); 46 | 47 | }); 48 | -------------------------------------------------------------------------------- /docs/assets/js/mm-event.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | $('#menu').metisMenu().on('show.metisMenu', function(event) { 4 | new Noty({ 5 | text: $(event.target).parent('li').children('a').html() + ' opening ...', 6 | layout: 'topRight', 7 | type: 'information', 8 | theme: 'relax', 9 | 10 | timeout: 350 11 | }).show(); 12 | }).on('shown.metisMenu', function(event) { 13 | new Noty({ 14 | text: $(event.target).parent('li').children('a').html() + ' opened', 15 | layout: 'topRight', 16 | type: 'success', 17 | theme: 'relax', 18 | timeout: 350 19 | }).show(); 20 | }).on('hide.metisMenu', function(event) { 21 | new Noty({ 22 | text: $(event.target).parent('li').children('a').html() + ' collapsing ...', 23 | layout: 'topRight', 24 | type: 'warning', 25 | theme: 'relax', 26 | timeout: 350 27 | }).show(); 28 | }).on('hidden.metisMenu', function(event) { 29 | new Noty({ 30 | text: $(event.target).parent('li').children('a').html() + ' collapsed', 31 | layout: 'topRight', 32 | type: 'error', 33 | theme: 'relax', 34 | timeout: 350 35 | }).show(); 36 | }); 37 | 38 | }); 39 | -------------------------------------------------------------------------------- /docs/assets/js/mm-event2.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | $('#menu') 3 | .metisMenu() 4 | .on('shown.metisMenu', function(event) { 5 | Jump("#menu") 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /docs/assets/js/mm-faq.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | $('.faq-menu').metisMenu({ 4 | toggle: false, 5 | triggerElement: '.faq-link', 6 | parentTrigger: '.faq-item', 7 | subMenu: '.faq-answer' 8 | }); 9 | 10 | }); 11 | -------------------------------------------------------------------------------- /docs/assets/js/mm-folder.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | $('.metisFolder').metisMenu({ 3 | toggle: false 4 | }); 5 | }); 6 | -------------------------------------------------------------------------------- /docs/assets/js/mm-horizontal.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | $('#menu1').metisMenu(); 4 | 5 | $('#menu2').metisMenu(); 6 | 7 | }); 8 | -------------------------------------------------------------------------------- /docs/assets/js/mm-vertical-hover.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | $('#menu1').metisMenu(); 4 | 5 | }); 6 | -------------------------------------------------------------------------------- /docs/assets/js/mm-vertical.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | $('#menu1').metisMenu(); 4 | 5 | $('#menu2').metisMenu({ 6 | toggle: false 7 | }); 8 | 9 | $('#menu3').metisMenu(); 10 | 11 | }); 12 | -------------------------------------------------------------------------------- /docs/demo-ajax.html: -------------------------------------------------------------------------------- 1 |
  • 2 | 3 | 9 |
  • 10 | -------------------------------------------------------------------------------- /docs/mm-ajax.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | metisMenu - Ajax 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
    29 | 118 |
    119 |
    120 | 121 | 122 |
    123 |

    Ajax

    124 | 125 | 126 | Download CSS 127 | 128 | 129 | 130 | Download JS 131 |
    132 | 133 |
    134 |
    135 | 206 |
    207 | 208 |
    209 |
    210 |
    211 |
    Simple Ajax
    212 | 215 |
    $('#menu').metisMenu();
    216 | 
    217 | $("#ajaxButton").one('click', function() {
    218 |   var $this = $(this);
    219 |   $.ajax({
    220 |     url: "demo-ajax.html",
    221 |     success: function(result) {
    222 | 
    223 |       $('#menu').metisMenu('dispose');
    224 |       $("#menu").append(result);
    225 | 
    226 |       $('#menu').metisMenu();
    227 |       $this.attr('disabled', 'disabled');
    228 |     }
    229 |   });
    230 | });
    231 | 
    232 |
    233 |
    234 |
    235 | 236 | 237 |
    238 | 239 | 240 |
    241 | 242 |
    243 |
    244 | 254 |
    255 | 256 |
    257 |
    258 |
    259 |
    Simple Ajax one level
    260 |
      $('#menu2').metisMenu();
    261 | 
    262 |   $("[data-url]").each(function(){
    263 |       $(this).one('click', function(event){
    264 |         event.preventDefault();
    265 |         var $this = $(this);
    266 |         var url = $this.attr('data-url');
    267 |         console.log(url);
    268 | 
    269 |         $.ajax({
    270 |           url: url,
    271 |           success: function(result) {
    272 | 
    273 |             $('#menu2').metisMenu('dispose');
    274 |             $this.parent('li').append(result);
    275 | 
    276 |             $('#menu2').metisMenu();
    277 | 
    278 |             $this.click();
    279 |           }
    280 |         });
    281 | 
    282 |       });
    283 |   });
    284 | 
    285 |
    286 |
    287 |
    288 | 289 |
    290 | 291 | 292 | 293 | 294 |
    295 | 296 | 297 | 298 | 299 | -------------------------------------------------------------------------------- /docs/mm-bs-card.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | metisMenu - Bootstrap Card 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
    30 | 119 |
    120 |
    121 | 126 |
    127 |

    Bootstrap Card

    128 | 129 | 130 | Download JS 131 |
    132 | 133 |
    134 |
    135 |
    136 |
    137 | Featured 138 |
    139 |
    140 |
    Special title treatment
    141 |

    With supporting text below as a natural lead-in to additional content.

    142 | Go somewhere 143 |
    144 |
    145 |
    146 |
    147 |
    148 |
    149 | Featured 150 |
    151 |
    152 |
    Special title treatment
    153 |

    With supporting text below as a natural lead-in to additional content.

    154 | Go somewhere 155 |
    156 |
    157 |
    158 |
    159 | 160 |
    161 | 162 | 163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /docs/mm-dispose.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | metisMenu - dispose menu 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
    29 | 118 |
    119 |
    120 | 121 | 122 |
    123 |

    Stop/Re-start

    124 | 125 | 126 | Download CSS 127 | 128 | 129 | 130 | Download JS 131 |
    132 | 133 | 134 |
    135 |
    136 | 207 |
    208 | 209 | 210 |
    211 |
    212 |
    213 |
    Stop/Re-start
    214 | 217 | 220 | 221 |
    $(function() {
    222 | 
    223 |   $('#menu').metisMenu();
    224 | 
    225 |   $('#stopMm').on('click', function (event) {
    226 |     $('#menu').metisMenu('dispose');
    227 |   });
    228 | 
    229 |   $('#startMm').on('click', function (event) {
    230 |     $('#menu').metisMenu();
    231 |   });
    232 | 
    233 | });
    234 | 
    235 |
    236 |
    237 |
    238 | 239 |
    240 | 241 |
    242 | 243 |
    244 |
    245 | 316 |
    317 | 318 | 319 |
    320 |
    321 |
    322 |
    Delete elements
    323 | 326 |
    $('#menu1').metisMenu();
    327 | 
    328 | $('#deleteElem').one('click', function (event) {
    329 | 
    330 |   $(this).removeClass('btn-danger')
    331 |     .addClass('btn-success')
    332 |     .html('Menu 1 removed')
    333 |     .attr('disabled', 'disabled');
    334 | 
    335 |   $('#menu1').metisMenu('dispose');
    336 | 
    337 |   $('#menu1 #removable').remove();
    338 | 
    339 |   $('#menu1').metisMenu();
    340 | });
    341 | 
    342 |
    343 |
    344 |
    345 |
    346 | 347 | 348 |
    349 | 350 | 351 | 352 | 353 | 354 | -------------------------------------------------------------------------------- /docs/mm-event.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | metisMenu - events 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
    29 | 118 |
    119 |
    120 | 121 | 122 |
    123 |

    Event

    124 | 125 | 126 | Download CSS 127 | 128 | 129 | 130 | Download JS 131 |
    132 | 133 |
    134 |
    135 | 206 |
    207 | 208 |
    209 |
    210 |
    211 |
    Event
    212 | 213 |
    $(function() {
    214 | 
    215 |  $('#menu').metisMenu()
    216 |  .on('show.metisMenu', function(event) {
    217 | 
    218 |      // do something…
    219 | 
    220 |  }).on('shown.metisMenu', function(event) {
    221 | 
    222 |    // do something…
    223 | 
    224 |  }).on('hide.metisMenu', function(event) {
    225 | 
    226 |    // do something…
    227 | 
    228 |  }).on('hidden.metisMenu', function(event) {
    229 | 
    230 |    // do something…
    231 | 
    232 |  });
    233 | });
    234 | 
    235 | 236 |
    237 |
    238 |
    239 | 240 |
    241 | 242 | 243 | 244 |
    245 | 246 | 247 | 248 | 249 | -------------------------------------------------------------------------------- /docs/mm-faq.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | metisMenu - FAQ 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
    30 | 119 |
    120 |
    121 | 122 | 123 | 124 |
    125 |

    Faq

    126 | 127 | 128 | Download CSS 129 | 130 | 131 | 132 | Download JS 133 |
    134 | 135 | 136 |
    137 | 138 |
    139 |
    140 |

    FAQ

    141 |
    142 |
    143 |
    144 | 145 |
    146 | 147 |
    148 |

    149 | Lorem ipsum dolor sit, amet consectetur adipisicing elit. Ipsam provident reiciendis recusandae accusamus hic, reprehenderit quo magni ullam dicta labore ratione, earum veritatis laboriosam cum sunt, unde quaerat a impedit. 150 |

    151 |
    152 |
    153 | 154 |
    155 | 156 |
    157 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. 158 |
    159 |
    160 | 161 |
    162 | 163 |
    164 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. 165 |
    166 |
    167 | 168 |
    169 | 170 |
    $(function() {
    171 | 
    172 |   $('.faq-menu').metisMenu({
    173 |     toggle: false,
    174 |     triggerElement: '.faq-link',
    175 |     parentTrigger: '.faq-item',
    176 |     subMenu: '.faq-answer'
    177 |   });
    178 | 
    179 | });
    180 | 
    181 | 182 |
    183 |
    184 |
    185 | 186 | 187 | 188 | 189 |
    190 | 191 | 192 | 193 | 194 | -------------------------------------------------------------------------------- /docs/mm-folder.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | metisMenu - folder view 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
    29 | 118 |
    119 |
    120 | 121 |
    122 |

    Folder View

    123 | 124 | 125 | Download CSS 126 | 127 | 128 | 129 | Download JS 130 |
    131 |
    132 |
    133 | 262 |
    263 | 264 | 265 |
    266 |
    267 |
    268 |
    Folder View default
    269 |
    <script>
    270 |   $(function () {
    271 | 
    272 |     $('.metisFolder').metisMenu({
    273 |       toggle: false
    274 |     });
    275 | 
    276 |   });
    277 | </script>
    278 | 
    279 | 280 |
    281 |
    282 |
    283 |
    284 | 285 | 286 |
    287 | 288 | 289 | 290 | 291 | -------------------------------------------------------------------------------- /docs/mm-horizontal.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | metisMenu - horizontal menu 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
    29 | 118 |
    119 |
    120 | 121 |
    122 |

    Horizontal Menu responsive

    123 | 124 | 125 | Download CSS 126 | 127 | 128 | 129 | Download JS 130 |
    131 |
    132 |
    133 |

    Clickable & Responsive default

    134 | 205 |
    206 |
    207 |

    Hoverable for Desktop & Responsive

    208 | 279 |
    280 |
    281 | 282 | 283 |
    284 | 285 | 286 | 287 | 288 | -------------------------------------------------------------------------------- /docs/mm-vertical-hover.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | metisMenu - hoverable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
    29 | 118 |
    119 |
    120 | 121 |
    122 |

    Hoverable Vertical Menu

    123 | 124 | 125 | Download CSS 126 | 127 | 128 | 129 | Download JS 130 |
    131 |
    132 |
    133 | 204 |
    205 |
    206 |
    207 |
    208 |
    Hoverable Vertical Menu
    209 |
    <script>
    210 | $(function() {
    211 | 
    212 |  $('#menu1').metisMenu();
    213 | 
    214 | });
    215 | </script>
    216 | 
    217 | 218 |
    219 |
    220 |
    221 |
    222 | 223 | 224 | 225 |
    226 | 227 | 228 | 229 | 230 | -------------------------------------------------------------------------------- /package.js: -------------------------------------------------------------------------------- 1 | Package.describe({ 2 | name: 'onokumus:metismenu', 3 | version: '3.0.6', 4 | summary: 'A jQuery menu plugin', 5 | git: 'https://github.com/onokumus/metisMenu', 6 | documentation: 'README.md' 7 | }); 8 | 9 | Package.onUse(function(api) { 10 | api.use(['jquery@1.11.4']); 11 | api.addFiles([ 12 | "dist/metisMenu.css", 13 | "dist/metisMenu.js" 14 | ], 'client'); 15 | }); 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "metismenu", 3 | "version": "3.0.7", 4 | "description": "A collapsible jQuery menu plugin", 5 | "type": "module", 6 | "main": "dist/metisMenu.js", 7 | "module": "dist/metisMenu.esm.js", 8 | "browser": "dist/metisMenu.min.js", 9 | "unpkg": "dist/metisMenu.min.js", 10 | "jsdelivr": "dist/metisMenu.min.js", 11 | "typings": "types/metismenu.d.ts", 12 | "style": "dist/metisMenu.css", 13 | "sass": "src/metisMenu.scss", 14 | "files": [ 15 | "dist", 16 | "src", 17 | "types" 18 | ], 19 | "scripts": { 20 | "js:dev": "rollup -c -w", 21 | "js:prod": "rollup -c", 22 | "js:umd:min": "terser --compress typeofs=false --mangle --comments \"/^!/\" --source-map \"content=dist/metisMenu.js.map,includeSources,url=metisMenu.min.js.map\" --output dist/metisMenu.min.js dist/metisMenu.js", 23 | "js:esm:min": "terser --compress typeofs=false --mangle --comments \"/^!/\" --source-map \"content=dist/metisMenu.esm.js.map,includeSources,url=metisMenu.esm.min.js.map\" --output dist/metisMenu.esm.min.js dist/metisMenu.esm.js", 24 | "css:dev": "sass src:demo/assets/css -w", 25 | "css:prod": "sass src:dist", 26 | "css:min": "sass src/metisMenu.scss dist/metisMenu.min.css -s compressed", 27 | "build": "npm run js:prod && npm run js:umd:min && npm run js:esm:min && npm run css:prod && npm run css:min", 28 | "test": "eslint src/*.js" 29 | }, 30 | "repository": "onokumus/metismenu", 31 | "keywords": [ 32 | "accordion", 33 | "jquery", 34 | "menu", 35 | "metis", 36 | "metisMenu", 37 | "toggle" 38 | ], 39 | "author": "Osman Nuri Okumus (https://github.com/onokumus)", 40 | "contributors": [ 41 | "Rein de Vries (https://github.com/reinos/)", 42 | "Arthur CHAN (http://catchtop.com)", 43 | "Andrew Eastwood (https://github.com/AndrewEastwood)", 44 | "Marcelo Tosco (http://ecapy.com)", 45 | "Radoslav Štofko (http://www.stoweb.cz)", 46 | "Umut Karcı (https://github.com/cediddi)", 47 | "Chris Wiggins (https://github.com/chriswiggins)", 48 | "Jacob Magnusson (https://github.com/jmagnusson)", 49 | "QQ (https://github.com/sinabs)", 50 | "roman (https://github.com/rgnevashev)", 51 | "diegozhu (http://sae.zhuhaiyang.me)", 52 | "WoMayr (https://github.com/WoMayr)", 53 | "719media (https://github.com/719media)", 54 | "Boris Burkov (Boris Burkov)", 55 | "Matt Dziuban (http://mattdziuban.com)", 56 | "Valerio Belli (https://github.com/DrugoLebowski)", 57 | "Diogo Pereira (http://pereiradiogo.com)", 58 | "Nicolas Igot (http://www.igot-web.com)" 59 | ], 60 | "license": "MIT", 61 | "bugs": { 62 | "url": "https://github.com/onokumus/metismenu/issues" 63 | }, 64 | "homepage": "https://github.com/onokumus/metismenu#readme", 65 | "devDependencies": { 66 | "@rollup/plugin-node-resolve": "^15.0.1", 67 | "@types/jquery": "^3.5.14", 68 | "cross-env": "^7.0.3", 69 | "eslint": "^8.27.0", 70 | "eslint-config-airbnb-base": "^15.0.0", 71 | "eslint-plugin-import": "^2.26.0", 72 | "rollup": "^3.3.0", 73 | "sass": "^1.56.1", 74 | "terser": "^5.15.1" 75 | }, 76 | "peerDependencies": { 77 | "jquery": "^3.4.1" 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from '@rollup/plugin-node-resolve'; 2 | import pkg from './package.json' assert { type: "json" }; 3 | 4 | const banner = `/*! 5 | * ${pkg.name} ${pkg.homepage} 6 | * ${pkg.description} 7 | * @version ${pkg.version} 8 | * @author ${pkg.author} 9 | * @license: ${pkg.license} 10 | */`; 11 | 12 | const production = !process.env.ROLLUP_WATCH; 13 | 14 | export default [ 15 | { 16 | input: 'src/index.js', 17 | external: ['jquery'], 18 | output: [ 19 | { 20 | name: 'metisMenu', 21 | banner, 22 | globals: { 23 | jquery: '$', 24 | }, 25 | file: production ? pkg.main : 'demo/assets/js/metisMenu.js', 26 | format: 'umd', 27 | sourcemap: true, 28 | }, 29 | { 30 | file: pkg.module, 31 | banner, 32 | format: 'esm', 33 | sourcemap: true, 34 | }, 35 | ], 36 | plugins: [ 37 | resolve(), 38 | ], 39 | }, 40 | ]; 41 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import $ from 'jquery'; 2 | import Util from './util'; 3 | 4 | const NAME = 'metisMenu'; 5 | const DATA_KEY = 'metisMenu'; 6 | const EVENT_KEY = `.${DATA_KEY}`; 7 | const DATA_API_KEY = '.data-api'; 8 | const JQUERY_NO_CONFLICT = $.fn[NAME]; 9 | const TRANSITION_DURATION = 350; 10 | 11 | const Default = { 12 | toggle: true, 13 | preventDefault: true, 14 | triggerElement: 'a', 15 | parentTrigger: 'li', 16 | subMenu: 'ul', 17 | }; 18 | 19 | const Event = { 20 | SHOW: `show${EVENT_KEY}`, 21 | SHOWN: `shown${EVENT_KEY}`, 22 | HIDE: `hide${EVENT_KEY}`, 23 | HIDDEN: `hidden${EVENT_KEY}`, 24 | CLICK_DATA_API: `click${EVENT_KEY}${DATA_API_KEY}`, 25 | }; 26 | 27 | const ClassName = { 28 | METIS: 'metismenu', 29 | ACTIVE: 'mm-active', 30 | SHOW: 'mm-show', 31 | COLLAPSE: 'mm-collapse', 32 | COLLAPSING: 'mm-collapsing', 33 | COLLAPSED: 'mm-collapsed', 34 | }; 35 | 36 | class MetisMenu { 37 | // eslint-disable-line no-shadow 38 | constructor(element, config) { 39 | this.element = element; 40 | this.config = { 41 | ...Default, 42 | ...config, 43 | }; 44 | this.transitioning = null; 45 | 46 | this.init(); 47 | } 48 | 49 | init() { 50 | const self = this; 51 | const conf = this.config; 52 | const el = $(this.element); 53 | 54 | el.addClass(ClassName.METIS); // add metismenu class to element 55 | 56 | el.find(`${conf.parentTrigger}.${ClassName.ACTIVE}`) 57 | .children(conf.triggerElement) 58 | .attr('aria-expanded', 'true'); // add attribute aria-expanded=true the trigger element 59 | 60 | el.find(`${conf.parentTrigger}.${ClassName.ACTIVE}`) 61 | .parents(conf.parentTrigger) 62 | .addClass(ClassName.ACTIVE); 63 | 64 | el.find(`${conf.parentTrigger}.${ClassName.ACTIVE}`) 65 | .parents(conf.parentTrigger) 66 | .children(conf.triggerElement) 67 | .attr('aria-expanded', 'true'); // add attribute aria-expanded=true the triggers of all parents 68 | 69 | el.find(`${conf.parentTrigger}.${ClassName.ACTIVE}`) 70 | .has(conf.subMenu) 71 | .children(conf.subMenu) 72 | .addClass(`${ClassName.COLLAPSE} ${ClassName.SHOW}`); 73 | 74 | el 75 | .find(conf.parentTrigger) 76 | .not(`.${ClassName.ACTIVE}`) 77 | .has(conf.subMenu) 78 | .children(conf.subMenu) 79 | .addClass(ClassName.COLLAPSE); 80 | 81 | el 82 | .find(conf.parentTrigger) 83 | // .has(conf.subMenu) 84 | .children(conf.triggerElement) 85 | .on(Event.CLICK_DATA_API, function (e) { // eslint-disable-line func-names 86 | const eTar = $(this); 87 | 88 | if (eTar.attr('aria-disabled') === 'true') { 89 | return; 90 | } 91 | 92 | if (conf.preventDefault && eTar.attr('href') === '#') { 93 | e.preventDefault(); 94 | } 95 | 96 | const paRent = eTar.parent(conf.parentTrigger); 97 | const sibLi = paRent.siblings(conf.parentTrigger); 98 | const sibTrigger = sibLi.children(conf.triggerElement); 99 | 100 | if (paRent.hasClass(ClassName.ACTIVE)) { 101 | eTar.attr('aria-expanded', 'false'); 102 | self.removeActive(paRent); 103 | } else { 104 | eTar.attr('aria-expanded', 'true'); 105 | self.setActive(paRent); 106 | if (conf.toggle) { 107 | self.removeActive(sibLi); 108 | sibTrigger.attr('aria-expanded', 'false'); 109 | } 110 | } 111 | 112 | if (conf.onTransitionStart) { 113 | conf.onTransitionStart(e); 114 | } 115 | }); 116 | } 117 | 118 | setActive(li) { 119 | $(li).addClass(ClassName.ACTIVE); 120 | const ul = $(li).children(this.config.subMenu); 121 | if (ul.length > 0 && !ul.hasClass(ClassName.SHOW)) { 122 | this.show(ul); 123 | } 124 | } 125 | 126 | removeActive(li) { 127 | $(li).removeClass(ClassName.ACTIVE); 128 | const ul = $(li).children(`${this.config.subMenu}.${ClassName.SHOW}`); 129 | if (ul.length > 0) { 130 | this.hide(ul); 131 | } 132 | } 133 | 134 | show(element) { 135 | if (this.transitioning || $(element).hasClass(ClassName.COLLAPSING)) { 136 | return; 137 | } 138 | const elem = $(element); 139 | 140 | const startEvent = $.Event(Event.SHOW); 141 | elem.trigger(startEvent); 142 | 143 | if (startEvent.isDefaultPrevented()) { 144 | return; 145 | } 146 | 147 | elem.parent(this.config.parentTrigger).addClass(ClassName.ACTIVE); 148 | 149 | if (this.config.toggle) { 150 | const toggleElem = elem.parent(this.config.parentTrigger).siblings().children(`${this.config.subMenu}.${ClassName.SHOW}`); 151 | this.hide(toggleElem); 152 | } 153 | 154 | elem 155 | .removeClass(ClassName.COLLAPSE) 156 | .addClass(ClassName.COLLAPSING) 157 | .height(0); 158 | 159 | this.setTransitioning(true); 160 | 161 | const complete = () => { 162 | // check if disposed 163 | if (!this.config || !this.element) { 164 | return; 165 | } 166 | elem 167 | .removeClass(ClassName.COLLAPSING) 168 | .addClass(`${ClassName.COLLAPSE} ${ClassName.SHOW}`) 169 | .height(''); 170 | 171 | this.setTransitioning(false); 172 | 173 | elem.trigger(Event.SHOWN); 174 | }; 175 | 176 | elem 177 | .height(element[0].scrollHeight) 178 | .one(Util.TRANSITION_END, complete) 179 | .mmEmulateTransitionEnd(TRANSITION_DURATION); 180 | } 181 | 182 | hide(element) { 183 | if ( 184 | this.transitioning || !$(element).hasClass(ClassName.SHOW) 185 | ) { 186 | return; 187 | } 188 | 189 | const elem = $(element); 190 | 191 | const startEvent = $.Event(Event.HIDE); 192 | elem.trigger(startEvent); 193 | 194 | if (startEvent.isDefaultPrevented()) { 195 | return; 196 | } 197 | 198 | elem.parent(this.config.parentTrigger).removeClass(ClassName.ACTIVE); 199 | // eslint-disable-next-line no-unused-expressions 200 | elem.height(elem.height())[0].offsetHeight; 201 | 202 | elem 203 | .addClass(ClassName.COLLAPSING) 204 | .removeClass(ClassName.COLLAPSE) 205 | .removeClass(ClassName.SHOW); 206 | 207 | this.setTransitioning(true); 208 | 209 | const complete = () => { 210 | // check if disposed 211 | if (!this.config || !this.element) { 212 | return; 213 | } 214 | if (this.transitioning && this.config.onTransitionEnd) { 215 | this.config.onTransitionEnd(); 216 | } 217 | 218 | this.setTransitioning(false); 219 | elem.trigger(Event.HIDDEN); 220 | 221 | elem 222 | .removeClass(ClassName.COLLAPSING) 223 | .addClass(ClassName.COLLAPSE); 224 | }; 225 | 226 | if (elem.height() === 0 || elem.css('display') === 'none') { 227 | complete(); 228 | } else { 229 | elem 230 | .height(0) 231 | .one(Util.TRANSITION_END, complete) 232 | .mmEmulateTransitionEnd(TRANSITION_DURATION); 233 | } 234 | } 235 | 236 | setTransitioning(isTransitioning) { 237 | this.transitioning = isTransitioning; 238 | } 239 | 240 | dispose() { 241 | $.removeData(this.element, DATA_KEY); 242 | 243 | $(this.element) 244 | .find(this.config.parentTrigger) 245 | // .has(this.config.subMenu) 246 | .children(this.config.triggerElement) 247 | .off(Event.CLICK_DATA_API); 248 | 249 | this.transitioning = null; 250 | this.config = null; 251 | this.element = null; 252 | } 253 | 254 | static jQueryInterface(config) { 255 | // eslint-disable-next-line func-names 256 | return this.each(function () { 257 | const $this = $(this); 258 | let data = $this.data(DATA_KEY); 259 | const conf = { 260 | ...Default, 261 | ...$this.data(), 262 | ...(typeof config === 'object' && config ? config : {}), 263 | }; 264 | 265 | if (!data) { 266 | data = new MetisMenu(this, conf); 267 | $this.data(DATA_KEY, data); 268 | } 269 | 270 | if (typeof config === 'string') { 271 | if (data[config] === undefined) { 272 | throw new Error(`No method named "${config}"`); 273 | } 274 | data[config](); 275 | } 276 | }); 277 | } 278 | } 279 | /** 280 | * ------------------------------------------------------------------------ 281 | * jQuery 282 | * ------------------------------------------------------------------------ 283 | */ 284 | 285 | $.fn[NAME] = MetisMenu.jQueryInterface; // eslint-disable-line no-param-reassign 286 | $.fn[NAME].Constructor = MetisMenu; // eslint-disable-line no-param-reassign 287 | $.fn[NAME].noConflict = () => { 288 | // eslint-disable-line no-param-reassign 289 | $.fn[NAME] = JQUERY_NO_CONFLICT; // eslint-disable-line no-param-reassign 290 | return MetisMenu.jQueryInterface; 291 | }; 292 | 293 | export default MetisMenu; 294 | -------------------------------------------------------------------------------- /src/metisMenu.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * metismenu https://github.com/onokumus/metismenu#readme 3 | * A collapsible jQuery menu plugin 4 | * @version 3.0.6 5 | * @author Osman Nuri Okumus (https://github.com/onokumus) 6 | * @license: MIT 7 | */ 8 | 9 | .metismenu .arrow { 10 | float: right; 11 | line-height: 1.42857; 12 | } 13 | *[dir="rtl"] .metismenu .arrow { 14 | float: left; 15 | } 16 | 17 | /* 18 | * Require Bootstrap 3.x 19 | * https://github.com/twbs/bootstrap 20 | */ 21 | 22 | .metismenu .glyphicon.arrow:before { 23 | content: "\e079"; 24 | } 25 | .metismenu .mm-active > a > .glyphicon.arrow:before { 26 | content: "\e114"; 27 | } 28 | 29 | /* 30 | * Require Font-Awesome 31 | * http://fortawesome.github.io/Font-Awesome/ 32 | */ 33 | 34 | .metismenu .fa.arrow:before { 35 | content: "\f104"; 36 | } 37 | .metismenu .mm-active > a > .fa.arrow:before { 38 | content: "\f107"; 39 | } 40 | 41 | /* 42 | * Require Ionicons 43 | * http://ionicons.com/ 44 | */ 45 | 46 | .metismenu .ion.arrow:before { 47 | content: "\f3d2" 48 | } 49 | .metismenu .mm-active > a > .ion.arrow:before { 50 | content: "\f3d0"; 51 | } 52 | .metismenu .plus-times { 53 | float: right; 54 | } 55 | *[dir="rtl"] .metismenu .plus-times { 56 | float: left; 57 | } 58 | .metismenu .fa.plus-times:before { 59 | content: "\f067"; 60 | } 61 | .metismenu .mm-active > a > .fa.plus-times { 62 | transform: rotate(45deg); 63 | } 64 | .metismenu .plus-minus { 65 | float: right; 66 | } 67 | *[dir="rtl"] .metismenu .plus-minus { 68 | float: left; 69 | } 70 | .metismenu .fa.plus-minus:before { 71 | content: "\f067"; 72 | } 73 | .metismenu .mm-active > a > .fa.plus-minus:before { 74 | content: "\f068"; 75 | } 76 | .metismenu .mm-collapse:not(.mm-show) { 77 | display: none; 78 | } 79 | 80 | .metismenu .mm-collapsing { 81 | position: relative; 82 | height: 0; 83 | overflow: hidden; 84 | transition-timing-function: ease; 85 | transition-duration: .35s; 86 | transition-property: height, visibility; 87 | } 88 | 89 | .metismenu .has-arrow { 90 | position: relative; 91 | } 92 | 93 | .metismenu .has-arrow::after { 94 | position: absolute; 95 | content: ''; 96 | width: .5em; 97 | height: .5em; 98 | border-width: 1px 0 0 1px; 99 | border-style: solid; 100 | border-color: initial; 101 | right: 1em; 102 | transform: rotate(-45deg) translate(0, -50%); 103 | transform-origin: top; 104 | top: 50%; 105 | transition: all .3s ease-out; 106 | } 107 | 108 | *[dir="rtl"] .metismenu .has-arrow::after { 109 | right: auto; 110 | left: 1em; 111 | transform: rotate(135deg) translate(0, -50%); 112 | } 113 | 114 | .metismenu .mm-active > .has-arrow::after, 115 | .metismenu .has-arrow[aria-expanded="true"]::after { 116 | transform: rotate(-135deg) translate(0, -50%); 117 | } 118 | 119 | *[dir="rtl"] .metismenu .mm-active > .has-arrow::after, 120 | *[dir="rtl"] .metismenu .has-arrow[aria-expanded="true"]::after { 121 | transform: rotate(225deg) translate(0, -50%); 122 | } 123 | -------------------------------------------------------------------------------- /src/util.js: -------------------------------------------------------------------------------- 1 | import $ from 'jquery'; 2 | 3 | const Util = (($) => { // eslint-disable-line no-shadow 4 | const TRANSITION_END = 'transitionend'; 5 | 6 | const Util = { // eslint-disable-line no-shadow 7 | TRANSITION_END: 'mmTransitionEnd', 8 | 9 | triggerTransitionEnd(element) { 10 | $(element).trigger(TRANSITION_END); 11 | }, 12 | 13 | supportsTransitionEnd() { 14 | return Boolean(TRANSITION_END); 15 | }, 16 | }; 17 | 18 | function getSpecialTransitionEndEvent() { 19 | return { 20 | bindType: TRANSITION_END, 21 | delegateType: TRANSITION_END, 22 | handle(event) { 23 | if ($(event.target).is(this)) { 24 | return event 25 | .handleObj 26 | .handler 27 | .apply(this, arguments); // eslint-disable-line prefer-rest-params 28 | } 29 | return undefined; 30 | }, 31 | }; 32 | } 33 | 34 | function transitionEndEmulator(duration) { 35 | let called = false; 36 | 37 | $(this).one(Util.TRANSITION_END, () => { 38 | called = true; 39 | }); 40 | 41 | setTimeout(() => { 42 | if (!called) { 43 | Util.triggerTransitionEnd(this); 44 | } 45 | }, duration); 46 | 47 | return this; 48 | } 49 | 50 | function setTransitionEndSupport() { 51 | $.fn.mmEmulateTransitionEnd = transitionEndEmulator; // eslint-disable-line no-param-reassign 52 | // eslint-disable-next-line no-param-reassign 53 | $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent(); 54 | } 55 | 56 | setTransitionEndSupport(); 57 | 58 | return Util; 59 | })($); 60 | 61 | export default Util; 62 | -------------------------------------------------------------------------------- /types/metismenu.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for metisMenu 3.0 2 | // Project: http://github.com/onokumus/metisMenu 3 | // Definitions by: onokumus 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | /// 7 | 8 | interface MetisMenuOptions { 9 | toggle?: boolean; 10 | preventDefault?: boolean; 11 | triggerElement?: string; 12 | parentTrigger?: string; 13 | subMenu?: string; 14 | } 15 | 16 | type MetisMenuEvents = "show.metisMenu" | "shown.metisMenu" | "hide.metisMenu" | "hidden.metisMenu"; 17 | 18 | interface JQuery { 19 | metisMenu(options?: MetisMenuOptions | "dispose"): JQuery; 20 | on(events: MetisMenuEvents, handler: (eventObject: JQuery.Event) => any): JQuery; 21 | } 22 | --------------------------------------------------------------------------------