github.com/shyftnetwork/go-empyrean@v1.8.3-0.20191127201940-fbfca9338f04/shyft_documentation/source/javascripts/app/_toc.js (about) 1 //= require ../lib/_jquery 2 //= require ../lib/_imagesloaded.min 3 ;(function () { 4 'use strict'; 5 6 var loaded = false; 7 8 var debounce = function(func, waitTime) { 9 var timeout = false; 10 return function() { 11 if (timeout === false) { 12 setTimeout(function() { 13 func(); 14 timeout = false; 15 }, waitTime); 16 timeout = true; 17 } 18 }; 19 }; 20 21 var closeToc = function() { 22 $(".toc-wrapper").removeClass('open'); 23 $("#nav-button").removeClass('open'); 24 }; 25 26 function loadToc($toc, tocLinkSelector, tocListSelector, scrollOffset) { 27 var headerHeights = {}; 28 var pageHeight = 0; 29 var windowHeight = 0; 30 var originalTitle = document.title; 31 32 var recacheHeights = function() { 33 headerHeights = {}; 34 pageHeight = $(document).height(); 35 windowHeight = $(window).height(); 36 37 $toc.find(tocLinkSelector).each(function() { 38 var targetId = $(this).attr('href'); 39 if (targetId[0] === "#") { 40 headerHeights[targetId] = $(targetId).offset().top; 41 } 42 }); 43 }; 44 45 var refreshToc = function() { 46 var currentTop = $(document).scrollTop() + scrollOffset; 47 48 if (currentTop + windowHeight >= pageHeight) { 49 // at bottom of page, so just select last header by making currentTop very large 50 // this fixes the problem where the last header won't ever show as active if its content 51 // is shorter than the window height 52 currentTop = pageHeight + 1000; 53 } 54 55 var best = null; 56 for (var name in headerHeights) { 57 if ((headerHeights[name] < currentTop && headerHeights[name] > headerHeights[best]) || best === null) { 58 best = name; 59 } 60 } 61 62 // Catch the initial load case 63 if (currentTop == scrollOffset && !loaded) { 64 best = window.location.hash; 65 loaded = true; 66 } 67 68 var $best = $toc.find("[href='" + best + "']").first(); 69 if (!$best.hasClass("active")) { 70 // .active is applied to the ToC link we're currently on, and its parent <ul>s selected by tocListSelector 71 // .active-expanded is applied to the ToC links that are parents of this one 72 $toc.find(".active").removeClass("active"); 73 $toc.find(".active-parent").removeClass("active-parent"); 74 $best.addClass("active"); 75 $best.parents(tocListSelector).addClass("active").siblings(tocLinkSelector).addClass('active-parent'); 76 $best.siblings(tocListSelector).addClass("active"); 77 $toc.find(tocListSelector).filter(":not(.active)").slideUp(150); 78 $toc.find(tocListSelector).filter(".active").slideDown(150); 79 // TODO remove classnames 80 document.title = $best.data("title") + " – " + originalTitle; 81 } 82 }; 83 84 var makeToc = function() { 85 recacheHeights(); 86 refreshToc(); 87 88 $("#nav-button").click(function() { 89 $(".toc-wrapper").toggleClass('open'); 90 $("#nav-button").toggleClass('open'); 91 return false; 92 }); 93 $(".page-wrapper").click(closeToc); 94 $(".toc-link").click(closeToc); 95 96 // reload immediately after scrolling on toc click 97 $toc.find(tocLinkSelector).click(function() { 98 setTimeout(function() { 99 refreshToc(); 100 }, 0); 101 }); 102 103 $(window).scroll(debounce(refreshToc, 200)); 104 $(window).resize(debounce(recacheHeights, 200)); 105 }; 106 107 makeToc(); 108 109 window.recacheHeights = recacheHeights; 110 window.refreshToc = refreshToc; 111 } 112 113 window.loadToc = loadToc; 114 })();