MediaWiki:Common.js:修订间差异

来自神国反恶俗
跳到导航跳到搜索
无编辑摘要
add private message topbar link
 
(未显示同一用户的13个中间版本)
第1行: 第1行:
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */
( function () {
( function () {


    /* ==========================================================
      一、把页面里的目录(TOC)搬到左侧栏
      —— 你原来就有的功能,保持不动
      ========================================================== */
     function moveTOC() {
     function moveTOC() {
         var toc = document.getElementById( 'toc' )
         var toc = document.getElementById( "toc" );
            || document.querySelector( '.mw-table-of-contents-container' )
        if ( !toc ) { toc = document.querySelector( ".mw-table-of-contents-container" ); }
            || document.querySelector( '.mw-table-of-contents' );
         var sidebar = document.getElementById( "column-one" );
         var sidebar = document.getElementById( 'column-one' )
        if ( !toc || !sidebar ) { return; }
            || document.getElementById( 'mw-panel' );
        var nav = document.getElementById( "p-navigation" );
 
         var container = ( nav && nav.parentNode ) ? nav.parentNode : sidebar;
         if ( !toc || !sidebar || document.getElementById( 'p-toc' ) ) {
        var existing = document.getElementById( "p-toc" );
        if ( existing ) {
            if ( nav ) {
                container.insertBefore( existing, nav.nextSibling );
            } else {
                container.appendChild( existing );
            }
             return;
             return;
         }
         }
 
         var box = document.createElement( "div" );
         var box = document.createElement( 'div' );
         box.className = "portlet";
         box.className = 'portlet';
         box.id = "p-toc";
         box.id = 'p-toc';
         var title = document.createElement( "h3" );
 
         title.textContent = "\u76ee\u5f55";
         var title = document.createElement( 'h3' );
         var inner = document.createElement( "div" );
         title.textContent = '目录';
         inner.className = "pBody";
 
         var inner = document.createElement( 'div' );
         inner.className = 'pBody';
         inner.appendChild( toc );
         inner.appendChild( toc );
         box.appendChild( title );
         box.appendChild( title );
         box.appendChild( inner );
         box.appendChild( inner );
         sidebar.appendChild( box );
         if ( nav ) {
            container.insertBefore( box, nav.nextSibling );
        } else {
            var search = document.getElementById( "p-search" );
            if ( search && search.parentNode ) {
                search.parentNode.insertBefore( box, search );
            } else {
                container.appendChild( box );
            }
        }
     }
     }


     /* ==========================================================
     function pickLinks( portlet ) {
      二、吸顶:左侧栏 / 顶部编辑标签栏 / 右上账号栏
        var out = [];
      —— 按页面实际有没有这些栏目动态处理,不会多留空白
         if ( !portlet ) { return out; }
      ========================================================== */
         var links = portlet.querySelectorAll( "ul a" );
    var STICKY_CSS = [
         for ( var i = 0; i < links.length; i++ ) { out.push( links[ i ] ); }
        '#sg-personal-bar,#sg-cactions-bar{',
         return out;
        '  position:fixed;top:0;z-index:401;',
     }
         '  background:#fff;box-shadow:0 1px 4px rgba(0,0,0,.18);',
        '  padding:4px 10px;font-size:88%;line-height:1.4;',
        '  white-space:nowrap;overflow-x:auto;overflow-y:hidden;',
        '}',
        '#sg-personal-bar{right:0;border-radius:0 0 0 8px;}',
        '#sg-cactions-bar{border-radius:0 0 8px 0;}',
        '#sg-personal-bar a,#sg-cactions-bar a{',
        '  color:#36c;text-decoration:none;padding:2px 5px;',
        '}',
        '#sg-personal-bar a:hover,#sg-cactions-bar a:hover{',
        '  text-decoration:underline;',
        '}',
         '#sg-cactions-bar a{border-right:1px solid #e3e5e8;}',
        '#sg-cactions-bar a:last-child{border-right:none;}',
        '#column-one{',
        '  position:sticky;top:var(--sg-top-offset,0px);',
         '  max-height:calc(100vh - var(--sg-top-offset,0px));',
        '  overflow-y:auto;',
        '}',
        'body.sg-sticky-on #content{',
        '  padding-top:var(--sg-top-offset,0px) !important;',
         '}'
     ].join( '\n' );


     function injectCSS() {
     function syncBarHeight( bar ) {
         if ( document.getElementById( 'sg-sticky-style' ) ) { return; }
         if ( !bar ) { return; }
         var s = document.createElement( 'style' );
         document.body.style.paddingTop = bar.offsetHeight + "px";
        s.id = 'sg-sticky-style';
        s.type = 'text/css';
        s.textContent = STICKY_CSS;
        document.head.appendChild( s );
     }
     }


    /* 把某个栏目里的链接复制到一条固定栏上;栏目为空就不做 */
     function enableHorizontalScroll( bar ) {
     function buildBar( portlet, barId ) {
         if ( !bar ) { return; }
         if ( !portlet ) { return null; }
        bar.addEventListener( "wheel", function ( e ) {
            if ( Math.abs( e.deltaY ) > Math.abs( e.deltaX ) ) {
                bar.scrollLeft += e.deltaY;
                e.preventDefault();
            }
        }, { passive: false } );


         var links = portlet.querySelectorAll( 'ul a' );
         var down = false, startX = 0, startLeft = 0;
         if ( !links.length ) { return null; }
        bar.addEventListener( "mousedown", function ( e ) {
            if ( e.target && e.target.tagName === "A" ) { return; }
            down = true;
            startX = e.pageX;
            startLeft = bar.scrollLeft;
            bar.style.cursor = "grabbing";
         } );
        window.addEventListener( "mousemove", function ( e ) {
            if ( !down ) { return; }
            bar.scrollLeft = startLeft - ( e.pageX - startX );
        } );
        window.addEventListener( "mouseup", function () {
            down = false;
            bar.style.cursor = "";
        } );
    }


         var old = document.getElementById( barId );
    function makeSticky() {
         if ( old && old.parentNode ) { old.parentNode.removeChild( old ); }
         var old = document.getElementById( "sg-topbar" );
         if ( old ) { old.parentNode.removeChild( old ); }


         var bar = document.createElement( 'div' );
         var leftLinks = pickLinks( document.getElementById( "p-cactions" ) );
         bar.id = barId;
         var rightLinks = pickLinks( document.getElementById( "p-personal" ) );


         Array.prototype.forEach.call( links, function ( a ) {
         var notifHref = null;
            var copy = document.createElement( 'a' );
        var notifCount = 0;
            copy.href = a.href;
        var notifIndex = -1;
            copy.textContent = a.textContent;
        var plainRightLinks = [];
             bar.appendChild( copy );
        for ( var n = 0; n < rightLinks.length; n++ ) {
         } );
            var item = rightLinks[ n ];
            var parent = item.parentNode;
            var itemId = parent ? parent.id : "";
            if ( itemId === "pt-notifications-alert" || itemId === "pt-notifications-notice" ) {
                if ( notifIndex < 0 ) { notifIndex = plainRightLinks.length; }
                if ( !notifHref ) { notifHref = item.href; }
                var raw = item.getAttribute( "data-counter-num" );
                var count = parseInt( raw, 10 );
                if ( isNaN( count ) ) {
                    var match = ( item.textContent || "" ).match( /[((](\d+)[))]/ );
                    count = match ? parseInt( match[ 1 ], 10 ) : 0;
                }
                notifCount += count;
                continue;
             }
            plainRightLinks.push( item );
         }
        rightLinks = plainRightLinks;


         document.body.appendChild( bar );
         var privateIndex = -1;
        return bar;
        for ( var p = 0; p < rightLinks.length; p++ ) {
    }
            var pParent = rightLinks[ p ].parentNode;
            var pId = pParent ? pParent.id : "";
            var pText = ( rightLinks[ p ].textContent || "" ).replace( /\s/g, "" );
            if ( pId === "pt-mytalk" || pText === "\u8ba8\u8bba" ) {
                privateIndex = p + 1;
                break;
            }
        }


    function makeSticky() {
        if ( leftLinks.length === 0 && rightLinks.length === 0 && !notifHref ) { return; }
        injectCSS();


         var personal = document.getElementById( 'p-personal' ); /* 账号那排 */
         var bar = document.createElement( "div" );
         var cactions = document.getElementById( 'p-cactions' ); /* 编辑标签那排 */
         bar.id = "sg-topbar";
        bar.className = "sg-sticky-bar";


         /* 账号栏:永远吸顶、靠右 */
         var left = document.createElement( "div" );
         if ( buildBar( personal, 'sg-personal-bar' ) && personal ) {
         left.className = "sg-bar-left";
             personal.style.visibility = 'hidden';
        for ( var i = 0; i < leftLinks.length; i++ ) {
            var a = document.createElement( "a" );
             a.href = leftLinks[ i ].href;
            a.textContent = leftLinks[ i ].textContent;
            left.appendChild( a );
         }
         }


         /* 编辑标签栏:吸顶,排在账号栏下面 */
         var right = document.createElement( "div" );
         var ca = buildBar( cactions, 'sg-cactions-bar' );
         right.className = "sg-bar-right";
        if ( ca && cactions ) { cactions.style.visibility = 'hidden'; }
        for ( var j = 0; j <= rightLinks.length; j++ ) {
            if ( j === privateIndex ) {
                var privateLink = document.createElement( "a" );
                privateLink.href = "/index.php?title=Special:UserBoard";
                privateLink.textContent = "\u79c1\u4fe1";
                privateLink.title = "\u67e5\u770b\u79c1\u4fe1";
                right.appendChild( privateLink );
            }
            if ( j === notifIndex && notifHref ) {
                var notice = document.createElement( "a" );
                notice.href = notifHref;
                notice.textContent = "\u901a\u77e5\uff08" + notifCount + "\uff09";
                notice.title = "\u91cd\u8981\u901a\u77e5\u4e0e\u5e38\u89c4\u901a\u77e5";
                right.appendChild( notice );
            }
            if ( j === rightLinks.length ) { break; }
            var b = document.createElement( "a" );
            b.href = rightLinks[ j ].href;
            b.textContent = rightLinks[ j ].textContent;
            right.appendChild( b );
        }


         /* 算出顶部实际占多高,动态决定正文留白 */
         bar.appendChild( left );
         var topH = 0;
        bar.appendChild( right );
         var pBar = document.getElementById( 'sg-personal-bar' );
        document.body.appendChild( bar );
         if ( pBar ) { topH += pBar.offsetHeight; }
 
         if ( ca ) {
         var personal = document.getElementById( "p-personal" );
            ca.style.top = topH + 'px';
         var cactions = document.getElementById( "p-cactions" );
            topH += ca.offsetHeight;
         if ( personal ) { personal.style.visibility = "hidden"; }
        }
         if ( cactions ) { cactions.style.visibility = "hidden"; }


         document.documentElement.style.setProperty( '--sg-top-offset', topH + 'px' );
         document.body.className = document.body.className + " sg-sticky-on";
        syncBarHeight( bar );
        enableHorizontalScroll( bar );
        window.addEventListener( "resize", function () { syncBarHeight( bar ); } );
    }


        if ( topH > 0 ) {
    function moveSearch() {
            document.body.classList.add( 'sg-sticky-on' );
        var search = document.getElementById( "p-search" );
         } else {
        var nav = document.getElementById( "p-navigation" );
            document.body.classList.remove( 'sg-sticky-on' );
         if ( !search || !nav ) { return; }
         }
        var container = nav.parentNode;
        if ( !container || search.parentNode !== container ) { return; }
        if ( container.firstChild === search ) { return; }
         container.insertBefore( search, container.firstChild );
     }
     }


    /* ==========================================================
      启动
      ========================================================== */
     function run() {
     function run() {
         moveTOC();
         moveTOC();
        moveSearch();
         makeSticky();
         makeSticky();
     }
     }


     if ( document.readyState === 'loading' ) {
     if ( document.readyState === "loading" ) {
         document.addEventListener( 'DOMContentLoaded', run );
         document.addEventListener( "DOMContentLoaded", run );
     } else {
     } else {
         run();
         run();
     }
     }
    window.addEventListener( 'resize', function () {
        clearTimeout( window.__sgTimer );
        window.__sgTimer = setTimeout( makeSticky, 150 );
    } );


}() );
}() );

