обзор
Существует три основных API браузера для копирования в буфер обмена:
- Async Clipboard API
[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, в некоторых браузерах (включая Chrome и Microsoft Edge) не работают встроенные демонстрационные кнопки «Выполнить фрагмент кода» и «пример codepen.io». ).
Для разработки создайте свою собственную веб-страницу, используйте эту страницу через соединение HTTPS для тестирования и разработки.
Вот тестовая / демонстрационная страница, которая демонстрирует работающий код:
https://deanmarktaylor.github.io/clipboard-test/
Async + Fallback
Из-за уровня поддержки браузера для нового Async Clipboard API вы, вероятно, захотите использовать этот 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
Async Clipboard API
Обратите внимание, что в Chrome 66 есть возможность «запросить разрешение» и проверить доступ к буферу обмена через API разрешений.
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')
вызовы должны происходить как прямой результат действия пользователя, например, обработчик события click. Это мера, позволяющая избежать путаницы с буфером обмена пользователя, когда он этого не ожидает.
Смотрите пост разработчиков 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
block, вызываемый в результате щелчка пользователя, обеспечит вам наибольшую совместимость, используйте следующие условия:
Любой вызов document.execCommand
, document.queryCommandSupported
или document.queryCommandEnabled
должен быть завернут в try
/ catch
блоке.
Различные реализации браузера и версии браузера выдают разные типы исключений при вызове вместо возврата false
.
Различные реализации браузеров все еще находятся в движении, а API буфера обмена все еще находится в стадии разработки, поэтому не забудьте провести тестирование.