Jak działa obraz wklejania ze schowka w Gmailu i Google Chrome 12+?

148

Zauważyłem post na blogu Google, w którym wspomniano o możliwości wklejania obrazów bezpośrednio ze schowka do wiadomości Gmaila, jeśli używasz najnowszej wersji Chrome. Wypróbowałem to z moją wersją Chrome (12.0.742.91 beta-m) i działa świetnie przy użyciu klawiszy sterowania lub menu kontekstowego.

Na podstawie tego zachowania muszę założyć, że najnowsza wersja zestawu webkit używanego w Chrome jest w stanie poradzić sobie z obrazami w zdarzeniu wklejania JavaScript, ale nie mogłem znaleźć żadnych odniesień do takiego ulepszenia. Uważam, że ZeroClipboard wiąże się ze zdarzeniami naciśnięcia klawisza, aby uruchomić swoją funkcję flashowania i jako taki nie działałby w menu kontekstowym (również ZeroClipboard jest cross-browser, a post mówi, że działa tylko z Chrome).

Jak więc to działa i gdzie wprowadzono ulepszenie do Webkita (lub Chrome), które zapewnia tę funkcjonalność?

Emil Lerch
źródło
3
Wygląda na to, że działa również losowo z Firefoksem. Czy ktoś wie, czy ma to być obsługiwane przez przeglądarkę Firefox?
Sébastien

Odpowiedzi:

231

Spędziłem trochę czasu eksperymentując z tym. Wygląda na to, że jest zgodny ze specyfikacją nowego interfejsu API schowka . Możesz zdefiniować procedurę obsługi zdarzenia „wklej”, spojrzeć na event.clipboardData.items i wywołać na nich getAsFile (), aby uzyskać obiekt Blob. Gdy masz już Bloba , możesz użyć na nim FileReadera , aby zobaczyć, co w nim jest. Oto jak możesz uzyskać adres URL danych dla rzeczy, które właśnie wkleiłeś w 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);
    }
  }
}

Gdy masz adres URL danych, możesz wyświetlić obraz na stronie. Jeśli zamiast tego chcesz go przesłać, możesz użyć readAsBinaryString lub umieścić go w XHR za pomocą FormData .

Nick Retallack
źródło
6
Ściskając się tutaj, ale masz jakieś pomysły, dlaczego event.clipboardData.items wydaje się być „niezdefiniowany” w Safari 5.1? A nawet jak zdobyć zawartość schowka dla pliku / obiektu blob w Safari? Działa świetnie w Chrome. Można by pomyśleć, że webkit to webkit :(
Gavin Gilmour
7
@SenicaGonzalez to dlatego, że dane istnieją tylko na czas trwania wydarzenia. Po wydarzeniu już go nie ma, więc kiedy spróbujesz otworzyć obiekt w inspektorze, nic nie zobaczysz.
Nick Retallack
3
uruchamiam to w przeglądarce Firefox i var blob = items [0] .getAsFile () throw TypeError: items is undefined
chinna_82
2
Czy mógłbyś zrobić przykład, jak przesłać XMLHttpRequest z danymi obrazu? To byłoby naprawdę miłe: D
poitroae
1
Oto jak możesz to zgłosić za pomocą XMLHttpRequest, napisałem to na blogu po tym, jak go zaimplementowałem: blog.securevideo.com/2013/11/27/…
JT Taylor
56

Odpowiedź Nicka wydaje się wymagać drobnych zmian, aby nadal działała :)

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

Przykładowy uruchomiony kod: http://jsfiddle.net/bt7BU/225/

Tak więc zmiana odpowiedzi na nicki brzmiała:

var items = event.clipboardData.items;

do

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

Musiałem również pobrać drugi element z wklejonych elementów (pierwszy wydaje się być tekstem / html, jeśli kopiujesz obraz z innej strony internetowej do bufora). Więc się zmieniłem

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

do pętli znajdującej element zawierający obraz (patrz wyżej)

Nie wiedziałem, jak odpowiedzieć bezpośrednio na odpowiedź Nicka, mam nadzieję, że jest w porządku: $ :)

