「MediaWiki:Common.js」:修訂間差異

出自Quickpedia wiki
無編輯摘要
無編輯摘要
 
(未顯示同一使用者於中間所作的 14 次修訂)
第1行: 第1行:
$(function() {
/**
  var variants = mw.config.get('wgContentLanguageVariants'); // 獲取可用的語言變體
* MediaWiki:Common.js 強化完整版
* 適用對象:Quickpedia wiki
* 功能:語系導向、手動字詞轉換、自動暫存(防 Cloudflare 斷線)、持久連線心跳包、深色模式、時鐘
*/


  if (variants && variants.length > 1) {
mw.loader.using(['mediawiki.util', 'mediawiki.Uri', 'mediawiki.api']).then(function () {
    var currentVariant = mw.config.get('wgUserVariant');
    var languageDropdown = $('<div id="zh-variant-dropdown"></div>').append('<label for="zh-variant-select">中文:</label><select id="zh-variant-select"></select>');
    var variantSelect = languageDropdown.find('#zh-variant-select');


     for (var i = 0; i < variants.length; i++) {
     $(function () {
      var variantCode = variants[i];
      var variantName = '';


      switch (variantCode) {
        /* ============================================================
        case 'zh-tw':
        * ① 語系自動導向與切換 (針對訪客預設 zh)
         case 'zh-hant':
        * ============================================================ */
          variantName = '中文(繁體)';
         var isAnon = mw.config.get('wgUserName') === null;
          break;
         var currentVariant = mw.util.getParamValue('variant');
         case 'zh-cn':
        case 'zh-hans':
          variantName = '中文(簡體)';
          break;
        default:
          variantName = variantCode;
      }


      var option = $('<option>').val(variantCode).text(variantName);
        // 訪客預設導向中文 (zh)
      if (variantCode === currentVariant) {
        if (isAnon && !currentVariant && mw.config.get('wgAction') === 'view') {
        option.prop('selected', true);
            var url = new mw.Uri(window.location.href);
      }
            url.query.variant = 'zh';
      variantSelect.append(option);
            window.location.replace(url.toString());
    }
            return;
        }
 
        // 建立右上角切換按鈕
        var variants = [
            { code: 'zh', label: '中文' },
            { code: 'zh-tw', label: '繁體' },
            { code: 'zh-cn', label: '简体' }
        ];
 
        var $langContainer = $('<span>').attr('id', 'custom-variant-switches');
        variants.forEach(function (v, i) {
            var $link = $('<a>')
                .text(v.label)
                .css({
                    cursor: 'pointer',
                    padding: '0 5px',
                    color: currentVariant === v.code ? '#000' : '#0645ad',
                    fontWeight: currentVariant === v.code ? 'bold' : 'normal'
                })
                .on('click', function (e) {
                    e.preventDefault();
                    var url = new mw.Uri(window.location.href);
                    url.query.variant = v.code;
                    window.location.href = url.toString();
                });
            $langContainer.append($link);
            if (i < variants.length - 1) $langContainer.append('|');
        });
 
        mw.util.addPortletLink('p-personal', '#', '', 'pt-variant-switch', '切換語系', '#pt-logout');
        $('#pt-variant-switch').append($langContainer);


    variantSelect.on('change', function() {
      var selectedVariant = $(this).val();
      var currentUrl = new URL(window.location.href);
      currentUrl.searchParams.set('variant', selectedVariant);
      window.location.href = currentUrl.toString();
    });


    // 將下拉選單添加到您希望顯示的位置,例如側邊欄頂部
        /* ============================================================
    $('#mw-panel').prepend(languageDropdown);
        * ② 手動字詞轉換 (確保站名正確顯示)
        * ============================================================ */
        function applyManualTranslation() {
            var v = mw.util.getParamValue('variant') || mw.config.get('wgUserVariant') || mw.config.get('wgUserLanguage');
            if (v === 'zh-hans' || v === 'zh-cn') {
                $('h1#firstHeading, #p-logo-text, .mw-wiki-title, title').each(function() {
                    var t = $(this).text();
                    $(this).text(t.replace(/Quickpedia wiki/g, 'Quickpedia wiki'));
                });
            }
        }
        applyManualTranslation();


    // 或者添加到左上角 (需要 CSS 定位,如同之前的討論)
    // $('body').prepend(languageDropdown);
  }
});


/* Language Redirection and Menu Filtering for Simplified/Traditional Chinese */
        /* ============================================================
        * ③ 自動暫存與持久編輯 (對抗 Cloudflare 驗證中斷)
        * ============================================================ */
        if (['edit', 'submit'].indexOf(mw.config.get('wgAction')) !== -1) {
            var pageName = mw.config.get('wgPageName');
            var storageKey = 'edit_cache_' + pageName;
            var $textbox = $('#wpTextbox1');


(function() {
            // A. 心跳包:每 2 分鐘向伺服器發送請求,防止 Session 過期或驗證跳出
    // === 1. 自動語系導向邏輯 ===
            setInterval(function() {
    var lang = (navigator.language || navigator.userLanguage).toLowerCase();
                new mw.Api().get({
    var simplifiedCodes = ['zh-cn', 'zh-sg', 'zh-hans']; // 簡體中文語系代碼
                    action: 'query',
    var traditionalCodes = ['zh-tw', 'zh-hk', 'zh-mo', 'zh-hant']; // 繁體中文語系代碼
                    titles: pageName,
                    prop: 'info'
                }).done(function() {
                    console.log('Quickpedia wiki 連線維持中...');
                });
            }, 120000);


    var currentURL = window.location.href;
            // B. 高頻率自動暫存:每 20 秒存一次草稿
            setInterval(function () {
                var content = $textbox.val();
                if (content && content.length > 10) {
                    localStorage.setItem(storageKey, JSON.stringify({
                        text: content,
                        timestamp: Date.now()
                    }));
                }
            }, 20000);  


    // 檢查 URL 中是否已經有繁體或簡體的標示
            // C. 檢查並還原草稿
    // 注意:您可能需要根據您的實際URL結構調整 '/簡體' 和 '/繁體'
            var savedCache = localStorage.getItem(storageKey);
    // 如果您的繁體版本不需要 '/繁體' 這個路徑,或者預設就是繁體,請調整 below!
            if (savedCache) {
    var hasSimplifiedInURL = currentURL.includes('/簡體');
                var data = JSON.parse(savedCache);
    var hasTraditionalInURL = currentURL.includes('/繁體');
                if (Date.now() - data.timestamp < 86400000 && $textbox.val().length < 50) {
                    if (confirm('偵測到未儲存草稿(可能因 Cloudflare 驗證中斷),是否還原?')) {
                        $textbox.val(data.text);
                    }
                }
            }


    // 只有當 URL 中尚未明確指定繁簡版本時,才進行語系導向
            // D. 離開頁面警告
    if (!hasSimplifiedInURL && !hasTraditionalInURL) {
            window.onbeforeunload = function() {
        var isSimplifiedBrowser = simplifiedCodes.includes(lang);
                if ($textbox.val().length > 50) return "內容尚未儲存!";
        var isTraditionalBrowser = traditionalCodes.includes(lang);
            };


        if (isSimplifiedBrowser) {
             // E. 儲存後清除暫存
             // 如果瀏覽器是簡體,導向到簡體版本
             $('#wpSave, #wpSaveWidget, input#wpSave').on('click', function() {
             window.location.href = currentURL + '/簡體';
                localStorage.removeItem(storageKey);
        } else if (isTraditionalBrowser) {
                window.onbeforeunload = null;  
            // 如果瀏覽器是繁體,導向到繁體版本
            });
            // 再次強調:確保您的 Wiki 支援 /繁體 這個路徑來顯示繁體內容。
            // 如果您的繁體版本就是預設URL (沒有額外路徑),則這裡可以考慮不導向。
            window.location.href = currentURL + '/繁體';
        } else {
            // 如果瀏覽器語系既不是簡體也不是繁體中文 (例如英文),則預設導向到繁體中文。
            window.location.href = currentURL + '/繁體';
         }
         }
    }


    // === 2. 隱藏其他語系選項 (MediaWiki 右上角的語系切換器) ===
    // MediaWiki 的語系切換器通常在一個 class 為 'mw-portlet' 或 id 為 'p-variants' 的區塊裡
    // 裡面的每個語系選項是一個 <li> 包含一個 <a>
    // 我們需要移除或隱藏那些非 'zh-hans' 或 'zh-hant' 的選項


    // 等待頁面內容完全加載,確保語系選單已經存在
        /* ============================================================
    $(document).ready(function() {
        * ④ 深色模式
        var variantsMenu = $('#p-variants'); // 這是 MediaWiki 語系選單的標準 ID
        * ============================================================ */
        var darkBtn = mw.util.addPortletLink('p-personal', '#', '深色模式', 'pt-darkmode', '切換深色模式', '#pt-variant-switch');
        $(darkBtn).on('click', function (e) {
            e.preventDefault();
            $('body').toggleClass('dark-mode');
            localStorage.setItem('wiki-dark-mode', $('body').hasClass('dark-mode') ? '1' : '0');
        });


         if (variantsMenu.length > 0) {
         if (localStorage.getItem('wiki-dark-mode') === '1') {
            // 遍歷所有的語系選項 (<li> 元素)
            $('body').addClass('dark-mode');
            variantsMenu.find('li').each(function() {
        }
                var $li = $(this);
                var $link = $li.find('a');
                if ($link.length > 0) {
                    var href = $link.attr('href');
                    // 檢查 href 中是否包含簡體或繁體的標識
                    // MediaWiki 通常會使用 /zh-hans, /zh-hant 這樣的路徑
                    if (!href.includes('/zh-hans') && !href.includes('/zh-hant') &&
                        !href.includes('/zh-cn') && !href.includes('/zh-tw')) {
                        // 如果不包含,則隱藏這個 li 元素
                        $li.hide();
                    }
                }
            });


            // 可選:如果你希望將原本的語系選擇標題 (例如 "Language variants") 也改為中文
            // 找到標題元素,通常是 .mw-portlet-variants h3 或類似
            // 實際元素請檢查您的 Wiki HTML 結構
            // var titleElement = variantsMenu.find('h3'); // 假設是 h3
            // if (titleElement.length > 0) {
            //    titleElement.text('語系選項'); // 或 '語言選項'
            // }


            // 可選:如果你希望簡化菜單,只顯示“簡體”和“繁體”的文字
        /* ============================================================
            // 而不是預設的“中文(簡體)” “中文(臺灣)” 等
        * ⑤ 即時時鐘
            variantsMenu.find('a[href*="/zh-hans"]').text('簡體中文');
        * ============================================================ */
            variantsMenu.find('a[href*="/zh-cn"]').text('簡體中文'); // 確保zh-cn也顯示為簡體
        var $clock = $('<li>').attr('id', 'pt-clock').css({
            variantsMenu.find('a[href*="/zh-hant"]').text('繁體中文');
             fontWeight: 'bold',
             variantsMenu.find('a[href*="/zh-tw"]').text('繁體中文'); // 確保zh-tw也顯示為繁體
             marginLeft: '10px',
             variantsMenu.find('a[href*="/zh-hk"]').text('繁體中文'); // 確保zh-hk也顯示為繁體
             color: '#54595d'
             variantsMenu.find('a[href*="/zh-mo"]').text('繁體中文'); // 確保zh-mo也顯示為繁體
        });


        function updateClock() {
            var now = new Date();
            $clock.text(now.toLocaleTimeString('zh-TW', { hour12: false }));
         }
         }
        $('#p-personal ul').append($clock);
        setInterval(updateClock, 1000);
        updateClock();
     });
     });
 
});
})();

