Comment copier dans le presse-papiers en JavaScript?

3324

Quelle est la meilleure façon de copier du texte dans le presse-papiers? (multi-navigateur)

J'ai essayé:

function copyToClipboard(text) {
    if (window.clipboardData) { // Internet Explorer
        window.clipboardData.setData("Text", text);
    } else {  
        unsafeWindow.netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");  
        const clipboardHelper = Components.classes["@mozilla.org/widget/clipboardhelper;1"].getService(Components.interfaces.nsIClipboardHelper);  
        clipboardHelper.copyString(text);
    }
}

mais dans Internet Explorer, il donne une erreur de syntaxe. Dans Firefox, c'est écrit unsafeWindow is not defined.

Une bonne astuce sans flash: comment Trello accède-t-il au presse-papiers de l'utilisateur?

Santiago Corredoira
la source
Juste curieux, qu'est-ce que vous voulez copier dans le presse-papiers que l'utilisateur ne peut pas faire lui-même?
scunliffe
233
Rien de spécial. Ils peuvent le faire eux-mêmes, mais je veux également offrir la possibilité de cliquer sur un bouton sans se soucier de sélectionner la bonne partie du texte.
Santiago Corredoira
4
Ce long article de blog contient de nombreuses façons de procéder: Accéder au Presse-papiers du système avec JavaScript - Un Saint Graal?
Aaron Digulla
Il donne une exception non définie au navigateur dans IE ainsi que dans FF
Jagadeesh
1
Si nous pouvons mettre du texte dans le presse-papiers de l'utilisateur, nous pouvons ruiner son presse-papiers.
Frank Fang

Réponses:

2251

Aperçu

Il existe trois API de navigateur principales pour la copie dans le presse-papiers:

  1. 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.
  2. 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.
  3. 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 textareaou inputest 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 truesi la commande "est prise en charge par le navigateur".
  • et document.queryCommandEnabled('copy')revenir truesi 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 truede 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/ catchappelé à 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.queryCommandSupportedou document.queryCommandEnableddoit ê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.

Dean Taylor
la source
41
comment copier directement à partir de données d' une variable .ie: var str = "word";?
jscripter
10
@BubuDaba Créez un mannequin caché <textarea>avec JS, ajoutez-le à document.body, définissez sa valeur sur la variable et utilisez-le à la vitesse de copyTextarea, puis supprimez-le juste après la copie du contenu.
SeinopSys
3
Y a-t-il quelque chose pour Safari ou des indicateurs qu'il sera implémenté dans Safari?
www139
3
La seule version que j'ai trouvée qui fonctionne dans tous les navigateurs. J'ai découvert qu'en utilisant ceci dans Boostrap Modal, je devais ajouter la zone de texte au modal. Je donnerais un +1000 si je pouvais pour votre solution !!! MERCI!
Patrick
3
@AyaSalama, le point clé est que l'action de "copie" ne peut avoir lieu que si le navigateur apparaît que l'utilisateur effectue l'action. L'utilisateur ne pourrait pas entreprendre l'action si l'élément est stylisé avec "display: none" car il ne pourrait pas le voir, ni interagir avec lui.
Dean Taylor
1258

La copie automatique dans le presse-papiers peut être dangereuse, donc la plupart des navigateurs (sauf IE) rendent la tâche très difficile. Personnellement, j'utilise l'astuce simple suivante:

function copyToClipboard(text) {
  window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
}

L'utilisateur est présenté avec la boîte d'invite, où le texte à copier est déjà sélectionné. Il suffit maintenant d'appuyer sur Ctrl+ Cet Enter(pour fermer la boîte) - et le tour est joué!

Maintenant, l'opération de copie du presse-papiers est SÉCURITAIRE, car l'utilisateur le fait manuellement (mais d'une manière assez simple). Bien sûr, fonctionne dans tous les navigateurs.

<button id="demo" onclick="copyToClipboard(document.getElementById('demo').innerHTML)">This is what I want to copy</button>

<script>
  function copyToClipboard(text) {
    window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
  }
</script>

Jarek Milewski
la source
91
Intelligent, mais cela ne prend en charge qu'une seule ligne.
Aram Kocharyan
61
Il est trivial de changer la fonction "d'invite" en un modal personnalisé, l'essentiel de l'astuce est d'utiliser un champ de contenu modifiable et de présélectionner le texte, et que cela ne casse pas l'interface utilisateur du navigateur en imposant que l'utilisateur prenne le l'action eux-mêmes. A ++
Jon z
110
n'utilise toujours pas javascript pour copier dans le presse-papiers ^ _ ^
RozzA
23
Si votre texte
contient
445
Étrange que cela obtienne 457 votes positifs alors qu'il ne répond pas à la question: copier dans le presse-papiers en Javascript !
stevenvh
300

L'approche suivante fonctionne dans Chrome, Firefox, Internet Explorer et Edge, et dans les versions récentes de Safari (le support de copie a été ajouté dans la version 10 qui a été publiée en octobre 2016).

  • Créez une zone de texte et définissez son contenu sur le texte que vous souhaitez copier dans le presse-papiers.
  • Ajoutez la zone de texte au DOM.
  • Sélectionnez le texte dans la zone de texte.
  • Appelez document.execCommand ("copier")
  • Retirez la zone de texte du dom.

Remarque: vous ne verrez pas la zone de texte, car elle est ajoutée et supprimée dans le même appel synchrone de code Javascript.

Certaines choses à surveiller si vous implémentez cela vous-même:

  • Pour des raisons de sécurité, cela ne peut être appelé qu'à partir d'un gestionnaire d'événements tel que click (comme avec l'ouverture de fenêtres).
  • Internet Explorer affichera une boîte de dialogue d'autorisation la première fois que le presse-papiers est mis à jour.
  • Internet Explorer et Edge défileront lorsque la zone de texte sera mise au point.
  • execCommand () peut lancer dans certains cas.
  • Les sauts de ligne et les tabulations peuvent être avalés, sauf si vous utilisez une zone de texte. (La plupart des articles semblent recommander l'utilisation d'un div)
  • La zone de texte sera visible lorsque la boîte de dialogue Internet Explorer est affichée, vous devez soit la masquer, soit utiliser l'API clipboardData spécifique à Internet Explorer.
  • Dans Internet Explorer, les administrateurs système peuvent désactiver l'API du presse-papiers.

