Visão geral
Existem três APIs principais do navegador para copiar para a área de transferência:
- API de área de transferência assíncrona
[navigator.clipboard.writeText]
- Parte com foco em texto disponível no Chrome 66 (março de 2018)
- O acesso é assíncrono e usa promessas de JavaScript , pode ser gravado para que os prompts do usuário de segurança (se exibidos) não interrompam o JavaScript na página.
- O texto pode ser copiado para a área de transferência diretamente de uma variável.
- Suportado apenas em páginas veiculadas em HTTPS.
- No Chrome 66, as páginas nas guias ativas podem gravar na área de transferência sem um prompt de permissão.
document.execCommand('copy')
- A maioria dos navegadores é compatível com isso a partir de abril de 2015 (consulte Suporte ao navegador abaixo).
- O acesso é síncrono, ou seja, interrompe o JavaScript na página até a conclusão, incluindo a exibição e a interação do usuário com qualquer solicitação de segurança.
- O texto é lido do DOM e colocado na área de transferência.
- Durante o teste ~ abril de 2015, apenas o Internet Explorer foi observado como exibindo prompts de permissões enquanto gravava na área de transferência.
- Substituindo o evento de cópia
- Consulte a documentação da API da área de transferência em Substituindo o evento de cópia .
- Permite modificar o que aparece na área de transferência a partir de qualquer evento de cópia, podendo incluir outros formatos de dados que não sejam texto sem formatação.
- Não abordado aqui, pois não responde diretamente à pergunta.
Notas gerais de desenvolvimento
Não espere que os comandos relacionados à área de transferência funcionem enquanto você estiver testando o código no console. Geralmente, é necessário que a página esteja ativa (API do Async Clipboard) ou requer interação do usuário (por exemplo, um clique do usuário) para permitir ( document.execCommand('copy')) acessar a área de transferência, veja abaixo para obter mais detalhes.
IMPORTANTE (observado aqui 2020/02/20)
Observe que, desde que esta postagem foi originalmente descontinuada por escrito, as permissões em IFRAMEs de origem cruzada e outros "sandboxing" de IFRAME impedem que as demos incorporadas "Execute o snippet de código" e o "codepen.io example" funcionem em alguns navegadores (incluindo Chrome e Microsoft Edge) )
Para desenvolver, crie sua própria página da web, sirva essa página pela conexão HTTPS para testar e desenvolver.
Aqui está uma página de teste / demonstração que demonstra o funcionamento do código:
https://deanmarktaylor.github.io/clipboard-test/
Async + Fallback
Devido ao nível de suporte do navegador para a nova API do Async Clipboard, você provavelmente desejará recorrer ao document.execCommand('copy')método para obter uma boa cobertura do navegador.
Aqui está um exemplo simples (pode não funcionar incorporado neste site, leia a nota "importante" acima):
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>
(o exemplo do codepen.io pode não funcionar, leia a observação "importante" acima). Observe que este snippet não está funcionando bem na visualização incorporada do Stack Overflow. Você pode experimentá-lo aqui: https://codepen.io/DeanMarkTaylor/pen/RMRaJX?editors = 1011
API de área de transferência assíncrona
Observe que existe a capacidade de "solicitar permissão" e testar o acesso à área de transferência por meio da API de permissões no 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 ('copy')
O restante deste post aborda as nuances e os detalhes da document.execCommand('copy')API.
Suporte do navegador
O document.execCommand('copy')suporte ao JavaScript aumentou, veja os links abaixo para atualizações do navegador:
Exemplo Simples
(pode não funcionar incorporado neste site, leia a nota "importante" acima)
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>
Exemplo complexo: Copiar para a área de transferência sem exibir a entrada
O exemplo simples acima funciona muito bem se houver um elemento textareaou inputvisível na tela.
Em alguns casos, você pode querer copiar texto para a área de transferência sem exibir um elemento input/ textarea. Este é um exemplo de uma maneira de contornar isso (basicamente insira o elemento, copie para a área de transferência, remova o elemento):
Testado com Google Chrome 44, Firefox 42.0a1 e Internet Explorer 11.0.8600.17814.
(pode não funcionar incorporado neste site, leia a nota "importante" acima)
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 Adicionais
Funciona apenas se o usuário executar uma ação
Todas as document.execCommand('copy')chamadas devem ocorrer como resultado direto de uma ação do usuário, por exemplo, clique em manipulador de eventos. Esta é uma medida para evitar mexer com a área de transferência do usuário quando eles não a esperam.
Veja a postagem dos desenvolvedores do Google aqui para obter mais informações.
API da área de transferência
Observe que a especificação completa do rascunho da API da área de transferência pode ser encontrada aqui:
https://w3c.github.io/clipboard-apis/
É suportado?
document.queryCommandSupported('copy')deve retornar truese o comando "é suportado pelo navegador".
- e
document.queryCommandEnabled('copy')retorne truese o document.execCommand('copy')for bem-sucedido se for chamado agora. Verificando para garantir que o comando foi chamado a partir de um encadeamento iniciado pelo usuário e outros requisitos sejam atendidos.
No entanto, como um exemplo de problemas de compatibilidade do navegador, o Google Chrome de ~ abril a ~ outubro de 2015 retornou apenas truede document.queryCommandSupported('copy')se o comando foi chamado a partir de um encadeamento iniciado pelo usuário.
Observe os detalhes de compatibilidade abaixo.
Detalhes de compatibilidade do navegador
Enquanto um simples chamada para document.execCommand('copy')envolto em um try/ catchbloco chamado como resultado de um clique do usuário irá obter o uso mais compatibilidade a seguinte tem algumas ressalvas:
Qualquer chamada para document.execCommand, document.queryCommandSupportedou document.queryCommandEnableddeve ser agrupada em um try/ catchbloco.
Diferentes implementações de navegador e versões de navegador lançam diferentes tipos de exceções quando chamadas em vez de retornar false.
Diferentes implementações de navegadores ainda estão em andamento e a API da área de transferência ainda está em rascunho. Lembre-se de fazer seus testes.