WaniKani Recent Topics Filter

Hides activity from certain boards in the recent topics list

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name        WaniKani Recent Topics Filter
// @namespace   ajpazder
// @description Hides activity from certain boards in the recent topics list
// @version     1.0.1
// @author      Johnathon Pazder
// @copyright   2015+, Johnathon Pazder
// @license     MIT; http://opensource.org/licenses/MIT
// @include     http://www.wanikani.com/
// @include     https://www.wanikani.com/
// @include     http://www.wanikani.com/dashboard
// @include     https://www.wanikani.com/dashboard
// @run-at      document-end
// @grant       none
// ==/UserScript==

$(function () {
    // To exlcude topics from a specific board, set "shouldBeIgnored" to true
    // for the desired board(s) below.  Recent posts from these boards will no
    // longer be shown in the "Recent Community Chat Topics" list.
    var boards = [
        {
            title: "API And Third-Party Apps",
            homepageUrl: "/chat/api-and-third-party-apps",
            shouldBeIgnored: false
        },
        {
            title: "Kanji And Japanese",
            homepageUrl: "/chat/kanji-and-japanese",
            shouldBeIgnored: false
        },
        {
            title: "WaniKani",
            homepageUrl: "/chat/wanikani",
            shouldBeIgnored: false
        },
        {
            title: "Campfire",
            homepageUrl: "/chat/campfire",
            shouldBeIgnored: false
        },
        {
            title: "Japanese Only",
            homepageUrl: "/chat/japanese-only",
            shouldBeIgnored: false
        }
    ];
    
    // Leave the rest of this alone, unless you know what you're doing.
    //-----------------------------------------------------------------//
    
    indicateFilteringStarted();
    
    var mostRecentTopicsFromAllBoards = [];
    var getBoardRequests = [];
    boards.forEach(function (board) {
        if (board.shouldBeIgnored) 
            return;
        
        getBoardRequests.push($.get(board.homepageUrl, function (html) {
            var mostRecentTopics = getTopFiveMostRecentTopicsFromBoard(html);
            mostRecentTopics.forEach(function (topic) {
                topic.board = board;
            });
            mostRecentTopicsFromAllBoards = mostRecentTopicsFromAllBoards.concat(mostRecentTopics);
        }));
    });
    
    $.when.apply($, getBoardRequests).done(function () {
        var numberOfTopicsShownInRecentTopicsList = 5;
        var topicsToShowOnDashboard = mostRecentTopicsFromAllBoards
            .sort(sortByLastPostNewestFirst)
            .slice(0, numberOfTopicsShownInRecentTopicsList);
        
        updateMostRecentTopicsList(topicsToShowOnDashboard);
        indicateFilteringStopped();
    });
});

function indicateFilteringStarted() {
    $(".forum-topics-list h3").append('<span id="waitingForFilterLabel">(filtering...)</span>');
}

function indicateFilteringStopped() {
    $("#waitingForFilterLabel").remove();
}

function getTopFiveMostRecentTopicsFromBoard(boardIndexHtml) {
    var topicTableRows = $(boardIndexHtml).find(".forum-topics-list tr");
    var numberOfUnpinnedTopicsSeen = 0;
    var desiredNumberOfUnpinnedTopics = 5;
    var topics = [];
    topicTableRows.each(function () {
        if (numberOfUnpinnedTopicsSeen === desiredNumberOfUnpinnedTopics)
            return false; // Stop iterating.

        var currentRow = $(this);
        if (isHeaderRow(currentRow)) 
            return; // Skip this row.

        var topic = createTopicObjectFromTableRow(currentRow);
        topics.push(topic);
        if (!topic.isPinned)
            numberOfUnpinnedTopicsSeen++;
    });

    return takeMostRecentTopics(topics, 5);
}

function isHeaderRow(row) {
    return row.find("th").length > 1;
}

function createTopicObjectFromTableRow(topicRow) {
    var isPinned = topicRow.find(".icon-pushpin").length > 0;
    var topicTitle = topicRow.find(".topic-title").first().text();
    var lastPostAuthor = topicRow.children("td:last-child").find('a[href*="community/people"]').first().text();
    var linkToTopic = topicRow.find("a").first().attr("href");
    var timeElement = topicRow.find("time").first();
    var lastPostTime = new Date(timeElement.attr("datetime"));
    
    return {
        isPinned: isPinned,
        title: topicTitle,
        url: linkToTopic,
        lastPost: {
            author: lastPostAuthor,
            time: lastPostTime
        }
    };
}

function takeMostRecentTopics(topics, amount) {
    var topicsByPostDate = topics.sort(sortByLastPostNewestFirst);
    var mostRecentTopics = topics.slice(0, amount);
    
    return mostRecentTopics;
}

function sortByLastPostNewestFirst(a, b) {
  return ((a.lastPost.time > b.lastPost.time) ? -1 : ((a.lastPost.time < b.lastPost.time) ? 1 : 0));
}

function updateMostRecentTopicsList(topics) {
    var topicIndex = 0;
    $(".forum-topics-list tr").each(function() {
        if (isSeparator(this))
            return;
        
        var topic = topics[topicIndex];
        $(this).replaceWith(createTopicInfoRow(topic));
        
        topicIndex++;
    });
    
    // Get fuzzy dates on our updated topic list.
    DateTime.activateFuzzyDate();
}

function isSeparator(tableRow) {
    return $(tableRow).find("td").length === 1;
}

function createTopicInfoRow(topic) {
    var lastPostDateTime = topic.lastPost.time.toISOString();
    return '<tr>' +
             '<td class="description">' +
               '<a href="' + topic.url + '" class="topic-title">' + topic.title + '</a><br>@ <a href="' + topic.board.homepageUrl + '">' + topic.board.title + '</a>' +
             '</td>' +
             '<td>' +
               '<a href="' + topic.url + '"><time class="timeago" datetime="' + lastPostDateTime + '" title="' + topic.lastPost.time.toString() + '">' + lastPostDateTime + '</time></a>' +
               '<br>by <a href="/community/people/' + topic.lastPost.author + '" target="_blank">' + topic.lastPost.author + '</a>' +
             '</td>' +
           '</tr>';
}