Greasy Fork

Greasy Fork is available in English.

在新标签页中打开链接

在页面上显示一个功能开关,改变网页跳转方式改为打开新标签页进行跳转,请自行配置脚本作用域

当前为 2024-11-19 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         在新标签页中打开链接
// @namespace    http://tampermonkey.net/
// @version      1.15
// @description  在页面上显示一个功能开关,改变网页跳转方式改为打开新标签页进行跳转,请自行配置脚本作用域
// @author       晚风知我意
// @match        https://yesicon.app/*
// @match        https://bbs.binmt.cc/*
// @grant        none
// @license      GNU AGPLv3
// ==/UserScript==

(function() {
    'use strict';

    if (localStorage.getItem('linkToggleEnabled') === null) {
        localStorage.setItem('linkToggleEnabled', 'true');
    }

    let isEnabled = localStorage.getItem('linkToggleEnabled') === 'true';
    const ignoredLinks = new Set(JSON.parse(localStorage.getItem('ignoredLinks')) || []);
    
    const button = document.createElement("div");
    button.style.position = "fixed";
    button.style.right = "10px";
    button.style.top = "50%";
    button.style.transform = "translateY(-50%)";
    button.style.cursor = "pointer";
    button.style.zIndex = "9999";
    button.style.width = "50px";  
    button.style.height = "50px"; 
    button.style.borderRadius = "50%";
    button.style.display = "flex"; 
    button.style.alignItems = "center"; 
    button.style.justifyContent = "center"; 
    button.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="none"><path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z"/><path fill="#cccccc" class="icon-path" d="M11.298 2.195a2 2 0 0 1 1.232-.055l.172.055l7 2.625a2 2 0 0 1 1.291 1.708l.007.165v5.363a9 9 0 0 1-4.709 7.911l-.266.139l-3.354 1.677a1.5 1.5 0 0 1-1.198.062l-.144-.062l-3.354-1.677a9 9 0 0 1-4.97-7.75l-.005-.3V6.693a2 2 0 0 1 1.145-1.808l.153-.065zM12 4.068L5 6.693v5.363a7 7 0 0 0 3.635 6.138l.235.123L12 19.882l3.13-1.565a7 7 0 0 0 3.865-5.997l.005-.264V6.693zm3.433 4.561a1 1 0 0 1 1.497 1.32l-.083.094l-5.234 5.235a1.1 1.1 0 0 1-1.46.085l-.096-.085l-2.404-2.404a1 1 0 0 1 1.32-1.498l.094.083l1.768 1.768z"/></g></svg>`;
    document.body.appendChild(button);

    let longPressTimeout;
    let isDragging = false;

    button.addEventListener("mousedown", (e) => {
        e.preventDefault(); 
        longPressTimeout = setTimeout(() => {
            isDragging = true;
            document.addEventListener('mousemove', mouseMoveHandler);
        }, 500); 
    });

    button.addEventListener("click", (e) => {
        if (!isDragging) {
            toggleFunctionality();
        }
    });

    document.addEventListener("mouseup", () => {
        clearTimeout(longPressTimeout);
        isDragging = false;
        document.removeEventListener('mousemove', mouseMoveHandler);
    });

    function mouseMoveHandler(e) {
        if (isDragging) {
            e.preventDefault(); 
            button.style.left = (e.clientX - button.offsetWidth / 2) + 'px';
            button.style.top = (e.clientY - button.offsetHeight / 2) + 'px';
        }
    }
    
    button.addEventListener('touchstart', (e) => {
        e.preventDefault(); 
        longPressTimeout = setTimeout(() => {
            isDragging = true;
            document.addEventListener('touchmove', touchMoveHandler);
        }, 500); 
    });

    button.addEventListener("touchend", () => {
        clearTimeout(longPressTimeout);
        if (!isDragging) {
            toggleFunctionality(); 
        }
        isDragging = false;
        document.removeEventListener('touchmove', touchMoveHandler);
    });

    function touchMoveHandler(e) {
        if (isDragging) {
            e.preventDefault(); 
            button.style.left = (e.touches[0].clientX - button.offsetWidth / 2) + 'px';
            button.style.top = (e.touches[0].clientY - button.offsetHeight / 2) + 'px';
        }
    }

    function toggleFunctionality() {     
        isEnabled = !isEnabled;
        localStorage.setItem('linkToggleEnabled', isEnabled);
        updateButtonState(isEnabled);

        if (isEnabled) {
            enableLinkOpening();
        } else {
            disableLinkOpening();
        }
    }

    function updateButtonState(newState) {
        const paths = button.querySelectorAll('.icon-path');
        paths.forEach(path => {
            path.setAttribute('fill', newState ? "#FDB122" : "#cccccc");        
        });
    }

    function enableLinkOpening() {
        const links = document.querySelectorAll('a');
        links.forEach(link => {
            link.addEventListener('click', handleLinkClick, true);
        });

        const observer = new MutationObserver(mutations => {
            mutations.forEach(mutation => {
                mutation.addedNodes.forEach(node => {
                    if (node.nodeType === 1) {
                        const newLinks = node.querySelectorAll('a');
                        newLinks.forEach(newLink => {
                            newLink.addEventListener('click', handleLinkClick, true);
                        });
                    }
                });
            });
        });

        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
    }

    function disableLinkOpening() {
        const links = document.querySelectorAll('a');
        links.forEach(link => {
            link.removeEventListener('click', handleLinkClick, true);
        });
    }

    function isExcludedElement(element) {
        return element.closest('input, textarea, button, .modal, .dialog, [data-popup], [data-modal], .sidebar, .sidebar *, .dropdown, .dropdown *, [role="button"], [onclick], [data-ignore-link], .fixed-container *');
    }

    function handleLinkClick(event) {
        const isLinkElement = event.target.closest('a');
        if (!isLinkElement) return; 
        
        if (isExcludedElement(event.target)) {
            return; 
        }

        const url = new URL(event.currentTarget.href);
        if (ignoredLinks.has(url.href)) {
            console.log(`Ignoring link: ${url.href}`);
            return; 
        }

        const newTab = window.open(url.href, '_blank');
        
        setTimeout(() => {
            try {
                if (!newTab || newTab.closed || typeof newTab.closed === 'undefined' || newTab.document.title === "无标题") {
                    ignoredLinks.add(url.href);
                    localStorage.setItem('ignoredLinks', JSON.stringify(Array.from(ignoredLinks)));
                    console.log(`Added to ignored links: ${url.href}`);
                }
            } catch (e) {
                ignoredLinks.add(url.href);
                localStorage.setItem('ignoredLinks', JSON.stringify(Array.from(ignoredLinks)));
                console.log(`Added to ignored links (cross-origin error): ${url.href}`);
            }
        }, 500); 

        event.preventDefault(); 
        event.stopImmediatePropagation(); 
    }

    updateButtonState(isEnabled);
    if (isEnabled) {
        enableLinkOpening();
    }
})();