Jak skopiować do schowka w JavaScript?

3316

Jaki jest najlepszy sposób na skopiowanie tekstu do schowka? (wiele przeglądarek)

Próbowałem:

function copyToClipboard(text) {
    if (window.clipboardData) { // Internet Explorer
        window.clipboardData.setData("Text", text);
    } else {  
        unsafeWindow.netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");  
        const clipboardHelper = Components.classes["@mozilla.org/widget/clipboardhelper;1"].getService(Components.interfaces.nsIClipboardHelper);  
        clipboardHelper.copyString(text);
    }
}

ale w Internet Explorerze daje błąd składniowy. W Firefoksie jest napisane unsafeWindow is not defined.

Fajna sztuczka bez flasha: w jaki sposób Trello uzyskuje dostęp do schowka użytkownika?

Santiago Corredoira
źródło
Ciekawe, co chcesz skopiować do schowka, czego użytkownik nie może zrobić sam?
scunliffe
233
Nic specjalnego. Mogą to zrobić sami, ale chcę również zaoferować możliwość kliknięcia przycisku bez obawy o wybranie właściwej części tekstu.
Santiago Corredoira,
4
Ten długi post na blogu zawiera wiele sposobów: Dostęp do schowka systemowego za pomocą JavaScript - Święty Graal?
Aaron Digulla
Daje ona nieokreślony wyjątek dla przeglądarki zarówno w IE, jak i FF
Jagadeesh
1
Jeśli umieścimy tekst w schowku użytkownika, możemy zniszczyć jego schowek.
Frank Fang

Odpowiedzi:

2240

Przegląd

Istnieją trzy podstawowe interfejsy API przeglądarki do kopiowania do schowka:

  1. Asynchroniczny interfejs API schowka [navigator.clipboard.writeText]
    • Część tekstowa dostępna w Chrome 66 (marzec 2018)
    • Dostęp jest asynchroniczny i korzysta z obietnic JavaScript , można je zapisać, aby monity użytkowników zabezpieczeń (jeśli są wyświetlane) nie przerywały JavaScript na stronie.
    • Tekst można skopiować do schowka bezpośrednio ze zmiennej.
    • Obsługiwane tylko na stronach obsługiwanych przez HTTPS.
    • W Chrome 66 stron w aktywnych kartach może pisać do schowka bez monitu o uprawnienia.
  2. document.execCommand('copy')
    • Większość przeglądarek obsługuje to od ~ kwietnia 2015 r. (Patrz Obsługa przeglądarki poniżej).
    • Dostęp jest synchroniczny, tzn. Zatrzymuje JavaScript na stronie, dopóki nie zostanie zakończony, włączając wyświetlanie i interakcję użytkownika z wszelkimi monitami bezpieczeństwa.
    • Tekst jest odczytywany z DOM i umieszczany w schowku.
    • Podczas testowania ~ kwietnia 2015 r. Tylko Internet Explorer odnotował wyświetlanie monitów o uprawnienia podczas pisania do schowka.
  3. Przesłanianie zdarzenia kopiowania
    • Zobacz dokumentację API schowka na temat zastępowania zdarzenia kopiowania .
    • Pozwala modyfikować to, co pojawia się w schowku z dowolnego zdarzenia kopiowania, może obejmować inne formaty danych inne niż zwykły tekst.
    • Nie omówione tutaj, ponieważ nie odpowiada bezpośrednio na pytanie.

Ogólne uwagi dotyczące rozwoju

Nie oczekuj, że polecenia związane ze schowkiem będą działać podczas testowania kodu w konsoli. Zasadniczo strona musi być aktywna (Async Clipboard API) lub wymaga interakcji użytkownika (np. Kliknięcia użytkownika), aby umożliwić ( document.execCommand('copy')) dostęp do schowka, patrz poniżej, aby uzyskać więcej szczegółów.

WAŻNE (odnotowano tutaj 2020/02/20)

Zauważ, że ponieważ ten post został pierwotnie napisany, wycofanie uprawnień w IFRAME pochodzących z różnych źródeł i innych „piaskownicach” IFRAME uniemożliwia osadzonym demonstracjom przyciski „Uruchom fragment kodu” oraz „przykładowy kodepen.io” w niektórych przeglądarkach (w tym Chrome i Microsoft Edge ).

Aby opracować, stwórz własną stronę internetową, wyświetl tę stronę przez połączenie HTTPS, aby przetestować i rozwinąć.

Oto strona testowa / demonstracyjna, która demonstruje działanie kodu: https://deanmarktaylor.github.io/clipboard-test/

Async + Fallback

Z powodu poziomu obsługi przeglądarki dla nowego API Async Clipboard prawdopodobnie będziesz chciał wrócić do tej document.execCommand('copy')metody, aby uzyskać dobry zasięg przeglądarki.

Oto prosty przykład (może nie działać osadzony w tej witrynie, przeczytaj „ważną” uwagę powyżej):

function fallbackCopyTextToClipboard(text) {
  var textArea = document.createElement("textarea");
  textArea.value = text;
  
  // Avoid scrolling to bottom
  textArea.style.top = "0";
  textArea.style.left = "0";
  textArea.style.position = "fixed";

  document.body.appendChild(textArea);
  textArea.focus();
  textArea.select();

  try {
    var successful = document.execCommand('copy');
    var msg = successful ? 'successful' : 'unsuccessful';
    console.log('Fallback: Copying text command was ' + msg);
  } catch (err) {
    console.error('Fallback: Oops, unable to copy', err);
  }

  document.body.removeChild(textArea);
}
function copyTextToClipboard(text) {
  if (!navigator.clipboard) {
    fallbackCopyTextToClipboard(text);
    return;
  }
  navigator.clipboard.writeText(text).then(function() {
    console.log('Async: Copying to clipboard was successful!');
  }, function(err) {
    console.error('Async: Could not copy text: ', err);
  });
}

var copyBobBtn = document.querySelector('.js-copy-bob-btn'),
  copyJaneBtn = document.querySelector('.js-copy-jane-btn');

copyBobBtn.addEventListener('click', function(event) {
  copyTextToClipboard('Bob');
});


copyJaneBtn.addEventListener('click', function(event) {
  copyTextToClipboard('Jane');
});
<div style="display:inline-block; vertical-align:top;">
  <button class="js-copy-bob-btn">Set clipboard to BOB</button><br /><br />
  <button class="js-copy-jane-btn">Set clipboard to JANE</button>
</div>
<div style="display:inline-block;">
  <textarea class="js-test-textarea" cols="35" rows="4">Try pasting into here to see what you have on your clipboard:

  </textarea>
</div>

(przykład codepen.io może nie działać, przeczytaj „ważną” uwagę powyżej). Uwaga: ten fragment kodu nie działa dobrze we wbudowanym podglądzie przepełnienia stosu, możesz go wypróbować tutaj: https://codepen.io/DeanMarkTaylor/pen/RMRaJX?editors = 1011

Asynchroniczny interfejs API schowka

Pamiętaj, że istnieje możliwość „żądania uprawnień” i testowania dostępu do schowka za pośrednictwem interfejsu API uprawnień w Chrome 66.

var text = "Example text to appear on clipboard";
navigator.clipboard.writeText(text).then(function() {
  console.log('Async: Copying to clipboard was successful!');
}, function(err) {
  console.error('Async: Could not copy text: ', err);
});

document.execCommand („kopia”)

