mirror of
https://github.com/ryan-haskell/elm-spa.git
synced 2024-11-22 20:01:19 +03:00
102 lines
3.0 KiB
JavaScript
102 lines
3.0 KiB
JavaScript
const app = Elm.Main.init({ flags: window.__FLAGS__ })
|
|
|
|
// Handle smoothly scrolling to links
|
|
const scrollToHash = () => {
|
|
const BREAKPOINT_XL = 1920
|
|
const NAVBAR_HEIGHT_PX = window.innerWidth > BREAKPOINT_XL ? 127 : 102
|
|
const element = window.location.hash && document.querySelector(window.location.hash)
|
|
if (element) {
|
|
// element.scrollIntoView({ behavior: 'smooth' })
|
|
window.scroll({ behavior: 'smooth', top: window.pageYOffset + element.getBoundingClientRect().top - NAVBAR_HEIGHT_PX })
|
|
} else {
|
|
window.scroll({ behavior: 'smooth', top: 0 })
|
|
}
|
|
}
|
|
|
|
app.ports.onUrlChange.subscribe(_ => setTimeout(scrollToHash, 400))
|
|
setTimeout(scrollToHash, 400)
|
|
|
|
// 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('prism-js', class HighlightJS extends HTMLElement {
|
|
constructor() { super() }
|
|
connectedCallback() {
|
|
const pre = document.createElement('pre')
|
|
|
|
pre.className = this.language ? `language-${this.language}` : `language-elm`
|
|
pre.textContent = this.body
|
|
|
|
this.appendChild(pre)
|
|
window.Prism.highlightElement(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()
|
|
}
|
|
}) |