查看“Widget:BilibiliVideo”的源代码
←
Widget:BilibiliVideo
跳转至:
导航
、
搜索
因为以下原因,您没有权限编辑本页:
您所请求的操作仅限于该用户组的用户使用:
用户
您没有权限编辑
Widget
名字空间内的页面。
您可以查看与复制此页面的源代码。
<noinclude>{{BilibiliVideo/doc/copyright}} '''本Widget不能单独使用''',请使用{{tl|BilibiliVideo}}!</noinclude><includeonly><!--{if !isset($wgBilibili) || !$wgBilibili}--><!--{assign var="wgBilibili" value=true scope="global"}--><style> .bilibili-video-container { border: 1px solid rgba(170,170,170,0.37); max-width: 100%; } .bilibili-video-container.exec { display: table; } .bilibili-iframe-container, .bilibili-video-container { display: none; } .bilibili-video-container, .bilibili-video-container .bilibili-widescreen, .bilibili-video-container iframe { max-width: 100%; background-color: #fff!important; } .bilibili-title { padding: .2em 6.5em .2em 1em; position: relative; } .bilibili-title a { word-break: break-word; } .bilibili-widescreen { position: absolute; display: none; width: 1em; right: calc(-2rem - 1px); border: 1px solid rgba(170,170,170,0.37); padding: .25rem .5rem; line-height: 1.5em; top: -2px; user-select: none; cursor: pointer; } .onshow .bilibili-widescreen{ display: block; } .bilibili-toggle { position: absolute; top: calc(50% - .5em); right: .7em; line-height: 1em; cursor: pointer; padding-left: 1em; background-image: url(/skins/Vector/images/search-ltr.png?39f97); background-image: linear-gradient(transparent,transparent), url(data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2212%22%20height%3D%2213%22%3E%3Cg%20stroke-width%3D%222%22%20stroke%3D%22%236c6c6c%22%20fill%3D%22none%22%3E%3Cpath%20d%3D%22M11.29%2011.71l-4-4%22%2F%3E%3Ccircle%20cx%3D%225%22%20cy%3D%225%22%20r%3D%224%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E); background-image: linear-gradient(transparent,transparent), url(/skins/Vector/images/search-ltr.svg?07752)!ie; background-image: -o-linear-gradient(transparent,transparent), url(/skins/Vector/images/search-ltr.png?39f97); background-position: left center; background-repeat: no-repeat; } .bilibili-toggle:hover { color: #36b; } .bilibili-video-button, .bilibili-video-button:visited { display: inline-block; margin: 4px 5px; padding: 10px 25px; font-size: 14px; text-align: center; color: #fff; background: #de698c; border-radius: 4px; } .bilibili-iframe-container { padding: 6px; position: relative; border: 0 solid rgba(170,170,170,0.37); border-top-width: 1px; } .bilibili-video-container:not([data-max-width]) .bilibili-iframe-container { max-width: calc(100% - 12px)!important; } .bilibili-video-container:not([data-max-width]).onshow .bilibili-iframe-container { max-height: calc(100% - 27px)!important; } .bilibili-video-container textarea { background: white; color: black; width: 80%; margin: auto; } .bilibili-iframe-overlay { width: 0; height: 0; padding-top: 30%; text-align: center; box-sizing: border-box; background: rgb(167, 215, 249); position: absolute; top: 3px; left: 6px; z-index: 2; } .bilibili-iframe-retry-link { position: absolute; top: 10px; right: 10px; display: none; background: white; padding: 0px 0.5em; } html > body > .navpopup .bilibili-video-container > * { display: none !important; } html > body > .navpopup .bilibili-video-container::before { content: "请不要在注释里使用 BilibiliVideo 模板"; font-style: italic; } </style><script> "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") === "minerva") { 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://player.bilibili.com/player.html?as_wide=1&high_quality=1&"; 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 */ } }); </script><!--{/if}--></includeonly>
该页面使用的模板:
模板:BilibiliVideo/doc/copyright
(
查看源代码
)
模板:Tl
(
查看源代码
)
模板:胡话
(
查看源代码
)
返回至
Widget:BilibiliVideo
。
导航菜单
个人工具
登录
名字空间
Widget
讨论
变种
视图
阅读
查看源代码
查看历史
更多
搜索
导航
首页
随机页面
最近更改
最新文件
常用
上传多个文件
工具
链入页面
相关更改
特殊页面
页面信息