Pozostała część tego postu dotyczy niuansów i szczegółów document.execCommand('copy')API.

Obsługa przeglądarki

Obsługa JavaScript document.execCommand('copy')wzrosła, zobacz poniższe linki do aktualizacji przeglądarki:

Prosty przykład

(może nie działać w tej witrynie, przeczytaj „ważną” uwagę powyżej)

var copyTextareaBtn = document.querySelector('.js-textareacopybtn');

copyTextareaBtn.addEventListener('click', function(event) {
  var copyTextarea = document.querySelector('.js-copytextarea');
  copyTextarea.focus();
  copyTextarea.select();

  try {
    var successful = document.execCommand('copy');
    var msg = successful ? 'successful' : 'unsuccessful';
    console.log('Copying text command was ' + msg);
  } catch (err) {
    console.log('Oops, unable to copy');
  }
});
<p>
  <button class="js-textareacopybtn" style="vertical-align:top;">Copy Textarea</button>
  <textarea class="js-copytextarea">Hello I'm some text</textarea>
</p>

Skomplikowany przykład: skopiuj do schowka bez wyświetlania danych wejściowych

Powyższy prosty przykład działa świetnie, jeśli na ekranie widoczny jest element textarealub input.

W niektórych przypadkach możesz chcieć skopiować tekst do schowka bez wyświetlania elementu input/ textarea. To jest jeden przykład sposobu obejścia tego (w zasadzie wstaw element, skopiuj do schowka, usuń element):

Testowane z Google Chrome 44, Firefox 42.0a1 i Internet Explorer 11.0.8600.17814.

(może nie działać w tej witrynie, przeczytaj „ważną” uwagę powyżej)

function copyTextToClipboard(text) {
  var textArea = document.createElement("textarea");

  //
  // *** This styling is an extra step which is likely not required. ***
  //
  // Why is it here? To ensure:
  // 1. the element is able to have focus and selection.
  // 2. if element was to flash render it has minimal visual impact.
  // 3. less flakyness with selection and copying which **might** occur if
  //    the textarea element is not visible.
  //
  // The likelihood is the element won't even render, not even a
  // flash, so some of these are just precautions. However in
  // Internet Explorer the element is visible whilst the popup
  // box asking the user for permission for the web page to
  // copy to the clipboard.
  //

  // Place in top-left corner of screen regardless of scroll position.
  textArea.style.position = 'fixed';
  textArea.style.top = 0;
  textArea.style.left = 0;

  // Ensure it has a small width and height. Setting to 1px / 1em
  // doesn't work as this gives a negative w/h on some browsers.
  textArea.style.width = '2em';
  textArea.style.height = '2em';

  // We don't need padding, reducing the size if it does flash render.
  textArea.style.padding = 0;

  // Clean up any borders.
  textArea.style.border = 'none';
  textArea.style.outline = 'none';
  textArea.style.boxShadow = 'none';

  // Avoid flash of white box if rendered for any reason.
  textArea.style.background = 'transparent';


  textArea.value = text;

  document.body.appendChild(textArea);
  textArea.focus();
  textArea.select();

  try {
    var successful = document.execCommand('copy');
    var msg = successful ? 'successful' : 'unsuccessful';
    console.log('Copying text command was ' + msg);
  } catch (err) {
    console.log('Oops, unable to copy');
  }

  document.body.removeChild(textArea);
}


var copyBobBtn = document.querySelector('.js-copy-bob-btn'),
  copyJaneBtn = document.querySelector('.js-copy-jane-btn');

copyBobBtn.addEventListener('click', function(event) {
  copyTextToClipboard('Bob');
});


copyJaneBtn.addEventListener('click', function(event) {
  copyTextToClipboard('Jane');
});
<div style="display:inline-block; vertical-align:top;">
  <button class="js-copy-bob-btn">Set clipboard to BOB</button><br /><br />
  <button class="js-copy-jane-btn">Set clipboard to JANE</button>
</div>
<div style="display:inline-block;">
  <textarea class="js-test-textarea" cols="35" rows="4">Try pasting into here to see what you have on your clipboard:

  </textarea>
</div>

Dodatkowe uwagi

Działa tylko wtedy, gdy użytkownik podejmie akcję

Wszystkie document.execCommand('copy')połączenia muszą odbywać się bezpośrednio w wyniku działania użytkownika, np. Obsługi zdarzenia kliknięcia. Jest to środek zapobiegający bałaganowi w schowku użytkownika, gdy się tego nie spodziewa.

Aby uzyskać więcej informacji, zobacz post Google Developers tutaj .

Interfejs API schowka

Uwaga: pełna specyfikacja wersji roboczej API Clipboard można znaleźć tutaj: https://w3c.github.io/clipboard-apis/

Czy to jest obsługiwane?

  • document.queryCommandSupported('copy')powinien zwrócić, truejeśli polecenie „jest obsługiwane przez przeglądarkę”.
  • i document.queryCommandEnabled('copy')wróć, truejeśli document.execCommand('copy')odniesie sukces, jeśli zostanie teraz wezwany Sprawdzanie, czy polecenie zostało wywołane z wątku inicjowanego przez użytkownika i czy spełnione są inne wymagania.

Jednak jako przykład problemów z kompatybilnością przeglądarka Google Chrome ~ od kwietnia do października 2015 r ~ tylko powracających truez document.queryCommandSupported('copy')jeżeli zostało wywołane z wątku inicjowane przez użytkownika.

Zwróć uwagę na szczegóły dotyczące kompatybilności poniżej.

Szczegółowa kompatybilność przeglądarki

Podczas gdy proste wywołanie document.execCommand('copy')owinięte w blok try/ catchwywoływany w wyniku kliknięcia przez użytkownika zapewni największą kompatybilność, poniższe mają pewne zastrzeżenia:

Wszelkie wywołanie document.execCommand, document.queryCommandSupportedlub document.queryCommandEnabledpowinny być zapakowane w try/ catchbloku.

Różne implementacje przeglądarki i wersje przeglądarki generują różne typy wyjątków, gdy są wywoływane zamiast zwracane false.

Różne implementacje przeglądarki wciąż się zmieniają, a Clipboard API jest nadal w fazie roboczej, więc pamiętaj, aby wykonać test.

Dean Taylor
źródło
41
Jak skopiować bezpośrednio ze zmiennym .ie danych: var str = "word";?
jscripter
10
@BubuDaba Utwórz manekina ukrytego za <textarea>pomocą JS, dołącz go document.body, ustaw jego wartość na zmienną i użyj jej w tempie copyTextarea, a następnie usuń ją zaraz po skopiowaniu zawartości.
SeinopSys
3
Czy jest coś dla Safari lub jakieś wskaźniki, które zostaną zaimplementowane w Safari?
www139
3
Jedyna znaleziona wersja, która działa we wszystkich przeglądarkach. Zauważyłem, że używając tego w Boostrap Modal, musiałem dołączyć pole tekstowe do modalu. Dałbym +1000, gdybym mógł za twoje rozwiązanie !!! DZIĘKI!
Patrick,
3
@AyaSalama kluczową kwestią jest to, że akcja „kopiowania” nie może się odbyć, chyba że w przeglądarce pojawi się informacja, że ​​użytkownik ją wykonuje. Użytkownik nie byłby w stanie podjąć działania, jeśli element ma styl „display: none”, ponieważ nie byłby w stanie go zobaczyć ani z nim współdziałać.
Dean Taylor,
1256

