欢迎来到纸飞机Wiki !
纸飞机Wiki目前包含43个页面,303次编辑,6个用户。
MediaWiki:Common.js
来自纸飞机Wiki
注意:在发布之后,您可能需要清除浏览器缓存才能看到所作出的变更的影响。
- Firefox或Safari:按住Shift的同时单击刷新,或按Ctrl-F5或Ctrl-R(Mac为⌘-R)
- Google Chrome:按Ctrl-Shift-R(Mac为⌘-Shift-R)
- Internet Explorer或Edge:按住Ctrl的同时单击刷新,或按Ctrl-F5
- Opera:按 Ctrl-F5。
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */
console.log("欢迎来到纸飞机Wiki")
"use strict";
window.RLQ.push(async () => {
const errMsg = {
id: '此处填写的id有误,请参考<a href="https://zh.moegirl.org.cn/Template:BilibiliVideo#firstHeading" target="_blank">模板文档</a>修正……',
error: "执行出现问题,请复制以下内容并在提问求助区处粘贴寻求帮助:$$$",
attr: '下方填写的参数 $$$ 有误,请参考<a href="https://zh.moegirl.org.cn/Template:BilibiliVideo#firstHeading" target="_blank">模板文档</a>修正……',
};
await $.ready;
const ifNamespaceAllow = [0, 4, 10, 12].includes(mw.config.get("wgNamespaceNumber"));
const sanNode = $(`<${"span/"}>`);
const genErr = (type, msg = "") => type in errMsg ? `<${"div"} style="font-style: italic; border: 1px dashed red;">BilibiliVideo模板:${errMsg[type].replace("$$$", sanNode.text(msg).html())}<${"/div"}>` : "";
const injectErrMsgBefore = ($ele, type, msg = "") => $ele.before(genErr(type, msg));
const getErrorType = (code) => {
switch (code) {
case 62003: {
return false;
}
case -403: {
return "forbidden";
}
default: {
return "failed";
}
}
};
try {
const isNaN = Number.isNaN || window.isNaN;
const cssLengthUnitValidator = (length, defaultValue, callback, paramName, $ele) => {
if (typeof length !== "string" || length.length === 0) {
callback(false);
return defaultValue;
}
const parsedNumber = parseFloat(length.replace(/[a-z]+/i, ""));
if (isNaN(parsedNumber) || parsedNumber <= 0) {
callback(false);
injectErrMsgBefore($ele, "attr", paramName);
return defaultValue;
}
if (/^(?:\d+|\d*\.\d+)(?:em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|Q|in|pc|pt|px|%)$/.test(length)) {
callback(true);
return length;
}
if (/^(?:\d+|\d*\.\d+)$/.test(length)) {
callback(true);
return `${length}px`;
}
callback(false);
injectErrMsgBefore($ele, "attr", paramName);
return defaultValue;
};
const fixedNumber = (number) => `${+number < 10 ? "0" : ""}${number}`;
const secondsParser = (seconds) => `${Math.floor(+seconds / 60)}:${fixedNumber(+seconds % 60)}`;
const idCorrector = (id) => {
if (/^(?:av)?\d{1,9}$/i.test(id)) {
return {
id: id.replace(/^av/i, ""),
prefix: {
href: "av",
iframe: "aid",
},
};
} else if (/^(?:(?:[bB][vV])?1)?[fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF]{9}$/.test(id)
&& /4.1.7..$/.test(id)) {
return {
id: id.replace(/^.*([fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF]{9})$/i, "1$1"),
prefix: {
href: "BV",
iframe: "bvid",
},
};
}
return false;
};
const submit = (ids) => {
if (!ifNamespaceAllow) {
return;
}
if (--ids.pending > 0) {
return;
}
let changed = false;
if (ids.failed.aid.size + ids.failed.bvid.size > 0 && !mw.config.get("wgCategories").includes("带有失效视频的条目")) {
changed = true;
}
if (ids.forbidden.aid.size + ids.forbidden.bvid.size > 0 && !mw.config.get("wgCategories").includes("带有受限视频的条目")) {
changed = true;
}
if (ids.failed.aid.size + ids.failed.bvid.size === 0 && mw.config.get("wgCategories").includes("带有失效视频的条目")) {
changed = true;
}
if (ids.forbidden.aid.size + ids.forbidden.bvid.size === 0 && mw.config.get("wgCategories").includes("带有受限视频的条目")) {
changed = true;
}
if (changed) {
const url = new URL("https://moegirlpedia.annangela.cn/bilibiliCollector/videoCheck");
url.searchParams.set("pageid", mw.config.get("wgArticleId"));
$.get(`${url}`);
}
};
if (mw.config.get("skin") === "MoeMobileSkin") {
const ids = {
failed: {
aid: new Set(),
bvid: new Set(),
},
forbidden: {
aid: new Set(),
bvid: new Set(),
},
pending: 0,
};
const targets = $(".bilibili-video-container:not(.bilibili-video-initialized)");
ids.pending = targets.length;
targets.each((_, ele) => {
const element = $(ele),
dataset = ele.dataset;
element.addClass("bilibili-video-initialized");
const _id = dataset.id,
title = dataset.title,
pagename = dataset.pagename,
t = parseInt(dataset.t),
tIsInvalid = isNaN(t) || t <= 0,
subtitle = dataset.subtitle === "true" ? true : false;
let page = parseInt(dataset.page);
if (isNaN(page) || page < 1) {
page = 1;
if (typeof dataset.page === "string" && dataset.page !== "") {
injectErrMsgBefore(element, "attr", "page");
}
}
if ((isNaN(t) || t <= 0) && typeof dataset.t === "string" && dataset.t !== "") {
injectErrMsgBefore(element, "attr", "t");
}
const validation = idCorrector(_id);
let id,
prefix;
if (validation) {
id = validation.id;
prefix = validation.prefix;
} else {
ele.outerHTML = genErr("id");
return;
}
ele.innerText = "正在加载中,若长时间空白则说明是网络问题……";
$.ajax({
url: `https://api.bilibili.com/x/web-interface/view?${prefix.iframe}=${id}&jsonp=jsonp`,
type: "GET",
dataType: "jsonp",
timeout: 10000,
success: function ({ code, message, data }) {
if (code !== 0) {
element.before($("<a/>").addClass("bilibili-video-button").attr("rel", "nofollow noreferrer noopener").attr("href", `https://www.bilibili.com/video/${prefix.href}${id}?p=${page}${tIsInvalid ? "" : `&t=${t}`}`).text((title || prefix.href + id) + (![0, 1].includes(page) && !isNaN(page) ? ` (P${page})` : ""))).remove();
console.info("Widget:BilibiliVideo", `${prefix.href}${id}`, code, message);
const errorType = getErrorType(code);
if (errorType) {
ids[errorType][prefix.iframe].add(id);
}
return;
}
const list = data.pages;
let _page = 1;
const name = title || (data.title ? data.title : prefix.href + id);
let index;
let length;
if (pagename) {
for (index = 0, length = list.length; index < length; index++) {
if (list[index].part !== pagename) { continue; }
_page = list[index].page;
break;
}
} else { _page = page; }
index = _page - 1;
const time = secondsParser(t);
const button = $("<a/>").addClass("bilibili-video-button").attr("rel", "nofollow noreferrer noopener").attr("href", `https://www.bilibili.com/video/${prefix.href}${id}?p=${_page}${tIsInvalid ? "" : `&t=${t}`}`).text(`${name} [${_page}/${secondsParser(list[index].duration)}]${tIsInvalid ? "" : `[跳转至${time}]`}`);
if (list[index] !== undefined && list[index].cid !== undefined && subtitle) {
button.append(`<br>(${_page}、${list[index].part})`);
}
element.before(button).remove();
},
error: function () {
element.before($("<a/>").addClass("bilibili-video-button").attr("rel", "nofollow noreferrer noopener").attr("href", `https://www.bilibili.com/video/${prefix.href}${id}?p=${page}${tIsInvalid ? "" : `&t=${t}`}`).text((title || prefix.href + id) + (![0, 1].includes(page) && !isNaN(page) ? ` (P${page})` : ""))).remove();
},
complete: () => {
submit(ids);
},
});
});
}
else {
const global_element = $("#mw-content-text");
const placeholderToggle = (iframe) => {
if (iframe.data("displayFlag")) {
iframe.data("displayFlag", false);
iframe.data("placeholder").fadeOut(370);
}
};
let lazyLoadObserver;
if ("IntersectionObserver" in window &&
"IntersectionObserverEntry" in window &&
"intersectionRatio" in window.IntersectionObserverEntry.prototype &&
"isIntersecting" in window.IntersectionObserverEntry.prototype) {
lazyLoadObserver = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.src = entry.target.dataset.src;
setTimeout(() => {
placeholderToggle($(entry.target));
}, 13070);
lazyLoadObserver.unobserve(entry.target);
}
});
});
} else {
lazyLoadObserver = {
observe: (target) => {
target.src = target.dataset.src;
setTimeout(() => {
placeholderToggle($(target));
}, 13070);
},
};
}
const iframe_href_base = "https://www.bilibili.com/blackboard/newplayer.html?playlist=true&playlist_order=sequential&musth5=1&noEndPanel=1&crossDomain=1&autoplay=0&";
const EPSILON = 2.220446049250313e-16,
rememberWH = function rememberWH(ele) {
ele.data({ width: ele.width(), height: ele.height() });
},
setTureHeight = function setTureHeight(ele) {
const barHeight = ele.data("height") - ele.data("width") * 9 / 16; //计算标题和播放器控制栏高度
ele.height(ele.width() * 9 / 16 + barHeight);
},
setWH = function setWH(ele) {
ele.css({ width: "100%", height: "100%" });
},
recallWH = function recallWH(ele) {
ele.width(ele.data("width")).height(ele.data("height"));
},
setMaxHeight = function setMaxHeight(container, target) {
const h = container.outerHeight(true);
let t = 0;
container.children().each((_, ele) => {
t += $(ele).outerHeight(true);
});
target.css("max-height", `calc(100% - ${parseInt(t - h + 2 - (Number.EPSILON || EPSILON))}px)`);
};
const run = () => {
const ids = {
failed: {
aid: new Set(),
bvid: new Set(),
},
forbidden: {
aid: new Set(),
bvid: new Set(),
},
pending: 0,
};
const targets = $(".bilibili-video-container:not(.exec)");
ids.pending = targets.length;
targets.addClass("exec").each((_, ele) => {
const dataset = ele.dataset;
const _id = dataset.id;
const selfbox = $(ele);
const toggleButton = selfbox.find(".bilibili-toggle");
const widescreenButton = selfbox.find(".bilibili-widescreen");
const validation = idCorrector(_id);
let id,
prefix;
if (validation) {
id = validation.id;
prefix = validation.prefix;
} else {
ele.outerHTML = genErr("id");
return;
}
let page = parseInt(+(dataset.page || 1));
if (isNaN(page) || page < 1) {
page = 1;
if (typeof dataset.page === "string" && dataset.page !== "") {
injectErrMsgBefore(selfbox, "attr", "page");
}
}
const pagename = dataset.pagename;
const title = dataset.title;
const height = cssLengthUnitValidator(dataset.height, "441px", (isValidated) => isValidated || selfbox.removeAttr("data-height"), "height", selfbox);
const width = cssLengthUnitValidator(dataset.width, "665px", (isValidated) => isValidated || selfbox.removeAttr("data-width"), "width", selfbox);
const maxHeight = cssLengthUnitValidator(dataset.maxHeight, "100vh", (isValidated) => isValidated || selfbox.removeAttr("data-max-height"), "maxHeight", selfbox);
const maxWidth = cssLengthUnitValidator(dataset.maxWidth, "100%", (isValidated) => isValidated || selfbox.removeAttr("data-max-width"), "maxWidth", selfbox);
const subtitle = dataset.subtitle === "true" ? true : false;
const t = parseInt(dataset.t);
const tIsInvalid = isNaN(t) || t <= 0;
const iframeContainer = selfbox.find(".bilibili-iframe-container");
const title_text = $("<a/>").attr("rel", "nofollow noreferrer noopener").addClass("external text").attr({
href: `https://www.bilibili.com/video/${prefix.href}${id}?p=${page}${tIsInvalid ? "" : `&t=${t}`}`,
target: "_blank",
}).prependTo(selfbox.find(".bilibili-title"));
const iframe = $("<iframe/>").attr({
allow: "fullscreen",
allowfullscreen: true,
frameborder: 0,
scrolling: "no",
src: "",
"class": "bilibili-iframe",
}).css({
width: width,
height: height,
"max-width": maxWidth,
"max-height": maxHeight,
});
if (!tIsInvalid) {
selfbox.removeAttr("data-auto-expand");
} else if (typeof dataset.t === "string" && dataset.t !== "") {
injectErrMsgBefore(selfbox, "attr", "t");
}
const time = secondsParser(t);
title_text.text(`${(title || prefix.href + id) + (![0, 1].includes(page) ? ` (P${page})` : "") + (tIsInvalid ? "" : `[视频从${time}开始播放]`)}【视频信息加载中……】`);
iframeContainer.css({
width: width,
height: height,
"max-width": maxWidth,
"max-height": maxHeight,
});
iframe.appendTo(iframeContainer);
const div = $("<div/>");
div.css({
position: "absolute",
top: "0",
left: "0",
bottom: "0",
right: "0",
"z-index": "99",
display: "flex",
"align-items": "center",
background: "rgba(255, 255, 255, .37)",
});
const text = $("<div/>");
text.css({
"text-align": "center",
width: "100%",
}).text("正在加载中,若长时间空白则说明是网络问题……");
div.append(text).appendTo(iframeContainer);
iframe.data({
placeholder: div,
displayFlag: true,
});
iframe[0].addEventListener("load", () => {
placeholderToggle(iframe);
});
$.ajax({
url: `https://api.bilibili.com/x/web-interface/view?${prefix.iframe}=${id}&jsonp=jsonp`,
type: "GET",
dataType: "jsonp",
timeout: 10000,
success: function ({ code, message, data }) {
if (code !== 0) {
title_text.text((title || prefix.href + id) + (![0, 1].includes(page) ? ` (P${page})` : "") + (tIsInvalid ? "" : `[视频从${time}开始播放]`));
iframe.attr("data-src", `${iframe_href_base + prefix.iframe}=${id}&page=${page}${tIsInvalid ? "" : `&t=${t}`}`);
lazyLoadObserver.observe(iframe[0]);
console.info("Widget:BilibiliVideo", `${prefix.href}${id}`, code, message);
const errorType = getErrorType(code);
if (errorType) {
ids[errorType][prefix.iframe].add(id);
}
return;
}
const list = data.pages;
let _page = 1;
const name = title || (data.title ? data.title : prefix.href + id);
let index;
let length;
if (pagename) {
for (index = 0, length = list.length; index < length; index++) {
if (list[index].part !== pagename) { continue; }
_page = list[index].page;
break;
}
} else { _page = page; }
index = _page - 1;
const href = title_text.attr("href");
if (list[index] !== undefined && list[index].cid !== undefined) {
iframe.attr("data-src", `${iframe_href_base}${prefix.iframe}=${id}&cid=${list[index].cid}&page=${_page}${tIsInvalid ? "" : `&t=${t}`}`);
title_text.attr("href", href.replace(new RegExp(`\\?p=${page}`, "g"), `?p=${_page}`));
title_text.text(`${name} [${_page}/${list.length}]${tIsInvalid ? "" : `[视频从${time}开始播放]`}`);
if (subtitle) { title_text.append(`<br>(${_page}、${list[index].part})`); }
} else {
title_text.text(name + (tIsInvalid ? "" : `[视频从${time}开始播放]`));
iframe.attr("data-src", `${iframe_href_base + prefix.iframe}=${id}&page=${_page}${tIsInvalid ? "" : `&t=${t}`}`);
}
lazyLoadObserver.observe(iframe[0]);
},
error: function () {
title_text.text((title || prefix.href + id) + (![0, 1].includes(page) ? ` (P${page})` : "") + (tIsInvalid ? "" : `[视频从${time}开始播放]`));
iframe.attr("data-src", `${iframe_href_base + prefix.iframe}=${id}&page=${page}${tIsInvalid ? "" : `&t=${t}`}`);
lazyLoadObserver.observe(iframe[0]);
},
complete: function () {
if (selfbox.is('[data-auto-expand="true"]')) {
selfbox.addClass("onshow");
iframeContainer.show();
toggleButton.text("隐藏视频");
selfbox.removeAttr("style");
}
submit(ids);
},
});
//toggle
toggleButton.on("click", () => {
selfbox.width(iframeContainer.outerWidth(true));
selfbox.toggleClass("onshow");
iframeContainer.toggle();
if (toggleButton.text() === "显示视频") {
toggleButton.text("隐藏视频");
$(window).resize();
} else {
toggleButton.text("显示视频");
selfbox.removeAttr("style");
}
});
widescreenButton.on("click", () => {
if (selfbox.is(":not(.onshow)")) { return; }
if (selfbox.is(".widescreen")) {
selfbox.removeClass("widescreen");
widescreenButton.text("显示宽屏");
recallWH(iframeContainer);
recallWH(iframe);
recallWH(selfbox);
} else {
selfbox.addClass("widescreen");
widescreenButton.text("退出宽屏");
rememberWH(selfbox);
selfbox.css("width", selfbox.parent().width() > Math.min(911, global_element.width()) ? "73%" : "100%"); //可以看见按钮的最小宽度 665 的 1/0.73 倍
setTureHeight(selfbox);
rememberWH(iframe);
rememberWH(iframeContainer);
setWH(iframe);
setWH(iframeContainer);
iframeContainer.height(selfbox.height() - title_text.parent().height());
setMaxHeight(selfbox, iframeContainer);
}
});
});
};
$(run);
mw.hook("wikipage.content").add(run);
$(window).on("load", run);
$(window).on("resize", () => {
$(".bilibili-video-container.onshow.widescreen").each((_, ele) => {
const selfbox = $(ele);
selfbox.css("width", selfbox.parent().width() > Math.min(911, global_element.width()) ? "73%" : "100%");
setTureHeight(selfbox);
setMaxHeight(selfbox, selfbox.find(".bilibili-iframe-container"));
});
});
}
} catch (e) {
/* eslint-disable */
var msg = genErr("error", navigator.userAgent + " : " + e + " " + e.stack.split("\n")[1].trim());
$(".bilibili-video-container").each(function (_, ele) {
ele.outerHTML = msg;
});
/* eslint-enable */
}
});