robintibor
źródło
1
W jaki sposób powinniśmy przesłać dane obrazu jako XMLHttpRequest?
poitroae
Dla innych, którzy to czytają, odpowiedź na to pytanie może być tam teraz zawarta: stackoverflow.com/questions/18055422/… :)
robintibor
4
Nie rozumiem. Kiedy wklejam pliki w przeglądarce, clipboardData.itemsw Google Chrome jest zawsze puste (Firefox działa). Chrome potrzebuje teraz prawie takiej samej optymalizacji, jak kiedyś IE.
Tomáš Zato - Przywróć Monikę
1
Mała edycja: if (blob! = Null) {(lub ustaw blob = null podczas inicjalizacji)
Pancakeo
1
event.clipboardData.itemsdziałało dobrze dla mnie w najnowszym Chrome, nie wiesz, kiedy event.originalEvent...jest przydatny?
Ruben Martinez Jr.
5

Przeglądarki internetowe idą do przodu. Niedawno znalazłem to:

Fragment kodu - dostęp do obrazów schowka za pomocą JavaScript

i to:

The Paste Wasteland (lub dlaczego wydarzenie onPaste to bałagan)

Pierwszy link opisuje sposób uzyskiwania obrazów ze schowka przy użyciu JavaScript tylko w przeglądarkach Firefox i Chrome. Drugi link zawiera postscriptum, który wspomina o tej samej technice, która została dostosowana do IE (wersja nieznana).

Rich Apodaca
źródło
Firefox nawet nie aktywuje Edytuj | Wklej element menu dla mnie, więc w ogóle nie widzę, jak to działa w Firefoksie.
podperson
Żaden z tych linków nie działa w momencie komentowania.
Crazywako
2

Z tego co wiem -

Dzięki funkcjom HTML 5 (File Api i pokrewne) - dostęp do danych obrazu schowka jest teraz możliwy za pomocą zwykłego javascript.

To jednak nie działa w IE (mniej niż IE 10). Nie wiem też zbyt wiele o obsłudze IE10.

W przypadku IE optiens, które moim zdaniem są opcjami „rezerwowymi”, używają interfejsu Adobe AIR API lub podpisanego apletu

saurshaz
źródło
1

Wow, to super. Nie zagłębiłem się jeszcze w źródło Gmaila, aby to rozgryźć (zrobiłem to z funkcją przeciągania), ale zgaduję, że jest to rozszerzenie interfejsu API przeciągania / upuszczania, które Chrome już rozszerzył. Jest przyzwoity opis działania funkcji przeciągnij na pulpit: http://www.thecssninja.com/javascript/gmail-dragout, który może przynajmniej wskazać Ci właściwy kierunek.

Mark Kahn
źródło
0

To jest z przykładu z typem angular2, który działa dla mojego projektu. Mam nadzieję, że to komuś pomoże. Logika jest taka sama w innych przypadkach.

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

Oto implementacja na żywo:

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

Sandeep K Nair
źródło
1
Czy mógłbyś wyjaśnić, jaki proces przeszedłeś? Możesz otworzyć link https://stackblitz.com/edit/angular-f7kcny?file=app/app.component.tsw chrome, a następnie kliknąć prawym przyciskiem myszy obraz z dowolnej witryny internetowej. Następnie wklej go w podanym polu tekstowym. To powinno działać w ten sposób.
Sandeep K Nair
skopiowane z obrazów internetowych. Wypróbowałem obrazy z Eksploratora Windows, dlatego wtedy to nie działało. Czy znasz jakiś sposób na obsłużenie skopiowanego obrazu z eksploratora Windows w celu wklejenia go na stronę internetową?
Battle Hawk
Nie próbowałem jeszcze tej opcji. Mam nadzieję, że można dostać się spostrzeżeniami z tych bibliotek zamiast https://github.com/layerssss/paste.js/, https://github.com/JoelBesada/pasteboard. Pod tymi linkami dostępne są wersje demonstracyjne, które możesz wypróbować.
Sandeep K Nair
Event.clipboardData jest pusty, gdy wklejałem obraz na komputerach z systemem operacyjnym Windows. Czy ktoś może wyjaśnić, dlaczego tak się dzieje?
Tunç Doğan