MediaWiki:Common.js: Difference between revisions

No edit summary
No edit summary
Line 343: Line 343:
         toc.querySelectorAll('.gr-toc-in-path').forEach(function (el) { el.classList.remove('gr-toc-in-path'); });
         toc.querySelectorAll('.gr-toc-in-path').forEach(function (el) { el.classList.remove('gr-toc-in-path'); });
     }
     }
     function setActiveToc(id) {
    function ownLink(li) {
        return li.querySelector(':scope > .vector-toc-link') || li.querySelector('.vector-toc-link');
    }
    function isShown(el) {
        return !!(el && (el.offsetParent || (el.getClientRects && el.getClientRects().length)));
    }
    // Open a collapsed section so a given entry can be seen. Vector marks a
    // top-level item open with vector-toc-list-item-expanded plus
    // aria-expanded on its toggle, so this matches what its own button does.
    function expandTocFor(li) {
        var top = li.closest ? li.closest('.vector-toc-level-1') : null;
        if (!top) return;
        if (!top.classList.contains('vector-toc-list-item-expanded')) {
            top.classList.add('vector-toc-list-item-expanded');
            var tg = top.querySelector('.vector-toc-toggle');
            if (tg) tg.setAttribute('aria-expanded', 'true');
        }
        var anc = li.parentNode;
        while (anc && anc.classList) {
            anc.classList.remove('vector-toc-list-item-collapsed');
            if (anc.classList.contains('vector-toc')) break;
            anc = anc.parentNode;
        }
    }
 
    // expand=true when the reader picked the entry (TOC click, search
    // result, #hash): open its section so the exact entry is shown.
    // expand=false while scrolling: never open or close anything — if the
    // entry is hidden inside a collapsed section, the section itself is
    // highlighted instead, so the reader still sees where they are.
     function setActiveToc(id, expand) {
         var toc = document.querySelector('.vector-toc');
         var toc = document.querySelector('.vector-toc');
         if (!toc) return;
         if (!toc) return;
         if (_tocActiveId === id) return;
        var shownNow = toc.querySelector('.gr-toc-current');
         if (_tocActiveId === id && !expand && shownNow && isShown(shownNow)) return;
         _tocActiveId = id;
         _tocActiveId = id;
         clearActiveToc();
         clearActiveToc();
Line 352: Line 383:
         var li = getTocLi(id);
         var li = getTocLi(id);
         if (!li) return;
         if (!li) return;
         // The entry itself — the link only, so sub-entries stay as they are.
         if (expand) expandTocFor(li);
        var lnk = li.querySelector(':scope > .vector-toc-link') || li.querySelector('.vector-toc-link');
 
        var lnk = ownLink(li);
        var hostLi = li;
        if (lnk && !isShown(lnk)) {          // hidden in a collapsed section
            var p = li.parentNode;
            while (p && p !== toc) {
                if (p.classList && p.classList.contains('vector-toc-list-item')) {
                    var pl = ownLink(p);
                    if (pl && isShown(pl)) { lnk = pl; hostLi = p; break; }
                }
                p = p.parentNode;
            }
        }
         if (lnk) lnk.classList.add('gr-toc-current');
         if (lnk) lnk.classList.add('gr-toc-current');
         // Its parent sections get the quieter "you are in here" treatment,
         // Sections above it get the quieter "you are in here" treatment.
        // and any collapsed ancestor is opened so the entry is visible.
         var anc = hostLi.parentNode;
         var anc = li.parentNode;
         while (anc && anc !== toc) {
         while (anc && anc !== toc) {
             if (anc.classList) {
             if (anc.classList && anc.classList.contains('vector-toc-list-item')) anc.classList.add('gr-toc-in-path');
                anc.classList.remove('vector-toc-list-item-collapsed');
                if (anc.classList.contains('vector-toc-list-item')) anc.classList.add('gr-toc-in-path');
            }
            if (anc.tagName === 'UL' || anc.tagName === 'LI') anc.style.removeProperty('display');
             anc = anc.parentNode;
             anc = anc.parentNode;
         }
         }
         keepTocEntryVisible(lnk || li);
         keepTocEntryVisible(lnk || hostLi);
     }
     }


Line 507: Line 545:
         if (!id) return;
         if (!id) return;
         _pin = { id: id, y: scrollY(), until: Date.now() + 900 };
         _pin = { id: id, y: scrollY(), until: Date.now() + 900 };
         setActiveToc(id);
         setActiveToc(id, true);         // open its section if collapsed
         scheduleRecheck(950);
         scheduleRecheck(950);
     }
     }
Line 521: Line 559:
             if (Date.now() < _pin.until) {              // still settling after the jump
             if (Date.now() < _pin.until) {              // still settling after the jump
                 _pin.y = y;
                 _pin.y = y;
                 setActiveToc(_pin.id);
                 setActiveToc(_pin.id, true);
                 scheduleRecheck(_pin.until - Date.now() + 30);
                 scheduleRecheck(_pin.until - Date.now() + 30);
                 return;
                 return;