JavaScript cut / copy / paste to clipboard: jak Google go rozwiązać?

Tak, to pytanie było zadawane wielokrotnie: jak kopiować i wklejać ze schowka systemowego i do niego za pomocą javascript? Do tej pory znalazłem tylko częściowe rozwiązania i hacki. Powodem, dla którego pytano go tak często w przeszłości, jest to, że nadal nie ma działającego rozwiązania. Jednak zobaczyłem, że Google Docs rzeczywiście ma teraz rozwiązanie robocze dla obu zdarzeń klawiatury, a także przycisków. Jest to więc możliwe, ale jak oni to robią? Artykuł o oprogramowaniu, dostęp do systemu Schowek z JavaScript-Święty Graal?, daje ładny przegląd problemu (ale to kilka lat).

W skrócie:

  • Możesz użyć zdarzeń klawiatury ctrl + x, ctrl + C, ctrl + v, aby skopiować tekst z ukrytej strefy tekstowej z przygotowanymi danymi lub złapać wklejony tekst w ukrytym polu, a następnie coś z nim zrobić

  • Można użyć jakiegoś hack przez Flash lub może aplet Java skopiować coś do schowka systemowego bez potrzeby użytkownika zgoda.

  • Możesz użyć "rzeczywistego" rozwiązania z clipboardData.setData dla IE i execCommand dla innych przeglądarek, co zależy od zgody użytkownika.

Jakiś pomysł jak Google rozwiązało problem ze schowkiem?

Author: Joshua Taylor, 2012-03-11

5 answers

[Uwaga: Ta odpowiedź była dokładna w momencie pisania i prawidłowo odpowiedziała na pytanie OP. Jednak od tego czasu technologia ewoluowała; jeśli jesteś zainteresowany obsługą kopiowania i wklejania w swojej aplikacji internetowej, zapoznaj się z innymi, nowszymi odpowiedziami na tej stronie. - ruakh]


Jednak widziałem, że Google Docs rzeczywiście ma rozwiązanie pracy teraz zarówno dla zdarzeń klawiatury, jak i przycisków.

Nie, wcale nie. Dla zdarzeń klawiatury, Google Docs nic nie robi; po prostu nie blokuje domyślnej funkcji kopiowania i wklejania przeglądarki; więc użytkownicy mogą kopiować i wklejać swobodnie bez Google Docs wchodząc w drogę. W przypadku przycisków Google Docs nie obsługuje schowka System, ale jego własny "Schowek internetowy", który jest całkowicie w Google Docs. Nie można użyć przycisków paska narzędzi, aby skopiować tekst do wklejenia do innego programu na komputerze lub wkleić tekst skopiowany z innego programu na komputerze komputer.

Aby uzyskać więcej informacji na ten temat, zobacz "kopiowanie i wklejanie w Dokumentach Google" . (To jest zorientowane na użytkownika, a nie dewelopera, ale robi przyzwoitą pracę, wyjaśniając, co jest i nie jest obsługiwane.)

 10
Author: ruakh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-11 17:20:03

Wiem, że to pytanie było napisane dawno temu, ale musiałem sprawdzić, jak google to robi, więc może komuś się to przyda.

Właściwie google używa również schowka systemowego, ale jest to trochę trudne. W przypadku użycia skrótu klawiaturowego można przechwycić Zdarzenie kopiuj / wklej/wytnij na np. window:

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

Przykład na żywo skrótu klawiaturowego: http://jsfiddle.net/tyk9U/

Niestety jest to jedyne rozwiązanie dla skrótów klawiaturowych i jest problem z menu kontekstowe, ponieważ nie można uzyskać dostępu do danych schowka bez natywnego (zaufanego) zdarzenia Kopiuj/wytnij/wklej. Ale google robi ciekawe sztuczki. Istnieje API document.execCommand(), które pozwala na uruchamianie poleceń dla elementu contenteditable oraz polecenie 'copy', które można uruchomić za pomocą document.execCommand('copy'). Ale gdy spróbujesz tego w konsoli w Chrome zwróci false. Spędziłem trochę czasu badając to i okazało się, że mają zainstalowane rozszerzenie Chrome, o nazwie "Dysk Google" (przejdź do chrome://aplikacje/ i można go tam zobaczyć), który umożliwia dostęp do schowka dla domen drive.google.com oraz docs.google.com. Otwórz jakiś dokument lub arkusz kalkulacyjny i wpisz w konsoli document.execCommand('copy') - zwróci true. Po odinstalowaniu rozszerzenia nie będzie można używać operacji schowka z menu kontekstowego.

Możesz stworzyć taką aplikację dla siebie za pomocą bardzo prostego pliku manifestu (szczegóły tutaj 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"
    ]
}

Pole" uprawnienia " umożliwia operacje schowka.

Teraz, gdy masz to włączone, możesz zrobić document.execCommand('copy') i będzie działać (zwróci true). Ale to nie wszystko - document.execCommand('copy') w chrome uruchamia Zdarzenie copy i można go złapać za pomocą tego samego kodu, który jest używany do przechwytywania skrótów klawiatury schowka. To jest teraz Google robi to.

Oczywiście ten opis jest ważny tylko dla Chrome.

 25
Author: Mateusz W,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-04 23:47:04

Jako dodatek do tego, co inni już opublikowali w tym wątku, stworzyłem w pełni działający przykład, który demonstruje podejście do skrótów klawiaturowych (CTRL + C lub CMD + c na Mac OS X), a także niestandardowe podejście do przycisków, które uruchamia akcję kopiowania.

Pełne demo można znaleźć tutaj: http://jsfiddle.net/rve7d/

Znalazłem Mateusz W odpowiedzi bardzo przydatne podczas próby stworzenia tego demo, ale nie wziął pod uwagę wsparcia dla IE, który zachowuje się nieco inaczej i używa różnych typów danych jako pierwszego parametru.

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: potrzebowałem tej funkcjonalności dla naszego komponentu widoku arkusza kalkulacyjnego i po drodze analizowałem kod źródłowy arkuszy kalkulacyjnych Google, więc moje rozwiązanie jest w większości zgodne z ich rozwiązaniem.

 4
Author: Marek Suscak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-25 15:57:18

Google używa bardzo prostej, ale fajnej metody. Używając firebug dowiesz się, że załadowany kod html ma obszar tekstowy na początku rozmiaru 1. To, co robi google doc, to to, że gdy użytkownik wybiera tekst i naciska ctrl + c, przechwytuje Zdarzenie i jakimś sposobem pobiera tekst, który jest zaznaczony w kontenerze doc i ustawia wartość obszaru tekstowego na tę zawartość. Następnie skupia się i zaznacza obszar tekstu. Teraz zwalnia Zdarzenie ctrl + C. Ale teraz tekst jest zaznaczony w tekście obszar więc gdy zdarzenie jest realeased przeglądarka kopiuje tekst w obszarze tekstowym i w ten sposób otrzymujemy skopiowany tekst

 3
Author: coder hacker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-13 13:25:12
<p>COPY : </p>
<p>Email me at <a class="js-emaillink" href="mailto:[email protected]">[email protected]</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
Author: zloctb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-19 18:44:31