您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Hides threads in SDMB vBulletin board (or other compatible boards).
// ==UserScript== // @name Hide SDMB Forum Threads // @namespace SDMB_HideThreads // @version 0.6.2 // @description Hides threads in SDMB vBulletin board (or other compatible boards). // @author TroutMan // @include http://boards.straightdope.com/sdmb/forumdisplay.php* // @include http://boards.straightdope.com/sdmb/search.php* // @include https://boards.straightdope.com/sdmb/forumdisplay.php* // @include https://boards.straightdope.com/sdmb/search.php* // @require http://code.jquery.com/jquery-2.1.1.min.js // @grant GM_addStyle // @grant GM_getValue // @grant GM_setValue // @grant unsafeWindow // ==/UserScript== var divider = "|||"; var threadIdListKey = "threadIds_" + location.hostname; // migrate old storage key to domain-specific key if (GM_getValue("HideThreadFile", "").length > 0) { GM_setValue("threadIds_boards.straightdope.com", GM_getValue("HideThreadFile", "")); GM_setValue("HideThreadFile", ""); } unsafeWindow._hideThread = exportFunction(function(threadId, threadTitle) { window.setTimeout(SetThreadToHide, 0, threadId, threadTitle); // alert('Thread added to hidden list: ' + threadId); }, unsafeWindow); unsafeWindow._hideThread(); AddConfigLink(); FilterThreads(); function UpdateHideList(list) { window.setTimeout(GM_setValue, 0, threadIdListKey, titleEncode(list)); GM_setValue(threadIdListKey, titleEncode(list)); } // add threadId to storage function SetThreadToHide(threadId, threadTitle) { var currentFile = ""; if (threadTitle.length > 40) { threadTitle = threadTitle.substr(0, 37) + '...'; } currentFile = titleDecode(GM_getValue(threadIdListKey, "-----" + String.fromCharCode(10))); // append to list and save currentFile += divider + threadId + divider + threadTitle + String.fromCharCode(10); UpdateHideList(currentFile); // hide the thread var divElement = document.getElementById("td_threadtitle_" + threadId); HideThread(divElement.parentNode); } function HideThread(node) { if (node.parentNode !== null) { node.parentNode.removeChild(node); } } function AddHideThreadLink (thisElement, threadId, threadTitle) { var link = document.createElement('a'); link.setAttribute('href', 'javascript:_hideThread("' + threadId + '","' + titleEncode(threadTitle) + '")'); link.setAttribute('style', 'float:right;font-size:x-small;'); link.innerHTML = "Hide"; thisElement.childNodes[1].appendChild(link); } function FilterThreads() { var hideFile = titleDecode(GM_getValue(threadIdListKey, "")); var hideGames = GM_getValue("HideThreadGameSetting", false); // get all <td> elements matching the thread pattern allElements = document.evaluate( './/td[contains(@id, "td_threadtitle_")]', document.body, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); for (var i = 0; i < allElements.snapshotLength; i++) { var thisElement = allElements.snapshotItem(i); var threadId = thisElement.getAttribute('id'); if (threadId !== null) { threadId = threadId.substring(15); // get thread title to check for [GAME] threads and for a user-friendly display of hidden threads var titleNode = document.getElementById('thread_title_' + threadId); var threadTitle = titleNode.innerHTML; // hide game threads if [GAME] setting is checked if (hideGames && threadTitle.substr(0, 6).toUpperCase() == '[GAME]') { HideThread(thisElement.parentNode); } // hide threads matching IDs in the master hide file else if (hideFile.indexOf(divider + threadId + divider) >= 0) { HideThread(thisElement.parentNode); } else { AddHideThreadLink(thisElement, threadId, threadTitle); } } } } // functions to encode and decode titles - handles quotes and & function titleEncode(str) { if (typeof str == "string") { return encodeURI(str.replace(/&/g, '&').replace(/"/g, '"')); } else { return ""; } } function titleDecode(str) { return decodeURI(str).replace(/"/g, '"'); } function AddConfigLink() { element = document.evaluate( ".//td[@class='vbmenu_control']", document.body, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null); var topToolBar = element.singleNodeValue.parentNode; if (topToolBar !== null) { var tableCell = document.createElement('td'); tableCell.setAttribute('class', 'vbmenu_control'); var link = document.createElement('a'); link.setAttribute('href', 'javascript:_OpenConfigWindow();'); link.innerHTML = "Hidden Threads"; tableCell.appendChild(link); topToolBar.appendChild(tableCell); } } unsafeWindow._OpenConfigWindow = exportFunction(function() { // load current settings var hideGames = GM_getValue("HideThreadGameSetting", false); $("#hideAllGame").prop("checked", hideGames); var list = titleDecode(GM_getValue(threadIdListKey, "-----")); $("#hiddenThreadList").val(list); $("#hideThreadConfigPopup").show(); }, unsafeWindow); unsafeWindow._OpenConfigWindow(); // Configuration popup $("body").append ( ' \ <div id="hideThreadConfigPopup" style="display: none;"> \ <p style="font-size:20px;font-weight:bold">SDMB Hidden Thread Configuration</p> \ <form> \ <input type="checkbox" id="hideAllGame">Hide all [GAME] threads \ <p style="font-weight:bold">Hidden threads - edit at your own risk<br> \ <textarea id="hiddenThreadList" rows=15 cols=55></textarea></p> \ <p> </p> \ <button id="hideThreadSave" type="button">Save Changes</button> \ <button id="hideThreadCancel" type="button">Cancel</button> \ </form> \ </div> \ ' ); // save configuration edits $("#hideThreadSave").click ( function () { var str = $("#hiddenThreadList").val(); // save [GAME] setting var hideGames = $("#hideAllGame").prop("checked"); window.setTimeout(GM_setValue, 0, "HideThreadGameSetting", hideGames); // save thread list var list = $("#hiddenThreadList").val(); window.setTimeout(GM_setValue, 0, threadIdListKey, titleEncode(list)); $("#hideThreadConfigPopup").hide(); } ); // close config popup without saving $("#hideThreadCancel").click ( function () { $("#hideThreadConfigPopup").hide(); } ); // CSS styles for the config window GM_addStyle ( " \ #hideThreadConfigPopup { \ position: fixed; \ top: 10%; \ left: 50%; \ padding: 2em; \ background: Gainsboro; \ border: 1px double black; \ border-radius: 1ex; \ z-index: 777; \ } \ #hideThreadConfigPopup button{ \ cursor: pointer; \ -webkit-border-radius: 6; \ -moz-border-radius: 6; \ border-radius: 6px; \ font-family: Arial; \ color: White; \ font-size: 14px; \ background: DarkBlue; \ padding: 6px 12px 6px 12px; \ } \ " );