您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Remove cruft from ride reports on ADVRider, i.e. only show posts from the member who started the thread.
// ADV Ride Report De-crufter // version 4.2 // Release Date: 2018.09.11 // http://devourmiles.com // Copyright (c) 2009-2018, All Rights Reserved (except where // otherwise noted) // // You may modify this script for your own personal use, // but please contact me first before releasing any changes. // // ***** INSTRUCTIONS ***** // // This is a Greasemonkey user script. // // To use this script, get Greasemonkey: http://greasemonkey.mozdev.org/ // After you've installed it, come back to this page. A dialog box will // appear asking you if you want to install this script. Believe me, you do. // // To uninstall, go to Tools->Greasemonkey->Manage User Scripts, select // "ADV Ride Report De-crufter" from the list on the left, and click // Uninstall. // // // ==UserScript== // @name ADV Ride Report De-crufter // @namespace http://devourmiles.com // @version 4.2 // @description Remove cruft from ride reports on ADVRider, i.e. only show posts from the member who started the thread. // // @include https://www.advrider.com/* // @include https://advrider.com/* // ==/UserScript== function Querystring(qs) { this.qstr = ''; this.params = []; if (qs == null) qs = location.search.substring(1, location.search.length); if (qs.length == 0) return; qs = qs.replace(/\+/g, ' '); this.qstr = qs; this.params = qs.split('/'); } Querystring.prototype.contains = function(key) { for (var i=0; i<this.params.length; i++) { if (this.params[i] == key) { return true; } return false; } } /* xpath helper * http://wiki.greasespot.net/Code_snippets#XPath_helper */ function $x() { var x='', // default values node=document, type=0, fix=true, i=0, toAr=function(xp){ // XPathResult to array var final=[], next; while(next=xp.iterateNext()) final.push(next); return final }, cur; while (cur=arguments[i++]) // argument handler switch(typeof cur) { case "string":x+=(x=='') ? cur : " | " + cur;continue; case "number":type=cur;continue; case "object":node=cur;continue; case "boolean":fix=cur;continue; } if (fix) { // array conversion logic if (type==6) type=4; if (type==7) type=5; } if (!/^\//.test(x)) x="//"+x; // selection mistake helper if (node!=document && !/^\./.test(x)) x="."+x; // context mistake helper var temp=document.evaluate(x,node,null,type,null); //evaluate! if (fix) switch(type) { // automatically return special type case 1:return temp.numberValue; case 2:return temp.stringValue; case 3:return temp.booleanValue; case 8:return temp.singleNodeValue; case 9:return temp.singleNodeValue; } return fix ? toAr(temp) : temp; } /*! * JavaScript Cookie v2.2.0 * https://github.com/js-cookie/js-cookie * * Copyright 2006, 2015 Klaus Hartl & Fagner Brack * Released under the MIT license */ ;(function (factory) { var registeredInModuleLoader; if (typeof define === 'function' && define.amd) { define(factory); registeredInModuleLoader = true; } if (typeof exports === 'object') { module.exports = factory(); registeredInModuleLoader = true; } if (!registeredInModuleLoader) { var OldCookies = window.Cookies; var api = window.Cookies = factory(); api.noConflict = function () { window.Cookies = OldCookies; return api; }; } }(function () { function extend () { var i = 0; var result = {}; for (; i < arguments.length; i++) { var attributes = arguments[ i ]; for (var key in attributes) { result[key] = attributes[key]; } } return result; } function decode (s) { return s.replace(/(%[0-9A-Z]{2})+/g, decodeURIComponent); } function init (converter) { function api() {} function set (key, value, attributes) { if (typeof document === 'undefined') { return; } attributes = extend({ path: '/' }, api.defaults, attributes); if (typeof attributes.expires === 'number') { attributes.expires = new Date(new Date() * 1 + attributes.expires * 864e+5); } // We're using "expires" because "max-age" is not supported by IE attributes.expires = attributes.expires ? attributes.expires.toUTCString() : ''; try { var result = JSON.stringify(value); if (/^[\{\[]/.test(result)) { value = result; } } catch (e) {} value = converter.write ? converter.write(value, key) : encodeURIComponent(String(value)) .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent); key = encodeURIComponent(String(key)) .replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent) .replace(/[\(\)]/g, escape); var stringifiedAttributes = ''; for (var attributeName in attributes) { if (!attributes[attributeName]) { continue; } stringifiedAttributes += '; ' + attributeName; if (attributes[attributeName] === true) { continue; } // Considers RFC 6265 section 5.2: // ... // 3. If the remaining unparsed-attributes contains a %x3B (";") // character: // Consume the characters of the unparsed-attributes up to, // not including, the first %x3B (";") character. // ... stringifiedAttributes += '=' + attributes[attributeName].split(';')[0]; } return (document.cookie = key + '=' + value + stringifiedAttributes); } function get (key, json) { if (typeof document === 'undefined') { return; } var jar = {}; // To prevent the for loop in the first place assign an empty array // in case there are no cookies at all. var cookies = document.cookie ? document.cookie.split('; ') : []; var i = 0; for (; i < cookies.length; i++) { var parts = cookies[i].split('='); var cookie = parts.slice(1).join('='); if (!json && cookie.charAt(0) === '"') { cookie = cookie.slice(1, -1); } try { var name = decode(parts[0]); cookie = (converter.read || converter)(cookie, name) || decode(cookie); if (json) { try { cookie = JSON.parse(cookie); } catch (e) {} } jar[name] = cookie; if (key === name) { break; } } catch (e) {} } return key ? jar[key] : jar; } api.set = set; api.get = function (key) { return get(key, false /* read as raw */); }; api.getJSON = function (key) { return get(key, true /* read as json */); }; api.remove = function (key, attributes) { set(key, '', extend(attributes, { expires: -1 })); }; api.defaults = {}; api.withConverter = init; return api; } return init(function () {}); })); function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } /* begin de-crufter code... */ var advRR = { showOptionsDiv: function() { // get current settings, if any var settings = Cookies.get(advRR.getThreadId()); if (settings) { settings = settings.split(/:/); advRR.author = settings[0]; advRR.filter = (settings[1] == "1" ? true : false); if (typeof(settings[2]) != "undefined" || settings[2] != "") { if (settings[2] == "") { var exception_list = ""; } else { advRR.exceptions = settings[2].split(/,/); var exception_list = advRR.exceptions.join(","); } } var op_username = settings[0]; var advRR_chk = (settings[1] == "1" ? "checked " : ""); } else { var op = $x("//p[@id='pageDescription']/a[@class='username']", XPathResult.FIRST_ORDERED_NODE_TYPE); var op_username = op.textContent; var advRR_chk = ""; var exception_list = ""; } if (typeof(op_username) != "undefined") { var newNode = document.createElement("div"); var innerHTML = "Only show <b>" + op_username + "</b>'s posts? <input type='checkbox' id='advRR_chk_show' " + advRR_chk + "> <span style='padding-left:20px'>Exceptions: [<span id='exception_span'>" + exception_list + "</span>] <a href='#' id='exception_edit' style='margin-left:10px'>edit</a> | <a href='#' id='exception_clear'>clear</a></span>"; newNode.innerHTML = innerHTML; newNode.addEventListener ('click', function () { advRRToggle(op_username); }); var target = $x("//p[@id='pageDescription']", XPathResult.ANY_UNORDERED_NODE_TYPE); target.appendChild(newNode); var exceptionEdit = $x("//a[@id='exception_edit']", XPathResult.ANY_UNORDERED_NODE_TYPE); exceptionEdit.addEventListener ('click', function (e) { e.preventDefault(); editExceptions(); }); var exceptionClear = $x("//a[@id='exception_clear']", XPathResult.ANY_UNORDERED_NODE_TYPE); exceptionClear.addEventListener ('click', function (e) { e.preventDefault(); clearExceptions(); }); } }, getPosts: function () { advRR.posts = $x("//li[contains(@id, 'post')]", XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); }, getThreadId: function () { return advRR.urlParts[5]; }, isFirstPage: function () { var pageNavHeader = $x("//span[@class='pageNavHeader']", XPathResult.FIRST_ORDERED_NODE_TYPE); if (/Page 1/.test(pageNavHeader.innerHTML)) { return true; } else { return false; } }, showError: function (message) { var newNode = document.createElement("div"); newNode.innerHTML = message; var target = $x("//p[@id='pageDescription']", XPathResult.ANY_UNORDERED_NODE_TYPE); target.appendChild(newNode); }, setGMOption: function (key, value) { Cookies.set(key, value, { expires: 3650 }); }, author: "", filter: false, queryStr: {}, urlParts: [], exceptions: [], posts: [] } // end advRR deCruftify = function() { for (var i=0; i < advRR.posts.length; i++) { var post = advRR.posts[i]; if (advRR.filter && post.dataset.author != advRR.author && !advRR.exceptions.includes(post.dataset.author)) { post.style.display = "none"; } else { post.style.display = ""; } } } advRRToggle = function(username) { var advRR_chk_show = $x("//input[@id='advRR_chk_show']", XPathResult.FIRST_ORDERED_NODE_TYPE); if (advRR_chk_show.checked) { advRR.setGMOption(advRR.getThreadId(), username + ":1:" + advRR.exceptions.join(',')); advRR.author = username; advRR.filter = true; } else { advRR.setGMOption(advRR.getThreadId(), username + ":0:" + advRR.exceptions.join(',')); advRR.author = username; advRR.filter = false; } // refresh display of posts deCruftify(); } editExceptions = function() { var exception_span = $x("//span[@id='exception_span']", XPathResult.FIRST_ORDERED_NODE_TYPE); var input = prompt("Make exceptions for? (separate multiple usernames with commas)", advRR.exceptions.join(",")); if (input == null || input == "") { return false; } else { var newSettings = advRR.author + ":" + (advRR.filter ? "1" : "0") + ":" + input; advRR.setGMOption(advRR.getThreadId(), newSettings); advRR.exceptions = input.split(","); exception_span.innerHTML = input; deCruftify(); } } clearExceptions = function() { var exception_span = $x("//span[@id='exception_span']", XPathResult.FIRST_ORDERED_NODE_TYPE); var c = confirm("Clear exceptions for " + advRR.exceptions.join(",") + "?"); if (!c) { return false; } else { var newSettings = advRR.author + ":" + (advRR.filter ? "1" : "0") + ":"; advRR.setGMOption(advRR.getThreadId(), newSettings); advRR.exceptions = []; exception_span.innerHTML = ""; deCruftify(); } } async function doIt() { console.log("Firing up the ADV RR De-crufter..."); await sleep(1200); // wait for XenForo to do its thing console.log("ADV RR De-crufter ready to go."); // get URL and split into an array of parts advRR.urlParts = document.URL.split("/"); // are we even viewing a thread? if (!advRR.urlParts[4] == "threads") { // nope, so GTFO return; } console.log("De-crufting..."); advRR.getPosts(); advRR.showOptionsDiv(); deCruftify(); } doIt();