跳转到内容

MediaWiki:Common.js:修订间差异

来自天明的百科全书
Ztm0929留言 | 贡献
尝试增加针对移动端的紧凑模式识别
标签已被回退
Ztm0929留言 | 贡献
修正尺寸切换逻辑
标签已被回退
第31行: 第31行:


// logo 切换逻辑
// logo 切换逻辑
// Common.js - footer logo 切换逻辑
// Common.js - footer logo 切换逻辑(支持 dark/light + compact/normal + Citizen)
$(function () {
$(function () {
     // ======================
     // ======================
第37行: 第37行:
     // ======================
     // ======================


     // 判断当前主题:dark / light
     // 获取当前主题:dark / light
     function getEffectiveTheme() {
     function getEffectiveTheme() {
         var cls = document.documentElement.classList;
         const cls = document.documentElement.classList;
         if (cls.contains('skin-theme-clientpref-night')) return 'dark';
         if (cls.contains('skin-theme-clientpref-night')) return 'dark';
         if (cls.contains('skin-theme-clientpref-day')) return 'light';
         if (cls.contains('skin-theme-clientpref-day')) return 'light';
         if (cls.contains('skin-theme-clientpref-os')) {
         if (cls.contains('skin-theme-clientpref-os')) {
             if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
             if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) return 'dark';
                return 'dark';
            }
             return 'light';
             return 'light';
         }
         }
        // 兜底:系统偏好
         if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) return 'dark';
         if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
            return 'dark';
        }
         return 'light';
         return 'light';
     }
     }


     // 判断是否为移动端 compact 模式(小图)
     // 判断是否小屏(compact)
     function isCompactMode() {
     function isCompactMode() {
         return window.matchMedia && window.matchMedia('(max-width: 500px)').matches;
         return window.matchMedia && window.matchMedia('(max-width: 500px)').matches;
     }
     }


     // 如果元素存在就设置 src
     // 设置 <img> src
     function setSrcIfExists(selector, src) {
     function setImgSrc($img, src) {
        var $el = $(selector);
         if ($img.length) $img.attr('src', src);
         if ($el.length) {
    }
            $el.attr('src', src);
 
            console.log('[logo-switch] set', selector, '->', src);
    // 设置 <source> srcset
        }
    function setSourceSrcset($source, srcset) {
        if ($source.length) $source.attr('srcset', srcset);
     }
     }


