Обзор
Существует три основных API браузера для копирования в буфер обмена:
API асинхронного буфера обмена [navigator.clipboard.writeText]
- Text-focused portion available in Chrome 66 (March 2018)
- Доступ является асинхронным и использует JavaScript Promises, может быть написан так, чтобы пользователь безопасности запрашивал (если отображается) не прерывают JavaScript на странице.
- Текст можно скопировать в буфер обмена прямо из переменной.
- Поддерживается только на страницах, обслуживаемых по HTTPS.
- На 66 страницах Chrome неактивные вкладки могут записываться в буфер обмена без запроса разрешений.
document.execCommand('copy')
- Most browsers support this as of ~April 2015 (see Browser Support below).
- Доступ является синхронным, то есть останавливает JavaScript на странице до завершения, включая отображение и взаимодействие пользователя с любыми запросами безопасности.
- Текст считывается из модели DOM и помещается в буфер обмена.
- Во время тестирования ~ апрель 2015 года было замечено, что только Internet Explorer отображает запросы разрешений при записи в буфер обмена.
Переопределение события копирования
- See Clipboard API documentation on Overriding the copy event.
- Позволяет вам изменять то, что появляется в буфере обмена из любого события копирования, может включать другие форматы данных, кроме обычного текста.
- Здесь не рассматривается, поскольку не дает прямого ответа на вопрос.
Общие замечания по развитию
Не ожидайте, что команды, связанные с буфером обмена, будут работать, пока вы тестируете код в консоли. Как правило, страница должна быть активной (API асинхронного буфера обмена) или требует взаимодействия с пользователем (например, щелчка пользователя), чтобы разрешить (document.execCommand('copy')
) доступ к буферу обмена, подробнее см. Ниже.
ВАЖНО (указано здесь 2020/02/20)
Обратите внимание: поскольку этот пост был изначально написан прекращение поддержки разрешений в IFRAME с несколькими источниками и других песочница IFRAME предотвращает работу встроенных демонстраций кнопок фрагмента кода и примера codepen.io в некоторых браузерах (включая Chrome и Microsoft Edge).
Для разработки создайте свою собственную веб-страницу, обслуживайте эту страницу через соединение HTTPS для тестирования и разработки.
Вот тестовая / демонстрационная страница, демонстрирующая работу кода: https://deanmarktaylor.github.io/clipboard-test/
Асинхронный + резервный
Из-за уровня поддержки браузером нового 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
API асинхронного буфера обмена
Обратите внимание, что есть возможность запросить разрешение и проверить доступ к буферу обмена через 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.
Поддержка браузера
Увеличилась поддержка document.execCommand('copy')
JavaScript, см. Ссылки ниже для обновлений браузера:
Простой пример
(may not work embedded in this site, read "important" note above)
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.
(may not work embedded in this site, read "important" note above)
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 the 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 the 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 the 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')
, заключенный в блок _27 _ / _ 28_, вызываемый в результате щелчка пользователя, обеспечит вам максимальную совместимость, использование следующего имеет некоторые оговорки:
Любой вызов document.execCommand
, document.queryCommandSupported
или document.queryCommandEnabled
должен быть заключен в блок _32 _ / _ 33_.
Различные реализации и версии браузеров при вызове выдают разные типы исключений вместо того, чтобы возвращать false
.
Различные реализации браузеров все еще находятся в стадии разработки, а Clipboard API все еще находится в стадии разработки, поэтому не забудьте сделать ваше тестирование.
person
Dean Taylor
schedule
12.06.2015