|
| 1 | +// Inspired by https://github.com/JorelAli/mdBook-pagetoc/tree/98ee241 (under WTFPL) |
| 2 | + |
| 3 | +letactiveHref=location.href; |
| 4 | +functionupdatePageToc(elem=undefined){ |
| 5 | +letselectedPageTocElem=elem; |
| 6 | +constpagetoc=document.getElementById("pagetoc"); |
| 7 | + |
| 8 | +functiongetRect(element){ |
| 9 | +returnelement.getBoundingClientRect(); |
| 10 | +} |
| 11 | + |
| 12 | +functionoverflowTop(container,element){ |
| 13 | +returngetRect(container).top-getRect(element).top; |
| 14 | +} |
| 15 | + |
| 16 | +functionoverflowBottom(container,element){ |
| 17 | +returngetRect(container).bottom-getRect(element).bottom; |
| 18 | +} |
| 19 | + |
| 20 | +// We've not selected a heading to highlight, and the URL needs updating |
| 21 | +// so we need to find a heading based on the URL |
| 22 | +if(selectedPageTocElem===undefined&&location.href!==activeHref){ |
| 23 | +activeHref=location.href; |
| 24 | +for(constpageTocElementofpagetoc.children){ |
| 25 | +if(pageTocElement.href===activeHref){ |
| 26 | +selectedPageTocElem=pageTocElement; |
| 27 | +} |
| 28 | +} |
| 29 | +} |
| 30 | + |
| 31 | +// We still don't have a selected heading, let's try and find the most |
| 32 | +// suitable heading based on the scroll position |
| 33 | +if(selectedPageTocElem===undefined){ |
| 34 | +constmargin=window.innerHeight/3; |
| 35 | + |
| 36 | +constheaders=document.getElementsByClassName("header"); |
| 37 | +for(leti=0;i<headers.length;i++){ |
| 38 | +constheader=headers[i]; |
| 39 | +if(selectedPageTocElem===undefined&&getRect(header).top>=0){ |
| 40 | +if(getRect(header).top<margin){ |
| 41 | +selectedPageTocElem=header; |
| 42 | +}else{ |
| 43 | +selectedPageTocElem=headers[Math.max(0,i-1)]; |
| 44 | +} |
| 45 | +} |
| 46 | +// a very long last section's heading is over the screen |
| 47 | +if(selectedPageTocElem===undefined&&i===headers.length-1){ |
| 48 | +selectedPageTocElem=header; |
| 49 | +} |
| 50 | +} |
| 51 | +} |
| 52 | + |
| 53 | +// Remove the active flag from all pagetoc elements |
| 54 | +for(constpageTocElementofpagetoc.children){ |
| 55 | +pageTocElement.classList.remove("active"); |
| 56 | +} |
| 57 | + |
| 58 | +// If we have a selected heading, set it to active and scroll to it |
| 59 | +if(selectedPageTocElem!==undefined){ |
| 60 | +for(constpageTocElementofpagetoc.children){ |
| 61 | +if(selectedPageTocElem.href.localeCompare(pageTocElement.href)===0){ |
| 62 | +pageTocElement.classList.add("active"); |
| 63 | +if(overflowTop(pagetoc,pageTocElement)>0){ |
| 64 | +pagetoc.scrollTop=pageTocElement.offsetTop; |
| 65 | +} |
| 66 | +if(overflowBottom(pagetoc,pageTocElement)<0){ |
| 67 | +pagetoc.scrollTop-=overflowBottom(pagetoc,pageTocElement); |
| 68 | +} |
| 69 | +} |
| 70 | +} |
| 71 | +} |
| 72 | +} |
| 73 | + |
| 74 | +if(document.getElementById("sidetoc")===null){ |
| 75 | +// Element doesn't exist yet, let's create it |
| 76 | +constmain=document.querySelector('main'); |
| 77 | +constwrapper=document.createElement('div'); |
| 78 | +wrapper.className="content-wrap"; |
| 79 | + |
| 80 | +// Move all children into the wrapper |
| 81 | +while(main.firstChild){ |
| 82 | +wrapper.appendChild(main.firstChild); |
| 83 | +} |
| 84 | + |
| 85 | +// Append the wrapper back to main |
| 86 | +main.appendChild(wrapper); |
| 87 | + |
| 88 | +// Create the empty sidetoc and pagetoc elements |
| 89 | +constsidetoc=document.createElement("div"); |
| 90 | +constpagetoc=document.createElement("div"); |
| 91 | +sidetoc.id="sidetoc"; |
| 92 | +pagetoc.id="pagetoc"; |
| 93 | + |
| 94 | +// And append them to the current DOM |
| 95 | +sidetoc.appendChild(pagetoc); |
| 96 | +main.appendChild(sidetoc); |
| 97 | +} |
| 98 | + |
| 99 | +if(document.getElementsByClassName("header").length<=1){ |
| 100 | +// There's one or less headings, we don't need a page table of contents |
| 101 | +document.getElementById("sidetoc").remove(); |
| 102 | +}else{ |
| 103 | +// Populate sidebar on load |
| 104 | +window.addEventListener("load",()=>{ |
| 105 | +for(constheaderofdocument.getElementsByClassName("header")){ |
| 106 | +constlink=document.createElement("a"); |
| 107 | +link.innerHTML=header.innerHTML; |
| 108 | +link.href=header.hash; |
| 109 | +link.classList.add("pagetoc-"+header.parentElement.tagName); |
| 110 | +document.getElementById("pagetoc").appendChild(link); |
| 111 | +link.onclick=()=>updatePageToc(link); |
| 112 | +} |
| 113 | +updatePageToc(); |
| 114 | +}); |
| 115 | + |
| 116 | +// Update page table of contents selected heading on scroll |
| 117 | +window.addEventListener("scroll",()=>updatePageToc()); |
| 118 | +} |
0 commit comments