Comment fonctionne la fonctionnalité Coller l'image à partir du presse-papiers dans Gmail et Google Chrome 12+?

148

J'ai remarqué un article de blog de Google qui mentionne la possibilité de coller des images directement à partir du presse-papiers dans un message Gmail si vous utilisez la dernière version de Chrome. J'ai essayé cela avec ma version de Chrome (12.0.742.91 beta-m) et cela fonctionne très bien en utilisant les touches de contrôle ou le menu contextuel.

À partir de ce comportement, je dois supposer que la dernière version du kit Web utilisée dans Chrome est capable de traiter les images dans l'événement de collage Javascript, mais je n'ai pas pu localiser de références à une telle amélioration. Je pense que ZeroClipboard se lie aux événements de pression de touche pour déclencher sa fonctionnalité flash et, en tant que tel, ne fonctionnerait pas via le menu contextuel (également, ZeroClipboard est multi-navigateur et l'article dit que cela ne fonctionne qu'avec Chrome).

Alors, comment cela fonctionne-t-il et où l'amélioration a été apportée à Webkit (ou Chrome) qui active la fonctionnalité?

Emil Lerch
la source
3
Il semble que cela fonctionne également de manière aléatoire avec Firefox. Quelqu'un sait si cela est censé être pris en charge avec Firefox?
Sébastien

Réponses:

231

J'ai passé un certain temps à expérimenter cela. Il semble en quelque sorte suivre la nouvelle spécification de l'API Clipboard . Vous pouvez définir un gestionnaire d'événement "coller" et consulter event.clipboardData.items, et appeler getAsFile () sur eux pour obtenir un Blob. Une fois que vous avez un objet blob, vous pouvez utiliser FileReader dessus pour voir ce qu'il contient . Voici comment obtenir une URL de données pour les éléments que vous venez de coller dans Chrome:

// window.addEventListener('paste', ... or
document.onpaste = function(event){
  var items = (event.clipboardData || event.originalEvent.clipboardData).items;
  console.log(JSON.stringify(items)); // will give you the mime types
  for (index in items) {
    var item = items[index];
    if (item.kind === 'file') {
      var blob = item.getAsFile();
      var reader = new FileReader();
      reader.onload = function(event){
        console.log(event.target.result)}; // data url!
      reader.readAsDataURL(blob);
    }
  }
}

Une fois que vous avez une URL de données, vous pouvez afficher l'image sur la page. Si vous souhaitez le télécharger à la place, vous pouvez utiliser readAsBinaryString, ou vous pouvez le placer dans un XHR à l'aide de FormData .

Nick Retallack
la source
6
Vous ne savez pas pourquoi event.clipboardData.items semble être «indéfini» dans Safari 5.1? Ou même comment obtenir le contenu du presse-papiers pour un fichier / objet blob dans Safari? Fonctionne très bien dans Chrome. Vous penseriez que le webkit serait le webkit :(
Gavin Gilmour
7
@SenicaGonzalez c'est parce que les données n'existent que pour la durée de l'événement. Après l'événement, il a disparu, donc lorsque vous essayez d'ouvrir l'objet dans l'inspecteur, vous ne verrez rien.
Nick Retallack
3
je lance ceci sur Firefox et var blob = items [0] .getAsFile () throw TypeError: items is undefined
chinna_82
2
Pourriez-vous donner un exemple sur la manière de soumettre une requête XMLHttpRequest avec ces données d'image? Ce serait vraiment bien: D
poitroae
1
Voici comment vous pouvez soumettre qu'en utilisant XMLHttpRequest, je l'ai écrit dans un blog après l'avoir implémenté: blog.securevideo.com/2013/11/27
JT Taylor
56

La réponse de Nick semble avoir besoin de petits changements pour fonctionner encore :)

// window.addEventListener('paste', ... or
document.onpaste = function (event) {
  // use event.originalEvent.clipboard for newer chrome versions
  var items = (event.clipboardData  || event.originalEvent.clipboardData).items;
  console.log(JSON.stringify(items)); // will give you the mime types
  // find pasted image among pasted items
  var blob = null;
  for (var i = 0; i < items.length; i++) {
    if (items[i].type.indexOf("image") === 0) {
      blob = items[i].getAsFile();
    }
  }
  // load image if there is a pasted image
  if (blob !== null) {
    var reader = new FileReader();
    reader.onload = function(event) {
      console.log(event.target.result); // data url!
    };
    reader.readAsDataURL(blob);
  }
}

Exemple de code en cours d'exécution: http://jsfiddle.net/bt7BU/225/

Donc, les changements apportés aux pseudos ont été:

var items = event.clipboardData.items;

à