第73行: 第69行:
     // ======================
     // ======================
     function updateLogos() {
     function updateLogos() {
         var theme = getEffectiveTheme();
         const theme = getEffectiveTheme();
         var compact = isCompactMode();
         const compact = isCompactMode();
 
        // 尺寸逻辑:大屏用 source 横版,宽度 88x31;小屏 fallback img 用 25x25
        // 注意:compact 状态下实际用 img,小屏时尺寸固定为 25x25
        const sizeNormal = { width: 88, height: 31 };
        const sizeCompact = { width: 25, height: 25 };
 
        // ----------------------
        // 公共 Logo
        // ----------------------
        ['copyright', 'poweredby', 'poweredbysmw'].forEach(id => {
            const $li = $(`#footer-${id}ico`);
            if (!$li.length) return;
 
            const $picture = $li.find('picture');
            if (!$picture.length) return;
 
            const $source = $picture.find('source');
            const $img = $picture.find('img');
 
            // 构造文件名
            let baseName = '';
            switch(id) {
                case 'copyright': baseName = 'cc-by-nc-sa'; break;
                case 'poweredby': baseName = 'poweredby-mediawiki'; break;
                case 'poweredbysmw': baseName = 'poweredby-smw'; break;
            }
            const normalFile = `/resources/assets/${baseName}${theme === 'dark' ? '-dark' : ''}.svg`;
            const compactFile = `/resources/assets/${baseName}-compact${theme === 'dark' ? '-dark' : ''}.svg`;


        // 文件名后缀
            // 设置 source -> 大屏横版
        var suffix = '';
            setSourceSrcset($source, normalFile);
        if (compact) {
             $source.attr('width', sizeNormal.width);
             suffix += '-compact';
            $source.attr('height', sizeNormal.height);
        }
        if (theme === 'dark') {
            suffix += '-dark';
        }


        // 公共 logo(所有皮肤都显示)
            // 设置 img -> 小屏紧凑版
        setSrcIfExists('#footer-copyrightico img', '/resources/assets/cc-by-nc-sa' + suffix + '.svg');
            setImgSrc($img, compactFile);
        setSrcIfExists('#footer-poweredbyico img', '/resources/assets/poweredby-mediawiki' + suffix + '.svg');
            $img.attr('width', sizeCompact.width);
        setSrcIfExists('#footer-poweredbysmwico img', '/resources/assets/poweredby-smw' + suffix + '.svg');
            $img.attr('height', sizeCompact.height);
        });


         // Citizen 专属(仅当元素存在时才切换)
        // ----------------------
         // Citizen 专属
        // ----------------------
         if (document.body.classList.contains('skin-Citizen')) {
         if (document.body.classList.contains('skin-Citizen')) {
             setSrcIfExists('#footer-poweredbycitizenico img', '/resources/assets/poweredby-citizen' + suffix + '.svg');
             const $li = $('#footer-poweredbycitizenico');
            if ($li.length) {
                const $picture = $li.find('picture');
                const $img = $picture.length ? $picture.find('img') : $li.find('img');
 
                const normalFile = `/resources/assets/poweredby-citizen${theme === 'dark' ? '-dark' : ''}.svg`;
                const compactFile = `/resources/assets/poweredby-citizen-compact${theme === 'dark' ? '-dark' : ''}.svg`;
 
                if ($picture.length) {
                    const $source = $picture.find('source');
                    setSourceSrcset($source, normalFile);
                    $source.attr('width', sizeNormal.width);
                    $source.attr('height', sizeNormal.height);
                }
 
                setImgSrc($img, compactFile);
                $img.attr('width', sizeCompact.width);
                $img.attr('height', sizeCompact.height);
            }
         }
         }
     }
     }
第99行: 第140行:
     // 触发时机
     // 触发时机
     // ======================
     // ======================
    // 首次运行
     updateLogos();
     updateLogos();


     // 监听 <html> class 变化(主题切换)
     // 监听 <html> class 变化(主题切换)
     var htmlObserver = new MutationObserver(function (mutations) {
     new MutationObserver(() => updateLogos()).observe(document.documentElement, { attributes: true, attributeFilter: ['class'] });
        for (var i = 0; i < mutations.length; i++) {
            if (mutations[i].attributeName === 'class') {
                updateLogos();
                break;
            }
        }
    });
    htmlObserver.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] });


     // 监听 body DOM 变动,防止 footer 异步插入
     // 监听 body DOM 变动(footer 异步插入)
     var bodyObserver = new MutationObserver(function () {
     new MutationObserver(() => updateLogos()).observe(document.body, { childList: true, subtree: true });
        updateLogos();
    });
    bodyObserver.observe(document.body, { childList: true, subtree: true });


     // 监听系统主题变化
     // 监听系统主题 & 屏幕宽度变化
     if (window.matchMedia) {
     if (window.matchMedia) {
         var mqDark = window.matchMedia('(prefers-color-scheme: dark)');
         const mqDark = window.matchMedia('(prefers-color-scheme: dark)');
         if (typeof mqDark.addEventListener === 'function') {
        const mqCompact = window.matchMedia('(max-width: 500px)');
            mqDark.addEventListener('change', updateLogos);
 
         } else if (typeof mqDark.addListener === 'function') {
         if (mqDark.addEventListener) mqDark.addEventListener('change', updateLogos);
            mqDark.addListener(updateLogos);
         else if (mqDark.addListener) mqDark.addListener(updateLogos);
        }


        // 监听屏幕宽度变化(compact <-> normal)
         if (mqCompact.addEventListener) mqCompact.addEventListener('change', updateLogos);
        var mqCompact = window.matchMedia('(max-width: 500px)');
         else if (mqCompact.addListener) mqCompact.addListener(updateLogos);
         if (typeof mqCompact.addEventListener === 'function') {
            mqCompact.addEventListener('change', updateLogos);
         } else if (typeof mqCompact.addListener === 'function') {
            mqCompact.addListener(updateLogos);
        }
     }
     }


     // MediaWiki hook
     // MediaWiki hook
     if (window.mw && mw.hook) {
     if (window.mw && mw.hook) mw.hook('user.preferencesSaved').add(updateLogos);
        mw.hook('user.preferencesSaved').add(updateLogos);
    }


     // 兜底:页面 load 后、延迟再执行一次
     // 兜底
     $(window).on('load', updateLogos);
     $(window).on('load', updateLogos);
     setTimeout(updateLogos, 1500);
     setTimeout(updateLogos, 1500);
});
});


