您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
auto load item detail when mouseover title
// ==UserScript== // @name v2ex+ // @namespace http://tampermonkey.net/ // @version 0.19 // @description auto load item detail when mouseover title // @author Silvio27 // @match https://*.v2ex.com/* // @match https://v2ex.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=v2ex.com // @license GPLv3 // @grant GM_addStyle // @grant GM_registerMenuCommand // ==/UserScript== (function() { 'use strict'; console.log("script") topics_node_page(true, true, true, 600) member_replies_page(true, false, false, 0) linksToImgs() const menu_command_id = GM_registerMenuCommand("加载页面全部内容", function () { document.querySelectorAll(".triangle").forEach(e => {setTimeout(e.click(), 500)}) }, "a"); function topics_node_page(show_topic, show_fav_btn, show_reply, defaultHeight) { let topics if (document.getElementById("TopicsNode")) { // alert("TopicsNode") topics = document.querySelectorAll("#TopicsNode>.cell") } else { // alert("No TopicsNode") topics = document.querySelectorAll(".cell.item") } topics.forEach((element, index) => { let new_item = create_item("td", element.querySelector("tr"), element.querySelector("tr").lastElementChild, '▼', "triangle", 30) // 修改cursor_style cursor_style(new_item) new_item.onclick = function () { let url = element.querySelector(".topic-link").href let id = url.replace("https://www.v2ex.com/t/", "").split("#")[0] + "_topic" load_item_change_btn(element, id, url, new_item, show_topic, show_fav_btn, show_reply, defaultHeight) } }) } function member_replies_page(show_topic, show_fav_btn, show_reply, defaultHeight) { let dock_areas = document.querySelectorAll(".dock_area") dock_areas.forEach((element, index) => { // 创建新的列 let new_item = create_item("span", element.querySelector("td"), "", '▼', "triangle", 30) cursor_style(new_item) new_item.onclick = function () { let url = element.querySelectorAll("a")[2].href let id = url.replace("https://www.v2ex.com/t/", "").split("#")[0] + "_reply" load_item_change_btn(element, id, url, new_item, show_topic, show_fav_btn, show_reply, defaultHeight) } }) } function load_item_change_btn(element, id, url, btn, show_topic, show_fav_btn, show_reply, defaultHeight) { let content = document.getElementById(id) if (content) { if (content.style.display === "none") { content.style.display = "block" btn.innerText = "▲" } else { content.style.display = "none" btn.innerText = "▼" } } else { btn.innerText = "加载中" document.body.style.cursor = "wait"; btn.className = "content-loaded" load_item_topic_favBtn_reply(element, url, id, btn, show_topic, show_fav_btn, show_reply, defaultHeight) } } function load_item_topic_favBtn_reply(target_ele, url, id, load_btn, show_topic, show_fav_btn, show_reply, defaultHeight) { // 创建一个临时容器元素来容纳加载的内容 const tempContainer = document.createElement('div'); // 使用Ajax异步加载下一页的内容 const xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.onload = function () { if (xhr.status === 200) { tempContainer.innerHTML = xhr.responseText // 创建返回的内容元素 let contents = document.createElement('div') contents.id = id contents.className = "woDeStyle" // 绑定Escape折叠contents mouse_escape(contents) if (show_topic) { // 获得 topic_content let topic_contents = tempContainer.querySelectorAll(".topic_content") contents.innerHTML += '<div class="topic-content-box"></div>' topic_contents.forEach((e) => { // 即 .topic-content-box contents.firstChild.appendChild(e.parentElement) }) } if (show_fav_btn) { // 添加topic_buttons let favorite_btn = tempContainer.querySelector(".topic_buttons") // 点击收藏,页面在新标签中打开 let fav_ele = favorite_btn.querySelector("a") fav_ele.onclick = function (e) { // 阻止原始a标签打开新页面 e.preventDefault() // 后台发送xhr mark_favourite(this) } contents.firstElementChild.appendChild(favorite_btn) } if (show_reply) { // todo 展示不清楚为什么box会出现不同的情况,待研究 // 获得 reply_content let reply_box = tempContainer.querySelectorAll(".box") reply_box.forEach((e, index) => { if (e.innerText.includes("条回复")) { contents.appendChild(e) } }) // 去除reply_content中头像及空格 contents.querySelectorAll("tbody>tr").forEach((e) => { e.removeChild(e.firstElementChild) e.removeChild(e.firstElementChild) }) // 添加一个折叠按钮 todo 是否可以直接把tr中添加的拿来用? let hideBtn = document.createElement("div") hideBtn.innerText = "▲" hideBtn.className = "content-loaded" hideBtn.style.textAlign = "right" hideBtn.onclick = (() => { // 隐藏主题详情 contents.style.display = "none" // 切换主题展开为关闭 contents.parentElement.querySelector(".content-loaded").innerText = "▼" }) cursor_style(hideBtn) contents.appendChild(hideBtn) } // content添加到target_ele target_ele.appendChild(contents) // 解析markdown图片 linksToImgs() // 设置默认高度 set_content_default_height(contents, defaultHeight) // 修改折叠按钮为展开,切换样式 set_btn_up(load_btn) } }; xhr.send(); } function cursor_style(element) { element.addEventListener("mouseover", function () { document.body.style.cursor = "pointer"; }); element.addEventListener("mouseout", function () { document.body.style.cursor = "auto"; }); } function create_item(tagName, element, element_place, inner_text, class_name, width) { let item = document.createElement(tagName) item.setAttribute("width", width) item.setAttribute("align", "center") item.setAttribute("class", class_name) item.innerText = inner_text if (element_place) { element.insertBefore(item, element_place) } else { element.appendChild(item) } return item } function mark_favourite(ele) { let url = ele.href const xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.onload = function () { if (xhr.status === 200) { if (ele.innerText !== "取消收藏") { ele.innerText = "取消收藏" ele.style.backgroundColor = "gold" ele.href = url.replace("fav", "unfav") } else { // todo 取消收藏,好像有页面重定向的问题 console("目前需要手动处理") // ele.innerText = "加入收藏" // ele.style.backgroundColor = "" // ele.href = url.replace("unfav", "fav") } } } xhr.send(); } function mouse_escape(element) { element.addEventListener('mouseover', function () { document.addEventListener('keydown', escKeyPressed); }); element.addEventListener('mouseout', function () { document.removeEventListener('keydown', escKeyPressed); }); function escKeyPressed(event) { if (event.key === 'Escape') { element.style.display = 'none'; // todo 这个位置应该需要结构 element.parentElement.querySelector(".content-loaded").innerText = "▼" } } } function set_content_default_height(element, defaultHeight) { // 如果没有设置,默认高度600px;如果输入0,完整显示 if (defaultHeight === 0) { defaultHeight = element.offsetHeight } else if (!defaultHeight) { defaultHeight = 600 } if (element.offsetHeight > defaultHeight) { element.style.height = defaultHeight + "px" } else { element.style.height = element.offsetHeight } } function set_btn_up(element) { element.innerText = "▲" element.className = "content-loaded" document.body.style.cursor = "auto"; } // 链接转图片 // 修改自 https://greasyfork.org/zh-CN/scripts/424246 // size调整为30%;考虑可以点击图片,窗口最大化 // todo 可以考虑把外面的括号进行替换 function linksToImgs() { let links = document.links; Array.from(links).forEach(function (_this) { if (/^https.*\.(?:jpg|jpeg|jpe|bmp|png|gif)/i.test(_this.href) && !(/<img\s/i.test(_this.innerHTML))) { _this.innerHTML = `<img src="${_this.href}" style="max-width: 30%!important;" />`; // alert("有图片被替换了") } else if (/^https:\/\/imgur\.com\/[a-z]+$/i.test(_this.href)) { // 针对没有文件后缀的 imgur 图床链接 _this.innerHTML = `<img src="${_this.href}.png" style="max-width: 30%!important;" />`; } }); } let css = ` .woDeStyle { /*height: 600px;*/ padding: 10px; margin: 10px auto; border: 1px solid gray; border-radius: 10px; overflow: scroll; } .topic-content-box { border-bottom: 2px dashed gray; padding-bottom: 10px; margin-bottom: 10px; } .triangle { color: gray; padding-left: 10px; } .content-loaded { color: greenyellow; padding-left: 10px; } #Wrapper { background-color: var(--box-background-color) !important; background-image: none !important; } .toggle-more-nodes { display: none; } #nodes-more-children, #nodes-more-related { display: block !important; } ` GM_addStyle(css) })();