Utiliser execCommand (Javascript) pour copier du texte caché dans le presse-papiers

J'essaie de copier dans le presse-papiers sans utiliser Flash, je prévois de revenir sur Flash avec l'utilisation de ZeroClipboard si le navigateur est incompatible avec l'approche javascript.

J'ai un écouteur onClick pour le bouton qui ressemble à:

$(buttonWhereActionWillBeTriggered).click(function(){ 
    var copyDiv = document.getElementById(inputContainingTextToBeCopied);
    copyDiv.focus();
    document.execCommand('SelectAll');
    document.execCommand("Copy", false, null);
}

Et un champ de saisie comme suit:

<input type="text" name="Element To Be Copied" id="inputContainingTextToBeCopied" value="foo"/>

Cela fonctionne actuellement comme prévu, mais la conception nécessite que le champ contenant le texte à copier soit invisible. J'ai essayé les deux paramètres type="hidden" et style="display: none" aucune n'a réussi. Les deux résultant dans le bouton en sélectionnant la page entière et en copiant tout le contenu dans le presse-papiers de l'utilisateur.
Je suis relativement confiant que la cause n'est pas basée sur un navigateur mais juste au cas où, je teste sur Chrome (Version 43.0.2357.134 (64-bit)) sur Mac OS X 10.10.4.

Existe-t-il un moyen de maintenir la fonctionnalité lorsque est visible tout en le cachant? ou si ce n'est pas un autre itinéraire que je peux prendre?


Je suis conscient de similaire des questions, dont aucune n'aborde mon problème, soit d'être trop vieux, ne pas utiliser réellement Javascript ou ne pas correspondre au scénario particulier. Voici une bonne réponse pour toute personne ayant des problèmes similaires, moins spécifiques.

23
demandé sur Community 2015-07-23 19:39:19

4 réponses

-- Mise à jour--

Document.execCommand()

[1] avant Firefox 41, la capacité du presse-papiers devait être activée dans l'utilisateur.fichier de préférence js. Voir un bref guide des préférences de Mozilla pour plus d'informations . Si la commande n'était pas prise en charge ou activée, execCommand déclenchait une exception au lieu de renvoyer false.In Firefox 41 et versions ultérieures, les capacités du presse-papiers sont activées par défaut dans tout gestionnaire d'événement capable de faire apparaître un fenêtre (scripts semi-approuvés).

Depuis Firefox version 41 Document.execCommand() fonctionne maintenant. Donc pas besoin d'utiliser un repli plus.


Puisque les navigateurs semblent se comporter différemment quand il s'agit de l'accès au presse-papiers, il m'a fallu un certain temps pour obtenir ma tête autour de lui.

C'est assez similaire à votre solution, mais la différence est de créer un élément temporaire et de le remplir avec l'Entrée value. De cette façon, nous pouvons conserver la propriété display de l'entrée défini sur none.

, Il est aussi une solution de contournement pour IE, qui utilise window.clipboardData.

Firefox ne me laisse pas accéder au presse-papier. J'ai donc dû ajouter un prompt pour permettre aux utilisateurs de copier manuellement la valeur d'entrée. Bien sûr, un prompt est moche, mais vous pouvez simplement utiliser une fenêtre modale, ce qui ferait la même chose.

Comme cela semble être une chose noueuse, je suis sur Win7 (64 bits) et testé dans

Chrome-Version 43.0.2357.134 m

IE - Version 11.0.9600.17914

et Firefox n'est pas pertinent, car il ne me laisserait pas y accéder de toute façon.

var copyBtn   = $("#copy-btn"),
    input     = $("#copy-me");

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

function copyToClipboard() {
  var success   = true,
      range     = document.createRange(),
      selection;

  // For IE.
  if (window.clipboardData) {
    window.clipboardData.setData("Text", input.val());        
  } else {
    // Create a temporary element off screen.
    var tmpElem = $('<div>');
    tmpElem.css({
      position: "absolute",
      left:     "-1000px",
      top:      "-1000px",
    });
    // Add the input value to the temp element.
    tmpElem.text(input.val());
    $("body").append(tmpElem);
    // Select temp element.
    range.selectNodeContents(tmpElem.get(0));
    selection = window.getSelection ();
    selection.removeAllRanges ();
    selection.addRange (range);
    // Lets copy.
    try { 
      success = document.execCommand ("copy", false, null);
    }
    catch (e) {
      copyToClipboardFF(input.val());
    }
    if (success) {
      alert ("The text is on the clipboard, try to paste it!");
      // remove temp element.
      tmpElem.remove();
    }
  }
}

copyBtn.on('click', copyToClipboard);
#copy-me {
    display:none
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" name="Element To Be Copied" id="copy-me" value="foo loves bar"/>
<button id="copy-btn">Copy</button><br/><br/>
<textarea placeholder="paste here"></textarea>
23
répondu DavidDomain 2016-08-15 07:42:34

Voici ma solution qui n'utilise pas jQuery:

function setClipboard(value) {
    var tempInput = document.createElement("input");
    tempInput.style = "position: absolute; left: -1000px; top: -1000px";
    tempInput.value = value;
    document.body.appendChild(tempInput);
    tempInput.select();
    document.execCommand("copy");
    document.body.removeChild(tempInput);
}
<!DOCTYPE html>
<html>
<head>
<title>Set Clipboard</title>
</head>
<body>
    <button onclick="setClipboard('foo loves bar')">Set Clipboard</button>
</body>
</html>
39
répondu Dan Stevens 2017-02-23 12:43:51

Grâce à l'aide de @ DavidDomain, j'ai trouvé une approche quelque peu hacky, mais fonctionnelle.

Tout d'abord, j'ai déplacé le chemin d'entrée hors de l'écran et modifié certaines propriétés, ce qui a donné ceci:

<input type="text" name="Element To Be Copied" id="inputContainingTextToBeCopied" value="foo" style="display:none; position: relative; left: -10000px;"/>

Affichage: Aucun n'a été ajouté après les modifications suivantes au js

Après cela, le commentaire de @ Pokkanome m'a permis de modifier la fonction onClick comme suit:

$(buttonWhereActionWillBeTriggered).click(function(){ 
    var copyDiv = document.getElementById(inputContainingTextToBeCopied);
    copyDiv.style.display = 'block';
    copyDiv.focus();
    document.execCommand('SelectAll');
    document.execCommand("Copy", false, null);
    copyDiv.style.display = 'none';
}

Je ne suis pas sûr s'il est possible de copier à partir d'un div caché en utilisant cette méthode, ce qui faire sens en termes de sécurité du navigateur comme donnant un accès incontesté au presse-papiers va être un peu risqué. L'approche adoptée a cependant eu le même résultat escompté.

15
répondu Aaron Critchley 2015-07-23 17:20:43

Voici une réponse facile, bien que hacky à cela qui semble fonctionner pour moi. Plutôt que d'utiliser display: none; Utilisez ceci:

height: 0px;
width: 0px;
overflow: hidden;
position: absolute;

Cela permet la sélection tout en masquant la zone de texte et sans affecter la conception.

-1
répondu Luke 2018-06-08 16:19:23