Cómo copiar texto al portapapeles con Javascript fácilmente

Cómo copiar texto al portapapeles con Javascript fácilmente

El hecho de copiar texto al portapapeles automaticamente puede ser extremadamente peligroso, por ello la mayoría de exploradores hacen esta tarea dificil de lograr. Nadie, pero absolutamente nadie quiere terminar con direcciones web raras que pueden llegar a asustar en el portapapeles además de perder sin querer información que estaba en el portapapeles.

Cualquiera de las posibles soluciones que realmente funcionan y que puedes encontrar en Internet, deben ser si o si ejecutadas mediante la acción de un usuario (es decir un click). De ninguna manera podrás copiar automaticamente cosas al portapapeles sin la interacción del usuario. Basicamente, eso es todo lo que necesitas saber acerca del portapapeles en Javascript y Flash.

En este post, te ofreceremos diferentes maneras de lograr esta tarea fácilmente usando solo Javascript, en caso de que no se pueda con Javascript, el segundo método provee un fallback que usa Flash.

Javascript

Hay 2 maneras en las que puedes copiar texto al portapapeles:

1. execCommand

La primera implementación usa la función execCommand, disponible en el documento. Esta función está soportada por los siguientes navegadores:

  • IE10.
  • Google Chrome >=43.
  • Mozilla Firefox >=41.
  • Opera >=29.

El truco que utilizaremos para esto es sencillo, normalmente este método solo te permite copiar lo seleccionado en el documento. Lo que significa que debemos seleccionar el texto de un textarea que no sea visible para el usuario.

Importante

El código no funcionara si la acción no es ejecutada por el usuario (es decir un click por ejemplo). La inyección del script por la consola no funcionará. Note que el textarea debe ser visible pero escondido (el uso de display:none; hará que el código falle).

function setClipboardText(text){
    var id = "el-id-del-textarea";
    var existsTextarea = document.getElementById(id);

    if(!existsTextarea){
        console.log("Creando textarea");
        var textarea = document.createElement("textarea");
        textarea.id = id;
        // Coloca el textarea en el borde superior izquierdo
        textarea.style.position = 'fixed';
        textarea.style.top = 0;
        textarea.style.left = 0;

        // Asegurate que las dimensiones del textarea son minimas, normalmente 1px 
        // 1em no funciona porque esto generate valores negativos en algunos exploradores
        textarea.style.width = '1px';
        textarea.style.height = '1px';

        // No se necesita el padding
        textarea.style.padding = 0;

        // Limpiar bordes
        textarea.style.border = 'none';
        textarea.style.outline = 'none';
        textarea.style.boxShadow = 'none';

        // Evitar el flasheo de la caja blanca al renderizar
        textarea.style.background = 'transparent';
        document.querySelector("body").appendChild(textarea);
        console.log("The textarea now exists :)");
        existsTextarea = document.getElementById(id);
    }else{
        console.log("El textarea ya existe")
    }

    existsTextarea.value = text;
    existsTextarea.select();

    try {
        var status = document.execCommand('copy');
        if(!status){
            console.error("No se pudo copiar el texto");
        }else{
            console.log("El texto ahora está en el portapapeles");
        }
    } catch (err) {
        console.log('Uy, no se pudo copiar');
    }
}

Prueba el código en el siguiente fiddle:

2. Usando Clipboard.js

Todo el mundo ama las librerías, tu deberías amar las librerías (al menos las de código libre). Una librería hace todo más fácil para ti y además ha sido probada por un montón de personas lo que garantiza un funcionamiento adecuado en entornos de producción. Clipboard.js es una de esas hermosas librerías que con tan solo un par de lineas podrás lograr lo que con tanto sufrimiento, dolor y lagrimas intentas hacer desde hace mucho tiempo tu mismo. Clipboard.js es un intento moderno para copiar texto al portapapeles de tu sistema operativo sin usar Flash, no tiene dependencias y es realmente fácil de usar.

Para inicializar clipboard.js usa el siguiente código:

<button class="btn" data-clipboard-text="Este texto sera copiado">Copiar texto</button>

<script>
var clipboard = new Clipboard('.btn');

clipboard.on('success', function(e) {
    console.info('Accion:', e.action);
    console.info('Texto:', e.text);
    console.info('Trigger:', e.trigger);

    e.clearSelection();
});

clipboard.on('error', function(e) {
    console.error('Accion:', e.action);
    console.error('Trigger:', e.trigger);
});
</script>

El constructor de Clipboard.js espera un selector de DOM como primer argumento. En este ejemplo todos los elementos del documento que tengan la clase btn copiarán el texto dentro del atributo data-clipboard-text.

Fallback con flash

Si realmente necesitas implementar esta característica en tu sitio web y además dar soporte a exploradores viejos, no tendrás otra opción que recurrir al uso de flash.

Pero no te preocupes en hacer un desastre con el código que uses para ello, puedes hacerlo facil y organizado usando ZeroClipboard. Mira un ejemplo funcional visitando la página oficial del plugin aquí.

Sin embargo esta solución tampoco está libre de limitaciones. Debido al explorador y otras restricciones de seguridad de flash, la inserción de texto al portapapeles solo puede ser usado cuando el usuario clickea en la pelicula invisible de flash. Un evento click simulado no bastaría.

La implementación de ZeroClipboard es tan sencilla como el siguiente código:

<!DOCTYPE html>
<html>

<head>
    <!--
         Obten una copia de ZeroClibboard.js en el repositorio oficial
         Nota que el archivo .swf necesita estár localizado en el mismo directorio
         del archivo .js de ZeroClibboard
         El archivo flash será cargado automaticamente por el plugin
    -->
    <script src="ZeroClipboard.js"></script>
</head>

<body>
    <button id="copy-button" data-clipboard-text="Copiame !" title="Click para copiar !">Copiar al portapapeles</button>
    <script>
        var client = new ZeroClipboard(document.getElementById("copy-button"));
        // Encierra el codigo dentro del evento ready del archivo swf
        client.on("ready", function (readyEvent) {
            // alert( "ZeroClipboard SWF está listo!" );

            client.on("aftercopy", function (event) {
                // `this` === `client`
                // `event.target` === El elemento que fue clickeado
                event.target.style.display = "none";
                alert("Texto copiado al portapapeles: " + event.data["text/plain"]);
            });
        });
    </script>
</body>

</html>

Que te diviertas !

Esto podría ser de tu interes

Conviertete en un programador más sociable