|
|
|
|
@ -96,12 +96,22 @@
|
|
|
|
|
.overline.pa-5.pb-0(:class='$vuetify.theme.dark ? `blue--text text--lighten-2` : `primary--text`') {{$t('common:page.toc')}}
|
|
|
|
|
v-list.pb-3(dense, nav, :class='$vuetify.theme.dark ? `darken-3-d3` : ``')
|
|
|
|
|
template(v-for='(tocItem, tocIdx) in tocDecoded')
|
|
|
|
|
v-list-item(@click='$vuetify.goTo(tocItem.anchor, scrollOpts)', :id='tocItem.anchor')
|
|
|
|
|
v-list-item(
|
|
|
|
|
:key='`toc-${tocIdx}`'
|
|
|
|
|
@click='$vuetify.goTo(tocItem.anchor, scrollOpts)'
|
|
|
|
|
:id='tocItem.anchor'
|
|
|
|
|
:class='{ titleactive: activeTocId === tocItem.anchor }'
|
|
|
|
|
)
|
|
|
|
|
v-icon(color='grey', small) {{ $vuetify.rtl ? `mdi-chevron-left` : `mdi-chevron-right` }}
|
|
|
|
|
v-list-item-title.px-3 {{tocItem.title}}
|
|
|
|
|
//- v-divider(v-if='tocIdx < toc.length - 1 || tocItem.children.length')
|
|
|
|
|
template(v-for='tocSubItem in tocItem.children')
|
|
|
|
|
v-list-item(@click='$vuetify.goTo(tocSubItem.anchor, scrollOpts)', :id='tocSubItem.anchor')
|
|
|
|
|
template(v-for='(tocSubItem, tocSubIdx) in tocItem.children')
|
|
|
|
|
v-list-item(
|
|
|
|
|
:key='`toc-${tocIdx}-${tocSubIdx}`'
|
|
|
|
|
@click='$vuetify.goTo(tocSubItem.anchor, scrollOpts)'
|
|
|
|
|
:id='tocSubItem.anchor'
|
|
|
|
|
:class='{ titleactive: activeTocId === tocSubItem.anchor }'
|
|
|
|
|
)
|
|
|
|
|
v-icon.px-3(color='grey lighten-1', small) {{ $vuetify.rtl ? `mdi-chevron-left` : `mdi-chevron-right` }}
|
|
|
|
|
v-list-item-title.px-3.caption.grey--text(:class='$vuetify.theme.dark ? `text--lighten-1` : `text--darken-1`') {{tocSubItem.title}}
|
|
|
|
|
//- v-divider(inset, v-if='tocIdx < toc.length - 1')
|
|
|
|
|
@ -520,7 +530,9 @@ export default {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
winWidth: 0
|
|
|
|
|
winWidth: 0,
|
|
|
|
|
activeTocId: null,
|
|
|
|
|
debouncedScrollHandler: null
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
computed: {
|
|
|
|
|
@ -600,7 +612,8 @@ export default {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.$store.set('page/mode', 'view')
|
|
|
|
|
window.addEventListener('scroll', this.handleScroll)
|
|
|
|
|
this.debouncedScrollHandler = _.debounce(this.handleScroll, 100)
|
|
|
|
|
window.addEventListener('scroll', this.debouncedScrollHandler, { passive: true })
|
|
|
|
|
},
|
|
|
|
|
mounted () {
|
|
|
|
|
if (this.$vuetify.theme.dark) {
|
|
|
|
|
@ -645,11 +658,19 @@ export default {
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
if (this.tocDecoded.length) {
|
|
|
|
|
this.handleScroll()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
window.boot.notify('page-ready')
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
destroyed () {
|
|
|
|
|
window.removeEventListener('scroll', this.handleScroll)
|
|
|
|
|
beforeDestroy () {
|
|
|
|
|
// Properly remove the debounced scroll handler
|
|
|
|
|
if (this.debouncedScrollHandler) {
|
|
|
|
|
window.removeEventListener('scroll', this.debouncedScrollHandler)
|
|
|
|
|
this.debouncedScrollHandler = null
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
|
goHome () {
|
|
|
|
|
@ -674,23 +695,24 @@ export default {
|
|
|
|
|
},
|
|
|
|
|
// Highlight the current section items in a sticky table of contents as you scroll down the page.
|
|
|
|
|
handleScroll () {
|
|
|
|
|
if (!this.$refs.container) return
|
|
|
|
|
|
|
|
|
|
const scrollPosition = window.scrollY
|
|
|
|
|
const sections = document.querySelectorAll('h1, h2')
|
|
|
|
|
const links = document.querySelectorAll('.v-list-item--link') // .v-list-item--link .v-list-item__title
|
|
|
|
|
const current = []
|
|
|
|
|
sections.forEach((el) => {
|
|
|
|
|
if (el.offsetTop <= scrollPosition + 5) {
|
|
|
|
|
current.push(el)
|
|
|
|
|
const offset = 100
|
|
|
|
|
const sections = this.$refs.container.querySelectorAll('h1, h2')
|
|
|
|
|
|
|
|
|
|
let activeSection = null
|
|
|
|
|
|
|
|
|
|
for (let i = sections.length - 1; i >= 0; i--) {
|
|
|
|
|
const section = sections[i]
|
|
|
|
|
if (section.offsetTop <= scrollPosition + offset) {
|
|
|
|
|
activeSection = section
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
const currentSection = current[current.length - 1]
|
|
|
|
|
const id = currentSection && currentSection.id
|
|
|
|
|
links.forEach((el) => {
|
|
|
|
|
el.classList.remove('titleactive')
|
|
|
|
|
if (el.getAttribute('id') === `#${id}`) {
|
|
|
|
|
el.classList.add('titleactive')
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const id = activeSection?.id
|
|
|
|
|
this.activeTocId = id ? `#${id}` : null
|
|
|
|
|
},
|
|
|
|
|
pageEdit () {
|
|
|
|
|
this.$root.$emit('pageEdit')
|
|
|
|
|
|