MediaWiki:Gadget-AdvancedSiteNotices.js
外观
注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google Chrome、Firefox、Microsoft Edge及Safari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。
/* __________________________________________________________________________
* | |
* | === WARNING: GLOBAL GADGET FILE === |
* | Changes to this page affect many users. |
* | Please discuss changes on the talk page or on [[WP:VPT]] before editing. |
* |__________________________________________________________________________|
*
* Advanced Site Notices
* Allow to custom dynamic site notices
* Maintainer: [[User:PhiLiP]]
*/
$(() => {
if (window.closeASNForever || $('#siteNotice').length < 0 || mw.config.get('wgAction') === 'edit' || mw.config.get('wgAction') === 'submit') {
return;
}
const { conv } = require('ext.gadget.HanAssist');
let customASNInterval = window.customASNInterval || 15;
const COOKIE_NAME = 'dismissASN';
let cookieVal = parseInt($.cookie(COOKIE_NAME) || '-1');
let revisionId = 0;
let timeoutId = null;
let $asnRoot = $('<div>', { id: 'asn-dismissable-notice' });
let $asnBody = $('<div>', { id: 'advancedSiteNotices', class: 'mw-parser-output' });
let $asnClose = $('<button>', {
title: conv({ hans: '关闭', hant: '關閉' }),
'aria-label': conv({ hans: '关闭', hant: '關閉' }),
class: 'asn-close-button',
});
$asnRoot.append($asnBody, $asnClose);
$asnClose.click(() => {
$asnClose.prop('disabled', true);
$.cookie(COOKIE_NAME, revisionId, {
expires: 30,
path: '/',
secure: true
});
clearTimeout(timeoutId);
$asnRoot.fadeOut(() => {
$asnRoot.remove();
});
});
let $nts = null;
let styles = [];
function matchCriteria(nt) {
let cache = nt.data('asn-cache');
if (cache !== undefined) {
return cache;
}
let criteria = nt.attr('data-asn-criteria');
if (criteria === undefined) {
criteria = nt.attr('class') ? 'false' : 'true';
if (nt.hasClass('only_sysop')) {
criteria += '||in_group("sysop")';
}
if (nt.hasClass('only_logged')) {
criteria += '||in_group("user")';
}
if (nt.hasClass('only_anon')) {
criteria += '||!in_group("user")';
}
if (nt.hasClass('only_zh_cn')) {
criteria += '||only_for("zh-cn")';
}
if (nt.hasClass('only_zh_hk')) {
criteria += '||only_for("zh-hk")';
}
if (nt.hasClass('only_zh_sg')) {
criteria += '||only_for("zh-sg")';
}
if (nt.hasClass('only_zh_tw')) {
criteria += '||only_for("zh-tw")';
}
} else {
criteria = decodeURIComponent(criteria.replace(/\+/g, '%20'));
criteria = criteria.trim();
}
if (criteria === '') {
criteria = 'true';
}
function testCriteria() {
let in_country = function (country) {
return window.Geo === undefined || Geo.country === country;
},
in_region = function (region) {
return window.Geo === undefined || Geo.region === region;
},
in_city = function (city) {
return window.Geo === undefined || Geo.city === city;
},
in_group = function (group) {
return $.inArray(group, mw.config.get('wgUserGroups')) > -1;
},
only_for = function (userlang) {
return userlang === mw.config.get('wgUserLanguage');
};
// FIXME: This shouldn't be using eval on data entered in wikitext. If that data is malformed it will throw an exception e.g. criteria = "(false))"
try {
return eval(criteria);
} catch (e) {
return false;
}
}
cache = testCriteria();
nt.data('asn-cache', cache);
return cache;
}
let isSetMinHeightCalled = false;
/**
* Set ASN's height to be the maximum of all entries to prevent massive layout shift when shuffling.
*/
function setMinHeight() {
if (!$nts) {
return;
}
$asnRoot.css({
'min-height': '',
});
let minHeight = -1;
$nts.each((_, nt) => {
let $nt = $(nt);
$asnBody.replaceWith($nt);
minHeight = Math.max(minHeight, $nt.height());
$nt.replaceWith($asnBody);
});
$asnRoot.css({
'min-height': `${minHeight}px`,
});
if (!isSetMinHeightCalled) {
isSetMinHeightCalled = true;
window.addEventListener('resize', mw.util.debounce(setMinHeight, 300));
}
}
function loadNotices(pos) {
if (!$asnRoot.length) {
return;
}
let nt = null;
let rt = 0;
while (rt++ < $nts.length) {
nt = $($nts[pos]);
if (matchCriteria(nt)) {
break;
}
pos = (pos + 1) % $nts.length;
}
if (rt >= $nts.length) {
return;
}
if (typeof nt.data('asn-style') === 'string') {
let style = mw.util.addCSS(decodeURIComponent(nt.data('asn-style').replace(/\+/g, '%20')));
nt.data('asn-style', null);
nt.data('asn-style-id', styles.length);
style.disabled = true;
styles.push(style);
}
if (typeof nt.data('asn-html') === 'string') {
nt.data('asn-html-raw', decodeURIComponent(nt.data('asn-html').replace(/\+/g, '%20')));
nt.data('asn-html', null);
}
let styleId = nt.data('asn-style-id');
nt = nt.data('asn-html-raw') || nt.html();
let asnBodyHtml = $asnBody.html();
if (asnBodyHtml) {
if (asnBodyHtml !== nt) {
$asnBody.stop().fadeOut(() => {
styles.forEach((style) => {
style.disabled = true;
})
if (styles[styleId]) {
styles[styleId].disabled = false;
}
$asnBody.html(nt);
// animation try /catched to avoid TypeError: (Animation.tweeners[prop]||[]).concat is not a function error being seen in production
try {
$asnBody.fadeIn();
} catch (e) { }
});
}
} else if (revisionId === cookieVal) {
return;
} else {
$.cookie(COOKIE_NAME, null);
$asnRoot.appendTo($('#siteNotice'));
if (styles[styleId]) {
styles[styleId].disabled = false;
}
setMinHeight();
$asnBody.html(nt).fadeIn();
}
timeoutId = setTimeout(() => {
loadNotices((pos + 1) % $nts.length);
}, customASNInterval * 1000);
}
new mw.Api({
ajax: {
headers: {
'Api-User-Agent': 'w:zh:MediaWiki:Gadget-AdvancedSiteNotices.js'
}
}
}).get({
page: 'Template:AdvancedSiteNotices/ajax',
variant: mw.config.get('wgUserVariant'),
prop: 'text',
action: 'parse',
format: 'json',
maxage: 3600,
smaxage: 3600
}).then((json) => {
if (!json || !json.parse || !json.parse.text || !json.parse.text['*']) return;
let $json = $('<div>').html(json.parse.text['*']).find('ul.sitents');
$nts = $('li', $json);
revisionId = $json.data('asn-version');
loadNotices(Math.floor(Math.random() * $nts.length));
}).catch((e) => {
console.error('[AdvancedSiteNotices]: error ', e);
});
});