La fonction ci-dessous doit gérer tous les problèmes suivants aussi proprement que possible. Veuillez laisser un commentaire si vous rencontrez des problèmes ou avez des suggestions pour l'améliorer.

// Copies a string to the clipboard. Must be called from within an
// event handler such as click. May return false if it failed, but
// this is not always possible. Browser support for Chrome 43+,
// Firefox 42+, Safari 10+, Edge and Internet Explorer 10+.
// Internet Explorer: The clipboard feature may be disabled by
// an administrator. By default a prompt is shown the first
// time the clipboard is used (per session).
function copyToClipboard(text) {
    if (window.clipboardData && window.clipboardData.setData) {
        // Internet Explorer-specific code path to prevent textarea being shown while dialog is visible.
        return clipboardData.setData("Text", text);

    }
    else if (document.queryCommandSupported && document.queryCommandSupported("copy")) {
        var textarea = document.createElement("textarea");
        textarea.textContent = text;
        textarea.style.position = "fixed";  // Prevent scrolling to bottom of page in Microsoft Edge.
        document.body.appendChild(textarea);
        textarea.select();
        try {
            return document.execCommand("copy");  // Security exception may be thrown by some browsers.
        }
        catch (ex) {
            console.warn("Copy to clipboard failed.", ex);
            return false;
        }
        finally {
            document.body.removeChild(textarea);
        }
    }
}

https://jsfiddle.net/fx6a6n6x/

Greg Lowe
la source
9
Bonne réponse: prise en charge de plusieurs navigateurs, gestion des erreurs + nettoyage. Depuis la nouvelle prise en charge d'aujourd'hui pour queryCommandSupported, la copie dans le presse-papiers est désormais possible en Javascript et cela devrait être la réponse acceptée, au lieu de maladroit 'window.prompt ("Copier dans le presse-papiers: Ctrl + C, Entrée", texte)'. window.clipboardData est pris en charge dans IE9, vous devez donc ajouter IE9 dans la liste de prise en charge du navigateur et je pense que peut-être IE8 et les versions précédentes également, mais vous devez vérifier.
user627283
Ouais. IE 8/9 devrait être ok. Notre application ne les prend pas en charge. Je n'ai donc pas testé. IE arrête le support en janvier, donc je ne suis pas trop agité. J'espère que le support Safari arrivera bientôt. Je suis sûr que c'est sur leur radar.
Greg Lowe
4
@SantiagoCorredoira: En 2016, cela mérite d'être la réponse acceptée. Veuillez envisager de réaffecter le BGT (grosse coche verte).
Lawrence Dol
3
@Noitidart I Tested et cela fonctionne parfaitement pour Firefox 54, Chrome 60 et le navigateur Edge, même lorsque le focus n'est pas dans le document HTML, l'erreur que vous rencontrez est probablement spécifique à la version FF 55
Tosin John
2
@Noitidart Cela fonctionne toujours parfaitement ici, se concentrer sur les outils de développement ne l'a pas arrêté. Et au fait, que fera un utilisateur normal d'une application Web sur les outils de développement
Tosin John
97

Voici mon point de vue sur celui-là ...

function copy(text) {
    var input = document.createElement('input');
    input.setAttribute('value', text);
    document.body.appendChild(input);
    input.select();
    var result = document.execCommand('copy');
    document.body.removeChild(input);
    return result;
 }

@korayem: Notez que l'utilisation du inputchamp html ne respectera pas les sauts de ligne \net aplatira tout texte en une seule ligne.

Comme mentionné par @nikksan dans les commentaires, l'utilisation résoudra textareale problème comme suit:

function copy(text) {
    var input = document.createElement('textarea');
    input.innerHTML = text;
    document.body.appendChild(input);
    input.select();
    var result = document.execCommand('copy');
    document.body.removeChild(input);
    return result;
}
nikksan
la source
@nikksan comment copier la chaîne avec \n?
sof-03
2
@ sof-03 utilise textarea au lieu de saisir et ajoute \r\npour un saut de ligne
nikksan
1
Ne fonctionne pas dans Microsoft Edge 42.17134.1.0 sur Win10x64
Honsa Stunna
3
J'ai copié votre réponse. Il fonctionne en chrome et c'est tout ce dont j'ai besoin.
user875234
Il s'agit de la solution la plus simple qui fonctionne avec Firefox v68.0.2 (64 bits).
Arya
88

Si vous voulez une solution vraiment simple (prend moins de 5 minutes à intégrer) et semble bonne dès la sortie de la boîte, alors Clippy est une belle alternative à certaines des solutions les plus complexes.

Il a été écrit par un co-fondateur de GitHub. Exemple de code d'intégration Flash ci-dessous:

<object
   classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
   width="110"
   height="14"
   id="clippy">
  <param name="movie" value="/flash/clippy.swf"/>
  <param name="allowScriptAccess" value="always"/>
  <param name="quality" value="high"/>
  <param name="scale" value="noscale"/>
  <param NAME="FlashVars" value="text=#{text}"/>
  <param name="bgcolor" value="#{bgcolor}"/>
  <embed
     src="/flash/clippy.swf"
     width="110"
     height="14"
     name="clippy"
     quality="high"
     allowScriptAccess="always"
     type="application/x-shockwave-flash"
     pluginspage="http://www.macromedia.com/go/getflashplayer"
     FlashVars="text=#{text}"
     bgcolor="#{bgcolor}"/>