var items = (event.clipboardData  || event.originalEvent.clipboardData).items;

J'ai également dû prendre le deuxième élément des éléments collés (le premier semble être du texte / html si vous copiez une image d'une autre page Web dans le tampon). Alors j'ai changé

  var blob = items[0].getAsFile();

vers une boucle trouvant l'élément contenant l'image (voir ci-dessus)

Je ne savais pas comment répondre directement à la réponse de Nick, j'espère que tout va bien ici: $ :)

robintibor
la source
1
Comment devons-nous soumettre les données d'image en tant que XMLHttpRequest?
poitroae
Pour les autres lisant ceci, la réponse à cette question peut être incluse ici maintenant: stackoverflow.com/questions/18055422/… :)
robintibor
4
Je ne comprends pas. Lorsque je colle des fichiers dans le navigateur, le clipboardData.itemsest toujours vide dans Google Chrome (Firefox fonctionne). Le chrome nécessite maintenant presque autant d'optimisation qu'avant.
Tomáš Zato - Réintégrer Monica
1
Petite modification: if (blob! = Null) {(ou set blob = null lors de l'initialisation)
Pancakeo
1
event.clipboardData.itemsa bien fonctionné pour moi sur la dernière version de Chrome, je ne sais pas quand event.originalEvent...est-ce utile?
Ruben Martinez Jr.
5

Les navigateurs Web continuent d'avancer. J'ai récemment trouvé ceci:

Extrait de code - Accéder aux images du presse-papiers avec Javascript

et ça:

The Paste Wasteland (ou, pourquoi l'événement onPaste est un gâchis)

Le premier lien décrit un moyen d'obtenir des images de presse-papiers en utilisant JavaScript uniquement sur Firefox et Chrome. Le deuxième lien contient un post-scriptum qui mentionne que la même technique a été adaptée à IE (version inconnue).

Rich Apodaca
la source
Firefox n'active même pas le Modifier | Collez l'élément de menu pour moi, donc je ne vois pas du tout comment cela fonctionne dans Firefox.
podperson
Aucun de ces liens ne fonctionne au moment du commentaire.
Crazywako
2

Pour autant que je sache -

Avec les fonctionnalités HTML 5 (File Api et les éléments associés) - l'accès aux données d'image du presse-papiers est désormais possible avec du javascript brut.

Cela ne fonctionne cependant pas sur IE (rien de moins que IE 10). Je ne sais pas grand-chose sur le support IE10 également.

Pour IE, les optiens que je crois être les options de `` secours '' utilisent soit l'API AIR d'Adobe, soit une applet signée

saurshaz
la source
1

Wow, c'est cool. Je n'ai pas encore plongé dans la source gmail pour le comprendre (je l'ai fait avec la fonctionnalité de glisser-déposer), mais je suppose que c'est une extension de l'API glisser / déposer que Chrome a déjà étendue. Il y a un article décent sur le fonctionnement de la fonction glisser vers le bureau: http://www.thecssninja.com/javascript/gmail-dragout qui peut au moins vous orienter dans la bonne direction.

Mark Kahn
la source
0

Ceci est d'un exemple avec le typographie angular2 qui fonctionne pour mon projet. J'espère que ça aide quelqu'un. La logique est la même pour les autres cas également.

https://gist.github.com/sandeepsuvit/a8ba77faebba260455985504be24aef7

Voici une implémentation en direct:

https://stackblitz.com/edit/angular-f7kcny?file=app/app.component.ts

Sandeep K Nair
la source
1
Pouvez-vous expliquer quel processus avez-vous suivi? Vous pouvez ouvrir le lien https://stackblitz.com/edit/angular-f7kcny?file=app/app.component.tsdans Chrome, puis cliquer avec le bouton droit sur une image de n'importe quel site Web. Puis collez-le dans la zone de texte fournie. Cela devrait fonctionner de cette façon.
Sandeep K Nair
copié à partir de l'image Web fonctionne. J'ai essayé des images de l'explorateur Windows, c'est pourquoi cela ne fonctionnait pas à l'époque. Connaissez-vous un moyen de gérer l'image copiée à partir de l'explorateur Windows pour la coller sur la page Web ?.
Battle Hawk
Je n'ai pas encore essayé cette option. Nous espérons que vous pouvez obtenir un aperçu de ces bibliothèques au lieu https://github.com/layerssss/paste.js/, https://github.com/JoelBesada/pasteboard. Il existe des démos disponibles sur ces liens que vous pouvez essayer.
Sandeep K Nair
event.clipboardData est vide lorsque j'ai collé une image sur des machines du système d'exploitation Windows. Est-ce que quelqu'un peut expliquer pourquoi cela se produit?
Tunç Doğan