A Universal Script to Re-Enable the Selection and Copying

Enables select, right-click, copy and drag on pages that disable them.

当前为 2021-06-11 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         A Universal Script to Re-Enable the Selection and Copying
// @version      1.4.0
// @description  Enables select, right-click, copy and drag on pages that disable them.
// @include      /^https?\:\/\//
// @grant        none
// @run-at       document-start
// @namespace https://greasyfork.org/users/371179
// ==/UserScript==
"use strict";
(function(usrScrDS) {

    function isDocumentObj(x) {
        return x && x.nodeType == 9
    }

    function isHTMLElementObj(x) {
        return x && x.nodeType == 1
    }

    function appendCssEnabler(container, cssStyle) {
        if (!isHTMLElementObj(container)) return;
        try {
            var css = document.createElement('style');
            css.type = 'text/css';
            css.innerHTML = cssStyle;
            container.appendChild(css);
        } catch (e) {}
    }

    // console.log('script at', location+"")
    if (document == null) return;
    if (!document.documentElement) return;

    var mKey = 'dqzadwpujtct';
    var nonFalseFunc = '___nff_' + mKey + '___';
    var rvSCC = '___returnValue_' + mKey + '___';


    usrScrDS.utSelectionColorHack = 'msmtwejkzrqa';

    var cssStyleOnReady = '*, body *, div, span, body *::before, body *::after, *:hover, *:link, *:visited, *:active , *[style], *[class]{' +
        '-webkit-touch-callout: default !important; -webkit-user-select: auto !important; ' +
        '-khtml-user-select: auto !important; -moz-user-select: auto !important; ' +
        '-ms-user-select: auto !important; user-select: auto !important;}' +
        'html body *:hover>img[src]{pointer-events:auto;}' +
        '[' + usrScrDS.utSelectionColorHack + '] :not(input):not(textarea)::selection{ background-color: Highlight !important; color: HighlightText !important;}' +
        '[' + usrScrDS.utSelectionColorHack + '] :not(input):not(textarea)::-moz-selection{ background-color: Highlight !important; color: HighlightText !important;}';

    //dummy function in case alert replacement is not valid
    usrScrDS.mAlert_DOWN = function() {}
    usrScrDS.mAlert_UP = function() {}

    function universaler(originalFunc, pName) {
        var uid = (+new Date) + "_" + pName
        var resFX = function(ev) {
            var func;
            var p = false;
            try {
                func = this[pName];
                if (typeof func == 'function' && func.uid === uid) {
                    p = true;
                }
            } catch (e) {}
            var res = originalFunc.apply(this, arguments);
            if (p) {
                if (res !== false) {
                    originalFunc[nonFalseFunc] = true;
                    this[pName] = originalFunc;
                    return res;
                }
            } else {
                return res;
            }
        }
        resFX.toString = () => originalFunc.toString()
        resFX.uid = uid
        return resFX;
    }


    usrScrDS.evtListener_disableAll =
        function disableAll(event) {
            var elmNode = event.target
            while (elmNode && elmNode.nodeType > 0) {
                var pName = 'on' + event.type
                var f = elmNode[pName];
                if (f && f[nonFalseFunc] !== true) {
                    var nf = universaler(f, pName);
                    nf[nonFalseFunc] = true;
                    elmNode[pName] = nf;
                }
                elmNode = elmNode.parentNode;
            }
        }


    usrScrDS.isAnySelection =
        function anySelection() {
            var sel = (window.getSelection || function() {})();
            if (!sel) return null;
            if (typeof sel.isCollapsed == 'boolean') return !sel.isCollapsed;
            return sel.toString().length > 0
        }

    usrScrDS.productFakeAlert = function(_alert) {

        var _mAlert = null;

        if (_alert && typeof _alert == 'function') {
            _mAlert = function alert(msg) {
                setTimeout(() => {
                    alert._click.isDisabled() ? console.log("alert msg disabled: ", msg) : _alert.apply(this, arguments)
                }, 9);
            };
            _mAlert.toString = () => "function alert() { [native code] }"
        }

        return _mAlert


    }

    function enableSelectClickCopy() {

        var preventEventList01 = ['copy', 'contextmenu', 'select', 'selectstart', 'dragstart', 'beforecopy'];

        var isAnySelection = usrScrDS.isAnySelection

        Event.prototype.preventDefault = (function(f) {
            var eys = preventEventList01;
            return function preventDefault() {
                if (eys.indexOf(this.type) >= 0) return;
                if (this.type == 'keydown' || this.type == 'keyup') {
                    if (this.ctrlKey && this.keyCode == 67 && !this.altKey && !this.shiftKey && isAnySelection() === true) return;
                }
                return f.apply(this);
            }
        })(Event.prototype.preventDefault);
        Event.prototype.preventDefault.toString = () => "function preventDefault() { [native code] }"

        var exs = preventEventList01;
        Object.defineProperty(Event.prototype, "returnValue", {
            get() {
                return rvSCC in this ? this[rvSCC] : true;
            },
            set(newValue) {
                if (exs.indexOf(this.type) < 0 && newValue === false) this.preventDefault();
                this[rvSCC] = newValue;
            },
            enumerable: true,
            configurable: true
        });

        var ezs = preventEventList01;
        var eventsCount = ezs.length;

        for (var i = 0; i < eventsCount; i++) {
            var event = ezs[i];
            document.addEventListener(event, usrScrDS.evtListener_disableAll, true);
        }


        var _alert = window.alert
        if (_alert && typeof _alert == 'function') {
            var _mAlert = usrScrDS.productFakeAlert(_alert)
            if (_mAlert) {
                var clickLog = {
                    isDisabled: function() {
                        return this.status == 1 && this.last + 50 > +new Date;
                    }
                }
                _mAlert._click = clickLog
                usrScrDS.mAlert_DOWN = function() {
                    clickLog.last = +new Date;
                    clickLog.status = 1;
                }
                usrScrDS.mAlert_UP = function() {
                    clickLog.last = +new Date;
                    clickLog.status = 0;
                }
                window.alert = _mAlert
            }
        }


        usrScrDS.trigger_cssHighlight = () => {
            usrScrDS.trigger_cssHighlight = null
            try {
                //firefox bug: some element, even body, gives wrong bg color -> choose random element on the page.
                var s = [...document.querySelectorAll('a,p,div,span,b,i,strong,li')].filter(elm => elm.childElementCount === 0);
                var elm = (!s.length) ? document.body : s[s.length >> 1];
                var styles = window.getComputedStyle(elm, ':selection');
                var bgColor = styles["backgroundColor"]
                if (/^rgba\(\d+,\s*\d+,\s*\d+,\s*0\)$/.test(bgColor)) document.documentElement.setAttribute(usrScrDS.utSelectionColorHack, "");
            } catch (e) {}

        };


    }

    enableSelectClickCopy()
    appendCssEnabler(document.documentElement, cssStyleOnReady);


    var cid_mouseup = 0;

    var alert_bypass_events_down = ["mousedown", "click", "dblclick", "contextmenu"];
    var alert_bypass_eventFunc_down = function(evt) {
        if (usrScrDS.trigger_cssHighlight) window.requestAnimationFrame(usrScrDS.trigger_cssHighlight);
        if (evt.type != "contextmenu" && evt.which != 3) return;
        if (cid_mouseup > 0) {
            clearTimeout(cid_mouseup)
            cid_mouseup = 0;
        }
        usrScrDS.mAlert_DOWN();
    }
    var alert_bypass_eventFunc_up = function(evt) {
        if (evt.which != 3) return;
        cid_mouseup = setTimeout(function() {
            usrScrDS.mAlert_UP();
        }, 17);
    }

    alert_bypass_events_down.forEach(function(event) {
        document.addEventListener(event, alert_bypass_eventFunc_down, true);
    })

    document.addEventListener("mouseup", alert_bypass_eventFunc_up, true);


})({});