Cómo copiar un texto en el portapapeles mediante Javascript usando el API de Clipboard, de manera sencilla y rápida.
En este artículo vamos a explicar y mostrar ejemplos sobre cómo se copia un valor en el portapapeles con Javascript en el navegador. Actualmente es una tarea sencilla, gracias al API que nos permite interaccionar directamente con el clipboard desde Javascript. Sin embargo, en su día fue una tarea compleja, que requería bastanta código y diferenciar entre distintos navegadores.
En este artículo vamos a explicar cómo debes hacer el copiado en el portapapeles en la actualidad y cómo se hacía esta tarea en el pasado.
Cómo copiar texto en el portapapeles con Clipboard API
Para copiar texto al portapapeles en una página web usando JavaScript, puedes utilizar la API de Clipboard que proporciona una forma moderna y sencilla de interactuar con el portapapeles.
Básicamente tenemos que invocar un método del objeto clipboard
que tenemos dentro del objeto navigator
, indicando el texto que se desea almacenar en el portapapeles.
navigator.clipboard.writeText(texto)
Este método te devuelve una promesa mediante la que podemos realizar acciones cuando el texo ha sido copiado y ya se encuentra disponible en el portapapeles.
Ejemplo Básico de copiado de un texto
Aquí pudes ver un código HTML de una página que realiza la acción de copiado. El texto específico que queremos copiar lo vamos a pasar por parámetro a una función que se encargará de enviarlo al portapapeles:
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Copiar al Portapapeles</title>
</head>
<body>
<!-- Botón que el usuario puede presionar para copiar texto -->
<button id="copybutton">Copiar Texto</button>
<script>
function clipboardCopy(texto) {
navigator.clipboard.writeText(texto).then(function() {
console.log('Texto copiado al portapapeles');
}).catch(function(err) {
console.error('Error al copiar texto: ', err);
});
}
document.addEventListener("DOMContentLoaded", function() {
document.getElementById("copybutton").addEventListener("click", function() {
clipboardCopy('Esto es el texto que voy a copiar')
});
});
</script>
</body>
</html>
En el código anterior vemos un botón HTML con un id
.
Luego mediante Javascript realizamos un evento DOMContentLoaded
que nos sirve para ejecutar acciones cuando el navegador ya tiene el DOM listo. Luego se define un evento click
sobre el botón que llama a la función clipboardCopy
con un string como argumento.
La función JavaScript que copia al portapapeles toma un texto como parámetro y utiliza navigator.clipboard.writeText()
, enviando ese texto recibido. Como habíamos dicho, navigator.clipboard.writeText()
nos entrega una promesa que intentará copiar el texto proporcionado al portapapeles del usuario.
- Si la operación es exitosa, imprime un mensaje en la consola.
- Si falla, captura el error y también lo imprime en la consola.
Mejora del script para copiar el texto que hay en un textarea
Generalmente usaremos algún elemento de la página como origen de los datos que deseamos copiar, por ejemplo un campo de formulario o lo que hay escrito en un elemento de la página con innerText.
Ahora vamos a ver cómo mejorar el código anterior, haciendo que el copiado venga de un textarea.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Copiar al Portapapeles</title>
</head>
<body>
<p>
<textarea id="textoACopiar" cols="50" rows="3">Esto es el texto que aparece en el textarea, que voy a copiar. Puedes editarlo!!</textarea>
</p>
<p>
<button id="copybutton">Copiar Texto</button>
</p>
<!-- Elemento para mostrar mensajes al usuario -->
<p id="feedbackElement"></p>
<script>
function clipboardCopy() {
// Obtiene el texto del textarea
var texto = document.getElementById("textoACopiar").value;
navigator.clipboard.writeText(texto).then(function () {
let feedbackElement = document.getElementById("feedbackElement")
// Muestra un mensaje de éxito al usuario en la página
feedbackElement.textContent = 'Texto copiado al portapapeles';
}).catch(function (err) {
// Muestra un mensaje de error al usuario en la página
feedbackElement.textContent = 'Error al copiar texto: ' + err;
});
}
document.addEventListener("DOMContentLoaded", function () {
document.getElementById("copybutton").addEventListener("click", clipboardCopy);
});
</script>
</body>
</html>
Este segundo ejemplo es muy similar al anterior. Solo tiene unos pequeños cambios:
- El copiado se realiza desde un campo textarea
- El mensaje de feedback al usuario, que indica que el texto se ha copiado no se envía a la consola, sino que se muestra en la propia página, debajo del textarea, para que lo vea el usuario
Realmente la funcionalidad de copiado en el portapapeques, que es lo que nos interesaba en este artículo, es similar a lo que habíamos explicado, por lo que no requiere mucho más detalle.
Consideraciones de Seguridad y Compatibilidad del copiado en el portapapeles con Javascript
Hay algunos detalles importantes que se deben mencionar para que no te sorprenda el uso de la funcionalidad de copiado en el portapapeles.
Permisos necesarios por interacción
Para usar navigator.clipboard
, el usuario debe haber interactuado con la página de alguna manera. Por ejemplo debe haber hecho clic en algún lugar de la página. Esto se hace para evitar el abuso de esta funcionalidad.
Compatibilidad con navegadores
El API de Clipboard funciona en la mayoría de los navegadores modernos como Chrome, Firefox, y Safari. Sin embargo, puede tener limitaciones en navegadores más antiguos o en algunos entornos de navegación móvil.
En Firefox en concreto se permite escribir en el portapapeles, pero no se pueden hacer todas las funcionalidades del API que otros sí permiten. Al menos por el momento.
Podría ser necesario usar HTTPS
Algunos navegadores solo permiten el uso del Clpboard API si las páginas se sirven mediante conexiones seguras (HTTPS).
En muchos casos no habrá problema si no usas HTTPS, peor para asegurarte que esta funcionalidad se ejecute correctamente podrías necesitar desplegar tu web en un servidor seguro.
A veces desde
localhost
los navegadores no requieren que se use HTTPS, porque lo entienden como un acceso seguro.
Para ampliar esta información y apreciar una variante de copiado en el portapapeles puedes leer esta FAQ: Copiar en el portapapeles únicamente el texto seleccionado de un campo textarea
Código antiguo de copiado en el portapapeles
Ahora te vamos a dejar el texto antiguo de este artículo, que se escribió originalmente antes de que el API de Clipboard se crease. No te recomendamos este enfoque, ya que ahora afortunadamente las cosas se pueden realizar de una manera mucho más fácil. De todos modos, por motivos de archivo dejamos el texto antiguo de este artículo para que sirva de muestra de lo que teníamos que sufrir los desarrolladores antes de que los navegadores se pusieran de acuerdo para apoyar y respetar los estándares.
El script que vamos a comentar sirve para seleccionar un texto que hay en un textarea y copiarlo en el portapapeles. Esta es una tarea que se puede realizar fácilmente en Internet Explorer, pero que da algún mayor quebradero de cabeza en Firefox.
Internet Explorer dispone de un par de mecanismos para copiar texto en el portapapeles de una manera sencilla, a partir de las cual he confeccionado el siguiente script:
<form name="f1">
<textarea cols="50" rows="5" name="campo1">Hola. Este texto es el que vamos a seleccionar y copiar.</textarea>
<br>
<input type="button" value="Copiar" onclick="copia_portapapeles()">
</form>
<script language="javascript">
function copia_portapapeles(){
document.f1.campo1.select()
window.clipboardData.setData("Text", document.f1.campo1.value);
}
</script>
Tenemos un formulario con un textarea y un botón. En el textarea hay un texto y al pulsar el botón se seleccionará y copiará el texto. Utilizamos el método setData()
del objeto clipboardData
. Este método recibe dos parámetros. El primero indica el tipo de formato de la información a copiar y el segundo es la cadena de texto que se va a introducir en el portapapeles.
Lo malo es que este script no funciona con Firefox. Esto es porque este navegador no tiene el objeto clipboardData
. Parece ser que este objeto es propio de Internet Explorer, aunque Firefox también debe considerar que copiar en el portapapeles conlleva algunos posibles agujeros de seguridad, por lo que no permite en principio trabajar con el portapapeles.
Para que esta función no lance un error javascript al ejecutarla, tenemos que prevenir la llamada al método setData()
del objeto clipboardData
, para que no se realice si no existe tal objeto. La función quedaría de la siguiente manera:
function copia_portapapeles(){
document.f1.campo1.select()
if (window.clipboardData){
window.clipboardData.setData("Text", document.f1.campo1.value);
}
}
Simplemente se comprueba si existe window.clipboardData
, evaluándolo en un if, antes de ejecutar su método. En Firefox, que no tiene window.clipboardData
, simplemente se seleccionará el texto, pero no se llegará a copiar en el portapapeles.
Para hacer un script que copie un texto en el portapapeles y funcione en Firefox se debe utilizar otro mecanismo más complejo, que no he investigado a fondo. El tema es que, aunque funciona, debería configurarse Firefox para permitir ese tipo de acciones, o realizar un script firmado (http://www.mozilla.org/projects/security/components/signed-scripts.html).
El script que utilizan es el siguiente:
function copy_clip(textocopiado) {
if (window.clipboardData) {
window.clipboardData.setData("Text", textocopiado);
}
else if (window.netscape) {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var clip = Components.classes['@mozilla.org/widget/clipboard;1']
.createInstance(Components.interfaces.nsIClipboard);
if (!clip) return;
var trans = Components.classes['@mozilla.org/widget/transferable;1']
.createInstance(Components.interfaces.nsITransferable);
if (!trans) return;
trans.addDataFlavor('text/unicode');
var str = new Object();
var len = new Object();
var str = Components.classes["@mozilla.org/supports-string;1"]
.createInstance(Components.interfaces.nsISupportsString);
var copyTextString = textocopiado;
str.data = copyTextString;
trans.setTransferData("text/unicode", str, copyTextString.length * 2);
var clipid = Components.interfaces.nsIClipboard;
if (!clip) return false;
clip.setData(trans, null, clipid.kGlobalClipboard);
}
alert("Se ha podido copiar el texto: " + textocopiado);
return false;
}
Como ves, esta funcionalidad sin el API de Clipboard era una auténtica locura... afortunadamente las cosas han cambiado bastante desde entonces.
Miguel Angel Alvarez
Fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Com...