javascript couper/copier/coller dans le presse-papiers: comment fait Google le résoudre?

Oui, cette question a été posée encore et encore: comment copier et coller depuis et vers le presse-papiers système avec javascript? J'ai trouvé que des solutions partielles et hacks jusqu'à présent. La raison pour laquelle il a été demandé si souvent dans le passé est qu'il n'y a toujours pas de solution de travail. Cependant, j'ai vu que Google Docs a en fait une solution de travail maintenant pour les événements de clavier ainsi que les boutons. Donc, c'est possible, mais comment le font-ils? Logiciel salade article, accès au système Presse-papiers avec JavaScript - un saint Graal?, donne un bon aperçu du problème (mais il a quelques années).

En bref:

  • Vous pouvez utiliser les événements clavier ctrl + x, ctrl+c, ctrl+v pour copier du texte à partir d'une zone de texte cachée avec des données préparées, ou attraper du texte collé dans un champ caché, puis faire quelque chose avec

  • Vous pouvez utiliser un hack via Flash ou peut être une Applet Java pour copier quelque chose dans le presse papiers du système sans avoir besoin d'utilisateur approbation.

  • Vous pouvez utiliser une solution "réelle" avec clipboardData.setData pour IE et execCommand pour les autres navigateurs, qui dépend de l'approbation de l'utilisateur.

Une idée de la façon dont Google a abordé le problème du presse-papiers?

22
demandé sur Joshua Taylor 2012-03-11 23:43:57

5 réponses

[Note: Cette réponse était exacte au moment où elle a été écrite et répondait correctement à la question du PO. Cependant, la technologie a évolué depuis; si vous êtes intéressé à prendre en charge le copier-coller dans votre application web, veuillez consulter les autres réponses plus récentes sur cette page. - ruakh]


Cependant, j'ai vu que Google Docs a en fait une solution de travail maintenant pour les événements de clavier ainsi que les boutons.

Non, il ne le fait pas. Pas vraiment. Pour les événements clavier, Google Docs ne fait rien; il ne bloque tout simplement pas la fonction de copier-coller par défaut du navigateur; ainsi, les utilisateurs peuvent copier et coller librement sans que Google Docs ne gêne. Pour les boutons, Google Docs ne prend pas en charge le presse-papiers system, mais son propre "presse-papiers web" qui est entièrement dans Google Docs. Vous ne pouvez pas utiliser les boutons de la barre d'outils pour copier du texte à coller dans un autre programme de votre ordinateur ou pour coller du texte qui a été copié ordinateur.

Pour plus d'informations à ce sujet, consultez "copier et coller dans Google Docs". (C'est orienté utilisateur plutôt que développeur, mais il fait un travail décent en précisant ce qui est et n'est pas pris en charge.)

10
répondu ruakh 2016-02-11 17:20:03

Je sais que cette question a été postée il y a longtemps, mais je devais vérifier comment google le fait, alors peut-être que quelqu'un trouvera cela utile.

En fait, google utilise également le presse-papiers du système, mais c'est un peu délicat. Dans le cas où vous utilisez un raccourci clavier, vous pouvez attraper l'événement copier/coller/couper sur la fenêtre par exemple:

window.addEventListener('copy', function (ev) {
    console.log('copy event');
    // you can set clipboard data here, e.g.
    ev.clipboardData.setData('text/plain', 'some text pushed to clipboard');
    // you need to prevent default behaviour here, otherwise browser will overwrite your content with currently selected 
    ev.preventDefault();
});

Exemple en direct pour le raccourci clavier: http://jsfiddle.net/tyk9U/

