MediaWiki:Gadget-StickyToC.js

From JoJo's Bizarre Encyclopedia - JoJo Wiki
Revision as of 20:36, 19 May 2024 by Vish (talk | contribs)
Jump to navigation Jump to search

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
$(function(){
    if (!$('#toc').length) {
        return;
    }
    var i18n = {
        header: 'Contents',
        top: '(Top)'
    };

    function adjustPanelHeight() {
        var panelHeight = document.body.scrollHeight - 10;
        var viewportHeight = window.innerHeight - 10;
        $('#mw-panel').css('height', Math.min(panelHeight, viewportHeight));
    }

    new ResizeObserver(function(entries) {
        adjustPanelHeight();
    }).observe($('#content')[0]);

    $(window).resize(adjustPanelHeight); // Adjust on window resize as well

    var tocCollapsed = (localStorage.getItem("sidebar_vector_c_p-toc") === "y");
    $('<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)
        ).on("keypress", function(event) {
            if (event.which == 13) {
                $(this).trigger("click");
                event.stopImmediatePropagation()
            }
        }).on("click", function(event) {
            var $el = $(this).parent();
            event.stopPropagation();
            $el.toggleClass("collapsed");
            if($el.hasClass("collapsed")){
                localStorage.setItem("sidebar_vector_c_p-toc", "y");
                $el.find(".vector-menu-content").slideUp("fast");
                $el.css({'margin-right': '', 'margin-left': ''});
            } else {
                localStorage.setItem("sidebar_vector_c_p-toc", "n");
                $el.find(".vector-menu-content").slideDown("fast");
                var $toc = $el.find(".vector-menu-content-list")[0];
                if ($toc.clientWidth < $toc.scrollWidth) {
                    $el.css({'margin-right': '0', 'margin-left': '0'});
                }
                if (window.innerWidth >= 982 && $toc.clientWidth < $toc.scrollWidth) {
                    $el.css({'margin-right': '-0.5em', 'margin-left': '-0.5em'});
                }
            }
            adjustPanelHeight(); // Adjust height after toggling
        }),
        $('<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()
            )
        ).addClass($('#toc').parent().prop('class').split(/\s+/).filter(function(classname) {
            return classname.startsWith('toc-');
        }).join(' ')).css('display', tocCollapsed ? 'none' : '')
    ).addClass(tocCollapsed ? 'collapsed' : '').appendTo('#mw-panel');

    mw.loader.using(['ext.gadget.sectionObserver'], function(require) {
        var initSectionObserver = require('ext.gadget.sectionObserver');
        var allSections = document.querySelectorAll('#firstHeading, .mw-headline');
        var sectionObserver = initSectionObserver({topMargin: 20, onIntersection: onIntersection});
        sectionObserver.setElements(allSections);
        sectionObserver.calcIntersection();

        allSections = Array.from(allSections);
        var tocList = $('#p-toc .vector-menu-content-list')[0];
        var tocSections = $('#p-toc .vector-menu-content-list li');
        var baseOffset = $('#p-toc .tocsection-0 .toctext')[0].offsetTop;

        function onIntersection(section) {
            var index = allSections.indexOf(section);
            $('#p-toc .tocsection-current').removeClass('tocsection-current');
            var tocSection = tocSections.eq(index).addClass('tocsection-current');

            var tocItemOffsetTop = tocSection[0].offsetTop - tocList.offsetTop;
            var tocItemHeight = tocSection.outerHeight();

            if (tocItemOffsetTop < tocList.scrollTop) {
                tocList.scrollTop = tocItemOffsetTop - tocItemHeight;
            } else if (tocItemOffsetTop + tocItemHeight > tocList.scrollTop + tocList.clientHeight) {
                tocList.scrollTop = tocItemOffsetTop + tocItemHeight - tocList.clientHeight;
            }
        }
    });

    adjustPanelHeight(); // Initial adjustment
});