Automatyczne kopiowanie do schowka może być niebezpieczne, dlatego większość przeglądarek (oprócz IE) bardzo utrudnia. Osobiście używam następującej prostej sztuczki:

function copyToClipboard(text) {
  window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
}

Użytkownik zostanie wyświetlony z monitem, w którym tekst do skopiowania jest już zaznaczony. Teraz wystarczy nacisnąć Ctrl+ Ci Enter(aby zamknąć okno) - i voila!

Teraz operacja kopiowania do schowka jest BEZPIECZNA, ponieważ użytkownik robi to ręcznie (ale w całkiem prosty sposób). Oczywiście działa we wszystkich przeglądarkach.

<button id="demo" onclick="copyToClipboard(document.getElementById('demo').innerHTML)">This is what I want to copy</button>

<script>
  function copyToClipboard(text) {
    window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
  }
</script>

Jarek Milewski
źródło
91
Sprytne, ale obsługuje tylko jedną linię.
Aram Kocharyan
61
Zmiana funkcji „monitu” na niestandardowy modalny jest trywialna, istotą sztuczki jest użycie edytowalnego pola treści i wstępny wybór tekstu oraz nie psuje interfejsu przeglądarki poprzez wymuszenie, że użytkownik weźmie same działania. A ++
Jon z
110
nadal nie używa javascript do kopiowania do schowka ^ _ ^
RozzA
23
Jeśli twój tekst ma ponad 2000 znaków, zostanie obcięty, ale w przypadku mniejszych próbek tekstowych działa świetnie
RasTheDestroyer
445
Dziwne, że dostaje 457 głosów pozytywnych, gdy nie odpowiada na pytanie: skopiuj do schowka w JavaScript !
stevenvh
298

Poniższe podejście działa w Chrome, Firefox, Internet Explorer i Edge oraz w najnowszych wersjach Safari (obsługa kopiowania została dodana w wersji 10, która została wydana w październiku 2016 r.).

  • Utwórz obszar tekstowy i ustaw jego zawartość na tekst, który chcesz skopiować do schowka.
  • Dołącz obszar tekstowy do DOM.
  • Wybierz tekst w obszarze tekstowym.
  • Zadzwoń do document.execCommand („kopiuj”)
  • Usuń obszar tekstowy z domeny.

Uwaga: obszar tekstowy nie będzie widoczny, ponieważ jest on dodawany i usuwany w ramach tego samego synchronicznego wywołania kodu JavaScript.

Kilka rzeczy, na które należy uważać, jeśli wdrażasz to sam:

  • Ze względów bezpieczeństwa można to wywoływać tylko z modułu obsługi zdarzeń, takiego jak kliknięcie (podobnie jak w przypadku otwierania okien).
  • Internet Explorer wyświetli okno dialogowe uprawnień przy pierwszej aktualizacji schowka.
  • Internet Explorer i Edge przewijają się, gdy obszar tekstowy jest aktywny.
  • execCommand () może w niektórych przypadkach generować.
  • Nowe linie i karty mogą zostać połknięte, chyba że użyjesz obszaru tekstowego. (Większość artykułów zaleca używanie div)
  • Obszar tekstowy będzie widoczny, gdy wyświetlone zostanie okno dialogowe Internet Explorera, albo musisz je ukryć, albo użyć specyficznego dla przeglądarki Internet Explorer interfejsu API danych.
  • W systemie Internet Explorer administratorzy mogą wyłączyć interfejs API schowka.

Poniższa funkcja powinna obsłużyć wszystkie poniższe problemy tak czysto, jak to możliwe. Zostaw komentarz, jeśli znajdziesz jakieś problemy lub masz sugestie dotyczące jego poprawy.

// Copies a string to the clipboard. Must be called from within an
// event handler such as click. May return false if it failed, but
// this is not always possible. Browser support for Chrome 43+,
// Firefox 42+, Safari 10+, Edge and Internet Explorer 10+.
// Internet Explorer: The clipboard feature may be disabled by
// an administrator. By default a prompt is shown the first
// time the clipboard is used (per session).
function copyToClipboard(text) {
    if (window.clipboardData && window.clipboardData.setData) {
        // Internet Explorer-specific code path to prevent textarea being shown while dialog is visible.
        return clipboardData.setData("Text", text);

    }
    else if (document.queryCommandSupported && document.queryCommandSupported("copy")) {
        var textarea = document.createElement("textarea");
        textarea.textContent = text;
        textarea.style.position = "fixed";  // Prevent scrolling to bottom of page in Microsoft Edge.
        document.body.appendChild(textarea);
        textarea.select();
        try {
            return document.execCommand("copy");  // Security exception may be thrown by some browsers.
        }
        catch (ex) {
            console.warn("Copy to clipboard failed.", ex);
            return false;
        }
        finally {
            document.body.removeChild(textarea);
        }
    }
}

https://jsfiddle.net/fx6a6n6x/

Greg Lowe
źródło
9
Dobra odpowiedź: obsługa wielu przeglądarek, obsługa błędów + czyszczenie. Począwszy od dzisiejszego nowego wsparcia dla queryCommandSupported, kopiowanie do schowka jest teraz możliwe w Javascripcie i powinna to być zaakceptowana odpowiedź, zamiast niewygodnego 'window.prompt (obejście „Kopiuj do schowka: Ctrl + C, Enter”, tekst). window.clipboardData jest obsługiwany w IE9, więc powinieneś dodać IE9 do listy obsługiwanych przeglądarek i myślę, że może IE8 i poprzednie również, ale trzeba to zweryfikować.
user627283,
Tak. IE 8/9 Powinno być w porządku. Nasza aplikacja ich nie obsługuje. Więc nie testowałem. IE przestaje obsługiwać w styczniu, więc nie jestem zbyt zdenerwowany. Mamy nadzieję, że wkrótce pojawi się obsługa Safari. Jestem pewien, że jest na ich radarze.
Greg Lowe,
4
@SantiagoCorredoira: W 2016 r. Zasługuje na zaakceptowaną odpowiedź. Proszę rozważyć zmianę przypisania BGT (duży zielony ptaszek).
Lawrence Dol
3
@Noitidart I Testowałem i działa idealnie dla Firefoxa 54, Chrome 60 i przeglądarki krawędzi, nawet jeśli fokus nie jest w dokumencie HTML, błąd, który masz prawdopodobnie jest specyficzny dla wersji FF 55
Tosin John
2
@Noitidart Nadal działa tutaj doskonale, skupienie się na narzędziach programistycznych nie zatrzymało tego. A tak przy okazji, co normalny użytkownik aplikacji zrobi na narzędziach dla programistów
Tosin John,
97

Oto moje zdanie na temat tego ...

function copy(text) {
    var input = document.createElement('input');
    input.setAttribute('value', text);
    document.body.appendChild(input);
    input.select();
    var result = document.execCommand('copy');
    document.body.removeChild(input);
    return result;
 }

@korayem: Zauważ, że użycie inputpola html nie będzie respektować podziałów linii \ni spłaszczy tekst w jednym wierszu.

Jak wspomniano w komentarzach @nikksan, użycie textarearozwiąże problem w następujący sposób:

