1// mtree.js 2// Requires jquery.js and velocity.js (optional but recommended). 3// Copy the below function, add to your JS, and simply add a list <ul class=mtree> ... </ul> 4;(function ($, window, document, undefined) { 5 "use strict"; 6 // Only apply if mtree list exists 7 if($('ul.mtree').length) { 8 9 // Settings 10 var collapsed = true; // Start with collapsed menu (only level 1 items visible) 11 var close_same_level = true; // Close elements on same level when opening new node. 12 var duration = 400; // Animation duration should be tweaked according to easing. 13 var listAnim = true; // Animate separate list items on open/close element (velocity.js only). 14 var easing = 'easeInOutQuad'; // Velocity.js only, defaults to 'swing' with jquery animation. 15 16 if ( $( '.vertical-menu-outer' ).hasClass( 'show-current-menu-open' ) || $( '.responsive-menu-wrap' ).hasClass( 'show-current-menu-open' ) ) { 17 close_same_level = false; 18 } 19 // Set initial styles 20 $('.mtree ul').css({'overflow':'hidden', 'height': (collapsed) ? 0 : 'auto', 'display': (collapsed) ? 'none' : 'block' }); 21 22 // Get node elements, and add classes for styling 23 var node = $('.mtree li:has(ul)'); 24 node.each(function(index, val) { 25 $(this).children(':first-child').css('cursor', 'pointer') 26 $(this).addClass('mtree-node mtree-' + ((collapsed) ? 'closed' : 'open')); 27 $(this).children('ul').addClass('mtree-level-' + ($(this).parentsUntil($('ul.mtree'), 'ul').length + 1)); 28 }); 29 30 // Set mtree-active class on list items for last opened element 31 $('.mtree li > *:first-child').on('click.mtree-active', function(e){ 32 if($(this).parent().hasClass('mtree-closed')) { 33 $('.mtree-active').not($(this).parent()).removeClass('mtree-active'); 34 $(this).parent().addClass('mtree-active'); 35 } else if($(this).parent().hasClass('mtree-open')){ 36 $(this).parent().removeClass('mtree-active'); 37 } else { 38 $('.mtree-active').not($(this).parent()).removeClass('mtree-active'); 39 $(this).parent().toggleClass('mtree-active'); 40 } 41 }); 42 if ( $( '.vertical-menu-outer' ).hasClass( 'show-current-menu-open' ) || $( '.responsive-menu-wrap' ).hasClass( 'show-current-menu-open' ) ) { 43 $('.mtree li').find('.current-menu-item').parents( '.sub-menu' ).css({'overflow':'hidden', 'height': 'auto', 'display': 'block' }); 44 $('.mtree li').parents('.current-menu-ancestor').removeClass('mtree-closed').addClass('mtree-open').addClass('mtree-active'); 45 } 46 // Set node click elements, preferably <a> but node links can be <span> also 47 node.children(':first-child').on('click.mtree', function(e){ 48 49 // element vars 50 var el = $(this).parent().children('ul').first(); 51 var isOpen = $(this).parent().hasClass('mtree-open'); 52 53 // close other elements on same level if opening 54 if((close_same_level || $('.csl').hasClass('active')) && !isOpen) { 55 var close_items = $(this).closest('ul').children('.mtree-open').not($(this).parent()).children('ul'); 56 57 // Velocity.js 58 if($.Velocity) { 59 close_items.velocity({ 60 height: 0 61 }, { 62 duration: duration, 63 easing: easing, 64 display: 'none', 65 delay: 100, 66 complete: function(){ 67 setNodeClass($(this).parent(), true) 68 } 69 }); 70 71 // jQuery fallback 72 } else { 73 close_items.delay(100).slideToggle(duration, function(){ 74 setNodeClass($(this).parent(), true); 75 }); 76 } 77 } 78 79 // force auto height of element so actual height can be extracted 80 el.css({'height': 'auto'}); 81 82 // listAnim: animate child elements when opening 83 if(!isOpen && $.Velocity && listAnim) el.find(' > li, li.mtree-open > ul > li').css({'opacity':0}).velocity('stop').velocity('list'); 84 85 // Velocity.js animate element 86 if($.Velocity) { 87 el.velocity('stop').velocity({ 88 //translateZ: 0, // optional hardware-acceleration is automatic on mobile 89 height: isOpen ? [0, el.outerHeight()] : [el.outerHeight(), 0] 90 },{ 91 queue: false, 92 duration: duration, 93 easing: easing, 94 display: isOpen ? 'none' : 'block', 95 begin: setNodeClass($(this).parent(), isOpen), 96 complete: function(){ 97 if(!isOpen) $(this).css('height', 'auto'); 98 } 99 }); 100 101 // jQuery fallback animate element 102 } else { 103 setNodeClass($(this).parent(), isOpen); 104 el.slideToggle(duration); 105 } 106 107 // We can't have nodes as links unfortunately 108 e.preventDefault(); 109 }); 110 111 // Function for updating node class 112 function setNodeClass(el, isOpen) { 113 if(isOpen) { 114 el.removeClass('mtree-open').addClass('mtree-closed'); 115 } else { 116 el.removeClass('mtree-closed').addClass('mtree-open'); 117 } 118 } 119 120 // List animation sequence 121 if($.Velocity && listAnim) { 122 $.Velocity.Redirects.list = function (element, options, index, size) { 123 $.Velocity.animate(element, { 124 opacity: [1,0], 125 translateY: [0, -(index+12)] 126 }, { 127 delay: index*(duration/size/1.2), 128 duration: duration, 129 easing: easing 130 }); 131 }; 132 } 133 134 // Fade in mtree after classes are added. 135 // Useful if you have set collapsed = true or applied styles that change the structure so the menu doesn't jump between states after the function executes. 136 if($('.mtree').css('opacity') == 0) { 137 if($.Velocity) { 138 $('.mtree').css('opacity', 1).children().css('opacity', 0).velocity('list'); 139 } else { 140 $('.mtree').show(200); 141 } 142 } 143 144 $('body').addClass('menu-loaded'); 145 146 } 147}(jQuery, this, this.document));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.