WaniKani Recent Topics Filter

Hides activity from certain boards in the recent topics list

  1. // ==UserScript==
  2. // @name WaniKani Recent Topics Filter
  3. // @namespace ajpazder
  4. // @description Hides activity from certain boards in the recent topics list
  5. // @version 1.0.1
  6. // @author Johnathon Pazder
  7. // @copyright 2015+, Johnathon Pazder
  8. // @license MIT; http://opensource.org/licenses/MIT
  9. // @include http://www.wanikani.com/
  10. // @include https://www.wanikani.com/
  11. // @include http://www.wanikani.com/dashboard
  12. // @include https://www.wanikani.com/dashboard
  13. // @run-at document-end
  14. // @grant none
  15. // ==/UserScript==
  16.  
  17. $(function () {
  18. // To exlcude topics from a specific board, set "shouldBeIgnored" to true
  19. // for the desired board(s) below. Recent posts from these boards will no
  20. // longer be shown in the "Recent Community Chat Topics" list.
  21. var boards = [
  22. {
  23. title: "API And Third-Party Apps",
  24. homepageUrl: "/chat/api-and-third-party-apps",
  25. shouldBeIgnored: false
  26. },
  27. {
  28. title: "Kanji And Japanese",
  29. homepageUrl: "/chat/kanji-and-japanese",
  30. shouldBeIgnored: false
  31. },
  32. {
  33. title: "WaniKani",
  34. homepageUrl: "/chat/wanikani",
  35. shouldBeIgnored: false
  36. },
  37. {
  38. title: "Campfire",
  39. homepageUrl: "/chat/campfire",
  40. shouldBeIgnored: false
  41. },
  42. {
  43. title: "Japanese Only",
  44. homepageUrl: "/chat/japanese-only",
  45. shouldBeIgnored: false
  46. }
  47. ];
  48. // Leave the rest of this alone, unless you know what you're doing.
  49. //-----------------------------------------------------------------//
  50. indicateFilteringStarted();
  51. var mostRecentTopicsFromAllBoards = [];
  52. var getBoardRequests = [];
  53. boards.forEach(function (board) {
  54. if (board.shouldBeIgnored)
  55. return;
  56. getBoardRequests.push($.get(board.homepageUrl, function (html) {
  57. var mostRecentTopics = getTopFiveMostRecentTopicsFromBoard(html);
  58. mostRecentTopics.forEach(function (topic) {
  59. topic.board = board;
  60. });
  61. mostRecentTopicsFromAllBoards = mostRecentTopicsFromAllBoards.concat(mostRecentTopics);
  62. }));
  63. });
  64. $.when.apply($, getBoardRequests).done(function () {
  65. var numberOfTopicsShownInRecentTopicsList = 5;
  66. var topicsToShowOnDashboard = mostRecentTopicsFromAllBoards
  67. .sort(sortByLastPostNewestFirst)
  68. .slice(0, numberOfTopicsShownInRecentTopicsList);
  69. updateMostRecentTopicsList(topicsToShowOnDashboard);
  70. indicateFilteringStopped();
  71. });
  72. });
  73.  
  74. function indicateFilteringStarted() {
  75. $(".forum-topics-list h3").append('<span id="waitingForFilterLabel">(filtering...)</span>');
  76. }
  77.  
  78. function indicateFilteringStopped() {
  79. $("#waitingForFilterLabel").remove();
  80. }
  81.  
  82. function getTopFiveMostRecentTopicsFromBoard(boardIndexHtml) {
  83. var topicTableRows = $(boardIndexHtml).find(".forum-topics-list tr");
  84. var numberOfUnpinnedTopicsSeen = 0;
  85. var desiredNumberOfUnpinnedTopics = 5;
  86. var topics = [];
  87. topicTableRows.each(function () {
  88. if (numberOfUnpinnedTopicsSeen === desiredNumberOfUnpinnedTopics)
  89. return false; // Stop iterating.
  90.  
  91. var currentRow = $(this);
  92. if (isHeaderRow(currentRow))
  93. return; // Skip this row.
  94.  
  95. var topic = createTopicObjectFromTableRow(currentRow);
  96. topics.push(topic);
  97. if (!topic.isPinned)
  98. numberOfUnpinnedTopicsSeen++;
  99. });
  100.  
  101. return takeMostRecentTopics(topics, 5);
  102. }
  103.  
  104. function isHeaderRow(row) {
  105. return row.find("th").length > 1;
  106. }
  107.  
  108. function createTopicObjectFromTableRow(topicRow) {
  109. var isPinned = topicRow.find(".icon-pushpin").length > 0;
  110. var topicTitle = topicRow.find(".topic-title").first().text();
  111. var lastPostAuthor = topicRow.children("td:last-child").find('a[href*="community/people"]').first().text();
  112. var linkToTopic = topicRow.find("a").first().attr("href");
  113. var timeElement = topicRow.find("time").first();
  114. var lastPostTime = new Date(timeElement.attr("datetime"));
  115. return {
  116. isPinned: isPinned,
  117. title: topicTitle,
  118. url: linkToTopic,
  119. lastPost: {
  120. author: lastPostAuthor,
  121. time: lastPostTime
  122. }
  123. };
  124. }
  125.  
  126. function takeMostRecentTopics(topics, amount) {
  127. var topicsByPostDate = topics.sort(sortByLastPostNewestFirst);
  128. var mostRecentTopics = topics.slice(0, amount);
  129. return mostRecentTopics;
  130. }
  131.  
  132. function sortByLastPostNewestFirst(a, b) {
  133. return ((a.lastPost.time > b.lastPost.time) ? -1 : ((a.lastPost.time < b.lastPost.time) ? 1 : 0));
  134. }
  135.  
  136. function updateMostRecentTopicsList(topics) {
  137. var topicIndex = 0;
  138. $(".forum-topics-list tr").each(function() {
  139. if (isSeparator(this))
  140. return;
  141. var topic = topics[topicIndex];
  142. $(this).replaceWith(createTopicInfoRow(topic));
  143. topicIndex++;
  144. });
  145. // Get fuzzy dates on our updated topic list.
  146. DateTime.activateFuzzyDate();
  147. }
  148.  
  149. function isSeparator(tableRow) {
  150. return $(tableRow).find("td").length === 1;
  151. }
  152.  
  153. function createTopicInfoRow(topic) {
  154. var lastPostDateTime = topic.lastPost.time.toISOString();
  155. return '<tr>' +
  156. '<td class="description">' +
  157. '<a href="' + topic.url + '" class="topic-title">' + topic.title + '</a><br>@ <a href="' + topic.board.homepageUrl + '">' + topic.board.title + '</a>' +
  158. '</td>' +
  159. '<td>' +
  160. '<a href="' + topic.url + '"><time class="timeago" datetime="' + lastPostDateTime + '" title="' + topic.lastPost.time.toString() + '">' + lastPostDateTime + '</time></a>' +
  161. '<br>by <a href="/community/people/' + topic.lastPost.author + '" target="_blank">' + topic.lastPost.author + '</a>' +
  162. '</td>' +
  163. '</tr>';
  164. }