Вы ненавидите репутацию? Нажмите здесь, чтобы избавиться от него
Су ... Недавно я прочитал мета-сообщение о неотъемлемых проблемах репутации. В нем перечислены такие вещи, как:
- Подтверждение смещения.
- Demotivating для пользователей с низким уровнем репутаций.
- Hubris и элитарность высокопоставленных пользователей по сравнению с пользователями с низким уровнем репутаций.
- Неправильное представление компетенции.
- ...
Поэтому я подумал про себя: «Как могла бы быть сеть, без репутации?»
Я схватил инспектора, проверил вопросы, мою страницу профиля и активную страницу, и как отображается репутация.
Затем я быстро взломал следующий небольшой пользовательский скрипт (ECMA6) для Greasemonkey, который скрывал бы всю репутацию от вида:
// ==UserScript==
// @name Reputation Hider
// @namespace http://gihub.com/Vogel612/ReputationHider
// @version 0.1
// @description Hides all reputation displays from StackExchange sites
// @author Vogel612
// @grant none
// @include /https?:\/\/(meta\.)?.*\.stackexchange\.com\/.*/
// @include /https?:\/\/(stackoverflow|serverfault|superuser|askubuntu)\.com\/.*/
// ==/UserScript==
/* jshint -W097 */
'use strict';
let slice = function(collection) {
return [].slice.call(collection);
}
let repClasses = [ "rep", "reputation", "reputation-score" ];
let hideRepz = function() {
repClasses.forEach(clazz =>
slice(document.getElementsByClassName(clazz))
.forEach(el => {
// this results in minor inconsistencies in CSS, but alas
el.style.visibility = 'hidden';
})
);
}
hideRepz();
// add event listener for live-updates
document.addEventListener("DOMNodeInserted", hideRepz);
Это уже давно работает для меня, и мне нравится говорить, что это освежающее изменение. Это в стороне:
Он скрывает все номера репутации на странице. Если вам интересно, вы все равно можете их найти. Также он выглядит забавным в /questions
, когда активные таймеры outdented по-разному, но это только мой OCD сходит с ума.
Он также проверяет новые вопросы, которые вы загружаете по уведомлению.
Что я могу сделать лучше в этом usercript?
6 ответов
Было бы лучше сделать это с помощью стиля пользователя , например используя расширение Стильное , например:
.rep, .reputation, .reputation-score {
visibility: hidden;
}
Одно из преимуществ пользовательских стилей над сценариями заключается в том, что они применяются, как только страница начинает загружаться, поэтому вы не увидите кратковременное замедление количества повторений во время загрузки страницы. Кроме того, стили пользователей будут автоматически применяться также к новому динамическому содержимому, загруженному, например. через Ajax (например, новые ответы, отправленные во время просмотра страницы).
Если вы настаиваете на использовании пользовательского сценария , возможно, он будет эмулировать стили пользователей, используя @run-at document-start
и вводить элемент
style
Я использую этот метод в своем Неофициальном патче стека (SOUP) пользовательский скрипт (который сочетает в себе кучу более или менее небольших исправлений и улучшений интерфейса), чтобы я мог эффективно применять CSS-only и JS-tweaks из одного пользовательского скрипта.
Следует отметить одну деталь: стили, введенные таким образом, обычно включаются до в любые фактические таблицы стилей сайта на странице, что означает, что они будут переопределены селекторами CSS сайта с одинаковой специфичностью , В некоторых случаях вам может понадобиться использовать // ==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);
и /или различные специфические хаки , чтобы убедиться, что ваши пользовательские стили будут иметь приоритет.
Вы можете использовать querySelectorAll
вместо getElementsByClassName
. Таким образом, вы обладаете большей гибкостью в элементах таргетинга. Он также позволяет несколько селекторов. Таким образом, вам не нужно дважды зацикливаться.
Вместо [].slice
, который использует ненужный массив как хост, попробуйте вместо этого использовать Array.prototype.slice.call
. Дольше, но без этого дополнительного массива.
Кроме того, попробуйте использовать display:none
, поскольку видимость просто скрывает элемент, но поддерживает макет. Таким образом, нет неловкого пробела, где была репутация, делая макет естественным.
Увидев, что вы положили ES6, мы также можем использовать удобные функции стрелок dandy.
'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';
});
});
Обновить URL
UserScripts обладают магической способностью обновлять себя, если вы предоставляете ссылку на исходную версию своего скрипта в качестве заголовка UserScript:
Примечание. Фактически вам нужно увеличить версию, или она не будет обновляться.
// ==UserScript== // @name Reputation Hider // @namespace http://gihub.com/Vogel612/ReputationHider // @version 0.1 // @downloadURL // @updateURL
Метод
Я не являюсь поклонником вашего метода.
Проверка обновлений DOM перед повторным просмотром всего.
Было бы разумнее просто вставить таблицу стилей, чтобы переопределить таблицы стилей SE.
Гораздо больше труда.
Функции ES6
Мне нравится использование ES6 в вашем коде, но вы не использовали его в полном объеме:
let slice = function(collection) { return [].slice.call(collection); }
Вместо использования старой function(collection){}
, вы можете использовать (collection) => ()
:
let slice = (collection) => [].slice.call(collection)
То же самое относится к функции в вашем основном цикле.
Нарезка и нарезка
В настоящее время вы используете только slice
с вашим выбором элемента.
Вы должны объединить два!
slice(document.getElementsByClassName(clazz))
let fetchElements(clazz) => [].slice.call(document.getElementsByClassName(clazz))
Или, эй, давайте сделаем еще один шаг и сделаем магию конкатенации:
let fetchElements = (clazzArrey) =>
clazzArrey.map((clazz) => [].slice.call(document.getElementsByClassName(clazz)))
В качестве альтернативы вы можете использовать конкатенацию строк, чтобы создать одну огромную селекторную строку и использовать querySelectorAll
, как описано Джозефом.
Я нахожу, что querySelector*
может иметь худшую производительность, но всегда были краевыми случаями, которые запускают это для меня.
Поддержка
В настоящее время очень мало браузеров полностью поддерживают ES6. Я не обязательно буду использовать его, если это необходимо. Вы не особенно хотите убить поддержку значительной части пользователей, используя ее.
Будущее глядя
Это, как правило, не является точкой обзора, но я думаю, что вы могли бы добавить поддержку для других полей и создать удобное диалоговое окно dandy, которое вы хотите скрыть. Это будет достойное создание StackApps в моих глазах.
Вместо document.getElementsByClassName
вы можете использовать document.querySelectorAll(CSS selector)
.
Изменить (Ответить на @ 200_success):
Вы можете использовать любого из них. Просто я предпочитаю document.querySelectorAll
, так как я думаю, что это лучше немного .
-
document.getElementsByClassName
имеет 31 букву, аdocument.querySelectorAll
имеет 25 букв. -
document.querySelectorAll
использует CSS для получения элементов DOM, ноdocument.getElementsByClassName
не работает. - IE 8 + поддерживает
document.querySelectorAll
(IE 8 поддерживает только селектора CSS2), ноdocument.getElementsByClassName
предназначен для IE 9 + .
И вам не нужно создавать Array
из DOMNodeList
с помощью slice
, так как DOMNodeList - это DOMNodeList
-like. т. е. вы можете использовать его как Array
, используя Array
.
Array.prototype.forEach.call(DOMNodeList, callbackFunction)
Поскольку вы используете ES6, вы можете заменить функцию slice
на Array.from
, как это (изменение Джозефа тоже);
let hideRepz = function() {
repClasses.forEach(clazz =>
Array.from(document.querySelectorAll(`.${clazz}`))
.forEach(el => {
el.style.display = 'none';
})
);
}
Избегайте использования устаревших событий
События мутации (DOMNodeInserted
) устарел , и вы должны использовать наблюдателей Mutation .
Использование образца:
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
});