1/** 2 * Elementor TOC anchor fix. 3 * Injects ez-toc-section spans into headings that lack them (e.g. Elementor 4 * underlined headings) so TOC jump links work. Only runs when TOC exists. 5 * Pure JS, no jQuery. 6 */ 7(function () { 8 'use strict'; 9 10 function run() { 11 var tocContainers = document.querySelectorAll('#ez-toc-container, .ez-toc-split-section, .ez-toc-widget-sticky-container'); 12 if (!tocContainers.length) return; 13 14 var anchorIds = []; 15 for (var c = 0; c < tocContainers.length; c++) { 16 var nav = tocContainers[c].querySelector('nav'); 17 if (!nav) continue; 18 var tocLinks = nav.querySelectorAll('a.ez-toc-link'); 19 for (var i = 0; i < tocLinks.length; i++) { 20 var href = tocLinks[i].getAttribute('href') || tocLinks[i].getAttribute('data-href') || ''; 21 var hashIdx = href.indexOf('#'); 22 var id = hashIdx >= 0 ? href.substring(hashIdx + 1) : ''; 23 try { id = decodeURIComponent(id); } catch (e) { /* keep id as-is */ } 24 if (id && anchorIds.indexOf(id) === -1) { 25 anchorIds.push(id); 26 } 27 } 28 } 29 if (!anchorIds.length) return; 30 31 var allHeadings = document.querySelectorAll('h1, h2, h3, h4, h5, h6'); 32 var contentHeadings = []; 33 for (var j = 0; j < allHeadings.length; j++) { 34 var el = allHeadings[j]; 35 if (el.closest('#ez-toc-container, .ez-toc-split-section') || el.closest('.ez-toc-widget-sticky-container')) continue; 36 if (el.querySelector('span.ez-toc-section')) continue; 37 contentHeadings.push(el); 38 } 39 if (!contentHeadings.length) return; 40 41 function normalizeText(str) { 42 if (typeof str !== 'string') return ''; 43 return str.replace(/\s+/g, ' ').trim(); 44 } 45 46 if (contentHeadings.length === anchorIds.length) { 47 for (var k = 0; k < contentHeadings.length; k++) { 48 injectSpan(contentHeadings[k], anchorIds[k]); 49 } 50 return; 51 } 52 53 for (var m = 0; m < tocLinks.length; m++) { 54 var linkText = normalizeText(tocLinks[m].textContent); 55 var anchorId = anchorIds[m]; 56 for (var n = 0; n < contentHeadings.length; n++) { 57 var h = contentHeadings[n]; 58 if (h._eztocMatched) continue; 59 if (normalizeText(h.textContent) === linkText) { 60 injectSpan(h, anchorId); 61 h._eztocMatched = true; 62 break; 63 } 64 } 65 } 66 } 67 68 function injectSpan(heading, id) { 69 if (heading.querySelector('span.ez-toc-section')) return; 70 var span = document.createElement('span'); 71 span.className = 'ez-toc-section'; 72 span.id = id; 73 heading.insertBefore(span, heading.firstChild); 74 } 75 76 if (document.readyState === 'loading') { 77 document.addEventListener('DOMContentLoaded', run); 78 } else { 79 run(); 80 } 81})();
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.