Github News Feed Filter

Add filters for Github homepage news feed items

当前为 2014-03-19 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Github News Feed Filter
  3. // @namespace https://github.com/jerone/UserScripts
  4. // @description Add filters for Github homepage news feed items
  5. // @author jerone
  6. // @homepage https://github.com/jerone/UserScripts/tree/master/Github_News_Feed_Filter
  7. // @homepageURL https://github.com/jerone/UserScripts/tree/master/Github_News_Feed_Filter
  8. // @include https://github.com/
  9. // @version 4.1
  10. // @grant none
  11. // ==/UserScript==
  12.  
  13. (function() {
  14.  
  15. var filters = [
  16. { text: "All News Feed", icon: "octicon-radio-tower", classNames: ["*"] },
  17. { text: "Commits", icon: "octicon-git-commit", classNames: ["push"] },
  18. { text: "Pull Requests", icon: "octicon-git-pull-request", classNames: ["pull_request", "pull_request_comment"] },
  19. {
  20. text: "Issues", icon: "octicon-issue-opened", classNames: ["issues_comment", "issues_opened", "issues_closed", "issues_reopened"], subFilters: [
  21. { text: "Comments", icon: "octicon-comment-discussion", classNames: ["issues_comment"] },
  22. { text: "Opened", icon: "octicon-issue-opened", classNames: ["issues_opened"] },
  23. { text: "Closed", icon: "octicon-issue-closed", classNames: ["issues_closed"] },
  24. { text: "Reopened", icon: "octicon-issue-reopened", classNames: ["issues_reopened"] }
  25. ]
  26. },
  27. { text: "Stars", icon: "octicon-star", classNames: ["watch_started"] },
  28. { text: "Repo", icon: "octicon-repo", classNames: ["create", "public", "release", "fork"] },
  29. { text: "Wiki", icon: "octicon-book", classNames: ["gollum"] },
  30. { text: "Gist", icon: "octicon-gist", classNames: ["gist"] }
  31. // Pissible other classes: commit_comment & follow & member_add
  32. ];
  33.  
  34. function proxy(fn) {
  35. return function() {
  36. var that = this;
  37. return function(e) {
  38. var args = that.slice(0); // clone;
  39. args.unshift(e); // prepend event;
  40. fn.apply(this, args);
  41. };
  42. }.call([].slice.call(arguments, 1));
  43. }
  44.  
  45. function addFilterMenuItem(filter, parent, container, sidebar) {
  46. var a = document.createElement("a");
  47. a.classList.add("filter-item");
  48. a.setAttribute("href", "/");
  49. a.setAttribute("title", filter.classNames.join(" & "));
  50. if (filter.classNames[0] === "*") {
  51. a.classList.add("selected");
  52. a.style.fontWeight = "bold";
  53. }
  54.  
  55. var s = document.createElement("span");
  56. s.classList.add("octicon", filter.icon);
  57. s.style.marginRight = "10px";
  58. s.style.cssFloat = "left";
  59. s.style.minWidth = "16px";
  60. a.appendChild(s);
  61.  
  62. var c = document.createElement("span");
  63. c.classList.add("count");
  64. c.appendChild(document.createTextNode("0"));
  65. a.appendChild(c);
  66.  
  67. a.appendChild(document.createTextNode(filter.text));
  68.  
  69. a.addEventListener("click", proxy(function(e, className) {
  70. e.preventDefault();
  71.  
  72. Array.forEach(container.querySelectorAll(".alert"), function(alert) {
  73. alert.style.display = className[0] === "*" || className.some(function(cl) { return alert.classList.contains(cl); }) ? "block" : "none";
  74. });
  75.  
  76. Array.forEach(sidebar.querySelectorAll(".filter-list.small"), function(subUl) {
  77. subUl.style.display = "none";
  78. });
  79. var subUl = this.parentNode.querySelector("ul");
  80. if (!subUl && this.parentNode.parentNode.classList.contains("filter-list") && this.parentNode.parentNode.classList.contains("small")) {
  81. subUl = this.parentNode.parentNode;
  82. }
  83. if (subUl) {
  84. subUl.style.display = "block";
  85. }
  86.  
  87. Array.forEach(sidebar.querySelectorAll(".selected"), function(m) { m.classList.remove("selected"); });
  88. this.classList.add("selected");
  89. }, filter.classNames));
  90.  
  91. var li = document.createElement("li");
  92. li.appendChild(a);
  93. li.filterClassNames = filter.classNames;
  94.  
  95. parent.appendChild(li);
  96.  
  97. return li;
  98. }
  99.  
  100. function addFilters() {
  101. var container = document.querySelector(".news");
  102. if (!container) return;
  103.  
  104. var sidebar = document.querySelector(".dashboard-sidebar");
  105.  
  106. var rule = document.createElement("div");
  107. rule.classList.add("rule");
  108. sidebar.insertBefore(rule, sidebar.firstChild);
  109.  
  110. var ul = document.createElement("ul");
  111. ul.classList.add("filter-list");
  112. sidebar.insertBefore(ul, sidebar.firstChild);
  113.  
  114. filters.forEach(function(filter) {
  115. var li = addFilterMenuItem(filter, ul, container, sidebar);
  116.  
  117. if (filter.subFilters) {
  118. var subUl = document.createElement("ul");
  119. subUl.classList.add("filter-list", "small");
  120. subUl.style.marginLeft = "10px";
  121. subUl.style.display = "none";
  122. li.appendChild(subUl);
  123.  
  124. filter.subFilters.forEach(function(subFilter) {
  125. addFilterMenuItem(subFilter, subUl, container, sidebar);
  126. });
  127. }
  128. });
  129.  
  130. // update on clicking "More"-button;
  131. $.pageUpdate(function() {
  132. window.setTimeout(function() {
  133. Array.forEach(container.querySelectorAll(".alert"), function(alert) {
  134. if (alert.getElementsByClassName("octicon-git-pull-request").length > 0) {
  135. alert.classList.remove("issues_opened", "issues_closed");
  136. alert.classList.add("pull_request");
  137. } else if (alert.classList.contains("issues_comment") && alert.querySelectorAll(".title a")[1].getAttribute("href").split("/")[5] === "pull") {
  138. alert.classList.remove("issues_comment");
  139. alert.classList.add("pull_request_comment");
  140. }
  141. });
  142.  
  143. Array.forEach(ul.querySelectorAll("li"), function(li) {
  144. var c = li.querySelector(".count");
  145. if (li.filterClassNames[0] === "*") {
  146. c.textContent = container.querySelectorAll(".alert").length;
  147. } else {
  148. c.textContent = "0";
  149. Array.forEach(container.querySelectorAll(".alert"), function(alert) {
  150. if (li.filterClassNames.some(function(cl) { return alert.classList.contains(cl); })) {
  151. c.textContent = parseInt(c.textContent, 10) + 1;
  152. }
  153. });
  154. }
  155. });
  156.  
  157. sidebar.querySelector(".selected").dispatchEvent(new Event("click"));
  158. }, 1);
  159. });
  160. }
  161.  
  162. // init;
  163. addFilters();
  164.  
  165. // on pjax;
  166. $(document).on("pjax:success", addFilters);
  167.  
  168. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址