// ==UserScript== // @name 手机百度贴吧自动展开楼层 // @namespace http://tampermonkey.net/ // @homepage https://greasyfork.org/scripts/445657 // @version 5.2 // @description 有时候用手机的浏览器打开百度贴吧,只想看一眼就走,并不想打开APP,这个脚本用于帮助用户自动展开楼层。注意:只支持手机浏览器,测试环境为Iceraven+Tampermonkey // @author voeoc // @icon https://tieba.baidu.com/favicon.ico // @match https://tieba.baidu.com/* // @match https://jump2.bdimg.com/* // @match https://tiebac.baidu.com/* // @exclude /^https?:\/\/[\.a-z]*\/(index|f\?.*kw=)/ // @exclude /^https?:\/\/[.a-z]*\/(index|f?.*kw=)/ // @connect tieba.baidu.com // @connect jump2.bdimg.com // @connect tiebac.baidu.com // @grant unsafeWindow // @grant GM_addStyle // @grant GM_xmlhttpRequest // @grant GM_getValue // @grant GM_setValue // @grant GM_listValues // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @grant GM_getResourceText // @run-at document-start // @require https://unpkg.com/ajax-hook@2.1.3/dist/ajaxhook.core.min.js // @require https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.min.js // @noframes // @license MIT // @downloadURL https://update.greasyfork.icu/scripts/445657/%E6%89%8B%E6%9C%BA%E7%99%BE%E5%BA%A6%E8%B4%B4%E5%90%A7%E8%87%AA%E5%8A%A8%E5%B1%95%E5%BC%80%E6%A5%BC%E5%B1%82.user.js // @updateURL https://update.greasyfork.icu/scripts/445657/%E6%89%8B%E6%9C%BA%E7%99%BE%E5%BA%A6%E8%B4%B4%E5%90%A7%E8%87%AA%E5%8A%A8%E5%B1%95%E5%BC%80%E6%A5%BC%E5%B1%82.meta.js // ==/UserScript== !function($) { "use strict"; function _interopDefaultLegacy(e) { return e && "object" == typeof e && "default" in e ? e : { default: e }; } var $__default = _interopDefaultLegacy($); if (window.VOEOC_SCRIPT_ALREADY_LOAD_TAG_BAIDU_TIEBA) throw new Error("VOEOC_SCRIPT_ALREADY_LOAD_TAG_BAIDU_TIEBA"); window.VOEOC_SCRIPT_ALREADY_LOAD_TAG_BAIDU_TIEBA = !0; if (top !== self) throw new Error("NO FRAME"); var _Stack_items, _ElementSearcher_options, CSS_REMOVE = ".comment-box, .only-lz, .nav-bar-bottom, .open-app, .more-image-desc {\r\n display: none !important;\r\n}\r\n.logo-wrapper {\r\n visibility: hidden !important;\r\n pointer-events: none !important;\r\n height: 0;\r\n}\r\n.open-app-text {\r\n display: none !important;\r\n}"; function __classPrivateFieldGet(receiver, state, kind, f) { if ("a" === kind && !f) throw new TypeError("Private accessor was defined without a getter"); if ("function" == typeof state ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return "m" === kind ? f : "a" === kind ? f.call(receiver) : f ? f.value : state.get(receiver); } function __classPrivateFieldSet(receiver, state, value, kind, f) { if ("m" === kind) throw new TypeError("Private method is not writable"); if ("a" === kind && !f) throw new TypeError("Private accessor was defined without a setter"); if ("function" == typeof state ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return "a" === kind ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value), value; } class Stack { constructor() { _Stack_items.set(this, void 0); __classPrivateFieldSet(this, _Stack_items, [], "f"); } push(element) { __classPrivateFieldGet(this, _Stack_items, "f").push(element); } pop() { return __classPrivateFieldGet(this, _Stack_items, "f").pop(); } peek() { return __classPrivateFieldGet(this, _Stack_items, "f")[__classPrivateFieldGet(this, _Stack_items, "f").length - 1]; } isEmpty() { return 0 === __classPrivateFieldGet(this, _Stack_items, "f").length; } size() { return __classPrivateFieldGet(this, _Stack_items, "f").length; } clear() { __classPrivateFieldSet(this, _Stack_items, [], "f"); } } _Stack_items = new WeakMap; function ASSERT(condition, msg) { if (!condition) throw new Error(msg); } function AUTO_CATCH_ERROR(func, msg, dirObj) { try { func(); } catch (e) {} } class ElementSearcher { constructor(options) { _ElementSearcher_options.set(this, void 0); __classPrivateFieldSet(this, _ElementSearcher_options, options, "f"); } wait(selector) { return ElementSearcher.WAIT(selector, __classPrivateFieldGet(this, _ElementSearcher_options, "f")); } static WAIT(selector, options) { const realOptions = Object.assign(Object.assign({}, ElementSearcher.DEFAULT_OPTIONS), options); selector || (selector = realOptions.selector); return new Promise(((resolve, reject) => { let findTimeNum = 0, timer = setInterval((() => { let element = realOptions.searchFunc(selector); if (element) { clearInterval(timer); resolve(element); } else { findTimeNum++; if (realOptions.searchNum < findTimeNum) { clearInterval(timer); reject(new Error(`search time out: ${selector}=${element}`)); } } }), realOptions.interval); })); } } _ElementSearcher_options = new WeakMap; ElementSearcher.DEFAULT_OPTIONS = { selector: "", searchNum: 100, searchFunc: document.querySelector.bind(document), interval: 50 }; ElementSearcher.CommonSearcher = new ElementSearcher; function MATCH_REG(regExp, str) { let regExpMatchArray = regExp.exec(str); if (regExpMatchArray && regExpMatchArray.length > 1) return regExpMatchArray[1].trim(); } class IframeUtils { constructor(parentNode, id) { this.iframeNode = parentNode.ownerDocument.createElement("iframe"); id && (this.iframeNode.id = id); this.parentNode = parentNode; this.parentNode.appendChild(this.iframeNode); } get contentDocument() { return this.iframeNode.contentDocument; } get contentWindow() { return this.iframeNode.contentWindow; } get ownerDocument() { return this.iframeNode.ownerDocument; } writeDoc(data) { try { this.contentDocument.open().write(data); } finally { this.contentDocument.close(); } } } function STOPPROPAGATION(event) { event.stopPropagation ? event.stopPropagation() : event.cancelBubble = !0; return !1; } function GET_URL_ATTR(url, attrName) { return MATCH_REG(RegExp(`${attrName}=([^&]*)&?`, "i"), url); } class SettingValue { constructor(key, defaultValue) { this.keyGM = key; this.defaultValue = defaultValue; } get value() { return GM_getValue(this.keyGM, this.defaultValue); } set value(newVal) { GM_setValue(this.keyGM, newVal); } } const settingDatas = (() => { const datas = { isClickToExpandLzlPage: new SettingValue("VOEOC_GMKEY_isClickToExpandLzlPage", !0), isLongClickToExpandLzlPage: new SettingValue("VOEOC_GMKEY_isLongClickToExpandLzlPage", !0), isAutoGotoPostPage: new SettingValue("VOEOC_GMKEY_isAutoGotoPostPage", !0), isAutoExpand: new SettingValue("VOEOC_GMKEY_isAutoExpand", !0), isRemaindAutoExpand: new SettingValue("VOEOC_GMKEY_isRemaindAutoExpand", !0), eachExpandSize: new SettingValue("VOEOC_GMKEY_eachExpandSize", 10), autoExpandNum: new SettingValue("VOEOC_GMKEY_autoExpandNum", 1), remaindAutoExpandSize: new SettingValue("VOEOC_GMKEY_remaindAutoExpandSize", 7), lzlCacheSize: new SettingValue("VOEOC_GMKEY_lzlCacheSize", 10) }; datas.isClickToExpandLzlPage.value = !0; datas.isLongClickToExpandLzlPage.value = !0; datas.lzlCacheSize.value = 10; return datas; })(), jquerySearchFunc = (selector, doc = document) => { const el = $__default.default(selector, doc); return el.length > 0 ? el : null; }, jquerySearcher = new ElementSearcher({ searchFunc: jquerySearchFunc }), REGEXP_PBDATA = RegExp("getPbData?.*pn=.*", "i"), REGEXP_POSTPAGE = RegExp("postPage?(?=.*tid=)(?=.*postAuthorId=)(?=.*forumId=)", "i"), REGEXP_LZLPAGE = RegExp("lzlPage?(?=.*floor=)(?=.*pid=)", "i"); var PAGE_TYPE, _a, _HistoryStateManager_showDialogList, _HistoryStateManager_instance; !function(PAGE_TYPE) { PAGE_TYPE[PAGE_TYPE.UNKNOW = 0] = "UNKNOW"; PAGE_TYPE[PAGE_TYPE.MAINPAGE = 1] = "MAINPAGE"; PAGE_TYPE[PAGE_TYPE.POSTPAGE = 2] = "POSTPAGE"; PAGE_TYPE[PAGE_TYPE.LZLPAGE = 3] = "LZLPAGE"; PAGE_TYPE[PAGE_TYPE.TIEBAPAGE = 4] = "TIEBAPAGE"; }(PAGE_TYPE || (PAGE_TYPE = {})); function GET_PAGE_TYPE() { let isTiePage = !1; if (RegExp("^/f").test(window.location.pathname)) { if (GET_URL_ATTR(window.location.href, "kw")) return PAGE_TYPE.TIEBAPAGE; GET_URL_ATTR(window.location.href, "kz") && (isTiePage = !0); } else RegExp("^/p").test(window.location.pathname) && (isTiePage = !0); if (isTiePage) { let hash = window.location.hash; if ("" === hash || "#/" === hash) return PAGE_TYPE.MAINPAGE; if (REGEXP_POSTPAGE.test(hash)) return PAGE_TYPE.POSTPAGE; if (REGEXP_LZLPAGE.test(hash)) return PAGE_TYPE.LZLPAGE; } return PAGE_TYPE.UNKNOW; } class FirstFloor { get tieBaName() { var _a, _b, _c; return null === (_c = null === (_b = null === (_a = this.titleNode[0]) || void 0 === _a ? void 0 : _a.innerText) || void 0 === _b ? void 0 : _b.replace("吧", "")) || void 0 === _c ? void 0 : _c.trim(); } get height() { return this.tieNode.outerHeight(!0); } waitInit(searchFunc = jquerySearchFunc) { return new Promise(((resolve, reject) => { ElementSearcher.WAIT(".main-thread-content", { searchFunc: searchFunc }).then((tieNode => { this.tieNode = tieNode; this.titleNode = searchFunc(".forum-block"); resolve(this); })).catch(reject); })); } restorePostPageTitle() { return new Promise(((resolve, reject) => { jquerySearcher.wait(".text").then((titletextNode => { const titleCloneNode = this.titleNode.clone(); titletextNode.replaceWith(titleCloneNode); titleCloneNode[0].onclick = () => { const tiebaName = this.tieBaName; tiebaName && (window.location.href = `${window.origin}/f?kw=${tiebaName}`); }; resolve(null); })).catch(reject); })); } restorePostPageFirstFloor() { return new Promise((resolve => { AUTO_CATCH_ERROR((() => { if (!this.tieNode) throw new Error("1楼内容为空!"); const tieCloneNode = this.tieNode.clone()[0]; tieCloneNode.style.cssText = "margin-left:0.12rem;margin-right:0.12rem;margin-bottom:0.25rem;"; tieCloneNode.style.display = "none"; jquerySearcher.wait(".avatar").then((lzavatarNode => { lzavatarNode.css("background-image", `url("${lzavatarNode.attr("data-src")}")`); })); let textContentNode = tieCloneNode.querySelector(".thread-text"); textContentNode && (textContentNode.style.cssText = "margin-top:0.18rem;font-size:0.16rem;line-height:0.28rem;"); let replySwitchNode = document.querySelector("#replySwitch"); if (replySwitchNode && replySwitchNode.parentNode) { replySwitchNode.parentNode.insertBefore(tieCloneNode, replySwitchNode); $__default.default(tieCloneNode).slideDown("normal", (() => { const imgNodes = tieCloneNode.querySelectorAll("img.img"); imgNodes.forEach((imgNode => { AUTO_CATCH_ERROR((() => { imgNode.setAttribute("src", imgNode.getAttribute("data-src")); })); })); })); } })); AUTO_CATCH_ERROR((() => { let threadtitleNode = document.querySelector(".thread-title"); threadtitleNode || (threadtitleNode = document.querySelector(".bottom-thread-title")); if (!threadtitleNode) throw new Error("标题为空!"); threadtitleNode.style.cssText = "margin-bottom: 0.13rem;font-size:0.22rem;font-weight:700;line-height:0.33rem;"; })); resolve(null); })); } } class FirstFloorFrame { constructor() { this.firstFloor = new FirstFloor; const frameParentNode = $__default.default('
\n
'); this.firstFloorFrameUtils = new IframeUtils(frameParentNode[0]); const jqIframeNode = $__default.default(this.firstFloorFrameUtils.iframeNode); jqIframeNode.attr("src", MainPage.GET_MAIN_URL()); jquerySearcher.wait("div.nav-bar-v2-fixed:nth-child(2)").then((splitNode => { frameParentNode.insertBefore(splitNode); this.firstFloor.waitInit((selector => { var _a; return jquerySearchFunc(selector, null === (_a = this.firstFloorFrameUtils) || void 0 === _a ? void 0 : _a.contentDocument); })).then((() => { this.firstFloorFrameUtils.contentWindow.stop(); !function INSERT_CSS(cssText, documentNode = document) { let newStyleNode = documentNode.createElement("style"); newStyleNode.appendChild(documentNode.createTextNode(cssText)); let head = documentNode.getElementsByTagName("head")[0]; head.appendChild(newStyleNode); }("html{overflow: hidden;}:not(.main-thread-content *, .main-thread-content, .pb-page-wrapper, .main-page-wrap, symbol, symbol *,body, html) {display: none !important;}div.nav-bar-v2-fixed:nth-child(1) {display: none !important;}.main-thread-content{margin: 0 !important;}" + CSS_REMOVE, this.firstFloorFrameUtils.contentDocument); })).finally((() => { var _a; const originHeight = this.firstFloor.height; null === (_a = this.onload) || void 0 === _a || _a.call(this); jqIframeNode.hide(0, (() => { jqIframeNode.css("height", originHeight + "px"); frameParentNode.removeClass("VOEOC_LOADING"); jqIframeNode.slideDown("normal"); })); })); })); } } class MainPage { constructor() { this.currentHash = window.location.hash; this.currentScrollYPos = NaN; this.storagePageData = { lzId: "", floorDataList: new Map, someKey: { host: "tieba.baidu_mobile_expand.com", tid: "", postAuthorId: "", forumId: "", source: "" } }; this.firstFloor = new FirstFloor; ah.hook({ onreadystatechange: (xhr, ev) => { if (xhr.readyState === XMLHttpRequest.DONE) { const url = xhr.responseURL, resText = xhr.responseText; REGEXP_PBDATA.test(url) && "" !== resText && this.parsePbData(resText, url); } return !1; } }, unsafeWindow); unsafeWindow.onscroll = () => { this.checkUrlHashChange(); GET_PAGE_TYPE() === PAGE_TYPE.POSTPAGE && 0 !== window.scrollY && (this.currentScrollYPos = window.scrollY); }; unsafeWindow.onhashchange = () => { this.checkUrlHashChange(); }; } tryCollectSomeKey() { this.storagePageData.someKey.host = window.location.hostname; let tid, postAuthorId, forumId, source; ((tid = GET_URL_ATTR(this.currentHash, "tid")) || (tid = window.location.pathname.replace("/p/", "")) && !isNaN(tid)) && (this.storagePageData.someKey.tid = tid); void 0 !== (postAuthorId = GET_URL_ATTR(this.currentHash, "postAuthorId")) && (this.storagePageData.someKey.postAuthorId = postAuthorId); void 0 !== (forumId = GET_URL_ATTR(this.currentHash, "forumId")) && (this.storagePageData.someKey.forumId = forumId); void 0 !== (source = GET_URL_ATTR(this.currentHash, "source")) && (this.storagePageData.someKey.source = source); } static GET_MAIN_URL() { return window.location.href.replace(window.location.hash, ""); } tryGetFirstFloor() { return this.firstFloor.waitInit().then(); } tryGotoPostPage() { return new Promise(((resolve, reject) => { if (GET_PAGE_TYPE() !== PAGE_TYPE.POSTPAGE) { this.tryCollectSomeKey(); this.currentScrollYPos = 0; MainPage.scrollTo(0); jquerySearcher.wait(".post-item").then((() => { var _a; const postbtn = document.querySelector(".post-page-entry-btn"); if (postbtn && (null === (_a = settingDatas.isAutoGotoPostPage) || void 0 === _a ? void 0 : _a.value)) { postbtn.click(); resolve(void 0); this.checkUrlHashChange(!1, PAGE_TYPE.MAINPAGE); } else { resolve(void 0); this.checkUrlHashChange(!0); } })).catch(reject); } else { this.checkUrlHashChange(!0); resolve(void 0); } })); } restorePostPage() { var _a; if (null === (_a = this.firstFloor) || void 0 === _a ? void 0 : _a.tieNode) this.firstFloor.restorePostPageTitle().then((() => { this.firstFloor.restorePostPageFirstFloor().finally(); })); else { const firstFloorFrameUtils = new FirstFloorFrame; firstFloorFrameUtils.onload = () => { this.firstFloor = firstFloorFrameUtils.firstFloor; MainPage.scrollTo(this.currentScrollYPos + this.firstFloor.height - 50); firstFloorFrameUtils.firstFloor.restorePostPageTitle().finally(); }; } } listenFloorChange(floorParentNode) { const searchAndUpdatePostPage = () => { let floorNodeList = floorParentNode.querySelectorAll("div.post-item:not(.VOEOCMARK)"); floorNodeList.forEach((value => { this.onNewFloorAdded.call(this, value); })); }; let observer = new MutationObserver((_mutationList => { searchAndUpdatePostPage(); })); observer.observe(floorParentNode, { attributes: !1, childList: !0, characterData: !1, subtree: !1 }); searchAndUpdatePostPage(); } checkUrlHashChange(force = !1, lastPageType) { var _a; if (this.currentHash !== window.location.hash) this.currentHash = window.location.hash; else if (!force) return !1; let pageType = GET_PAGE_TYPE(); if (pageType === PAGE_TYPE.POSTPAGE) { PAGE_TYPE.MAINPAGE; this.tryCollectSomeKey(); jquerySearcher.wait(".post-page-list").then((postpagelist => { this.listenFloorChange(postpagelist[0]); })); this.restorePostPage(); MainPage.scrollTo(this.currentScrollYPos); } else if (pageType === PAGE_TYPE.MAINPAGE) { jquerySearcher.wait(".pb-page-wrapper").then((pbpageNode => { this.listenFloorChange(pbpageNode[0]); })); MainPage.scrollTo(0); } null === (_a = this.onEnterFinalPage) || void 0 === _a || _a.call(this); return !0; } static scrollTo(yPos, documentNode = document) { jquerySearcher.wait(".post-page").then((() => { documentNode.documentElement.scrollTop = yPos; setTimeout((() => { documentNode.documentElement.scrollTop = yPos; }), 200); })).catch(); } parsePbData(responseText, responseURL) { AUTO_CATCH_ERROR((() => { var _a, _b; let data; data = "object" == typeof responseText ? responseText.data : JSON.parse(responseText).data; ASSERT(data, "无法获取PBDATA"); (null === (_a = null == data ? void 0 : data.forum) || void 0 === _a ? void 0 : _a.id) && (this.storagePageData.someKey.forumId = data.forum.id); (null === (_b = null == data ? void 0 : data.thread) || void 0 === _b ? void 0 : _b.id) && (this.storagePageData.someKey.tid = data.thread.id); AUTO_CATCH_ERROR((() => { let post_list = data.post_list; if (!post_list) throw new Error(`该PBDATA没有post_list数据, ${data}`); AUTO_CATCH_ERROR((() => { if ("1" === GET_URL_ATTR(responseURL, "pn")) { this.storagePageData.lzId = post_list[0].author.id; this.storagePageData.someKey.postAuthorId = this.storagePageData.lzId; this.storagePageData.lzId; } })); for (let i = 0; i < post_list.length; i++) { let d = post_list[i]; this.storagePageData.floorDataList.set(d.floor.toString(), d); } })); this.storagePageData.someKey; })); } } class VoeocDialog { constructor(historyState, dialogNode) { this.historyState = historyState; this.dialogNode = dialogNode; this.dialogNode && !this.dialogNode.classList.contains(VoeocDialog.STR_CLASSNAME_DIALOG) && this.dialogNode.classList.add(VoeocDialog.STR_CLASSNAME_DIALOG); } static initHistoryStateManager() { HistoryStateManager.getInstance().init(); } getHistoryState() { return this.historyState; } show() { var _b, _c; null === (_c = null === (_b = this.dialogNode) || void 0 === _b ? void 0 : _b.classList) || void 0 === _c || _c.add(VoeocDialog.STR_CLASSNAME_SHOW_TAG); } hide() { var _b, _c; null === (_c = null === (_b = this.dialogNode) || void 0 === _b ? void 0 : _b.classList) || void 0 === _c || _c.remove(VoeocDialog.STR_CLASSNAME_SHOW_TAG); } isShown() { var _b, _c; return (null === (_c = null === (_b = this.dialogNode) || void 0 === _b ? void 0 : _b.classList) || void 0 === _c ? void 0 : _c.contains(VoeocDialog.STR_CLASSNAME_SHOW_TAG)) || !1; } open() { HistoryStateManager.getInstance().showNewDialog(this); } close() { HistoryStateManager.getInstance().closeLastDialog(); } } VoeocDialog.STR_CLASSNAME_DIALOG = "VOEOC_DIALOG"; VoeocDialog.STR_CLASSNAME_SHOW_TAG = "VOEOC_DIALOG_SHOW"; class HistoryStateManager { constructor() { _HistoryStateManager_showDialogList.set(this, void 0); } static getInstance() { __classPrivateFieldGet(HistoryStateManager, _a, "f", _HistoryStateManager_instance) || __classPrivateFieldSet(HistoryStateManager, _a, new HistoryStateManager, "f", _HistoryStateManager_instance); return __classPrivateFieldGet(HistoryStateManager, _a, "f", _HistoryStateManager_instance); } init() { __classPrivateFieldSet(this, _HistoryStateManager_showDialogList, new Stack, "f"); window.addEventListener("popstate", (() => { var _b, _c; (null === (_b = __classPrivateFieldGet(this, _HistoryStateManager_showDialogList, "f")) || void 0 === _b ? void 0 : _b.isEmpty()) || (null === (_c = __classPrivateFieldGet(this, _HistoryStateManager_showDialogList, "f")) || void 0 === _c ? void 0 : _c.peek().isShown()) && this.closeLastDialog(); }), !1); } showNewDialog(voeocDialog) { var _b, _c, _d; if (!voeocDialog.isShown()) { voeocDialog.show(); window.history.pushState(voeocDialog.getHistoryState(), null !== (_c = null === (_b = voeocDialog.getHistoryState()) || void 0 === _b ? void 0 : _b.title) && void 0 !== _c ? _c : ""); null === (_d = __classPrivateFieldGet(this, _HistoryStateManager_showDialogList, "f")) || void 0 === _d || _d.push(voeocDialog); } } closeLastDialog() { var _b, _c, _d, _e; if (null === (_b = __classPrivateFieldGet(this, _HistoryStateManager_showDialogList, "f")) || void 0 === _b ? void 0 : _b.isEmpty()) return; let hiddenDialog = null === (_c = __classPrivateFieldGet(this, _HistoryStateManager_showDialogList, "f")) || void 0 === _c ? void 0 : _c.peek(); if (null == hiddenDialog ? void 0 : hiddenDialog.isShown()) { if (window.history.state && window.history.state.id && window.history.state.id === (null === (_d = null == hiddenDialog ? void 0 : hiddenDialog.getHistoryState()) || void 0 === _d ? void 0 : _d.id)) { window.history.back(); return; } null == hiddenDialog || hiddenDialog.hide(); null === (_e = __classPrivateFieldGet(this, _HistoryStateManager_showDialogList, "f")) || void 0 === _e || _e.pop(); } } } _a = HistoryStateManager, _HistoryStateManager_showDialogList = new WeakMap; _HistoryStateManager_instance = { value: void 0 }; function SettingFrameInit(iframeUtils) { const contentDocument = iframeUtils.contentDocument; function onRangeChange() { const numNode = this.parentNode.previousElementSibling.querySelector("span"); numNode.innerHTML = this.value; } function onMulSwitchChange() { const radioElements = this.parentNode.querySelectorAll("input[type=radio]"); radioElements[0] && (radioElements[0].checked = this.checked); radioElements[1] && (radioElements[1].checked = !this.checked); } function bindSwitch(switchElement, bindElement) { switchElement.onchange = () => { switchElement.checked ? bindElement.classList.remove("disable") : bindElement.classList.add("disable"); }; switchElement.onchange(); } function getElementByName(name) { return contentDocument.querySelector(`input[name=${name}]`); } (() => { const allInputElements = function getAllInputElements() { const allInputElements = new Map; for (let settingKey in settingDatas) allInputElements.set(settingKey, getElementByName(settingKey)); return allInputElements; }(); bindSwitch(allInputElements.get("isAutoExpand"), allInputElements.get("autoExpandNum").parentElement.parentElement); bindSwitch(allInputElements.get("isRemaindAutoExpand"), allInputElements.get("remaindAutoExpandSize").parentElement.parentElement); const rangeElements = contentDocument.querySelectorAll("input[type=range]"); rangeElements.forEach((rangeElement => { rangeElement.onchange = onRangeChange; rangeElement.oninput = onRangeChange; })); const mulSwitchElements = contentDocument.querySelectorAll("input.mul_switch"); mulSwitchElements.forEach((mulSwitchElement => { mulSwitchElement.onchange = onMulSwitchChange; })); })(); } class SettingsDialog extends VoeocDialog { constructor(parentNode, settingDatas) { super({ title: "设置窗口", id: "SettingsDialog" }, parentNode.ownerDocument.createElement("div")); this.dialogNode.classList.add("VOEOC_DIALOG_BACKGROUND"); parentNode.appendChild(this.dialogNode); const iframeUtils = new IframeUtils(this.dialogNode, "VOEOC-ID-SETTING-FRAME"); iframeUtils.iframeNode.ontouchmove = STOPPROPAGATION; iframeUtils.iframeNode.onpointermove = STOPPROPAGATION; iframeUtils.iframeNode.onscroll = STOPPROPAGATION; iframeUtils.writeDoc('Title
'); SettingFrameInit(iframeUtils); const contentDocument = iframeUtils.contentDocument, btnSaveAndClose = contentDocument.getElementById("btnSaveAndClose"), btnSave = contentDocument.getElementById("btnSave"), btnClose = contentDocument.getElementById("btnClose"), allInputElements = new Map, originSettingsData = new Map(Object.entries(settingDatas)); originSettingsData.forEach(((settingValue, key) => { const inputElement = contentDocument.querySelector(`input[name=${key}]`); if (inputElement) { allInputElements.set(key, inputElement); !function SET_INPUT_ELEMENT_VALUE(inputElement, value) { "checkbox" === inputElement.type ? inputElement.checked = value : inputElement.value = String(value); inputElement.onchange && inputElement.onchange(void 0); }(inputElement, settingValue.value); } })); btnSaveAndClose.onclick = () => { btnSave.click(); btnClose.click(); window.location.reload(); }; btnSave.onclick = () => { allInputElements.forEach(((element, key) => { const settingValue = originSettingsData.get(key); settingValue && (settingValue.value = function GET_INPUT_ELEMENT_VALUE(inputElement) { switch (inputElement.type) { case "checkbox": return inputElement.checked; case "range": return Number(inputElement.value); default: return inputElement.value; } }(element)); })); btnClose.click(); }; btnClose.onclick = () => { this.close(); }; } hide() { super.hide(); this.dialogNode.remove(); } } var _CustomLzlExpandManager_instances, _CustomLzlExpandManager_showError, _CustomLzlExpandManager_startExpandAnimation, _CustomLzlExpandManager_endExpandAnimation, _CustomLzlExpandManager_destroy; class CustomLzlExpandManager { constructor(floorNode, expandBtnNode, floorPbData, someKey) { var _a, _b, _c, _d, _e; _CustomLzlExpandManager_instances.add(this); ASSERT(floorNode, "floorNode is null"); this.lzlInfo = { floorPbData: floorPbData, someKey: someKey, lzTagHTML: "", data_v_a: "lines-v-a", data_v_b: "lines-v-b", expandNum: 0, currentPageNum: 1, floorNum: String(null == floorPbData ? void 0 : floorPbData.floor), pageSize: (null === (_a = settingDatas.eachExpandSize) || void 0 === _a ? void 0 : _a.value) < 10 ? 10 : null === (_b = settingDatas.eachExpandSize) || void 0 === _b ? void 0 : _b.value, pid: null == floorPbData ? void 0 : floorPbData.id, floorNode: floorNode, lzlNode: floorNode.querySelector("div.lzl-post"), expandBtnNode: expandBtnNode, expandBtnTextNode: document.createElement("span") }; this.lzlInfo.originItemNodeList = this.lzlInfo.lzlNode.getElementsByClassName("lzl-post-item"); this.lzlInfo.sampleItemNode = this.lzlInfo.originItemNodeList[0].cloneNode(!0); let dvList = []; for (let dv in null === (_d = null === (_c = this.lzlInfo.originItemNodeList[0]) || void 0 === _c ? void 0 : _c.querySelector(".thread-text")) || void 0 === _d ? void 0 : _d.dataset) dvList.push(`data-v-${dv.slice(1).replace("-", "")}`); this.lzlInfo.data_v_a = dvList[0]; this.lzlInfo.data_v_b = dvList[1]; this.lzlInfo.lzTagHTML = ``; this.lzlInfo.expandBtnTextNode.className = "open-app-text-real"; this.lzlInfo.expandBtnTextNode.innerHTML = "展开评论"; let timeOutEvent, clickFunc = this.expandLzl.bind(this), longClickFunc = this.expandLzl.bind(this); expandBtnNode.ontouchstart = () => { timeOutEvent = setTimeout((() => { timeOutEvent = 0; longClickFunc(); }), 500); return !1; }; expandBtnNode.ontouchend = () => { clearTimeout(timeOutEvent); 0 !== timeOutEvent && clickFunc(); return !1; }; expandBtnNode.ontouchmove = () => { clearTimeout(timeOutEvent); timeOutEvent = 0; }; expandBtnNode.onmousedown = expandBtnNode.ontouchstart.bind(expandBtnNode); expandBtnNode.onmouseup = expandBtnNode.ontouchend.bind(expandBtnNode); expandBtnNode.onmousemove = expandBtnNode.ontouchmove.bind(expandBtnNode); expandBtnNode.insertBefore(this.lzlInfo.expandBtnTextNode, expandBtnNode.children[0]); if (null === (_e = settingDatas.isAutoExpand) || void 0 === _e ? void 0 : _e.value) { this.lzlInfo.floorNum; this.expandLzl(); } } expandLzl(isTheLast = !1, waitFinishFunc) { ASSERT(this.lzlInfo.expandBtnNode, `尝试展开不存在的评论区,楼层号${this.lzlInfo.floorNum}`); const url = `${window.origin}/mg/o/getFloorData?pn=${this.lzlInfo.currentPageNum}&rn=${this.lzlInfo.pageSize}&tid=${this.lzlInfo.someKey.tid}&pid=${this.lzlInfo.pid}`; this.lzlInfo.floorNum; const onerror = () => { __classPrivateFieldGet(this, _CustomLzlExpandManager_instances, "m", _CustomLzlExpandManager_endExpandAnimation).call(this); __classPrivateFieldGet(this, _CustomLzlExpandManager_instances, "m", _CustomLzlExpandManager_showError).call(this, !0); }, abortFunc = GM_xmlhttpRequest({ method: "GET", url: url, onload: details => { var _a, _b, _c, _d; __classPrivateFieldGet(this, _CustomLzlExpandManager_instances, "m", _CustomLzlExpandManager_endExpandAnimation).call(this); let floorData, subPostList; try { floorData = JSON.parse(details.responseText); subPostList = floorData.data.sub_post_list; ASSERT(subPostList && 0 !== subPostList.length, "sub_post_list为空"); } catch (e) { __classPrivateFieldGet(this, _CustomLzlExpandManager_instances, "m", _CustomLzlExpandManager_showError).call(this, !0); return; } __classPrivateFieldGet(this, _CustomLzlExpandManager_instances, "m", _CustomLzlExpandManager_showError).call(this, !1); if (1 === this.lzlInfo.currentPageNum && this.lzlInfo.originItemNodeList && this.lzlInfo.lzlNode) for (let i = this.lzlInfo.originItemNodeList.length - 1; i > -1; i--) this.lzlInfo.lzlNode.removeChild(this.lzlInfo.originItemNodeList[i]); subPostList.forEach((subpost => { var _a, _b; let contentHTML = ""; subpost.content.forEach((subContent => { let itemHTML; switch (subContent.type) { case 2: itemHTML = `${subContent.text}`; break; case 4: itemHTML = subContent.uid === this.lzlInfo.someKey.postAuthorId ? ` ${subContent.text} ${this.lzlInfo.lzTagHTML} ` : ` ${subContent.text} `; break; default: itemHTML = `${subContent.text}`; } contentHTML += itemHTML; })); let newItemNode = null === (_a = this.lzlInfo.sampleItemNode) || void 0 === _a ? void 0 : _a.cloneNode(!0); if (newItemNode && this.lzlInfo.expandBtnNode) { newItemNode.querySelector(".username").innerHTML = `${subpost.author.show_nickname} ${this.lzlInfo.someKey.postAuthorId === subpost.author.id ? this.lzlInfo.lzTagHTML : ""}:`; newItemNode.querySelector(".thread-text").innerHTML = contentHTML; null === (_b = this.lzlInfo.lzlNode) || void 0 === _b || _b.insertBefore(newItemNode, this.lzlInfo.expandBtnNode); } })); let pageinfo = floorData.data.page, total_page = parseInt(pageinfo.total_page); if (total_page > this.lzlInfo.currentPageNum) { this.lzlInfo.currentPageNum++; let total_num = parseInt(pageinfo.total_num), remaind_num = total_num - this.lzlInfo.pageSize * (this.lzlInfo.currentPageNum - 1); this.lzlInfo.expandBtnNode && (this.lzlInfo.expandBtnNode.children[0].innerHTML = (num => `剩余${num}个评论`)(remaind_num)); (null === (_a = settingDatas.isRemaindAutoExpand) || void 0 === _a ? void 0 : _a.value) && (null === (_b = settingDatas.remaindAutoExpandSize) || void 0 === _b ? void 0 : _b.value) > remaind_num ? isTheLast || this.expandLzl(!0) : (null === (_c = settingDatas.isAutoExpand) || void 0 === _c ? void 0 : _c.value) && this.lzlInfo.expandNum < (null === (_d = settingDatas.autoExpandNum) || void 0 === _d ? void 0 : _d.value) && this.expandLzl(); } else __classPrivateFieldGet(this, _CustomLzlExpandManager_instances, "m", _CustomLzlExpandManager_destroy).apply(this); this.lzlInfo.expandNum++; }, onerror: onerror, onabort: onerror, ontimeout: onerror }); abortFunc && __classPrivateFieldGet(this, _CustomLzlExpandManager_instances, "m", _CustomLzlExpandManager_startExpandAnimation).call(this, abortFunc.abort); } } _CustomLzlExpandManager_instances = new WeakSet, _CustomLzlExpandManager_showError = function _CustomLzlExpandManager_showError(isError = !0) { var _a, _b; isError ? null === (_a = this.lzlInfo.expandBtnTextNode) || void 0 === _a || _a.classList.add("error") : null === (_b = this.lzlInfo.expandBtnTextNode) || void 0 === _b || _b.classList.remove("error"); }, _CustomLzlExpandManager_startExpandAnimation = function _CustomLzlExpandManager_startExpandAnimation(abortFunc) { this.lzlInfo.expandBtnNode && this.lzlInfo.expandBtnNode.classList.add("loading"); this.expandTimeoutTimer = setTimeout((() => { __classPrivateFieldGet(this, _CustomLzlExpandManager_instances, "m", _CustomLzlExpandManager_endExpandAnimation).call(this); __classPrivateFieldGet(this, _CustomLzlExpandManager_instances, "m", _CustomLzlExpandManager_showError).call(this, !0); abortFunc(); }), 5e3); }, _CustomLzlExpandManager_endExpandAnimation = function _CustomLzlExpandManager_endExpandAnimation() { this.lzlInfo.expandBtnNode && this.lzlInfo.expandBtnNode.classList.remove("loading"); if (this.expandTimeoutTimer) { clearTimeout(this.expandTimeoutTimer); this.expandTimeoutTimer = void 0; } }, _CustomLzlExpandManager_destroy = function _CustomLzlExpandManager_destroy() { var _a; try { if (this.lzlInfo.expandBtnNode) { this.lzlInfo.expandBtnNode.style.display = "none"; null === (_a = this.lzlInfo.expandBtnNode.parentNode) || void 0 === _a || _a.removeChild(this.lzlInfo.expandBtnNode); this.lzlInfo.expandBtnNode = void 0; } } finally {} }; const HIDE_MAIN_PAGE = (() => { let timer, styleElement; GM_addStyle("html {transition: opacity 0.4s}"); return (isHidden = !0) => { if (styleElement) { styleElement.remove(); styleElement = void 0; } if (isHidden) { styleElement = GM_addStyle("html {opacity: 0.2;}"); clearTimeout(timer); timer = setTimeout((() => { HIDE_MAIN_PAGE(!1); }), 5e3); } }; })(), OPEN_SETTING_DIALOG = () => { var _a; null === (_a = new SettingsDialog(document.body, settingDatas)) || void 0 === _a || _a.open(); }, tryInitMainPage = (() => { let mainPage; return () => { if (mainPage) return mainPage; GM_addStyle(CSS_REMOVE + ':root {\r\n --str_lzl_page_transition_duration: 0.2s;\r\n}\r\n.open-app-text-real {\r\n display: block !important;\r\n -webkit-box-flex: 0;\r\n -webkit-flex: none;\r\n -ms-flex: none;\r\n flex: none;\r\n font-size: .13rem;\r\n color: #614ec2;\r\n}\r\n.open-app-text-real.error {\r\n color: #ff3366 !important;\r\n text-decoration: line-through;\r\n}\r\n\r\n@keyframes rotate3d {\r\n 0%{-webkit-transform:rotate3d(1, 0, 0, 0deg);}\r\n 25%{-webkit-transform:rotate3d(1, 0, 0, 90deg);}\r\n 50%{-webkit-transform:rotate3d(1, 0, 0, 180deg);}\r\n 75%{-webkit-transform:rotate3d(1, 0, 0, 270deg);}\r\n 100%{-webkit-transform:rotate3d(1, 0, 0, 360deg);}\r\n}\r\n.open-app-guide.VOEOC_LOADING {\r\n animation: rotate3d 0.5s linear infinite;\r\n pointer-events: none;\r\n}\r\n.VOEOC_DIALOG {\r\n position: fixed;\r\n z-index: 999;\r\n height: 0;\r\n visibility: hidden;\r\n transition: visibility var(--str_lzl_page_transition_duration);\r\n}\r\n.VOEOC_DIALOG.VOEOC_DIALOG_SHOW {\r\n display: block;\r\n height: 100%;\r\n visibility: visible;\r\n}\r\n#VOEOC-ID-LZLPAGE {\r\n overscroll-behavior: none;\r\n width: 100%;\r\n overflow: scroll;\r\n}\r\n#VOEOC-ID-LZLPAGE::-webkit-scrollbar { width: 0 !important }\r\n#VOEOC-ID-LZLPAGEBACKGROUND {\r\n position: fixed;\r\n width: 100%;\r\n height: 200%;\r\n background-color: #00000077;\r\n z-index: 1;\r\n opacity: 0;\r\n transition: opacity var(--str_lzl_page_transition_duration);\r\n}\r\n.VOEOC-CLASSNAME-LZLPAGEIFRAME {\r\n position: fixed;\r\n width: 100%;\r\n height: 0%;\r\n background-color: #ffffff;\r\n bottom: 0;\r\n transition: height var(--str_lzl_page_transition_duration);\r\n overflow: hidden;\r\n}\r\n#VOEOC-ID-LZLPAGE.VOEOC_LOADING, #VOEOC-ID-LZLPAGE.VOEOC_LOADING > .VOEOC-CLASSNAME-LZLPAGEIFRAME {\r\n pointer-events: none;\r\n}\r\n#VOEOC-ID-LZLPAGE.VOEOC_DIALOG_SHOW > .VOEOC-CLASSNAME-LZLPAGEIFRAME.VOEOC_DIALOG_SHOW {\r\n height: 80%;\r\n}\r\n#VOEOC-ID-LZLPAGE.VOEOC_DIALOG_SHOW > #VOEOC-ID-LZLPAGEBACKGROUND {\r\n opacity: 1;\r\n}\r\n#VOEOC-ID-LZLPAGE.VOEOC_DIALOG_SHOW > .lzl-reload-btn {\r\n margin-left: 0.1rem;\r\n}\r\n\r\n.circle_loading {\r\n position: relative;\r\n width: 30px;\r\n height: 30px;\r\n border: 2px solid rgba(0, 176, 255, 0.3);\r\n border-left-color: #00b0ff;\r\n border-radius: 100%;\r\n animation: circle infinite 0.75s linear;\r\n}\r\n@keyframes circle {\r\n 0% {\r\n transform: rotate(0);\r\n }\r\n 100% {\r\n transform: rotate(360deg);\r\n }\r\n}\r\n#VOEOC_ID_FIRST_FLOOR_IFRAME_CONTAINER {\r\n position: relative;\r\n min-height: 50px;\r\n}\r\n#VOEOC_ID_FIRST_FLOOR_IFRAME_CONTAINER.VOEOC_LOADING{\r\n pointer-events: none;\r\n}\r\n#VOEOC_ID_FIRST_FLOOR_IFRAME_CONTAINER > .circle_loading{\r\n display: none;\r\n position: absolute;\r\n left: 0;\r\n top: 0;\r\n right: 0;\r\n bottom: 0;\r\n margin: auto;\r\n}\r\n#VOEOC_ID_FIRST_FLOOR_IFRAME_CONTAINER.VOEOC_LOADING > .circle_loading{\r\n display: block;\r\n}\r\n#VOEOC_ID_FIRST_FLOOR_IFRAME_CONTAINER.VOEOC_LOADING > iframe {\r\n opacity: 0.2;\r\n}\r\n#VOEOC_ID_FIRST_FLOOR_IFRAME_CONTAINER > iframe {\r\n display: block;\r\n width: 100%;\r\n height: 0;\r\n border: 0;\r\n padding: 0;\r\n /*height: 1rem;*/\r\n /*transition: all 0.2s;*/\r\n}\r\n.lzl-nav-btn.lzl-reload-btn {\r\n position:fixed;\r\n top:20%;\r\n margin: 0.1rem 0.1rem 0.1rem -0.5rem;\r\n transition: margin-left var(--str_lzl_page_transition_duration);\r\n}\r\n.lzl-nav-btn {\r\n width: .32rem;\r\n height: .32rem;\r\n display: flex;\r\n background-color:#d0d0d04a;\r\n border-radius:50%;\r\n cursor: pointer;\r\n}\r\n.lzl-nav-btn > *{\r\n position: relative;\r\n top: 50%;\r\n left: 50%;\r\n transform: translate(-50%, -50%);\r\n height: fit-content;\r\n width: fit-content;\r\n}\r\n@keyframes rotate {\r\n 0%{-webkit-transform:rotate(0deg);}\r\n 25%{-webkit-transform:rotate(90deg);}\r\n 50%{-webkit-transform:rotate(180deg);}\r\n 75%{-webkit-transform:rotate(270deg);}\r\n 100%{-webkit-transform:rotate(360deg);}\r\n}\r\n#VOEOC-ID-LZLPAGE.VOEOC_LOADING > .lzl-reload-btn {\r\n animation: rotate 0.2s linear infinite;\r\n pointer-events: none;\r\n }\r\n#VOEOC-ID-LZLPAGE.error > .lzl-reload-btn {\r\n background-color: #ff000070 !important;\r\n }\r\n.slide-down-btn{\r\n position: fixed;\r\n top: 20%;\r\n left: 50%;\r\n margin-left: -0.32rem;\r\n opacity: 0;\r\n transition: opacity,margin-top,background-color 0.1s;\r\n}\r\n.slide-down-btn.confirm{\r\n background-color: #0000004a;\r\n}\r\n#VOEOC-ID-SETTING-FRAME {\r\n height: 100%;\r\n width: 100%;\r\n position: fixed;\r\n z-index: 9999;\r\n display: block;\r\n border: 0;\r\n padding: 0;\r\n left: 0;\r\n top: 0;\r\n overscroll-behavior: none;\r\n background-color: white;\r\n}\r\n\r\n.VOEOC_DIALOG_BACKGROUND {\r\n position: fixed;\r\n width: 100%;\r\n height: 101%;\r\n left: 0;\r\n top: 0;\r\n z-index: 9999;\r\n overflow: scroll;\r\n overscroll-behavior: none;\r\n background-color: #00000077;\r\n transition: opacity var(--str_lzl_page_transition_duration);\r\n}\r\n.VOEOC_DIALOG_BACKGROUND::before {\r\n content: " ";\r\n width: 100%;\r\n height: 101%;\r\n display: block;\r\n overscroll-behavior: none;\r\n}\r\n.VOEOC_DIALOG_BACKGROUND::-webkit-scrollbar,\r\n.VOEOC_DIALOG_BACKGROUND::before::-webkit-scrollbar {\r\n width: 0 !important;\r\n}'); mainPage = new MainPage; mainPage.onEnterFinalPage = () => { jquerySearcher.wait(".nav-bar-top").then((navbar => { HIDE_MAIN_PAGE(!1); const id = "VOEOC-ID-SETTINGBTNNODE"; if (document.getElementById(id)) return; const settingBtnNode = $__default.default(`
设置
`); settingBtnNode.on("click", OPEN_SETTING_DIALOG); navbar.append(settingBtnNode); (() => { GM_registerMenuCommand("设置", OPEN_SETTING_DIALOG, "VOEOC_MENU_ACCESS_KEY_SETTINGS"); })(); VoeocDialog.initHistoryStateManager(); jquerySearcher.wait(".post-show-more").then((btnShowMore => { btnShowMore.trigger("click"); })).catch(); })); }; mainPage.onNewFloorAdded = floorNode => { if (!floorNode.classList.contains("VOEOCMARK")) { floorNode.classList.add("VOEOCMARK"); AUTO_CATCH_ERROR((() => { let floorNum, expandBtnNode = floorNode.querySelector(".open-app-guide"); if (!expandBtnNode) return; let floorinfoNode = floorNode.querySelector(".floor-info"); floorNum = floorinfoNode ? MATCH_REG(RegExp(/第(\d+)楼/, "i"), floorinfoNode.innerHTML) : floorNode.getAttribute("data-floor"); if (!floorNum) throw new Error("无法获取楼层数"); new CustomLzlExpandManager(floorNode, expandBtnNode, mainPage.storagePageData.floorDataList.get(floorNum), mainPage.storagePageData.someKey); })); } }; return mainPage; }; })(); (() => { window.addEventListener("load", (() => { setTimeout((() => { HIDE_MAIN_PAGE(!1); }), 1e3); })); switch (GET_PAGE_TYPE()) { case PAGE_TYPE.MAINPAGE: window.location.href; HIDE_MAIN_PAGE(!0); const mainPage = tryInitMainPage(); mainPage.tryGetFirstFloor().then((() => { mainPage.tryGotoPostPage().finally((() => { HIDE_MAIN_PAGE(!1); })); })); break; case PAGE_TYPE.POSTPAGE: window.location.href; tryInitMainPage().tryGotoPostPage().finally((() => { HIDE_MAIN_PAGE(!1); })); break; case PAGE_TYPE.LZLPAGE: default: window.location.href; } })(); }($);