Огляд
Існує три основні API браузера для копіювання в буфер обміну:
- API буфера обміну Async
[navigator.clipboard.writeText]
- Текстова частина, доступна в Chrome 66 (березень 2018 року)
- Доступ асинхронний і використовує Обіцяння JavaScript , можна писати так, щоб підказки користувачів безпеки (якщо вони відображаються) не перебивали JavaScript на сторінці.
- Текст можна скопіювати у буфер обміну безпосередньо зі змінної.
- Підтримується лише на сторінках, що подаються через HTTPS.
- У веб-переглядачах Chrome 66 на активних вкладках можна записувати у буфер обміну без відповідного запиту.
document.execCommand('copy')
- Більшість браузерів підтримують це станом на ~ квітня 2015 року (див. Підтримку браузера нижче).
- Доступ синхронний, тобто зупиняє JavaScript на сторінці до повного включення відображення та взаємодії користувача з будь-якими запитами безпеки.
- Текст читається з DOM та розміщується у буфері обміну.
- Під час тестування ~ квітня 2015 року лише Internet Explorer було відмічено як відображення дозволів під час запису в буфер обміну.
- Перезапис події копіювання
- Див. Документацію API буфера обміну щодо переосмислення події копіювання .
- Дозволяє змінювати те, що з’являється у буфері обміну з будь-якої події копіювання, може включати інші формати даних, крім звичайного тексту.
- Тут не висвітлено, оскільки це не відповідає безпосередньо на питання.
Загальні конспекти розвитку
Не очікуйте, що команди, пов’язані з буфером, працюватимуть під час тестування коду в консолі. Як правило, сторінка повинна бути активною (Async Clipboard API) або вимагає взаємодії з користувачем (наприклад, натисканням користувача), щоб дозволити ( document.execCommand('copy')
) отримати доступ до буфера обміну, див. Нижче для отримання більш детальної інформації.
ВАЖЛИВО (зазначено тут 2020/02/20)
Зауважте, що оскільки ця публікація спочатку писала анулювання дозволів у перехресних джерелах IFRAME та інших "пісочниць" IFRAME, заважає вбудованим демо-кнопкам "Запустити фрагмент коду" та "codepen.io приклад" працювати в деяких браузерах (включаючи Chrome та Microsoft Edge ).
Щоб розробити, створіть власну веб-сторінку, подайте її на з'єднання HTTPS для тестування та розробки.
Ось тестова / демонстраційна сторінка, яка демонструє працюючий код:
https://deanmarktaylor.github.io/clipboard-test/
Async + Fallback
Завдяки рівню підтримки браузера для нового API Async Clipboard ви, швидше за все, захочете відмовитися від document.execCommand('copy')
методу, щоб отримати гарне покриття браузера.
Ось простий приклад (може не працювати, вбудований на цей сайт, читайте "важливу" примітку вище):
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>
(приклад codepen.io може не працювати, читайте "важливу" примітку вище). Зверніть увагу, що цей фрагмент не працює добре у вбудованому попередньому попередньому перегляді Stack Overflow. Спробуйте його тут: https://codepen.io/DeanMarkTaylor/pen/RMRaJX?editors = 1011
API буфера обміну Async
Зауважте, що існує можливість "вимагати дозволу" та перевірити на доступ до буфера обміну через API дозволів у 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 ('копія')
У решті цього допису йдеться про нюанси та деталізацію document.execCommand('copy')
API.
Підтримка браузера
Підтримка JavaScript document.execCommand('copy')
зросла, дивіться посилання нижче для оновлень браузера:
Простий приклад
(можливо, не працює вбудований у цей сайт, читайте "важливу" примітку вище)
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>
Складний приклад: Скопіюйте у буфер обміну, не відображаючи введення
Наведений вище простий приклад чудово працює, якщо на екрані видно textarea
або input
елемент.
У деяких випадках ви можете скопіювати текст у буфер обміну, не відображаючи input
/ textarea
елемент. Це один із прикладів способу подолати це (в основному вставити елемент, скопіювати у буфер обміну, видалити елемент):
Тестовано з Google Chrome 44, Firefox 42.0a1 та Internet Explorer 11.0.8600.17814.
(можливо, не працює вбудований у цей сайт, читайте "важливу" примітку вище)
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>
Додаткові нотатки
Працює лише в тому випадку, якщо користувач вживає дій
Усі document.execCommand('copy')
дзвінки повинні відбуватися як безпосередній результат дії користувача, наприклад, обробник подій клацання. Це міра запобігти возитися з буфера обміну користувача, коли він цього не очікує.
Дивіться публікацію розробників Google тут для отримання додаткової інформації.
Буфер обміну API
Зверніть увагу, що повну специфікацію API буфера обміну можна знайти тут:
https://w3c.github.io/clipboard-apis/
Це підтримується?
document.queryCommandSupported('copy')
повинен повернутися, true
якщо команда "підтримується браузером".
- і
document.queryCommandEnabled('copy')
повернутися, true
якщо document.execCommand('copy')
заповіт буде успішний, якщо його зараз зателефонують. Перевірка на те, щоб команда була викликана з потоку, ініційованого користувачем, і інші вимоги виконуються.
Однак, як приклад проблем із сумісністю браузера, Google Chrome з ~ квітня по ~ жовтня 2015 року повертався лише true
з того document.queryCommandSupported('copy')
випадку, якщо команда була викликана з ініційованого користувачем потоку.
Зверніть увагу на деталі сумісності нижче.
Деталі сумісності браузера
У той час як простий дзвінок, document.execCommand('copy')
перетворений в try
/ catch
блок, викликаний в результаті натискання користувача, отримає максимальну сумісність, використовуйте наступні умови:
Будь-який виклик document.execCommand
, document.queryCommandSupported
або document.queryCommandEnabled
повинен бути загорнутий в try
/ catch
блоці.
Різні реалізації браузера та версії браузера викидають різні типи винятків, коли викликаються замість повернення false
.
Різні реалізації браузера все ще знаходяться в потоці, а API буфера обміну все ще знаходиться в чернеті, тому не забудьте зробити тестування.