Como a imagem da funcionalidade colar da área de transferência funciona no Gmail e no Google Chrome 12+?

148

Percebi uma postagem de blog do Google que menciona a capacidade de colar imagens diretamente da área de transferência em uma mensagem do Gmail se você estiver usando a versão mais recente do Chrome. Eu tentei isso com a minha versão do Chrome (12.0.742.91 beta-m) e funciona muito bem usando as teclas de controle ou o menu de contexto.

Com base nesse comportamento, devo assumir que a versão mais recente do webkit usada no Chrome é capaz de lidar com imagens no evento de colar Javascript, mas não consegui localizar nenhuma referência a esse aprimoramento. Acredito que o ZeroClipboard se liga a eventos de pressionamento de tecla para acionar sua funcionalidade de flash e, como tal, não funcionaria no menu de contexto (também, o ZeroClipboard é cross-browser e a publicação diz que isso funciona apenas com o Chrome).

Então, como isso funciona e onde o aprimoramento foi feito no Webkit (ou Chrome) que habilita a funcionalidade?

Emil Lerch
fonte
3
Parece que ele funciona aleatoriamente com o Firefox também. Alguém sabe se isso é suportado pelo Firefox?
Sébastien

Respostas:

231

Passei algum tempo experimentando isso. Parece seguir a nova especificação da API da área de transferência . Você pode definir um manipulador de eventos "colar" e consultar event.clipboardData.items e chamar getAsFile () para obter um Blob. Depois de ter um Blob, você pode usar o FileReader para ver o que há nele. É assim que você pode obter um URL de dados para as coisas que você acabou de colar no 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);
    }
  }
}

Depois de ter um URL de dados, você pode exibir a imagem na página. Se você quiser fazer o upload, poderá usar readAsBinaryString ou colocá-lo em um XHR usando FormData .

Nick Retallack
fonte
6
Segurando palhinhas aqui, mas alguma idéia de por que event.clipboardData.items parece estar "indefinido" no Safari 5.1? Ou mesmo como obter o conteúdo da área de transferência para um arquivo / blob no Safari? Funciona muito bem no Chrome. Você pensaria que o webkit seria o webkit :(
Gavin Gilmour
7
@SenicaGonzalez é porque os dados existem apenas durante o evento. Após o evento desaparecer, portanto, ao tentar abrir o objeto no inspetor, você não verá nada.
Nick Retallack
3
i executar este no Firefox e var blob = itens [0] .getAsFile () jogue TypeError: itens é indefinido
chinna_82
2
Você se importaria em fazer um exemplo de como enviar um XMLHttpRequest com esses dados de imagem? Isso seria muito bom: D
poitroae
1
Aqui está como você pode enviar isso usando XMLHttpRequest, escrevi em um blog depois de implementá-lo: blog.securevideo.com/2013/11/27/…
JT Taylor
56

A resposta de Nick parece precisar de pequenas alterações para continuar funcionando :)

// 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);
  }
}

Exemplo de código em execução: http://jsfiddle.net/bt7BU/225/

Portanto, as mudanças nas respostas de nicks foram:

var items = event.clipboardData.items;

para

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

Também tive que pegar o segundo elemento dos itens colados (o primeiro parece ser text / html se você copiar uma imagem de outra página da web no buffer). Então eu mudei

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

para um loop localizando o item que contém a imagem (veja acima)

Eu não sabia como responder diretamente à resposta de Nick, espero que esteja bem aqui: $ :)

robintibor
fonte
1
Como devemos enviar os dados da imagem como XMLHttpRequest?
precisa saber é
Para os outros que lêem este, a resposta a esta pergunta pode ser incluído lá agora: stackoverflow.com/questions/18055422/... :)
robintibor
4
Eu não entendo Quando colo arquivos no navegador, ele clipboardData.itemsestá sempre vazio no google chrome (o Firefox funciona). O chrome agora precisa quase da mesma otimização que o IE costumava.
Tomáš Zato - Restabelece Monica
1
Edição
1
event.clipboardData.itemsfuncionou bem para mim no Chrome mais recente, não sabe quando event.originalEvent...é útil?
Ruben Martinez Jr.
5

Os navegadores da Web continuam avançando. Eu encontrei recentemente isso:

Snippet de código - Acessando imagens da área de transferência com Javascript

e isto:

Paste Wasteland (ou, por que o evento onPaste está uma bagunça)

O primeiro link descreve uma maneira de obter imagens da área de transferência usando JavaScript apenas no Firefox e Chrome. O segundo link contém um postscript que menciona a mesma técnica foi adaptada ao IE (versão desconhecida).

Rich Apodaca
fonte
O Firefox nem ativa o Edit | Cole o item de menu para mim, para não ver como ele funciona no Firefox.
podperson
Qualquer um desses links não funciona no momento dos comentários.
Crazywako 12/03
2

Até onde sei -

Com os recursos HTML 5 (File Api e os relacionados) - agora é possível acessar dados de imagem da área de transferência com javascript comum.

No entanto, isso não funciona no IE (nada menos que o IE 10). Também não sei muito sobre o suporte ao IE10.

Para o IE, as opções que acredito serem as opções de "fallback" estão usando a API do Adobe AIR ou usando um applet assinado

saurshaz
fonte
1

Uau isso é legal. Ainda não mergulhei na fonte do Gmail para descobrir isso (fiz com a funcionalidade de arrastar), mas acho que é uma extensão da API de arrastar / soltar que o chrome já estendeu. Há uma descrição decente sobre como o recurso de arrastar para a área de trabalho funciona: http://www.thecssninja.com/javascript/gmail-dragout que pode pelo menos apontar você na direção certa.

Mark Kahn
fonte
0

Isto é de um exemplo com texto datilografado angular2 que funciona para o meu projeto. Espero que ajude alguém. A lógica é a mesma para outros casos também.

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

Aqui está uma implementação ao vivo:

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

Sandeep K Nair
fonte
1
Você poderia, por favor, explicar qual processo seguiu? Você pode abrir o link https://stackblitz.com/edit/angular-f7kcny?file=app/app.component.tsno chrome e clicar com o botão direito do mouse em uma imagem de qualquer site. Em seguida, cole-o na caixa de texto fornecida. Deveria funcionar assim.
Sandeep K Nair
copiado de obras de imagem da web. Tentei imagens do Windows Explorer, por isso não estava funcionando. Você conhece alguma maneira de lidar com a imagem copiada do Windows Explorer para colá-la na página da Web ?.
Battle Hawk
Ainda não tentei esta opção. Esperamos que você pode obter insights de essas bibliotecas em vez https://github.com/layerssss/paste.js/, https://github.com/JoelBesada/pasteboard. Existem demos disponíveis nesses links que você pode experimentar.
Sandeep K Nair
event.clipboardData está vazio quando colei a imagem em máquinas com sistema operacional Windows. Alguém pode explicar por que isso acontece?
Tunç Doğan