function copy(text) {
    var input = document.createElement('textarea');
    input.innerHTML = text;
    document.body.appendChild(input);
    input.select();
    var result = document.execCommand('copy');
    document.body.removeChild(input);
    return result;
}
nikksan
źródło
@nikksan jak skopiować ciąg \n?
sof-03
2
@ sof-03 użyj textarea zamiast wprowadzania i dodaj \r\ndo podziału wiersza
nikksan
1
Nie działa w Microsoft Edge 42.17134.1.0 na Win10x64
Honsa Stunna
3
Skopiowałem twoją odpowiedź. Działa w chromie i to wszystko, czego potrzebuję.
user875234,
To najprostsze rozwiązanie działające z Firefoksem v68.0.2 (64-bit).
Arya
88

Jeśli chcesz naprawdę prostego rozwiązania (integracja zajmuje mniej niż 5 minut) i wygląda dobrze od razu po wyjęciu z pudełka, to Clippy to miła alternatywa dla niektórych bardziej złożonych rozwiązań.

Został napisany przez współzałożyciela GitHub. Przykładowy kod Flash poniżej:

<object
   classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
   width="110"
   height="14"
   id="clippy">
  <param name="movie" value="/flash/clippy.swf"/>
  <param name="allowScriptAccess" value="always"/>
  <param name="quality" value="high"/>
  <param name="scale" value="noscale"/>
  <param NAME="FlashVars" value="text=#{text}"/>
  <param name="bgcolor" value="#{bgcolor}"/>
  <embed
     src="/flash/clippy.swf"
     width="110"
     height="14"
     name="clippy"
     quality="high"
     allowScriptAccess="always"
     type="application/x-shockwave-flash"
     pluginspage="http://www.macromedia.com/go/getflashplayer"
     FlashVars="text=#{text}"
     bgcolor="#{bgcolor}"/>
</object>

Pamiętaj, aby zastąpić #{text}tekstem, który chcesz skopiować, i #{bgcolor}kolorem.

Brent Matzelle
źródło
12
Dla wszystkich zainteresowanych sprawdź Clippy używane na GitHub podczas kopiowania adresu URL repozytorium.
Radek
66
Do Twojej wiadomości, użycie Clippy na GitHub zostało zastąpione przez ZeroClipboard.
James M. Greene,
219
OP szukał rozwiązania w JavaScript. Nie flash.
MT.
21
@MT, przez „javascript”, niektórzy ludzie rozumieją „w kliencie przeglądarki”, więc chociaż tylko JS może być wymogiem, wiele osób, które mają szansę na tę odpowiedź, naprawdę szuka JS-a-innych-szeroko obsługiwanych- technologia klienta Flash nie działa na wszystkich platformach, ale dla polskiej funkcji, takiej jak obsługa schowka, warto dodać, jeśli poprawia UX w wyskakującym oknie dialogowym (co z pewnością robi).
Dave Dopson
13
Odtąd poleganie na Flashie oznacza brak działania dla procentu odwiedzających witrynę, co jest nie do przyjęcia dla prawie wszystkich osób tworzących strony internetowe.
jinglesthula
86

Czytanie i modyfikowanie schowka ze strony budzi obawy dotyczące bezpieczeństwa i prywatności. Jednak w Internet Explorerze można to zrobić. Znalazłem ten przykładowy fragment :

    <script type="text/javascript">
        function select_all(obj) {
            var text_val=eval(obj);
            text_val.focus();
            text_val.select();
            r = text_val.createTextRange();
            if (!r.execCommand) return; // feature detection
            r.execCommand('copy');
        }
    </script>
    <input value="http://www.sajithmr.com"
     onclick="select_all(this)" name="url" type="text" />

