Aperçu
Il existe trois API de navigateur principales pour la copie dans le presse-papiers:
- API Async Clipboard
[navigator.clipboard.writeText]
- Partie textuelle disponible dans Chrome 66 (mars 2018)
- L'accès est asynchrone et utilise des promesses JavaScript , peut être écrit pour que les invites utilisateur de sécurité (si affichées) n'interrompent pas le JavaScript dans la page.
- Le texte peut être copié dans le presse-papiers directement à partir d'une variable.
- Prise en charge uniquement sur les pages diffusées via HTTPS.
- Dans Chrome 66, les pages des onglets actifs peuvent écrire dans le presse-papiers sans invite d'autorisation.
document.execCommand('copy')
- La plupart des navigateurs le prennent en charge en date d'avril 2015 (voir Prise en charge du navigateur ci-dessous).
- L'accès est synchrone, c'est-à-dire qu'il arrête JavaScript dans la page jusqu'à ce qu'il soit terminé, y compris l'affichage et l'interaction de l'utilisateur avec les invites de sécurité.
- Le texte est lu à partir du DOM et placé dans le presse-papiers.
- Lors des tests ~ avril 2015, seul Internet Explorer a été noté comme affichant des invites d'autorisation lors de l'écriture dans le presse-papiers.
- Remplacement de l'événement de copie
- Voir la documentation de l'API Clipboard sur le remplacement de l'événement de copie .
- Vous permet de modifier ce qui apparaît dans le presse-papiers à partir de n'importe quel événement de copie, peut inclure d'autres formats de données autres que du texte brut.
- Non couvert ici car il ne répond pas directement à la question.
Notes générales de développement
Ne vous attendez pas à ce que les commandes liées au presse-papiers fonctionnent pendant que vous testez du code dans la console. Généralement, la page doit être active (API Async Clipboard) ou nécessite une interaction de l'utilisateur (par exemple un clic de l'utilisateur) pour permettre à ( document.execCommand('copy')
) d'accéder au presse-papiers, voir ci-dessous pour plus de détails.
IMPORTANT (noté ici 2020/02/20)
Notez que puisque cette publication a été rédigée à l'origine, la dépréciation des autorisations dans les IFRAME d'origine croisée et d'autres "sandboxing" IFRAME empêche les boutons de démonstration intégrés "Exécuter un extrait de code" et "l'exemple codepen.io" de fonctionner dans certains navigateurs (y compris Chrome et Microsoft Edge). ).
Pour développer, créez votre propre page Web, servez-vous de cette page via une connexion HTTPS pour tester et développer.
Voici une page de test / démo qui montre le fonctionnement du code:
https://deanmarktaylor.github.io/clipboard-test/
Async + Fallback
En raison du niveau de prise en charge du navigateur pour la nouvelle API Async Clipboard, vous souhaiterez probablement recourir à la document.execCommand('copy')
méthode pour obtenir une bonne couverture du navigateur.
Voici un exemple simple (peut ne pas fonctionner intégré dans ce site, lisez la note "importante" ci-dessus):
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>
(l'exemple codepen.io peut ne pas fonctionner, lisez la note "importante" ci-dessus) Notez que cet extrait ne fonctionne pas bien dans l'aperçu intégré de Stack Overflow, vous pouvez l'essayer ici: https://codepen.io/DeanMarkTaylor/pen/RMRaJX?editors = 1011
API Async Clipboard
Notez qu'il est possible de "demander l'autorisation" et de tester l'accès au presse-papiers via l'API d'autorisations dans 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 ('copie')
Le reste de cet article va dans les nuances et les détails de l' document.execCommand('copy')
API.
Prise en charge du navigateur
Le document.execCommand('copy')
support JavaScript a grandi, voir les liens ci-dessous pour les mises à jour du navigateur:
Exemple simple
(peut ne pas fonctionner intégré dans ce site, lisez la note "importante" ci-dessus)
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>
Exemple complexe: copier dans le presse-papiers sans afficher d'entrée
L'exemple simple ci-dessus fonctionne très bien si un élément textarea
ou input
est visible à l'écran.
Dans certains cas, vous souhaiterez peut-être copier du texte dans le presse-papiers sans afficher d' élément input
/ textarea
. Voici un exemple de méthode pour contourner ce problème (essentiellement insérer un élément, copier dans le presse-papiers, supprimer un élément):
Testé avec Google Chrome 44, Firefox 42.0a1 et Internet Explorer 11.0.8600.17814.
(peut ne pas fonctionner intégré dans ce site, lisez la note "importante" ci-dessus)
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>
Notes complémentaires
Fonctionne uniquement si l'utilisateur effectue une action
Tous les document.execCommand('copy')
appels doivent être le résultat direct d'une action de l'utilisateur, par exemple un gestionnaire d'événements de clic. Il s'agit d'une mesure pour éviter de jouer avec le presse-papiers de l'utilisateur lorsqu'il ne s'y attend pas.
Consultez le post des développeurs Google ici pour plus d'informations.
API Clipboard
Notez que le projet de spécification complet de l'API Clipboard se trouve ici:
https://w3c.github.io/clipboard-apis/
Est-il pris en charge?
document.queryCommandSupported('copy')
doit retourner true
si la commande "est prise en charge par le navigateur".
- et
document.queryCommandEnabled('copy')
revenir true
si le document.execCommand('copy')
réussit si appelé maintenant. Vérification pour vous assurer que la commande a été appelée à partir d'un thread initié par l'utilisateur et que d'autres exigences sont remplies.
Cependant , comme un exemple de problèmes de compatibilité du navigateur, Google Chrome de ~ Avril à Octobre 2015 , ne ~ retour true
de document.queryCommandSupported('copy')
si la commande a été appelé à partir d' un fil lancé par l' utilisateur.
Notez les détails de compatibilité ci-dessous.
Détails de compatibilité du navigateur
Bien qu'un simple appel à document.execCommand('copy')
enveloppé dans un bloc try
/ catch
appelé à la suite d'un clic de l'utilisateur vous obtienne le plus de compatibilité, ce qui suit a certaines conditions:
Tout appel à document.execCommand
, document.queryCommandSupported
ou document.queryCommandEnabled
doit être encapsulé dans un bloc try
/ catch
.
Différentes implémentations et versions de navigateur lancent différents types d'exceptions lorsqu'elles sont appelées au lieu de revenir false
.
Différentes implémentations de navigateur sont toujours en cours et l' API Clipboard est toujours en projet, alors n'oubliez pas de faire vos tests.