「MediaWiki:Common.js」:修訂間差異
無編輯摘要 |
無編輯摘要 |
||
| 第1行: | 第1行: | ||
/** | /** | ||
* MediaWiki:Common. | * MediaWiki:Common.js 強化完整版 | ||
* | * 適用對象:維基家族 wiki | ||
* | * 功能:語言切換、自動暫存、深色模式、右上角時鐘 | ||
*/ | */ | ||
| 第12行: | 第9行: | ||
$(function () { | $(function () { | ||
/* ========================= | /* ============================================================ | ||
* ① | * ① 語系自動導向與切換 (針對訪客預設 zh-tw) | ||
* ========================= */ | * ============================================================ */ | ||
var isAnon = mw.config.get('wgUserName') === null; | |||
var currentVariant = mw.util.getParamValue('variant'); | |||
// 如果是訪客且網址沒帶語系參數,自動導向繁體中文 (避免搜尋引擎抓到英文版) | |||
if (isAnon && !currentVariant && mw.config.get('wgAction') === 'view') { | |||
var url = new mw.Uri(window.location.href); | |||
url.query.variant = 'zh-tw'; | |||
window.location.replace(url.toString()); | |||
return; | |||
} | |||
// 建立右上角切換按鈕 | |||
var variants = [ | var variants = [ | ||
{ code: 'zh-tw', label: '繁體' }, | { code: 'zh-tw', label: '繁體' }, | ||
| 第21行: | 第29行: | ||
]; | ]; | ||
var $langMenu = $('<span>').css({ marginLeft: '10px', fontSize: '0.9em' }); | |||
var $langMenu = $('<span>').css({ | |||
variants.forEach(function (v, i) { | variants.forEach(function (v, i) { | ||
var $link = $('<a>') | var $link = $('<a>') | ||
| 第36行: | 第35行: | ||
.css({ | .css({ | ||
cursor: 'pointer', | cursor: 'pointer', | ||
padding: '0 2px', | |||
color: v.code | color: currentVariant === v.code ? '#000' : '#0645ad', | ||
fontWeight: currentVariant === v.code ? 'bold' : 'normal' | |||
}) | }) | ||
.on('click', function () { | .on('click', function () { | ||
| 第45行: | 第44行: | ||
window.location.href = url.toString(); | window.location.href = url.toString(); | ||
}); | }); | ||
$langMenu.append($link); | $langMenu.append($link); | ||
if (i < variants.length - 1) | if (i < variants.length - 1) $langMenu.append('|'); | ||
}); | }); | ||
mw.util.addPortletLink( | mw.util.addPortletLink('p-personal', '#', $langMenu.prop('outerHTML'), 'pt-variant-switch', '切換語系', '#pt-logout'); | ||
/* ========================= | /* ============================================================ | ||
* ② | * ② 自動暫存功能 (應對 Cloudflare 驗證中斷) | ||
* ========================= */ | * ============================================================ */ | ||
if (['edit', 'submit'].indexOf(mw.config.get('wgAction')) !== -1) { | |||
var pageName = mw.config.get('wgPageName'); | |||
var storageKey = 'edit_cache_' + pageName; | |||
var $textbox = $('#wpTextbox1'); | |||
// 1. 每 30 秒自動存檔一次 (縮短間隔以防 Cloudflare 突然跳出) | |||
setInterval(function () { | |||
var content = $textbox.val(); | |||
if (content && content.length > 10) { | |||
var cacheData = { | |||
text: content, | |||
timestamp: Date.now() | |||
}; | |||
localStorage.setItem(storageKey, JSON.stringify(cacheData)); | |||
console.log('草稿已暫存於瀏覽器: ' + new Date().toLocaleTimeString()); | |||
} | |||
}, 30000); | |||
// 2. 進入編輯頁面時,檢查是否有未儲存的草稿 | |||
var savedCache = localStorage.getItem(storageKey); | |||
if (savedCache) { | |||
var data = JSON.parse(savedCache); | |||
// 如果暫存是在 24 小時內,且目前編輯框是空的或只有基礎內容 | |||
if (Date.now() - data.timestamp < 86400000 && $textbox.val().length < 50) { | |||
var confirmRecover = confirm('偵測到此頁面有未儲存的草稿(可能因 Cloudflare 驗證而中斷),是否還原內容?'); | |||
if (confirmRecover) { | |||
$textbox.val(data.text); | |||
} | |||
} | |||
} | |||
// 3. 按下儲存按鈕後,清除該頁面的暫存 | |||
$('#wpSave, #wpSaveWidget').on('click', function() { | |||
localStorage.removeItem(storageKey); | |||
}); | |||
} | |||
/* ============================================================ | |||
* ③ 深色模式切換 | |||
* ============================================================ */ | |||
var darkBtn = mw.util.addPortletLink('p-personal', '#', '深色模式', 'pt-darkmode', '切換深色/淺色模式'); | |||
$(darkBtn).on('click', function (e) { | $(darkBtn).on('click', function (e) { | ||
e.preventDefault(); | e.preventDefault(); | ||
$('body').toggleClass('dark-mode'); | $('body').toggleClass('dark-mode'); | ||
var isDark = $('body').hasClass('dark-mode'); | var isDark = $('body').hasClass('dark-mode'); | ||
localStorage.setItem('dark-mode', isDark ? '1' : '0'); | localStorage.setItem('wiki-dark-mode', isDark ? '1' : '0'); | ||
}); | }); | ||
if (localStorage.getItem('dark-mode') === '1') { | // 頁面載入時檢查狀態 | ||
if (localStorage.getItem('wiki-dark-mode') === '1') { | |||
$('body').addClass('dark-mode'); | $('body').addClass('dark-mode'); | ||
} | } | ||
/* ========================= | /* ============================================================ | ||
* | * ④ 右上角即時時鐘 (顯示伺服器/本地時間) | ||
* ========================= */ | * ============================================================ */ | ||
var $clock = $('<li>').attr('id', 'pt-clock').css({ | |||
fontWeight: 'bold', | |||
color: '#54595d', | |||
marginLeft: '10px', | |||
display: 'inline-block', | |||
verticalAlign: 'middle' | |||
}); | |||
function | function tick() { | ||
var now = new Date(); | var now = new Date(); | ||
var timeStr = now.toLocaleTimeString('zh-TW', { hour12: false }); | |||
$clock.text(timeStr); | |||
} | } | ||
$('#p-personal ul').append($clock); | |||
setInterval(tick, 1000); | |||
tick(); | |||
$('#p-personal').append($clock); | |||
setInterval( | |||
}); | }); | ||
}); | }); | ||
於 2026年4月25日 (六) 06:22 的修訂
/**
* MediaWiki:Common.js 強化完整版
* 適用對象:維基家族 wiki
* 功能:語言切換、自動暫存、深色模式、右上角時鐘
*/
mw.loader.using(['mediawiki.util', 'mediawiki.Uri']).then(function () {
$(function () {
/* ============================================================
* ① 語系自動導向與切換 (針對訪客預設 zh-tw)
* ============================================================ */
var isAnon = mw.config.get('wgUserName') === null;
var currentVariant = mw.util.getParamValue('variant');
// 如果是訪客且網址沒帶語系參數,自動導向繁體中文 (避免搜尋引擎抓到英文版)
if (isAnon && !currentVariant && mw.config.get('wgAction') === 'view') {
var url = new mw.Uri(window.location.href);
url.query.variant = 'zh-tw';
window.location.replace(url.toString());
return;
}
// 建立右上角切換按鈕
var variants = [
{ code: 'zh-tw', label: '繁體' },
{ code: 'zh-cn', label: '简体' }
];
var $langMenu = $('<span>').css({ marginLeft: '10px', fontSize: '0.9em' });
variants.forEach(function (v, i) {
var $link = $('<a>')
.text(v.label)
.css({
cursor: 'pointer',
padding: '0 2px',
color: currentVariant === v.code ? '#000' : '#0645ad',
fontWeight: currentVariant === v.code ? 'bold' : 'normal'
})
.on('click', function () {
var url = new mw.Uri(window.location.href);
url.query.variant = v.code;
window.location.href = url.toString();
});
$langMenu.append($link);
if (i < variants.length - 1) $langMenu.append('|');
});
mw.util.addPortletLink('p-personal', '#', $langMenu.prop('outerHTML'), 'pt-variant-switch', '切換語系', '#pt-logout');
/* ============================================================
* ② 自動暫存功能 (應對 Cloudflare 驗證中斷)
* ============================================================ */
if (['edit', 'submit'].indexOf(mw.config.get('wgAction')) !== -1) {
var pageName = mw.config.get('wgPageName');
var storageKey = 'edit_cache_' + pageName;
var $textbox = $('#wpTextbox1');
// 1. 每 30 秒自動存檔一次 (縮短間隔以防 Cloudflare 突然跳出)
setInterval(function () {
var content = $textbox.val();
if (content && content.length > 10) {
var cacheData = {
text: content,
timestamp: Date.now()
};
localStorage.setItem(storageKey, JSON.stringify(cacheData));
console.log('草稿已暫存於瀏覽器: ' + new Date().toLocaleTimeString());
}
}, 30000);
// 2. 進入編輯頁面時,檢查是否有未儲存的草稿
var savedCache = localStorage.getItem(storageKey);
if (savedCache) {
var data = JSON.parse(savedCache);
// 如果暫存是在 24 小時內,且目前編輯框是空的或只有基礎內容
if (Date.now() - data.timestamp < 86400000 && $textbox.val().length < 50) {
var confirmRecover = confirm('偵測到此頁面有未儲存的草稿(可能因 Cloudflare 驗證而中斷),是否還原內容?');
if (confirmRecover) {
$textbox.val(data.text);
}
}
}
// 3. 按下儲存按鈕後,清除該頁面的暫存
$('#wpSave, #wpSaveWidget').on('click', function() {
localStorage.removeItem(storageKey);
});
}
/* ============================================================
* ③ 深色模式切換
* ============================================================ */
var darkBtn = mw.util.addPortletLink('p-personal', '#', '深色模式', 'pt-darkmode', '切換深色/淺色模式');
$(darkBtn).on('click', function (e) {
e.preventDefault();
$('body').toggleClass('dark-mode');
var isDark = $('body').hasClass('dark-mode');
localStorage.setItem('wiki-dark-mode', isDark ? '1' : '0');
});
// 頁面載入時檢查狀態
if (localStorage.getItem('wiki-dark-mode') === '1') {
$('body').addClass('dark-mode');
}
/* ============================================================
* ④ 右上角即時時鐘 (顯示伺服器/本地時間)
* ============================================================ */
var $clock = $('<li>').attr('id', 'pt-clock').css({
fontWeight: 'bold',
color: '#54595d',
marginLeft: '10px',
display: 'inline-block',
verticalAlign: 'middle'
});
function tick() {
var now = new Date();
var timeStr = now.toLocaleTimeString('zh-TW', { hour12: false });
$clock.text(timeStr);
}
$('#p-personal ul').append($clock);
setInterval(tick, 1000);
tick();
});
});