PageRenderTime 35ms CodeModel.GetById 0ms RepoModel.GetById 1ms app.codeStats 0ms

/ajax/libs/jQuery.mmenu/4.3.1/js/jquery.mmenu.oncanvas.js

https://gitlab.com/Mirros/cdnjs
JavaScript | 768 lines | 602 code | 106 blank | 60 comment | 94 complexity | 37f981e4d43f359199ba74cf6ca399ea MD5 | raw file
  1. /*
  2. * jQuery mmenu v4.3.1
  3. * @requires jQuery 1.7.0 or later
  4. *
  5. * mmenu.frebsite.nl
  6. *
  7. * Copyright (c) Fred Heusschen
  8. * www.frebsite.nl
  9. *
  10. * Dual licensed under the MIT and GPL licenses.
  11. * http://en.wikipedia.org/wiki/MIT_License
  12. * http://en.wikipedia.org/wiki/GNU_General_Public_License
  13. */
  14. (function( $ ) {
  15. var _PLUGIN_ = 'mmenu',
  16. _VERSION_ = '4.3.1';
  17. // Plugin already excists
  18. if ( $[ _PLUGIN_ ] )
  19. {
  20. return;
  21. }
  22. // Global variables
  23. var _c = {}, _d = {}, _e = {},
  24. plugin_initiated = false;
  25. var glbl = {
  26. $wndw: null,
  27. $html: null,
  28. $body: null
  29. };
  30. $[ _PLUGIN_ ] = function( $menu, opts, conf )
  31. {
  32. this.$menu = $menu;
  33. this.opts = opts
  34. this.conf = conf;
  35. this.vars = {};
  36. this._init();
  37. return this;
  38. };
  39. $[ _PLUGIN_ ].uniqueId = 0;
  40. $[ _PLUGIN_ ].prototype = {
  41. _init: function()
  42. {
  43. this.opts = extendOptions( this.opts, this.conf, this.$menu );
  44. this._initMenu();
  45. this._initPanels();
  46. this._initLinks();
  47. this._bindCustomEvents();
  48. if ( $[ _PLUGIN_ ].addons )
  49. {
  50. for ( var a = 0; a < $[ _PLUGIN_ ].addons.length; a++ )
  51. {
  52. if ( typeof this[ '_addon_' + $[ _PLUGIN_ ].addons[ a ] ] == 'function' )
  53. {
  54. this[ '_addon_' + $[ _PLUGIN_ ].addons[ a ] ]();
  55. }
  56. }
  57. }
  58. },
  59. _bindCustomEvents: function()
  60. {
  61. var that = this;
  62. // Panel-events
  63. var $panels = this.$menu.find( this.opts.isMenu && !this.opts.slidingSubmenus ? 'ul, ol' : '.' + _c.panel );
  64. $panels
  65. .off( _e.toggle + ' ' + _e.open + ' ' + _e.close )
  66. .on( _e.toggle + ' ' + _e.open + ' ' + _e.close,
  67. function( e )
  68. {
  69. e.stopPropagation();
  70. }
  71. );
  72. if ( this.opts.slidingSubmenus )
  73. {
  74. $panels
  75. .on( _e.open,
  76. function( e )
  77. {
  78. return openSubmenuHorizontal( $(this), that.$menu );
  79. }
  80. );
  81. }
  82. else
  83. {
  84. $panels
  85. .on( _e.toggle,
  86. function( e )
  87. {
  88. var $t = $(this);
  89. return $t.triggerHandler( $t.parent().hasClass( _c.opened ) ? _e.close : _e.open );
  90. }
  91. )
  92. .on( _e.open,
  93. function( e )
  94. {
  95. $(this).parent().addClass( _c.opened );
  96. return 'open';
  97. }
  98. )
  99. .on( _e.close,
  100. function( e )
  101. {
  102. $(this).parent().removeClass( _c.opened );
  103. return 'close';
  104. }
  105. );
  106. }
  107. },
  108. _initMenu: function()
  109. {
  110. var that = this;
  111. // Clone if needed
  112. if ( this.opts.offCanvas && this.conf.clone )
  113. {
  114. this.$menu = this.$menu.clone( true );
  115. this.$menu.add( this.$menu.find( '*' ) ).filter( '[id]' ).each(
  116. function()
  117. {
  118. $(this).attr( 'id', _c.mm( $(this).attr( 'id' ) ) );
  119. }
  120. );
  121. }
  122. // Strip whitespace
  123. this.$menu.contents().each(
  124. function()
  125. {
  126. if ( $(this)[ 0 ].nodeType == 3 )
  127. {
  128. $(this).remove();
  129. }
  130. }
  131. );
  132. this.$menu
  133. .parent()
  134. .addClass( _c.wrapper );
  135. var clsn = [ _c.menu ];
  136. // Add direction class
  137. clsn.push( _c.mm( this.opts.slidingSubmenus ? 'horizontal' : 'vertical' ) );
  138. // Add options classes
  139. if ( this.opts.classes )
  140. {
  141. clsn.push( this.opts.classes );
  142. }
  143. if ( this.opts.isMenu )
  144. {
  145. clsn.push( _c.ismenu );
  146. }
  147. this.$menu.addClass( clsn.join( ' ' ) );
  148. },
  149. _initPanels: function()
  150. {
  151. var that = this;
  152. // Refactor List class
  153. this.__refactorClass( $('.' + this.conf.classNames.list, this.$menu), this.conf.classNames.list, 'list' );
  154. // Add List class
  155. if ( this.opts.isMenu )
  156. {
  157. $('ul, ol', this.$menu)
  158. .not( '.mm-nolist' )
  159. .addClass( _c.list );
  160. }
  161. var $lis = $('.' + _c.list + ' > li', this.$menu);
  162. // Refactor Selected class
  163. this.__refactorClass( $lis, this.conf.classNames.selected, 'selected' );
  164. // Refactor Label class
  165. this.__refactorClass( $lis, this.conf.classNames.label, 'label' );
  166. // Refactor Spacer class
  167. this.__refactorClass( $lis, this.conf.classNames.spacer, 'spacer' );
  168. // setSelected-event
  169. $lis
  170. .off( _e.setSelected )
  171. .on( _e.setSelected,
  172. function( e, selected )
  173. {
  174. e.stopPropagation();
  175. $lis.removeClass( _c.selected );
  176. if ( typeof selected != 'boolean' )
  177. {
  178. selected = true;
  179. }
  180. if ( selected )
  181. {
  182. $(this).addClass( _c.selected );
  183. }
  184. }
  185. );
  186. // Refactor Panel class
  187. this.__refactorClass( $('.' + this.conf.classNames.panel, this.$menu), this.conf.classNames.panel, 'panel' );
  188. // Add Panel class
  189. this.$menu
  190. .children()
  191. .filter( this.conf.panelNodetype )
  192. .add( this.$menu.find( '.' + _c.list ).children().children().filter( this.conf.panelNodetype ) )
  193. .addClass( _c.panel );
  194. var $panels = $('.' + _c.panel, this.$menu);
  195. // Add an ID to all panels
  196. $panels
  197. .each(
  198. function( i )
  199. {
  200. var $t = $(this),
  201. id = $t.attr( 'id' ) || that.__getUniqueId();
  202. $t.attr( 'id', id );
  203. }
  204. );
  205. // Add open and close links to menu items
  206. $panels
  207. .find( '.' + _c.panel )
  208. .each(
  209. function( i )
  210. {
  211. var $t = $(this),
  212. $u = $t.is( 'ul, ol' ) ? $t : $t.find( 'ul ,ol' ).first(),
  213. $l = $t.parent(),
  214. $a = $l.find( '> a, > span' ),
  215. $p = $l.closest( '.' + _c.panel );
  216. $t.data( _d.parent, $l );
  217. if ( $l.parent().is( '.' + _c.list ) )
  218. {
  219. var $btn = $( '<a class="' + _c.subopen + '" href="#' + $t.attr( 'id' ) + '" />' ).insertBefore( $a );
  220. if ( !$a.is( 'a' ) )
  221. {
  222. $btn.addClass( _c.fullsubopen );
  223. }
  224. if ( that.opts.slidingSubmenus )
  225. {
  226. $u.prepend( '<li class="' + _c.subtitle + '"><a class="' + _c.subclose + '" href="#' + $p.attr( 'id' ) + '">' + $a.text() + '</a></li>' );
  227. }
  228. }
  229. }
  230. );
  231. // Link anchors to panels
  232. var evt = this.opts.slidingSubmenus ? _e.open : _e.toggle;
  233. $panels
  234. .each(
  235. function( i )
  236. {
  237. var $opening = $(this),
  238. id = $opening.attr( 'id' );
  239. $('a[href="#' + id + '"]', that.$menu)
  240. .off( _e.click )
  241. .on( _e.click,
  242. function( e )
  243. {
  244. e.preventDefault();
  245. $opening.trigger( evt );
  246. }
  247. );
  248. }
  249. );
  250. if ( this.opts.slidingSubmenus )
  251. {
  252. // Add opened-classes
  253. var $selected = $('.' + _c.list + ' > li.' + _c.selected, this.$menu);
  254. $selected
  255. .parents( 'li' )
  256. .removeClass( _c.selected )
  257. .end()
  258. .add( $selected.parents( 'li' ) )
  259. .each(
  260. function()
  261. {
  262. var $t = $(this),
  263. $u = $t.find( '> .' + _c.panel );
  264. if ( $u.length )
  265. {
  266. $t.parents( '.' + _c.panel ).addClass( _c.subopened );
  267. $u.addClass( _c.opened );
  268. }
  269. }
  270. )
  271. .closest( '.' + _c.panel )
  272. .addClass( _c.opened )
  273. .parents( '.' + _c.panel )
  274. .addClass( _c.subopened );
  275. }
  276. else
  277. {
  278. // Replace Selected-class with opened-class in parents from .Selected
  279. var $selected = $('li.' + _c.selected, this.$menu);
  280. $selected
  281. .parents( 'li' )
  282. .removeClass( _c.selected )
  283. .end()
  284. .add( $selected.parents( 'li' ) )
  285. .addClass( _c.opened );
  286. }
  287. // Set current opened
  288. var $current = $panels.filter( '.' + _c.opened );
  289. if ( !$current.length )
  290. {
  291. $current = $panels.first();
  292. }
  293. $current
  294. .addClass( _c.opened )
  295. .last()
  296. .addClass( _c.current );
  297. // Rearrange markup
  298. if ( this.opts.slidingSubmenus )
  299. {
  300. $panels
  301. .not( $current.last() )
  302. .addClass( _c.hidden )
  303. .end()
  304. .find( '.' + _c.panel )
  305. .appendTo( this.$menu );
  306. }
  307. },
  308. _initLinks: function()
  309. {
  310. var that = this;
  311. $('.' + _c.list + ' > li > a', this.$menu)
  312. .not( '.' + _c.subopen )
  313. .not( '.' + _c.subclose )
  314. .not( '[rel="external"]' )
  315. .not( '[target="_blank"]' )
  316. .off( _e.click )
  317. .on( _e.click,
  318. function( e )
  319. {
  320. var $t = $(this),
  321. href = $t.attr( 'href' );
  322. // Set selected item
  323. if ( that.__valueOrFn( that.opts.onClick.setSelected, $t ) )
  324. {
  325. $t.parent().trigger( _e.setSelected );
  326. }
  327. // Prevent default / don't follow link. Default: false
  328. var preventDefault = that.__valueOrFn( that.opts.onClick.preventDefault, $t, href.slice( 0, 1 ) == '#' );
  329. if ( preventDefault )
  330. {
  331. e.preventDefault();
  332. }
  333. // Block UI. Default: false if preventDefault, true otherwise
  334. if ( that.__valueOrFn( that.opts.onClick.blockUI, $t, !preventDefault ) )
  335. {
  336. glbl.$html.addClass( _c.blocking );
  337. }
  338. // Close menu. Default: true if preventDefault, false otherwise
  339. if ( that.__valueOrFn( that.opts.onClick.close, $t, preventDefault ) )
  340. {
  341. that.$menu.triggerHandler( _e.close );
  342. }
  343. }
  344. );
  345. },
  346. _update: function( fn )
  347. {
  348. if ( !this.updates )
  349. {
  350. this.updates = [];
  351. }
  352. if ( typeof fn == 'function' )
  353. {
  354. this.updates.push( fn );
  355. }
  356. else
  357. {
  358. for ( var u = 0, l = this.updates.length; u < l; u++ )
  359. {
  360. this.updates[ u ].call( this, fn );
  361. }
  362. }
  363. },
  364. __valueOrFn: function( o, $e, d )
  365. {
  366. if ( typeof o == 'function' )
  367. {
  368. return o.call( $e[ 0 ] );
  369. }
  370. if ( typeof o == 'undefined' && typeof d != 'undefined' )
  371. {
  372. return d;
  373. }
  374. return o;
  375. },
  376. __refactorClass: function( $e, o, c )
  377. {
  378. $e.filter( '.' + o )
  379. .removeClass( o )
  380. .addClass( _c[ c ] );
  381. },
  382. __transitionend: function( $e, fn, duration )
  383. {
  384. var _ended = false,
  385. _fn = function()
  386. {
  387. if ( !_ended )
  388. {
  389. fn.call( $e[ 0 ] );
  390. }
  391. _ended = true;
  392. };
  393. $e.one( _e.transitionend, _fn );
  394. $e.one( _e.webkitTransitionEnd, _fn );
  395. setTimeout( _fn, duration * 1.1 );
  396. },
  397. __getUniqueId: function()
  398. {
  399. return _c.mm( $[ _PLUGIN_ ].uniqueId++ );
  400. }
  401. };
  402. $.fn[ _PLUGIN_ ] = function( opts, conf )
  403. {
  404. // First time plugin is fired
  405. if ( !plugin_initiated )
  406. {
  407. _initPlugin();
  408. }
  409. // Extend options
  410. opts = extendOptions( opts, conf );
  411. conf = extendConfiguration( conf );
  412. return this.each(
  413. function()
  414. {
  415. var $menu = $(this);
  416. if ( $menu.data( _PLUGIN_ ) )
  417. {
  418. return;
  419. }
  420. $menu.data( _PLUGIN_, new $[ _PLUGIN_ ]( $menu, opts, conf ) );
  421. }
  422. );
  423. };
  424. $[ _PLUGIN_ ].version = _VERSION_;
  425. $[ _PLUGIN_ ].defaults = {
  426. classes : '',
  427. slidingSubmenus : true,
  428. onClick : {
  429. // close : true,
  430. // blockUI : null,
  431. // preventDefault : null,
  432. setSelected : true
  433. }
  434. };
  435. $[ _PLUGIN_ ].configuration = {
  436. panelNodetype : 'ul, ol, div',
  437. transitionDuration : 400,
  438. classNames : {
  439. panel : 'Panle',
  440. list : 'List',
  441. selected : 'Selected',
  442. label : 'Label',
  443. spacer : 'Spacer'
  444. }
  445. };
  446. /*
  447. SUPPORT
  448. */
  449. (function() {
  450. var wd = window.document,
  451. ua = window.navigator.userAgent;
  452. var _touch = 'ontouchstart' in wd,
  453. _overflowscrolling = 'WebkitOverflowScrolling' in wd.documentElement.style,
  454. _oldAndroidBrowser = (function() {
  455. if ( ua.indexOf( 'Android' ) >= 0 )
  456. {
  457. return 2.4 > parseFloat( ua.slice( ua.indexOf( 'Android' ) +8 ) );
  458. }
  459. return false;
  460. })();
  461. $[ _PLUGIN_ ].support = {
  462. touch: _touch,
  463. oldAndroidBrowser: _oldAndroidBrowser,
  464. overflowscrolling: (function() {
  465. if ( !_touch )
  466. {
  467. return true;
  468. }
  469. if ( _overflowscrolling )
  470. {
  471. return true;
  472. }
  473. if ( _oldAndroidBrowser )
  474. {
  475. return false;
  476. }
  477. return true;
  478. })()
  479. };
  480. })();
  481. /*
  482. DEBUG
  483. */
  484. $[ _PLUGIN_ ].debug = function( msg ) {};
  485. $[ _PLUGIN_ ].deprecated = function( depr, repl )
  486. {
  487. if ( typeof console != 'undefined' && typeof console.warn != 'undefined' )
  488. {
  489. console.warn( 'MMENU: ' + depr + ' is deprecated, use ' + repl + ' instead.' );
  490. }
  491. };
  492. function extendOptions( o, c, $m )
  493. {
  494. if ( $m )
  495. {
  496. if ( typeof o != 'object' )
  497. {
  498. o = {};
  499. }
  500. if ( typeof o.isMenu != 'boolean' )
  501. {
  502. var $c = $m.children();
  503. o.isMenu = ( $c.length == 1 && $c.is( c.panelNodetype ) );
  504. }
  505. return o;
  506. }
  507. // Extend from defaults
  508. o = $.extend( true, {}, $[ _PLUGIN_ ].defaults, o );
  509. // DEPRECATED
  510. if ( o.position == 'top' || o.position == 'bottom' )
  511. {
  512. if ( o.zposition == 'back' || o.zposition == 'next' )
  513. {
  514. $[ _PLUGIN_ ].deprecated( 'Using position "' + o.position + '" in combination with zposition "' + o.zposition + '"', 'zposition "front"' );
  515. o.zposition = 'front';
  516. }
  517. }
  518. for ( var a = [ 'position', 'zposition', 'modal', 'moveBackground' ], b = 0, l = a.length; b < l; b++ )
  519. {
  520. if ( typeof o[ a[ b ] ] != 'undefined' )
  521. {
  522. $[ _PLUGIN_ ].deprecated( 'The option "' + a[ b ] + '"', 'offCanvas.' + a[ b ] );
  523. o.offCanvas = o.offCanvas || {};
  524. o.offCanvas[ a[ b ] ] = o[ a[ b ] ];
  525. }
  526. }
  527. // /DEPRECATED
  528. return o;
  529. }
  530. function extendConfiguration( c )
  531. {
  532. c = $.extend( true, {}, $[ _PLUGIN_ ].configuration, c )
  533. // DEPRECATED
  534. for ( var a = [ 'panel', 'list', 'selected', 'label', 'spacer' ], b = 0, l = a.length; b < l; b++ )
  535. {
  536. if ( typeof c[ a[ b ] + 'Class' ] != 'undefined' )
  537. {
  538. $[ _PLUGIN_ ].deprecated( 'The configuration option "' + a[ b ] + 'Class"', 'classNames.' + a[ b ] );
  539. c.classNames[ a[ b ] ] = c[ a[ b ] + 'Class' ];
  540. }
  541. }
  542. if ( typeof c.counterClass != 'undefined' )
  543. {
  544. $[ _PLUGIN_ ].deprecated( 'The configuration option "counterClass"', 'classNames.counters.counter' );
  545. c.classNames.counters = c.classNames.counters || {};
  546. c.classNames.counters.counter = c.counterClass;
  547. }
  548. if ( typeof c.collapsedClass != 'undefined' )
  549. {
  550. $[ _PLUGIN_ ].deprecated( 'The configuration option "collapsedClass"', 'classNames.labels.collapsed' );
  551. c.classNames.labels = c.classNames.labels || {};
  552. c.classNames.labels.collapsed = c.collapsedClass;
  553. }
  554. if ( typeof c.header != 'undefined' )
  555. {
  556. for ( var a = [ 'panelHeader', 'panelNext', 'panelPrev' ], b = 0, l = a.length; b < l; b++ )
  557. {
  558. if ( typeof c.header[ a[ b ] + 'Class' ] != 'undefined' )
  559. {
  560. $[ _PLUGIN_ ].deprecated( 'The configuration option "header.' + a[ b ] + 'Class"', 'classNames.header.' + a[ b ] );
  561. c.classNames.header = c.classNames.header || {};
  562. c.classNames.header[ a[ b ] ] = c.header[ a[ b ] + 'Class' ];
  563. }
  564. }
  565. }
  566. for ( var a = [ 'pageNodetype', 'pageSelector', 'menuWrapperSelector', 'menuInjectMethod' ], b = 0, l = a.length; b < l; b++ )
  567. {
  568. if ( typeof c[ a[ b ] ] != 'undefined' )
  569. {
  570. $[ _PLUGIN_ ].deprecated( 'The configuration option "' + a[ b ] + '"', 'offCanvas.' + a[ b ] );
  571. c.offCanvas = c.offCanvas || {};
  572. c.offCanvas[ a[ b ] ] = c[ a[ b ] ];
  573. }
  574. }
  575. // /DEPRECATED
  576. return c;
  577. }
  578. function _initPlugin()
  579. {
  580. plugin_initiated = true;
  581. glbl.$wndw = $(window);
  582. glbl.$html = $('html');
  583. glbl.$body = $('body');
  584. // Classnames, Datanames, Eventnames
  585. $.each( [ _c, _d, _e ],
  586. function( i, o )
  587. {
  588. o.add = function( c )
  589. {
  590. c = c.split( ' ' );
  591. for ( var d in c )
  592. {
  593. o[ c[ d ] ] = o.mm( c[ d ] );
  594. }
  595. };
  596. }
  597. );
  598. // Classnames
  599. _c.mm = function( c ) { return 'mm-' + c; };
  600. _c.add( 'wrapper menu ismenu inline panel list subtitle selected label spacer current highest hidden opened subopened subopen fullsubopen subclose' );
  601. _c.umm = function( c )
  602. {
  603. if ( c.slice( 0, 3 ) == 'mm-' )
  604. {
  605. c = c.slice( 3 );
  606. }
  607. return c;
  608. };
  609. // Datanames
  610. _d.mm = function( d ) { return 'mm-' + d; };
  611. _d.add( 'parent' );
  612. // Eventnames
  613. _e.mm = function( e ) { return e + '.mm'; };
  614. _e.add( 'toggle open close setSelected transitionend webkitTransitionEnd mousedown mouseup touchstart touchmove touchend scroll resize click keydown keyup' );
  615. $[ _PLUGIN_ ]._c = _c;
  616. $[ _PLUGIN_ ]._d = _d;
  617. $[ _PLUGIN_ ]._e = _e;
  618. $[ _PLUGIN_ ].glbl = glbl;
  619. }
  620. function openSubmenuHorizontal( $opening, $m )
  621. {
  622. if ( $opening.hasClass( _c.current ) )
  623. {
  624. return false;
  625. }
  626. var $panels = $('.' + _c.panel, $m),
  627. $current = $panels.filter( '.' + _c.current );
  628. $panels
  629. .removeClass( _c.highest )
  630. .removeClass( _c.current )
  631. .not( $opening )
  632. .not( $current )
  633. .addClass( _c.hidden );
  634. if ( $opening.hasClass( _c.opened ) )
  635. {
  636. $current
  637. .addClass( _c.highest )
  638. .removeClass( _c.opened )
  639. .removeClass( _c.subopened );
  640. }
  641. else
  642. {
  643. $opening
  644. .addClass( _c.highest );
  645. $current
  646. .addClass( _c.subopened );
  647. }
  648. $opening
  649. .removeClass( _c.hidden )
  650. .addClass( _c.current );
  651. // Without the timeout, the animation won't work because the element had display: none;
  652. setTimeout(
  653. function()
  654. {
  655. $opening
  656. .removeClass( _c.subopened )
  657. .addClass( _c.opened );
  658. }, 25
  659. );
  660. return 'open';
  661. }
  662. })( jQuery );