// ==UserScript==
// @name 哔哩哔哩视频页面常驻显示AV/BV号[已完全重构,支持显示分P标题]
// @namespace ckylin-bilibili-display-video-id
// @version 1.14
// @description 完全自定义你的视频标题下方信息栏,排序,增加,删除!
// @author CKylinMC
// @match https://www.bilibili.com/video*
// @match https://www.bilibili.com/medialist/play/*
// @resource cktools https://greasyfork.org/scripts/429720-cktools/code/CKTools.js?version=967994
// @resource popjs https://cdn.jsdelivr.net/gh/CKylinMC/PopNotify.js@master/PopNotify.js
// @resource popcss https://cdn.jsdelivr.net/gh/CKylinMC/PopNotify.js@master/PopNotify.css
// @resource timeago https://unpkg.com/timeago.js@4.0.2/dist/timeago.min.js
// @grant unsafeWindow
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_getResourceText
// @grant GM_registerMenuCommand
// @grant GM_unregisterMenuCommand
// @license GPL-3.0-only
// @downloadURL none
// ==/UserScript==
(function () {
//======[Apply all resources]
const resourceList = [
{ name: 'cktools', type: 'js' },
{ name: 'timeago', type: 'js' },
{ name: 'popjs', type: 'js' },
{ name: 'popcss', type: 'css' },
{ name: 'popcsspatch', type: 'rawcss', content: "div.popNotifyUnitFrame{z-index:110000!important;}.CKTOOLS-modal-content{color: #616161!important;max-height: 80vh;overflow: auto;}" },
]
function applyResource() {
resloop: for (let res of resourceList) {
if (!document.querySelector("#" + res.name)) {
let el;
switch (res.type) {
case 'js':
case 'rawjs':
el = document.createElement("script");
break;
case 'css':
case 'rawcss':
el = document.createElement("style");
break;
default:
console.log('Err:unknown type', res);
continue resloop;
}
el.id = res.name;
el.innerHTML = res.type.startsWith('raw') ? res.content : GM_getResourceText(res.name);
document.head.appendChild(el);
}
}
}
applyResource();
//======
const wait = (t) => new Promise(r => setTimeout(r, t));
const waitForPageVisible = async () => {
return document.hidden && new Promise(r => document.addEventListener("visibilitychange", r))
}
const log = (...m) => console.log('[ShowAV]', ...m);
const getAPI = (bvid) => fetch('https://api.bilibili.com/x/web-interface/view?bvid=' + bvid).then(raw => raw.json());
const getAidAPI = (aid) => fetch('https://api.bilibili.com/x/web-interface/view?aid=' + aid).then(raw => raw.json());
const config = {
defaultAv: true,
hideTime: false,
firstTimeLoad: true,
defaultTextTime: true,
foldedWarningTip: true,
showInNewLine: false,
pnmaxlength: 18,
orders: ['openGUI', 'showPic', 'showAv', 'showPn'],
all: ['showAv', 'showSAv', 'showSBv', 'showPn', 'showCid', 'showCate', 'openGUI', 'showPic', 'showSize', 'showMore', 'showCTime', 'showViews', 'showDmk', 'showTop'],
copyitems: ['currTime', 'short', 'shareTime', 'vid'],
copyitemsAll: ['curr', 'currTime', 'short', 'share', 'shareTime', 'md', 'bb', 'html', 'vid'],
customcopyitems: {},
vduration: 0
};
const menuId = {
defaultAv: -1,
foldedWarningTip: -1,
showInNewLine: -1,
};
const txtCn = {
showAv: "可切换视频编号和高级复制",
showSAv: "视频AV号和高级复制",
showSBv: "视频BV号和高级复制",
showPn: "视频分P名",
showCid: "视频CID编号",
showCate: "视频所在分区",
showPic: "视频封面",
showSize: "视频分辨率",
showMore: "更多信息",
showCTime: "视频投稿时间",
showViews: "替换视频播放量",
showDmk: "替换视频弹幕量",
showTop: "替换全站排名提示",
curr: "当前视频地址",
currTime: "当前视频地址(含视频进度)",
short: "短地址",
share: "快速分享",
shareTime: "快速分享(含视频进度)",
md: "Markdown 格式",
bb: "BBCode 格式",
html: "HTML 格式",
vid: "视频编号",
openGUI: "设置选项"
};
const descCn = {
showAv: "展示视频号(AV号/BV号可切换),右键单击可以切换,左键单击快速复制(包含当前播放时间),左键长按打开更多格式复制窗口",
showSAv: "展示视频AV号,右键单击可以切换,左键单击快速复制(包含当前播放时间),左键长按打开更多格式复制窗口",
showSBv: "展示视频BV号,右键单击可以切换,左键单击快速复制(包含当前播放时间),左键长按打开更多格式复制窗口",
showPn: "展示视频分P信息以及缓存名(分P名)。可能较长,建议放在最下面,并调整最大长度。",
showCid: "展示视频资源CID编号,通常不需要展示。",
showCate: "展示视频所在的子分区。",
showPic: "提供按钮一键查看封面,长按可以在新标签页打开大图。",
showSize: "展示视频当前分辨率(宽高信息)。",
showMore: "查看视频更多信息。",
showCTime: "用文字方式描述投稿时间,如:一周前",
showViews: "替换展示视频播放量(由于内容相同,将自动隐藏原版播放量信息)",
showDmk: "替换展示视频弹幕量(由于内容相同,将自动隐藏原版弹幕量信息)",
showTop: "替换原版全站排名信息",
curr: "提供当前视频纯净地址",
currTime: "提供当前视频地址,并在播放时提供含跳转时间的地址(可以直接跳转到当前进度)。",
short: "提供当前视频的b23.tv短地址",
share: "提供当前视频的标题和地址组合文本。",
shareTime: "提供当前视频的标题和地址组合文本,在播放时提供含跳转时间的地址(可以直接跳转到当前进度)。",
md: "提供Markdown特殊语法的快速复制。",
bb: "提供BBCode特殊语法的快速复制。",
html: "提供HTML格式的快速复制。",
vid: "提供当前视频av号/BV号/CID号",
openGUI: "提供按钮快速进入设置选项。"
};
const idTn = {
showAv: 2,
showSAv: 2,
showSBv: 2,
showPn: 5,
showCid: 2,
showCate: 3,
showPic: 1,
showSize: 2,
showMore: 1,
showCTime: -4,
showViews: -2,
showDmk: -2,
showTop: 0,
openGUI: 1
};
let infos = {};
// https://stackoverflow.com/questions/10726638
String.prototype.mapReplace = function (map) {
var regex = [];
for (var key in map)
regex.push(key.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"));
return this.replace(new RegExp(regex.join('|'), "g"), function (word) {
return map[word];
});
};
// CSDN https://blog.csdn.net/namechenfl/article/details/91968396
function numberFormat(value) {
let param = {};
let k = 10000,
sizes = ['', '万', '亿', '万亿'],
i;
if (value < k) {
param.value = value
param.unit = ''
} else {
i = Math.floor(Math.log(value) / Math.log(k));
param.value = ((value / Math.pow(k, i))).toFixed(2);
param.unit = sizes[i];
}
return param;
}
async function saveAllConfig() {
for (let configKey of Object.keys(config)) {
if ([
"all", "vduration", "firstTimeLoad"
].includes(configKey)) continue;
await GM_setValue(configKey, config[configKey]);
}
popNotify.success("配置保存成功");
}
async function initScript(flag = false) {
for (let menuitem of Object.keys(menuId)) {
if (menuId[menuitem] != -1) GM_unregisterMenuCommand(menuId[menuitem]);
}
for (let configKey of Object.keys(config)) {
if ([
"all", "vduration", "firstTimeLoad"
].includes(configKey)) continue;
if (typeof (await GM_getValue(configKey)) === 'undefined') {
await GM_setValue(configKey, config[configKey]);
} else {
config[configKey] = await GM_getValue(configKey);
}
}
GM_registerMenuCommand("打开设置", async () => {
await GUISettings();
});
CKTools.addStyle(`
#bilibiliShowPN{
max-width: ${config.pnmaxlength}em!important;
}
`, "showav_pnlen", "update", document.head);
tryInject(flag);
}
async function playerReady() {
let i = 150;
while (--i > 0) {
await wait(100);
if (!('player' in unsafeWindow)) continue;
if (!('isInitialized' in unsafeWindow.player)) continue;
if (!unsafeWindow.player.isInitialized()) continue;
break;
}
if (i < 0) return false;
await waitForPageVisible();
while (1) {
await wait(200);
if (document.querySelector(".bilibili-player-video-control-wrap")) return true;
}
}
async function waitForDom(q) {
let i = 50;
let dom;
while (--i >= 0) {
if (dom = document.querySelector(q)) break;
await wait(100);
}
return dom;
}
function getUrlParam(key) {
return (new URL(location.href)).searchParams.get(key);
}
function getOrNew(id, parent,) {
let marginDirection = config.showInNewLine ? "Right" : "Left";
let target = document.querySelector("#" + id);
if (!target) {
target = document.createElement("span");
target.id = id;
target.style['margin' + marginDirection] = "16px";
parent.appendChild(target);
}
return target;
}
async function getPlayerSeeks() {
const video = await waitForDom(".bilibili-player-video video");
let seconds = 0;
if (video) {
seconds = Math.floor(video.currentTime);
}
if (seconds == 0) {
let fromParam = getUrlParam("t") || 0;
return fromParam;
} else return seconds;
}
async function registerVideoChangeHandler() {
const video = await waitForDom(".bilibili-player-video video");
if (!video) return;
const observer = new MutationObserver(async e => {
if (e[0].target.src) {
tryInject(true);
}
});
observer.observe(video, { attribute: true, attributes: true, childList: false });
}
function getPageFromCid(cid, infos) {
if (!cid || !infos || !infos.pages) return 1;
let pages = infos.pages;
if (pages.length == 1) return 1;
let page;
for (page of pages) {
if (!page) continue;
if (page.cid == cid) return page.page;
}
return 1;
}
async function feat_showCate() {
const { av_root, infos } = this;
const cate_span = getOrNew("bilibiliShowCate", av_root);
//if (config.showCate) {
cate_span.style.textOverflow = "ellipsis";
cate_span.style.whiteSpace = "nowarp";
cate_span.style.overflow = "hidden";
cate_span.title = "分区:" + infos.tname;
cate_span.innerText = "分区:" + infos.tname;
//} else cate_span.remove();
}
async function feat_showStaticAv() {
const func = feat_showAv.bind(this);
func(true);
}
async function feat_showStaticBv() {
const func = feat_showAv.bind(this);
func(true, 'bv');
}
async function feat_showAv(force = false, mode = 'av'/* 'bv' */) {
const { av_root, infos } = this;
const av_span = getOrNew("bilibiliShowAV" + (force ? mode : ''), av_root);
//if (config.showAv) {
if (force) {
if (mode == 'bv') {
av_span.innerText = infos.bvid;
} else {
av_span.innerText = 'av' + infos.aid;
}
} else if (config.defaultAv)
av_span.innerText = 'av' + infos.aid;
else
av_span.innerText = infos.bvid;
av_span.style.overflow = "hidden";
const video = await waitForDom("video");
if (video) {
config.vduration = Math.floor(video.duration);
}
if (av_span.getAttribute("setup") != "ok") {
if (!force)
av_span.oncontextmenu = e => {
if (e.target.innerText.startsWith('av')) e.target.innerText = infos.bvid;
else av_span.innerText = 'av' + infos.aid;
e.preventDefault();
}
const avspanHC = new CKTools.HoldClick(av_span);
avspanHC.onclick(async e => {
const currpage = new URL(location.href);
let part = infos.p==currpage.searchParams.get("p")
? infos.p
: (currpage.searchParams.get("p") ? currpage.searchParams.get("p") : infos.p);
let url = new URL(location.protocol + "//" + location.hostname + "/video/" + e.target.innerText);
part == 1 || url.searchParams.append("p", part);
let t = await getPlayerSeeks();
if (t && t != "0" && t != ("" + config.vduration)) url.searchParams.append("t", t);
copy(url);
popNotify.success("完整地址复制成功", url);
});
avspanHC.onhold(async e => {
let url = new URL(location.protocol + "//" + location.hostname + "/video/" + e.target.innerText);
infos.p == 1 || url.searchParams.append("p", infos.p);
let vidurl = new URL(url);
let shorturl = new URL(location.protocol + "//b23.tv/" + e.target.innerText);
let t = await getPlayerSeeks();
if (t && t != "0" && t != ("" + config.vduration)) url.searchParams.append("t", t);
let modalcontent = `
点击输入框可以快速复制
`;
for (let copyitem of config.copyitems) {
switch (copyitem) {
case "curr":
modalcontent += `当前地址
`;
break;
case "currTime":
modalcontent += `含视频进度地址(仅在播放时提供)
`;
break;
case "short":
modalcontent += `短地址格式
`;
break;
case "share":
modalcontent += `快速分享
`;
break;
case "shareTime":
modalcontent += `快速分享(含视频进度)
`;
break;
case "md":
modalcontent += `MarkDown格式
`;
break;
case "bb":
modalcontent += `BBCode格式
`;
break;
case "html":
modalcontent += `HTML格式
`;
break;
case "vid":
modalcontent += `
`;
break;
default:
if (Object.keys(config.customcopyitems).includes(copyitem)) {
let ccopyitem = config.customcopyitems[copyitem];
let pat = ccopyitem.content ? ccopyitem.content : "无效内容";
pat = pat.mapReplace({
"%timeurl%": url,
"%vidurl%": vidurl,
"%shorturl%": shorturl,
"%seek%": t,
"%title%": infos.title,
"%av%": infos.aid,
"%bv%": infos.bvid,
"%cid%": infos.cid,
"%p%": part,
"'": "\'"
});
modalcontent += `(自定义) ${ccopyitem.title}
`;
}
}
}
modalcontent += `
⚙ 复制设置
缺少你需要的格式?反馈来添加...
`;
modalcontent+= closeButton().outerHTML;
CKTools.modal.alertModal("高级复制", modalcontent, "关闭");
});
av_span.setAttribute("setup", "ok");
}
//} else av_span.remove();
}
async function feat_showMore() {
const { av_root, infos } = this;
log('infos', infos);
const more_span = getOrNew("bilibiliShowMore", av_root);
more_span.innerHTML = '⋯';
more_span.title = "展示更多信息";
more_span.style.cursor = "pointer";
if (more_span.getAttribute("setup") != "ok") {
more_span.addEventListener('click', async e => {
let part, videoData = infos;
try {
part = videoData.pages[infos.p - 1];
} catch (e) {
part = videoData.pages[0];
}
let currentPageName = part.part.length ? part.part : '';
let currentPageNum;
if (videoData.videos != 1) {
currentPageNum = `P ${infos.p}/${videoData.videos}`;
} else {
currentPageNum = "P 1/1";
}
CKTools.modal.alertModal("视频信息", `
AV号: av${infos.aid}
BV号: ${infos.bvid}
CID: ${infos.cid}
分P: ${currentPageNum}
P名: ${currentPageName}
长度: ${infos.duration}s
投稿: ${timeago.format(infos.ctime * 1000, 'zh_CN')}
分区: ${infos.tname}
大小: ${infos.dimension.width}x${infos.dimension.height}
封面: 点击查看
`, "确定");
})
more_span.setAttribute("setup", "ok");
}
}
async function feat_showCTime() {
const { av_root, infos } = this;
const ct_span = getOrNew("bilibiliShowCTime", av_root);
ct_span.style.textOverflow = "ellipsis";
ct_span.style.whiteSpace = "nowarp";
ct_span.style.overflow = "hidden";
const d = new Date(infos.ctime * 1000);
let txttime = timeago.format(infos.ctime * 1000, 'zh_CN');
let rawtime = `${d.getFullYear()}-${(d.getMonth() + 1) < 10 ? '0' + (d.getMonth() + 1) : d.getMonth() + 1}-${d.getDate() < 10 ? '0' + d.getDate() : d.getDate()} ${d.getHours() < 10 ? '0' + d.getHours() : d.getHours()}:${d.getMinutes() < 10 ? '0' + d.getMinutes() : d.getMinutes()}:${d.getSeconds() < 10 ? '0' + d.getSeconds() : d.getSeconds()}`;
ct_span.title = "投稿时间 " + (config.defaultTextTime ? rawtime : txttime);
ct_span.innerHTML = config.defaultTextTime ? txttime : rawtime
if (config.hideTime) ct_span.innerHTML += `
`;
}
async function feat_showViews() {
const { av_root, infos } = this;
const v_span = getOrNew("bilibiliShowViews", av_root);
v_span.style.textOverflow = "ellipsis";
v_span.style.whiteSpace = "nowarp";
v_span.style.overflow = "hidden";
v_span.title = `播放量 ${infos.stat.view}`;
v_span.innerHTML = (() => {
const res = numberFormat(infos.stat.view);
return `${res.value}${res.unit}播放`;
})();
v_span.innerHTML += `
`;
}
async function feat_showDmk() {
const { av_root, infos } = this;
const dmk_span = getOrNew("bilibiliShowDmk", av_root);
dmk_span.style.textOverflow = "ellipsis";
dmk_span.style.whiteSpace = "nowarp";
dmk_span.style.overflow = "hidden";
dmk_span.title = `${infos.stat.danmaku}条弹幕`;
dmk_span.innerHTML = (() => {
const res = numberFormat(infos.stat.danmaku);
return `${res.value}${res.unit}条弹幕`;
})();
dmk_span.innerHTML += `
`;
}
async function feat_showTop() {
const { av_root, infos } = this;
const top_span = getOrNew("bilibiliShowTop", av_root);
top_span.style.textOverflow = "ellipsis";
top_span.style.whiteSpace = "nowarp";
top_span.style.overflow = "hidden";
top_span.title = `全站最高排行第${infos.stat.his_rank}名`;
top_span.innerHTML = ''
top_span.innerHTML += `
`;
if (infos.stat.his_rank === 0) {
top_span.style.display = "none";
setTimeout(() => {
if (top_span.nextElementSibling) {
top_span.nextElementSibling.style.marginLeft = 0;
}
}, 100);
} else {
top_span.innerHTML += '📊 ' + infos.stat.his_rank;
}
}
async function feat_showPic() {
const { av_root, infos } = this;
const pic_span = getOrNew("bilibiliShowPic", av_root);
pic_span.style.textOverflow = "ellipsis";
pic_span.style.whiteSpace = "nowarp";
pic_span.style.overflow = "hidden";
pic_span.title = "查看封面";
pic_span.innerHTML = "🖼️";
pic_span.style.cursor = "pointer";
if (pic_span.getAttribute("setup") != "ok") {
const picHC = new CKTools.HoldClick(pic_span);
picHC.onclick(() => {
CKTools.modal.alertModal("封面", `
`, "关闭");
});
picHC.onhold(() => {
open(infos.pic);
});
pic_span.setAttribute("setup", "ok");
}
}
async function feat_showCid() {
const { av_root, infos } = this;
const cid_span = getOrNew("bilibiliShowCID", av_root);
//if (config.showCid) {
cid_span.style.textOverflow = "ellipsis";
cid_span.style.whiteSpace = "nowarp";
cid_span.style.overflow = "hidden";
cid_span.title = "CID:" + infos.cid;
cid_span.innerText = "CID:" + infos.cid;
if (cid_span.getAttribute("setup") != "ok") {
const cidspanHC = new CKTools.HoldClick(cid_span);
cidspanHC.onclick(() => {
copy(currentPageName);
popNotify.success("CID复制成功", infos.cid);
});
cidspanHC.onhold(() => {
CKTools.modal.alertModal("CID信息", `
`, "关闭");
});
cid_span.setAttribute("setup", "ok");
}
//} else cid_span.remove();
}
async function feat_showSize() {
const { av_root, infos } = this;
const size_span = getOrNew("bilibiliShowSize", av_root);
//if (config.showCid) {
size_span.style.textOverflow = "ellipsis";
size_span.style.whiteSpace = "nowarp";
size_span.style.overflow = "hidden";
size_span.title = `${infos.dimension.width}x${infos.dimension.height}`;
size_span.innerText = `${infos.dimension.width}x${infos.dimension.height}`;
//} else cid_span.remove();
}
async function feat_openGUI() {
const { av_root, infos } = this;
const gui_span = getOrNew("bilibiliShowGUISettings", av_root);
gui_span.innerHTML = "⚙";
gui_span.title = "ShowAV 设置";
gui_span.style.overflow = "hidden";
gui_span.style.cursor = "pointer";
gui_span.onclick = e => GUISettings();
}
async function feat_showPn() {
const { av_root, infos } = this;
const pn_span = getOrNew("bilibiliShowPN", av_root);
//if (config.showPn) {
const videoData = infos;
if (!videoData) return;
let part = {
part: 'P' + infos.p
}
try {
part = videoData.pages[infos.p - 1];
} catch (e) {
part = videoData.pages[0];
}
let currentPageName = part.part.length ? `《${part.part}》` : '';
let currentPageNum;
let delimiters;
if (videoData.videos != 1) {
currentPageNum = `P ${infos.p}/${videoData.videos}`;
delimiters = ["\n", " "];
} else {
currentPageNum = "";
delimiters = ["", ""];
}
pn_span.style.textOverflow = "ellipsis";
pn_span.style.whiteSpace = "nowarp";
pn_span.style.overflow = "hidden";
pn_span.title = currentPageNum + delimiters[0] + currentPageName
pn_span.innerText = currentPageNum + delimiters[1] + currentPageName;
if (pn_span.getAttribute("setup") != "ok") {
const pnspanHC = new CKTools.HoldClick(pn_span);
pnspanHC.onclick(() => {
copy(currentPageName);
popNotify.success("分P标题复制成功", currentPageName);
});
pnspanHC.onhold(() => {
CKTools.modal.alertModal("分P标题", `
`, "关闭");
});
pn_span.setAttribute("setup", "ok");
}
//} else pn_span.remove();
}
async function tryInject(flag) {
if (flag && config.orders.length === 0) return log('Terminated because no option is enabled.');
if (!(await playerReady())) return log('Can not load player in time.');
if (config.firstTimeLoad) {
registerVideoChangeHandler();
config.firstTimeLoad = false;
}
if (location.pathname.startsWith("/medialist")) {
let aid = unsafeWindow.aid;
if (!aid) {
log("Variable 'aid' is not available from unsafeWindow.");
let activeVideo = await waitForDom(".player-auxiliary-playlist-item-active");
aid = activeVideo.getAttribute("data-aid");
//console.log("SHOWAV",activeVideo);
}
log(aid);
let apidata = await getAidAPI(aid);
//console.log("SHOWAV",apidata);
infos = apidata.data;
} else {
if (flag)
infos = (await getAPI(unsafeWindow.bvid)).data;
else infos = unsafeWindow.vd;
}
infos.p = getUrlParam("p") || getPageFromCid(unsafeWindow.cid, infos);
const av_infobar = await waitForDom(".video-data");
if (!av_infobar) return log('Can not load info-bar in time.');
let av_root;
if (config.showInNewLine) {
av_root = getOrNew("bilibiliShowInfos", av_infobar.parentElement);
} else {
let rootel = document.querySelector("#bilibiliShowInfos");
if (!rootel) {
rootel = document.createElement("span");
rootel.id = "bilibiliShowInfos";
av_infobar.appendChild(rootel);
}
av_root = rootel;
}
//const av_root = getOrNew("bilibiliShowInfos",av_infobar);
//const av_root = av_infobar;
av_root.style.textOverflow = "ellipsis";
av_root.style.whiteSpace = "nowarp";
av_root.style.overflow = "hidden";
const that = {
av_root, config, av_infobar, infos, CKTools
};
const functions = {
showAv: feat_showAv.bind(that),
showSAv: feat_showStaticAv.bind(that),
showSBv: feat_showStaticBv.bind(that),
showCate: feat_showCate.bind(that),
showCid: feat_showCid.bind(that),
showPn: feat_showPn.bind(that),
showPic: feat_showPic.bind(that),
showSize: feat_showSize.bind(that),
showMore: feat_showMore.bind(that),
showCTime: feat_showCTime.bind(that),
showDmk: feat_showDmk.bind(that),
showViews: feat_showViews.bind(that),
showTop: feat_showTop.bind(that),
openGUI: feat_openGUI.bind(that)
}
config.orders.forEach(k => functions[k]());
}
function closeButton(){
const closebtn = document.createElement("div");
closebtn.innerHTML = "✖️";
closebtn.style.position = "absolute";
closebtn.style.top = "10px";
closebtn.style.right = "10px";
closebtn.style.cursor = "pointer";
closebtn.setAttribute("onclick","CKTools.modal.hideModal()");
return closebtn;
}
async function GUISettings() {
CKTools.modal.openModal("ShowAV / 设置", await CKTools.makeDom("div", async container => {
container.style.alignItems = "stretch";
const refreshRecommendShield = () => {
let shield = document.querySelector("#showav_newlinetip");
if (!shield) return;
let enabledArray = [];
const enableddiv = document.querySelector(".showav_enableddiv");
const elements = enableddiv.querySelectorAll(".showav_dragableitem");
for (let element of [...elements]) {
enabledArray.push(element.getAttribute('data-id'));
}
let sum = 0;
enabledArray.forEach(k => sum += idTn[k]);
if (sum >= 6) {
shield.classList.add('showav_newlinetip');
} else {
shield.classList.remove('showav_newlinetip');
}
}
[
closeButton(),
await CKTools.makeDom("li", async list => {
list.style.lineHeight = "2em";
[
await CKTools.makeDom("input", input => {
input.type = "checkbox";
input.id = "showav_newline";
input.name = "showav_newline";
input.checked = config.showInNewLine;
input.addEventListener("change", e => {
let shield = document.querySelector("#showav_newlinetip");
if (!shield) return;
if (input.checked) shield.classList.add('showav_newlinetip_ok');
else shield.classList.remove('showav_newlinetip_ok');
})
}),
await CKTools.makeDom("label", label => {
label.style.paddingLeft = "3px";
label.setAttribute('for', "showav_newline");
label.innerHTML = "在新的一行中显示信息 建议开启";
})
].forEach(e => list.appendChild(e));
}),
await CKTools.makeDom("li", async list => {
list.style.lineHeight = "2em";
[
await CKTools.makeDom("label", label => {
label.style.paddingLeft = "3px";
label.setAttribute('for', "showav_pnwid");
label.innerHTML = "视频分P名: 字数限制";
}),
await CKTools.makeDom("input", input => {
input.type = "number";
input.id = "showav_pnwid";
input.name = "showav_pnwid";
input.setAttribute('min', 5);
input.setAttribute('max', 100);
input.style.width = "3em";
input.style.textAlign = "center";
input.style.marginLeft = "1em";
input.style.lineHeight = "1em";
input.value = config.pnmaxlength;
})
].forEach(e => list.appendChild(e));
}),
await CKTools.makeDom("li", async list => {
list.style.lineHeight = "2em";
[
await CKTools.makeDom("label", label => {
label.style.paddingLeft = "3px";
label.id = "showav_defaultav_tip";
label.setAttribute('for', "showav_defaultav");
if (config.defaultAv)
label.innerHTML = "视频编号: 默认展示 视频AV号 (点击切换)";
else
label.innerHTML = "视频编号: 默认展示 视频BV号 (点击切换)";
}),
await CKTools.makeDom("input", input => {
input.type = "checkbox";
input.id = "showav_defaultav";
input.name = "showav_defaultav";
input.style.display = "none";
input.checked = config.defaultAv;
input.addEventListener('change', e => {
const label = document.querySelector("#showav_defaultav_tip");
if (!label) return;
if (input.checked)
label.innerHTML = "视频编号: 默认展示 视频AV号 (点击切换)";
else
label.innerHTML = "视频编号: 默认展示 视频BV号 (点击切换)";
})
}),
await CKTools.makeDom("div", div => {
div.style.paddingLeft = "20px";
div.style.color = "#919191";
div.innerHTML = `此功能仅对可切换视频编号和高级复制功能起效。`;
})
].forEach(e => list.appendChild(e));
}),
await CKTools.makeDom("li", async list => {
list.style.lineHeight = "2em";
[
await CKTools.makeDom("label", label => {
label.style.paddingLeft = "3px";
label.id = "showav_foldvidwarn_tip";
label.setAttribute('for', "showav_foldvidwarn");
if (config.foldedWarningTip)
label.innerHTML = "显示优化: 默认 折叠 视频警告文字(点击切换)";
else
label.innerHTML = "显示优化: 默认 展示 视频警告文字(点击切换)";
}),
await CKTools.makeDom("input", input => {
input.type = "checkbox";
input.id = "showav_foldvidwarn";
input.name = "showav_foldvidwarn";
input.style.display = "none";
input.checked = config.foldedWarningTip;
input.addEventListener('change', e => {
const label = document.querySelector("#showav_foldvidwarn_tip");
if (!label) return;
if (input.checked)
label.innerHTML = "显示优化: 默认 折叠 视频警告文字(点击切换)";
else
label.innerHTML = "显示优化: 默认 展示 视频警告文字(点击切换)";
})
}),
await CKTools.makeDom("div", div => {
div.style.paddingLeft = "20px";
div.style.color = "#919191";
div.innerHTML = `此功能可将视频警告(如 含有危险行为)折叠为图标,防止占用信息栏空间。`;
})
].forEach(e => list.appendChild(e));
}),
await CKTools.makeDom("li", async list => {
list.style.lineHeight = "2em";
[
await CKTools.makeDom("label", label => {
label.style.paddingLeft = "3px";
label.id = "showav_hidetime_tip";
label.setAttribute('for', "showav_hidetime");
if (config.hideTime)
label.innerHTML = "投稿时间: 隐藏原版发布时间 (点击切换)";
else
label.innerHTML = "投稿时间: 显示原版发布时间 (点击切换)";
}),
await CKTools.makeDom("input", input => {
input.type = "checkbox";
input.id = "showav_hidetime";
input.name = "showav_hidetime";
input.style.display = "none";
input.checked = config.hideTime;
input.addEventListener('change', e => {
const label = document.querySelector("#showav_hidetime_tip");
if (!label) return;
if (input.checked)
label.innerHTML = "投稿时间: 隐藏原版发布时间 (点击切换)";
else
label.innerHTML = "投稿时间: 显示原版发布时间 (点击切换)";
})
}),
await CKTools.makeDom("div", div => {
div.style.paddingLeft = "20px";
div.style.color = "#919191";
div.innerHTML = `此功能仅在开启视频投稿时间功能时起效,视频投稿时间可以显示两种时间格式,并且可排序。`;
})
].forEach(e => list.appendChild(e));
}),
await CKTools.makeDom("li", async list => {
list.style.lineHeight = "2em";
[
await CKTools.makeDom("label", label => {
label.style.paddingLeft = "3px";
label.id = "showav_deftxttime_tip";
label.setAttribute('for', "showav_deftxttime");
if (config.defaultTextTime)
label.innerHTML = "投稿时间: 显示相对时间 (点击切换)";
else
label.innerHTML = "投稿时间: 显示完整时间戳 (点击切换)";
}),
await CKTools.makeDom("input", input => {
input.type = "checkbox";
input.id = "showav_deftxttime";
input.name = "showav_deftxttime";
input.style.display = "none";
input.checked = config.defaultTextTime;
input.addEventListener('change', e => {
const label = document.querySelector("#showav_deftxttime_tip");
if (!label) return;
if (input.checked)
label.innerHTML = "投稿时间: 显示相对时间 (点击切换)";
else
label.innerHTML = "投稿时间: 显示完整时间戳 (点击切换)";
})
}),
await CKTools.makeDom("div", div => {
div.style.paddingLeft = "20px";
div.style.color = "#919191";
div.innerHTML = `相对时间格式: 如 1周前
完整时间戳格式: 如 2021-09-10 11:21:03
此功能仅对视频投稿时间功能起效。`;
})
].forEach(e => list.appendChild(e));
}),
await CKTools.makeDom("li", async list => {
list.style.lineHeight = "2em";
[
await CKTools.makeDom("label", label => {
label.style.paddingLeft = "3px";
label.innerHTML = "高级复制: 自定义复制格式";
label.addEventListener("click", () => GUISettings_advcopy())
}),
await CKTools.makeDom("div", div => {
div.style.paddingLeft = "20px";
div.style.color = "#919191";
div.innerHTML = `进入自定义复制格式设置界面。此功能仅在高级复制功能启用时生效。
请注意未保存的修改将会丢失。`;
})
].forEach(e => list.appendChild(e));
}),
// dragable code from ytb v=jfYWwQrtzzY
await CKTools.makeDom("li", async list => {
const makeDragable = async id => {
return await CKTools.makeDom("div", draggable => {
draggable.className = "showav_dragableitem";
draggable.setAttribute("draggable", true);
draggable.setAttribute("data-id", id);
draggable.innerHTML = txtCn[id];
draggable.innerHTML += `${descCn[id]}
`;
let expanded = false;
draggable.addEventListener('dragstart', e => {
if (expanded) draggable.classList.remove('showav_expand');
draggable.classList.add('showav_dragging');
[...document.querySelectorAll('.showav_dragablediv')].forEach(e => e.classList.add('showav_child_dragging'))
})
draggable.addEventListener('dragend', e => {
if (expanded) draggable.classList.add('showav_expand');
draggable.classList.remove('showav_dragging');
[...document.querySelectorAll('.showav_child_dragging')].forEach(e => e.classList.remove('showav_child_dragging'))
refreshRecommendShield();
})
draggable.addEventListener('click', e => {
expanded = draggable.classList.toggle('showav_expand');
})
})
};
function getClosestItem(container, y) {
const draggables = [...container.querySelectorAll(".showav_dragableitem:not(.showav_dragging)")];
return draggables.reduce((closest, child) => {
const box = child.getBoundingClientRect();
const offset = y - box.top - box.height / 2;
if (offset < 0 && offset > closest.offset) return { offset, element: child };
else return closest;
}, { offset: Number.NEGATIVE_INFINITY }).element;
}
function registerDragEvent(draggablediv) {
draggablediv.addEventListener('dragover', e => {
e.preventDefault();
const closestElement = getClosestItem(draggablediv, e.clientY);
const dragging = document.querySelector(".showav_dragging");
if (closestElement === null) {
draggablediv.appendChild(dragging);
} else {
draggablediv.insertBefore(dragging, closestElement);
}
})
}
[
await CKTools.makeDom("div", div => {
div.innerHTML = `拖动下面的功能模块进行排序`;
}),
await CKTools.makeDom("div", async enableddiv => {
enableddiv.innerHTML = `启用`;
enableddiv.className = "showav_dragablediv showav_enableddiv";
config.orders.forEach(async k => {
enableddiv.appendChild(await makeDragable(k));
});
registerDragEvent(enableddiv);
}),
await CKTools.makeDom("div", async disableddiv => {
disableddiv.innerHTML = `禁用`;
disableddiv.className = "showav_dragablediv showav_disableddiv";
config.all.forEach(async k => {
if (config.orders.includes(k)) return;
disableddiv.appendChild(await makeDragable(k));
});
registerDragEvent(disableddiv);
}),
await CKTools.makeDom("div", async div => {
div.style.lineHeight = "2em";
div.innerHTML = `需要添加其他的显示或快捷功能?反馈来添加...`
}),
await CKTools.makeDom("div", async div => {
div.appendChild(await CKTools.makeDom("div", async btns => {
btns.style.display = "flex";
btns.appendChild(await CKTools.makeDom("button", btn => {
btn.className = "CKTOOLS-toolbar-btns";
btn.innerHTML = "保存并关闭";
btn.onclick = e => {
const enableddiv = document.querySelector(".showav_enableddiv");
const elements = enableddiv.querySelectorAll(".showav_dragableitem");
let enabledArray = [];
for (let element of [...elements]) {
enabledArray.push(element.getAttribute('data-id'));
}
config.orders = enabledArray;
config.defaultAv = document.querySelector("#showav_defaultav").checked;
config.hideTime = document.querySelector("#showav_hidetime").checked;
config.defaultTextTime = document.querySelector("#showav_deftxttime").checked;
config.foldedWarningTip = document.querySelector("#showav_foldvidwarn").checked;
config.pnmaxlength = parseInt(document.querySelector("#showav_pnwid").value);
config.showInNewLine = document.querySelector("#showav_newline").checked;
saveAllConfig();
CKTools.modal.hideModal();
if (config.foldedWarningTip) {
CKTools.addStyle(`
.video-data>span.argue{
width: 0.5rem;
margin-left: 0!important;
margin-right: 16px;
}
`, 'showav_hidevidwarn', 'update');
} else {
CKTools.addStyle('', 'showav_hidevidwarn', 'update');
}
let old = document.querySelector("#bilibiliShowInfos")
if (old) old.remove();
initScript(true);
}
}))
btns.appendChild(await CKTools.makeDom("button", btn => {
btn.className = "CKTOOLS-toolbar-btns";
btn.innerHTML = "关闭";
btn.style.background = "#ececec";
btn.style.color = "black";
btn.onclick = e => {
CKTools.modal.hideModal();
}
}))
}))
}),
].forEach(e => list.appendChild(e));
})
].forEach(e => container.appendChild(e));
setTimeout(refreshRecommendShield, 500);
}));
}
async function GUISettings_advcopy() {
if (CKTools.modal.isModalShowing()) {
CKTools.modal.hideModal();
await wait(300);
}
CKTools.modal.openModal("ShowAV / 设置 / 快速复制设置", await CKTools.makeDom("div", async container => {
container.style.alignItems = "stretch";
[
closeButton(),
// dragable code from ytb v=jfYWwQrtzzY
await CKTools.makeDom("li", async list => {
const makeDragable = async id => {
return await CKTools.makeDom("div", draggable => {
draggable.className = "showav_dragableitem copyitem";
draggable.setAttribute("draggable", true);
draggable.setAttribute("data-id", id);
if (id.split(":")[0] === "custom") {
draggable.innerHTML = config.customcopyitems[id].title;
const node = document.createElement("div");
node.appendChild(document.createTextNode(config.customcopyitems[id].content));
draggable.appendChild(node);
} else {
draggable.innerHTML = txtCn[id];
draggable.innerHTML += `${descCn[id]}
`;
}
draggable.removeItem = draggable.remove;
let expanded = false;
draggable.addEventListener('dragstart', e => {
if (expanded) draggable.classList.remove('showav_expand');
draggable.classList.add('showav_dragging');
[...document.querySelectorAll('.showav_dragablediv')].forEach(e => e.classList.add('showav_child_dragging'))
})
draggable.addEventListener('dragend', e => {
if (expanded) draggable.classList.add('showav_expand');
draggable.classList.remove('showav_dragging');
[...document.querySelectorAll('.showav_child_dragging')].forEach(e => e.classList.remove('showav_child_dragging'))
})
draggable.addEventListener('click', e => {
expanded = draggable.classList.toggle('showav_expand');
})
})
};
function getClosestItem(container, y) {
const draggables = [...container.querySelectorAll(".showav_dragableitem:not(.showav_dragging)")];
return draggables.reduce((closest, child) => {
const box = child.getBoundingClientRect();
const offset = y - box.top - box.height / 2;
if (offset < 0 && offset > closest.offset) return { offset, element: child };
else return closest;
}, { offset: Number.NEGATIVE_INFINITY }).element;
}
function registerDragEvent(draggablediv) {
draggablediv.addEventListener('dragover', e => {
e.preventDefault();
const closestElement = getClosestItem(draggablediv, e.clientY);
const dragging = document.querySelector(".showav_dragging");
if (closestElement === null) {
draggablediv.appendChild(dragging);
} else {
draggablediv.insertBefore(dragging, closestElement);
}
})
}
[
await CKTools.makeDom("div", div => {
div.innerHTML = `拖动下面的功能模块进行排序`;
}),
await CKTools.makeDom("div", async enableddiv => {
enableddiv.innerHTML = `启用`;
enableddiv.className = "showav_dragablediv showav_enableddiv";
config.copyitems.forEach(async k => {
enableddiv.appendChild(await makeDragable(k));
});
registerDragEvent(enableddiv);
}),
await CKTools.makeDom("div", async disableddiv => {
disableddiv.innerHTML = `禁用`;
disableddiv.className = "showav_dragablediv showav_disableddiv";
config.copyitemsAll.forEach(async k => {
if (config.copyitems.includes(k)) return;
disableddiv.appendChild(await makeDragable(k));
});
registerDragEvent(disableddiv);
}),
await CKTools.makeDom("li", async list => {
const makeItem = (copyitemid,focus=false) => {
const item = config.customcopyitems[copyitemid];
const node = document.createElement("li");
node.className = "copyitem";
if(focus){
node.classList.add("actionpending");
setTimeout(() => {
node.classList.remove("actionpending");
node.scrollIntoView();
},20);
}
node.setAttribute("data-id", copyitemid);
node.innerHTML = `${item.title}
`;
node.style.borderRadius = "3px";
node.style.border = "solid 2px grey";
node.style.padding = "3px";
node.style.margin = "1px";
const smallp = document.createElement("p");
smallp.style.fontSize = "small";
smallp.style.color = "grey";
smallp.style.overflow = "hidden";
smallp.style.wordWrap = "nowarp";
smallp.appendChild(document.createTextNode(item.content));
node.appendChild(smallp);
node.removeItem = ()=>{
node.classList.add("actionpending");
setTimeout(()=>node.remove(),350);
};
node.onclick = async e => {
if(node.classList.contains("preremove")){
if (config.all.includes(copyitemid)) {
config.all.splice(config.all.indexOf(copyitemid), 1);
}
if (config.orders.includes(copyitemid)) {
config.orders.splice(config.orders.indexOf(copyitemid), 1);
}
delete config.customcopyitems[copyitemid];
saveAllConfig();
[...document.querySelectorAll(`.copyitem[data-id="${copyitemid}"]`)].forEach(e => e.removeItem());
}else{
[...document.querySelectorAll("li.copyitem.preremove")].forEach(e=>{
e.classList.remove("preremove");
try{if(e.clearTimer){
clearTimeout(e.clearTimer);
}}catch(e){};
});
node.classList.add("preremove");
node.clearTimer = setTimeout(() => {
node.classList.remove("preremove");
node.clearTimer = null;
},5000);
}
}
return node;
};
[
await CKTools.makeDom("label", label => {
label.style.paddingLeft = "3px";
label.style.fontWeight = "bold";
label.innerHTML = "添加自定义复制项目";
}),
await CKTools.makeDom("div", async div => {
div.style.paddingLeft = "20px";
[
await CKTools.makeDom("input", async input => {
input.id = "showav_customcopytitle";
input.setAttribute("type", "text");
input.style.width = "60%";
input.style.margin = "6px 0 0 0";
input.style.padding = "6px";
input.style.borderRadius = "6px";
input.style.border = "solid 2px grey";
input.setAttribute("placeholder", "自定义标题");
}),
await CKTools.makeDom("input", async input => {
input.id = "showav_customcopycontent";
input.setAttribute("type", "text");
input.style.width = "60%";
input.style.margin = "6px 0 0 0";
input.style.padding = "6px";
input.style.borderRadius = "6px";
input.style.border = "solid 2px grey";
input.setAttribute("placeholder", "自定义内容");
}),
await CKTools.makeDom("div", div => {
div.style.paddingLeft = "20px";
div.style.color = "#919191";
div.innerHTML = `变量提示
- %timeurl% => 包含时间的完整地址
- %vidurl% => 视频纯净地址
- %shorturl% => 短地址
- %seek% => 当前视频播放秒数
- %title% => 视频标题
- %av% => av号
- %bv% => BV号
- %cid% => CID号
- %p% => 分P
`;
div.style.maxHeight = '2rem';
div.style.overflow = 'hidden';
div.style.transition = 'all .3s';
let expanded = false;
div.onclick = e => {
expanded = !expanded;
if (expanded) {
div.style.maxHeight = "20rem";
} else {
div.style.maxHeight = '2rem';
}
}
}),
await CKTools.makeDom("button", btn => {
btn.className = "CKTOOLS-toolbar-btns";
btn.innerHTML = "添加";
btn.style.background = "#ececec";
btn.style.color = "black";
btn.onclick = async e => {
const ccid = "custom:" + Math.random().toString(36).replace('.', '');
const title = document.querySelector("#showav_customcopytitle").value;
const content = document.querySelector("#showav_customcopycontent").value;
if (title.trim().length < 1 || content.trim().length < 1) {
popNotify.warn("无法添加自定义项目", "标题或内容为空");
return;
}
config.customcopyitems[ccid] = { title, content };
if (!config.all.includes(ccid)) config.all.push(ccid);
saveAllConfig();
const disablediv = document.querySelector(".showav_disableddiv");
disablediv && disablediv.appendChild(await makeDragable(ccid));
const customlist = document.querySelector("#showav_customitems");
customlist && customlist.appendChild(makeItem(ccid,true));
document.querySelector("#showav_customcopytitle").value = "";
document.querySelector("#showav_customcopycontent").value = "";
}
})
].forEach(e => div.appendChild(e));
}),
await CKTools.makeDom("label", label => {
label.style.paddingLeft = "3px";
label.style.fontWeight = "bold";
label.innerHTML = "已有自定义复制项目 (点击移除)";
}),
await CKTools.makeDom("ul", ul => {
ul.style.paddingLeft = "3px";
ul.id = "showav_customitems";
for (let copyitemid of Object.keys(config.customcopyitems)) {
ul.appendChild(makeItem(copyitemid));
}
}),
].forEach(e => list.appendChild(e));
}),
await CKTools.makeDom("div", async div => {
div.appendChild(await CKTools.makeDom("div", async btns => {
btns.style.display = "flex";
btns.appendChild(await CKTools.makeDom("button", btn => {
btn.className = "CKTOOLS-toolbar-btns";
btn.innerHTML = "保存并关闭";
btn.onclick = e => {
const enableddiv = document.querySelector(".showav_enableddiv");
const elements = enableddiv.querySelectorAll(".showav_dragableitem");
let enabledArray = [];
for (let element of [...elements]) {
enabledArray.push(element.getAttribute('data-id'));
}
config.copyitems = enabledArray;
saveAllConfig();
CKTools.modal.hideModal();
initScript(true);
}
}))
btns.appendChild(await CKTools.makeDom("button", btn => {
btn.className = "CKTOOLS-toolbar-btns";
btn.innerHTML = "关闭";
btn.onclick = e => {
CKTools.modal.hideModal();
}
}))
}))
}),
].forEach(e => list.appendChild(e));
})
].forEach(e => container.appendChild(e));
}));
}
const copy = function copy(text) {
if (!navigator.clipboard) {
prompt('请手动复制', text);
return;
}
navigator.clipboard.writeText(text).then(function () {
log('Copy OK');
}, function (err) {
log('Auto Copy Failed:', err);
prompt('请手动复制', text);
});
}
unsafeWindow.showav_fastcopy = (el) => {
copy(el.value);
popNotify.success("复制成功", el.value);
}
unsafeWindow.showav_guisettings = GUISettings;
unsafeWindow.showav_guisettings_shoy = GUISettings_advcopy;
CKTools.modal.initModal();
CKTools.modal.hideModal();
const blockwin = CKTools.get("#CKTOOLS-blockWindow");
blockwin&&(blockwin.onclick = CKTools.modal.hideModal);
CKTools.addStyle(`
.showav_dragablediv {
width: 300px;
min-height: 60px;
border: dotted;
border-radius: 8px;
padding: 12px;
margin: 5px;
position: relative;
margin: 3px auto;
}
.showav_dragableitem {
background: white;
margin: 3px;
padding: 3px;
border-radius: 4px;
border: solid #bdbdbd 2px;
color: black;
transition: all .3s;
max-height: 2rem;
}
.showav_dragableitem.showav_expand {
max-height: 8rem;
}
.showav_dragableitem>div {
color: #adadad;
margin: 0 6px;
opacity: 0;
transition: all .3s ease-in-out;
transform: translateX(-10px);
font-size: small;
overflow: hidden;
max-height: 0;
}
.showav_dragableitem.showav_expand>div{
transform: translateX(0px);
max-height: 8rem;
opacity: 1;
}
.showav_dragableitem::before {
content: "⋮⋮";
float: right;
font-size: xx-small;
padding: 3px;
color: #bbbbbb !important;
}
.showav_dragging {
background: grey;
color: white;
border: solid #515050 2px;
transform: scale(1.1);
transition: all .3s;
}
.showav_dragablediv:not(.showav_child_dragging) .showav_dragableitem:hover:not(.showav_dragging) {
background: grey;
color: white;
border: solid #515050 2px;
transform: scale(1.03);
transition: all .3s;
}
.showav_dragablediv>b {
position: absolute;
left: -4rem;
}
.showav_disableddiv .showav_dragableitem {
color: #a9a8a8;
}
.showav_enableddiv{
background: #dcedc8;
}
.showav_disableddiv{
background: #ffcdd2;
}
#showav_newlinetip{
font-size: small;
display: inline-block;
padding: 0 2px;
line-height: 1.5em;
border-radius: 3px;
background: #ff5722;
color: white;
overflow: hidden;
transition: all .3s;
opacity: 0;
}
#showav_newlinetip.showav_newlinetip_ok{
background: #0288d1!important;
}
#showav_newlinetip.showav_newlinetip{
opacity: 1;
}
ul#showav_customitems{
min-height: 60px;
}
ul#showav_customitems::after{
content:"目前没有自定义项目。当添加了自定义项目时,可以在这里删除。";
padding: 6px;
display: block;
opacity: 0;
transition: all.3s;
overflow: hidden;
height: 0px;
}
ul#showav_customitems:empty::after{
opacity: 1;
height: 4rem!important;
}
li.copyitem{
transition: all 0.3s;
opacity: 1;
max-height: 8em;
}
li.copyitem.preremove{
color: red!important;
border-color: red!important;
}
li.copyitem::after{
transition: all 0.3s;
line-height: 0px!important;
content:"再次点击以移除";
display: block;
overflow: hidden;
color: red!important;
opacity: 0;
max-height: 8em;
}
li.copyitem.actionpending{
transition: all 0.5s;
padding: 0px!important;
border-width: 0px;
margin-top: 0px!important;
margin-bottom: 0px!important;
max-height: 0em!important;
opacity: 0;
}
li.copyitem.preremove::after{
line-height: 2rem!important;
opacity: 1;
}
`, 'showav_dragablecss', "unique", document.head);
initScript(false);
})();