CopyAnything

Allows highlighting and copying text on websites where it might be disabled by overriding CSS and removing common disabling attributes.

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

Bu betiği yüklemek için Tampermonkey gibi bir uzantı yüklemeniz gerekir.

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!)

Advertisement:

Bu stili yüklemek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için Stylus gibi bir uzantı kurmanız gerekir.

Bu stili yükleyebilmek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı kurmanız gerekir.

Bu stili yükleyebilmek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

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

Advertisement:

// ==UserScript==
// @name         CopyAnything
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Allows highlighting and copying text on websites where it might be disabled by overriding CSS and removing common disabling attributes.
// @author       Aditya Mendiratta
// @match        *://*/*
// @license      MIT
// @grant        none
// ==/UserScript==

(function() {
    'use strict';


    function applyCssOverrides() {
        const style = document.createElement('style');
        style.type = 'text/css';

        style.innerHTML = `
            * {
                -webkit-user-select: text !important;
                -moz-user-select: text !important;
                -ms-user-select: text !important;
                user-select: text !important;
            }
            body {
                -webkit-user-select: text !important;
                -moz-user-select: text !important;
                -ms-user-select: text !important;
                user-select: text !important;
            }
            input, textarea {
                /* Ensure input fields are always selectable,
                   though 'text' should generally cover this too. */
                user-select: auto !important;
            }
        `;
        document.head.appendChild(style);
        console.log('User select CSS overrides applied.');
    }


    function removeDisablingAttributes() {
        const elements = document.querySelectorAll('*');
        let removedCount = 0;
        elements.forEach(el => {
            if (el.hasAttribute('onselectstart')) {
                el.removeAttribute('onselectstart');
                removedCount++;
            }
            if (el.hasAttribute('ondragstart')) {
                el.removeAttribute('ondragstart');
                removedCount++;
            }
            if (el.hasAttribute('oncontextmenu')) {
                el.removeAttribute('oncontextmenu');
                removedCount++;
            }
        });
        if (removedCount > 0) {
            console.log(`Removed ${removedCount} disabling attributes.`);
        }
    }


    const observer = new MutationObserver((mutations) => {
        mutations.forEach((mutation) => {
            if (mutation.type === 'attributes' &&
                (mutation.attributeName === 'onselectstart' ||
                 mutation.attributeName === 'ondragstart' ||
                 mutation.attributeName === 'oncontextmenu')) {
                if (mutation.target.hasAttribute('onselectstart')) { mutation.target.removeAttribute('onselectstart'); }
                if (mutation.target.hasAttribute('ondragstart')) { mutation.target.removeAttribute('ondragstart'); }
                if (mutation.target.hasAttribute('oncontextmenu')) { mutation.target.removeAttribute('oncontextmenu'); }
            }
            else if (mutation.type === 'childList') {
                mutation.addedNodes.forEach(node => {
                    if (node.nodeType === Node.ELEMENT_NODE) {
                        node.style.setProperty('-webkit-user-select', 'text', 'important');
                        node.style.setProperty('-moz-user-select', 'text', 'important');
                        node.style.setProperty('-ms-user-select', 'text', 'important');
                        node.style.setProperty('user-select', 'text', 'important');

                        if (node.hasAttribute('onselectstart')) { node.removeAttribute('onselectstart'); }
                        if (node.hasAttribute('ondragstart')) { node.removeAttribute('ondragstart'); }
                        if (node.hasAttribute('oncontextmenu')) { node.removeAttribute('oncontextmenu'); }

                        node.querySelectorAll('*').forEach(descendant => {
                            if (descendant.hasAttribute('onselectstart')) { descendant.removeAttribute('onselectstart'); }
                            if (descendant.hasAttribute('ondragstart')) { descendant.removeAttribute('ondragstart'); }
                            if (descendant.hasAttribute('oncontextmenu')) { descendant.removeAttribute('oncontextmenu'); }
                        });
                    }
                });
            }
        });
    });


    window.addEventListener('DOMContentLoaded', () => {
        applyCssOverrides();
        removeDisablingAttributes();


        observer.observe(document.body, {
            attributes: true,
            childList: true,
            subtree: true
        });
        console.log('MutationObserver started for dynamic content.');
    });


    window.addEventListener('load', () => {
        applyCssOverrides();
        removeDisablingAttributes();
    });

})();