</object>

N'oubliez pas de remplacer #{text}par le texte à copier et #{bgcolor}par une couleur.

Brent Matzelle
la source
12
Pour toute personne intéressée, vérifiez que Clippy est utilisé sur GitHub lors de la copie de l'URL du dépôt.
Radek
66
Pour info, l'utilisation de Clippy sur GitHub a été remplacée par ZeroClipboard.
James M. Greene
219
L'OP voulait une solution en JavaScript. Pas flash.
MT.
21
@MT, par "javascript", certaines personnes veulent dire "dans le client du navigateur", donc bien que JS uniquement puisse être une exigence, beaucoup de gens qui ont la chance de trouver cette réponse recherchent vraiment JS ou un autre support largement répandu. client-tech. Flash ne touche pas toutes les plates-formes, mais pour une fonctionnalité polie comme la prise en charge du presse-papiers, il vaut la peine d'ajouter s'il améliore l'UX par rapport à une boîte de dialogue contextuelle (ce qu'il fait certainement).
Dave Dopson
13
S'appuyer maintenant sur Flash signifie que les choses ne fonctionnent pas pour un pourcentage de visiteurs du site, ce qui est inacceptable pour presque tout le monde qui fait du développement Web.
jinglesthula
86

La lecture et la modification du presse-papiers à partir d'une page Web soulèvent des problèmes de sécurité et de confidentialité. Cependant, dans Internet Explorer, il est possible de le faire. J'ai trouvé cet exemple d'extrait :

    <script type="text/javascript">
        function select_all(obj) {
            var text_val=eval(obj);
            text_val.focus();
            text_val.select();
            r = text_val.createTextRange();
            if (!r.execCommand) return; // feature detection
            r.execCommand('copy');
        }
    </script>
    <input value="http://www.sajithmr.com"
     onclick="select_all(this)" name="url" type="text" />