2026年11月1日 (日) 04:16的最新版本

( function () {

    function moveTOC() {
        var toc = document.getElementById( "toc" );
        if ( !toc ) { toc = document.querySelector( ".mw-table-of-contents-container" ); }
        var sidebar = document.getElementById( "column-one" );
        if ( !toc || !sidebar ) { return; }
        var nav = document.getElementById( "p-navigation" );
        var container = ( nav && nav.parentNode ) ? nav.parentNode : sidebar;
        var existing = document.getElementById( "p-toc" );
        if ( existing ) {
            if ( nav ) {
                container.insertBefore( existing, nav.nextSibling );
            } else {
                container.appendChild( existing );
            }
            return;
        }
        var box = document.createElement( "div" );
        box.className = "portlet";
        box.id = "p-toc";
        var title = document.createElement( "h3" );
        title.textContent = "\u76ee\u5f55";
        var inner = document.createElement( "div" );
        inner.className = "pBody";
        inner.appendChild( toc );
        box.appendChild( title );
        box.appendChild( inner );
        if ( nav ) {
            container.insertBefore( box, nav.nextSibling );
        } else {
            var search = document.getElementById( "p-search" );
            if ( search && search.parentNode ) {
                search.parentNode.insertBefore( box, search );
            } else {
                container.appendChild( box );
            }
        }
    }

    function pickLinks( portlet ) {
        var out = [];
        if ( !portlet ) { return out; }
        var links = portlet.querySelectorAll( "ul a" );
        for ( var i = 0; i < links.length; i++ ) { out.push( links[ i ] ); }
        return out;
    }

    function syncBarHeight( bar ) {
        if ( !bar ) { return; }
        document.body.style.paddingTop = bar.offsetHeight + "px";
    }

    function enableHorizontalScroll( bar ) {
        if ( !bar ) { return; }
        bar.addEventListener( "wheel", function ( e ) {
            if ( Math.abs( e.deltaY ) > Math.abs( e.deltaX ) ) {
                bar.scrollLeft += e.deltaY;
                e.preventDefault();
            }
        }, { passive: false } );

        var down = false, startX = 0, startLeft = 0;
        bar.addEventListener( "mousedown", function ( e ) {
            if ( e.target && e.target.tagName === "A" ) { return; }
            down = true;
            startX = e.pageX;
            startLeft = bar.scrollLeft;
            bar.style.cursor = "grabbing";
        } );
        window.addEventListener( "mousemove", function ( e ) {
            if ( !down ) { return; }
            bar.scrollLeft = startLeft - ( e.pageX - startX );
        } );
        window.addEventListener( "mouseup", function () {
            down = false;
            bar.style.cursor = "";
        } );
    }

    function makeSticky() {
        var old = document.getElementById( "sg-topbar" );
        if ( old ) { old.parentNode.removeChild( old ); }

        var leftLinks = pickLinks( document.getElementById( "p-cactions" ) );
        var rightLinks = pickLinks( document.getElementById( "p-personal" ) );

        var notifHref = null;
        var notifCount = 0;
        var notifIndex = -1;
        var plainRightLinks = [];
        for ( var n = 0; n < rightLinks.length; n++ ) {
            var item = rightLinks[ n ];
            var parent = item.parentNode;
            var itemId = parent ? parent.id : "";
            if ( itemId === "pt-notifications-alert" || itemId === "pt-notifications-notice" ) {
                if ( notifIndex < 0 ) { notifIndex = plainRightLinks.length; }
                if ( !notifHref ) { notifHref = item.href; }
                var raw = item.getAttribute( "data-counter-num" );
                var count = parseInt( raw, 10 );
                if ( isNaN( count ) ) {
                    var match = ( item.textContent || "" ).match( /[((](\d+)[))]/ );
                    count = match ? parseInt( match[ 1 ], 10 ) : 0;
                }
                notifCount += count;
                continue;
            }
            plainRightLinks.push( item );
        }
        rightLinks = plainRightLinks;

        var privateIndex = -1;
        for ( var p = 0; p < rightLinks.length; p++ ) {
            var pParent = rightLinks[ p ].parentNode;
            var pId = pParent ? pParent.id : "";
            var pText = ( rightLinks[ p ].textContent || "" ).replace( /\s/g, "" );
            if ( pId === "pt-mytalk" || pText === "\u8ba8\u8bba" ) {
                privateIndex = p + 1;
                break;
            }
        }

        if ( leftLinks.length === 0 && rightLinks.length === 0 && !notifHref ) { return; }

        var bar = document.createElement( "div" );
        bar.id = "sg-topbar";
        bar.className = "sg-sticky-bar";

        var left = document.createElement( "div" );
        left.className = "sg-bar-left";
        for ( var i = 0; i < leftLinks.length; i++ ) {
            var a = document.createElement( "a" );
            a.href = leftLinks[ i ].href;
            a.textContent = leftLinks[ i ].textContent;
            left.appendChild( a );
        }

        var right = document.createElement( "div" );
        right.className = "sg-bar-right";
        for ( var j = 0; j <= rightLinks.length; j++ ) {
            if ( j === privateIndex ) {
                var privateLink = document.createElement( "a" );
                privateLink.href = "/index.php?title=Special:UserBoard";
                privateLink.textContent = "\u79c1\u4fe1";
                privateLink.title = "\u67e5\u770b\u79c1\u4fe1";
                right.appendChild( privateLink );
            }
            if ( j === notifIndex && notifHref ) {
                var notice = document.createElement( "a" );
                notice.href = notifHref;
                notice.textContent = "\u901a\u77e5\uff08" + notifCount + "\uff09";
                notice.title = "\u91cd\u8981\u901a\u77e5\u4e0e\u5e38\u89c4\u901a\u77e5";
                right.appendChild( notice );
            }
            if ( j === rightLinks.length ) { break; }
            var b = document.createElement( "a" );
            b.href = rightLinks[ j ].href;
            b.textContent = rightLinks[ j ].textContent;
            right.appendChild( b );
        }

        bar.appendChild( left );
        bar.appendChild( right );
        document.body.appendChild( bar );

        var personal = document.getElementById( "p-personal" );
        var cactions = document.getElementById( "p-cactions" );
        if ( personal ) { personal.style.visibility = "hidden"; }
        if ( cactions ) { cactions.style.visibility = "hidden"; }

        document.body.className = document.body.className + " sg-sticky-on";
        syncBarHeight( bar );
        enableHorizontalScroll( bar );
        window.addEventListener( "resize", function () { syncBarHeight( bar ); } );
    }

    function moveSearch() {
        var search = document.getElementById( "p-search" );
        var nav = document.getElementById( "p-navigation" );
        if ( !search || !nav ) { return; }
        var container = nav.parentNode;
        if ( !container || search.parentNode !== container ) { return; }
        if ( container.firstChild === search ) { return; }
        container.insertBefore( search, container.firstChild );
    }

    function run() {
        moveTOC();
        moveSearch();
        makeSticky();
    }

    if ( document.readyState === "loading" ) {
        document.addEventListener( "DOMContentLoaded", run );
    } else {
        run();
    }

}() );