🏠 Home 

Greasy Fork is available in English.

Reddit User/Subreddit/Domain Filter

Filter Reddit posts based on the user, subreddit, domain, or post flair name.


安装此脚本?
  1. // ==UserScript==
  2. // @name Reddit User/Subreddit/Domain Filter
  3. // @namespace RedditUserSubDomainFilter
  4. // @version 1.0.3
  5. // @license GNU AGPLv3
  6. // @description Filter Reddit posts based on the user, subreddit, domain, or post flair name.
  7. // @author jcunews
  8. // @include https://*.reddit.com/*
  9. // @grant none
  10. // ==/UserScript==
  11. var filterFlair = JSON.parse(localStorage.filterFlair || "[]"),
  12. filterUser = JSON.parse(localStorage.filterUser || "[]"),
  13. filterSub = JSON.parse(localStorage.filterSub || "[]"),
  14. filterDomain = JSON.parse(localStorage.filterDomain || "[]"),
  15. posts, flair, user, sub, domain, buttonTemplate, button, match, filtered;
  16. function doFilter(dontHide) {
  17. posts = Array.prototype.slice.call(document.querySelectorAll(".thing"));
  18. posts.forEach(function(post,i) {
  19. filtered = false;
  20. flair = post.querySelector(".linkflairlabel");
  21. if (flair) {
  22. match = filterFlair.indexOf(flair.title) >= 0;
  23. filtered = filtered || !!match;
  24. button = flair.nextSibling;
  25. if (!button || !button.getAttribute || !button.getAttribute("type")) {
  26. button = buttonTemplate.cloneNode(true);
  27. button.title = "Filter posts with this flair (CTRL+Click to undo)";
  28. button.style.marginLeft = "";
  29. button.setAttribute("type", "flair");
  30. button.setAttribute("value", flair.title);
  31. button.onclick = setFilter;
  32. flair.parentNode.insertBefore(button, flair.nextSibling);
  33. }
  34. button.style.background = match ? "#b0b" : "#c00";
  35. }
  36. user = post.querySelector(".author");
  37. if (user) {
  38. match = filterUser.indexOf(user.textContent) >= 0;
  39. filtered = filtered || !!match;
  40. button = user.nextSibling;
  41. if (!button || !button.getAttribute || !button.getAttribute("type")) {
  42. button = buttonTemplate.cloneNode(true);
  43. button.title = "Filter posts from this user (CTRL+Click to undo)";
  44. button.style.marginLeft = "";
  45. button.setAttribute("type", "user");
  46. button.setAttribute("value", user.textContent);
  47. button.onclick = setFilter;
  48. user.parentNode.insertBefore(button, user.nextSibling);
  49. }
  50. button.style.background = match ? "#b0b" : "#c00";
  51. }
  52. sub = post.querySelector(".subreddit");
  53. if (sub) {
  54. match = filterSub.indexOf(sub.textContent.match(/\/?(.*)/)[1]) >= 0;
  55. filtered = filtered || !!match;
  56. button = sub.nextSibling;
  57. if (!button || !button.getAttribute || !button.getAttribute("type")) {
  58. button = buttonTemplate.cloneNode(true);
  59. button.title = "Filter posts from this subreddit (CTRL+Click to undo)";
  60. button.setAttribute("type", "sub");
  61. button.setAttribute("value", sub.textContent.match(/\/?(.*)/)[1]);
  62. button.onclick = setFilter;
  63. sub.parentNode.insertBefore(button, sub.nextSibling);
  64. }
  65. button.style.background = match ? "#b0b" : "#c00";
  66. }
  67. domain = post.querySelector(".domain");
  68. if (domain) {
  69. match = filterDomain.indexOf(domain.textContent.match(/\((.*)\)/)[1]) >= 0;
  70. filtered = filtered || !!match;
  71. button = domain.nextSibling;
  72. if (!button || !button.getAttribute || !button.getAttribute("type")) {
  73. button = buttonTemplate.cloneNode(true);
  74. button.title = "Filter posts from this domain (CTRL+Click to undo)";
  75. button.setAttribute("type", "domain");
  76. button.setAttribute("value", domain.textContent.match(/\((.*)\)/)[1]);
  77. button.onclick = setFilter;
  78. domain.parentNode.insertBefore(button, domain.nextSibling);
  79. }
  80. button.style.background = match ? "#b0b" : "#c00";
  81. }
  82. if (filtered) {
  83. if (!dontHide) {
  84. post.setAttribute("filtered", "1");
  85. post.style.display = "none";
  86. }
  87. } else {
  88. post.removeAttribute("filtered");
  89. post.style.display = "";
  90. }
  91. });
  92. }
  93. function setFilter(ev) {
  94. var value, i;
  95. button = ev.target;
  96. value = button.getAttribute("value");
  97. if (!ev.ctrlKey) {
  98. //add filter
  99. switch (button.getAttribute("type")) {
  100. case "flair":
  101. if (filterFlair.indexOf(value) < 0) {
  102. filterFlair.push(value);
  103. localStorage.filterFlair = JSON.stringify(filterFlair);
  104. }
  105. break;
  106. case "user":
  107. if (filterUser.indexOf(value) < 0) {
  108. filterUser.push(value);
  109. localStorage.filterUser = JSON.stringify(filterUser);
  110. }
  111. break;
  112. case "sub":
  113. if (filterSub.indexOf(value) < 0) {
  114. filterSub.push(value);
  115. localStorage.filterSub = JSON.stringify(filterSub);
  116. }
  117. break;
  118. default: //domain
  119. if (filterDomain.indexOf(value) < 0) {
  120. filterDomain.push(value);
  121. localStorage.filterDomain = JSON.stringify(filterDomain);
  122. }
  123. }
  124. } else {
  125. //remove filter
  126. switch (button.getAttribute("type")) {
  127. case "flair":
  128. i = filterFlair.indexOf(value);
  129. if (i >= 0) {
  130. filterFlair.splice(i, 1);
  131. localStorage.filterFlair = JSON.stringify(filterFlair);
  132. }
  133. break;
  134. case "user":
  135. i = filterUser.indexOf(value);
  136. if (i >= 0) {
  137. filterUser.splice(i, 1);
  138. localStorage.filterUser = JSON.stringify(filterUser);
  139. }
  140. break;
  141. case "sub":
  142. i = filterSub.indexOf(value);
  143. if (i >= 0) {
  144. filterSub.splice(i, 1);
  145. localStorage.filterSub = JSON.stringify(filterSub);
  146. }
  147. break;
  148. default: //domain
  149. i = filterDomain.indexOf(value);
  150. if (i >= 0) {
  151. filterDomain.splice(i, 1);
  152. localStorage.filterDomain = JSON.stringify(filterDomain);
  153. }
  154. }
  155. }
  156. doFilter(ev.ctrlKey);
  157. }
  158. function showFiltered() {
  159. posts = Array.prototype.slice.call(document.querySelectorAll(".thing[filtered]"));
  160. posts.forEach(function(post) {
  161. post.style.display = "";
  162. });
  163. }
  164. function addLink(ele) {
  165. ele.appendChild(button);
  166. //monitor dynamic post list
  167. if (window.siteTable_organic) {
  168. (new MutationObserver(function(records) {
  169. var newNodes = 0;
  170. records.forEach(function(record) {
  171. if (record.addedNodes) newNodes += record.addedNodes.length;
  172. });
  173. if (newNodes) doFilter();
  174. })).observe(window.siteTable_organic, { childList: true });
  175. }
  176. }
  177. if (!document.querySelector(".siteTable")) {
  178. //create button template
  179. buttonTemplate = document.createElement("DIV");
  180. buttonTemplate.textContent = "X";
  181. buttonTemplate.style.cssText = "\
  182. display:inline-block; margin-left:1ex; border-radius:4px; padding:0 .7ex; \
  183. background:#c00; text-align:center; line-height:normal; font-size: x-small; \
  184. font-weight:bold; color:#fff; cursor:pointer";
  185. //filter posts
  186. doFilter();
  187. //add link to show all filtered posts
  188. button = document.createElement("A");
  189. button.textContent = "Show Filtered";
  190. button.title = "Temporarily show filtered posts";
  191. button.style.marginLeft = "2ex";
  192. button.href = "javascript:void(0)";
  193. button.onclick = showFiltered;
  194. if (match = document.querySelector(".tabmenu")) { //old layout
  195. addLink(match);
  196. } else if (match = document.querySelector(".gXMvOl")) { //new layout
  197. setTimeout(addLink, 50, match);
  198. }
  199. }