rBlock

Removes redirects of some sites, such as google, zhihu..., add some customization.

As of 2016-06-14 09:50:06 UTC. See the latest version.

// ==UserScript==
// @name         rBlock
// @description  Removes redirects of some sites, such as google, zhihu..., add some customization.
// @namespace    https://greasyfork.org/zh-CN/scripts/20524-redirect-blocker
// @author       nonoroazoro
// @include      /^https?\:\/\/(www|encrypted|news)\.google\./
// @include      /^https?\:\/\/(www)\.zhihu\./
// @version      1.1
// @grant        none
// ==/UserScript==

if (typeof unsafeWindow == "undefined")
{
    unsafeWindow = window;
}

const rBlock = {

    _blockers: [],

    start: function ()
    {
        this.reset();
        for (let blocker of this._blockers)
        {
            blocker.start();
        }
    },

    reset: function ()
    {
        this._blockers = [];

        // 1. google
        this._blockers.push(
            {
                start: function ()
                {
                    if (/^https?\:\/\/(www|encrypted|news)\.google\./.test(unsafeWindow.location.href))
                    {
                        const scope = this._getScope();
                        if (scope)
                        {
                            this._block(scope);
                            const observer = new unsafeWindow.MutationObserver((p_mutations) =>
                            {
                                this._block(scope);
                            });
                            observer.observe(document.body,
                                {
                                    childList: true,
                                    subtree: true
                                });
                        }
                    }
                },

                // block redirects of google
                _block: function (p_scope)
                {
                    let base;
                    let elem;
                    let elems;
                    if (["all", "videos", "news", "apps"].indexOf(p_scope) != -1)
                    {
                        // 1. all/videos/news/apps
                        base = document.querySelector("div#search");
                        elems = base.querySelectorAll(`a[onmousedown^="return rwt("]`);
                        for (let e of elems)
                        {
                            _removeAttributes(e, "onmousedown");
                        }
                    }
                    else if (["images"].indexOf(p_scope) != -1)
                    {
                        // 2. images
                        base = document.querySelector("div#search");
                        elems = base.querySelectorAll(`#irc_cc a[class^="irc_"], #irc_cc a[class*=" irc_"]`);
                        for (let e of elems)
                        {
                            _removeListeners(e, "mousedown");
                        }
                    }
                    else if (["news.google.com"].indexOf(p_scope) != -1)
                    {
                        // 3. news.google.com
                        elems = document.querySelectorAll(`.content-pane-container a.article`);
                        for (let e of elems)
                        {
                            _removeListeners(e, "click mousedown");
                        }
                    }

                    // 4. general
                    revealURL(
                        document.querySelectorAll(`a[href^="/url?"]`),
                        /(?:\/url\?.*url\=)(http.*?)$/i
                    );

                    // 5. cached links
                    let menuLink;
                    let cacheLink;
                    elems = document.querySelectorAll(`a[href^="http://webcache.googleusercontent."], a[href^="https://webcache.googleusercontent."]`);
                    for (let e of elems)
                    {
                        e.style.display = "inline";
                        menuLink = e.closest("div.action-menu.ab_ctl");

                        cacheLink = document.createElement("a");
                        cacheLink.href = e.href.replace(/^http\:/, "https:");
                        cacheLink.target = "_blank";
                        cacheLink.innerText = " Cached ";

                        menuLink.parentNode.insertBefore(cacheLink, menuLink);
                    }
                },

                _getScope: function ()
                {
                    const elem = document.querySelector("div.hdtb-msel");
                    const result = (elem ? elem.innerText : unsafeWindow.location.host).toLowerCase();
                    return result;
                }
            }
        );

        // 2. zhihu
        this._blockers.push(
            {
                start: function ()
                {
                    if (/^https?\:\/\/(www)\.zhihu\./.test(unsafeWindow.location.href))
                    {
                        this._block();
                        const observer = new unsafeWindow.MutationObserver((p_mutations) =>
                        {
                            this._block();
                        });
                        observer.observe(document.body,
                            {
                                childList: true,
                                subtree: true
                            });
                    }
                },

                _block: function ()
                {
                    // 1. general
                    revealURL(
                        document.querySelectorAll(`a[href^="http://link.zhihu.com"], a[href^="https://link.zhihu.com"]`),
                        /https?\:\/\/link\.zhihu\.com\/\?target=(.*)/i
                    );
                }
            }
        );
    }
};

function _removeAttributes(p_element, p_attributes)
{
    if (p_element && typeof p_attributes === "string")
    {
        const attributes = p_attributes.split(/\W+/) || [];
        for (let attribute of attributes)
        {
            p_element.removeAttribute(attribute);
        }
    }
}

function _removeListeners(p_element, p_events)
{
    if (p_element && typeof p_events === "string")
    {
        const events = p_events.split(/\W+/) || [];
        for (let event of events)
        {
            p_element.removeEventListener(event, _preventDefaultAction, true);
            p_element.addEventListener(event, _preventDefaultAction, true);
        }
    }
}

function _preventDefaultAction(e)
{
    e.stopPropagation();
}

/**
 * reveal url
 */
function revealURL(p_elems, p_regex)
{
    if (p_elems && p_regex)
    {
        for (let e of p_elems)
        {
            // reveal url
            const m = e.href.match(p_regex);
            if (m && m[1])
            {
                e.href = decodeURIComponent(m[1]);
            }

            // open in new tab
            if (!e.target)
            {
                e.target = "_blank";
            }
        }
    }
}

rBlock.start();