Google: News Filter

Show or Hide news whatever you want.

Bu betiği kurabilmeniz için Tampermonkey, Greasemonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

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

Bu betiği kurabilmeniz için Tampermonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği kurabilmeniz için Tampermonkey ya da Userscripts gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği indirebilmeniz için ayrıca Tampermonkey gibi bir eklenti kurmanız gerekmektedir.

Bu komut dosyasını yüklemek için bir kullanıcı komut dosyası yöneticisi uzantısı yüklemeniz gerekecek.

(Zaten bir kullanıcı komut dosyası yöneticim var, kurmama izin verin!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Zateb bir user-style yöneticim var, yükleyeyim!)

// ==UserScript==
// @name                Google: News Filter
// @name:zh-TW          Google 新聞過濾篩選
// @name:zh-CN          Google 新闻过滤筛选
// @name:ja             Googleニュースフィルター
// @name:ko             Google 뉴스 필터
// @name:ru             Новостной фильтр Google
// @version             1.0.6
// @description         Show or Hide news whatever you want.
// @description:zh-TW   可自行設定指定的新聞報社顯示或隱藏。
// @description:zh-CN   可自行设定指定的新闻报社显示或隐藏。
// @description:ja      好きなようにニュースを表示または非表示にします。
// @description:ko      원하는 뉴스를 표시하거나 숨 깁니다.
// @description:ru      Показать или скрыть новости, что вы хотите.
// @author              Hayao-Gai
// @namespace           https://github.com/HayaoGai
// @icon                https://i.imgur.com/zHU2Zt3.png
// @match               https://news.google.com/*
// @grant               GM_setValue
// @grant               GM_getValue
// ==/UserScript==

/* jshint esversion: 6 */

