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