於 2026年9月9日 (三) 03:44 的最新修訂

/**
 * MediaWiki:Common.js 強化完整版
 * 適用對象:Quickpedia wiki
 * 功能:語系導向、手動字詞轉換、自動暫存(防 Cloudflare 斷線)、持久連線心跳包、深色模式、時鐘
 */

mw.loader.using(['mediawiki.util', 'mediawiki.Uri', 'mediawiki.api']).then(function () {

    $(function () {

        /* ============================================================
         * ① 語系自動導向與切換 (針對訪客預設 zh)
         * ============================================================ */
        var isAnon = mw.config.get('wgUserName') === null;
        var currentVariant = mw.util.getParamValue('variant');

        // 訪客預設導向中文 (zh)
        if (isAnon && !currentVariant && mw.config.get('wgAction') === 'view') {
            var url = new mw.Uri(window.location.href);
            url.query.variant = 'zh';
            window.location.replace(url.toString());
            return; 
        }

        // 建立右上角切換按鈕
        var variants = [
            { code: 'zh', label: '中文' },
            { code: 'zh-tw', label: '繁體' },
            { code: 'zh-cn', label: '简体' }
        ];

        var $langContainer = $('<span>').attr('id', 'custom-variant-switches');
        variants.forEach(function (v, i) {
            var $link = $('<a>')
                .text(v.label)
                .css({
                    cursor: 'pointer',
                    padding: '0 5px',
                    color: currentVariant === v.code ? '#000' : '#0645ad',
                    fontWeight: currentVariant === v.code ? 'bold' : 'normal'
                })
                .on('click', function (e) {
                    e.preventDefault();
                    var url = new mw.Uri(window.location.href);
                    url.query.variant = v.code;
                    window.location.href = url.toString();
                });
            $langContainer.append($link);
            if (i < variants.length - 1) $langContainer.append('|');
        });

        mw.util.addPortletLink('p-personal', '#', '', 'pt-variant-switch', '切換語系', '#pt-logout');
        $('#pt-variant-switch').append($langContainer);


        /* ============================================================
         * ② 手動字詞轉換 (確保站名正確顯示)
         * ============================================================ */
        function applyManualTranslation() {
            var v = mw.util.getParamValue('variant') || mw.config.get('wgUserVariant') || mw.config.get('wgUserLanguage');
            if (v === 'zh-hans' || v === 'zh-cn') {
                $('h1#firstHeading, #p-logo-text, .mw-wiki-title, title').each(function() {
                    var t = $(this).text();
                    $(this).text(t.replace(/Quickpedia wiki/g, 'Quickpedia wiki'));
                });
            }
        }
        applyManualTranslation();


        /* ============================================================
         * ③ 自動暫存與持久編輯 (對抗 Cloudflare 驗證中斷)
         * ============================================================ */
        if (['edit', 'submit'].indexOf(mw.config.get('wgAction')) !== -1) {
            var pageName = mw.config.get('wgPageName');
            var storageKey = 'edit_cache_' + pageName;
            var $textbox = $('#wpTextbox1');

            // A. 心跳包:每 2 分鐘向伺服器發送請求,防止 Session 過期或驗證跳出
            setInterval(function() {
                new mw.Api().get({
                    action: 'query',
                    titles: pageName,
                    prop: 'info'
                }).done(function() {
                    console.log('Quickpedia wiki 連線維持中...');
                });
            }, 120000);

            // B. 高頻率自動暫存:每 20 秒存一次草稿
            setInterval(function () {
                var content = $textbox.val();
                if (content && content.length > 10) {
                    localStorage.setItem(storageKey, JSON.stringify({
                        text: content,
                        timestamp: Date.now()
                    }));
                }
            }, 20000); 

            // C. 檢查並還原草稿
            var savedCache = localStorage.getItem(storageKey);
            if (savedCache) {
                var data = JSON.parse(savedCache);
                if (Date.now() - data.timestamp < 86400000 && $textbox.val().length < 50) {
                    if (confirm('偵測到未儲存草稿(可能因 Cloudflare 驗證中斷),是否還原?')) {
                        $textbox.val(data.text);
                    }
                }
            }

            // D. 離開頁面警告
            window.onbeforeunload = function() {
                if ($textbox.val().length > 50) return "內容尚未儲存!";
            };

            // E. 儲存後清除暫存
            $('#wpSave, #wpSaveWidget, input#wpSave').on('click', function() {
                localStorage.removeItem(storageKey);
                window.onbeforeunload = null; 
            });
        }


        /* ============================================================
         * ④ 深色模式
         * ============================================================ */
        var darkBtn = mw.util.addPortletLink('p-personal', '#', '深色模式', 'pt-darkmode', '切換深色模式', '#pt-variant-switch');
        $(darkBtn).on('click', function (e) {
            e.preventDefault();
            $('body').toggleClass('dark-mode');
            localStorage.setItem('wiki-dark-mode', $('body').hasClass('dark-mode') ? '1' : '0');
        });

        if (localStorage.getItem('wiki-dark-mode') === '1') {
            $('body').addClass('dark-mode');
        }


        /* ============================================================
         * ⑤ 即時時鐘
         * ============================================================ */
        var $clock = $('<li>').attr('id', 'pt-clock').css({
            fontWeight: 'bold',
            marginLeft: '10px',
            color: '#54595d'
        });

        function updateClock() {
            var now = new Date();
            $clock.text(now.toLocaleTimeString('zh-TW', { hour12: false }));
        }

        $('#p-personal ul').append($clock);
        setInterval(updateClock, 1000);
        updateClock();

    });
});