bandi
źródło
7
Używanie flasha do prostej operacji kopiowania wydaje się przesadą, cieszę się, że był to czysty sposób JS. A ponieważ jesteśmy w środowisku korporacyjnym. IE jest w porządku. Dzięki Bandi!
Eddie
5
proszę wyjaśnić co execCommand(\\’copy\\’);, jeśli nie skopiować do schowka dla IE? @mrBorna
RozzA
20
Nie używać if(!document.all), ale if(!r.execCommand)żeby ktokolwiek Realizuje! Document.all absolutnie nie ma związku z tym.
m93a
1
Człowieku, to jest to, co uwielbiam w prostym i czystym kodzie, działa prawie wiecznie z niewielką obsługą. Zrobiło to dla mnie, działa pięknie.
Samuel Ramzan
1
nie działa w najnowszym chrome, firefoxie lub MS Edge :(
Jonathan Marzullo,
69

Niedawno napisałem techniczny post na blogu na ten temat (pracuję w Lucidchart, a ostatnio dokonaliśmy przeglądu naszego schowka).

Kopiowanie zwykłego tekstu do schowka jest stosunkowo proste, zakładając, że chcesz to zrobić podczas zdarzenia kopiowania systemowego (użytkownik naciska CtrlClub korzysta z menu przeglądarki).

var isIe = (navigator.userAgent.toLowerCase().indexOf("msie") != -1 
           || navigator.userAgent.toLowerCase().indexOf("trident") != -1);

document.addEventListener('copy', function(e) {
    var textToPutOnClipboard = "This is some text";
    if (isIe) {
        window.clipboardData.setData('Text', textToPutOnClipboard);    
    } else {
        e.clipboardData.setData('text/plain', textToPutOnClipboard);
    }
    e.preventDefault();
});

Umieszczanie tekstu w schowku poza zdarzeniem kopiowania systemowego jest znacznie trudniejsze. Wygląda na to, że niektóre z tych odpowiedzi odnoszą się do tego, jak to zrobić za pomocą Flasha, który jest jedynym sposobem na przeglądarkę (o ile rozumiem).

Poza tym istnieją pewne opcje dla poszczególnych przeglądarek.

Jest to najprostszy w IE, w którym można uzyskać dostęp do obiektu clipboardData w dowolnym momencie z JavaScript poprzez:

window.clipboardData

(Gdy jednak spróbujesz to zrobić poza zdarzeniem wycinania, kopiowania lub wklejania w systemie, IE wyświetli monit o przyznanie pozwolenia na schowek aplikacji sieci Web).

W Chrome możesz utworzyć rozszerzenie Chrome, które da ci uprawnienia do schowka (to właśnie robimy dla Lucidchart). Następnie dla użytkowników z zainstalowanym rozszerzeniem wystarczy samemu uruchomić zdarzenie systemowe:

document.execCommand('copy');

Wygląda na to, że Firefox ma pewne opcje, które pozwalają użytkownikom na przyznawanie uprawnień do niektórych witryn w celu uzyskania dostępu do schowka, ale nie próbowałem żadnej z nich osobiście.

Richard Shurtz
źródło
2
Nie wspomniany w poście na blogu (mam nadzieję, że zaktualizuję go w najbliższej przyszłości), nie ma możliwości uruchamiania wycinania i kopiowania za pomocą execCommand. Jest to obsługiwane w IE10 +, Chrome 43+ i Opera29 +. Przeczytaj o tym tutaj. updates.html5rocks.com/2015/04/cut-and-copy-commands
Richard Shurtz
Problem polega na tym, że przechwytuje inne normalne zdarzenia kopiowania.
Brock Adams,
NB! Wąchanie przeglądarki jest ZŁE. Wykonuj funkcję wąchania. Utrudniasz aktualizację IE.
odinho
51

clipboard.js to małe narzędzie inne niż Flash, które umożliwia kopiowanie danych tekstowych lub HTML do schowka. Jest bardzo łatwy w użyciu, wystarczy dołączyć .js i użyć czegoś takiego:

<button id='markup-copy'>Copy Button</button>

<script>
document.getElementById('markup-copy').addEventListener('click', function() {
  clipboard.copy({
    'text/plain': 'Markup text. Paste me into a rich text editor.',
    'text/html': '<i>here</i> is some <b>rich text</b>'
  }).then(
    function(){console.log('success'); },
    function(err){console.log('failure', err);
  });

});
</script>

clipboard.js jest również dostępny na GitHub .

Uwaga: teraz to jest przestarzałe. Przenieś się tutaj .

programista
źródło
Ta biblioteka jest używana przez angular.io do Tour of Hero i powrotu do trybu wdzięku dla przeglądarki nieobsługującej execCommand, wyświetlając wcześniej wybrany tekst, który użytkownik musi tylko skopiować.
John-Philip
1
Wygląda na to, że clipboard.js został zastąpiony lub rozwidlony, ale wydaje się, że nadal działa i jest aktywnie utrzymywany na stronie npmjs.com/package/clipboard
Joao
35

ZeroClipboard to najlepsze rozwiązanie dla różnych przeglądarek, jakie znalazłem:

<div id="copy" data-clipboard-text="Copy Me!">Click to copy</div>    
<script src="ZeroClipboard.js"></script>
<script>
  var clip = new ZeroClipboard( document.getElementById('copy') );
</script>

Jeśli potrzebujesz obsługi non-flash dla iOS, po prostu dodaj rezerwę:

clip.on( 'noflash', function ( client, args ) {
    $("#copy").click(function(){            
        var txt = $(this).attr('data-clipboard-text');
        prompt ("Copy link, then click OK.", txt);
    });
});  

http://zeroclipboard.org/

https://github.com/zeroclipboard/ZeroClipboard

Justin
źródło
25
przeglądarka z Flash? nie działa w systemach iOS i Android 4.4
Raptor
1
Zobacz zaktualizowaną odpowiedź. Pozwala to użytkownikom Flasha na mniejszą liczbę kroków, a dla wszystkich pozostałych na rezerwę.
Justin
8
ma miliard linii kodu. to absolutnie śmieszne. lepiej nie robić tego wcale, niż
włączyć
2
Istnieje prosta wersja gist.github.com/JamesMGreene/8698897 , czyli 20K, która nie ma wszystkich dzwonków i gwizdków w wersji 74k. Żadne z nich nie jest bardzo duże. Sądzę, że większość użytkowników jest w porządku z dodatkowymi milisekundami, które pobierze plik 74k lub 20k, więc kopiowanie / wklejanie to jedno kliknięcie zamiast dwóch.
Justin
@Justin Po prostu nie mogę sprawić, by działał lokalnie, nawet jeśli skopiuję i wkleję przykłady (wprowadzam minimalne zmiany, np. Wartość srcznaczników w skrypcie). Uważam, że ich dokumentacja jest ładna, ale nieefektywna.
Gui Imamura,
29

W 2018 r. Możesz to zrobić w następujący sposób:

async copySomething(text?) {
  try {
    const toCopy = text || location.href;
    await navigator.clipboard.writeText(toCopy);
    console.log('Text or Page URL copied');
  }
  catch (err) {
    console.error('Failed to copy: ', err);
  }
}

Jest używany w moim kodzie Angular 6+ w taki sposób:

<button mat-menu-item (click)="copySomething()">
    <span>Copy link</span>
</button>

Jeśli przekażę ciąg, kopiuje go. Jeśli nic, kopiuje adres URL strony.

Można również zrobić więcej gimnastyki do schowka. Zobacz więcej informacji tutaj:

Odblokowanie dostępu do schowka

KhoPhi
źródło
połączyłeś się z localhost
Joe Warner
2
Należy pamiętać, że to nie działa w przeglądarce Safari (wersja 11.1.2)
arjun27,
1
@ arjun27 Cóż, mam nadzieję, że pewnego dnia Apple to nadrobi. Chociaż ten caniuse.com/#feat=clipboard pokazuje powyższą wersję, o której wspomniałeś, że jest częściowo obsługiwana.
KhoPhi,
2
Dostaję dla obu funkcji readText, writeText Obietnica w stanie odrzuconym
ramin
3
Zgodnie z podanym linkiem „navigator.clipboard jest obsługiwany tylko dla stron obsługiwanych przez HTTPS”
TimH - Codidact
26

Z jednego z projektów, nad którymi pracowałem, wtyczka jQuery kopiująca do schowka, która wykorzystuje bibliotekę Zero Clipboard .

Jest łatwiejszy w użyciu niż natywna wtyczka Zero Clipboard, jeśli jesteś intensywnym użytkownikiem jQuery.

SteamDev
źródło
6
92kb nie jest aż tak duży, działa szybko i możesz go użyć text()zamiast tego, innerHTML()jeśli chcesz ...
RozzA
17
@John: już innerHTMLod dłuższego czasu jest obsługiwany w różnych przeglądarkach. Tylko dlatego, że Microsoft początkowo wpadł na ten pomysł, nie czyni go zawodnym ani zastrzeżonym. Jest także w końcu dodawany do oficjalnej specyfikacji (po tym, jak każdy większy sprzedawca przeglądarki dodał już obsługę tego ... westchnienie ).
James M. Greene,
19
@John Narzekasz, że jQuery nie jest wystarczająco JavaScripty w odpowiedzi, która korzysta z Flasha;)
Max Nanasy,
4
W większości przypadków innerHTML jest lepszy niż alternatywy. Przystopuj! Jest szybszy, wydajniejszy i nie wymaga ponownego renderowania strony.
Orbituje Eden
4
@RozzA 92KBjest naprawdę duży. Dopóki LTE nie dojrzeje GPRS jest standardem danych mobilnych WW i zaczyna się od 1 KB/s. Zrób matematykę sam.
Tino
23

Ponieważ przeglądarki Chrome 42+ i Firefox 41+ obsługują teraz polecenie document.execCommand ('copy') . Więc stworzyliśmy kilka funkcji dla cross-browser możliwość kopiowania do schowka, używając kombinacji starego odpowiedzi Tim Downa i odpowiedzi Google programisty :

function selectElementContents(el) {
    // Copy textarea, pre, div, etc.
    if (document.body.createTextRange) {
        // IE
        var textRange = document.body.createTextRange();
        textRange.moveToElementText(el);
        textRange.select();
        textRange.execCommand("Copy");
    } 
    else if (window.getSelection && document.createRange) {
        // Non-Internet Explorer
        var range = document.createRange();
        range.selectNodeContents(el);
        var sel = window.getSelection();
        sel.removeAllRanges();
        sel.addRange(range);
        try {
            var successful = document.execCommand('copy');
            var msg = successful ? 'successful' : 'unsuccessful';
            console.log('Copy command was ' + msg);
        }
        catch (err) {
            console.log('Oops, unable to copy');
        }
    }
} // end function selectElementContents(el)

function make_copy_button(el) {
    var copy_btn = document.createElement('input');
    copy_btn.type = "button";
    el.parentNode.insertBefore(copy_btn, el.nextSibling);
    copy_btn.onclick = function() {
        selectElementContents(el);
    };

    if (document.queryCommandSupported("copy") || parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2]) >= 42) {
        // Copy works with Internet Explorer 4+, Chrome 42+, Firefox 41+, Opera 29+
        copy_btn.value = "Copy to Clipboard";
    }
    else {
        // Select only for Safari and older Chrome, Firefox and Opera
        copy_btn.value = "Select All (then press Ctrl + C to Copy)";
    }
}
/* Note: document.queryCommandSupported("copy") should return "true" on browsers that support copy
    but there was a bug in Chrome versions 42 to 47 that makes it return "false".  So in those
    versions of Chrome feature detection does not work!
    See https://code.google.com/p/chromium/issues/detail?id=476508
*/

