Mobile Keyboard Spawner

Adds a draggable button that acts as an input to force the mobile keyboard open.Best for opening cheats on mobile.

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

You will need to install an extension such as Tampermonkey to install this script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

// ==UserScript==
// @name         Mobile Keyboard Spawner
// @namespace    https://greasyfork.org/users/Eternosen
// @version      1.2.1
// @description  Adds a draggable button that acts as an input to force the mobile keyboard open.Best for opening cheats on mobile.
// @author       Eternosen
// @match        *://*/*
// @grant        none
// @license      MIT
// @run-at       document-end
// ==/UserScript==

(function() {
    'use strict';

    // PC PROTECTION: Don't show the button on desktop/laptops
    if (!('ontouchstart' in window) && !navigator.maxTouchPoints) return;

    function createKeyboardTrigger() {
        if (document.getElementById('mobile-kb-container')) return;

        const container = document.createElement('div');
        container.id = 'mobile-kb-container';
        (document.body || document.documentElement).appendChild(container);

        const shadow = container.attachShadow({mode: 'open'});

        const input = document.createElement('input');
        input.type = 'text';
        input.value = '⌨️';
        input.setAttribute('autocomplete', 'off');
        input.setAttribute('spellcheck', 'false');
        input.setAttribute('autocorrect', 'off');
        input.setAttribute('autocapitalize', 'none');
        
        input.style = `
            position: fixed; top: 120px; right: 20px;
            width: 50px; height: 50px;
            background: #222; 
            border: 2px solid #444; border-radius: 50%;
            text-align: center; font-size: 24px;
            z-index: 2147483647; cursor: pointer;
            box-shadow: 0 4px 10px rgba(0,0,0,0.5);
            outline: none; touch-action: none;
            caret-color: transparent; color: transparent;
            text-shadow: 0 0 0 white;
            user-select: none; -webkit-user-select: none;
        `;
        shadow.appendChild(input);

        let isDragging = false, startX, startY, xOffset = 0, yOffset = 0;

        input.addEventListener('touchstart', (e) => {
            // Stop page from reacting to the touch start
            e.stopPropagation();
            const touch = e.touches[0];
            startX = touch.clientX - xOffset;
            startY = touch.clientY - yOffset;
            isDragging = false;
        }, {passive: false});

        input.addEventListener('touchmove', (e) => {
            isDragging = true;
            // THE FIX: Stop the page from scrolling while dragging the button
            if (e.cancelable) e.preventDefault();
            e.stopPropagation();
            
            const touch = e.touches[0];
            xOffset = touch.clientX - startX;
            yOffset = touch.clientY - startY;
            input.style.transform = `translate(${xOffset}px, ${yOffset}px)`;
        }, {passive: false});

        input.addEventListener('touchend', (e) => {
            e.stopPropagation();
            if (isDragging) {
                input.blur();
            } else {
                input.value = '';
                input.focus();
            }
        });

        input.addEventListener('blur', () => { input.value = '⌨️'; });

        // BLOCK messy mobile events from leaking to the site
        ['keydown', 'keyup', 'keypress'].forEach(evtType => {
            input.addEventListener(evtType, (e) => { e.stopPropagation(); });
        });

        input.addEventListener('input', (e) => {
            const char = e.data;
            if (!char) return;
            
            let codeVal = 'Unidentified';
            if (/^[a-zA-Z]$/.test(char)) {
                codeVal = `Key${char.toUpperCase()}`;
            } else if (/^[0-9]$/.test(char)) {
                codeVal = `Digit${char}`;
            }

            const keyCode = char.toUpperCase().charCodeAt(0);
            const isUpper = char === char.toUpperCase() && char !== char.toLowerCase();
            
            const eventParams = {
                key: char,
                code: codeVal,
                keyCode: keyCode,
                which: keyCode,
                shiftKey: isUpper,
                ctrlKey: false, altKey: false, metaKey: false,
                bubbles: true, cancelable: true, composed: true,
                view: window
            };

            const down = new KeyboardEvent('keydown', eventParams);
            const press = new KeyboardEvent('keypress', eventParams);
            const up = new KeyboardEvent('keyup', eventParams);

            const target = document.activeElement && document.activeElement !== input 
                           ? document.activeElement 
                           : document.body;

            target.dispatchEvent(down);
            target.dispatchEvent(press);
            target.dispatchEvent(up);

            window.dispatchEvent(down);
            window.dispatchEvent(press);
            window.dispatchEvent(up);
            
            input.value = ''; 
        });
    }

    createKeyboardTrigger();
    
    const observer = new MutationObserver(() => {
        if (!document.getElementById('mobile-kb-container')) createKeyboardTrigger();
    });
    observer.observe(document.documentElement, { childList: true, subtree: true });
})();