MediaWiki:Gadget-SidebarTOC.js: Difference between revisions

Jump to navigation Jump to search
mNo edit summary
mNo edit summary
Line 1: Line 1:
$(function(){
$(function(){
if (!$('#toc').length) {
    if (!$('#toc').length) {
return;
        return;
}
    }
var i18n = {
    var i18n = {
header: 'Contents',
        header: 'Contents',
top: '(Top)'
        top: '(Top)'
};
    };


// Remove the logic for collapsing and expanding the TOC
    // Remove the existing TOC
$('<nav id="p-toc" class="vector-menu mw-portlet mw-portlet-toc vector-menu-portal portal" aria-labelledby="p-toc-label" role="navigation">').append(
    $('#toc').remove();
    $('<h3 id="p-toc-label" class="vector-menu-heading" tabindex="0">').append(
        $('<span class="vector-menu-heading-label">').text(i18n.header)
    ),
    $('<div class="vector-menu-content">').append(
        $('<ul class="vector-menu-content-list">').append(
        $('<li class="toclevel-1 tocsection-0">').append($('<a href="#">').append(
        $('<span class="toctext">').text(i18n.top)
        )),
            $('#toc > ul').children().clone()
        )
    )
).appendTo('#mw-panel');


// Remove the original TOC on the page
    // Create a new TOC
$('#toc').remove();
    var $tocList = $('<ul class="vector-menu-content-list">').append(
        $('<li class="toclevel-1 tocsection-0">').append($('<a href="#">').append(
            $('<span class="toctext">').text(i18n.top)
        )),
        $('#content > h2, #content > h3, #content > h4, #content > h5, #content > h6').map(function() {
            var $this = $(this);
            return $('<li class="toclevel-' + this.tagName.slice(1) + '">').append(
                $('<a href="#' + this.id + '">').text($this.text())
            );
        })
    );


mw.loader.using( ['ext.gadget.sectionObserver'], function(require) {
    // Append the new TOC to the page
var initSectionObserver = require('ext.gadget.sectionObserver');
    $('<nav id="p-toc" class="vector-menu mw-portlet mw-portlet-toc vector-menu-portal portal" aria-labelledby="p-toc-label" role="navigation">').append(
var allSections = document.querySelectorAll('#firstHeading, .mw-headline');
        $('<h3 id="p-toc-label" class="vector-menu-heading" tabindex="0">').append(
var sectionObserver = initSectionObserver({topMargin: 20, onIntersection: onIntersection})
            $('<span class="vector-menu-heading-label">').text(i18n.header)
sectionObserver.setElements(allSections);
        ),
sectionObserver.calcIntersection();
        $('<div class="vector-menu-content">').append($tocList)
    ).appendTo('#mw-panel');
allSections = Array.from(allSections);
 
var tocList = $('#p-toc .vector-menu-content-list')[0];
    // Ensure that the "Contents" header still follows the user when scrolling
var tocSections = $('#p-toc .vector-menu-content-list li');
    var $pToc = $('#p-toc');
var baseOffset = $('#p-toc .tocsection-0 .toctext')[0].offsetTop;
    $(window).on('scroll', function() {
        var scrollTop = $(this).scrollTop();
function onIntersection(section) {
        if (scrollTop > 100) {
    var index = allSections.indexOf(section);
            $pToc.css('top', scrollTop - 100);
    $('#p-toc .tocsection-current').removeClass('tocsection-current');
        } else {
    var tocSection = tocSections.eq(index).addClass('tocsection-current');
            $pToc.css('top', 0);
    if ( tocSection.is(':hidden') && index > 0 ) return onIntersection(allSections[index - 1]);
        }
    var tocSectionPos = tocSection[0].offsetTop - baseOffset;
    });
    if ( tocSectionPos < tocList.scrollTop + (tocList.clientHeight * 0.15) ) {
 
        tocList.scrollTo({top: tocSectionPos - (tocList.clientHeight * 0.3)});
    // Prevent the TOC from collapsing immediately after opening it
    }
    $pToc.on('click', function(event) {
    else if ( tocSectionPos > tocList.scrollTop + (tocList.clientHeight * 0.85) ) {
        event.stopPropagation();
        tocList.scrollTo({top: tocSectionPos - (tocList.clientHeight * 0.7)});
        $pToc.toggleClass('collapsed');
    }
    });
}
});
} );
})

Revision as of 17:46, 22 February 2024

$(function(){
    if (!$('#toc').length) {
        return;
    }
    var i18n = {
        header: 'Contents',
        top: '(Top)'
    };

    // Remove the existing TOC
    $('#toc').remove();

    // Create a new TOC
    var $tocList = $('<ul class="vector-menu-content-list">').append(
        $('<li class="toclevel-1 tocsection-0">').append($('<a href="#">').append(
            $('<span class="toctext">').text(i18n.top)
        )),
        $('#content > h2, #content > h3, #content > h4, #content > h5, #content > h6').map(function() {
            var $this = $(this);
            return $('<li class="toclevel-' + this.tagName.slice(1) + '">').append(
                $('<a href="#' + this.id + '">').text($this.text())
            );
        })
    );

    // Append the new TOC to the page
    $('<nav id="p-toc" class="vector-menu mw-portlet mw-portlet-toc vector-menu-portal portal" aria-labelledby="p-toc-label" role="navigation">').append(
        $('<h3 id="p-toc-label" class="vector-menu-heading" tabindex="0">').append(
            $('<span class="vector-menu-heading-label">').text(i18n.header)
        ),
        $('<div class="vector-menu-content">').append($tocList)
    ).appendTo('#mw-panel');

    // Ensure that the "Contents" header still follows the user when scrolling
    var $pToc = $('#p-toc');
    $(window).on('scroll', function() {
        var scrollTop = $(this).scrollTop();
        if (scrollTop > 100) {
            $pToc.css('top', scrollTop - 100);
        } else {
            $pToc.css('top', 0);
        }
    });

    // Prevent the TOC from collapsing immediately after opening it
    $pToc.on('click', function(event) {
        event.stopPropagation();
        $pToc.toggleClass('collapsed');
    });
});