Greasy Fork

Greasy Fork is available in English.

密码可见性切换

在密码输入框旁添加可见性切换按钮

// ==UserScript==
// @name         密码可见性切换
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  在密码输入框旁添加可见性切换按钮
// @author       dangwa
// @match        *://*/*
// @grant        none
// @run-at       document-idle
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    // 创建样式
    const style = document.createElement('style');
    style.textContent = `
        .tampermonkey-password-toggle {
            position: absolute;
            right: 8px;
            top: 50%;
            transform: translateY(-50%);
            cursor: pointer;
            color: #6B7280;
            z-index: 100;
            border: none;
            background: none;
        }
        .tampermonkey-password-toggle:hover {
            color: #4F46E5;
        }
        .password-input-wrapper {
            position: relative;
        }
    `;
    document.head.appendChild(style);

    // 为主密码输入框添加切换按钮
    function addToggleToPasswordInputs() {
        // 查找所有密码输入框
        const passwordInputs = document.querySelectorAll('input[type="password"]');

        passwordInputs.forEach(input => {
            // 检查是否已经添加了切换按钮
            if (input.parentElement.classList.contains('password-input-wrapper')) {
                return;
            }

            // 创建父容器
            const wrapper = document.createElement('div');
            wrapper.className = 'password-input-wrapper';

            // 将输入框放入容器
            input.parentNode.insertBefore(wrapper, input);
            wrapper.appendChild(input);

            // 创建切换按钮
            const toggleBtn = document.createElement('button');
            toggleBtn.type = 'button';
            toggleBtn.className = 'tampermonkey-password-toggle';
            toggleBtn.innerHTML = '<i class="fa fa-eye-slash"></i>';
            toggleBtn.setAttribute('aria-label', '切换密码可见性');

            // 添加 Font Awesome
            if (!document.querySelector('link[href*="font-awesome"]')) {
                const faLink = document.createElement('link');
                faLink.href = 'https://cdn.jsdelivr.net/npm/[email protected]/css/font-awesome.min.css';
                faLink.rel = 'stylesheet';
                document.head.appendChild(faLink);
            }

            // 添加按钮到容器
            wrapper.appendChild(toggleBtn);

            // 添加点击事件
            toggleBtn.addEventListener('click', function() {
                const type = input.getAttribute('type') === 'password' ? 'text' : 'password';
                input.setAttribute('type', type);

                // 切换图标
                const icon = toggleBtn.querySelector('i');
                if (type === 'text') {
                    icon.classList.remove('fa-eye-slash');
                    icon.classList.add('fa-eye');
                } else {
                    icon.classList.remove('fa-eye');
                    icon.classList.add('fa-eye-slash');
                }
            });
        });
    }

    // 初始添加切换按钮
    addToggleToPasswordInputs();

    // 监听DOM变化,处理动态加载的密码输入框
    const observer = new MutationObserver(function(mutations) {
        mutations.forEach(function(mutation) {
            if (mutation.addedNodes && mutation.addedNodes.length > 0) {
                // 检查新增节点中是否有密码输入框
                for (let i = 0; i < mutation.addedNodes.length; i++) {
                    const node = mutation.addedNodes[i];
                    if (node.nodeType === 1) { // 元素节点
                        if (node.tagName === 'INPUT' && node.type === 'password') {
                            addToggleToPasswordInputs();
                            break;
                        } else {
                            // 检查子节点
                            const passwordInputs = node.querySelectorAll('input[type="password"]');
                            if (passwordInputs.length > 0) {
                                addToggleToPasswordInputs();
                                break;
                            }
                        }
                    }
                }
            }
        });
    });

    // 开始观察DOM变化
    observer.observe(document.body, {
        childList: true,
        subtree: true
    });

    // 添加键盘快捷键支持(Ctrl+Shift+P 切换焦点密码框可见性)
    document.addEventListener('keydown', function(e) {
        if (e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 'p') {
            e.preventDefault();
            const activeElement = document.activeElement;
            if (activeElement && activeElement.tagName === 'INPUT' && activeElement.type === 'password') {
                // 找到对应的切换按钮并点击
                const wrapper = activeElement.parentElement;
                if (wrapper.classList.contains('password-input-wrapper')) {
                    const toggleBtn = wrapper.querySelector('.tampermonkey-password-toggle');
                    if (toggleBtn) {
                        toggleBtn.click();
                    }
                }
            }
        }
    });
})();