mirror of
https://github.com/ryannhg/elm-spa.git
synced 2024-11-23 10:23:08 +03:00
102 lines
2.8 KiB
JavaScript
102 lines
2.8 KiB
JavaScript
|
const app = Elm.Main.init({ flags: window.__FLAGS__ })
|
||
|
|
||
|
// Handle smoothly scrolling to links
|
||
|
const scrollToHash = () => {
|
||
|
const element = window.location.hash && document.querySelector(window.location.hash)
|
||
|
if (element) {
|
||
|
element.scrollIntoView({ behavior: 'smooth' })
|
||
|
} else {
|
||
|
window.scroll({ behavior: 'smooth', top: 0 })
|
||
|
}
|
||
|
}
|
||
|
|
||
|
app.ports.onUrlChange.subscribe(_ => setTimeout(scrollToHash, 400))
|
||
|
setTimeout(scrollToHash, 200)
|
||
|
|
||
|
// Quick search shortcut (/)
|
||
|
window.addEventListener('keypress', (e) => {
|
||
|
if (e.key === '/') {
|
||
|
const el = document.getElementById('quick-search')
|
||
|
if (el && el !== document.activeElement) {
|
||
|
el.focus()
|
||
|
el.select()
|
||
|
e.preventDefault()
|
||
|
}
|
||
|
}
|
||
|
return false
|
||
|
})
|
||
|
|
||
|
// HighlightJS custom element
|
||
|
customElements.define('highlight-js', class HighlightJS extends HTMLElement {
|
||
|
constructor () { super() }
|
||
|
connectedCallback () {
|
||
|
const pre = document.createElement('pre')
|
||
|
const code = document.createElement('code')
|
||
|
|
||
|
pre.className = `language-elm`
|
||
|
code.innerText = this.body
|
||
|
|
||
|
pre.appendChild(code)
|
||
|
|
||
|
this.appendChild(pre)
|
||
|
window.hljs.highlightBlock(pre)
|
||
|
}
|
||
|
})
|
||
|
|
||
|
// Dropdown arrow key support
|
||
|
customElements.define('dropdown-arrow-keys', class DropdownArrowKeys extends HTMLElement {
|
||
|
constructor () {
|
||
|
super()
|
||
|
}
|
||
|
connectedCallback () {
|
||
|
const component = this
|
||
|
const arrows = { ArrowUp: -1, ArrowDown: 1 }
|
||
|
const interactiveChildren = () => component.querySelectorAll('input, a, button')
|
||
|
|
||
|
const onBlur = (e) => window.requestAnimationFrame(_ => {
|
||
|
const active = document.activeElement
|
||
|
const siblings = interactiveChildren()
|
||
|
let foundFocusedSibling = false
|
||
|
|
||
|
e.target.removeEventListener('blur', onBlur)
|
||
|
|
||
|
siblings.forEach(sibling => {
|
||
|
if (sibling === active) {
|
||
|
sibling.addEventListener('blur', onBlur)
|
||
|
foundFocusedSibling = true
|
||
|
}
|
||
|
})
|
||
|
if (foundFocusedSibling === false) {
|
||
|
component.dispatchEvent(new CustomEvent('clearDropdown'))
|
||
|
siblings.forEach(el => el.addEventListener('focus', _ => el.addEventListener('blur', onBlur)))
|
||
|
}
|
||
|
})
|
||
|
|
||
|
interactiveChildren().forEach(el => el.addEventListener('blur', onBlur))
|
||
|
|
||
|
component.addEventListener('keydown', (e) => {
|
||
|
const delta = arrows[e.key]
|
||
|
if (delta) {
|
||
|
e.preventDefault()
|
||
|
const interactive = interactiveChildren()
|
||
|
const count = interactive.length
|
||
|
const active = document.activeElement
|
||
|
if (count < 2) return
|
||
|
|
||
|
interactive.forEach((el, i) => {
|
||
|
if (active == el) {
|
||
|
const next = interactive[(i + delta + count) % count]
|
||
|
next.focus()
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
})
|
||
|
|
||
|
window.addEventListener('keyup', (e) => {
|
||
|
const el = document.getElementById('quick-search')
|
||
|
if (e.key === 'Escape' && el === document.activeElement) {
|
||
|
if (el) el.blur()
|
||
|
}
|
||
|
})
|