hugo-theme-even/src/js/even.js

228 lines
6.3 KiB
JavaScript
Raw Normal View History

2017-08-27 14:38:42 +00:00
'use strict'
const Even = {}
2017-08-27 14:38:42 +00:00
Even.backToTop = function () {
const $backToTop = $('#back-to-top')
2017-08-27 14:38:42 +00:00
$(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({
2017-08-27 14:38:42 +00:00
'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')
2017-08-27 14:38:42 +00:00
if ($toc.length) {
const minScrollTop = $toc.offset().top - SPACING
const maxScrollTop = $footer.offset().top - $toc.height() - SPACING
2017-08-27 14:38:42 +00:00
const tocState = {
2017-08-27 14:38:42 +00:00
start: {
'position': 'absolute',
'top': minScrollTop
},
process: {
'position': 'fixed',
'top': SPACING
},
end: {
'position': 'absolute',
'top': maxScrollTop
}
}
$(window).scroll(function () {
const scrollTop = $(window).scrollTop()
2017-08-27 14:38:42 +00:00
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')
2017-12-05 12:02:25 +00:00
const $tocLinkLis = $('.post-toc-content li')
2017-08-27 14:38:42 +00:00
const headerlinkTop = $.map($headerlink, function (link) {
2017-08-27 14:38:42 +00:00
return $(link).offset().top
})
2017-12-05 12:02:25 +00:00
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
}
2017-08-27 14:38:42 +00:00
$(window).scroll(function () {
const scrollTop = $(window).scrollTop()
2017-12-05 12:02:25 +00:00
const activeTocIndex = searchActiveTocIndex(headerLinksOffsetForSearch, scrollTop)
2017-08-27 14:38:42 +00:00
2017-12-05 12:02:25 +00:00
$($toclink).removeClass('active')
$($tocLinkLis).removeClass('has-active')
2017-08-27 14:38:42 +00:00
2017-12-05 12:02:25 +00:00
if (activeTocIndex !== -1) {
$($toclink[activeTocIndex]).addClass('active')
let ancestor = $toclink[activeTocIndex].parentNode
while (ancestor.tagName !== 'NAV') {
$(ancestor).addClass('has-active')
ancestor = ancestor.parentNode.parentNode
2017-08-27 14:38:42 +00:00
}
}
})
}
Even.fancybox = function () {
if ($.fancybox) {
$('.post-content').each(function () {
2017-08-27 14:38:42 +00:00
$(this).find('img').each(function () {
2017-09-06 09:20:16 +00:00
$(this).wrap(`<a class="fancybox" href="${this.src}" data-fancybox="gallery" data-caption="${this.title}"></a>`)
2017-08-27 14:38:42 +00:00
})
})
$('.fancybox').fancybox({
2017-09-06 09:20:16 +00:00
selector: '.fancybox',
protect: true
2017-08-27 14:38:42 +00:00
})
}
}
Even.highlight = function () {
const blocks = document.querySelectorAll('pre code')
for (let i = 0; i < blocks.length; i++) {
const block = blocks[i]
2017-08-27 14:38:42 +00:00
const rootElement = block.parentElement
const lineCodes = block.innerHTML.split(/\n/)
if (lineCodes[lineCodes.length - 1] === '') lineCodes.pop()
2017-08-27 14:38:42 +00:00
const lineLength = lineCodes.length
let codeLineHtml = ''
for (let i = 0; i < lineLength; i++) {
codeLineHtml += `<div class="line">${i + 1}</div>`
}
let codeHtml = ''
for (let i = 0; i < lineLength; i++) {
codeHtml += `<div class="line">${lineCodes[i]}</div>`
2017-08-27 14:38:42 +00:00
}
block.className += ' highlight'
2017-08-27 14:38:42 +00:00
const figure = document.createElement('figure')
figure.className = block.className
2017-08-27 14:38:42 +00:00
figure.innerHTML = `<table><tbody><tr><td class="gutter"><pre>${codeLineHtml}</pre></td><td class="code"><pre>${codeHtml}</pre></td></tr></tbody></table>`
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
2017-12-05 12:02:25 +00:00
while (newTocList.children.length === 1 && (temp = newTocList.children[0].children[0]).tagName === 'UL') newTocList = temp
2017-12-05 12:02:25 +00:00
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'
2017-08-27 14:38:42 +00:00
for (let num = 1; num <= 6; num++) {
2017-08-27 14:38:42 +00:00
const headers = document.querySelectorAll('.post-content>h' + num)
for (let i = 0; i < headers.length; i++) {
const header = headers[i]
header.innerHTML = `<a href="#${header.id}" class="headerlink"></a>${header.innerHTML}`
2017-08-27 14:38:42 +00:00
}
}
}
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 : {})
}
}
2017-08-27 14:38:42 +00:00
export {Even}