1/* 2 * stackable.js 3 * Author: Emiliano Prandi 4 * http://emiprandi.github.io/stackable 5 * MIT License 6 */ 7 8(function ($) { 9 'use strict'; 10 11 /* CLASS 12 * =============================== */ 13 var STACKable = function (e, o) { 14 this.stacker = { 15 e: null, 16 html: '<li class="sa-stacker"><a href="#">' + o.stackerLabel + '</a><ul></ul></li>', 17 width: 0 18 }; 19 this.e = e; 20 this.navItems = { 21 items: {}, 22 length: 0 23 }; 24 this.navWidth = 25 this.containerWidth = 0; 26 27 var t = 0, 28 tw = 0, 29 to = this.navItems.items; 30 this.e.children('li').each(function () { 31 to[t] = { 32 html: $(this)[0].outerHTML, 33 width: $(this).outerWidth(true), 34 submenu: false, 35 visible: true 36 }; 37 if ($(this).hasClass('submenu')) to[t].submenu = true; 38 tw += to[t].width; 39 t++; 40 }); 41 this.navItems.length = t; 42 this.navWidth = tw; 43 44 this.stacker.e = $(this.stacker.html).appendTo(this.e); 45 this.stacker.width = this.stacker.e.outerWidth(true); 46 this.stacker.e.remove(); 47 48 this.magic(); 49 }; 50 51 STACKable.prototype.resetStack = function () { 52 for (var tc = 0; tc < this.navItems.length; tc++) { 53 this.navItems.items[tc].visible = true; 54 } 55 }; 56 57 STACKable.prototype.magic = function () { 58 this.resetStack(); 59 this.containerWidth = this.e.parent().width(); 60 61 var match = 0, tc = 0; 62 63 if (this.containerWidth < this.navWidth) { 64 for (tc = 0; tc < this.navItems.length; tc++) { 65 match += this.navItems.items[tc].width; 66 if ((match+this.stacker.width) > this.containerWidth) { 67 this.navItems.items[tc].visible = false; 68 } 69 } 70 } 71 this.stack(); 72 }; 73 74 STACKable.prototype.stack = function () { 75 this.e.empty(); 76 var showStacker = false, tc = 0; 77 for (tc = 0; tc < this.navItems.length; tc++) { 78 if (this.navItems.items[tc].visible) { 79 $(this.navItems.items[tc].html).appendTo(this.e); 80 } else { 81 showStacker = true; 82 break; 83 } 84 } 85 86 if (showStacker) { 87 this.stacker.e = $(this.stacker.html).appendTo(this.e); 88 for (tc = 0; tc < this.navItems.length; tc++) { 89 if (!this.navItems.items[tc].visible) { 90 var th = this.navItems.items[tc].html; 91 if (th.indexOf('<ul>') !== -1) { 92 th = th.replace(/<a[^>]*>/, '<span class="sa-anchor-replacement">').replace(/<\/a>/, '</span>'); 93 } 94 $(th).appendTo(this.stacker.e.children('ul')); 95 this.navItems.items[tc].visible = false; 96 } 97 } 98 } 99 }; 100 101 STACKable.prototype.setActions = function () { 102 var te = this.e, 103 menuSelector = 'li.submenu, li.sa-stacker', 104 menuAnchorSelector = 'li.submenu>a, li.sa-stacker>a'; 105 106 $(te).on('click.stackable.nav', menuAnchorSelector, function () { 107 if ($(this).parent().hasClass('sa-open')) { 108 $(te.selector).children(menuSelector).removeClass('sa-open'); 109 } else { 110 $(te.selector).children(menuSelector).removeClass('sa-open'); 111 $(this).parent().toggleClass('sa-open'); 112 } 113 return false; 114 }); 115 $(document).on('click.stackable.closure', function () { 116 $(te.selector).children(menuSelector).removeClass('sa-open'); 117 }); 118 }; 119 120 /* PLUGIN 121 * =============================== */ 122 $.fn.stackable = function (options) { 123 var defaults = { stackerLabel: '+' }, 124 ko = false; 125 this.each(function () { if(this.tagName!='UL') ko = true; }); 126 127 if (!ko) { 128 var d = new STACKable(this, $.extend(defaults, options)); 129 d.setActions(); 130 $(window).resize( function () { d.magic(); }); 131 } 132 }; 133 134})( jQuery );
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.