make_copy_button(document.getElementById("markup"));
<pre id="markup">
  Text that can be copied or selected with cross browser support.
</pre>

Jeff Baker
źródło
Dzięki za podsumowanie tego! Masz trochę błędów w kodzie: dwukrotnie zdefiniowałeś zmienną „zakres” (var range = document.createRange ()).
Christian Engel,
1
Masz rację @ChristianEngel. Usunąłem drugi. Nie wiem jak się tam dostało.
Jeff Baker,
23

Używam tego bardzo skutecznie ( bez jQuery lub innych ram).

function copyToClp(txt){
    txt = document.createTextNode(txt);
    var m = document;
    var w = window;
    var b = m.body;
    b.appendChild(txt);
    if (b.createTextRange) {
        var d = b.createTextRange();
        d.moveToElementText(txt);
        d.select();
        m.execCommand('copy');
    } 
    else {
        var d = m.createRange();
        var g = w.getSelection;
        d.selectNodeContents(txt);
        g().removeAllRanges();
        g().addRange(d);
        m.execCommand('copy');
        g().removeAllRanges();
    }
    txt.remove();
}

Ostrzeżenie

Tabulatory są konwertowane na spacje (przynajmniej w Chrome).

Ponury
źródło
Brakuje spacji w tym podejściu
Bikram
1
Chrom. tabulatory są konwertowane na jedno miejsce
Bikram
22

Znalazłem następujące rozwiązanie:

Po naciśnięciu klawisza moduł obsługi tworzy znacznik „pre”. Ustawiamy zawartość do skopiowania do tego znacznika, następnie dokonujemy wyboru na tym znaczniku i zwracamy true w module obsługi. To wywołuje standardowy moduł obsługi chrome i kopiuje zaznaczony tekst.

W razie potrzeby możesz ustawić limit czasu dla funkcji przywracania poprzedniego wyboru. Moja implementacja w Mootools:

   function EnybyClipboard() {
     this.saveSelection = false;
     this.callback = false;
     this.pastedText = false;

     this.restoreSelection = function() {
       if (this.saveSelection) {
         window.getSelection().removeAllRanges();
         for (var i = 0; i < this.saveSelection.length; i++) {
           window.getSelection().addRange(this.saveSelection[i]);
         }
         this.saveSelection = false;
       }
     };

     this.copyText = function(text) {
       var div = $('special_copy');
       if (!div) {
         div = new Element('pre', {
           'id': 'special_copy',
           'style': 'opacity: 0;position: absolute;top: -10000px;right: 0;'
         });
         div.injectInside(document.body);
       }
       div.set('text', text);
       if (document.createRange) {
         var rng = document.createRange();
         rng.selectNodeContents(div);
         this.saveSelection = [];
         var selection = window.getSelection();
         for (var i = 0; i < selection.rangeCount; i++) {
           this.saveSelection[i] = selection.getRangeAt(i);
         }
         window.getSelection().removeAllRanges();
         window.getSelection().addRange(rng);
         setTimeout(this.restoreSelection.bind(this), 100);
       } else return alert('Copy not work. :(');
     };

     this.getPastedText = function() {
       if (!this.pastedText) alert('Nothing to paste. :(');
       return this.pastedText;
     };

     this.pasteText = function(callback) {
       var div = $('special_paste');
       if (!div) {
         div = new Element('textarea', {
           'id': 'special_paste',
           'style': 'opacity: 0;position: absolute;top: -10000px;right: 0;'
         });
         div.injectInside(document.body);
         div.addEvent('keyup', function() {
           if (this.callback) {
             this.pastedText = $('special_paste').get('value');
             this.callback.call(null, this.pastedText);
             this.callback = false;
             this.pastedText = false;
             setTimeout(this.restoreSelection.bind(this), 100);
           }
         }.bind(this));
       }
       div.set('value', '');
       if (document.createRange) {
         var rng = document.createRange();
         rng.selectNodeContents(div);
         this.saveSelection = [];
         var selection = window.getSelection();
         for (var i = 0; i < selection.rangeCount; i++) {
           this.saveSelection[i] = selection.getRangeAt(i);
         }
         window.getSelection().removeAllRanges();
         window.getSelection().addRange(rng);
         div.focus();
         this.callback = callback;
       } else return alert('Fail to paste. :(');
     };
   }

Stosowanie:

enyby_clip = new EnybyClipboard(); //init 

enyby_clip.copyText('some_text'); // place this in CTRL+C handler and return true;

enyby_clip.pasteText(function callback(pasted_text) {
        alert(pasted_text);
}); // place this in CTRL+V handler and return true;

Po wklejeniu tworzy obszar tekstowy i działa w ten sam sposób.

PS. Być może to rozwiązanie może być użyte do stworzenia w pełni przeglądarki dla wielu przeglądarek bez flashowania. Działa w FF i Chrome.

Enyby
źródło
2
Czy ktoś to wypróbował? Brzmi jak niezła rzecz, na wypadek, gdyby naprawdę działała w wielu przeglądarkach!
Michael
1
jsfiddle.net/H2FHC Demo: fiddle.jshell.net/H2FHC/show Otwórz go i naciśnij Ctrl + V lub Ctrl + C. W FF 19.0 doskonale widelce. Również w Chrome 25.0.1364.97 m. Opera 12.14 - OK. Safari 5.1.7 dla Windows - OK. IE - AWARIA.
Enyby
Dla IE należy uruchomić fokus na element wewnątrz strony. Zobacz fiddle.jshell.net/H2FHC/3/show i fiddle.jshell.net/H2FHC/3 Działa w IE 9/10. IE 6/7 potrzebuje procesu tworzenia selekcji w inny sposób, ponieważ document.createRange nie jest obsługiwany.
Enyby
21

Inne metody skopiują zwykły tekst do schowka. Aby skopiować HTML (tzn. Możesz wkleić wyniki do edytora WSIWYG), możesz wykonać następujące czynności TYLKO w IE . Jest to zasadniczo odmienne od innych metod, ponieważ przeglądarka faktycznie widocznie wybiera treść.

// create an editable DIV and append the HTML content you want copied
var editableDiv = document.createElement("div");
with (editableDiv) {
    contentEditable = true;
}     
editableDiv.appendChild(someContentElement);          

// select the editable content and copy it to the clipboard
var r = document.body.createTextRange();
r.moveToElementText(editableDiv);
r.select();  
r.execCommand("Copy");

// deselect, so the browser doesn't leave the element visibly selected
r.moveToElementText(someHiddenDiv);
r.select();   
Chase Seibert
źródło
zobacz więcej kompletnych rozwiązań HTML tutaj stackoverflow.com/questions/34191780/…
kofifus
21

Zebrałem razem to, co uważam za najlepsze.

  • Używa cssText, aby uniknąć wyjątków w Internet Explorerze, a nie bezpośrednio do stylu.
  • Przywraca wybór, jeśli taki był
  • Ustawia tylko do odczytu, aby klawiatura nie wyświetlała się na urządzeniach mobilnych
  • Ma obejście dla systemu iOS, dzięki czemu faktycznie działa tak, jak zwykle blokuje execCommand.

