Как мне скопировать в буфер обмена в JavaScript?
Каков наилучший способ скопировать текст в буфер обмена? (Мульти-браузер)
Я пытался:
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);
}
}
но в Internet Explorer выдает синтаксическую ошибку. В Firefox написано unsafeWindow is not defined
,
Хороший трюк без вспышки: как Trello получает доступ к буферу обмена пользователя?
74 ответа
обзор
Существует 3 основных API браузера для копирования в буфер обмена:
- Async Clipboard API
[navigator.clipboard.writeText]
- Текстовая часть доступна в Chrome 66 (март 2018)
- Доступ асинхронный и использует обещания JavaScript, может быть написан таким образом, чтобы запросы безопасности пользователя (если отображаются) не прерывали JavaScript на странице.
- Текст может быть скопирован в буфер обмена непосредственно из переменной.
- Поддерживается только на страницах, обслуживаемых по HTTPS.
- В Chrome 66 страниц в активных вкладках можно записывать в буфер обмена без запроса разрешения.
document.execCommand('copy')
- Большинство браузеров поддерживают это по состоянию на апрель 2015 года (см. "Поддержка браузеров" ниже).
- Доступ является синхронным, т.е. останавливает JavaScript на странице до завершения, включая отображение и взаимодействие пользователя с любыми запросами безопасности.
- Текст читается из DOM и помещается в буфер обмена.
- Во время тестирования ~ апреля 2015 года только Internet Explorer был отмечен как отображающий запросы разрешений при записи в буфер обмена.
- Переопределение события копирования
- См. Документацию Clipboard API по переопределению события копирования.
- Позволяет изменить то, что появляется в буфере обмена из любого события копирования, может включать в себя другие форматы данных, кроме обычного текста.
- Здесь не рассматривается, так как это не дает прямого ответа на вопрос.
Общие замечания по разработке
Не ожидайте, что команды, связанные с буфером обмена, будут работать, пока вы тестируете код в консоли. Обычно страница должна быть активной (Async Clipboard API) или требует взаимодействия с пользователем (например, щелчок пользователя), чтобы разрешить (document.execCommand('copy')
) для доступа к буферу обмена см. ниже для более подробной информации.
Async + Fallback
Из-за уровня поддержки браузера для нового Async Clipboard API вы, вероятно, захотите вернуться к document.execCommand('copy')
способ получить хорошее покрытие браузера.
Вот простой пример:
function fallbackCopyTextToClipboard(text) {
var textArea = document.createElement("textarea");
textArea.value = text;
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>
Обратите внимание, что этот фрагмент не работает хорошо во встроенном предварительном просмотре Stackru, вы можете попробовать его здесь: https://codepen.io/DeanMarkTaylor/pen/RMRaJX?editors=1011
Async Clipboard API
- Объявление Chrome 66 (март 2018)
- Ссылка на проект документации 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')
поддержка выросла, см. ссылки ниже для обновлений браузера:
- IE10 + (хотя этот документ указывает на некоторую поддержку со стороны IE5.5 +).
- Google Chrome 43+ (~ апрель 2015 г.)
- Mozilla Firefox 41+ (доставка ~ сентябрь 2015 г.)
- Opera 29+ (на основе Chromium 42, ~ апрель 2015 г.)
Простой пример
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 и IE 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 IE 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
Блок, вызываемый в результате щелчка пользователем, обеспечит вам наибольшую совместимость, используйте следующие условия:
Любой звонок в document.execCommand
, document.queryCommandSupported
или же document.queryCommandEnabled
должны быть завернуты в try
/ catch
блок.
Различные реализации браузера и версии браузера выдают разные типы исключений при вызове вместо возврата false
,
Различные реализации браузеров все еще находятся в процессе разработки, а API буфера обмена все еще находится в стадии разработки, поэтому не забудьте провести тестирование.
Автоматическое копирование в буфер обмена может быть опасным, поэтому большинство браузеров (кроме IE) делают это очень сложно. Лично я использую следующий простой трюк:
function copyToClipboard(text) {
window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
}
Пользователю предоставляется окно приглашения, в котором текст для копирования уже выделен. Теперь достаточно нажать Ctrl + C и Enter (чтобы закрыть окно) - и вуаля!
Теперь операция копирования в буфер обмена БЕЗОПАСНА, потому что пользователь делает это вручную (но довольно просто). Конечно, работает во всех браузерах.
<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>
Следующий подход работает в Chrome, Firefox, Internet Explorer и Edge, а также в последних версиях Safari (поддержка копирования была добавлена в версии 10, выпущенной в октябре 2016 года).
- Создайте текстовую область и установите для ее содержимого текст, который вы хотите скопировать в буфер обмена.
- Добавьте текстовое поле к DOM.
- Выделите текст в текстовой области.
- Вызовите document.execCommand("копировать")
- Удалить текстовую область из домена.
Примечание: вы не увидите текстовую область, так как она добавляется и удаляется в рамках одного и того же синхронного вызова кода Javascript.
Некоторые вещи, на которые стоит обратить внимание, если вы реализуете это самостоятельно:
- По соображениям безопасности, это может быть вызвано только из обработчика события, такого как щелчок (как и при открытии окон).
- IE покажет диалоговое окно разрешения при первом обновлении буфера обмена.
- IE и Edge будут прокручиваться, когда текстовая область сфокусирована.
- execCommand () может выдавать в некоторых случаях.
- Новые строки и вкладки могут быть проглочены, если вы не используете текстовую область. (В большинстве статей рекомендуется использовать div)
- Текстовая область будет видна, пока отображается диалоговое окно IE, вам нужно либо скрыть ее, либо использовать API-интерфейс clipboardData, специфичный для IE.
- В IE системные администраторы могут отключить буфер обмена API.
Приведенная ниже функция должна обрабатывать все следующие проблемы как можно более чисто. Пожалуйста, оставьте комментарий, если вы обнаружите какие-либо проблемы или у вас есть предложения по его улучшению.
// 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 IE 10+.
// IE: 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) {
// IE 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 MS 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);
}
}
}
Вот мой взгляд на это..
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;
}
Чтение и изменение буфера обмена с веб-страницы вызывает проблемы безопасности и конфиденциальности. Однако в Internet Explorer это можно сделать. Я нашел этот пример фрагмента:
<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" />
Если вы хотите действительно простое решение (занимает меньше 5 минут для интеграции) и хорошо выглядят прямо из коробки, то Clippy - хорошая альтернатива некоторым из более сложных решений.
Он был написан соучредителем GitHub. Пример встроенного кода Flash ниже:
<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>
Не забудьте заменить #{text}
с текстом, который вам нужно скопировать, и #{bgcolor}
с цветом.
Я недавно написал технический пост в блоге об этой самой проблеме (я работаю в Lucidchart, и мы недавно сделали капитальный ремонт нашего буфера обмена).
Копировать обычный текст в буфер обмена относительно просто, если вы хотите сделать это во время события копирования системы (пользователь нажимает CtrlC или использует меню браузера).
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();
});
Поместить текст в буфер обмена не во время системного копирования намного сложнее. Похоже, что некоторые из этих других ответов ссылаются на способы сделать это через Flash, который является единственным кросс-браузерным способом сделать это (насколько я понимаю).
Кроме этого, есть несколько опций для каждого браузера.
Это самый простой в IE, где вы можете получить доступ к объекту clipboardData в любое время из JavaScript через:
window.clipboardData
(Однако, если вы попытаетесь сделать это вне системного события вырезания, копирования или вставки, IE предложит пользователю предоставить разрешение буфера обмена веб-приложения.)
В Chrome вы можете создать расширение Chrome, которое предоставит вам разрешения для буфера обмена (это то, что мы делаем для Lucidchart). Тогда для пользователей с установленным расширением вам просто нужно самостоятельно запустить системное событие:
document.execCommand('copy');
Похоже, что у Firefox есть некоторые параметры, которые позволяют пользователям предоставлять разрешения определенным сайтам для доступа к буферу обмена, но я не пробовал ничего из этого лично.
Мне нравится этот:
<input onclick="this.select();" type='text' value='copy me' />
Если пользователь не знает, как копировать текст в своей ОС, скорее всего, он тоже не знает, как вставить. Поэтому просто выберите его автоматически, а все остальное предоставьте пользователю.
clipboard.js - это небольшая, не флэш-утилита, которая позволяет копировать текстовые или html-данные в буфер обмена. Это очень легко использовать, просто включите.js и используйте что-то вроде этого:
<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 также на GitHub
Гиш, не уверен, почему никто еще не указал на это.
В 2018 году, ребята, вот как вы можете это сделать:
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);
}
}
Используется в моем коде Angular 6+ примерно так:
<button mat-menu-item (click)="copySomething()">
<span>Copy link</span>
</button>
Если я передаю строку, она копируется. Если ничего, копирует URL страницы.
Можно сделать еще больше гимнастики для буфера обмена. Смотрите больше информации здесь:
https://developers.google.com/web/updates/2018/03/clipboardapi
Я использую это очень успешно (без jquery или каких-либо других фреймворков).
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();
}
Предупреждение
Вкладки преобразуются в пробелы (по крайней мере, в Chrome).
Лучший и простой способ в JavaScript/TypeScript использовать эту команду
navigator.clipboard.writeText(textExample);
просто передайте свое значение, которое вы хотите скопировать в буфер обмена в textExample
ZeroClipboard - лучшее кросс-браузерное решение, которое я нашел:
<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>
Если вам нужна поддержка не-flash для iOS, просто добавьте запасной вариант:
clip.on( 'noflash', function ( client, args ) {
$("#copy").click(function(){
var txt = $(this).attr('data-clipboard-text');
prompt ("Copy link, then click OK.", txt);
});
});
С недавнего времени Chrome 42+
а также Firefox 41+
Теперь поддержите команду document.execCommand('copy'). Поэтому я создал несколько функций для кросс-браузерного копирования в буфер обмена, используя комбинацию старого ответа Тима Дауна и ответа Google Developer:
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-IE
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 IE 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>
$("td").click(function (e) {
var clickedCell = $(e.target).closest("td");
navigator.clipboard.writeText(clickedCell.text());
alert(clickedCell.text());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td>First<td>
</tr>
<tr>
<td>Second<td>
</tr>
<tr>
<td>Third<td>
</tr>
<tr>
<td>Fourth<td>
</tr>
</table>
Я прочитал все ответы, по состоянию на 1 июня 2020 года я изо всех сил пытался решить эту проблему, когда наконец нашел документацию:
$("td").click(function (e) {
var clickedCell = $(e.target).closest("td");
navigator.clipboard.writeText(clickedCell.text());
});
Он запишет текст выбранной ячейки в буфер обмена браузера.
Вы можете изменить селекторы "td" на все, что захотите, вы можете добавить console.log для функций отладки и / или предупреждений.
Вот документация: https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/writeText
В одном из проектов, над которым я работал, плагин jQuery для копирования в буфер обмена, использующий библиотеку Zero Clipboard.
Он проще в использовании, чем нативный плагин Zero Clipboard, если вы большой пользователь jQuery.
Другие методы будут копировать обычный текст в буфер обмена. Чтобы скопировать HTML (т.е. вы можете вставить результаты в редактор WSIWYG), вы можете сделать следующее только в IE. Это принципиально отличается от других методов, так как браузер фактически визуально выбирает контент.
// 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();
Я собрал то, что считаю лучшим.
- Использует cssText, чтобы избежать исключений в IE, в отличие от стиля напрямую.
- Восстанавливает выбор, если был один
- Устанавливает только чтение, чтобы клавиатура не появлялась на мобильных устройствах
- Есть обходной путь для iOS, так что он на самом деле работает, как обычно, блокирует execCommand.
Вот:
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.
// https://stackru.com/questions/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) {
return false;
}
};
})();
Я нашел следующее решение:
Обработчик ключа вниз создает тэг "pre". Мы устанавливаем содержимое для копирования в этот тег, затем выбираем этот тег и возвращаем true в обработчике. Это вызывает стандартный обработчик хрома и копирует выделенный текст.
И если вам нужно, вы можете установить тайм-аут для функции для восстановления предыдущего выбора. Моя реализация на 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. :(');
};
}
Использование:
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;
При вставке он создает текстовую область и работает так же.
PS Возможно, это решение может быть использовано для создания полностью кросс-браузерного решения без флеш-памяти. Работает в FF и Chrome.
Я не хочу добавлять еще один ответ на этот вопрос, но чтобы помочь таким новичкам, как я, и потому что это лучший результат Google, я это сделаю.
В 2022 году для копирования текста в буфер обмена используется одна строка.
navigator.clipboard.writeText(textToCopy);
Это возвращает промис, который разрешается, если он копируется, или отклоняется, если он терпит неудачу.
Полная рабочая функция такова:
async function copyTextToClipboard(textToCopy) {
try {
await navigator.clipboard.writeText(textToCopy);
console.log('copied to clipboard')
} catch (error) {
console.log('failed to copy to clipboard. error=' + error);
}
}
ПРЕДУПРЕЖДЕНИЕ! Если у вас открыты Chrome Dev Tools во время тестирования, это не удастся, потому что для того, чтобы браузер включил буфер обмена, вам нужно, чтобы окно было в фокусе. Это делается для того, чтобы случайные веб-сайты не изменяли ваш буфер обмена, если вы этого не хотите. Инструменты разработки крадут этот фокус, поэтому закройте Инструменты разработки, и ваш тест будет работать.
Если вы хотите скопировать другие элементы (изображения и т. д.) в буфер обмена, просмотрите эти документы.
https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API
Это достаточно хорошо поддерживается в браузерах, которые вы можете использовать. Если вы беспокоитесь о Firefox, используйте запрос разрешений, чтобы показать или скрыть кнопку, если браузер поддерживает это. https://developer.mozilla.org/en-US/docs/Web/API/Permissions/query
Этот код протестирован @ 2021 мая. Работайте в Chrome, IE, Edge. Параметр "сообщение" ниже - это строковое значение, которое вы хотите скопировать.
<script type="text/javascript">
function copyToClipboard(message) {
var textArea = document.createElement("textarea");
textArea.value = message;
textArea.style.opacity = "0";
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
var successful = document.execCommand('copy');
var msg = successful ? 'successful' : 'unsuccessful';
alert('Copying text command was ' + msg);
} catch (err) {
alert('Unable to copy value , error : ' + err.message);
}
document.body.removeChild(textArea);
}
</script>
Это работает сразу же, используя новейший API буфера обмена и взаимодействие с пользователем:
Начиная с Flash 10, вы можете копировать в буфер обмена только в том случае, если действие происходит в результате взаимодействия пользователя с объектом Flash. ( Прочитайте соответствующий раздел из объявления Adobe Flash 10)
Решение состоит в том, чтобы чрезмерно использовать объект Flash над кнопкой "Копировать" или любым другим элементом, который инициирует копирование. Zero Clipboard в настоящее время является лучшей библиотекой с этой реализацией. Опытные разработчики Flash могут просто захотеть создать свою собственную библиотеку.
Лучший способ скопировать текст внутри текстового поля. Используйте navigator.clipboard.writeText.
<input type="text" value="Hello World" id="myId">
<button onclick="myFunction()" >Copy text</button>
<script>
function myFunction() {
var copyText = document.getElementById("myId");
copyText.select();
copyText.setSelectionRange(0, 99999);
navigator.clipboard.writeText(copyText.value);
}
</script>
Уже много ответов, но мне нравится добавлять один (jQuery). Работает как брелок в любом браузере, в том числе и в мобильном (т.е. запрашивает безопасность, но когда вы принимаете его, он просто отлично работает).
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;
}
В вашем коде:
if( !appCopyToClipBoard( 'Hai there! This is copied to the clipboard.' ))
{ alert('Sorry, copy to clipboard failed.'); }
Я нашел следующее решение:
У меня есть текст в скрытом входе. Так как setSelectionRange
не работает со скрытыми вводами, я временно изменил тип на текст, скопировал текст, а затем снова сделал его скрытым. Если вы хотите скопировать текст из элемента, вы можете передать его в функцию и сохранить его содержимое в целевой переменной.
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;
}
<!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>
Копировать текст из HTML-ввода в буфер обмена
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>
Примечание:
document.execCommand()
метод не поддерживается в IE9 и более ранних версиях.
У меня была такая же проблема при создании пользовательского редактирования сетки (что-то вроде Excel) и совместимости с Excel. Мне пришлось поддерживать выбор нескольких ячеек, копирование и вставку.
Решение: создайте текстовую область, в которую вы будете вставлять данные для копирования пользователем (для меня, когда пользователь выбирает ячейки), установите фокус на нем (например, когда пользователь нажимает Ctrl) и выделите весь текст.
Таким образом, когда пользователь нажимает Ctrl + C, он / она получает скопированные ячейки, которые он / она выбрал. После тестирования просто изменил размер текстовой области до одного пикселя (я не проверял, будет ли он работать на дисплее: нет). Он хорошо работает во всех браузерах и прозрачен для пользователя.
Вставка - вы можете сделать то же самое (отличается от цели) - сосредоточьтесь на textarea и ловите события вставки, используя onpaste (в моем проекте я использую textareas в ячейках для редактирования).
Я не могу вставить пример (коммерческий проект), но вы поняли идею.
Я также хотел бы поделиться своим решением, это что-то вроде комбинации других ответов.
var copyToClipboard = function(textToCopy){
$("body")
.append($('<input type="text" 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();
}
Он использует jQuery, но это не обязательно, вы можете изменить это, если хотите. Я просто имел в своем распоряжении jQuery. Вы также можете добавить немного CSS, чтобы убедиться, что ввод не отображается. Например что-то вроде:
.textToCopyInput{opacity: 0; position: absolute;}
Или, конечно, вы могли бы также сделать некоторые встроенные стили
.append($('<input type="text" name="fname" style="opacity: 0; position: absolute;" class="textToCopyInput"/>' )