Jump to content

User:Polygnotus/Scripts/Subpages.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
// <nowiki>
// Add subpage navigation below page title
(function() {
    'use strict';
    
    // Only run on article view (not edit, preview, etc.)
    var action = mw.config.get('wgAction');
    if (action !== 'view') {
        return;
    }
    
    var pageName = mw.config.get('wgPageName');
    var pageTitle = mw.config.get('wgTitle');
    var namespace = mw.config.get('wgNamespaceNumber');
    
    // Guard against Special pages (ns -1) and Media pages (ns -2)
    if (namespace < 0) {
        return;
    }
    
    var searchPrefix = pageTitle + '/';
    var api = new mw.Api();
    
    api.get({
        action: 'query',
        list: 'allpages',
        apprefix: searchPrefix,
        apnamespace: namespace,
        aplimit: 500
    }).done(function(data) {
        if (!data.query || !data.query.allpages || data.query.allpages.length === 0) {
            return;
        }
        
        // Filter out Archive subpages
        var pages = data.query.allpages.filter(function(page) {
            var subpageName = page.title.substring(pageName.length + 1);
            return !subpageName.startsWith('Archive');
        });
        
        if (pages.length === 0) {
            return;
        }
        
        var maxVisible = 5;
        var hiddenCount = Math.max(0, pages.length - maxVisible);
        
        var container = $('<div>')
            .attr('id', 'subpage-navigation')
            .css({
                'margin': '0.5em 0',
                'padding': '0.5em',
                // Use Codex design tokens so the box respects dark mode.
                'background': 'var(--background-color-neutral, #f8f9fa)',
                'border': '1px solid var(--border-color-base, #a2a9b1)',
                'font-size': '90%'
            });
        
        container.append($('<strong>').text('Subpages: '));
        var listSpan = $('<span class="subpage-list"></span>');
        var hiddenSpan = $('<span class="subpage-hidden" style="display:none;"></span>');
        container.append(listSpan).append(hiddenSpan);
        
        pages.forEach(function(page, idx) {
            var fullTitle = page.title;
            var subpageName = fullTitle.substring(pageName.length + 1);
            
            var link = $('<a>')
                .attr('href', mw.util.getUrl(fullTitle))
                .text(subpageName);
            var targetSpan = (idx < maxVisible) ? listSpan : hiddenSpan;
            targetSpan.append(link);
            var groupEnd =
                (idx === maxVisible - 1) ||
                (idx === pages.length - 1);
            if (!groupEnd) {
                targetSpan.append(' · ');
            }
        });
        
        if (pages.length > maxVisible) {
            var toggleSeparator = $('<span class="toggle-separator"> · </span>');
            container.append(toggleSeparator);
            var toggle = $('<a>')
                .attr('href', 'javascript:void(0)')
                .text('Show ' + hiddenCount + ' more')
                .on('click', function() {
                    var expanded = hiddenSpan.is(':visible');
                    if (expanded) {
                        hiddenSpan.hide();
                        $(this).text('Show ' + hiddenCount + ' more');
                        var first = hiddenSpan.contents().first();
                        if (first.text && first.text().trim() === '·') first.remove();
                    } else {
                        hiddenSpan.show();
                        $(this).text('Show less');
                        var first = hiddenSpan.contents().first();
                        if (!(first.text && first.text().trim() === '·')) {
                            hiddenSpan.prepend(' · ');
                        }
                        var last = hiddenSpan.contents().last();
                        if (last.text && last.text().trim() === '·') last.remove();
                    }
                });
            container.append(toggle);
        }
        
        $('#firstHeading').after(container);

        // Fire hook so Popups/Navigation Popups process the links in the container
        mw.hook('wikipage.content').fire(container);
        
    }).fail(function(error) {
        console.error('API error:', error);
    });
})();
// </nowiki>