/**
* @preserve W Zhang * For weixuanz.github.io */
/* Dark Toggle
* Modified, from https://gist.github.com/kslstn/20f654fd27eb29619040c74fa6526919 */
;(function initializeTheme() {
syncBetweenTabs() listenToOS() listenToCheckbox() hideCheckbox() updatePref(storedPref() || OSPref(), false)
})()
// Helper Functions
function currentPref() {
return document.querySelector('#dark-toggle-box').checked ? 'dark' : 'light'
}
function OSPref() {
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
}
function storedPref() {
const pref = localStorage.getItem('preference-theme') if (pref === 'light') return 'light' else if (pref === 'dark') return 'dark' else return undefined
}
function updateCheckbox(pref) {
document.querySelector('#dark-toggle-box').checked = pref === 'dark'
}
function savePref(key, value) {
localStorage.setItem(key, value)
}
function updatePref(
newPref, withTransition = true, save = true, override = false
) {
const root = document.documentElement const els = elsRequireTransit([ 'body', '#navbar', '#main-header', 'code', '#blog-list-mini', '.card', '#toc' ]) if ((currentPref() === 'dark' || override) && newPref === 'light') { if (withTransition) toggleTransition(els) root.classList.remove('theme-dark') navbar.style.background = '#fff' updateCheckbox('light') if (withTransition) setTimeout(() => { toggleTransition(els, false) }, 1000) } else if ((currentPref() === 'light' || override) && newPref === 'dark') { if (withTransition) toggleTransition(els) root.classList.add('theme-dark') navbar.style.background = '#121212' updateCheckbox('dark') if (withTransition) setTimeout(() => { toggleTransition(els, false) }, 1000) } if (save) savePref('preference-theme', newPref)
}
function toggleTransition(els, addTransit = true) {
els.map((el) => { addTransit ? el.forEach((e) => e.classList.add('theme-transit')) : el.forEach((e) => e.classList.remove('theme-transit')) })
}
function elsRequireTransit(els) {
return els.map((el) => document.querySelectorAll(el))
}
// Event Listeners
function hideCheckbox() {
const toggleLabel = document.querySelector('#dark-toggle-label') window.addEventListener('scroll', function () { if (this.scrollY >= nav_init) { toggleLabel.classList.add('transparent') if (currentPref() === 'dark') { navbar.style.background = '#22222280' } } else { toggleLabel.classList.remove('transparent') if (currentPref() === 'dark') { navbar.style.background = '#121212' } } })
}
function syncBetweenTabs() {
window.addEventListener('storage', (e) => { if (e.key === 'preference-theme') { if (e.newValue === 'light') { updatePref('light', true, false) } else if (e.newValue === 'dark') { updatePref('dark', true, false) } } })
}
function listenToOS() {
const mediaQueryList = window.matchMedia('(prefers-color-scheme: dark)') mediaQueryList.addListener((m) => { if (m.matches !== true) { updatePref('light') } else { updatePref('dark') } })
}
function listenToCheckbox() {
const checkbox = document.querySelector('#dark-toggle-box') checkbox.addEventListener('change', function () { if (this.checked) { updatePref('dark', true, true, true) } else { updatePref('light', true, true, true) } })
}
/* Code Copy
* Modified, from https://stackoverflow.com/a/48078807/10365842 */
const allCodeBlocksElements = document.querySelectorAll('div.highlighter-rouge') allCodeBlocksElements.forEach(function (el, i) {
const currentId = `codeblock${i + 1}` el.querySelector('code').setAttribute('id', currentId) const clipButton = document.createElement('button') clipButton.innerHTML = '<svg class="icon"><use xlink:href="#icon-clone-solid"></use></svg>' clipButton.className = 'code-copy-btn' clipButton.setAttribute('data-clipboard-target', `#${currentId}`) clipButton.setAttribute('aria-label', `Copy ${currentId}`) el.querySelector('code').after(clipButton)
}) if (allCodeBlocksElements.length > 0) {
new ClipboardJS('.code-copy-btn')
}
/* Share Button */ function share() {
if (navigator.share !== undefined) { navigator .share({ title: document.querySelector('.header').textContent, text: 'Check this out!', url: window.location.href }) .then(() => console.log('Shared!')) .catch((e) => console.error(e)) } else { const shareButton = document.querySelector('#share-btn') shareButton.setAttribute('data-clipboard-text', location.href) new ClipboardJS('#share-btn') shareButton.classList.add('shared') setTimeout(() => { shareButton.classList.remove('shared') }, 5000) }
}
const shareButton = document.querySelector('#share-btn') if (shareButton) shareButton.addEventListener('click', share)
/* Dynamic TOC */ const toc = document.querySelector('#toc') if (toc) {
const tocItems = Array.from(toc.querySelectorAll('li')) const tocMapping = tocItems.map(function (item) { const anchor = item.querySelector('a') const targetID = anchor.getAttribute('href').slice(1) const target = document.getElementById(targetID) return { listItem: item, anchor: anchor, targetID: targetID, target: target, targetOffset: target.offsetTop } }) function getCurrentSection(tocMapping) { return tocMapping.reduce((acc, val) => window.pageYOffset + 70 > val.targetOffset ? val : acc ) } function sectionUpdaterInit(initialSection = {}) { let currentSection = initialSection function wrapped(newSection) { if (newSection.targetID !== currentSection.targetID) { if (currentSection.targetID) { currentSection.anchor.classList.remove('active') } newSection.anchor.classList.add('active') currentSection = newSection } } return wrapped } const sectionUpdater = sectionUpdaterInit() window.addEventListener('scroll', () => sectionUpdater(getCurrentSection(tocMapping)) )
}