142 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Vue
		
	
	
	
			
		
		
	
	
			142 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Vue
		
	
	
	
| <template>
 | |
|   <ul
 | |
|     class="sidebar-links"
 | |
|     v-if="items.length"
 | |
|   >
 | |
|     <li v-for="(item, i) in items" :key="i">
 | |
|       <SidebarGroup
 | |
|         v-if="item.type === 'group'"
 | |
|         :item="item"
 | |
|         :open="i === openGroupIndex"
 | |
|         :collapsable="item.collapsable || item.collapsible"
 | |
|         :depth="depth"
 | |
|         @toggle="toggleGroup(i)"
 | |
|       />
 | |
|       <SidebarLink
 | |
|         v-else
 | |
|         :sidebarDepth="sidebarDepth"
 | |
|         :item="item"
 | |
|       />
 | |
|     </li>
 | |
|   </ul>
 | |
| </template>
 | |
| 
 | |
| <script>
 | |
| import SidebarGroup from '@theme/components/SidebarGroup'
 | |
| import SidebarLink from '@theme/components/SidebarLink'
 | |
| import { isActive } from '@theme/helpers/utils'
 | |
| 
 | |
| export default {
 | |
|   name: 'SidebarLinks',
 | |
| 
 | |
|   components: { SidebarGroup, SidebarLink },
 | |
| 
 | |
|   props: [
 | |
|     'items',
 | |
|     'depth', // depth of current sidebar links
 | |
|     'sidebarDepth' // depth of headers to be extracted
 | |
|   ],
 | |
| 
 | |
|   data () {
 | |
|     return {
 | |
|       openGroupIndex: 0
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   created () {
 | |
|     this.refreshIndex()
 | |
|   },
 | |
| 
 | |
|   watch: {
 | |
|     '$route' () {
 | |
|       this.refreshIndex()
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   mounted () {
 | |
|     // this.activationLink()
 | |
|     // this.isInViewPortOfOne()
 | |
|   },
 | |
| 
 | |
|   updated: function () {
 | |
|     this.isInViewPortOfOne()
 | |
|   },
 | |
| 
 | |
|   methods: {
 | |
|     activationLink () {
 | |
|       const subtitleName = decodeURIComponent(this.$route.fullPath)
 | |
|       if (!subtitleName || subtitleName == '') return
 | |
|       // eslint-disable-next-line no-undef
 | |
|       const subtitles = [].slice.call(document.querySelectorAll(AHL_SIDEBAR_LINK_SELECTOR))
 | |
|       for (let i = 0; i < subtitles.length; i++) {
 | |
|         if (decodeURIComponent(subtitles[i].getAttribute('href')).indexOf(subtitleName) != -1) {
 | |
|           subtitles[i].click()
 | |
|           this.activationAnchor()
 | |
|           return
 | |
|         }
 | |
|       }
 | |
|     },
 | |
| 
 | |
|     activationAnchor () {
 | |
|       // eslint-disable-next-line no-undef
 | |
|       const anchors = [].slice.call(document.querySelectorAll(AHL_HEADER_ANCHOR_SELECTOR))
 | |
|         .filter(anchor => decodeURIComponent(this.$route.fullPath).indexOf(decodeURIComponent(anchor.hash)) != -1)
 | |
|       if (anchors == null || anchors.length < 1 || anchors[0].offsetTop == undefined) return
 | |
|       setTimeout(function () {
 | |
|         window.scrollTo(0, anchors[0].offsetTop + 160)
 | |
|       }, 100)
 | |
|     },
 | |
| 
 | |
|     isInViewPortOfOne () {
 | |
|       const sidebarScroll = document.getElementsByClassName('sidebar')[0]
 | |
|       let el = document.getElementsByClassName('active sidebar-link')[1]
 | |
|       if (el == null || el == undefined || el.offsetTop == undefined) {
 | |
|         el = document.getElementsByClassName('active sidebar-link')[0]
 | |
|       }
 | |
|       if (el == null || el == undefined || el.offsetTop == undefined) return
 | |
| 
 | |
|       const viewPortHeight = sidebarScroll.clientHeight || window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
 | |
|       const offsetTop = el.offsetTop
 | |
|       const offsetBottom = el.offsetTop + el.offsetHeight
 | |
|       const scrollTop = sidebarScroll.scrollTop
 | |
|       const bottomVisible = (offsetBottom <= viewPortHeight + scrollTop)
 | |
|       if (!bottomVisible) {
 | |
|         sidebarScroll.scrollTop = (offsetBottom + 5 - viewPortHeight)
 | |
|       }
 | |
|       const topVisible = (offsetTop >= scrollTop)
 | |
|       if (!topVisible) {
 | |
|         sidebarScroll.scrollTop = (offsetTop - 5)
 | |
|       }
 | |
|     },
 | |
| 
 | |
|     refreshIndex () {
 | |
|       const index = resolveOpenGroupIndex(
 | |
|         this.$route,
 | |
|         this.items
 | |
|       )
 | |
|       if (index > -1) {
 | |
|         this.openGroupIndex = index
 | |
|       }
 | |
|     },
 | |
| 
 | |
|     toggleGroup (index) {
 | |
|       this.openGroupIndex = index === this.openGroupIndex ? -1 : index
 | |
|     },
 | |
| 
 | |
|     isActive (page) {
 | |
|       return isActive(this.$route, page.regularPath)
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| function resolveOpenGroupIndex (route, items) {
 | |
|   for (let i = 0; i < items.length; i++) {
 | |
|     const item = items[i]
 | |
|     if (item.type === 'group' && item.children.some(c => c.type === 'page' && isActive(route, c.path))) {
 | |
|       return i
 | |
|     }
 | |
|   }
 | |
|   return -1
 | |
| }
 | |
| </script>
 |