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