您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Desbloquea los textos artísticos, previene popups, copia al portapapeles sin notificaciones, sin afectar el scroll, y elimina "@Facemojikeyboard" del texto.
// ==UserScript== // @name Desbloquear Facemojikeyboard // @namespace http://tampermonkey.net/ // @version 1.3.1 // @description Desbloquea los textos artísticos, previene popups, copia al portapapeles sin notificaciones, sin afectar el scroll, y elimina "@Facemojikeyboard" del texto. // @author YouTubeDrawaria // @match https://www.facemojikeyboard.com/text-art-collection // @grant none // @license MIT // @icon https://cdn.facemojikeyboard.com/website/favicon.png // ==/UserScript== (function() { 'use strict'; // Cadena a eliminar de los textos const STRING_TO_REMOVE = '@Facemojikeyboard'; /** * Copia el texto dado al portapapeles. Sin notificaciones. * @param {string} text El texto a copiar. */ function copyTextToClipboard(text) { // Eliminar la cadena no deseada antes de copiar const cleanedText = text.replace(new RegExp(STRING_TO_REMOVE, 'g'), '').trim(); if (navigator.clipboard) { navigator.clipboard.writeText(cleanedText).catch(err => { console.error('No se pudo copiar el texto usando navigator.clipboard: ', err); fallbackCopyTextToClipboard(cleanedText); }); } else { fallbackCopyTextToClipboard(cleanedText); } } /** * Fallback para copiar texto al portapapeles usando un textarea temporal. * @param {string} text El texto a copiar. */ function fallbackCopyTextToClipboard(text) { const textarea = document.createElement('textarea'); textarea.value = text; textarea.style.position = 'fixed'; textarea.style.left = '-9999px'; textarea.style.top = '-9999px'; document.body.appendChild(textarea); textarea.focus(); textarea.select(); try { document.execCommand('copy'); } catch (err) { console.error('No se pudo copiar el texto con execCommand: ', err); } document.body.removeChild(textarea); } /** * Aplica las modificaciones a los elementos de arte de texto (eliminar candado, hacer seleccionable, añadir listener de copia). */ function applyModifications() { const textArtWrappers = document.querySelectorAll('.emojiwrapper-list-tool__wrapper'); textArtWrappers.forEach(item => { // 1. Elimina el icono de candado si existe const lockIcon = item.querySelector('img.lock'); if (lockIcon) { lockIcon.remove(); } // 2. Asegura que el texto sea seleccionable item.style.userSelect = 'text'; item.style.webkitUserSelect = 'text'; item.style.mozUserSelect = 'text'; item.style.msUserSelect = 'text'; // 3. Añade un listener de clic para copiar texto y prevenir popups if (!item.dataset.listenerAdded) { item.addEventListener('click', function(event) { event.preventDefault(); event.stopPropagation(); const textSpan = this.querySelector('span'); if (textSpan && textSpan.textContent) { copyTextToClipboard(textSpan.textContent.trim()); } }, { capture: true }); item.dataset.listenerAdded = 'true'; } }); } /** * Oculta elementos específicos de pop-up y asegura que el scroll no esté bloqueado. * Se usa `!important` para asegurar la anulación de estilos existentes. */ function hideSpecificPopupsAndRestoreScroll() { const popper = document.querySelector('.el-popper.tooltip-popper-class'); if (popper) { popper.style.setProperty('display', 'none', 'important'); popper.setAttribute('aria-hidden', 'true'); } const modal = document.querySelector('.dialog-container.default-modal'); if (modal) { modal.style.setProperty('display', 'none', 'important'); } document.body.style.setProperty('overflow', 'auto', 'important'); document.documentElement.style.setProperty('overflow', 'auto', 'important'); } // --- Lógica de Ejecución y Observación --- // 1. Añadir reglas CSS globales para ocultar los popups de forma persistente // y asegurar que el scroll siempre funcione. function addGlobalCSSRules() { const style = document.createElement('style'); style.type = 'text/css'; style.innerHTML = ` /* Ocultar los popups de información/descarga */ .el-popper.tooltip-popper-class, .dialog-container.default-modal { display: none !important; } /* Asegurar que el scroll siempre funcione */ body, html { overflow: auto !important; } `; document.head.appendChild(style); } addGlobalCSSRules(); // 2. Ejecutar las modificaciones iniciales y ocultar popups al cargar la página applyModifications(); hideSpecificPopupsAndRestoreScroll(); // 3. Observar cambios en el DOM para manejar contenido cargado dinámicamente y nuevos popups const observer = new MutationObserver((mutationsList, observer) => { let needsModifications = false; let needsPopupHiding = false; for (const mutation of mutationsList) { if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { mutation.addedNodes.forEach(node => { if (node.nodeType === 1) { // Solo si es un elemento HTML if (node.classList.contains('emojiwrapper-list-tool') || node.querySelector('.emojiwrapper-list-tool__wrapper')) { needsModifications = true; } if (node.classList.contains('el-popper') || node.classList.contains('dialog-container')) { needsPopupHiding = true; } } }); } else if (mutation.type === 'attributes' && (mutation.target === document.body || mutation.target === document.documentElement) && mutation.attributeName === 'style') { if (mutation.target.style.overflow === 'hidden') { needsPopupHiding = true; } } } if (needsModifications) { applyModifications(); } if (needsPopupHiding) { hideSpecificPopupsAndRestoreScroll(); } }); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style'] }); observer.observe(document.documentElement, { attributes: true, attributeFilter: ['style'] }); })();