dynamic-toc

Von $1

    Inhaltsverzeichnis
    keine Gliederung

    Version seit 15:43, 5 Nov 2026

    zu dieser Version.

    Zurück zu Versionshistorie.

    Zeige aktuelle Version

    (function () {
        function startTracker() {
            var panel = document.getElementById('trackerPageContent');
            var list  = document.getElementById('trackerList');
            if (!panel || !list) return;
    
            var headings = [];
            var currentIndex = -1;
            var timer;
    
            function collect() {
                var all = document.querySelectorAll('h2, h3, h4');
                headings = [];
                for (var i = 0; i < all.length; i++) {
                    headings.push({ el: all[i], text: all[i].textContent });
                }
            }
    
            function getTop(el) {
                return el.getBoundingClientRect().top + window.pageYOffset;
            }
    
            function findCurrent() {
                if (!headings.length) return 0;
                var scrollPos = window.pageYOffset;
                var triggerPoint = scrollPos + (window.innerHeight * 0.35);
                
                for (var i = headings.length - 1; i >= 0; i--) {
                    if (triggerPoint >= getTop(headings[i].el)) return i;
                }
                return 0;
            }
    
            function render() {
                list.innerHTML = '';
                if (!headings.length) return;
                
                var start = Math.max(0, currentIndex - 2);
                var end = Math.min(headings.length - 1, currentIndex + 2);
                
                for (var i = start; i <= end; i++) {
                    var item = document.createElement('div');
                    item.className = 'tracker-item';
                    if (i === currentIndex) item.className += ' current';
                    else if (Math.abs(i - currentIndex) === 1) item.className += ' near';
                    else item.className += ' far';
                    item.textContent = headings[i].text;
                    list.appendChild(item);
                }
            }
    
            function update() {
                var idx = findCurrent();
                if (idx !== currentIndex) {
                    currentIndex = idx;
                    render();
                }
            }
    
            window.addEventListener('scroll', function () {
                clearTimeout(timer);
                timer = setTimeout(update, 80);
            });
    
            collect();
            currentIndex = findCurrent();
            render();
        }
    
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', startTracker);
        } else {
            startTracker();
        }
    })();
    
    <div id="trackerPageContent">
     <div class="tracker-list" id="trackerList"></div>
    </div>
    #trackerPageContent {
        position: fixed;
        bottom: 110px;
        left: 20px;
        width: 250px;
        z-index: 2147483000;
        pointer-events: none;
        opacity: 1;
    }
    
    .tracker-list {
        display: flex;
        flex-direction: column;
        gap: 6px;
    }
    
    .tracker-item {
        line-height: 1.35;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        transition: all 0.25s;
    }
    
    .tracker-item.current {
        font-size: 22px;
        font-weight: 600;
        color: #06C;
    }
    
    .tracker-item.near {
        font-size: 16px;
        color: #777;
    }
    
    .tracker-item.far {
        font-size: 14px;
        color: #999;
    }
    

     
    Use the language selection below for English Utilise le sélecteur de langue ci-dessous pour français Per l'italiano, utilizzare la selezione della lingua qui sotto Schön sprichst du deutsch :-)