Ignore InsideNU commenters

Ignore specific users' comments to avoid obnoxious flame wars

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name        Ignore InsideNU commenters
// @description Ignore specific users' comments to avoid obnoxious flame wars
// @namespace   com.steve
// @include     http://www.insidenu.com/*
// @version     1
// @require     http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// @grant       GM_getValue
// @grant       GM_setValue
// @grant       GM_deleteValue
// @grant       GM_listValues
// ==/UserScript==
(function ($) {
  "use strict";
  
  // Gets a key corresponding to this author's ignore status in the greasemonkey store for this script
  function key(author) {
    return 'ignore_' + author;
  }
  
  // Sets a user's ignore status and makes their comments invisible
  function ignore (author) {
    GM_setValue(key(author), 'true');
    find_comments_by(author).each(function () { 
      handle_ignored_comment($(this), author);
    });
  }
  
  // Unsets a user's ignore status and makes their comments visible
  function unignore (author) {
    GM_deleteValue(key(author));
    find_comments_by(author).each(function () {
      handle_unignored_comment($(this), author);
    });
  }
  
  // Gets a value indicating whether the given author is ignored
  function is_ignored(author) {
    return GM_getValue(key(author), false);
  }
  
  // Returns a jquery list of DOM nodes for comments by a particular author
  function find_comments_by(author) {
    return $('.comment').filter(function () {
      return $(this).find('.poster').text() == author;
    });
  }
  
  // Given a comment and its author,
  // - ensure the comment is not visible
  // - remove any buttons related to 'ignoring' the user
  // - Add a message indicating that hte user has been ignored
  // - Add a button to unignore
  function handle_ignored_comment ($comment, author) {
    $comment.find('.title, .cbody, .sig').hide();
    $comment.find('.ignore-user').remove();
    $comment.prepend('<p class="unignore-user">You have ignored ' + author + '</p>');
    $comment.find('.user_actions').append('<a href="javascript: void(0)" class="unignore-user">Un-Ignore ' + author + '</a>');
    $comment.find('.unignore-user').click(function () { unignore(author); });
  }
  
  // Given a comment and its author, 
  // - ensure the comment is visible
  // - remove any buttons related to 'unignoring' the user
  // - add the ignore button
  function handle_unignored_comment ($comment, author) {
    $comment.find('.title, .cbody, .sig').show();
    $comment.find('.unignore-user').remove();
    $comment.find('.user_actions').append('<a href="javascript: void(0)" class="ignore-user">Ignore ' + author + '</a>');
    $comment.find('.ignore-user').click(function () { ignore(author); });
  }
  
  // Given a comment,
  // - check if it's been scanned before, if so return early if not mark scanned
  // - get the author of the comment
  // - if the author is ignored hide it and add the button to unhide
  // - if not, add the button to ignore
  function handle_comment($comment) {
    if ($comment.data('scanned')) { return; }
    $comment.data('scanned', true);
    
    var author = $comment.find('.poster').text();
    
    if (is_ignored(author)) {
      handle_ignored_comment($comment, author);
    }
    else {
      handle_unignored_comment($comment, author);
    }
  }
  
  // Scan comments as they come in
  var observer = new MutationObserver(function (mutations) {
    mutations.forEach(function (mutation) {
      var nodes = Array.prototype.slice.call(mutation.addedNodes);
      nodes.filter(function (node) { return node.nodeType == Node.ELEMENT_NODE && $(node).is('.citem'); })
           .forEach(function (node) {
        handle_comment($(node).find('.comment'));
      })
    });
  });
  
  var config = { childList: true, subtree: true };
  observer.observe(document.getElementById('comments'), config);
  
  // First run: scan all comments (race conditions handled by 'scanned' data member)
  $('#comments .comment').each(function () { handle_comment($(this)); });
})(jQuery.noConflict());