(function() {
    'use strict';

    // icon made by https://www.flaticon.com/authors/freepik
    const svg = `<svg width="15px" height="15px" viewBox="0 0 192.701 192.701" fill="#5f6368"><path d="M20.746,104.169l75.61-74.528l75.61,74.54c4.74,4.704,12.439,4.704,17.179,0s4.74-12.319,0-17.011l-84.2-82.997 c-4.559-4.511-12.608-4.535-17.191,0l-84.2,83.009c-4.74,4.692-4.74,12.319,0,17.011C8.307,108.873,16.006,108.873,20.746,104.169 z"/><path d="M104.946,88.373c-4.559-4.511-12.608-4.535-17.191,0l-84.2,82.997c-4.74,4.704-4.74,12.319,0,17.011 c4.74,4.704,12.439,4.704,17.179,0l75.622-74.528l75.61,74.54c4.74,4.704,12.439,4.704,17.179,0s4.74-12.319,0-17.011 L104.946,88.373z"/></svg>`;
    const css =
`.article {
    max-height: 100px;
    overflow: hidden;
    transition: all 0.3s;
}
.hide {
    max-height: 0px;
    padding: 0px !important;
}
.panel {
    border: 1px solid #dadce0;
    border-radius: 8px;
    padding: 8px;
    margin-right: 10px;
}
.title {
    font-size: 1rem;
    font-weight: 500;
    font-family: 'Google Sans', sans-serif;
    display: flex;
}
.hover {
    position: fixed;
    width: 450px;
    max-height: 1000px;
    right: 8px;
    top: 60px;
    border: 1px solid #dadce0;
    border-radius: 8px;
    z-index: 999;
    background: white;
    overflow: hidden;
    transition: max-height 0.3s;
}
.collapse1 {
    max-height: 0px;
}
.collapse2 {
    border: 0px;
}
.arrow {
    margin-left: 15px;
    padding-top: 3px;
    cursor: pointer;
    transform: rotate(0deg);
    transition: all 0.3s ease-in-out;
}
.rotateArrow {
    transform: rotate(180deg);
}
.pressed {
    background-color: #498ce4 !important;
    color: white !important;
}`;
    let scrolling = false;

    CSS();
    locationChange();
    window.addEventListener("load", init);
    window.addEventListener("scroll", update);

    function init(retry = 0) {
        // get all news title
        const titles = document.querySelectorAll("a.wEwyrc");
        // check
        if (!titles.length && retry < 5) {
            setTimeout(() => init(retry + 1), 500);
            return;
        }
        // title text
        const text = [...titles].map(title => title.innerText);
        const news = [...new Set(text)].sort();
        addMenu(news);
    }

    function addMenu(news) {
        // remove exist
        const exist1 = document.querySelector(".panel");
        const exist2 = document.querySelector(".hover");
        if (exist1) {
            exist2.firstElementChild.remove();
            addOption(exist2, news);
            return;
        }
        // get dynamic class.
        let dynamicClass = "";
        document.querySelector("[ng-non-bindable][data-ogsr-up]").classList.forEach(eachClass => {
            dynamicClass += `.${eachClass}`;
        });
        const parent = document.querySelector(dynamicClass);
        // create
        const panel = document.createElement("div");
        panel.className = "panel";
        parent.insertBefore(panel, parent.firstElementChild);
        const title = document.createElement("h2");
        title.className = "title";

        switch(document.querySelector("html").lang) {
            case "zh":
                title.innerText = "Google 新聞過濾篩選";
                break;
            case "ja":
                title.innerText = "Googleニュースフィルター";
                break;
            case "ko":
                title.innerText = "Google 뉴스 필터";
                break;
            case "ru":
                title.innerText = "Новостной фильтр Google";
                break;
            default:
                title.innerText = "Google News Filter";
        }

        panel.appendChild(title);
        const icon = document.createElement("div");
        icon.className = "arrow rotateArrow";
        icon.innerHTML = svg;
        icon.addEventListener("click", () => {
            const toggle = hover.classList.toggle("collapse1");
            setTimeout(() => hover.classList.toggle("collapse2"), toggle ? 300 : 0);
            icon.classList.toggle("rotateArrow");
        });
        title.appendChild(icon);
        const hover = document.createElement("div");
        hover.className = "hover collapse1 collapse2";
        document.body.appendChild(hover);
        // option
        addOption(hover, news);
    }

    function addOption(parent, news) {
        // create
        const div = document.createElement("div");
        div.className = "ndSf3d ttg1Pb j7vNaf Pz9Pcd a8arzf";
        // append
        parent.appendChild(div);
        // news
        news.forEach(text => singleOption(div, text));
    }

    function singleOption(div, text) {
        // create
        const div1 = document.createElement("div");
        div1.className = "To2ZZb u9jkpc hpDt6e DbQnIe rrijPb R7GTQ keNKEd";
        div1.style.cursor = "pointer";
        div1.addEventListener("click", () => setOption(div1, text));
        getOption(div1, text);
        const div2 = document.createElement("div");
        div2.className = "K9tMQ";
        const div3 = document.createElement("div");
        div3.className = "VgnMrb";
        const span1 = document.createElement("span");
        span1.className = "Ix4NZd";
        const span2 = document.createElement("span");
        span2.className = "pPbimc ljLXBd";
        span2.innerText = text;
        // append
        div.appendChild(div1);
        div1.appendChild(div2);
        div2.appendChild(div3);
        div3.appendChild(span1);
        span1.appendChild(span2);
    }

    function getOption(div, text) {
        // change color
        const isCollapse = GM_getValue(text, false);
        if (isCollapse) {
            div.classList.add("pressed");
        }
        // collapse or expand
        execution(isCollapse, text);
    }

    function setOption(div, text) {
        // change color and record
        const isCollapse = div.classList.toggle("pressed");
        GM_setValue(text, isCollapse);
        // collapse or expand
        execution(isCollapse, text);
    }

    function execution(isCollapse, text) {
        // add article class
        document.querySelectorAll("article:not(.article)").forEach(article => article.classList.add("article"));
        // collapse
        if (isCollapse) {
            document.querySelectorAll("article.article:not(.hide)").forEach(article => {
                const title = article.querySelector("a.wEwyrc").innerText;
                if (title.includes(text)) {
                    article.classList.add("hide");
                }
            });
        }
        // expand
        else {
            document.querySelectorAll("article.article.hide").forEach(article => {
                const title = article.querySelector("a.wEwyrc").innerText;
                if (title.includes(text)) {
                    article.classList.remove("hide");
                }
            });
        }
    }

    function update() {
        if (scrolling) return;
        scrolling = true;
        if (document.querySelectorAll("article:not(.article)").length) init();
        setTimeout(() => { scrolling = false; }, 1000);
    }

    function CSS() {
        const style = document.createElement("style");
        style.type = "text/css";
        style.innerHTML = css;
        document.head.appendChild(style);
    }

    function locationChange() {
        window.addEventListener('locationchange', init);
        // situation 1
        history.pushState = (f => function pushState(){
            var ret = f.apply(this, arguments);
            window.dispatchEvent(new Event('pushState'));
            window.dispatchEvent(new Event('locationchange'));
            return ret;
        })(history.pushState);
        // situation 2
        history.replaceState = (f => function replaceState(){
            var ret = f.apply(this, arguments);
            window.dispatchEvent(new Event('replaceState'));
            window.dispatchEvent(new Event('locationchange'));
            return ret;
        })(history.replaceState);
        // situation 3
        window.addEventListener('popstate', () => {
            window.dispatchEvent(new Event('locationchange'));
        });
    }

})();