Oto on:

const copyToClipboard = (function initClipboardText() {
  const textarea = document.createElement('textarea');

  // Move it off screen.
  textarea.style.cssText = 'position: absolute; left: -99999em';

  // Set to readonly to prevent mobile devices opening a keyboard when
  // text is .select()'ed.
  textarea.setAttribute('readonly', true);

  document.body.appendChild(textarea);

  return function setClipboardText(text) {
    textarea.value = text;

    // Check if there is any content selected previously.
    const selected = document.getSelection().rangeCount > 0 ?
      document.getSelection().getRangeAt(0) : false;

    // iOS Safari blocks programmtic execCommand copying normally, without this hack.
    // /programming/34045777/copy-to-clipboard-using-javascript-in-ios
    if (navigator.userAgent.match(/ipad|ipod|iphone/i)) {
      const editable = textarea.contentEditable;
      textarea.contentEditable = true;
      const range = document.createRange();
      range.selectNodeContents(textarea);
      const sel = window.getSelection();
      sel.removeAllRanges();
      sel.addRange(range);
      textarea.setSelectionRange(0, 999999);
      textarea.contentEditable = editable;
    }
    else {
      textarea.select();
    }

    try {
      const result = document.execCommand('copy');

      // Restore previous selection.
      if (selected) {
        document.getSelection().removeAllRanges();
        document.getSelection().addRange(selected);
      }

      return result;
    }
    catch (err) {
      console.error(err);
      return false;
    }
  };
})();

Stosowanie: copyToClipboard('some text')

Dominik
źródło
13

Począwszy od Flash 10, możesz kopiować do schowka tylko wtedy, gdy akcja pochodzi z interakcji użytkownika z obiektem Flash. ( Przeczytaj sekcję pokrewną z ogłoszenia Adobe Flash 10 )

Rozwiązaniem jest przesadny obiekt flash nad przyciskiem Kopiuj lub dowolny element inicjujący kopiowanie. Zero Clipboard jest obecnie najlepszą biblioteką z tą implementacją. Doświadczeni programiści Flash mogą po prostu chcieć stworzyć własną bibliotekę.

matthuhiggins
źródło
12

  <!DOCTYPE html>

  <style>
    #t {
      width: 1px
      height: 1px
      border: none
    }
    #t:focus {
      outline: none
    }
  </style>

  <script>
    function copy(text) {
      var t = document.getElementById('t')
      t.innerHTML = text
      t.select()
      try {
        var successful = document.execCommand('copy')
        var msg = successful ? 'successfully' : 'unsuccessfully'
        console.log('text coppied ' + msg)
      } catch (err) {
        console.log('Unable to copy text')
      }
      t.innerHTML = ''
    }
  </script>

  <textarea id=t></textarea>

  <button onclick="copy('hello world')">
    Click me
  </button>

Samuel Tees
źródło
Najlepsza odpowiedź: D, możesz to poprawić za pomocą czegoś takiego: #t {position: absolut; po lewej: 0; indeks z: -900; szerokość: 0px; wysokość: 0px; granica: brak; } Więc będzie w pełni ukryty! Ale naprawdę dzięki stary!
Federico Navarrete
#t {resize: none;}
SmartManoj
Wytłumaczenie byłoby w porządku.
Peter Mortensen
12

Znalazłem następujące rozwiązanie:

Mam tekst w ukrytym wejściu. Ponieważ setSelectionRangenie działa na ukrytych danych wejściowych, tymczasowo zmieniłem typ na tekst, skopiowałem tekst, a następnie ponownie go ukryłem. Jeśli chcesz skopiować tekst z elementu, możesz przekazać go do funkcji i zapisać jego zawartość w zmiennej docelowej.

jQuery('#copy').on('click', function () {
    copyToClipboard();
});

function copyToClipboard() {
    var target = jQuery('#hidden_text');

    // Make it visible, so can be focused
    target.attr('type', 'text');
    target.focus();
    // Select all the text
    target[0].setSelectionRange(0, target.val().length);

    // Copy the selection
    var succeed;
    try {
        succeed = document.execCommand("copy");
    }
    catch (e) {
        succeed = false;
    }

    // Hide input again
    target.attr('type', 'hidden');

    return succeed;
}
Vassilis Pallas
źródło
11

Skopiuj tekst z danych wejściowych HTML do schowka:

 function myFunction() {
   /* Get the text field */
   var copyText = document.getElementById("myInput");

   /* Select the text field */
   copyText.select();

   /* Copy the text inside the text field */
   document.execCommand("Copy");

   /* Alert the copied text */
   alert("Copied the text: " + copyText.value);
 }
 <!-- The text field -->
 <input type="text" value="Hello Friend" id="myInput">

 <!-- The button used to copy the text -->
<button onclick="myFunction()">Copy text</button>

Uwaga: Ta document.execCommand()metoda nie jest obsługiwana w przeglądarce Internet Explorer 9 i wcześniejszych.

Źródło : W3Schools - Skopiuj tekst do schowka

Alexandru Sirbu
źródło
11

Istnieje już wiele odpowiedzi, ale jak dodać jedną (jQuery). Działa świetnie w każdej przeglądarce, także mobilnej (tzn. Wyświetla monit o bezpieczeństwo, ale po zaakceptowaniu działa po prostu dobrze).

function appCopyToClipBoard(sText)
{
    var oText = false,
        bResult = false;
    try
    {
        oText = document.createElement("textarea");
        $(oText).addClass('clipboardCopier').val(sText).insertAfter('body').focus();
        oText.select();
        document.execCommand("Copy");
        bResult = true;
    }
    catch(e) {
    }

    $(oText).remove();
    return bResult;
}

W twoim kodzie:

if (!appCopyToClipBoard('Hai there! This is copied to the clipboard.'))
{
    alert('Sorry, copy to clipboard failed.');
}
Codebeat
źródło
9

To jest trochę połączenie innych odpowiedzi.

var copyToClipboard = function(textToCopy){
    $("body")
        .append($('<textarea name="fname" class="textToCopyInput"/>' )
        .val(textToCopy))
        .find(".textToCopyInput")
        .select();
      try {
        var successful = document.execCommand('copy');
        var msg = successful ? 'successful' : 'unsuccessful';
        alert('Text copied to clipboard!');
      } catch (err) {
          window.prompt("To copy the text to clipboard: Ctrl+C, Enter", textToCopy);
      }
     $(".textToCopyInput").remove();
}

Korzysta z jQuery, ale oczywiście nie musi. Możesz to zmienić, jeśli chcesz. Właśnie miałem do dyspozycji jQuery. Możesz również dodać trochę CSS, aby upewnić się, że dane wejściowe się nie wyświetlają. Na przykład coś takiego:

.textToCopyInput{opacity: 0; position: absolute;}

Lub oczywiście możesz wykonać stylizację wbudowaną

