论坛网页版增强脚本:适配任意倍率缩放页面,大幅提升窄屏阅读体验(Tampermonkey脚本)
上次由于考虑不周,擅自发布了破坏性脚本,于是这次想着痛改前非,来搞一个好脚本。发现问题:有的时候看四格漫画,或者看很小的文字,就会本能地想要放大页面。可是当页面放大到一定程度以后,有一部分就会跑到屏幕外面,此时要拖动页面底部的滚动条,相当地不方便。比如说下面的这个漫画(相当有趣!):
如果想要进一步放大,就会变成这个样子:
另外,如果我们想要缩小页面,或者显示器本来就相当巨大,或缩放比例过低,那么页面会变成这样:
如果说上面的都只是有些难受的话,那么看小说的时候,如果页面过窄或缩放比例过高,那么看到的将会是:
想看小说要不断地拖动横向滚动条,恶心到家了。
解决方法有没有呢?或许可以换手机版,但是电脑上是打不开手机版的,点开链接显示的是「立即使用手机访问,获得极速移动体验」,好可恶啊。如果能让电脑端也可以自由点开手机版,或许这个问题也算解决了吧。
但是,总之还是花了点时间写了这个脚本。实话实说,是因为我当时没有想到这一点。先展示一下做了什么改动吧:
隐藏了侧边栏,让页面始终处于屏幕内,缩小了页边距,让图片能够自适应页面宽度,此外将图片自动居中,不论是否有标签。
考虑到很多图片的宽度是直接写的900px,所以在页面宽度大于900px的时候没有选择放大图片,而是保持原大小,只在页面宽度小于图片宽度的时候,适当缩小图片,使之始终保持在页面范围之内。
小说的体验也和这个差不多:
总之就是这样了,依然还是直接放代码,因为论坛不能直接上传.user.js后缀名的文件。如何使用呢?一个方法是在浏览器里安装Tampermonkey插件,然后创建一个新脚本,用下面的代码完全替换新窗口里面的内容并保存。当然还有其他的方法,只要能让浏览器自动在页面加载完成后执行下面的代码即可。所以也可以建立一个反向代理服务器,转发www.yamibo.com的请求,并在每个HTML响应后加上一个<script>,里面放上这个代码,不过这纯属于杀鸡用牛刀了。
// ==UserScript==
// @name Yamibo Script
// @namespace http://tampermonkey.net/
// @version 0.0
// @description小幅增强百合会网页版观看体验
// @author VoltaXTY
// @Match https://bbs.yamibo.com/*
// @icon http://yamibo.com/favicon.ico
// @grant none
// @run-at document-end
// ==/UserScript==
let ID = 1;
const GenerateID = () => {
return ID++;
};
const HTML = (tagname, attrs, ...children) => {
if(attrs === undefined) return document.createTextNode(tagname);
const ele = document.createElement(tagname);
if(attrs) for(const of Object.entries(attrs)){
if(value === null || value === undefined) continue;
if(key.charAt(0) === "_"){
const type = key.slice(1);
ele.addEventListener(type, value);
}
else if(key.charAt(0) === "#" && ele.getAttribute("id") !== null){
const type = key.slice(1);
persistentEventListeners.set(ele.getAttribute("id"), {type: type, value: value});
ele.addEventListener(type, value);
}
else if(key === "eventListener"){
for(const listener of value){
ele.addEventListener(listener.type, listener.listener, listener.options);
}
}
else ele.setAttribute(key, value);
}
for(const child of children) if(child) ele.append(child);
return ele;
};
const ParseHTML = (html) => {
const t = document.createElement("template");
t.innerHTML = html;
return t.content;
}
const ThreadIDToURL = (tid, page = 1) => {
return `https://bbs.yamibo.com/thread-${tid}-${page}-1.html`;
}
const FetchThread = async (url) => {
let retry = false;
do{
retry = false;
let res = await fetch(url, {
credentials: "include",
});
let text = await res.text();
if(text.startsWith("<script")){
let jumploc = "";
let location = {
get href(){
return jumploc;
},
set href(_){
if(!jumploc) jumploc = _;
},
assign(_){
if(!jumploc) jumploc = _;
},
replace(_){
if(!jumploc) jumploc = _;
}
};
let window = {
get href(){
return jumploc;
},
set href(_){
if(!jumploc) jumploc = _;
}
};
const t = document.createElement("template");
t.innerHTML = text;
const s = t.content.firstElementChild;
if(s.tagName === "SCRIPT"){
const _ = s.innerHTML;
try{ eval(_); } catch (error){
console.error(_);
console.error(error);
jumploc = location = "";
retry = true;
}
}
if(typeof location === "string" && location.length > jumploc.length) jumploc = location;
if(jumploc !== ""){
let res2 = await fetch(`https://bbs.yamibo.com${jumploc}`, {
credentials: "include",
});
let text = await res2.text();
return text;
}
}
else return text;
}while(retry);
return "Should not reach here.";
}
const inj_style =
`
.zoom{
margin: 0px auto;
width: auto;
height: auto;
max-width: 100%;
min-width: 50px;
}
.zoom{
width: auto;
height: auto;
max-width: 100%;
min-width: 900px;
}
img.zoom{
display: block;
counter-increment: img-counter 1;
}
img.zoom::before{
display: block;
text-align: center;
}
td.plc{
counter-reset: img-counter;
}
body#nv_forum{
min-width: 0px;
}
@media(min-width: 900px){
.author-id__added{
display: none;
}
}
@media(max-width: 900px){
#hd .wp, #wp{
min-width: calc(100% - 20px);
}
div > table > tbody > tr{
display: grid;
grid-template-columns: 1fr;
width: 100%;
max-width: 9999px;
}
div > table > tbody > tr:nth-child(1) > td.pls{
grid-column: 1/1;
grid-row: 1/1;
margin-top: 37px;
width: 100%;
z-index: 1;
}
div > table > tbody > tr:nth-child(1) > td.pls > div > div.pi{
display: none;
}
div > table > tbody > tr:nth-child(1) > td.plc{
grid-column: 1/1;
grid-row: 1/1;
z-index: 0;
}
.author-id__added{
margin-left: 8px;
}
div.pls.cl.favatar{
height: auto;
width: auto;
display: none;
}
.favatar-group-top .pi{
display: none;
}
td.pls{
visibility: hidden;
}
.pls.ptn.pbn{
visibility: visible;
}
}
`
const InsertStyleSheet = (style) => {
const s = new CSSStyleSheet();
s.replaceSync(style);
document.adoptedStyleSheets = [...document.adoptedStyleSheets, s];
};
const IsForumPost = () => {
const forumview_url = /https:\/\/bbs\.yamibo\.com\/thread-+-+-+\.html/;
if(forumview_url.test(location.toString())) return true;
if((new URLSearchParams(window.location.search)).get("mod") === "viewthread") return true;
else return false;
}
const AddPreviewButton = () => {
// TODO
document.querySelectorAll("#threadlisttableid tbody").forEach((tbody) => {
if(tbody.hasAttribute("preview-button-added")) return;
else tbody.setAttribute("preview-button-added", "");
const id_pattern = /+_(+)/;
if(!id_pattern.test(tbody.id)) return;
const title_ele = tbody.querySelector(":scope tr th");
title_ele.insertAdjacentElement("afterbegin",
HTML("td", {class: "preview-button"}, "test")
);
})
};
const ImproveForumPost = () => {
if(!IsForumPost()) return;
document.querySelectorAll("div").forEach((div) => {
if(!(/post_+/.test(div.id)) || div.hasAttribute("modified")) return;
div.setAttribute("modified", "");
const tok = GenerateID();
const author_id = div.querySelector(":scope .pi .authi .xw1").textContent;
const post_content = div.querySelector(":scope .plc");
const post_content_header = post_content.querySelector(":scope .authicn");
post_content_header.insertAdjacentElement("afterend",
HTML("strong", {class: "author-id__added"}, author_id),
);
const post_content_author = div.querySelector(":scope div.pls");
const pcac = post_content_author.children;
const group1 = HTML("div", {class: "favatar-group-top"});
const group2 = HTML("div", {class: "favatar-group-bottom"});
while(!pcac.item(0).classList.contains("pil")) group1.append(pcac.item(0));
while(pcac.item(0)) group2.append(pcac.item(0));
post_content_author.append(group1, group2);
})
}
const OnMutation = (mulist, observer) => {
observer.disconnect();
//AddPreviewButton(...args);
ImproveForumPost();
observer.observe(document, {subtree: true, childList: true});
};
InsertStyleSheet(inj_style);
new MutationObserver(OnMutation).observe(document, {subtree: true, childList: true});
题外话,管理版没法编辑帖子真的是硬伤。
页:
[1]