bandi
la source
7
L'utilisation de Flash pour une simple opération de copie semble exagérée, heureux qu'il y ait une façon propre à JS de le faire. Et puisque nous sommes dans un environnement d'entreprise. IE est très bien. Merci Bandi!
Eddie
5
plz expliquer ce que execCommand(\\’copy\\’);fait, sinon copier dans le presse-papiers pour IE? @mrBorna
RozzA
20
N'utilisez pas if(!document.all)mais de if(!r.execCommand)peur que quelqu'un d'autre ne le mette en œuvre! Document.all n'est absolument pas pertinent pour cela.
m93a
1
Man, c'est ce que j'aime à propos du code simple et propre, il fonctionne presque toujours avec une maintenance mineure. Cela l'a fait pour moi, cela fonctionne à merveille.
Samuel Ramzan
1
ne fonctionne pas dans les derniers chrome, firefox ou MS Edge :(
Jonathan Marzullo
69

J'ai récemment écrit un blog technique sur ce problème (je travaille chez Lucidchart et nous avons récemment fait une refonte sur notre presse-papiers).

La copie de texte brut dans le presse-papiers est relativement simple, en supposant que vous vouliez le faire pendant un événement de copie système (l'utilisateur appuie CtrlCou utilise le menu du navigateur).

var isIe = (navigator.userAgent.toLowerCase().indexOf("msie") != -1 
           || navigator.userAgent.toLowerCase().indexOf("trident") != -1);

document.addEventListener('copy', function(e) {
    var textToPutOnClipboard = "This is some text";
    if (isIe) {
        window.clipboardData.setData('Text', textToPutOnClipboard);    
    } else {
        e.clipboardData.setData('text/plain', textToPutOnClipboard);
    }
    e.preventDefault();
});

Il est beaucoup plus difficile de placer du texte dans le presse-papiers pendant un événement de copie système. Il semble que certaines de ces autres réponses fassent référence à des façons de le faire via Flash, qui est la seule façon multi-navigateur de le faire (pour autant que je comprends).

En dehors de cela, il existe certaines options navigateur par navigateur.

C'est le plus simple dans IE, où vous pouvez accéder à tout moment à l'objet clipboardData à partir de JavaScript via:

window.clipboardData

(Toutefois, lorsque vous tentez d'effectuer cette opération en dehors d'un événement de coupure, de copie ou de collage système, IE invite l'utilisateur à accorder l'autorisation au presse-papiers de l'application Web.)

Dans Chrome, vous pouvez créer une extension Chrome qui vous donnera des autorisations de presse-papiers (c'est ce que nous faisons pour Lucidchart). Ensuite, pour les utilisateurs avec votre extension installée, vous aurez juste besoin de déclencher l'événement système vous-même:

document.execCommand('copy');

Il semble que Firefox dispose de certaines options qui permettent aux utilisateurs d'accorder des autorisations à certains sites pour accéder au presse-papiers, mais je n'ai essayé aucune de ces options personnellement.

Richard Shurtz
la source
2
Non mentionné dans le billet de blog (j'espère le mettre à jour dans un proche avenir), est la possibilité de déclencher la coupe et la copie à l'aide d'execCommand. Ceci est pris en charge dans IE10 +, Chrome 43+ et Opera29 +. Lisez à ce sujet ici. updates.html5rocks.com/2015/04/cut-and-copy-commands
Richard Shurtz
Un problème avec cela est qu'il détourne d'autres événements de copie normaux.
Brock Adams
NB! Ce navigateur reniflant est MAUVAIS. Ne reniflez pas. Vous avez du mal à mettre à jour IE.
odinho - Velmont
51

clipboard.js est un petit utilitaire non Flash qui permet de copier du texte ou des données HTML dans le presse-papiers. C'est très facile à utiliser, il suffit d'inclure le .js et d'utiliser quelque chose comme ceci:

<button id='markup-copy'>Copy Button</button>

<script>
document.getElementById('markup-copy').addEventListener('click', function() {
  clipboard.copy({
    'text/plain': 'Markup text. Paste me into a rich text editor.',
    'text/html': '<i>here</i> is some <b>rich text</b>'
  }).then(
    function(){console.log('success'); },
    function(err){console.log('failure', err);
  });

});
</script>

clipboard.js est également sur GitHub .

Remarque: cela est désormais obsolète. Migrez ici .

un codeur
la source
Cette bibliothèque est utilisée par angular.io pour son Tour of Hero et se replie en mode gracieux pour le navigateur ne prenant pas en charge execCommand en affichant un texte présélectionné que l'utilisateur vient de copier.
John-Philip
1
Il semble que clipboard.js a été remplacé ou bifurqué, mais il semble vivre et est activement maintenu sur npmjs.com/package/clipboard
Joao
35

ZeroClipboard est la meilleure solution multi-navigateur que j'ai trouvée:

<div id="copy" data-clipboard-text="Copy Me!">Click to copy</div>    
<script src="ZeroClipboard.js"></script>
<script>
  var clip = new ZeroClipboard( document.getElementById('copy') );
</script>

Si vous avez besoin d'une prise en charge non flash pour iOS, il vous suffit d'ajouter une solution de secours:

clip.on( 'noflash', function ( client, args ) {
    $("#copy").click(function(){            
        var txt = $(this).attr('data-clipboard-text');
        prompt ("Copy link, then click OK.", txt);
    });
});  

http://zeroclipboard.org/

https://github.com/zeroclipboard/ZeroClipboard

Justin
la source
25
cross-browser avec Flash? ne fonctionne pas dans iOS et Android 4.4
Raptor
1
Voir la réponse mise à jour. Cela permet moins d'étapes pour les utilisateurs de flash et un repli pour tout le monde.
Justin
8
il a un milliard de lignes de code. ce sont absolument des ridicules. vaut mieux ne pas le faire du tout que d'inclure un tel monstre dans un projet
vsync
2
Il existe une version simple gist.github.com/JamesMGreene/8698897 qui est 20K qui n'a pas toutes les cloches et les sifflets dans la version 74k. Ni l'un ni l'autre n'est très grand. Je suppose que la plupart des utilisateurs sont d'accord avec les millisecondes supplémentaires qu'un fichier 74k ou 20k en cours de téléchargement prendra donc le copier / coller est un clic au lieu de deux.
Justin
@Justin Je ne peux tout simplement pas le faire fonctionner localement, même si je copie et colle les exemples (j'apporte des modifications minimales, par exemple la valeur de srcdans les balises de script). Je pense que leur documentation est jolie mais inefficace.
Gui Imamura
29

En 2018, voici comment vous y prendre:

async copySomething(text?) {
  try {
    const toCopy = text || location.href;
    await navigator.clipboard.writeText(toCopy);
    console.log('Text or Page URL copied');
  }
  catch (err) {
    console.error('Failed to copy: ', err);
  }
}

Il est utilisé dans mon code Angular 6+ comme ceci:

<button mat-menu-item (click)="copySomething()">
    <span>Copy link</span>
</button>

Si je passe une chaîne, il la copie. Si rien, il copie l'URL de la page.

On peut aussi faire plus de gymnastique dans le presse-papiers. Voir plus d'informations ici:

Débloquer l'accès au presse-papiers

KhoPhi
la source
vous êtes lié à localhost
Joe Warner
2
Veuillez noter que cela ne fonctionne pas dans Safari (version 11.1.2)
arjun27
1
@ arjun27 Eh bien, j'espère qu'un jour Apple rattrapera son retard. Bien que ce caniuse.com/#feat=clipboard montre que la version ci-dessus que vous avez mentionnée soit partiellement prise en charge.
KhoPhi
2
Je reçois pour les deux fonctions readText, writeText une promesse dans l'état rejeté
ramin
3
Selon le lien fourni, "navigator.clipboard n'est pris en charge que pour les pages diffusées via HTTPS"
TimH - Codidact
26

À partir d'un des projets sur lesquels j'ai travaillé, un plugin de copie vers presse-papiers jQuery qui utilise la bibliothèque Zero Clipboard .

Il est plus facile à utiliser que le plugin natif Zero Clipboard si vous êtes un gros utilisateur de jQuery.

SteamDev
la source
6
92kb n'est pas si gros que ça, ça marche vite et vous pouvez utiliser à la text()place de innerHTML()si vous le souhaitez ..
RozzA
17
@John: innerHTMLest compatible avec plusieurs navigateurs depuis longtemps. Tout simplement parce que Microsoft a eu l'idée à l'origine de ne pas la rendre non fiable ou propriétaire. Il est également maintenant enfin être ajouté à la spécification officielle (après tous les principaux fournisseurs de navigateur déjà ajouté le support pour elle ... soupir ).
James M. Greene
19
@John Vous vous plaignez que jQuery n'est pas assez JavaScript dans une réponse qui utilise Flash;)
Max Nanasy
4
innerHTML est meilleur que les alternatives dans la plupart des cas. Descend de tes grands chevaux! Il est plus rapide, plus efficace et ne nécessite pas de nouveau rendu de page.
orbite autour d'Eden
4
@RozzA 92KBest vraiment grand. Jusqu'à ce que le LTE arrive à maturité, GPRS est la norme de données mobiles WW , et il commence à 1 KB/s. Faites le calcul vous-même.
Tino
23

Depuis Chrome 42+ et Firefox 41+ prennent désormais en charge la commande document.execCommand ('copy') . J'ai donc créé deux fonctions pour une capacité copie à presse - papiers multi-navigateur utilisant une combinaison de vieille réponse de Tim vers le bas et la réponse de Google Developer :

function selectElementContents(el) {
    // Copy textarea, pre, div, etc.
    if (document.body.createTextRange) {
        // IE
        var textRange = document.body.createTextRange();
        textRange.moveToElementText(el);
        textRange.select();
        textRange.execCommand("Copy");
    } 
    else if (window.getSelection && document.createRange) {
        // Non-Internet Explorer
        var range = document.createRange();
        range.selectNodeContents(el);
        var sel = window.getSelection();
        sel.removeAllRanges();
        sel.addRange(range);
        try {
            var successful = document.execCommand('copy');
            var msg = successful ? 'successful' : 'unsuccessful';
            console.log('Copy command was ' + msg);
        }
        catch (err) {
            console.log('Oops, unable to copy');
        }
    }
} // end function selectElementContents(el)

function make_copy_button(el) {
    var copy_btn = document.createElement('input');
    copy_btn.type = "button";
    el.parentNode.insertBefore(copy_btn, el.nextSibling);
    copy_btn.onclick = function() {
        selectElementContents(el);
    };

    if (document.queryCommandSupported("copy") || parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2]) >= 42) {
        // Copy works with Internet Explorer 4+, Chrome 42+, Firefox 41+, Opera 29+
        copy_btn.value = "Copy to Clipboard";
    }
    else {
        // Select only for Safari and older Chrome, Firefox and Opera
        copy_btn.value = "Select All (then press Ctrl + C to Copy)";
    }
}
/* Note: document.queryCommandSupported("copy") should return "true" on browsers that support copy
    but there was a bug in Chrome versions 42 to 47 that makes it return "false".  So in those
    versions of Chrome feature detection does not work!
    See https://code.google.com/p/chromium/issues/detail?id=476508
*/

make_copy_button(document.getElementById("markup"));
<pre id="markup">
  Text that can be copied or selected with cross browser support.
</pre>

Jeff Baker
la source
Merci d'avoir résumé cela! Vous avez une petite erreur dans votre code: vous avez défini deux fois la variable "range" (var range = document.createRange ()).
Christian Engel
1
Vous avez raison @ChristianEngel. J'ai supprimé le deuxième. Je ne sais pas comment c'est arrivé là-dedans.
Jeff Baker
23

J'utilise cela avec beaucoup de succès ( sans jQuery ou tout autre framework).

function copyToClp(txt){
    txt = document.createTextNode(txt);
    var m = document;
    var w = window;
    var b = m.body;
    b.appendChild(txt);
    if (b.createTextRange) {
        var d = b.createTextRange();
        d.moveToElementText(txt);
        d.select();
        m.execCommand('copy');
    } 
    else {
        var d = m.createRange();
        var g = w.getSelection;
        d.selectNodeContents(txt);
        g().removeAllRanges();
        g().addRange(d);
        m.execCommand('copy');
        g().removeAllRanges();
    }
    txt.remove();
}

Attention

Les tabulations sont converties en espaces (au moins dans Chrome).

Sinistre
la source
Des espaces manquent dans cette approche
Bikram
1
Chrome. les tabulations sont converties en un espace
Bikram
22

J'ai trouvé la solution suivante:

Le gestionnaire de touches enfoncées crée une balise "pre". Nous définissons le contenu à copier dans cette balise, puis faisons une sélection sur cette balise et retournons true dans le gestionnaire. Cela appelle un gestionnaire standard de chrome et copie le texte sélectionné.

Et si vous en avez besoin, vous pouvez définir le délai d'expiration pour la fonction de restauration de la sélection précédente. Mon implémentation sur Mootools:

   function EnybyClipboard() {
     this.saveSelection = false;
     this.callback = false;
     this.pastedText = false;

     this.restoreSelection = function() {
       if (this.saveSelection) {
         window.getSelection().removeAllRanges();
         for (var i = 0; i < this.saveSelection.length; i++) {
           window.getSelection().addRange(this.saveSelection[i]);
         }
         this.saveSelection = false;
       }
     };

     this.copyText = function(text) {
       var div = $('special_copy');
       if (!div) {
         div = new Element('pre', {
           'id': 'special_copy',
           'style': 'opacity: 0;position: absolute;top: -10000px;right: 0;'
         });
         div.injectInside(document.body);
       }
       div.set('text', text);
       if (document.createRange) {
         var rng = document.createRange();
         rng.selectNodeContents(div);
         this.saveSelection = [];
         var selection = window.getSelection();
         for (var i = 0; i < selection.rangeCount; i++) {
           this.saveSelection[i] = selection.getRangeAt(i);
         }
         window.getSelection().removeAllRanges();
         window.getSelection().addRange(rng);
         setTimeout(this.restoreSelection.bind(this), 100);
       } else return alert('Copy not work. :(');
     };

     this.getPastedText = function() {
       if (!this.pastedText) alert('Nothing to paste. :(');
       return this.pastedText;
     };

     this.pasteText = function(callback) {
       var div = $('special_paste');
       if (!div) {
         div = new Element('textarea', {
           'id': 'special_paste',
           'style': 'opacity: 0;position: absolute;top: -10000px;right: 0;'
         });
         div.injectInside(document.body);
         div.addEvent('keyup', function() {
           if (this.callback) {
             this.pastedText = $('special_paste').get('value');
             this.callback.call(null, this.pastedText);
             this.callback = false;
             this.pastedText = false;
             setTimeout(this.restoreSelection.bind(this), 100);
           }
         }.bind(this));
       }
       div.set('value', '');
       if (document.createRange) {
         var rng = document.createRange();
         rng.selectNodeContents(div);
         this.saveSelection = [];
         var selection = window.getSelection();
         for (var i = 0; i < selection.rangeCount; i++) {
           this.saveSelection[i] = selection.getRangeAt(i);
         }
         window.getSelection().removeAllRanges();
         window.getSelection().addRange(rng);
         div.focus();
         this.callback = callback;
       } else return alert('Fail to paste. :(');
     };
   }

Usage:

enyby_clip = new EnybyClipboard(); //init 

enyby_clip.copyText('some_text'); // place this in CTRL+C handler and return true;

enyby_clip.pasteText(function callback(pasted_text) {
        alert(pasted_text);
}); // place this in CTRL+V handler and return true;

Sur coller, il crée une zone de texte et fonctionne de la même manière.

PS peut être cette solution peut être utilisée pour créer une solution entièrement multi-navigateur sans flash. Ses œuvres en FF et Chrome.

Enyby
la source
2
Quelqu'un a-t-il essayé cela? Cela ressemble à un truc astucieux, au cas où cela fonctionne vraiment sur une gamme de navigateurs!
Michael
1
jsfiddle.net/H2FHC Demo: fiddle.jshell.net/H2FHC/show Veuillez l'ouvrir et appuyer sur Ctrl + V ou Ctrl + C. Dans les fourches FF 19.0 parfaitement. Dans Chrome 25.0.1364.97 m aussi. Opera 12.14 - OK. Safari 5.1.7 pour Windows - OK. IE - ÉCHEC.
Enyby
Pour IE, exécutez le focus sur l'élément à l'intérieur de la page. Voir fiddle.jshell.net/H2FHC/3/show et fiddle.jshell.net/H2FHC/3 Travaillé dans IE 9/10. IE 6/7 a besoin que le processus crée la sélection d'une autre manière car document.createRange n'est pas pris en charge.
Enyby
21

Les autres méthodes copient du texte brut dans le presse-papiers. Pour copier HTML (c'est-à-dire que vous pouvez coller les résultats dans un éditeur WSIWYG), vous pouvez effectuer les opérations suivantes dans IE UNIQUEMENT . Ceci est fondamentalement différent des autres méthodes, car le navigateur sélectionne en fait visiblement le contenu.

// create an editable DIV and append the HTML content you want copied
var editableDiv = document.createElement("div");
with (editableDiv) {
    contentEditable = true;
}     
editableDiv.appendChild(someContentElement);          

// select the editable content and copy it to the clipboard
var r = document.body.createTextRange();
r.moveToElementText(editableDiv);
r.select();  
r.execCommand("Copy");

// deselect, so the browser doesn't leave the element visibly selected
r.moveToElementText(someHiddenDiv);
r.select();   
Chase Seibert
la source
voir la solution HTML plus complète ici stackoverflow.com/questions/34191780/…
kofifus
21

J'ai rassemblé ce que je pense être le meilleur.

  • Utilise cssText pour éviter les exceptions dans Internet Explorer par opposition au style directement.
  • Restaure la sélection s'il y en avait une
  • Définit en lecture seule pour que le clavier ne s'affiche pas sur les appareils mobiles
  • Contient une solution de contournement pour iOS afin qu'il fonctionne réellement car il bloque normalement execCommand.

C'est ici:

const copyToClipboard = (function initClipboardText() {
  const textarea = document.createElement('textarea');

  // Move it off screen.
  textarea.style.cssText = 'position: absolute; left: -99999em';

  // Set to readonly to prevent mobile devices opening a keyboard when
  // text is .select()'ed.
  textarea.setAttribute('readonly', true);

  document.body.appendChild(textarea);

  return function setClipboardText(text) {
    textarea.value = text;

    // Check if there is any content selected previously.
    const selected = document.getSelection().rangeCount > 0 ?
      document.getSelection().getRangeAt(0) : false;

    // iOS Safari blocks programmtic execCommand copying normally, without this hack.
    // /programming/34045777/copy-to-clipboard-using-javascript-in-ios
    if (navigator.userAgent.match(/ipad|ipod|iphone/i)) {
      const editable = textarea.contentEditable;
      textarea.contentEditable = true;
      const range = document.createRange();
      range.selectNodeContents(textarea);
      const sel = window.getSelection();
      sel.removeAllRanges();
      sel.addRange(range);
      textarea.setSelectionRange(0, 999999);
      textarea.contentEditable = editable;
    }
    else {
      textarea.select();
    }

    try {
      const result = document.execCommand('copy');

      // Restore previous selection.
      if (selected) {
        document.getSelection().removeAllRanges();
        document.getSelection().addRange(selected);
      }

      return result;
    }
    catch (err) {
      console.error(err);
      return false;
    }
  };
})();

Usage: copyToClipboard('some text')

Dominique
la source
13

Depuis Flash 10, vous ne pouvez copier dans le presse-papiers que si l'action provient d'une interaction de l'utilisateur avec un objet Flash. ( Lire la section connexe de l'annonce d'Adobe Flash 10 )

La solution est de surcharger un objet flash au-dessus du bouton Copier, ou tout élément qui lance la copie. Zero Clipboard est actuellement la meilleure bibliothèque avec cette implémentation. Les développeurs Flash expérimentés peuvent simplement vouloir créer leur propre bibliothèque.

matthuhiggins
la source
12

  <!DOCTYPE html>

  <style>
    #t {
      width: 1px
      height: 1px
      border: none
    }
    #t:focus {
      outline: none
    }
  </style>

  <script>
    function copy(text) {
      var t = document.getElementById('t')
      t.innerHTML = text
      t.select()
      try {
        var successful = document.execCommand('copy')
        var msg = successful ? 'successfully' : 'unsuccessfully'
        console.log('text coppied ' + msg)
      } catch (err) {
        console.log('Unable to copy text')
      }
      t.innerHTML = ''
    }
  </script>

  <textarea id=t></textarea>

  <button onclick="copy('hello world')">
    Click me
  </button>

Samuel Tees
la source
La meilleure réponse: D, vous pouvez l'améliorer avec quelque chose comme ceci: #t {position: absolue; gauche: 0; indice z: -900; largeur: 0px; hauteur: 0px; frontière: aucune; } Donc ça va être complètement caché! Mais merci vraiment frère!
Federico Navarrete
#t {resize: none;}
SmartManoj
Une explication serait de mise.
Peter Mortensen
12

J'ai trouvé la solution suivante:

J'ai le texte dans une entrée cachée. Étant donné que setSelectionRangecela ne fonctionne pas sur les entrées masquées, j'ai temporairement changé le type en texte, copié le texte, puis rendu à nouveau masqué. Si vous souhaitez copier le texte d'un élément, vous pouvez le passer à la fonction et enregistrer son contenu dans la variable cible.

jQuery('#copy').on('click', function () {
    copyToClipboard();
});

function copyToClipboard() {
    var target = jQuery('#hidden_text');

    // Make it visible, so can be focused
    target.attr('type', 'text');
    target.focus();
    // Select all the text
    target[0].setSelectionRange(0, target.val().length);

    // Copy the selection
    var succeed;
    try {
        succeed = document.execCommand("copy");
    }
    catch (e) {
        succeed = false;
    }

    // Hide input again
    target.attr('type', 'hidden');

    return succeed;
}
Vassilis Pallas
la source
11

Copiez le texte de l'entrée HTML dans le presse-papiers:

 function myFunction() {
   /* Get the text field */
   var copyText = document.getElementById("myInput");

   /* Select the text field */
   copyText.select();

   /* Copy the text inside the text field */
   document.execCommand("Copy");

   /* Alert the copied text */
   alert("Copied the text: " + copyText.value);
 }
 <!-- The text field -->
 <input type="text" value="Hello Friend" id="myInput">

 <!-- The button used to copy the text -->
<button onclick="myFunction()">Copy text</button>

Remarque: La document.execCommand()méthode n'est pas prise en charge dans Internet Explorer 9 et versions antérieures.

Source : W3Schools - Copier du texte dans le presse-papiers

Alexandru Sirbu
la source
11

Il existe déjà de nombreuses réponses, mais vous souhaitez en ajouter une (jQuery). Fonctionne très bien sur n'importe quel navigateur, également mobile (c'est-à-dire, les invites sur la sécurité, mais lorsque vous l'acceptez, cela fonctionne très bien).

function appCopyToClipBoard(sText)
{
    var oText = false,
        bResult = false;
    try
    {
        oText = document.createElement("textarea");
        $(oText).addClass('clipboardCopier').val(sText).insertAfter('body').focus();
        oText.select();
        document.execCommand("Copy");
        bResult = true;
    }
    catch(e) {
    }

    $(oText).remove();
    return bResult;
}

Dans votre code:

if (!appCopyToClipBoard('Hai there! This is copied to the clipboard.'))
{
    alert('Sorry, copy to clipboard failed.');
}
Codebeat
la source
9

C'est un peu une combinaison entre les autres réponses.

var copyToClipboard = function(textToCopy){
    $("body")
        .append($('<textarea name="fname" class="textToCopyInput"/>' )
        .val(textToCopy))
        .find(".textToCopyInput")
        .select();
      try {
        var successful = document.execCommand('copy');
        var msg = successful ? 'successful' : 'unsuccessful';
        alert('Text copied to clipboard!');
      } catch (err) {
          window.prompt("To copy the text to clipboard: Ctrl+C, Enter", textToCopy);
      }
     $(".textToCopyInput").remove();
}

Il utilise jQuery, mais ce n'est pas obligatoire bien sûr. Vous pouvez changer cela si vous le souhaitez. Je viens d'avoir jQuery à ma disposition. Vous pouvez également ajouter du CSS pour vous assurer que l'entrée ne s'affiche pas. Par exemple quelque chose comme:

.textToCopyInput{opacity: 0; position: absolute;}

Ou bien sûr, vous pouvez également faire un style en ligne

.append($('<textarea name="fname" style="opacity: 0;  position: absolute;" class="textToCopyInput"/>' )
Bart Burg
la source
Comment copier directement à partir d'une donnée variable .ie: var str = "word"; ?
Le msg variable n'est pas utilisé
Voyager le
Mieux vaut utiliser '<textarea class = "textToCopyInput" /> </textarea>' dans le cas où il textToCopycontient\n
Voyager
8

Dans les navigateurs autres que IE, vous devez utiliser un petit objet flash pour manipuler le presse-papiers, par exemple

Quog
la source
Ceci est obsolète maintenant ... consultez la suggestion de GvS
Mottie
6
La suggestion de GvS utilise un film flash? N'est-ce pas la même idée?
TheEmirOfGroofunkistan
8

J'ai eu le même problème pour créer une modification de grille personnalisée à partir (quelque chose comme Excel) et la compatibilité avec Excel. Je devais prendre en charge la sélection de plusieurs cellules, la copie et le collage.

Solution: créez une zone de texte dans laquelle vous allez insérer des données à copier par l'utilisateur (pour moi lorsque l'utilisateur sélectionne des cellules), placez-y le focus (par exemple, lorsque l'utilisateur appuie sur Ctrl) et sélectionnez tout le texte.

Ainsi, lorsque l'utilisateur appuie sur Ctrl+ Cil obtient des cellules copiées qu'il / elle sélectionne. Après avoir testé, il suffit de redimensionner la zone de texte à un pixel (je n'ai pas testé si cela fonctionnera à l'écran: aucun). Cela fonctionne bien sur tous les navigateurs et il est transparent pour l'utilisateur.

Coller - vous pouvez faire la même chose comme cela (diffère selon votre cible) - garder le focus sur les zones de texte et attraper les événements de collage en utilisant onpaste (dans mon projet, j'utilise des zones de texte dans les cellules pour les modifier).

Je ne peux pas coller d'exemple (projet commercial), mais vous avez l'idée.

xiniu
la source
7

J'ai utilisé clipboard.js.

Nous pouvons l'obtenir sur npm:

npm install clipboard --save

Et aussi sur Bower

bower install clipboard --save

L'utilisation et les exemples se trouvent sur https://zenorocha.github.io/clipboard.js/ .

CodecPM
la source
J'avais peur qu'il ne soit pas compatible avec le contenu dynamique, mais il l'est ;-) Je pense que c'est la meilleure solution, MAINTENANT, que l'ancienne 2008.
BENARD Patrick
6

Il s'agit d'une extension de la réponse de @ Chase, avec l'avantage qu'elle fonctionnera pour les éléments IMAGE et TABLE, pas seulement pour les DIV sur IE9.

if (document.createRange) {
    // IE9 and modern browsers
    var r = document.createRange();
    r.setStartBefore(to_copy);
    r.setEndAfter(to_copy);
    r.selectNode(to_copy);
    var sel = window.getSelection();
    sel.addRange(r);
    document.execCommand('Copy');  // does nothing on FF
} else {
    // IE 8 and earlier.  This stuff won't work on IE9.
    // (unless forced into a backward compatibility mode,
    // or selecting plain divs, not img or table). 
    var r = document.body.createTextRange();
    r.moveToElementText(to_copy);
    r.select()
    r.execCommand('Copy');
}
Oliver Bock
la source
5

Il semble que j'ai mal lu la question, mais pour référence, vous pouvez extraire une plage du DOM (pas dans le presse-papiers; compatible avec tous les navigateurs modernes), et le combiner avec les événements oncopy et onpaste et onbeforepaste pour obtenir le comportement du presse-papiers. Voici le code pour y parvenir:

function clipBoard(sCommand) {
  var oRange=contentDocument.createRange();
  oRange.setStart(startNode, startOffset);
  oRange.setEnd(endNode, endOffset);
/* This is where the actual selection happens.
in the above, startNode and endNode are dom nodes defining the beginning 
and end of the "selection" respectively. startOffset and endOffset are 
constants that are defined as follows:

END_TO_END: 2
END_TO_START: 3
NODE_AFTER: 1
NODE_BEFORE: 0
NODE_BEFORE_AND_AFTER: 2
NODE_INSIDE: 3
START_TO_END: 1
START_TO_START: 0

and would be used like oRange.START_TO_END */
      switch(sCommand) {
    case "cut":
          this.oFragment=oRange.extractContents();
      oRange.collapse();
      break;
    case "copy":
      this.oFragment=oRange.cloneContents();
      break;
    case "paste":
      oRange.deleteContents();
      var cloneFragment=this.oFragment.cloneNode(true)
      oRange.insertNode(cloneFragment);
      oRange.collapse();
      break;
  }
}
mrBorna
la source
1
en fait j'ai corrigé le code. Il fonctionne dans tous les navigateurs mais ne copie pas réellement dans le presse-papiers. Il suffit d'extraire (couper), de cloner (copier) le contenu via des variables. Il semble que j'en ai oublié l'usage.
mrBorna
5

Ma faute. Cela ne fonctionne que dans IE.

Voici encore une autre façon de copier du texte:

<p>
    <a onclick="window.clipboardData.setData('text', document.getElementById('Test').innerText);">Copy</a>
</p>
dvallejo
la source
9
Cela ne fonctionne pas dans Chrome (V31) ou FireFox (v25). L'erreur est que window.clipboardData n'est pas défini. Sur le plan positif, cela fonctionne dans IE9. Donc, tant que vous ne vous souciez pas des bons navigateurs et que vous souhaitez verrouiller votre site pour en utiliser de mauvais, c'est la façon pour vous de le faire!
Anthony
2
je ne comprends pas pourquoi tant de réponses stupides. w3schools.com/howto/tryit.asp?filename=tryhow_js_copy_clipboard
Martian2049
5

C'est la seule chose que j'ai jamais mise au travail, après avoir recherché diverses manières sur Internet. C'est un sujet compliqué. Il existe de nombreuses solutions publiées dans le monde et la plupart d'entre elles ne fonctionnent pas . Cela a fonctionné pour moi:

REMARQUE: ce code ne fonctionnera que lorsqu'il sera exécuté en tant que code synchrone direct vers quelque chose comme une méthode «onClick». Si vous appelez une réponse asynchrone à Ajax ou de toute autre manière asynchrone, cela ne fonctionnera pas.

copyToClipboard(text) {
    var copyText = document.createElement("input");
    copyText.type = "text";
    document.body.appendChild(copyText);
    copyText.style = "display: inline; width: 1px;";
    copyText.value = text;
    copyText.focus();
    document.execCommand("SelectAll");
    document.execCommand("Copy");
    copyText.remove();
}

Je me rends compte que ce code affichera un composant de 1 pixel de large visiblement à l'écran pendant une milliseconde, mais j'ai décidé de ne pas vous en soucier, ce que d'autres peuvent résoudre en cas de problème réel.

Peter Mortensen
la source
5

Pour copier un texte sélectionné («Texte à copier») dans votre presse-papiers, créez un Bookmarklet (signet du navigateur qui exécute JavaScript) et exécutez-le (cliquez dessus). Cela créera une zone de texte temporaire.

Code de GitHub:

https://gist.github.com/stefanmaric/2abf96c740191cda3bc7a8b0fc905a7d

(function (text) {
  var node = document.createElement('textarea');
  var selection = document.getSelection();

  node.textContent = text;
  document.body.appendChild(node);

  selection.removeAllRanges();
  node.select();
  document.execCommand('copy');

  selection.removeAllRanges();
  document.body.removeChild(node);
})('Text To Copy');
Mau
la source