A Universal Script to Re-Enable the Selection and Copying

解除禁止復制、剪切、選擇文本、右鍵菜單的限制。

目前為 2021-06-12 提交的版本,檢視 最新版本

// ==UserScript==
// @name         A Universal Script to Re-Enable the Selection and Copying
// @version      1.5.0
// @description  Enables select, right-click, copy and drag on pages that disable them.
// @description:zh-TW 解除禁止復制、剪切、選擇文本、右鍵菜單的限制。
// @include      /^https?\:\/\//
// @grant        none
// @run-at       document-start
// @namespace https://gf.qytechs.cn/users/371179
// ==/UserScript==
'use strict';
(function($) {

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

    var mKey = 'dqzadwpujtct';
    var _ksNonFalseFunc = '___nff_' + mKey + '___',
        _ksReturnValue = '___returnValue_' + mKey + '___';

    $ = {
        utSelectionColorHack: 'msmtwejkzrqa',

        mAlert_DOWN: function() {}, //dummy function in case alert replacement is not valid
        mAlert_UP: function() {}, //dummy function in case alert replacement is not valid

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

        createCSSElement: function(cssStyle, container) {
            var css = document.createElement('style'); //slope: DOM throughout
            css.type = 'text/css';
            css.innerHTML = cssStyle;
            if (container) container.appendChild(css);
            return css;
        },

        createFakeAlert: function(_alert) {
            if (typeof _alert != 'function') return null;
            function alert(msg) {
                setTimeout(() => {
                    alert.__isDisabled__() ? console.log("alert msg disabled: ", msg) : _alert.apply(this, arguments)
                }, 9);
            };
            alert.toString = () => "function alert() { [native code] }"
            return alert;
        },

        createFuncReplacer: function(originalFunc, pName) {
            var uid = (+new Date) + "_" + pName; // uid for the fake function
            var resFX = function(ev) {
                var p = false;
                try {
                    var func = this[pName];
                    if (typeof func == 'function' && func.uid === uid) p = true;
                } catch (e) {}
                var res = originalFunc.apply(this, arguments);
                if (!p) return res; // unexpected behavior
                if (res !== false) { // return undefined when "return false;"
                    originalFunc[_ksNonFalseFunc] = true;
                    this[pName] = originalFunc; // restore original
                    return res;
                }
            }
            resFX.toString = () => originalFunc.toString()
            resFX.uid = uid
            return resFX;
        },

        listenerDisableAll: function(evt) {
            var elmNode = evt.target;
            while (elmNode && elmNode.nodeType > 0) { //i.e. HTMLDocument or HTMLElement
                var pName = 'on' + evt.type;
                var f = elmNode[pName];
                if (typeof f == 'function' && f[_ksNonFalseFunc] !== true) {
                    var nf = $.createFuncReplacer(f, pName);
                    nf[_ksNonFalseFunc] = true;
                    elmNode[pName] = nf;
                }
                elmNode = elmNode.parentNode;
            }
        },

        onceCssHighlightSelection: () => {
            $.onceCssHighlightSelection = 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($.utSelectionColorHack, "");
            } catch (e) {}
        },


        enableSelectClickCopy: function() {

            var eyEvts = ['keydown', 'keyup', 'copy', 'contextmenu', 'select', 'selectstart', 'dragstart', 'beforecopy']; //slope: throughout

            function isDeactivePreventDefault(evt){
                var j = eyEvts.indexOf(evt.type);
                return (j >= 2)||((j == 0 || j == 1) && evt.ctrlKey && evt.keyCode == 67 && !evt.altKey && !evt.shiftKey && $.isAnySelection() === true); //j<0 return false
            }

            Event.prototype.preventDefault = (function(f) {
                return function preventDefault() {
                    if(!isDeactivePreventDefault(this)) return f.apply(this);
                }
            })(Event.prototype.preventDefault);
            Event.prototype.preventDefault.toString = () => "function preventDefault() { [native code] }"

            Object.defineProperty(Event.prototype, "returnValue", {
                get() {
                    return _ksReturnValue in this ? this[_ksReturnValue] : true;
                },
                set(newValue) {
                    if(!isDeactivePreventDefault(this) && newValue === false) this.preventDefault();
                    this[_ksReturnValue] = newValue;
                },
                enumerable: true,
                configurable: true
            });

            for (var i = 2, eventsCount = eyEvts.length; i < eventsCount; i++) {
                document.addEventListener(eyEvts[i], $.listenerDisableAll, true);
            }

            var _alert = window.alert; //slope: temporary
            if (typeof _alert == 'function') {
                var _mAlert = $.createFakeAlert(_alert);
                if (_mAlert) {
                    var lastClickAt = 0;
                    _mAlert.__isDisabled__ = () => lastClickAt + 50 > +new Date;
                    $.mAlert_DOWN = () => (lastClickAt = +new Date);
                    $.mAlert_UP = () => (lastClickAt = 0);
                    window.alert = _mAlert
                }
            }

        },

        mainEnableScript: () => {

            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;}' +
                '[' + $.utSelectionColorHack + '] :not(input):not(textarea)::selection{ background-color: Highlight !important; color: HighlightText !important;}' +
                '[' + $.utSelectionColorHack + '] :not(input):not(textarea)::-moz-selection{ background-color: Highlight !important; color: HighlightText !important;}';

            $.enableSelectClickCopy()
            $.createCSSElement(cssStyleOnReady, document.documentElement);

        },

        mainEvents: () => {

            var cid_mouseup = 0;

            var alert_bypass_events_down = ["mousedown", "click", "dblclick", "contextmenu"];
            var alert_bypass_eventFunc_down = function(evt) {
                if ($.onceCssHighlightSelection) window.requestAnimationFrame($.onceCssHighlightSelection);
                if (evt.type != "contextmenu" && evt.which != 3) return;
                if (cid_mouseup > 0) {
                    clearTimeout(cid_mouseup)
                    cid_mouseup = 0;
                }
                $.mAlert_DOWN();
            }
            var alert_bypass_eventFunc_up = function(evt) {
                if (evt.which != 3) return;
                cid_mouseup = setTimeout(function() {
                    $.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);

        }

    }

    $.mainEnableScript();

    $.mainEvents();

})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址