dynamic-toc

Von $1

    Inhaltsverzeichnis
    keine Gliederung

    Version seit 15:43, 5 Nov 2026

    zu dieser Version.

    Zurück zu Versionshistorie.

    Zeige aktuelle Version

    :root {
        /* Layout */
        --tracker-width: 250px;
        --tracker-bottom: 110px;
        --tracker-left: 20px;
        /* Typography */
        --size-current: 22px;
        --size-near: 16px;
        --size-far: 14px;
        /* Colors */
        --color-current: #0066CC;
        --color-near: #777777;
        --color-far: #7777776b;
    }
    
    #trackerPageContent {
        position: fixed;
        bottom: var(--tracker-bottom);
        left: var(--tracker-left);
        width: var(--tracker-width);
        z-index: 2147483000;
        pointer-events: none;
        opacity: 1;
        transition: opacity 0.3s ease;
    }
    
    #trackerPageContent.hidden {
        opacity: 0;
    }
    
    .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 ease;
    }
    
    .tracker-item.current {
        font-size: var(--size-current);
        font-weight: 600;
        color: var(--color-current);
    }
    
    .tracker-item.near {
        font-size: var(--size-near);
        color: var(--color-near);
    }
    
    .tracker-item.far {
        font-size: var(--size-far);
        color: var(--color-far);
    }
    
    (function () {
        'use strict';
    
        var CONFIG = {
            selectors : 'h1, h2, h3, h4',
            threshold : 0.35,
            throttle  : 120,
            range     : 2,
            excludeTexts : ['Von $1', 'Edit']
        };
    
        var panel = document.getElementById('trackerPageContent');
        var list  = document.getElementById('trackerList');
        var content = document.querySelector('.content');
    
        if (!panel || !list) return;
    
        var headings = [];
        var currentIndex = -1;
        var timer;
    
        function checkCollision() {
            if (!content) {
                panel.classList.remove('hidden');
                return;
            }
    
            var panelRect = panel.getBoundingClientRect();
            var contentRect = content.getBoundingClientRect();
    
            var collision = !(
                panelRect.right < contentRect.left ||
                panelRect.left > contentRect.right ||
                panelRect.bottom < contentRect.top ||
                panelRect.top > contentRect.bottom
            );
    
            if (collision) {
                panel.classList.add('hidden');
            } else {
                panel.classList.remove('hidden');
            }
        }
    
        function collectHeadings() {
            headings = Array.from(document.querySelectorAll(CONFIG.selectors))
                .map(function (h) {
                    return {
                        el   : h,
                        text : h.textContent.trim()
                    };
                })
                .filter(function (h) {
                    return !CONFIG.excludeTexts.includes(h.text);
                });
        }
    
        function getTop(el) {
            return el.getBoundingClientRect().top + window.pageYOffset;
        }
    
        function findCurrent() {
            var pos = window.pageYOffset + window.innerHeight * CONFIG.threshold;
            for (var i = headings.length - 1; i >= 0; i--) {
                if (pos >= getTop(headings[i].el)) return i;
            }
            return 0;
        }
    
        function render() {
            list.innerHTML = '';
            if (!headings.length) return;
    
            var start = Math.max(0, currentIndex - CONFIG.range);
            var end   = Math.min(headings.length - 1, currentIndex + CONFIG.range);
    
            for (var i = start; i <= end; i++) {
                var item = document.createElement('div');
                item.className = 'tracker-item';
    
                if (i === currentIndex) {
                    item.classList.add('current');
                } else if (Math.abs(i - currentIndex) === 1) {
                    item.classList.add('near');
                } else {
                    item.classList.add('far');
                }
    
                item.textContent = headings[i].text;
                list.appendChild(item);
            }
        }
    
        function update() {
            if (!headings.length) return;
            var idx = findCurrent();
            if (idx === currentIndex) return;
            currentIndex = idx;
            render();
            checkCollision();
        }
    
        window.addEventListener('scroll', function () {
            clearTimeout(timer);
            timer = setTimeout(function() {
                update();
                checkCollision();
            }, CONFIG.throttle);
        }, { passive: true });
    
        window.addEventListener('resize', checkCollision);
    
        function init(retry) {
            collectHeadings();
            if (!headings.length && retry < 10) {
                setTimeout(function () { init(retry + 1); }, 300);
                return;
            }
            update();
            checkCollision();
        }
    
        init(0);
    })();
    

     
    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 :-)