1/************************* 2 * 3 * HTML Contents 4 * https://github.com/psalmody/html-contents 5 * MIT License 6 * 7 */ 8 9const htmlContents = function(toc, options) { 10 options = Object.assign({}, { 11 top: 2, // biggest header to include in outline - default H2 12 bottom: 3, // smallest header to include in outline - default H3 13 addIds: true, // addIds - yes by default to H* that don't have them 14 addLinks: true, // addLinks - 15 listType: 'u', // 'u' or 'o' - (u)nordered or (o)rdered list type 16 filter: false // CSS style selector to exclude from outline 17 }, options) 18 19 //shared functions 20 const getLevel = function(str) { 21 return parseInt(str.replace(/[a-z,A-Z]/g,'')) 22 } 23 //create listitem html 24 const listItem = function(el, level) { 25 let li = '<li data-level="' + level + '">' 26 if (options.addLinks) li += '<a href="#' + el.id + '">' 27 li += el.textContent 28 if (options.addLinks) li += '</a>' 29 li += '</li>' 30 return li 31 } 32 33 //toc of contents - remove # if necessary 34 let TOC = document.getElementById(toc.replace(/\#/g, '')) 35 36 //get levels in between top and bottom - make query string 37 let lvls = [] 38 for (let i = options.top; i <= options.bottom; i++) { 39 lvls.push('h' + i) 40 } 41 42 //select all levels 43 let entryContent=document.querySelector('.article-content'); 44 let hs = entryContent.querySelectorAll(lvls.join(',')) 45 let headers 46 47 //if filter? 48 if (options.filter instanceof Function) { 49 let arr = Array.prototype.slice.call(hs) 50 headers = arr.filter(options.filter) 51 } else if (options.filter instanceof String) { 52 let arr = Array.prototype.slice.call(hs) 53 headers = arr.filter(function(el) { 54 return !el.matches(options.filter) 55 }) 56 } else { 57 headers = Array.prototype.slice.call(hs) 58 } 59 60 //add ids if necessary 61 if (options.addIds) { 62 //keep track of ids 63 let ids = [] 64 headers.forEach(function(el) { 65 66 if(!el.hasAttribute("data-skipTOC")){ 67 68 //if it has an id already, just add that to the array 69 if (el.id) return ids.push(el.id) 70 //id will be the textcontent without non-letter characters in lower case 71 let id = el.textContent.replace(/[^a-zA-Z]/g, '').toLowerCase() + 'Header' 72 while(ids.indexOf(id) !== -1) { 73 //add zs to the end until we have a unique id 74 id = id + 'z' 75 } 76 //ready to be tracked 77 ids.push(id) 78 //okay we can set now 79 el.id = id 80 } 81 }) 82 } 83 84 //make list 85 //current level 86 let prevLevel = options.top 87 let html = '' 88 89 headers.forEach(function(h) { 90 if(h.textContent!="Related services" && h.textContent!="Related News" && h.textContent!="Share this:"){ 91 let currentLevel = getLevel(h.tagName) 92 let li = listItem(h, currentLevel) 93 //if we're still at level 94 if (currentLevel === prevLevel) { 95 html += li 96 } else if (currentLevel < prevLevel) { 97 //if we've gone back up 98 html += ('</' + options.listType + 'l>').repeat(prevLevel - currentLevel) + li 99 } else { 100 //we've gone down 101 html += '<' + options.listType + 'l>' + li 102 } 103 prevLevel = currentLevel 104 } 105 }) 106 107 if(headers.length>0){ 108 html=`<div class="toc-c-btn"> <button id="toc_closeButton" onclick='document.getElementById("toc").classList.remove("open");'><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M23 20.168l-8.185-8.187 8.185-8.174-2.832-2.807-8.182 8.179-8.176-8.179-2.81 2.81 8.186 8.196-8.186 8.184 2.81 2.81 8.203-8.192 8.18 8.192z"/></svg></button></div> 109 110 <h3 class="title-border">In this article</h3><ul>${html}</div>`; 111 } 112 113 TOC.insertAdjacentHTML('beforeend', html) 114 115 //let toc=document.querySelector('#toc') 116 let anchorlinks = document.querySelectorAll('a[href^="#"]') 117 //console.log(anchorlinks); 118 119 for (let item of anchorlinks) { // relitere 120 item.addEventListener('click', (e)=> { 121 let hashval = item.getAttribute('href') 122 let target = document.querySelector(hashval) 123 target.scrollIntoView(true)
124 target.focus() 125 126 // now account for fixed header 127 var scrolledY = document.documentElement.scrollTop; 128 console.log(scrolledY); 129 if(scrolledY){ 130 window.scroll(0, scrolledY - 200); 131 console.log(200); 132 } 133 134 history.pushState(null, null, hashval) 135 e.preventDefault() 136 }) 137 } 138 139}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.