|
| 1 | +/* |
| 2 | +GreedyNav.js - https://github.com/lukejacksonn/GreedyNav |
| 3 | +Licensed under the MIT license - http://opensource.org/licenses/MIT |
| 4 | +Copyright (c) 2015 Luke Jackson http://lukejacksonn.com |
| 5 | +*/ |
| 6 | + |
| 7 | +$(function() { |
| 8 | + |
| 9 | + var $btn = $("nav.greedy-nav .greedy-nav__toggle"); |
| 10 | + var $vlinks = $("nav.greedy-nav .visible-links"); |
| 11 | + var $hlinks = $("nav.greedy-nav .hidden-links"); |
| 12 | + var $nav = $("nav.greedy-nav"); |
| 13 | + var $logo = $('nav.greedy-nav .site-logo'); |
| 14 | + var $logoImg = $('nav.greedy-nav .site-logo img'); |
| 15 | + var $title = $("nav.greedy-nav .site-title"); |
| 16 | + var $search = $('nav.greedy-nav button.search__toggle'); |
| 17 | + |
| 18 | + var numOfItems, totalSpace, closingTime, breakWidths; |
| 19 | + |
| 20 | + // This function measures both hidden and visible links and sets the navbar breakpoints |
| 21 | + // This is called the first time the script runs and everytime the "check()" function detects a change of window width that reached a different CSS width breakpoint, which affects the size of navbar Items |
| 22 | + // Please note that "CSS width breakpoints" (which are only 4) !== "navbar breakpoints" (which are as many as the number of items on the navbar) |
| 23 | + function measureLinks(){ |
| 24 | + numOfItems = 0; |
| 25 | + totalSpace = 0; |
| 26 | + closingTime = 1000; |
| 27 | + breakWidths = []; |
| 28 | + |
| 29 | + // Adds the width of a navItem in order to create breakpoints for the navbar |
| 30 | + function addWidth(i, w) { |
| 31 | + totalSpace += w; |
| 32 | + numOfItems += 1; |
| 33 | + breakWidths.push(totalSpace); |
| 34 | + } |
| 35 | + |
| 36 | + // Measures the width of hidden links by making a temporary clone of them and positioning under visible links |
| 37 | + function hiddenWidth(obj){ |
| 38 | + var clone = obj.clone(); |
| 39 | + clone.css("visibility","hidden"); |
| 40 | + $vlinks.append(clone); |
| 41 | + addWidth(0, clone.outerWidth()); |
| 42 | + clone.remove(); |
| 43 | + } |
| 44 | + // Measure both visible and hidden links widths |
| 45 | + $vlinks.children().outerWidth(addWidth); |
| 46 | + $hlinks.children().each(function(){hiddenWidth($(this))}); |
| 47 | + } |
| 48 | + // Get initial state |
| 49 | + measureLinks(); |
| 50 | + |
| 51 | + var winWidth = $( window ).width(); |
| 52 | + // Set the last measured CSS width breakpoint: 0: < 768px, 1: < 1200px, 2: < 1400px, 3: >= 1400px. |
| 53 | + var lastBreakpoint = winWidth < 768 ? 0 : winWidth < 1200 ? 1 : winWidth < 1400 ? 2 : 3; |
| 54 | + |
| 55 | + var availableSpace, numOfVisibleItems, requiredSpace, timer; |
| 56 | + |
| 57 | + function check() { |
| 58 | + |
| 59 | + winWidth = $( window ).width(); |
| 60 | + // Set the current CSS width breakpoint: 0: <768px, 1: < 1200px, 2: < 1400px, 3: >= 1400px. |
| 61 | + var curBreakpoint = winWidth < 768 ? 0 : winWidth < 1200 ? 1 : winWidth < 1400 ? 2 : 3; |
| 62 | + // If current breakpoint is different from last measured breakpoint, measureLinks again |
| 63 | + if(curBreakpoint !== lastBreakpoint) measureLinks(); |
| 64 | + // Set the last measured CSS width breakpoint with the current breakpoint |
| 65 | + lastBreakpoint = curBreakpoint; |
| 66 | + |
| 67 | + // Get instant state |
| 68 | + numOfVisibleItems = $vlinks.children().length; |
| 69 | + // Decrease the width of visible elements from the nav innerWidth to find out the available space for navItems |
| 70 | + availableSpace = /* nav */ $nav.innerWidth() |
| 71 | + - /* logo */ ($logo.length !== 0 ? $logo.outerWidth(true) : 0) |
| 72 | + - /* title */ $title.outerWidth(true) |
| 73 | + - /* search */ ($search.length !== 0 ? $search.outerWidth(true) : 0) |
| 74 | + - /* toggle */ (numOfVisibleItems !== breakWidths.length ? $btn.outerWidth(true) : 0); |
| 75 | + requiredSpace = breakWidths[numOfVisibleItems - 1]; |
| 76 | + |
| 77 | + // There is not enought space |
| 78 | + if (requiredSpace > availableSpace) { |
| 79 | + $vlinks.children().last().prependTo($hlinks); |
| 80 | + numOfVisibleItems -= 1; |
| 81 | + check(); |
| 82 | + // There is more than enough space. If only one element is hidden, add the toggle width to the available space |
| 83 | + } else if (availableSpace + (numOfVisibleItems === breakWidths.length - 1?$btn.outerWidth(true):0) > breakWidths[numOfVisibleItems]) { |
| 84 | + $hlinks.children().first().appendTo($vlinks); |
| 85 | + numOfVisibleItems += 1; |
| 86 | + check(); |
| 87 | + } |
| 88 | + // Update the button accordingly |
| 89 | + $btn.attr("count", numOfItems - numOfVisibleItems); |
| 90 | + if (numOfVisibleItems === numOfItems) { |
| 91 | + $btn.addClass('hidden'); |
| 92 | + } else $btn.removeClass('hidden'); |
| 93 | + } |
| 94 | + |
| 95 | + // Window listeners |
| 96 | + $(window).resize(function() { |
| 97 | + check(); |
| 98 | + }); |
| 99 | + |
| 100 | + $btn.on('click', function() { |
| 101 | + $hlinks.toggleClass('hidden'); |
| 102 | + $(this).toggleClass('close'); |
| 103 | + clearTimeout(timer); |
| 104 | + }); |
| 105 | + |
| 106 | + $hlinks.on("click", function () { |
| 107 | + // Hide the hidden links & remove the overlay when one is clicked. |
| 108 | + $hlinks.addClass("hidden"); |
| 109 | + $btn.removeClass("close"); |
| 110 | + }).on('mouseleave', function() { |
| 111 | + // Mouse has left, start the timer |
| 112 | + timer = setTimeout(function() { |
| 113 | + $hlinks.addClass('hidden'); |
| 114 | + $('.greedy-nav__toggle').removeClass('close'); |
| 115 | + }, closingTime); |
| 116 | + }).on('mouseenter', function() { |
| 117 | + // Mouse is back, cancel the timer |
| 118 | + clearTimeout(timer); |
| 119 | + }) |
| 120 | + |
| 121 | + // check if page has a logo |
| 122 | + if($logoImg.length !== 0){ |
| 123 | + // check if logo is not loaded |
| 124 | + if(!($logoImg[0].complete || $logoImg[0].naturalWidth !== 0)){ |
| 125 | + // if logo is not loaded wait for logo to load or fail to check |
| 126 | + $logoImg.one("load error", check); |
| 127 | + // if logo is already loaded just check |
| 128 | + } else check(); |
| 129 | + // if page does not have a logo just check |
| 130 | + } else check(); |
| 131 | + |
| 132 | +}); |
0 commit comments