// 移除深色模式反馈提示
// 移除深色模式反馈提示

2025年9月28日 (日) 06:31的版本

/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */
// Cloudflare Web Analytics
var script = document.createElement('script');
script.defer = true;
script.src = 'https://static.cloudflareinsights.com/beacon.min.js';
script.setAttribute('data-cf-beacon', '{"token": "6180aa28fe1943b48c4059a5056f4738"}');
document.head.appendChild(script);
// End Cloudflare Web Analytics

$(function () {
    // 只在 Special:Search 页面运行
    if (mw.config.get("wgCanonicalSpecialPageName") === "Search") {
        const searchTerm = mw.util.getParamValue("search");
        const googleUrl = "https://www.google.com/search?q=" + encodeURIComponent(searchTerm);

        const $googleLink = $("<p>").html(
            `你也可以到 <a href="${googleUrl}" target="_blank" rel="noopener">Google 中搜索“${searchTerm}”</a>。`
        );

        // 优先在有搜索结果时插入
        if ($(".mw-search-results").length) {
            $googleLink.insertAfter(".mw-search-results");
        }
        // 否则在没有结果提示后插入
        else if ($(".mw-search-nonefound").length) {
            $googleLink.insertAfter(".mw-search-nonefound");
        }
    }
});


// logo 切换逻辑
// Common.js - footer logo 切换逻辑(支持 dark/light + compact/normal + Citizen)
$(function () {
    // ======================
    // 工具函数
    // ======================

    // 获取当前主题:dark / light
    function getEffectiveTheme() {
        const cls = document.documentElement.classList;
        if (cls.contains('skin-theme-clientpref-night')) return 'dark';
        if (cls.contains('skin-theme-clientpref-day')) return 'light';
        if (cls.contains('skin-theme-clientpref-os')) {
            if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) return 'dark';
            return 'light';
        }
        if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) return 'dark';
        return 'light';
    }

    // 判断是否小屏(compact)
    function isCompactMode() {
        return window.matchMedia && window.matchMedia('(max-width: 500px)').matches;
    }

    // 设置 <img> src
    function setImgSrc($img, src) {
        if ($img.length) $img.attr('src', src);
    }

    // 设置 <source> srcset
    function setSourceSrcset($source, srcset) {
        if ($source.length) $source.attr('srcset', srcset);
    }

    // ======================
    // 主更新逻辑
    // ======================
    function updateLogos() {
        const theme = getEffectiveTheme();
        const compact = isCompactMode();

        // 尺寸逻辑:大屏用 source 横版,宽度 88x31;小屏 fallback img 用 25x25
        // 注意:compact 状态下实际用 img,小屏时尺寸固定为 25x25
        const sizeNormal = { width: 88, height: 31 };
        const sizeCompact = { width: 25, height: 25 };

        // ----------------------
        // 公共 Logo
        // ----------------------
        ['copyright', 'poweredby', 'poweredbysmw'].forEach(id => {
            const $li = $(`#footer-${id}ico`);
            if (!$li.length) return;

            const $picture = $li.find('picture');
            if (!$picture.length) return;

            const $source = $picture.find('source');
            const $img = $picture.find('img');

            // 构造文件名
            let baseName = '';
            switch(id) {
                case 'copyright': baseName = 'cc-by-nc-sa'; break;
                case 'poweredby': baseName = 'poweredby-mediawiki'; break;
                case 'poweredbysmw': baseName = 'poweredby-smw'; break;
            }
            const normalFile = `/resources/assets/${baseName}${theme === 'dark' ? '-dark' : ''}.svg`;
            const compactFile = `/resources/assets/${baseName}-compact${theme === 'dark' ? '-dark' : ''}.svg`;

            // 设置 source -> 大屏横版
            setSourceSrcset($source, normalFile);
            $source.attr('width', sizeNormal.width);
            $source.attr('height', sizeNormal.height);

            // 设置 img -> 小屏紧凑版
            setImgSrc($img, compactFile);
            $img.attr('width', sizeCompact.width);
            $img.attr('height', sizeCompact.height);
        });

        // ----------------------
        // Citizen 专属
        // ----------------------
        if (document.body.classList.contains('skin-Citizen')) {
            const $li = $('#footer-poweredbycitizenico');
            if ($li.length) {
                const $picture = $li.find('picture');
                const $img = $picture.length ? $picture.find('img') : $li.find('img');

                const normalFile = `/resources/assets/poweredby-citizen${theme === 'dark' ? '-dark' : ''}.svg`;
                const compactFile = `/resources/assets/poweredby-citizen-compact${theme === 'dark' ? '-dark' : ''}.svg`;

                if ($picture.length) {
                    const $source = $picture.find('source');
                    setSourceSrcset($source, normalFile);
                    $source.attr('width', sizeNormal.width);
                    $source.attr('height', sizeNormal.height);
                }

                setImgSrc($img, compactFile);
                $img.attr('width', sizeCompact.width);
                $img.attr('height', sizeCompact.height);
            }
        }
    }

    // ======================
    // 触发时机
    // ======================
    updateLogos();

    // 监听 <html> class 变化(主题切换)
    new MutationObserver(() => updateLogos()).observe(document.documentElement, { attributes: true, attributeFilter: ['class'] });

    // 监听 body DOM 变动(footer 异步插入)
    new MutationObserver(() => updateLogos()).observe(document.body, { childList: true, subtree: true });

    // 监听系统主题 & 屏幕宽度变化
    if (window.matchMedia) {
        const mqDark = window.matchMedia('(prefers-color-scheme: dark)');
        const mqCompact = window.matchMedia('(max-width: 500px)');

        if (mqDark.addEventListener) mqDark.addEventListener('change', updateLogos);
        else if (mqDark.addListener) mqDark.addListener(updateLogos);

        if (mqCompact.addEventListener) mqCompact.addEventListener('change', updateLogos);
        else if (mqCompact.addListener) mqCompact.addListener(updateLogos);
    }

    // MediaWiki hook
    if (window.mw && mw.hook) mw.hook('user.preferencesSaved').add(updateLogos);

    // 兜底
    $(window).on('load', updateLogos);
    setTimeout(updateLogos, 1500);
});

// 移除深色模式反馈提示
$(function () {
    function removeBetaNotice() {
        var $node = $('#skin-theme-beta-notice');
        if ($node.length) {
            $node.remove();
            // 如果移除了,就断开观察器(可选)
            if (observer) {
                observer.disconnect();
            }
        }
    }

    // 第一次尝试
    removeBetaNotice();

    // 设置 MutationObserver 观察 body 或 document.body,监视 childList 增删
    var observer = new MutationObserver(function (mutations) {
        // 每次改变 DOM 时尝试移除
        removeBetaNotice();
    });
    observer.observe(document.body, {
        childList: true,
        subtree: true
    });

    // 作为兜底:在页面加载完成后一段时间再试一次
    $(window).on('load', function () {
        removeBetaNotice();
    });
    // 再加一个延时
    setTimeout(removeBetaNotice, 2000);
});

$(function () {
    // 移除上传文件、固定链接、引用此页
    $('#t-upload, #t-permalink, #t-cite').remove();
});