太...最近,我读了一篇有关声誉固有问题的元文章。它列出了一些东西,例如:


确认偏见。
低收入用户的动机不足。
能力代表不正确。
...我抓住检查员,检查了问题,我的个人资料页面和活动页面以及信誉如何显示。

然后,我迅速为Greasemonkey编写了以下小型用户脚本(ECMA6),该脚本会隐藏所有声誉:
对我来说已经运行了一段时间,我想说这是一个令人耳目一新的变化。除此之外:

它隐藏了页面上的所有信誉编号。如果您很好奇,您当然仍然可以找到它们。当活动计时器的伸出方式不同时,它在/questions上看起来也很有趣,但这只是我的OCD生气了。在该用户脚本中做得更好?

评论

欢迎使用Stack Exchange,它是组成一切和要点的网络。

您为什么为此使用JS?自定义CSS是否可以更好(更容易)解决这个问题?

您实际上可以从用户脚本执行相同操作。只是document.head.appendChild(document.createElement(“ style”))。textContent =“ .rep,.reputation,.reputation-scope {可见性:隐藏;}”;

您可以在StackApps上发布吗?

@ A.L。我原本不打算,但现在我正在考虑。我会在此之前添加更多功能。随意发布自己,即使这是3行CSS

#1 楼

最好使用用户样式(例如使用手写笔扩展名,如下所示:

 .rep, .reputation, .reputation-score {
    visibility: hidden;
}
 


用户样式优于脚本的一个优势是在页面开始加载后立即应用它们,因此在页面加载时您不会看到重复计数短暂闪烁。同样,用户样式也将自动应用于已加载的新动态内容,例如通过Ajax(例如,您在浏览页面时发布的新答案)。

如果您坚持使用用户脚本,则可能使用@run-at document-start并向其中注入自定义style元素来模拟用户样式像这样的页面:

 // ==UserScript==
// @name        Hide Stack Exchange reputation (demo)
// @namespace   http://vyznev.net/
// @description A demonstration of using style injection to emulate user styles
// @author      Ilmari Karonen
// @version     1.0
// @license     Public domain
// @match       *://*.stackexchange.com/*
// @match       *://*.stackoverflow.com/*
// @match       *://*.superuser.com/*
// @match       *://*.serverfault.com/*
// @match       *://*.stackapps.com/*
// @match       *://*.mathoverflow.net/*
// @match       *://*.askubuntu.com/*
// @homepageURL http://codereview.stackexchange.com/a/120100
// @grant       none
// @run-at      document-start
// ==/UserScript==

var css =
    ".rep, .reputation, .reputation-score {\n" +
    "    visibility: hidden;\n" +
    "}\n";

var style = document.createElement('style');
style.textContent = css;
(document.head || document.documentElement).appendChild(style);
 


我在我的非官方堆栈溢出中使用了此方法修补程序(SOUP)用户脚本(将许多或多或少的次要接口错误修正和改进结合在一起)使我可以从单个用户脚本中有效地应用纯CSS和基于JS的调整。值得注意的一个细节是,以这种方式注入的样式通常最终会包含在页面上任何实际的站点样式表之前,这意味着它们将被具有相同特异性的站点CSS选择器覆盖。在某些情况下,您可能需要使用!important和/或各种特殊性技巧,以确保自定义样式具有优先权。

评论


\ $ \ begingroup \ $
如果ES6可用,则最好使用模板字符串而不是串联。
\ $ \ endgroup \ $
–约瑟夫
16年2月16日在14:59

#2 楼

您可以使用querySelectorAll而不是getElementsByClassName。这样,您可以在定位元素方面更加灵活。它还允许多个选择器。这样,您不必循环两次。

代替[].slice使用不必要的数组作为主机,而尝试使用Array.prototype.slice.call。更长,但是没有多余的数组。这样,声誉就不会出现笨拙的空白,从而使布局变得自然。 >
'use strict';

const REPUTATION_ELEMENTS = '.rep, .reputation, .reputation-score';

function getElementArray(selector){
  return Array.prototype.slice.call(document.querySelectorAll(selector));
}

document.addEventListener("DOMNodeInserted", event => {
  getElementArray(REPUTATION_ELEMENTS).forEach( element => {
    element.style.display = 'none';
  });
});


评论


\ $ \ begingroup \ $
显示器:没有建议值得金。一件事:默认情况下,在加载页面时该命令不会运行。那只是一件很小的事情。我还记得听到过有关querySelectorAll慢于更专门的调用的信息,但我可能是错的。感谢您的评论:)
\ $ \ endgroup \ $
–Vogel612♦
16年2月15日在15:28

\ $ \ begingroup \ $
如果您使用的是ES6,则应该使用for for循环而不是forEach。
\ $ \ endgroup \ $
–贝尔吉
16年2月15日在16:17

