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 textarea
ou input
visí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 true
se o comando "é suportado pelo navegador".
- e
document.queryCommandEnabled('copy')
retorne true
se 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 true
de 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
/ catch
bloco 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.queryCommandSupported
ou document.queryCommandEnabled
deve ser agrupada em um try
/ catch
bloco.
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.