爱卡黑名单

在爱卡论坛中隐藏某些作者的帖子或者评论

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         爱卡黑名单
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  在爱卡论坛中隐藏某些作者的帖子或者评论
// @author       Junnnnne
// @match        https://*.xcar.com.cn/bbs/*
// @grant        GM_addStyle
// @icon64       data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48cGF0aCBmaWxsPSIjMzMzMzMzIiBzdHJva2U9IiNiYmJiYmIiIGQ9Ik00NSwzQzU3LDMsNjcsMTMsNjcsMjVDNjcsMzMsNjMsNDAsNTYsNDRDNTksNDUsNjIsNDcsNjQsNDlDNTEsNTEsNDIsNjMsNDIsNzZDNDIsODEsNDMsODYsNDYsOTBMMTIsOTBDMTEsOTAsOSw4OSw5LDg3QzEwLDY3LDIwLDUwLDM0LDQ0QzI3LDQwLDIzLDMzLDIzLDI1QzIzLDEzLDMzLDMsNDUsM3oiLz48cGF0aCBmaWxsPSIjYzgzMjMyIiBkPSJNNzAsNTVDODIsNTUsOTIsNjUsOTIsNzdDOTIsODksODIsOTksNzAsOTlDNTgsOTksNDgsODksNDgsNzdDNDgsNjUsNTgsNTUsNzAsNTV6TTgzLDg2Qzg1LDg0LDg2LDgwLDg2LDc3Qzg2LDY4LDc5LDYxLDcwLDYxQzY3LDYxLDYzLDYyLDYxLDY0TDgzLDg2ek01Nyw2OEM1NSw3MCw1NCw3NCw1NCw3N0M1NCw4Niw2MSw5Myw3MCw5M0M3Myw5Myw3Nyw5Miw3OSw5MEw1Nyw2OHoiLz48L3N2Zz4=
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    GM_addStyle(`
        .blacklist-icon {
            background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48cGF0aCBmaWxsPSIjMzMzMzMzIiBzdHJva2U9IiNiYmJiYmIiIGQ9Ik00NSwzQzU3LDMsNjcsMTMsNjcsMjVDNjcsMzMsNjMsNDAsNTYsNDRDNTksNDUsNjIsNDcsNjQsNDlDNTEsNTEsNDIsNjMsNDIsNzZDNDIsODEsNDMsODYsNDYsOTBMMTIsOTBDMTEsOTAsOSw4OSw5LDg3QzEwLDY3LDIwLDUwLDM0LDQ0QzI3LDQwLDIzLDMzLDIzLDI1QzIzLDEzLDMzLDMsNDUsM3oiLz48cGF0aCBmaWxsPSIjYzgzMjMyIiBkPSJNNzAsNTVDODIsNTUsOTIsNjUsOTIsNzdDOTIsODksODIsOTksNzAsOTlDNTgsOTksNDgsODksNDgsNzdDNDgsNjUsNTgsNTUsNzAsNTV6TTgzLDg2Qzg1LDg0LDg2LDgwLDg2LDc3Qzg2LDY4LDc5LDYxLDcwLDYxQzY3LDYxLDYzLDYyLDYxLDY0TDgzLDg2ek01Nyw2OEM1NSw3MCw1NCw3NCw1NCw3N0M1NCw4Niw2MSw5Myw3MCw5M0M3Myw5Myw3Nyw5Miw3OSw5MEw1Nyw2OHoiLz48L3N2Zz4=) !important;
            background-color: unset;
        }

        .blacklist-icon-notshown {
            background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIiBmaWxsPSJub25lIiBzdHJva2U9IiM0NjQ5NGQiIHN0cm9rZS13aWR0aD0iOCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PHBhdGggZD0iTTQ0Ljg5NjYsNUM1NS44NjIxLDUsNjUsMTQuNDgyOCw2NSwyNS44NjIxQzY1LDMzLjQ0ODMsNjIuODAxOSwzOC4xOTUsNTYsNDNDNTguNTIxOCw0NC4xNjYsNjAuMTE1NSw0NS40MjUyLDYxLDQ3QzQ5LjEyMDcsNDguODk2NiwzOS43MDIsNjEuNjE0OSwzOSw3NEMzOC43MzE3LDc4LjczMzgsMzkuMTQ1Niw4My4xNjg5LDQxLDg3TDE0Ljc0MTQsODcuNUMxMy44Mjc2LDg3LjUsMTIsODYuNTUxNywxMiw4NC42NTUyQzEyLjkxMzgsNjUuNjg5NywxNy4yMzIyLDU1LjQ4MjQsMzQsNDRDMjguNDIyNywzOS41OTUsMjQuNzkzMSwzMy40NDgzLDI0Ljc5MzEsMjUuODYyMUMyNC43OTMxLDE0LjQ4MjgsMzMuOTMxLDUsNDQuODk2Niw1eiIvPjxlbGxpcHNlIGN4PSI3MCIgY3k9Ijc3IiByeD0iMTkiIHJ5PSIxOSIvPjxwYXRoIGQ9Ik01Niw2M0w4NCw5MSIvPjwvc3ZnPg==) !important;
            background-color: unset;
        }

        .blacklist-placeholder {
            background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMCAzMCI+PHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZGRkZGRkIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgZD0iTTI1LDEyTDI1LDZMMjQsNUw0LDVMMyw2TDMsMjNMNCwyNEwxNCwyNE03LDEwTDE2LDEwTTcsMTRMMTIsMTRNNywxOEwxMiwxOE0yMiwxNEMyNS4zMTM3LDE0LDI4LDE2LjY4NjMsMjgsMjBDMjgsMjMuMzEzNywyNS4zMTM3LDI2LDIyLDI2QzE4LjY4NjMsMjYsMTYsMjMuMzEzNywxNiwyMEMxNiwxNi42ODYzLDE4LjY4NjMsMTQsMjIsMTR6TTE4LDE3TDI2LDIzIi8+PC9zdmc+);
        }

        .blacklist-unknownicon {
            background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAjhJREFUSEvtlr+vAUEQx1dCQqFQkFAoFAoKhUJBofBnKxQahUJBoVCSUJCQUEju5bN5I3tr73b9SF7zJrmcuN39zHdmdnYzURRF6g8s8w/2Rf18PqvD4fAYls1mVblcVoVCwTc19j041Pf7XS0WC3U8Hp2AWq2mms2mwpEQCwIDnc/nCrVpViwWVbfbDYIHgZfLpdrtdg9mtVp9hBanttut4o3V63Wt3GdeMAtOJhO9DmFEEcpMMyPCmOFw6OMqLxg1q9VKL9Tr9TRUVOZyOV1YwEjDbDbT4zqdjv4/zbzgzWajeAACxsi3FBkAQNh4PNbvRqOhn4/AVDLbp1Qq6TCbylg4n8+rwWAQA1MD7Xb7M7CoI5xsGZRKdZs5xzmcxMTJtxVfr1edN6lYcyFC32q1dApwBAdlHA6RlrSmkppjya/Lcyk0s/jMcWwptlaSpYLtfJqLjEajp0Izv/f7/fcVsxA5JYy2oYgw298IM1VOnt/OsUyUyk5d6fdjSEUz1LuPGeQqHunJZvGFFJU4HwS24a5m8go0WLF4aXYsKhYYlY+FhvhlxUwwwXa+Q0+ll8F2nm0w6mmdX70I0CTW67Wzg5kO0Kk4HAi7zxKLC9jpdFL7/d4LdKlnH1cqlUQnnsA0DPatqz/7VLi+J10eYmBg0+n0a1BxxJX/GDipPb6j1J5DwzHbaAycdhp9CrdPK2eOUS4H/ie5RqH5mM57WyaXgcvlovs1v2+3m1M8eaSVchXibd9E7Uk/sN2vthPbI3cAAAAASUVORK5CYII=);
        }

        .blacklist-button-add {
            background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA4IDgiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2M4MzIzMiI+PGVsbGlwc2UgY3g9IjQiIGN5PSI0IiByeD0iMyIgcnk9IjMiLz48cGF0aCBkPSJNMiwyTDYsNiIvPjwvc3ZnPg==);
            background-color: unset;
            border: none;
            width: 20px;
            height: 20px;
            cursor: pointer;
        }

        .MobileForumPage {
            margin-top: 10px;
            margin-left: 6px;
        }

        .MobileThreadPage {
            transform: translateY(25%);
            margin-left: 6px;
        }

        .ClassicForumPage {
            transform: translateY(20%);
            margin-left: 10px;
        }

        .ClassicThreadPage {
            float: right;
        }

        .NewStyleForumPage {
            float: left;
            transform: translateY(25%);
            margin-right: 10px;
        }

        .NewStyleThreadPage {
            transform: translateY(25%);
            margin-left: 10px;
        }

        a#blacklist_menuitem.show span {
            color: black;
            font-weight: bold;
        }

        a#blacklist_addbutton.show {
            color: black;
            font-weight: bold;
        }

        .blacklist-align-content-center {
            align-content: center;
        }

        .blacklist-pointer-events-none {
            pointer-events: none;
        }

        div#blacklist-panel {
            position: fixed;
            top: 50px;
            width: 300px;
            background: #FFFFFF;
            border: 1px solid #e0e0e0;
            box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
            display: flex;
            flex-direction: column;
            z-index: 9999;

            a {
                display: flex;
                text-decoration: none;
                color: #181818;
                align-items: center;
                margin-right: auto;
                overflow: hidden;
                text-overflow: ellipsis;
            }

            button {
                cursor: pointer;
            }

            button.remove {
                background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZDgxZTA2IiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PHBhdGggZD0iTTIsNkwyMiw2TTcsNkw3LDRMOCwzTDE2LDNMMTcsNEwxNyw0TDE3LDZNNSw5TDUsMjBMNywyMkwxNywyMkwxOSwyMEwxOSw5TTEwLDEwTDEwLDE5TTE0LDEwTDE0LDE5Ii8+PC9zdmc+);
            }

            a:hover {
                color: #08f;
            }

            h2 {
                display: flex;
                align-items: center;
                font-size: 16px;
                font-weight: bold;
                background: #1cb6f8;
                box-sizing: border-box;
                height: 30px;
                margin: 0px;
                padding: 5px;
                cursor: move;

                .button {
                    width: 20px;
                    height: 20px;
                    padding: 0px;
                    margin: 4px;
                    background: none;
                    border: none;

                    svg path {
                        stroke: white;
                        stroke-width: 2px;
                    }

                    #close {
                        margin-left: 10px;
                    }
                }

                .button:hover svg path {
                    stroke-width: 3px;
                }

                .on svg path {
                    stroke: orange;
                }
            }

            ul {
                list-style: none;
                font-size: 14px;
                margin: 2px;
                padding: 4px;
                height: inherit;
                min-height: 100px;
                max-height: 200px;
                overflow-y: auto;

                li {
                    display: flex;
                    align-items: center;
                    padding: 1px 1px;

                    img {
                        width: 30px;
                        height: 30px;
                        border: 1px solid lightgray;
                        border-radius: 50%;
                    }

                    span {
                        overflow: hidden;
                        text-overflow: ellipsis;
                        margin: 0px 6px;
                    }

                    span.count {
                        FONT-WEIGHT: 800;
                        font-size: 12px;
                        text-align: center;
                        color: white;
                        background-color: lightgray;
                        border-radius: 5px;
                        min-width: 12px;
                        margin-right: 8px;
                        padding: 0px 2px;
                        cursor: default;
                    }

                    button {
                        width: 18px;
                        min-width: 18px;
                        height: 18px;
                        padding: 0px;
                        border: none;
                        background: none;
                    }

                    button:hover svg path {
                        stroke-width: 3px;
                    }
                }

                li:hover {
                    background-color: lightgray;
                }

                li.disable {
                    a span {
                        color: darkgray;
                    }

                    a span:hover {
                        color: #08f;
                    }

                    button {
                        cursor: default;
                        pointer-events: none;
                        mix-blend-mode: luminosity;
                        opacity: 30%;
                    }
                }
            }

            ul::-webkit-scrollbar {
                width: 9px;
                height: 9px;
            }

            ul::-webkit-scrollbar-track {
                background-color: #ccc;
            }

            ul::-webkit-scrollbar-thumb {
                background-color: #999;
                border-radius: 2em;
            }

            ul::-webkit-scrollbar-thumb:hover {
                background-color: #fff;
            }

            ul#allAuthors {
                display: none;
            }
        }

        div.blacklist-placeholder {
            width: 30px;
            height: 30px;
            justify-self: center;
        }

        div.activity_three_picture div.blacklist-placeholder {
            margin-bottom: .12rem;
        }
    `);


    class Page {
        static postItemSelector;
        static authorItemSelector;
        static openAuthorHrefInNewWindow;
        static addButtonAfterItemSelector = null;
        static createBlacklistMenuItemWithOnClick(onClick) {}
        static needExcludePostItem($postItem) {return false;}
        static authorIDFromItem($authorItem) {return null;}
        static authorNameFromItem($authorItem) {return null;}
        static authorIconFromItem($authorItem) {return null;}
        static postIDFromItem($postItem) {return null;}

        static idFromHref(href) {
            return Number(substrByMarker(href, "id=", null));
        }

        static authorIconFromHref(href) {
            return (href ? substrByMarker(href, "/my/", ".jpg").split('_')[0] : null);
        }

        static authorHrefOfID(uid) {
            return `//my.xcar.com.cn/space.php?uid=${uid}`;
        }

        static showPostItem($postItem, show) {
            if (show) {
                $postItem.find("div.blacklist-placeholder").remove();
                $postItem.children().show();
            } else {
                $postItem.children().hide();
                $postItem.append($("<div>").addClass("blacklist-placeholder"));
            }
        }

        static observeMutation(onAddedPostItem) {}
    }

    class MobilePage extends Page {
        static mutationObserverSelector;

        static openAuthorHrefInNewWindow = false;

        static createBlacklistMenuItemWithOnClick(onClick) {
            $("div.menu-wrapper>section.tools.clearfix").children().last().after(`
                <div class="item">
                    <a id="blacklist_menuitem" href>
                        <span class="tag blacklist-panel-status" style="transform:scale(0.8);"></span>
                        <span class="txt">黑名单</span>
                    </a>
                </div>
            `);
            $('a#blacklist_menuitem').click(function(event) {
                event.preventDefault();
                event.stopPropagation();
                $("a.menu>em").first().click();
                onClick();
            });
        }

        static authorIDFromItem($authorItem) {
            let href = $authorItem.attr("href");
            return Number(substrByMarker(href, "/author/", ".html"));
        }

        static authorHrefOfID(uid) {
            return `//a.xcar.com.cn/aikahao/author/${uid}.html`;
        }

        static observeMutation(onAddedPostItem) {
            let $target = $(this.mutationObserverSelector);
            if ($target.length > 0) {
                var observer = new MutationObserver(function(mutations) {
                    mutations.forEach(function(mutation) {
                        $(mutation.addedNodes).each(function(){
                            onAddedPostItem($(this[0]));
                        });
                    });
                });
                observer.observe($target[0], {childList: true});
            }
        }
    }

    class ClassicPage extends Page {
        static openAuthorHrefInNewWindow = true;
        static mutationObserverSelector = null;

        static createBlacklistMenuItemWithOnClick(onClick) {
            $("div.muser.menubox>div.muser_show>a").last().before(`
                <a id="blacklist_menuitem" href>
                    <span class="blacklist-panel-status" style="background-size: 16px 16px; background-position: left; background-position-x: 12px;">黑&ensp;名&ensp;单</span>
                </a>
            `);
            $('a#blacklist_menuitem').click(function(event) {
                event.preventDefault();
                event.stopPropagation();
                $("div.muser.menubox").removeClass("hover");
                onClick();
            });
        }
    }

    class NewStylePage extends Page {
        static openAuthorHrefInNewWindow = true;

        static createBlacklistMenuItemWithOnClick(onClick) {
            $(".muser_show>.xlogined>a>i.icon-signoutx2").parent().before(`
                <a id="blacklist_menuitem" href>
                    <i class="blacklist-panel-status" style="width:16px; height:16px;"></i>
                    <span>黑&ensp;名&ensp;单</span>
                </a>
            `);
            $('a#blacklist_menuitem').click(function(event) {
                event.preventDefault();
                event.stopPropagation();
                $("a.menu>em").first().click();
                $("div#xlogininfo").removeClass("hover");
                onClick();
            });
        }
    }

    class MobileForumPage extends MobilePage {
        static postItemSelector = "div.activity_content>div.activity_three_picture";
        static authorItemSelector = "div>a.lazy-face";
        static mutationObserverSelector = "div.activity_content";

        static authorNameFromItem($authorItem) {
            return $authorItem.parent().find("span.go_author").text();
        }

        static authorIconFromItem($authorItem) {
            return this.authorIconFromHref($authorItem.attr("data-original"));
        }

        static postIDFromItem($postItem) {
            return Number(substrByMarker($postItem.attr("data-godetails"), "thread-", ".html").split("-")[0]);
        }

        static createBlacklistMenuItemWithOnClick(onClick) {
            super.createBlacklistMenuItemWithOnClick(onClick);

            $("div.post_interaction>div.post_interaction_tab").css("display", "flex");
            let $rightdiv = $("div.post_interaction_tab>div.follow_tpl.post-btn-wrap.row");
            $rightdiv.css("min-width", "fit-content");
            $rightdiv.children().first().before(`
                <a id="blacklist_addbutton" href style="margin-right: 6px; margin-left: 6px;">黑名单</a>
            `);
            $('a#blacklist_addbutton').click(function(event) {
                event.preventDefault();
                onClick();
            });
        }

        static showPostItem($postItem, show) {
            super.showPostItem($postItem, show);
            if (show) {
                $postItem.removeClass("blacklist-pointer-events-none");
            } else {
                $postItem.addClass("blacklist-pointer-events-none");
            }
        }
    }

    class MobileThreadPage extends MobilePage {
        static postItemSelector = "div.list_box>ul>li";
        static authorItemSelector = "div.post_top>a";
        static mutationObserverSelector = "div.list_box>ul";

        static authorNameFromItem($authorItem) {
            return $authorItem.find("em.username").text();
        }

        static authorIconFromItem($authorItem) {
            return this.authorIconFromHref($authorItem.find("span>img").attr("src"));
        }

        static postIDFromItem($postItem) {
            return Number($postItem.attr("pid"));
        }

        static createBlacklistMenuItemWithOnClick(onClick) {
            super.createBlacklistMenuItemWithOnClick(onClick);

            $("div.footer_replay>ul>li.replay_footer_btn").css("width", "auto");
            let $li = $(`
                <li style="height: 24px; margin-left:.31rem">
                  <span class="blacklist-panel-status" style="width:24px; height:24px;"></span>
                </li>
            `);
            $("div.footer_replay>ul").append($li);
            $li.find('span.blacklist-panel-status').click(function(event) {
                event.preventDefault();
                onClick();
            });
        }
    }

    class ClassicForumPage extends ClassicPage {
        static postItemSelector = "div.post-list>div.table-section>dl.list_dl:not(.table_head)";
        static authorItemSelector = "dd.pub_dd>a.linkblack";

        static authorIDFromItem($authorItem) {
            return this.idFromHref($authorItem.attr("href"));
        }

        static authorNameFromItem($authorItem) {
            return $authorItem.text();
        }

        static authorIconFromItem($authorItem) {
            return null;
        }

        static postIDFromItem($postItem) {
            return this.idFromHref($postItem.find("dt>p.thenomal>a.titlink").attr("href"));
        }

        static showPostItem($postItem, show) {
            super.showPostItem($postItem, show);
            if (show) {
                $postItem.removeClass("blacklist-align-content-center");
            } else {
                $postItem.addClass("blacklist-align-content-center");
            }
        }
    }

    class ClassicThreadPage extends ClassicPage {
        static postItemSelector = "form#delpost>div.main.item";
        static authorItemSelector = "table.mainbox>tbody>tr>td.sidebar>div.userside>div.user_info";
        static addButtonAfterItemSelector = "table.mainbox>tbody>tr>td.sidebar>div.userside>div.otherinfo>p.star>img:last";

        static needExcludePostItem($postItem) {
            return ($postItem.find("table.mainbox>tbody>tr>td.side_content>div.mainwrap>span.t_title1").length > 0);
        }

        static authorIDFromItem($authorItem) {
            return this.idFromHref($authorItem.find("p.avatar>a").attr("href"));
        }

        static authorNameFromItem($authorItem) {
            return $authorItem.find("p.name>a").text();
        }

        static authorIconFromItem($authorItem) {
            return this.authorIconFromHref($authorItem.find("p.avatar>a>img").attr("src"));
        }

        static postIDFromItem($postItem) {
            return Number(substrByMarker($postItem.find(">a").attr("name"), "pid", null));
        }
    }

    class NewStyleForumPage extends NewStylePage {
        static postItemSelector = "ul.topic_list_item>li.default_item";
        static authorItemSelector = "div.user_item>a.user_photo";

        static authorIDFromItem($authorItem) {
            return this.idFromHref($authorItem.attr("href"));
        }

        static authorNameFromItem($authorItem) {
            return $authorItem.find("span.user_name").text();
        }

        static authorIconFromItem($authorItem) {
            return this.authorIconFromHref($authorItem.find("img").attr("src"));
        }

        static postIDFromItem($postItem) {
            return this.idFromHref($postItem.find("dl.article_item>dt>a").attr("href"));
        }

        static createBlacklistMenuItemWithOnClick(onClick) {
            super.createBlacklistMenuItemWithOnClick(onClick);

            $("ul#navItem").append(`
                <li style="float: right;">
                  <a id="blacklist_addbutton" href style="font-size: 16px; margin-right: 30px; margin-left: 10px;">黑名单</a>
                </li>
            `);
            $("div#fixNav>div.nav_item>ul").append(`
                <li style="float: right;">
                  <a id="blacklist_addbutton" href style="font-size: 16px; margin-right: 20px; margin-left: 10px;">黑名单</a>
                </li>
            `);
            $('a#blacklist_addbutton').click(function(event) {
                event.preventDefault();
                onClick();
            });
        }

        static observeMutation(onAddedPostItem) {
            var observer = new MutationObserver(function(mutations) {
                mutations.forEach(function(mutation) {
                    $(mutation.addedNodes).filter("li.default_item").each(function(){
                        onAddedPostItem($(this));
                    });
                });
            });
            observer.observe($("ul#listForum.topic_list_item")[0], {childList: true});
        }
    }

    class NewStyleThreadPage extends NewStylePage {
        static postItemSelector = "div.comment_all>div.comment_txt_box";
        static authorItemSelector = "div.comment_author>div.author_div_user";

        static authorIDFromItem($authorItem) {
            return this.idFromHref($authorItem.find("a.comment_author_username").attr("href"));
        }

        static authorNameFromItem($authorItem) {
            return $authorItem.find("a.comment_author_username").text();
        }

        static authorIconFromItem($authorItem) {
            return this.authorIconFromHref($authorItem.find("a.comment_author_img>img").attr("src"));
        }

        static postIDFromItem($postItem) {
            return Number($postItem.find("div.jb_hover").attr("data_pid"));
        }

        static showPostItem($postItem, show) {
            super.showPostItem($postItem, show);
            if (show == false) {
                $postItem.find("div.comment_line").show();
            }
        }

        static observeMutation(onAddedPostItem) {
            var observer = new MutationObserver(function(mutations) {
                mutations.forEach(function(mutation) {
                    $(mutation.addedNodes).filter("div.comment_txt").find("div#comment_all>div.comment_txt_box").each(function(){
                        onAddedPostItem($(this));
                    });

                    var observerAgain = new MutationObserver(function(mutations) {
                        $(mutation.addedNodes).filter("div.comment_txt").find("div#comment_all>div.comment_txt_box").each(function(){
                            onAddedPostItem($(this));
                        });
                    });
                    observerAgain.observe($(mutation.addedNodes).filter("div.comment_txt").find("div#comment_all")[0], {childList: true});
                });
            });
            observer.observe($("div.details>div.floor_div>div#comment")[0], {childList: true});
        }
    }


    let forMobile = (location.hostname.split(".")[0] == "a");
    let isOldStyle = ($("div.forum-head>a.tabNewxbbxq").length > 0);
    let filename = location.pathname.split("/")[2];
    let pageClass;
    if (forMobile) {
        switch (filename.split("-")[0]) {
            case "forum":
            case "digest":
                pageClass = MobileForumPage;
                break;
            case "thread":
                pageClass = MobileThreadPage;
                break;
            default:
                return;
        }
    } else {
        if (isOldStyle) {
            switch (filename) {
                case "forumdisplay.php":
                    pageClass = ClassicForumPage;
                    break;
                case "viewthread.php":
                    pageClass = ClassicThreadPage;
                    break;
                default:
                    return;
            }
        } else {
            switch (filename) {
                case "forumdisplay.php":
                    pageClass = NewStyleForumPage;
                    break;
                case "viewthread.php":
                    pageClass = NewStyleThreadPage;
                    break;
                default:
                    return;
            }
        }
    }

    $('body').append($(`
        <div id="blacklist-panel" style="display: none;">
            <h2>
                <span class="blacklist-icon" style="width:24px; height:24px;"></span>
                <span style="color: #363636; margin-left: 2px; margin-right: auto;">黑名单</span>
                <button type="button" id="close" class="button">
                    <svg viewBox="0 0 20 20">
                        <path d="M3,3L17,17M17,3L3,17" />
                    </svg>
                </button>
            </h2>
            <ul id="blacklist">
            </ul>
        </div>
    `));

    const MIN_REMAIN_WIDTH = 80;
    const MIN_REMAIN_HEIGHT = 30;

    let $panel = $("div#blacklist-panel");
    let $h2 = $panel.find("h2");
    let $buttonClose = $h2.find("button#close");
    let $blacklist = $panel.find("ul#blacklist");

    pageClass.createBlacklistMenuItemWithOnClick(function() {
        adjustPanelPosition();

        if ($panel.is(':visible')) {
            $buttonClose.click();
        } else {
            $('a#blacklist_menuitem').addClass("show");
            $('a#blacklist_addbutton').addClass("show");
            $('.blacklist-panel-status').removeClass("blacklist-icon-notshown");
            $('.blacklist-panel-status').addClass("blacklist-icon");
            $panel.show();
            $(pageClass.postItemSelector).each(function(){
                if (pageClass.needExcludePostItem($(this)) == false) {
                    appendAddButton($(this));
                }
            });

            localStorage.setItem("show_panel", true);
        }
    });

    let panelPosition = JSON.parse(localStorage.getItem("panel_position") || '{"top": 0, "left": 0}');
    $panel.offset(panelPosition);
    var showPanel = JSON.parse(localStorage.getItem("show_panel") || "false");
    if (showPanel) {
        $('a#blacklist_menuitem').addClass("show");
        $('a#blacklist_addbutton').addClass("show");
        $('.blacklist-panel-status').addClass("blacklist-icon");
        $panel.show();
        adjustPanelPosition();
    } else {
        $('.blacklist-panel-status').addClass("blacklist-icon-notshown");
    }

    (function() {
        var active = false;
        var initialX;
        var initialY;

        function moveBegin($target, clientX, clientY) {
            if ($target.parents("button").length == 0) {
                initialX = clientX - ($panel.position().left - $(window).scrollLeft());
                initialY = clientY - ($panel.position().top - $(window).scrollTop());
                active = true;
            }
        }

        function moving(e, clientX, clientY) {
            if (active) {
                e.preventDefault();

                var maxLeft = document.documentElement.clientWidth - MIN_REMAIN_WIDTH;
                var maxTop = document.documentElement.clientHeight - MIN_REMAIN_HEIGHT;
                var currentX = clientX - initialX;
                var currentY = clientY - initialY;
                currentX = (currentX < 0 ? 0 : currentX);
                currentX = (currentX > maxLeft ? maxLeft : currentX);
                currentY = (currentY < 0 ? 0 : currentY);
                currentY = (currentY > maxTop ? maxTop : currentY);
                $panel.css({top: currentY, left: currentX});
                localStorage.setItem("panel_position", JSON.stringify({top: currentY, left: currentX}));
            }
        }

        function moveEnd(e) {
            active = false;
        }

        $h2.on("mousedown",          function (e) { moveBegin($(e.target), e.clientX, e.clientY); });
        $(document).on("mousemove",  function (e) { moving(e, e.clientX, e.clientY); });
        $(document).on("mouseup",    moveEnd);
        $h2.on("touchstart", function (e) { moveBegin($(e.target), e.touches[0].clientX, e.touches[0].clientY); });
        $h2.on("touchmove",  function (e) { moving(e, e.touches[0].clientX, e.touches[0].clientY); });
        $h2.on("touchend",   moveEnd);
    })();

    function adjustPanelPosition() {
        if ($panel.is(':visible')) {
            var maxLeft = document.documentElement.clientWidth - MIN_REMAIN_WIDTH;
            var maxTop = document.documentElement.clientHeight - MIN_REMAIN_HEIGHT;

            var oPanel = $panel[0];
            var changed = false;

            if (oPanel.offsetTop < 0) {
                oPanel.style.top = 0 + "px";
                changed = true;
            }

            if (oPanel.offsetLeft < 0) {
                oPanel.style.left = 0 + "px";
                changed = true;
            }

            if (oPanel.offsetTop > maxLeft) {
                oPanel.style.top = maxLeft + "px";
                changed = true;
            }

            if (oPanel.offsetLeft > maxTop) {
                oPanel.style.left = maxTop + "px";
                changed = true;
            }

            if (changed) {
                localStorage.setItem("panel_position", JSON.stringify({top: oPanel.offsetTop, left: oPanel.offsetLeft}));
            }
        }
    }

    $(window).resize(adjustPanelPosition);

    let blackListDatas = JSON.parse(localStorage.getItem("blackList") || "[]");
    blackListDatas.forEach(data => {
        let $authorItem = makeAuthorItem({
            uid: data.uid,
            name: data.name,
            icon: data.icon,
            pids: null
        });
        $blacklist.append($authorItem);
    });

    let allAuthorDatas = [];

    $(pageClass.postItemSelector).each(function(){
        if (pageClass.needExcludePostItem($(this)) == false) {
            dealWithAddedPostItem($(this));
        }
    });

    $buttonClose.click(function () {
        $('a#blacklist_menuitem').removeClass("show");
        $('a#blacklist_addbutton').removeClass("show");
        $('.blacklist-panel-status').removeClass("blacklist-icon");
        $('.blacklist-panel-status').addClass("blacklist-icon-notshown");
        $panel.hide();
        $("button.blacklist-button-add").remove();
        localStorage.setItem("show_panel", false);
    });

    pageClass.observeMutation(function($addedPostItem) {
        if (pageClass.needExcludePostItem($addedPostItem) == false) {
            dealWithAddedPostItem($addedPostItem);
        }
    });

    function makeAuthorItem(data) {
        let $img = $("<img>");
        if (data.icon != null) {
            $img.attr("src", `//image1.xcarimg.com/attachments/my/${data.icon}_50.jpg`);
            $img.attr("onerror", "this.onerror=null;this.src='//image1.xcarimg.com/attachments/my/default/50.jpg'");
        } else {
            $img.addClass("blacklist-unknownicon");
        }

        let $span = $("<span>").text(data.name);

        let authorHref = pageClass.authorHrefOfID(data.uid);
        let $a = $("<a>").attr("href", authorHref);
        if (pageClass.openAuthorHrefInNewWindow) {
            $a.attr("target", "_blank");
        }
        $a.append($img).append($span);

        let $spanCount = $("<span>").addClass("count");
        if (data.pids && data.pids.size > 0) {
            $spanCount.text(data.pids.size);
            $spanCount.show();
        } else {
            $spanCount.text("");
            $spanCount.hide();
        }

        let $button = $("<button>").addClass("remove");
        $button.click(function () {
            let $li = $(this).parent();
            let uid = Number($li.attr("id").substr(1));
            $li.remove();

            let dataIndex = blackListDatas.findIndex(data => data.uid === uid);
            if (dataIndex >= 0) {
                blackListDatas.splice(dataIndex, 1);
            }
            localStorage.setItem("blackList", JSON.stringify(blackListDatas));

            $(pageClass.postItemSelector).each(function(){
                if (pageClass.needExcludePostItem($(this)) == false) {
                    let $authorItem = $(this).find(pageClass.authorItemSelector);
                    if (pageClass.authorIDFromItem($authorItem) == uid) {
                        pageClass.showPostItem($(this), true);
                    }
                }
            });
        });

        let $li = $("<li>").attr("id", `u${data.uid}`);
        $li.append($a).append($spanCount).append($button);
        return $li;
    }

    function dealWithAddedPostItem($postItem) {
        let $authorItem = $postItem.find(pageClass.authorItemSelector);
        let uid = pageClass.authorIDFromItem($authorItem);
        let name = pageClass.authorNameFromItem($authorItem);
        let icon = pageClass.authorIconFromItem($authorItem);
        let pid = pageClass.postIDFromItem($postItem);

        if ($panel.is(':visible')) {
            appendAddButton($postItem);
        }

        let itemData;
        var countChanged = false;
        let blackListData = blackListDatas.find(data => data.uid == uid);
        let matched = allAuthorDatas.find(data => data.uid == uid);
        if (matched !== undefined) {
            itemData = matched;
            if (itemData.pids.has(pid) == false) {
                itemData.pids.add(pid);
                countChanged = true;
            }
        } else {
            itemData = {
                uid: uid,
                name: name,
                icon: icon,
                pids: new Set([pid])
            };
            allAuthorDatas.push(itemData);
            countChanged = true;
        }

        if (blackListData !== undefined) {
            let $blacklistItem = $blacklist.find(`li[id='u${uid}']`);
            if (countChanged) {
                let $countItem = $blacklistItem.find("span.count");
                if (itemData.pids.size > 0) {
                    $countItem.text(itemData.pids.size);
                    $countItem.show();
                } else {
                    $countItem.hide();
                }
            }

            var changed = false;
            if (blackListData.name != name) {
                blackListData.name = name;
                changed = true;
            }
            if (icon != null && blackListData.icon != icon) {
                blackListData.icon = icon;
                changed = true;
            }
            if (changed) {
                let $newAuthorItem = makeAuthorItem(itemData);
                $blacklistItem.replaceWith($newAuthorItem);

                localStorage.setItem("blackList", JSON.stringify(blackListDatas));
            }

            pageClass.showPostItem($postItem, false);
        }
    }

    function appendAddButton($postItem) {
        let $authorItem = $postItem.find(pageClass.authorItemSelector);
        let uid = pageClass.authorIDFromItem($authorItem);
        let name = pageClass.authorNameFromItem($authorItem);
        let icon = pageClass.authorIconFromItem($authorItem);

        let $button = $("<button>").attr("type", "button").addClass("blacklist-button-add").addClass(pageClass.name);
        $button.click(function (event) {
            event.stopPropagation();

            let matched = allAuthorDatas.find(data => data.uid == uid);
            let data = {
                uid: uid,
                name: name,
                icon: icon,
                pids: (matched !== undefined ? matched.pids : null)
            };
            let $authorItem = makeAuthorItem(data);
            $blacklist.append($authorItem);
            $blacklist.animate({scrollTop:$(document).height()}, 'slow');
            $blacklist.scrollTop($(document).height());

            blackListDatas.push({
                uid: uid,
                name: name,
                icon: icon
            });

            localStorage.setItem("blackList", JSON.stringify(blackListDatas));
            $(pageClass.postItemSelector).each(function(){
                if (pageClass.needExcludePostItem($(this)) == false) {
                    let $authorItem = $(this).find(pageClass.authorItemSelector);
                    if (pageClass.authorIDFromItem($authorItem) == uid) {
                        pageClass.showPostItem($(this), false);
                    }
                }
            });

        });
        let $afterItem = (pageClass.addButtonAfterItemSelector ? $postItem.find(pageClass.addButtonAfterItemSelector) : $authorItem);
        $afterItem.after($button);
    }

    function substrByMarker(string, leftMarker, rightMarker) {
        let indexOfLeft = (leftMarker != null ? string.indexOf(leftMarker) + leftMarker.length : 0);
        let indexOfRight = (rightMarker != null ? string.indexOf(rightMarker) : string.length);
        return string.substr(indexOfLeft, indexOfRight - indexOfLeft);
    }

})();