Drawaria Translator Menu Full

The ultimate, conflict-free translation tool for Drawaria.online, with multi-language support and direct chat sending. Now with integrated search in language selector!

// ==UserScript==
// @name         Drawaria Translator Menu Full
// @version      2.0
// @description  The ultimate, conflict-free translation tool for Drawaria.online, with multi-language support and direct chat sending. Now with integrated search in language selector!
// @author       YouTubeDrawaria
// @match        https://drawaria.online/*
// @license      MIT
// @icon         https://www.google.com/s2/favicons?sz=64&domain=drawaria.online
// @grant        none
// @run-at       document-idle
// @namespace    https://greasyfork.org/users/YOUR_USER_ID_HERE_ULTIMATE // IMPORTANT: Replace with your actual Greasy Fork User ID if you publish this
// ==/UserScript==

(function() {
    'use strict';
    console.log("Drawaria Ultimate Translator script starting...");

    // Function to create elements in a standard way
    function dtrCreateElement(tag, attributes = {}, children = []) {
        const element = document.createElement(tag);
        for (const [key, value] of Object.entries(attributes)) {
            if (key === 'style') {
                element.style.cssText = value;
            } else {
                element.setAttribute(key, value);
            }
        }
        children.forEach(child => {
            if (typeof child === 'string') {
                element.appendChild(document.createTextNode(child));
            } else if (child instanceof Node) {
                element.appendChild(child);
            }
        });
        return element;
    }

    // Function to make an element draggable
    function dtrMakeDraggable(element) {
        let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
        const header = element.querySelector('.dtr-header'); // Unique class for header
        if (!header) {
            console.warn("Drawaria Ultimate Translator: Draggable element has no .dtr-header to attach drag events.");
            return;
        }
        header.onmousedown = dragMouseDown;

        function dragMouseDown(e) {
            e = e || window.event;
            e.preventDefault();
            pos3 = e.clientX;
            pos4 = e.clientY;
            document.onmouseup = closeDragElement;
            document.onmousemove = elementDrag;
        }

        function elementDrag(e) {
            e = e || window.event;
            e.preventDefault();
            pos1 = pos3 - e.clientX;
            pos2 = pos4 - e.clientY;
            pos3 = e.clientX;
            pos4 = e.clientY;
            element.style.top = (element.offsetTop - pos2) + "px";
            element.style.left = (element.offsetLeft - pos1) + "px";
        }

        function closeDragElement() {
            document.onmouseup = null;
            document.onmousemove = null;
        }
    }

    // Function to translate text using Google Translate API
    function dtrTranslateText(textToTranslate, toLang, callback) {
        const url =
            "https://translate.googleapis.com/translate_a/single?client=gtx&sl=auto&tl=" +
            toLang +
            "&dt=t&q=" +
            encodeURI(textToTranslate);
        const req = new XMLHttpRequest();
        req.onload = () => {
            try {
                const data = JSON.parse(req.response);
                if (data && data[0] && data[0][0] && data[0][0][0]) {
                    callback(data[0][0][0]);
                } else {
                    console.warn("Drawaria Ultimate Translator: Translation failed or returned unexpected data:", data);
                    callback("Translation failed. Check console for details.");
                }
            } catch (error) {
                console.error("Drawaria Ultimate Translator: Error parsing JSON response for translation:", error);
                callback("Error during translation. Check console for details.");
            }
        };
        req.onerror = (e) => {
            console.error("Drawaria Ultimate Translator: Network error during translation request:", e);
            callback("Network error during translation. Check console for details.");
        };
        req.open("GET", url);
        req.send();
    }

    // Function to initialize the ultimate translator
    function dtrInitUltimateTranslator() {
        // Create the translator container
        const dtrTranslatorContainer = dtrCreateElement('div', {
            id: 'dtrTranslatorContainer', // Unique ID
            style: `
                position: fixed !important;
                top: 100px !important;
                left: 420px !important;
                background-color: #f8f9fa;
                border: 1px solid #343a40;
                border-radius: .5rem;
                padding: 10px;
                box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
                z-index: 99999 !important;
                font-family: 'Open Sans', sans-serif;
                color: #343a40;
                display: none; /* Starts hidden */
                flex-direction: column;
                gap: 10px;
                width: 320px;
                max-width: 90vw;
                resize: both;
                overflow: auto;
            `
        });

        // Create the header
        const dtrHeader = dtrCreateElement('div', {
            class: 'dtr-header', // Unique class
            style: `
                font-weight: bold;
                text-align: center;
                padding-bottom: 8px;
                margin-bottom: 5px;
                border-bottom: 1px solid #ced4da;
                cursor: grab;
                font-size: 1.1em;
                color: #343a40;
            `
        }, ["Drawaria Translator Full"]);

        // Create the input text area for the text to translate
        const dtrInputText = dtrCreateElement('textarea', {
            placeholder: "Enter text...",
            rows: 3,
            id: "dtrInputText", // Unique ID
            style: `
                width: calc(100% - 16px);
                padding: 8px;
                border: 1px solid #dee2e6;
                border-radius: .25rem;
                resize: vertical;
                min-height: 60px;
                background-color: #fff;
                color: #343a40;
                font-size: 0.95em;
                line-height: 1.4;
            `
        });

        // Prevent default behavior on input to allow text entry
        dtrInputText.addEventListener('keydown', function(e) {
            e.stopPropagation();
        });

        dtrInputText.addEventListener('focus', function(e) {
            this.style.outline = '2px solid blue';
        });

        dtrInputText.addEventListener('blur', function(e) {
            this.style.outline = 'none';
        });

        // Language data
        const languages = {
            "en": "English",
            "es": "Spanish",
            "fr": "French",
            "de": "German",
            "it": "Italian",
            "pt": "Portuguese",
            "ru": "Russian",
            "zh-CN": "Chinese (Simplified)",
            "ja": "Japanese",
            "ko": "Korean",
            "ar": "Arabic",
            "hi": "Hindi",
            "bn": "Bengali",
            "tr": "Turkish",
            "pl": "Polish",
            "nl": "Dutch",
            "sv": "Swedish",
            "da": "Danish",
            "no": "Norwegian",
            "fi": "Finnish",
            "el": "Greek",
            "he": "Hebrew",
            "id": "Indonesian",
            "ms": "Malay",
            "th": "Thai",
            "vi": "Vietnamese",
            "uk": "Ukrainian",
            "cs": "Czech",
            "hu": "Hungarian",
            "ro": "Romanian",
            "af": "Afrikaans",
            "sq": "Albanian",
            "am": "Amharic",
            "hy": "Armenian",
            "az": "Azerbaijani",
            "eu": "Basque",
            "be": "Belarusian",
            "bs": "Bosnian",
            "bg": "Bulgarian",
            "ca": "Catalan",
            "ceb": "Cebuano",
            "ny": "Chichewa",
            "co": "Corsican",
            "hr": "Croatian",
            "cz": "Czech (Legacy)",
            "eo": "Esperanto",
            "et": "Estonian",
            "tl": "Filipino",
            "fy": "Frisian",
            "gl": "Galician",
            "ka": "Georgian",
            "gu": "Gujarati",
            "ht": "Haitian Creole",
            "ha": "Hausa",
            "haw": "Hawaiian",
            "iw": "Hebrew (Legacy)",
            "hmn": "Hmong",
            "is": "Icelandic",
            "ig": "Igbo",
            "ga": "Irish",
            "jw": "Javanese",
            "kn": "Kannada",
            "kk": "Kazakh",
            "km": "Khmer",
            "ku": "Kurdish (Kurmanji)",
            "ky": "Kyrgyz",
            "lo": "Lao",
            "la": "Latin",
            "lv": "Latvian",
            "lt": "Lithuanian",
            "lb": "Luxembourgish",
            "mk": "Macedonian",
            "mg": "Malagasy",
            "ml": "Malayalam",
            "mt": "Maltese",
            "mi": "Maori",
            "mr": "Marathi",
            "mn": "Mongolian",
            "my": "Myanmar (Burmese)",
            "ne": "Nepali",
            "ps": "Pashto",
            "fa": "Persian",
            "pa": "Punjabi",
            "sm": "Samoan",
            "gd": "Scots Gaelic",
            "sr": "Serbian",
            "st": "Sesotho",
            "sn": "Shona",
            "sd": "Sindhi",
            "si": "Sinhala",
            "sk": "Slovak",
            "sl": "Slovenian",
            "so": "Somali",
            "su": "Sundanese",
            "sw": "Swahili",
            "tg": "Tajik",
            "ta": "Tamil",
            "te": "Telugu",
            "uz": "Uzbek",
            "xh": "Xhosa",
            "yi": "Yiddish",
            "yo": "Yoruba",
            "zu": "Zulu"
        };
        const defaultLanguageCode = "es";
        let currentSelectedLanguageCode = defaultLanguageCode;

        // --- NEW: Custom Language Dropdown Structure ---
        const dtrCustomLanguageDropdown = dtrCreateElement('div', {
            id: 'dtrCustomLanguageDropdown',
            style: `
                position: relative;
                width: 100%;
                font-size: 0.95em;
                margin-bottom: 10px;
            `
        });

        // The visible display for the selected language
        const dtrSelectedLanguageDisplay = dtrCreateElement('div', {
            id: 'dtrSelectedLanguageDisplay',
            style: `
                width: calc(100% - 18px); /* Adjust for padding and arrow */
                padding: 8px 10px;
                border: 1px solid #dee2e6;
                border-radius: .25rem;
                background-color: #fff;
                color: #343a40;
                cursor: pointer;
                display: flex;
                justify-content: space-between;
                align-items: center;
            `
        }, [
            dtrCreateElement('span', {}, [languages[defaultLanguageCode]]), // Initial selected language text
            dtrCreateElement('span', {style: 'font-size: 0.8em; margin-left: 5px;'}, ['▼']) // Dropdown arrow
        ]);

        // The dropdown panel itself (initially hidden)
        const dtrDropdownPanel = dtrCreateElement('div', {
            id: 'dtrDropdownPanel',
            style: `
                position: absolute;
                top: 100%; /* Position below the display */
                left: 0;
                width: 100%;
                background-color: #fff;
                border: 1px solid #ced4da;
                border-radius: .25rem;
                box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
                z-index: 100000; /* Above other elements */
                max-height: 250px; /* Max height for scroll */
                overflow-y: auto;
                display: none; /* Hidden by default */
                flex-direction: column;
                padding: 5px;
            `
        });

        // Search input within the dropdown panel
        const dtrLanguageSearchInput = dtrCreateElement('input', {
            type: 'text',
            placeholder: 'Search languages...',
            id: 'dtrLanguageSearchInput',
            style: `
                width: calc(100% - 16px);
                padding: 8px;
                border: 1px solid #dee2e6;
                border-radius: .25rem;
                margin-bottom: 5px;
                background-color: #f0f0f0; /* Slightly different background */
                color: #343a40;
                font-size: 0.9em;
            `
        });
        dtrLanguageSearchInput.addEventListener('keydown', function(e) {
            e.stopPropagation(); // Prevent script's hotkeys from interfering
        });

        // List container for languages
        const dtrLanguageList = dtrCreateElement('div', {
            id: 'dtrLanguageList',
            style: `
                display: flex;
                flex-direction: column;
                gap: 2px;
            `
        });

        // Populate language list and store references
        const languageItems = {}; // Store references to div elements
        for (const langCode in languages) {
            const langName = languages[langCode];
            const langItem = dtrCreateElement('div', {
                class: 'dtr-lang-item',
                'data-lang-code': langCode,
                style: `
                    padding: 8px 10px;
                    cursor: pointer;
                    white-space: nowrap;
                    overflow: hidden;
                    text-overflow: ellipsis;
                    border-radius: .20rem;
                `
            }, [langName]);

            langItem.addEventListener('mouseenter', () => {
                langItem.style.backgroundColor = '#e9ecef';
            });
            langItem.addEventListener('mouseleave', () => {
                langItem.style.backgroundColor = '';
            });

            langItem.addEventListener('click', (e) => {
                e.stopPropagation(); // Stop propagation to prevent document click from closing immediately
                currentSelectedLanguageCode = langCode;
                dtrSelectedLanguageDisplay.querySelector('span:first-child').textContent = langName;
                dtrDropdownPanel.style.display = 'none'; // Close dropdown
                console.log(`Drawaria Ultimate Translator: Language set to ${langName} (${langCode})`);
            });
            dtrLanguageList.appendChild(langItem);
            languageItems[langCode] = langItem;
        }

        // Search functionality
        dtrLanguageSearchInput.addEventListener('input', function() {
            const searchTerm = this.value.toLowerCase();
            for (const langCode in languages) {
                const langName = languages[langCode].toLowerCase();
                if (langName.startsWith(searchTerm)) {
                    languageItems[langCode].style.display = 'block';
                } else {
                    languageItems[langCode].style.display = 'none';
                }
            }
        });

        // Toggle dropdown visibility
        dtrSelectedLanguageDisplay.addEventListener('click', (e) => {
            e.stopPropagation(); // Prevent this click from closing the dropdown via document click
            dtrDropdownPanel.style.display = dtrDropdownPanel.style.display === 'none' ? 'flex' : 'none';
            if (dtrDropdownPanel.style.display === 'flex') {
                dtrLanguageSearchInput.focus(); // Focus search when opened
                dtrLanguageSearchInput.value = ''; // Clear search on open
                dtrLanguageSearchInput.dispatchEvent(new Event('input')); // Trigger filter
            }
        });

        // Close dropdown when clicking outside
        document.addEventListener('click', (e) => {
            if (!dtrCustomLanguageDropdown.contains(e.target) && dtrDropdownPanel.style.display === 'flex') {
                dtrDropdownPanel.style.display = 'none';
            }
        });

        // Append search input and language list to the dropdown panel
        dtrDropdownPanel.appendChild(dtrLanguageSearchInput);
        dtrDropdownPanel.appendChild(dtrLanguageList);

        // Append components to the custom dropdown container
        dtrCustomLanguageDropdown.appendChild(dtrSelectedLanguageDisplay);
        dtrCustomLanguageDropdown.appendChild(dtrDropdownPanel);
        // --- END NEW: Custom Language Dropdown Structure ---


        // Create the translate button
        const dtrTranslateButton = dtrCreateElement('button', {
            id: "dtrTranslateButton", // Unique ID
            style: `
                padding: 10px 15px;
                border: none;
                border-radius: .25rem;
                color: white;
                cursor: pointer;
                transition: background-color 0.2s ease;
                font-size: 1em;
                font-weight: 600;
                background-color: #17a2b8;
            `
        }, ["Translate"]);

        // Create the output text area
        const dtrOutputText = dtrCreateElement('textarea', {
            placeholder: "Translation will appear here...",
            rows: 3,
            readonly: true,
            id: "dtrOutputText", // Unique ID
            style: `
                width: calc(100% - 16px);
                padding: 8px;
                border: 1px solid #dee2e6;
                border-radius: .25rem;
                resize: vertical;
                min-height: 60px;
                background-color: #fff;
                color: #343a40;
                font-size: 0.95em;
                line-height: 1.4;
            `
        });

        // Create the send translation button
        const dtrSendButton = dtrCreateElement('button', {
            id: "dtrSendButton", // Unique ID
            style: `
                padding: 10px 15px;
                border: none;
                border-radius: .25rem;
                color: white;
                cursor: pointer;
                transition: background-color 0.2s ease;
                font-size: 1em;
                font-weight: 600;
                background-color: #007bff;
            `
        }, ["Send Translation"]);

        // Add elements to the container
        dtrTranslatorContainer.appendChild(dtrHeader);
        dtrTranslatorContainer.appendChild(dtrInputText);
        // --- NEW: Add the custom language dropdown here ---
        dtrTranslatorContainer.appendChild(dtrCustomLanguageDropdown);
        // --- END NEW ---
        dtrTranslatorContainer.appendChild(dtrTranslateButton);
        dtrTranslatorContainer.appendChild(dtrOutputText);
        dtrTranslatorContainer.appendChild(dtrSendButton);

        // Add the container to the document body
        document.body.appendChild(dtrTranslatorContainer);
        console.log("Drawaria Ultimate Translator: UI container appended to body.");

        // Make the translator UI draggable
        dtrMakeDraggable(dtrTranslatorContainer);
        console.log("Drawaria Ultimate Translator: UI made draggable.");

        // Add event listeners for the buttons
        dtrTranslateButton.addEventListener("click", () => {
            const textToTranslate = dtrInputText.value.trim();
            // --- Use the currentSelectedLanguageCode from the custom dropdown ---
            const toLang = currentSelectedLanguageCode;
            // --- END NEW ---
            if (textToTranslate) {
                console.log(`Drawaria Ultimate Translator: Translating text to ${languages[toLang]} (${toLang}):`, textToTranslate);
                dtrTranslateText(textToTranslate, toLang, (translatedText) => {
                    dtrOutputText.value = translatedText;
                    console.log("Drawaria Ultimate Translator: Translation complete:", translatedText);
                });
            } else {
                dtrOutputText.value = "Please enter text to translate.";
                console.log("Drawaria Ultimate Translator: No text to translate.");
            }
        });

        // Event listener for the "Send Translation" button
        dtrSendButton.addEventListener("click", () => {
            const translatedText = dtrOutputText.value;
            if (translatedText) {
                const chatInput = document.getElementById('chatbox_textinput');

                if (chatInput) {
                    chatInput.value = translatedText;
                    console.log("Drawaria Ultimate Translator: Text placed in chat input:", translatedText);

                    // Create and dispatch an 'Enter' keydown event to trigger sending
                    const event = new KeyboardEvent('keydown', {
                        key: 'Enter',
                        code: 'Enter',
                        keyCode: 13,
                        which: 13,
                        bubbles: true
                    });
                    chatInput.dispatchEvent(event);
                    console.log("Drawaria Ultimate Translator: 'Enter' keydown event dispatched.");

                    const originalText = dtrSendButton.textContent;
                    dtrSendButton.textContent = "Sent!";
                    setTimeout(() => {
                        dtrSendButton.textContent = originalText;
                        dtrInputText.value = "";
                        dtrOutputText.value = "";
                    }, 1500);

                } else {
                    console.warn("Drawaria Ultimate Translator: Could not find chat input element (#chatbox_textinput).");
                    const originalText = dtrSendButton.textContent;
                    dtrSendButton.textContent = "Chat not found!";
                    setTimeout(() => {
                        dtrSendButton.textContent = originalText;
                    }, 1500);
                }
            } else {
                console.log("Drawaria Ultimate Translator: Nothing to send.");
            }
        });

        // --- Toggle Button Functionality for T+ ---
        const roomcontrols = document.getElementById('roomcontrols');
        if (roomcontrols) {
            const dtrToggleButton = dtrCreateElement('button', {
                id: 'dtrTranslateMenuUltimateToggle', // Unique ID for this button
                class: 'btn btn-outline-secondary btn-sm',
                style: 'padding: 1px 5px; margin-left: 5px;', // Added margin for spacing
                title: 'Toggle Drawaria Ultimate Translator'
            }, ['T+']);

            // Find the roomcontrols-menu button to insert next to it, or append to roomcontrols
            const menuButton = document.getElementById('roomcontrols-menu'); // The ellipsis menu button
            if (menuButton) {
                // Insert the new button after the existing menu button
                menuButton.parentNode.insertBefore(dtrToggleButton, menuButton.nextSibling);
            } else {
                // Fallback if menuButton is not found, append to roomcontrols
                roomcontrols.appendChild(dtrToggleButton);
            }

            dtrToggleButton.addEventListener('click', () => {
                if (dtrTranslatorContainer.style.display === 'none') {
                    dtrTranslatorContainer.style.display = 'flex'; // Use 'flex' as it's a flex container
                } else {
                    dtrTranslatorContainer.style.display = 'none';
                }
            });
            console.log("Drawaria Ultimate Translator: Toggle button 'T+' added to roomcontrols.");
        } else {
            console.warn("Drawaria Ultimate Translator: Could not find #roomcontrols element to add toggle button.");
        }
    }

    // Wait for the DOM to be fully loaded before initializing the translator
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', dtrInitUltimateTranslator);
    } else {
        dtrInitUltimateTranslator();
    }
})();