'use strict' const Even = {} Even.backToTop = function () { const $backToTop = $('#back-to-top') $(window).scroll(function () { if ($(window).scrollTop() > 100) { $backToTop.fadeIn(1000) } else { $backToTop.fadeOut(1000) } }) $backToTop.click(function () { $('body,html').animate({ scrollTop: 0 }) }) } Even.mobileNavbar = function () { const $mobileNav = $('#mobile-navbar') const $mobileNavIcon = $('.mobile-navbar-icon') const slideout = new Slideout({ 'panel': document.getElementById('mobile-panel'), 'menu': document.getElementById('mobile-menu'), 'padding': 180, 'tolerance': 70 }) slideout.disableTouch() $mobileNavIcon.click(function () { slideout.toggle() }) slideout.on('beforeopen', function () { $mobileNav.addClass('fixed-open') $mobileNavIcon.addClass('icon-click').removeClass('icon-out') }) slideout.on('beforeclose', function () { $mobileNav.removeClass('fixed-open') $mobileNavIcon.addClass('icon-out').removeClass('icon-click') }) $('#mobile-panel').on('touchend', function () { slideout.isOpen() && $mobileNavIcon.click() }) } Even._initToc = function () { const SPACING = 20 const $toc = $('.post-toc') const $footer = $('.post-footer') if ($toc.length) { const minScrollTop = $toc.offset().top - SPACING const maxScrollTop = $footer.offset().top - $toc.height() - SPACING const tocState = { start: { 'position': 'absolute', 'top': minScrollTop }, process: { 'position': 'fixed', 'top': SPACING }, end: { 'position': 'absolute', 'top': maxScrollTop } } $(window).scroll(function () { const scrollTop = $(window).scrollTop() if (scrollTop < minScrollTop) { $toc.css(tocState.start) } else if (scrollTop > maxScrollTop) { $toc.css(tocState.end) } else { $toc.css(tocState.process) } }) } const HEADERFIX = 30 const $toclink = $('.toc-link') const $headerlink = $('.headerlink') const $tocLinkLis = $('.post-toc-content li') const headerlinkTop = $.map($headerlink, function (link) { return $(link).offset().top }) const headerLinksOffsetForSearch = $.map(headerlinkTop, function (offset) { return offset - HEADERFIX }) const searchActiveTocIndex = function (array, target) { for (let i = 0; i < array.length - 1; i++) { if (target > array[i] && target <= array[i + 1]) return i } if (target > array[array.length - 1]) return array.length - 1 return -1 } $(window).scroll(function () { const scrollTop = $(window).scrollTop() const activeTocIndex = searchActiveTocIndex(headerLinksOffsetForSearch, scrollTop) $($toclink).removeClass('active') $($tocLinkLis).removeClass('has-active') if (activeTocIndex !== -1) { $($toclink[activeTocIndex]).addClass('active') let ancestor = $toclink[activeTocIndex].parentNode while (ancestor.tagName !== 'NAV') { $(ancestor).addClass('has-active') ancestor = ancestor.parentNode.parentNode } } }) } Even.fancybox = function () { if ($.fancybox) { $('.post-content').each(function () { $(this).find('img').each(function () { $(this).wrap(``) }) }) $('.fancybox').fancybox({ selector: '.fancybox', protect: true }) } } Even.highlight = function () { const blocks = document.querySelectorAll('pre code') for (let i = 0; i < blocks.length; i++) { const block = blocks[i] const rootElement = block.parentElement const lineCodes = block.innerHTML.split(/\n/) if (lineCodes[lineCodes.length - 1] === '') lineCodes.pop() const lineLength = lineCodes.length let codeLineHtml = '' for (let i = 0; i < lineLength; i++) { codeLineHtml += `
${i + 1}
` } let codeHtml = '' for (let i = 0; i < lineLength; i++) { codeHtml += `
${lineCodes[i]}
` } block.className += ' highlight' const figure = document.createElement('figure') figure.className = block.className figure.innerHTML = `
${codeLineHtml}
${codeHtml}
` rootElement.parentElement.replaceChild(figure, rootElement) } } Even.toc = function () { const tocContainer = document.getElementById('post-toc') if (tocContainer !== null) { const toc = document.getElementById('TableOfContents') if (toc === null) { // toc = true, but there are no headings tocContainer.parentNode.removeChild(tocContainer) } else { this._refactorToc(toc) this._linkToc() this._initToc() } } } Even._refactorToc = function (toc) { // when headings do not start with `h1` const oldTocList = toc.children[0] let newTocList = oldTocList let temp while (newTocList.children.length === 1 && (temp = newTocList.children[0].children[0]).tagName === 'UL') newTocList = temp if (newTocList !== oldTocList) toc.replaceChild(newTocList, oldTocList) } Even._linkToc = function () { const links = document.querySelectorAll('#TableOfContents a:first-child') for (let i = 0; i < links.length; i++) links[i].className += ' toc-link' for (let num = 1; num <= 6; num++) { const headers = document.querySelectorAll('.post-content>h' + num) for (let i = 0; i < headers.length; i++) { const header = headers[i] header.innerHTML = `${header.innerHTML}` } } } Even.flowchart = function () { if (!window.flowchart) return const blocks = document.querySelectorAll('pre code.language-flowchart') for (let i = 0; i < blocks.length; i++) { const block = blocks[i] const rootElement = block.parentElement const container = document.createElement('div') const id = `js-flowchart-diagrams-${i}` container.id = id container.className = 'align-center' rootElement.parentElement.replaceChild(container, rootElement) const diagram = flowchart.parse(block.childNodes[0].nodeValue) diagram.drawSVG(id, window.flowchartDiagramsOptions ? window.flowchartDiagramsOptions : {}) } } Even.sequence = function () { if (!window.Diagram) return const blocks = document.querySelectorAll('pre code.language-sequence') for (let i = 0; i < blocks.length; i++) { const block = blocks[i] const rootElement = block.parentElement const container = document.createElement('div') const id = `js-sequence-diagrams-${i}` container.id = id container.className = 'align-center' rootElement.parentElement.replaceChild(container, rootElement) const diagram = Diagram.parse(block.childNodes[0].nodeValue) diagram.drawSVG(id, window.sequenceDiagramsOptions ? window.sequenceDiagramsOptions : {theme: 'simple'}) } } export {Even}