.append($('<textarea name="fname" style="opacity: 0;  position: absolute;" class="textToCopyInput"/>' )
Bart Burg
źródło
Jak kopiować bezpośrednio z danych zmiennych .ie: var str = "word"; ?
Zmienna msg nie jest używana
Voyager,
Lepiej używać „<textarea class =" textToCopyInput "/> </textarea> 'na wypadek, gdyby textToCopyzawierał\n
Voyager
8

W przeglądarkach innych niż IE musisz używać małego obiektu flash do manipulowania schowkiem, np

Quog
źródło
To jest już nieaktualne ... sprawdź sugestię GvS
Mottie
6
Sugestia GvS wykorzystuje film flash? Czy to nie ten sam pomysł?
TheEmirOfGroofunkistan
8

Miałem ten sam problem z budowaniem niestandardowej edycji siatki z (coś takiego jak Excel) i kompatybilnością z Excelem. Musiałem wspierać wybieranie wielu komórek, kopiowanie i wklejanie.

Rozwiązanie: utwórz obszar tekstowy, w którym wstawisz dane do skopiowania przez użytkownika (dla mnie, gdy użytkownik wybiera komórki), ustaw fokus na nim (na przykład po naciśnięciu przez użytkownika Ctrl) i zaznacz cały tekst.

Tak więc, gdy użytkownik naciśnie Ctrl+C on / ona pobiera skopiowane komórki, on / ona wybiera. Po przetestowaniu zmieniłem rozmiar obszaru tekstowego na jeden piksel (nie sprawdziłem, czy będzie działał na wyświetlaczu: brak). Działa ładnie na wszystkich przeglądarkach i jest przezroczysty dla użytkownika.

Wklejanie - możesz zrobić tak samo (w zależności od celu) - skup się na obszarze tekstowym i przechwytuj zdarzenia wklejania za pomocą onpaste (w moim projekcie do edycji używam obszarów tekstowych w komórkach).

Nie mogę wkleić przykładu (projekt komercyjny), ale masz pomysł.

Xiniu
źródło
7

Użyłem clipboard.js.

Możemy go zdobyć na npm:

npm install clipboard --save

A także na Bower

bower install clipboard --save

Sposób użycia i przykłady są na https://zenorocha.github.io/clipboard.js/ .

CodecPM
źródło
Bałem się, że nie jest kompatybilny z dynamiczną treścią, ale tak jest ;-) Myślę, że jest to lepsze rozwiązanie TERAZ, niż stare z 2008 roku.
BENARD Patrick
6

Jest to rozszerzenie odpowiedzi @ Chase, z tą zaletą, że będzie działać dla elementów OBRAZ i TABELA, nie tylko DIV na IE9.

if (document.createRange) {
    // IE9 and modern browsers
    var r = document.createRange();
    r.setStartBefore(to_copy);
    r.setEndAfter(to_copy);
    r.selectNode(to_copy);
    var sel = window.getSelection();
    sel.addRange(r);
    document.execCommand('Copy');  // does nothing on FF
} else {
    // IE 8 and earlier.  This stuff won't work on IE9.
    // (unless forced into a backward compatibility mode,
    // or selecting plain divs, not img or table). 
    var r = document.body.createTextRange();
    r.moveToElementText(to_copy);
    r.select()
    r.execCommand('Copy');
}
Oliver Bock
źródło
5

Wygląda na to, że źle odczytałem pytanie, ale w celach informacyjnych możesz wyodrębnić zakres DOM (nie do schowka; zgodny ze wszystkimi nowoczesnymi przeglądarkami) i połączyć go z zdarzeniami oncopy oraz onpaste i onbefastepaste, aby uzyskać zachowanie schowka. Oto kod, aby to osiągnąć:

function clipBoard(sCommand) {
  var oRange=contentDocument.createRange();
  oRange.setStart(startNode, startOffset);
  oRange.setEnd(endNode, endOffset);
/* This is where the actual selection happens.
in the above, startNode and endNode are dom nodes defining the beginning 
and end of the "selection" respectively. startOffset and endOffset are 
constants that are defined as follows:

END_TO_END: 2
END_TO_START: 3
NODE_AFTER: 1
NODE_BEFORE: 0
NODE_BEFORE_AND_AFTER: 2
NODE_INSIDE: 3
START_TO_END: 1
START_TO_START: 0

and would be used like oRange.START_TO_END */
      switch(sCommand) {
    case "cut":
          this.oFragment=oRange.extractContents();
      oRange.collapse();
      break;
    case "copy":
      this.oFragment=oRange.cloneContents();
      break;
    case "paste":
      oRange.deleteContents();
      var cloneFragment=this.oFragment.cloneNode(true)
      oRange.insertNode(cloneFragment);
      oRange.collapse();
      break;
  }
}
mrBorna
źródło
1
właściwie poprawiłem kod. Działa we wszystkich przeglądarkach, ale tak naprawdę nie kopiuje do schowka. Po prostu wyodrębnia (wycina), klonuje (kopiuje) zawartość za pomocą zmiennych. Wygląda na to, że zapomniałem użycia.
mrBorna
5

Mój błąd. Działa to tylko w IE.

Oto jeszcze jeden sposób na skopiowanie tekstu:

<p>
    <a onclick="window.clipboardData.setData('text', document.getElementById('Test').innerText);">Copy</a>
</p>
dvallejo
źródło
9
To nie działa w bieżącym Chrome (V31) lub FireFox (v25). Błąd polega na tym, że window.clipboardData nie jest zdefiniowany. Na plus działa to w IE9. Tak długo, jak nie zależy Ci na dobrych przeglądarkach i chcesz zablokować swoją witrynę przed używaniem złych, tak właśnie możesz to zrobić!
Anthony
2
nie rozumiem, dlaczego tak wiele głupich odpowiedzi. w3schools.com/howto/tryit.asp?filename=tryhow_js_copy_clipboard
Martian2049
5

To była jedyna rzecz, jaką kiedykolwiek pracowałem, po tym, jak szukałem różnych sposobów w Internecie. To jest niechlujny temat. Istnieje wiele rozwiązań opublikowanych na całym świecie i większość z nich nie działa. To działało dla mnie:

UWAGA: Ten kod będzie działał tylko wtedy, gdy zostanie wykonany jako bezpośredni kod synchroniczny do czegoś takiego jak metoda „onClick”. Jeśli wywołasz asynchroniczną odpowiedź do Ajax lub w jakikolwiek inny asynchroniczny sposób, to nie zadziała.

copyToClipboard(text) {
    var copyText = document.createElement("input");
    copyText.type = "text";
    document.body.appendChild(copyText);
    copyText.style = "display: inline; width: 1px;";
    copyText.value = text;
    copyText.focus();
    document.execCommand("SelectAll");
    document.execCommand("Copy");
    copyText.remove();
}

Zdaję sobie sprawę, że ten kod będzie wyświetlać na ekranie komponent o szerokości 1 piksela przez milisekundę, ale postanowiłem nie przejmować się tym, co inni mogą rozwiązać, jeśli to prawdziwy problem.

Peter Mortensen
źródło
5

Aby skopiować zaznaczony tekst („Tekst do skopiowania”) do schowka, utwórz Zakładkę (zakładkę przeglądarki, która wykonuje JavaScript) i uruchom ją (kliknij na nią). Stworzy tymczasowy obszar tekstowy.

Kod z GitHub:

https://gist.github.com/stefanmaric/2abf96c740191cda3bc7a8b0fc905a7d

(function (text) {
  var node = document.createElement('textarea');
  var selection = document.getSelection();

  node.textContent = text;
  document.body.appendChild(node);

  selection.removeAllRanges();
  node.select();
  document.execCommand('copy');

  selection.removeAllRanges();
  document.body.removeChild(node);
})('Text To Copy');
Mau
źródło