\ $ \ begingroup \ $
另一种隐藏事物的方法:element.hidden = true。秋,wwwg
\ $ \ endgroup \ $
– deltab
16-2-15在17:54



\ $ \ begingroup \ $
@ Vogel612是的,它比旧的元素选择API相对要慢,但是由于jQuery,对于某些元素它可以忽略不计且更加熟悉。说到jQuery,不确定是否可能,但是如果用户脚本可以利用页面上已经存在的脚本,则可以像$(selector).hide()一样简单。
\ $ \ endgroup \ $
–约瑟夫
16-2-16在1:24



\ $ \ begingroup \ $
@Bergi forEach只是出于本能,特别是对于数组。 :D
\ $ \ endgroup \ $
–约瑟夫
16年2月16日在1:29

#3 楼

更新URL

如果您提供脚本原始版本的链接作为UserScript标头,则UserScript具有自我更新的神奇能力:

注意:实际上,您必须增加版本,否则将不会更新。我不是特别喜欢您的方法。

在重新扫描所有内容之前检查DOM更新。

简单地插入样式表以覆盖SE会更有意义。样式表。

更多的劳动力表现。尚未充分利用它:


// ==UserScript==
// @name         Reputation Hider
// @namespace    http://gihub.com/Vogel612/ReputationHider
// @version      0.1
// @downloadURL
// @updateURL



而不是使用旧的function(collection){}方法,可以使用(collection) => ()

let slice = function(collection) {
  return [].slice.call(collection);   
}


主循环中的函数也是如此。


切片和切块

,您只能将slice与您的ele一起使用选择。
您应该将两者结合起来!让我们更进一步,做一些连接魔术:

let slice = (collection) => [].slice.call(collection)


或者,您可以使用字符串连接来制作一个巨大的选择器字符串,并使用Joseph所描述的querySelectorAll。 br />
我发现querySelector*的性能可能较差,但始终都是边缘情况触发了我的事情。通常,这不是我添加的检查点,但是,我认为您可以添加对其他字段的支持,并创建一个方便的花哨对话框以选择要隐藏的对话框。在我眼中,这将是值得创造的StackApps。

#4 楼

您可以使用document.getElementsByClassName代替document.querySelectorAll(CSS selector)

编辑(回复@ 200_success):
您可以使用任何一个。我更喜欢document.querySelectorAll,因为我认为它会好一点。



document.getElementsByClassName有31个字母,document.querySelectorAll有25个字母。 CSS获取DOM元素,但document.querySelectorAll不支持。
IE 8+支持document.getElementsByClassName(IE 8仅支持CSS2选择器),但是document.querySelectorAll用于IE 9+。

但是必须使用document.getElementsByClassNameArray生成DOMNodeList,因为slice对象类似于DOMNodeList。即您可以使用Array将其用作Array

window.addEventListener("load", _ => {
    Array.prototype.forEach.call(document.querySelectorAll(".rep, .reputation, .reputation-score, .-flair"), element => {
            element.style.display = "none";
        });
});


#5 楼

由于您使用的是ES6,因此可以将slice函数替换为Array.from(也可以实现Josephs的更改);

let hideRepz = function() {
  repClasses.forEach(clazz => 
    Array.from(document.querySelectorAll(`.${clazz}`))
      .forEach(el => { 
        el.style.display = 'none';
      })
    );
}


评论


\ $ \ begingroup \ $
如果您使用的是ES6,则应该使用for for循环而不是forEach。
\ $ \ endgroup \ $
–贝尔吉
16年2月15日在16:17

\ $ \ begingroup \ $
@Bergi除了“它在那里,所以让我们使用它”自变量之外,是否存在for(.. of ..)更可取的具体原因?
\ $ \ endgroup \ $
–spender
16年2月16日在2:17

\ $ \ begingroup \ $
它介于“更简洁,更优雅,更高效,更少键入,更易于理解”之间-如果JS有一个像“ pythonic”这样的形容词,那就是那样。技术上的争论是它不需要中间数组,您可以从中突破。基本上forEach不推荐使用ES6。
\ $ \ endgroup \ $
–贝尔吉
16-2-16在13:44



#6 楼

避免使用不推荐使用的事件

不推荐使用可变事件(DOMNodeInserted),而应该使用Mutation Observers。

示例用法:

function processNewNodes(topNode) {
    var nodes = topNode.querySelectorAll(selector);
    // ...
}

var observer = new MutationObserver(function(mutations, observer) {
    mutations.forEach(function(mutation) {
        Array.prototype.forEach.call(mutation.addedNodes, processNewNodes);
    });
});

observer.observe(document, {
    subtree: true,
    childList: true
});