Przegląd
Istnieją trzy podstawowe interfejsy API przeglądarki do kopiowania do schowka:
- 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.
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.
- 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 textarea
lub 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ć, true
jeśli polecenie „jest obsługiwane przez przeglądarkę”.
- i
document.queryCommandEnabled('copy')
wróć, true
jeś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 true
z 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
/ catch
wywoływany w wyniku kliknięcia przez użytkownika zapewni największą kompatybilność, poniższe mają pewne zastrzeżenia:
Wszelkie wywołanie document.execCommand
, document.queryCommandSupported
lub document.queryCommandEnabled
powinny być zapakowane w try
/ catch
bloku.
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.