1(function() { 2 var SOURCES = window.TEXT_VARIABLES.sources; 3 window.Lazyload.js(SOURCES.jquery, function() { 4 function toc(options) { 5 var $root = this, $window = $(window), $scrollTarget, $scroller, $tocUl = $('<ul class="toc toc--ellipsis"></ul>'), $tocLi, $headings, $activeLast, $activeCur, 6 selectors = 'h1,h2,h3', container = 'body', scrollTarget = window, scroller = 'html, body', disabled = false, 7 headingsPos, scrolling = false, hasRendered = false, hasInit = false; 8 9 function setOptions(options) { 10 var _options = options || {}; 11 _options.selectors && (selectors = _options.selectors); 12 _options.container && (container = _options.container); 13 _options.scrollTarget && (scrollTarget = _options.scrollTarget); 14 _options.scroller && (scroller = _options.scroller); 15 _options.disabled !== undefined && (disabled = _options.disabled); 16 $headings = $(container).find(selectors).filter('[id]'); 17 $scrollTarget = $(scrollTarget); 18 $scroller = $(scroller); 19 } 20 function calc() { 21 headingsPos = []; 22 $headings.each(function() { 23 headingsPos.push(Math.floor($(this).position().top)); 24 }); 25 } 26 function setState(element, disabled) { 27 var scrollTop = $scrollTarget.scrollTop(), i; 28 if (disabled || !headingsPos || headingsPos.length < 1) { return; } 29 if (element) { 30 $activeCur = element; 31 } else { 32 for (i = 0; i < headingsPos.length; i++) { 33 if (scrollTop >= headingsPos[i]) { 34 $activeCur = $tocLi.eq(i); 35 } else { 36 $activeCur || ($activeCur = $tocLi.eq(i)); 37 break; 38 } 39 } 40 } 41 $activeLast && $activeLast.removeClass('active'); 42 ($activeLast = $activeCur).addClass('active'); 43 } 44 function render() { 45 if(!hasRendered) { 46 $root.append($tocUl); 47 $headings.each(function() { 48 var $this = $(this); 49 $tocUl.append($('<li></li>').addClass('toc-' + $this.prop('tagName').toLowerCase()) 50 .append($('<a></a>').text($this.text()).attr('href', '#' + $this.prop('id')))); 51 }); 52 $tocLi = $tocUl.children('li'); 53 $tocUl.on('click', 'a', function(e) { 54 e.preventDefault(); 55 var $this = $(this); 56 scrolling = true; 57 setState($this.parent()); 58 $scroller.scrollToAnchor($this.attr('href'), 400, function() { 59 scrolling = false; 60 }); 61 }); 62 } 63 hasRendered = true; 64 } 65 function init() { 66 var interval, timeout; 67 if(!hasInit) { 68 render(); calc(); setState(null, scrolling); 69 // run calc every 100 millisecond 70 interval = setInterval(function() { 71 calc(); 72 }, 100); 73 timeout = setTimeout(function() { 74 clearInterval(interval); 75 }, 45000); 76 window.pageLoad.then(function() { 77 setTimeout(function() { 78 clearInterval(interval); 79 clearTimeout(timeout); 80 }, 3000); 81 }); 82 $scrollTarget.on('scroll', function() { 83 disabled || setState(null, scrolling); 84 }); 85 $window.on('resize', window.throttle(function() { 86 if (!disabled) { 87 render(); calc(); setState(null, scrolling); 88 } 89 }, 100)); 90 } 91 hasInit = true; 92 } 93 94 setOptions(options); 95 if (!disabled) { 96 init(); 97 } 98 $window.on('resize', window.throttle(function() { 99 init(); 100 }, 200)); 101 return { 102 setOptions: setOptions 103 }; 104 } 105 $.fn.toc = toc; 106 }); 107})();