Visión general
Hay tres API principales del navegador para copiar en el portapapeles:
- API del portapapeles asíncrono
[navigator.clipboard.writeText]
- Parte centrada en texto disponible en Chrome 66 (marzo de 2018)
- El acceso es asíncrono y usa Promesas de JavaScript , puede escribirse para que las indicaciones del usuario de seguridad (si se muestran) no interrumpan el JavaScript en la página.
- El texto se puede copiar al portapapeles directamente desde una variable.
- Solo se admite en páginas publicadas a través de HTTPS.
- En Chrome 66 páginas en pestañas activas pueden escribir en el portapapeles sin un aviso de permisos.
document.execCommand('copy')
- La mayoría de los navegadores admiten esto a partir de ~ abril de 2015 (consulte la Ayuda del navegador a continuación).
- El acceso es sincrónico, es decir, detiene JavaScript en la página hasta que se completa, incluida la visualización y la interacción del usuario con cualquier mensaje de seguridad.
- El texto se lee del DOM y se coloca en el portapapeles.
- Durante las pruebas ~ abril de 2015, solo se observó que Internet Explorer mostraba solicitudes de permisos mientras escribía en el portapapeles.
- Anular el evento de copia
- Consulte la documentación de la API del Portapapeles sobre Anulación del evento de copia .
- Le permite modificar lo que aparece en el portapapeles desde cualquier evento de copia, puede incluir otros formatos de datos que no sean texto sin formato.
- No se cubre aquí, ya que no responde directamente a la pregunta.
Notas generales de desarrollo
No espere que los comandos relacionados con el portapapeles funcionen mientras está probando el código en la consola. En general, se requiere que la página esté activa (API del portapapeles asíncrono) o requiere la interacción del usuario (por ejemplo, un clic del usuario) para permitir que ( document.execCommand('copy')
) acceda al portapapeles. Consulte a continuación para obtener más detalles.
IMPORTANTE (indicado aquí 2020/02/20)
Tenga en cuenta que, dado que esta publicación se escribió originalmente en desuso de permisos en IFRAME de origen cruzado y otros "sandboxing" de IFRAME, se evita que los demos integrados "Ejecutar fragmento de código" y "ejemplo codepen.io" funcionen en algunos navegadores (incluidos Chrome y Microsoft Edge )
Para desarrollar, cree su propia página web, sirva esa página a través de la conexión HTTPS para probar y desarrollar.
Aquí hay una página de prueba / demostración que demuestra el funcionamiento del código:
https://deanmarktaylor.github.io/clipboard-test/
Async + Fallback
Debido al nivel de soporte del navegador para la nueva API Async Clipboard, es probable que desee recurrir al document.execCommand('copy')
método para obtener una buena cobertura del navegador.
Aquí hay un ejemplo simple (puede que no funcione incrustado en este sitio, lea la nota "importante" arriba):
function fallbackCopyTextToClipboard(text) {
var textArea = document.createElement("textarea");
textArea.value = text;
// Avoid scrolling to bottom
textArea.style.top = "0";
textArea.style.left = "0";
textArea.style.position = "fixed";
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
var successful = document.execCommand('copy');
var msg = successful ? 'successful' : 'unsuccessful';
console.log('Fallback: Copying text command was ' + msg);
} catch (err) {
console.error('Fallback: Oops, unable to copy', err);
}
document.body.removeChild(textArea);
}
function copyTextToClipboard(text) {
if (!navigator.clipboard) {
fallbackCopyTextToClipboard(text);
return;
}
navigator.clipboard.writeText(text).then(function() {
console.log('Async: Copying to clipboard was successful!');
}, function(err) {
console.error('Async: Could not copy text: ', err);
});
}
var copyBobBtn = document.querySelector('.js-copy-bob-btn'),
copyJaneBtn = document.querySelector('.js-copy-jane-btn');
copyBobBtn.addEventListener('click', function(event) {
copyTextToClipboard('Bob');
});
copyJaneBtn.addEventListener('click', function(event) {
copyTextToClipboard('Jane');
});
<div style="display:inline-block; vertical-align:top;">
<button class="js-copy-bob-btn">Set clipboard to BOB</button><br /><br />
<button class="js-copy-jane-btn">Set clipboard to JANE</button>
</div>
<div style="display:inline-block;">
<textarea class="js-test-textarea" cols="35" rows="4">Try pasting into here to see what you have on your clipboard:
</textarea>
</div>
(el ejemplo de codepen.io puede no funcionar, lea la nota "importante" anterior) Tenga en cuenta que este fragmento no funciona bien en la vista previa incrustada de Stack Overflow. Puede probarlo aquí: https://codepen.io/DeanMarkTaylor/pen/RMRaJX?editors = 1011
API del portapapeles asíncrono
Tenga en cuenta que existe la posibilidad de "solicitar permiso" y probar el acceso al portapapeles a través de la API de permisos en Chrome 66.
var text = "Example text to appear on clipboard";
navigator.clipboard.writeText(text).then(function() {
console.log('Async: Copying to clipboard was successful!');
}, function(err) {
console.error('Async: Could not copy text: ', err);
});
document.execCommand ('copia')
El resto de esta publicación trata los matices y detalles de la document.execCommand('copy')
API.
Soporte de navegador
El document.execCommand('copy')
soporte de JavaScript ha crecido, consulte los enlaces a continuación para obtener actualizaciones del navegador:
Ejemplo simple
(puede no funcionar integrado en este sitio, lea la nota "importante" arriba)
var copyTextareaBtn = document.querySelector('.js-textareacopybtn');
copyTextareaBtn.addEventListener('click', function(event) {
var copyTextarea = document.querySelector('.js-copytextarea');
copyTextarea.focus();
copyTextarea.select();
try {
var successful = document.execCommand('copy');
var msg = successful ? 'successful' : 'unsuccessful';
console.log('Copying text command was ' + msg);
} catch (err) {
console.log('Oops, unable to copy');
}
});
<p>
<button class="js-textareacopybtn" style="vertical-align:top;">Copy Textarea</button>
<textarea class="js-copytextarea">Hello I'm some text</textarea>
</p>
Ejemplo complejo: copiar al portapapeles sin mostrar la entrada
El ejemplo anterior simple funciona muy bien si hay una textarea
o input
elemento visible en la pantalla.
En algunos casos, es posible que desee copiar texto en el portapapeles sin mostrar un elemento input
/ textarea
. Este es un ejemplo de una forma de evitar esto (básicamente insertar elemento, copiar al portapapeles, eliminar elemento):
Probado con Google Chrome 44, Firefox 42.0a1 e Internet Explorer 11.0.8600.17814.
(puede no funcionar integrado en este sitio, lea la nota "importante" arriba)
function copyTextToClipboard(text) {
var textArea = document.createElement("textarea");
//
// *** This styling is an extra step which is likely not required. ***
//
// Why is it here? To ensure:
// 1. the element is able to have focus and selection.
// 2. if element was to flash render it has minimal visual impact.
// 3. less flakyness with selection and copying which **might** occur if
// the textarea element is not visible.
//
// The likelihood is the element won't even render, not even a
// flash, so some of these are just precautions. However in
// Internet Explorer the element is visible whilst the popup
// box asking the user for permission for the web page to
// copy to the clipboard.
//
// Place in top-left corner of screen regardless of scroll position.
textArea.style.position = 'fixed';
textArea.style.top = 0;
textArea.style.left = 0;
// Ensure it has a small width and height. Setting to 1px / 1em
// doesn't work as this gives a negative w/h on some browsers.
textArea.style.width = '2em';
textArea.style.height = '2em';
// We don't need padding, reducing the size if it does flash render.
textArea.style.padding = 0;
// Clean up any borders.
textArea.style.border = 'none';
textArea.style.outline = 'none';
textArea.style.boxShadow = 'none';
// Avoid flash of white box if rendered for any reason.
textArea.style.background = 'transparent';
textArea.value = text;
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
var successful = document.execCommand('copy');
var msg = successful ? 'successful' : 'unsuccessful';
console.log('Copying text command was ' + msg);
} catch (err) {
console.log('Oops, unable to copy');
}
document.body.removeChild(textArea);
}
var copyBobBtn = document.querySelector('.js-copy-bob-btn'),
copyJaneBtn = document.querySelector('.js-copy-jane-btn');
copyBobBtn.addEventListener('click', function(event) {
copyTextToClipboard('Bob');
});
copyJaneBtn.addEventListener('click', function(event) {
copyTextToClipboard('Jane');
});
<div style="display:inline-block; vertical-align:top;">
<button class="js-copy-bob-btn">Set clipboard to BOB</button><br /><br />
<button class="js-copy-jane-btn">Set clipboard to JANE</button>
</div>
<div style="display:inline-block;">
<textarea class="js-test-textarea" cols="35" rows="4">Try pasting into here to see what you have on your clipboard:
</textarea>
</div>
Notas adicionales
Solo funciona si el usuario toma una acción
Todas las document.execCommand('copy')
llamadas deben realizarse como resultado directo de una acción del usuario, por ejemplo, haga clic en el controlador de eventos. Esta es una medida para evitar jugar con el portapapeles del usuario cuando no lo esperan.
Vea la publicación de Google Developers aquí para obtener más información.
API del portapapeles
Tenga en cuenta que la especificación del borrador de la API del Portapapeles se puede encontrar aquí:
https://w3c.github.io/clipboard-apis/
¿Es compatible?
document.queryCommandSupported('copy')
debería regresar true
si el comando "es compatible con el navegador".
- y
document.queryCommandEnabled('copy')
regresar true
si document.execCommand('copy')
tendrá éxito si se llama ahora. Verificación para asegurarse de que se llamó al comando desde un hilo iniciado por el usuario y se cumplen otros requisitos.
Sin embargo, como un ejemplo de los problemas de compatibilidad del navegador, Google Chrome desde abril a ~ ~ de octubre de de 2015 devueltos true
de document.queryCommandSupported('copy')
si el comando se llama desde un hilo iniciado por el usuario.
Observe los detalles de compatibilidad a continuación.
Detalle de compatibilidad del navegador
Si bien una simple llamada a document.execCommand('copy')
encapsulado en un try
/ catch
bloque llamado como resultado de un clic del usuario obtendrá la mayor compatibilidad, el uso tiene algunas condiciones:
Cualquier llamada a document.execCommand
, document.queryCommandSupported
o document.queryCommandEnabled
debe estar envuelto en un try
/ catch
bloque.
Las diferentes implementaciones y versiones de navegador lanzan diferentes tipos de excepciones cuando se llama en lugar de regresar false
.
Las diferentes implementaciones de navegador todavía están en proceso de cambio y la API del Portapapeles todavía está en borrador, así que recuerde hacer sus pruebas.