1/** 2 * Reaktion.js 3 * Version: 1.0 4 * URL: https://github.com/ryantbrown/reaktion.js 5 * Description: A lightweight responsive, nested navigation plugin for jQuery 6 * Author: Ryan Brown (http://[email protected]) (http://ryantbrown.io) 7 * Demo URL: http://ryantbrown.io/code/reaktionjs 8 * License: MIT 9 */ 10 11;(function(jQuery, document, window, undefined) { 12 13 var reaktion, nav, menu, defaults = { 14 breakPoint: 930, 15 navIcon: '', 16 arrows: true, 17 arrowIcon: '<span class="genericon genericon-expand"></span>', 18 arrowsToggleOnly: true, 19 animate: true, 20 effect: 'fade', 21 speed: 300, 22 animateSubNav: true, 23 subNavEffect: 'slide', 24 subNavSpeed: 300, 25 onOpen: function(){jQuery( ".mmenu, body" ).addClass( "opened" );}, 26 onClose: function(){jQuery( ".mmenu, body" ).removeClass( "opened" );} 27 }; 28 29 function Reaktion(element, options) { 30 this.element = element; 31 this.options = jQuery.extend({}, defaults, options); 32 this._defaults = defaults; 33 34 this._init(); 35 } 36 37 Reaktion.prototype = { 38 39 _init: function() { 40 41 nav = jQuery(this.element); 42 reaktion = this; 43 menu = jQuery(this.element).find('ul:first'); 44 45 nav.prepend('<button class="nav-bars">'+this.options.navIcon+'</button>'); 46 47 jQuery('.nav-bars').click(function() { 48 menu.is(':visible') ? reaktion.close() : reaktion.open(); 49 var findInsiders = function(elem) { 50 var tabbable = elem.find('select, input, textarea, button, a'); 51 52 var firstTabbable = tabbable.first(); 53 var lastTabbable = tabbable.last(); 54 /*set focus on first input*/ 55 firstTabbable.focus(); 56 57 /*redirect last tab to first input*/ 58 lastTabbable.on('keydown', function (e) { 59 if ((e.which === 9 && !e.shiftKey)) { 60 e.preventDefault(); 61 firstTabbable.focus(); 62 } 63 }); 64 65 /*redirect first shift+tab to last input*/ 66 firstTabbable.on('keydown', function (e) { 67 if ((e.which === 9 && e.shiftKey)) { 68 e.preventDefault(); 69 lastTabbable.focus(); 70 } 71 }); 72 73 /* allow escape key to close insiders div */ 74 elem.on('keyup', function(e){ 75 if (e.keyCode === 27 ) { 76 elem.hide(); 77 }; 78 }); 79 }; 80 findInsiders(jQuery('.mmenu')); 81 }); 82 83 if(this.options.arrows) { 84 nav.find('ul > li.menu-item-has-children .parent-menu-item') 85 .append('<button class="arrow">'+this.options.arrowIcon+'</button>'); 86 menu.on('click', 'button.arrow', function() { 87 reaktion._toggleSubNav(jQuery(this)); 88 }); 89 } else { 90 nav.find('ul > li').not('ul > li > ul li').has('ul') 91 .prepend('<button class="arrow" style="padding:0;"></button>'); 92 } 93 94 if(!this.options.arrows || !this.options.arrowsToggleOnly) { 95 nav.find('ul > li').not('ul > li > ul li').has('ul').find('a').on('click', function(){ 96 reaktion._toggleSubNav(jQuery(this)); 97 }); 98 } 99 100 reaktion._resize(); 101 102 jQuery(window).resize(function(){ 103 reaktion._resize(); 104 }); 105 106 }, 107 108 _resize: function() { 109 if(jQuery(window).width() > this.options.breakPoint) { 110 nav.removeClass('mobile'); 111 nav.find('ul:first').show().find('.arrow').removeClass('arrow-rotate') 112 .parent().find('ul').hide(); 113 114 nav.find('ul:first > li').hover(function() { 115 if(!nav.hasClass('mobile')) { 116 jQuery(this).find('ul').show(); 117 } 118 }, function(){ 119 if(!nav.hasClass('mobile')) { 120 jQuery(this).find('ul').hide(); 121 } 122 }); 123 124 } else { 125 if(!jQuery(this.element).hasClass('mobile')) { 126 jQuery(this.element).addClass('mobile'); 127 } 128 jQuery(this.element).unbind('mouseenter mouseleave'); 129 } 130 }, 131 132 _toggleSubNav: function(arrow) { 133 if(jQuery('.nav-bars').is(':visible')) { 134 if(this.options.animateSubNav) { 135 this.options.subNavEffect == 'slide' ? 136 arrow.parent().siblings('ul').slideToggle(this.options.subNavSpeed) : 137 arrow.parent().siblings('ul').fadeToggle(this.options.subNavSpeed); 138 } else { 139 arrow.parent().siblings('ul').toggle(); 140 } 141 if(this.options.arrows) { 142 arrow.toggleClass('arrow-rotate'); 143 } 144 } 145 }, 146 147 open: function() { 148 if(!menu.is(':visible')) { 149 if(this.options.animate) { 150 this.options.effect == 'slide' ? 151 menu.slideDown(this.options.speed, function(){ 152 if(typeof reaktion.options.onOpen === 'function'){ 153 reaktion.options.onOpen.call(this); 154 } 155 }) : 156 menu.fadeIn(this.options.speed, function(){ 157 if(typeof reaktion.options.onOpen === 'function'){ 158 reaktion.options.onOpen.call(this); 159 } 160 }); 161 } else { 162 menu.show(function(){ 163 if(typeof reaktion.options.onOpen === 'function'){ 164 reaktion.options.onOpen.call(this); 165 } 166 }); 167 } 168 } 169 }, 170 171 close: function() { 172 if(menu.is(':visible')) { 173 if(this.options.animate) { 174 this.options.effect == 'slide' ? 175 menu.slideUp(this.options.speed, function(){ 176 if(typeof reaktion.options.onClose === 'function'){ 177 reaktion.options.onClose.call(this); 178 } 179 }) : 180 menu.fadeOut(this.options.speed, function(){ 181 if(typeof reaktion.options.onClose === 'function'){ 182 reaktion.options.onClose.call(this); 183 } 184 }); 185 } else { 186 menu.hide(function(){ 187 if(typeof reaktion.options.onClose === 'function'){ 188 reaktion.options.onClose.call(this); 189 } 190 }); 191 } 192 } 193 }, 194 195 toggle: function(){ 196 menu.is(':visible') ? this.close() : this.open(); 197 } 198 199 }; 200 201 jQuery.fn['reaktion'] = function(args) { 202 if (!jQuery(this).length) { 203 return jQuery(this); 204 } 205 var instance = jQuery(this).data('reaktion'); 206 207 if(instance && instance[args] && args.indexOf('_') != 0 && typeof instance[args] === 'function') { 208 return instance[args].apply(instance, Array.prototype.slice.call(arguments, 1)); 209 } else if(typeof args === 'object' || !args) { 210 instance = new Reaktion(jQuery(this), args); 211 jQuery(this).data('reaktion', instance); 212 return this; 213 } else if(args.indexOf('_') == 0) { 214 jQuery.error('The ' + args + ' method is private and cannot be called publicly'); 215 } else { 216 jQuery.error('Method ' + args + ' does not exist in reaktion'); 217 } 218 }; 219 220})(jQuery, document, window); 221jQuery(document).ready(function(jQuery) { 222 jQuery('.mmenu').reaktion(); 223 }); 224 jQuery( ".mmenu ul.sub-menu" ).prev().wrap( "<div class='parent-menu-item'></div>" );
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.