Malheureusement, c'est seulement une solution pour le raccourci clavier et il y a un problème avec menu contextuel, car vous ne pouvez pas accéder aux données du presse-papiers sans l'événement copier/couper/coller natif (approuvé). Mais google fait astuce intéressante. Il y a API document.execCommand() qui vous permet d'exécuter des commandes pour l'élément contenteditable et il y a la commande 'copy' que vous pouvez déclencher via document.execCommand('copy'). Mais lorsque vous essayez cela dans la console dans Chrome, il retournera false. J'ai passé un peu de temps à enquêter sur cela et il s'est avéré qu'ils ont installé L'extension Chrome, appelée " Google Drive "(allez dans chrome://apps/ et vous pouvez le voir là) qui permet l'accès au presse-papiers pour les domaines drive.google.com et docs.google.com. ouvrez un document ou une feuille de calcul et tapez console document.execCommand('copy') - il retournera true. Lorsque vous désinstallez l'extension, vous ne pourrez pas utiliser les opérations du presse-papiers à partir du menu contextuel.

Vous pouvez créer une telle application pour vous-même avec un fichier manifeste très simple (détails ici https://developer.chrome.com/apps/first_app):

{
    "manifest_version": 2,
    "name": "App name",
    "description": "App description",
    "version": "1.0",
    "app": {
        "urls": [
            "http://your.app.url.here/"
        ],
        "launch": {
            "web_url": "http://your.app.url.here/"
        }
    },
    "icons": {
        "128": "x-128.png"
    },
    "permissions": [
        "clipboardRead",
        "clipboardWrite"
    ]
}

Le champ "autorisations" Active ici opérations de presse-papiers.

Maintenant, lorsque vous avez activé cela, vous pouvez faire document.execCommand('copy') et cela fonctionnera (retournera true). Mais ce n'est pas tout - document.execCommand('copy') dans chrome déclenche l'événement de copie et vous pouvez l'attraper avec le même code qui est utilisé pour attraper les raccourcis du presse-papiers du clavier. C'est maintenant Google le fait.

Bien sûr, cette description n'est valable que pour Chrome.

25
répondu Mateusz W 2015-05-04 23:47:04

En plus de ce que d'autres ont déjà posté dans ce fil, j'ai créé un exemple entièrement fonctionnel qui démontre l'approche de raccourci clavier (CTRL + C ou CMD + C sur Mac OS X) ainsi que l'approche de bouton personnalisé qui déclenche l'action de copie.

Démo Complète peut être trouvée ici: http://jsfiddle.net/rve7d/

J'ai trouvé Mateusz W answer très utile en essayant de créer cette démo mais il n'a pas pris en compte le support pour IE qui se comporte légèrement différent et utilise différents types de données comme premier paramètre.

if(window.clipboardData) {
    // use just 'Text' or 'Url' as a first param otherwise strange exception is thrown
    window.clipboardData.setData('Text', 'Text that will be copied to CB');        
} else if(ev.originalEvent.clipboardData) {
    ev.originalEvent.clipboardData.setData('text/plain', 'Text that will be copied to CB');      
} else {
    alert('Clipboard Data are not supported in this browser. Sorry.');
}

PS: j'avais besoin de cette fonctionnalité pour notre composant de vue de feuille de calcul personnalisée et j'ai analysé le code source de Google Spreadsheets afin que ma solution soit principalement conforme à leur solution.

4
répondu Marek Suscak 2014-06-25 15:57:18

Google utilise une méthode très simple mais cool. En utilisant firebug, vous apprendrez que le code html qui est chargé a une zone de texte en début de taille 1. Ce que google doc fait, c'est que lorsque l'utilisateur sélectionne du texte et appuie sur ctrl+c, il capture l'événement et, par une technique, obtient le texte sélectionné dans le conteneur doc et définit la valeur de la zone de texte à ce contenu. Qu'il se concentre, et sélectionne la zone de texte. Maintenant, il libère l'événement ctrl+C. Mais maintenant, le texte est sélectionné dans le texte donc, lorsque l'événement est realeased le navigateur copie le texte dans la zone de texte et nous obtenons ainsi le texte copié

3
répondu coder hacker 2013-04-13 13:25:12
<p>COPY : </p>
<p>Email me at <a class="js-emaillink" href="mailto:matt@example.co.uk">matt@example.co.uk</a></p>
<p><button class="js-emailcopybtn" value="clipboard" >clipboard</button></p>
<textarea rows="10" cols = "12"></textarea>
<p>CUT: </p>
<p><textarea class="js-cuttextarea">Hello I'm some text</textarea></p>
<p><button class="js-textareacutbtn" disable>Cut Textarea</button></p>
<script>
//copy clipboard
var copyEmailBtn = document.querySelector('.js-emailcopybtn');
copyEmailBtn.addEventListener('click', function(event) {
  // Выборка ссылки с электронной почтой
  var emailLink = document.querySelector('.js-emaillink');
  var range = document.createRange();
  range.selectNode(emailLink);
  window.getSelection().addRange(range);
  try {
    // Теперь, когда мы выбрали текст ссылки, выполним команду копирования
    var successful = document.execCommand('copy');
    var msg = successful ? 'successful' : 'unsuccessful';
    console.log('Copy email command was ' + msg);
  } catch(err) {
    console.log('Oops, unable to copy');
  }
  // Снятие выделения - ВНИМАНИЕ: вы должны использовать
  // removeRange(range) когда это возможно
  window.getSelection().removeAllRanges();
});
//cut
var cutTextareaBtn = document.querySelector('.js-textareacutbtn');
cutTextareaBtn.addEventListener('click', function(event) {
  var cutTextarea = document.querySelector('.js-cuttextarea');
  cutTextarea.select();
  try {
    var successful = document.execCommand('cut');
    var msg = successful ? 'successful' : 'unsuccessful';
    console.log('Cutting text command was ' + msg);
  } catch(err) {
    console.log('Oops, unable to cut');
  }
});
</script>
0
répondu zloctb 2018-01-19 18:44:31