Greasy Fork

来自缓存

Greasy Fork is available in English.

eagle tagger | 区分不同浏览器身份,添加不同的 tag

hover 和按键追加 eagle-tags,英文逗号隔开,去重添加,标签配置持久化存储,支持Alt键批量添加+节流防抖

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         eagle tagger | 区分不同浏览器身份,添加不同的 tag
// @namespace    http://leizingyiu.net/
// @version      20250511
// @description  hover 和按键追加 eagle-tags,英文逗号隔开,去重添加,标签配置持久化存储,支持Alt键批量添加+节流防抖
// @author       leizingyiu
// @match        *://*/*
// @grant        GM_getValue
// @grant        GM_setValue
// @license      GNU AGPLv3 

// ==/UserScript==

(function() {
    'use strict';

    const defaultBrowserTags = "browser-A,browser-B,browser-C";
    const defaultTagsDict = {
        a: "tagA",
        b: "tagB",
        c: "tagC"
    };

    function getBrowserTags() {
        let tags = GM_getValue('thisBrowserTags', defaultBrowserTags);
        return tags.replace(/,/g, ',');
    }

    function getTagsDict() {
        let dictStr = GM_getValue('tagsDict', JSON.stringify(defaultTagsDict));
        try {
            let dict = JSON.parse(dictStr);
            return dict;
        } catch (e) {
            console.error('tagsDict 格式错误,已重置默认值');
            GM_setValue('tagsDict', JSON.stringify(defaultTagsDict));
            return defaultTagsDict;
        }
    }

    function addTagsToItem(item, tags) {
        if (!item) return;

        let oriTag = item.getAttribute('eagle-tags') || '';

        let oriTagList = oriTag.split(',')
            .map(tag => tag.trim())
            .filter(tag => tag.length > 0);

        let addTagList = Array.isArray(tags)
            ? tags
            : tags.replace(/,/g, ',')
                .split(',')
                .map(tag => tag.trim())
                .filter(tag => tag.length > 0);

        addTagList.forEach(tag => {
            if (!oriTagList.includes(tag)) {
                oriTagList.push(tag);
            }
        });

        item.setAttribute('eagle-tags', oriTagList.join(', '));
        console.log('已更新 eagle-tags:', item.getAttribute('eagle-tags'));
    }

     function debounce(func, delay) {
        let timer;
        return function(...args) {
            clearTimeout(timer);
            timer = setTimeout(() => {
                func.apply(this, args);
            }, delay);
        };
    }

     function throttle(func, limit) {
        let inThrottle;
        return function(...args) {
            if (!inThrottle) {
                func.apply(this, args);
                inThrottle = true;
                setTimeout(() => inThrottle = false, limit);
            }
        };
    }

    let currentHoverItem = null;

    function addHoverListeners() {
        document.querySelectorAll('img, video').forEach(item => {
            if (item.hasAttribute('data-hover-tagged')) return;
            item.setAttribute('data-hover-tagged', 'true');

            item.addEventListener('mouseenter', debounce(function() {
                currentHoverItem = item;
                addTagsToItem(item, getBrowserTags());
            }, 200));

            item.addEventListener('mouseleave', function() {
                if (currentHoverItem === item) {
                    currentHoverItem = null;
                }
            });
        });
    }

    addHoverListeners();

    const observer = new MutationObserver((mutationsList) => {
        for (let mutation of mutationsList) {
            if (mutation.type === 'childList') {
                addHoverListeners();
            }
        }
    });

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

     window.addEventListener('keydown', throttle(function(e) {
        const key = e.code.replace('Key','').toLowerCase();
        const tagsDict = getTagsDict();

        if (tagsDict[key] && currentHoverItem) {
            addTagsToItem(currentHoverItem, tagsDict[key]);
        }

        if (e.altKey && tagsDict[key]) {
            document.querySelectorAll('img, video').forEach(item => {
                addTagsToItem(item, tagsDict[key]);
            });
        }
    }, 200));

})();