您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
remove any dom you hate
// ==UserScript== // @name 删除节点 // @license MIT // @version 1.0.3 // @namespace http://tampermonkey.net/ // @description remove any dom you hate // @author IBAS // @match *://*/* // @icon https://i0.hdslb.com/bfs/face/e86287c6372e8c603724f65049cad9671fa1460c.jpg@240w_240h_1c_1s_!web-avatar-nav.avif // @grant none // ==/UserScript== (function() { 'use strict'; const domAction = { delete: "delete", hide: "hide", nothing: "nothing", }; const selectorType = { all: "all", single: "single", }; const formatSelector = function (selector, action, selectorType) { if (typeof selector === "string") { return { selector: selector, action: domAction.delete, selectorType: selectorType, msg: "", } } else { return selector; } }; let updateLocalStorage = (function () { const cache_name = "test_rm_cache_keep_090812"; let cache = []; let init = false; const getIndex = function (selector, append = false) { let i = 0; for (;i < cache.length; i++) { if (cache[i].selector === selector) { break; } } if (i === cache.length) { if (append) { cache.push(formatSelector(selector)); return i; } else { return -1; } } return i; } return { init() { if (init) { return cache; } else { const cacheContent = localStorage.getItem(cache_name); if (cacheContent) { try { cache = JSON.parse(cacheContent); } catch (e) { cache = []; } finally { } } else { cache = []; } init = true; return cache; } }, set(selector, action = domAction.delete, sType = selectorType.single, msg = "") { let i = getIndex(selector, true); if (action && action in domAction) { cache[i].action = action; } if (sType && sType in selectorType) { cache[i].selectorType = sType; } if (msg) { cache[i].msg = msg; } localStorage.setItem(cache_name, JSON.stringify(cache)); }, remove(selector) { let i = getIndex(selector, false); if (i !== -1) { cache.splice(i, 1); localStorage.setItem(cache_name, JSON.stringify(cache)); } } } })(); function getSelector(element) { if (!element) return ''; // 如果元素有 id,直接返回 id 选择器 if (element.id) { return `#${element.id}`; } // 获取标签名 let selector = element.tagName.toLowerCase(); if (selector === 'body') { return selector; } // 如果有类名,添加类选择器 if (element.className) { const classNames = element.className.trim().split(/\s+/); // if (classNames.includes(labelCssName)) { // classNames.splice(classNames.indexOf(labelCssName), 1); // } selector += '.' + classNames.join('.'); } // 如果是兄弟节点中的唯一一个同类节点,返回标签名和类名 let sibling = element; let siblingIndex = 0; while (sibling.previousElementSibling) { sibling = sibling.previousElementSibling; siblingIndex++; } if (siblingIndex > 0) { selector += `:nth-child(${siblingIndex + 1})`; } // 递归获取父元素的选择器,并加上当前选择器 const parent = element.parentElement; if (parent) { return `${getSelector(parent)} > ${selector}`; } else { return selector; } }; let setStyle = function (style) { const styleDom = document.createElement("style"); styleDom.innerText = style; document.head.append(styleDom); }; let labelCssName = ""; const deleteElement = function (target) { target.classList.remove(labelCssName); let selector = getSelector(target); const msg = prompt("标签", "x"); if (target.id) { updateLocalStorage.set(selector, "", "", msg); // 去除 id,有些网站的 id 是随机的,如果不删除,可能下次将失效 target.id = ""; selector = getSelector(target); } updateLocalStorage.set(selector, "", "", msg); target.remove(); } let createChildNode = (function () { let historyList = []; const info = { action: '', target: null, dom: null, }; const render = function () { historyList.forEach(h => { if (h.classList) { h.classList.remove(labelCssName) } }); historyList = []; if (info.target) { historyList.push(info.target); info.target.classList.add(labelCssName); } }; const doAction = function () { switch (info.action) { case "up": if (info.target === document.body) { alert("无法继续到上一级了"); } else { info.target = info.target.parentNode; } break; case "down": const child = info.target.children; if (child && child.length) { info.target = child[0]; } break; case "left": if (info.target.previousElementSibling) { info.target = info.target.previousElementSibling; } break; case "right": if (info.target.nextElementSibling) { info.target = info.target.nextElementSibling; } break; case "delete": info.dom.style.display = "none"; deleteElement(info.target); case "close": info.target = null; info.dom.style.display = "none"; break; } render(); }; function first(dom) { let id = dom.id; labelCssName = `${id}_box_line_item_label`; setStyle(` #${id}_box { display: flex; flex-direction: column; gap: 2px; } #${id}_box_line { display: flex; flex-direction: row; gap: 2px; } .${id}_box_line_item { flex: 1; background: #03A9F4; width: 30px; text-align: center; } `); setStyle(` .${labelCssName} { background: repeating-linear-gradient(45deg, #fff, #fff 10px, #66A1FF 10px, #66a1ff 20px); border: 8px solid red; } `); dom.innerHTML = `<div id="${id}_box"> <div id="${id}_box_line"> <div class="${id}_box_line_item"></div> <div class="${id}_box_line_item" action="up">上</div> <div class="${id}_box_line_item" action="close">关</div> </div> <div id="${id}_box_line"> <div class="${id}_box_line_item" action="left">左</div> <div class="${id}_box_line_item" action="delete">删</div> <div class="${id}_box_line_item" action="right">右</div> </div> <div id="${id}_box_line"> <div class="${id}_box_line_item"></div> <div class="${id}_box_line_item" action="down">下</div> <div class="${id}_box_line_item"></div> </div> </div>`; new Array(...dom.getElementsByClassName(`${id}_box_line_item`)).forEach(ele => { ele.onclick = function () { const action = this.getAttribute("action"); info.action = action; if (action) { doAction(); } }; }); first = () => {}; }; return function (dom, target) { dom.style.display = "block"; first(dom); info.dom = dom; info.target = target; render(); }; })(); let getDom = (function() { const id = "menu_id_ibas_test_rm"; let ele = null; setStyle(` #menu_id_ibas_test_rm { display: block; position: fixed; z-index: 10000000000000000; background: darkgray; padding: 5px; border-radius: 5px; width: 100px; text-align: center; cursor: pointer; border: 2px solid gray; border-radius: 4px; }`); function createDom() { ele = document.createElement("div"); ele.id = id; document.body.append(ele); return ele; }; return function() { return ele ? ele : createDom(); }; })(); const table = (function () { const tbodyId = `menu_id_ibas_test_rm_panel_table_tbody`; let div = null; setStyle(` #menu_id_ibas_test_rm_panel { z-index: 1000000000000000000; position: fixed; top: 0px; left: 0px; width: 100vw; height: 100vh; background: #2196f340; cursor: pointer; } #menu_id_ibas_test_rm_panel_content { width: calc(100% - 60px); height: calc(100% - 60px); border-radius: 30px; margin: 30px; background: bisque; padding: 20px; box-sizing: border-box; display: flex; flex-direction: column; height: calc(100vh - 60px); } .menu_id_ibas_test_rm_panel_content_table_dom { flex: 1; overflow-y: scroll; } .menu_id_ibas_test_rm_panel_title { height: 30px; line-height: 30px; } .menu_id_ibas_test_rm_panel_title_btn { line-height: 30px; text-decoration: underline; cursor: pointer; margin: 0 10px 0 0; } .menu_id_ibas_test_rm_panel_content_table { width: 100%; border-collapse: collapse; font-family: Arial, sans-serif; table-layout: fixed; /* 让表格列可以自适应 */ } .menu_id_ibas_test_rm_panel_content_table th, .menu_id_ibas_test_rm_panel_content_table td { padding: 12px; border: 1px solid #ddd; text-align: left; } .menu_id_ibas_test_rm_panel_content_table th { background-color: #f2f2f2; font-weight: bold; } .menu_id_ibas_test_rm_panel_content_table tr:nth-child(even) { background-color: #f9f9f9; } .menu_id_ibas_test_rm_panel_content_table tr:hover { background-color: #f1f1f1; } .menu_id_ibas_test_rm_panel_content_table th:nth-child(-n+5), .menu_id_ibas_test_rm_panel_content_table td:nth-child(-n+5) { width: 60px; /* 第一列宽度固定为150px */ }`); function init() { div = document.createElement('div'); div.style.display = 'none'; div.id = `menu_id_ibas_test_rm_panel`; div.innerHTML = `<div id="menu_id_ibas_test_rm_panel_content"> <div class="menu_id_ibas_test_rm_panel_title"> <span class="menu_id_ibas_test_rm_panel_title_close menu_id_ibas_test_rm_panel_title_btn">关闭</span> <span class="menu_id_ibas_test_rm_panel_title_add menu_id_ibas_test_rm_panel_title_btn">添加</span> </div> <div class="menu_id_ibas_test_rm_panel_content_table_dom"> <table class="menu_id_ibas_test_rm_panel_content_table"> <thead> <tr> <th>删除</th> <th>隐藏</th> <th>跳过</th> <th>qAll</th> <th>删除</th> <th>标签</th> <th>选择器</th> </tr> </thead> <tbody id="${tbodyId}"> </tbody> </table> </div> </div>`; document.body.append(div); document.getElementsByClassName('menu_id_ibas_test_rm_panel_title_close')[0].onclick = function () { div.style.display = 'none'; }; document.getElementsByClassName('menu_id_ibas_test_rm_panel_title_add')[0].onclick = function () { alert("开发中... ...") }; init = () => {}; } return { showTable() { init(); let tbody = document.getElementById(tbodyId); tbody.innerHTML = ''; let newDom = ``; updateLocalStorage.init().forEach((cache, ind) => { const id = `table_label_${(Math.random() * 1000).toFixed()}_${ind}` cache = formatSelector(cache); newDom += `<tr class="${id}"> <td><input type="radio" action="${domAction.delete}" name="${cache.selector}" ${cache.action === domAction.delete ? 'checked' : ''}/></td> <td><input type="radio" action="${domAction.hide}" name="${cache.selector}" ${cache.action === domAction.hide ? 'checked' : ''}/></td> <td><input type="radio" action="${domAction.nothing}" name="${cache.selector}" ${cache.action === domAction.nothing ? 'checked' : ''}/></td> <td><input type="checkbox" ${cache.selectorType === selectorType.all ? 'checked' : ''} name="${cache.selector}" label="${id}"/><span id="${id}">${cache.selectorType === selectorType.all ? "多" : "单"}</span></td> <td><button name="${cache.selector}" label="${id}">删</button></td> <td>${cache.msg}</td> <td>${cache.selector}</td> </tr>`; }); tbody.innerHTML = newDom; new Array(...tbody.getElementsByTagName('input')).forEach(inp => { inp.onchange = function () { if (inp.type === 'radio') { const selector = this.getAttribute('name'); const action = this.getAttribute('action'); updateLocalStorage.set(selector, action); } else if (inp.type === 'checkbox') { const selector = this.getAttribute('name'); const label = this.getAttribute('label'); const checked = this.checked; updateLocalStorage.set(selector, "", checked ? selectorType.all : selectorType.single); document.getElementById(label).innerText = checked ? "多" : "单"; } }; }); new Array(...tbody.getElementsByTagName('button')).forEach(btn => { btn.onclick = function () { const selector = this.getAttribute('name'); while (true) { const ret = prompt("确定删除?(yes/y 或 no/n)", "yes"); if (ret.startsWith('y') || ret.startsWith('Y')) { updateLocalStorage.remove(selector); const label = this.getAttribute('label'); const tr = document.getElementsByClassName(label); if (tr && tr.length) { tr[0].remove(); } break; } else if (ret.startsWith('n') || ret.startsWith('N')) { break; } } }; }); div.style.display = 'block'; }, }; })(); let windowOnLoad = function () { const cache = new Array(...updateLocalStorage.init()); const removeDom = function () { const undo = []; while (cache.length) { const c = formatSelector(cache.shift()); let dom = []; if (c.selectorType === selectorType.all) { dom = document.querySelectorAll(c.selector); } else { dom = [document.querySelector(c.selector)]; } if (dom.length) { if (c.action === domAction.delete) { dom.forEach(d => d ? d.remove() : null); // dom.remove(); } else if (c.action === domAction.hide) { dom.forEach(d => d ? (d.style.display = 'none') : null); // dom.style.display = 'none'; } else { // nothing } } else { undo.push(c); return; } } cache.splice(0,0, ...undo); }; let run = false; let time = 10; let id = setInterval(() => { if (run) {} else { if (!time) { clearInterval(id); console.log("delete over"); return; } time--; run = true; removeDom(); run = false; if (!cache.length) { clearInterval(id); console.log("delete over"); } } }, 500); document.addEventListener('keydown', function(event) { // 检查是否按下 Ctrl + S if (event.ctrlKey && event.key === 'q') { // 在这里编写保存逻辑 table.showTable(); } }); }; document.addEventListener('contextmenu', function(event) { console.log(event); event.preventDefault(); // 阻止默认右键菜单 const menu = getDom(); createChildNode(menu, event.target); menu.style.top = event.clientY + 'px'; menu.style.left = event.clientX + 'px'; menu.style.display = 'block'; }); windowOnLoad(); })();