Advanced Password Revealer

Reveals passwords on mouse hover or focus, with improved performance, features, and safety.

// ==UserScript==
// @name           Advanced Password Revealer
// @namespace      http://userscripts.org/users/23652
// @description    Reveals passwords on mouse hover or focus, with improved performance, features, and safety.
// @include        http://*
// @include        https://*
// @include        file:///*
// @exclude        file:///*/perf.html*
// @copyright      JoeSimmons
// @version        1.2.0
// @license        GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html
// ==/UserScript==

(function() {
    const showOnlyOnClick = false; // Change to true to show passwords only on click
    const handlers = new Set();

    function togglePasswordVisibility(input, show) {
        const { selectionStart, selectionEnd, type } = input;

        input.type = show ? 'text' : 'password';
        input.setSelectionRange(selectionStart, selectionEnd);
    }

    function handleFocus(event) {
        const input = event.target;
        if (input.tagName === 'INPUT' && input.type === 'password') {
            togglePasswordVisibility(input, true);
        }
    }

    function handleBlur(event) {
        const input = event.target;
        if (input.tagName === 'INPUT' && input.type === 'text') {
            togglePasswordVisibility(input, false);
        }
    }

    function addHandlers() {
        const passwordFields = document.querySelectorAll('input[type="password"]');

        passwordFields.forEach(field => {
            if (!handlers.has(field)) {
                field.addEventListener('focus', handleFocus);
                field.addEventListener('blur', handleBlur);
                handlers.add(field);
            }
        });
    }

    function setupGlobalListeners() {
        if (!showOnlyOnClick) {
            window.addEventListener('mouseover', handleFocus);
            window.addEventListener('mouseout', handleBlur);
        }
    }

    function observeMutations() {
        const observer = new MutationObserver(addHandlers);
        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
    }

    // Initialize the script
    function init() {
        addHandlers();
        setupGlobalListeners();
        observeMutations(); // Watch for changes in the DOM
    }

    // Start the script
    init();
})();