Skip to content

Commit

Permalink
fix: detect active and exact active link (#64)
Browse files Browse the repository at this point in the history
  • Loading branch information
farnabaz authored Feb 15, 2021
1 parent c4980c2 commit 44ba5f8
Showing 1 changed file with 52 additions and 20 deletions.
72 changes: 52 additions & 20 deletions theme/components/templates/AppToc.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
v-for="link of toc"
:key="link.id"
class="hover:text-gray-900 dark:hover:text-gray-100"
:class="{ 'text-primary-500 hover:text-primary-500 dark:text-primary-400 dark:hover:text-primary-400': activeLink === link.id }"
:class="{ 'text-primary-500 hover:text-primary-500 dark:text-primary-400 dark:hover:text-primary-400': exactActiveLink === link.id || activeLink === link.id }"
>
<a
:href="`#${link.id}`"
Expand Down Expand Up @@ -40,36 +40,68 @@ export default {
},
data () {
return {
activeLink: ''
activeLink: '',
exactActiveLink: '',
sections: []
}
},
computed: {
...mapGetters([
'settings'
])
},
beforeMount () {
history.scrollRestoration = 'manual'
},
mounted () {
if (window.IntersectionObserver) {
this.observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
const id = entry.target.getAttribute('id')
if (entry.isIntersecting) {
this.activeLink = id
}
window.addEventListener('scroll', this.onScroll)
document
.querySelectorAll('.nuxt-content h2[id], .nuxt-content h3[id]')
.forEach((section) => {
this.sections.push({
level: section.tagName.replace(/h/i, ''),
id: section.getAttribute('id'),
top: section.offsetTop
})
}, { threshold: 1 })
// Track all titles generated by nuxt-content and displayed in the TOC
document
.querySelectorAll('.nuxt-content h2[id], .nuxt-content h3[id]')
.forEach((section) => {
this.observer.observe(section)
})
}
})
this.onScroll()
},
beforeDestroy () {
if (this.observer) {
this.observer.disconnect()
delete this.observer
window.removeEventListener('scroll', this.onScroll, true)
},
methods: {
onScroll () {
const yOffset = window.pageYOffset
const windowHeight = window.innerHeight
if (yOffset === 0) {
this.setActive(0)
} else if (yOffset + windowHeight >= document.body.scrollHeight) {
return this.setActive(this.sections.length - 1)
} else {
const targetPoint = yOffset + windowHeight / 2
let index = 0
for (let i = 0; i < this.sections.length; i++) {
if (this.sections[i].top <= targetPoint) {
index = i
}
}
this.setActive(index)
}
},
setActive (index) {
this.exactActiveLink = this.sections[index].id
this.activeLink = this.sections[index].id
if (this.sections[index].level === '3') {
let parentIndex = -1
for (let i = 0; i < index; i++) {
if (this.sections[i].level === '2') {
parentIndex = i
}
}
if (parentIndex >= 0) {
this.activeLink = this.sections[parentIndex].id
}
}
}
}
}
Expand Down

1 comment on commit 44ba5f8

@vercel
Copy link

@vercel vercel bot commented on 44ba5f8 Feb 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.