Как мне скопировать в буфер обмена в 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 получает доступ к буферу обмена пользователя?
29 ответов
Обзор
Существует три основных API браузера для копирования в буфер обмена:
-
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')
) получить доступ к буферу обмена см. ниже для получения более подробной информации.
Async + Fallback
Из-за уровня поддержки браузером нового API-интерфейса буфера обмена Async вы, вероятно, захотите использовать метод 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>
Обратите внимание, что этот фрагмент не работает должным образом во встроенном предварительном просмотре StackOverflow, вы можете попробовать его здесь: https://codepen.io/DeanMarkTaylor/pen/RMRaJX?editors=1011
API асинхронного буфера обмена
- Объявление Chrome 66 (март 2018 г.)
- Ссылка API Async Clipboard черновая документация
Обратите внимание, что в 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 ( 'Copy')
Остальная часть этого поста посвящена нюансам и деталям API document.execCommand('copy')
.
Поддержка браузера
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')
вызовы должны выполняться как прямой результат действий пользователя, например, щелкните обработчик события. Это мера, позволяющая избежать путаницы с буфером обмена пользователей, когда они этого не ожидают.
См. сообщение для разработчиков 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 ("copy")
- Удалить текстовую область из домена.
Примечание: вы не увидите текстовую область, так как она добавляется и удаляется в рамках одного и того же синхронного вызова кода 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);
}
}
}
Если вам нужно действительно простое решение (на интеграцию уходит менее 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, и мы недавно сделали капитальный ремонт нашего буфера обмена).
Копировать простой текст в буфер обмена относительно просто, если вы хотите сделать это во время события системного копирования (пользователь нажимает Ctrl C или использует меню браузера).
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 имеет некоторые параметры , которые позволяют пользователям предоставлять разрешения определенным сайтам для доступа к буфер обмена, но я не пробовал ничего из этого лично.
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
Вот мой взгляд на это ..
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;
}
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);
});
});
В одном из проектов, над которым я работал, плагин jQuery для копирования в буфер обмена, который использует
Я нашел следующее решение:
Обработчик нажатия клавиш создает тег «pre». Мы устанавливаем содержимое для копирования в этот тег, затем выбираем этот тег и возвращаем true в обработчике. Это вызывает стандартный обработчик Chrome и копирует выделенный текст.
И если вам нужно, вы можете установить тайм-аут для функции для восстановления предыдущего выбора. Моя реализация на 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.
Другие методы копируют обычный текст в буфер обмена. Чтобы скопировать 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();
С недавних пор Chrome 42+
и Firefox 41+
теперь поддерживает команду document.execCommand ('copy') . Поэтому я создал несколько функций для копирования между браузерами в буфер обмена, используя комбинацию старого ответа Тима Дауна и ответ разработчика Google :
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>
Гиш, я не уверен, почему никто еще не указал на это.
В 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).
Начиная с Flash 10, вы можете копировать в буфер обмена только в том случае, если действие происходит от взаимодействия пользователя с объектом Flash. ( прочитать соответствующий раздел из объявления Adobe Flash 10 )
Решение состоит в том, чтобы чрезмерно использовать флэш-объект над кнопкой «Копировать» или любым другим элементом, инициирующим копирование. Zero Clipboard в настоящее время является лучшей библиотекой с этой реализацией. Опытные разработчики Flash могут просто захотеть создать свою собственную библиотеку.
<!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>
Я нашел следующее решение:
У меня есть текст в скрытом вводе. Поскольку 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;
}
Копировать текст из 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 и более ранних версиях.
Источник : W3Schools - копировать текст в буфер обмена
Я собрал то, что считаю лучшим.
- Использует 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://stackoverflow.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;
}
};
})();
В браузерах, отличных от IE, вам нужно использовать небольшой flash-объект для работы с буфером обмена, например.
У меня была такая же проблема при создании пользовательского редактирования сетки (что-то вроде Excel) и совместимости с Excel. Мне пришлось поддерживать выбор нескольких ячеек, копирование и вставку.
Решение: создайте текстовую область, куда вы будете вставлять данные для копирования пользователем (для меня, когда пользователь выбирает ячейки), установите фокус на него (например, когда пользователь нажимает Ctrl ) и выделите весь текст.
Итак, когда пользователь нажимает Ctrl + C , он получает скопированные ячейки, которые он выбрал. После тестирования просто изменил размер текстовой области до 1 пикселя (я не проверял, будет ли он работать на дисплее: нет). Он хорошо работает во всех браузерах и прозрачен для пользователя.
Вставка - вы можете сделать то же самое (отличается от цели) - сосредоточиться на textarea и ловить события вставки, используя onpaste (в моем проекте я использую textareas в ячейках для редактирования).
Я не могу вставить пример (коммерческий проект), но у вас есть идея.
Я использовал clipboard.js
мы можем получить его по npm
npm install clipboard --save
а также на беседке
bower install clipboard --save
Использование & примеры приведены по адресу https://zenorocha.github.io/clipboard.js/
Уже много ответов, но мне нравится добавлять один (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.'); }
Это расширение ответа @ Chase с тем преимуществом, что оно будет работать для элементов IMAGE и TABLE, а не только для DIV в IE9.
if (document.createRange) {
// IE9 and modern browsers
var r = document.createRange();
r.setStartBefore(to_copy);
r.setEndAfter(to_copy);
r.selectNode(to_copy);
var sel = window.getSelection();
sel.addRange(r);
document.execCommand('Copy'); // does nothing on FF
} else {
// IE 8 and earlier. This stuff won't work on IE9.
// (unless forced into a backward compatibility mode,
// or selecting plain divs, not img or table).
var r = document.body.createTextRange();
r.moveToElementText(to_copy);
r.select()
r.execCommand('Copy');
}
Кажется, я неправильно понял вопрос, но для справки вы можете извлечь диапазон DOM (не для буфера обмена; совместим со всеми современными браузерами) и объединить его с событиями oncopy, onpaste и onbeforepaste, чтобы получить поведение буфера обмена. Вот код для достижения этого:
function clipBoard(sCommand) {
var oRange=contentDocument.createRange();
oRange.setStart(startNode, startOffset);
oRange.setEnd(endNode, endOffset);
/* This is where the actual selection happens.
in the above, startNode and endNode are dom nodes defining the beginning
and end of the "selection" respectively. startOffset and endOffset are
constants that are defined as follows:
END_TO_END: 2
END_TO_START: 3
NODE_AFTER: 1
NODE_BEFORE: 0
NODE_BEFORE_AND_AFTER: 2
NODE_INSIDE: 3
START_TO_END: 1
START_TO_START: 0
and would be used like oRange.START_TO_END */
switch(sCommand) {
case "cut":
this.oFragment=oRange.extractContents();
oRange.collapse();
break;
case "copy":
this.oFragment=oRange.cloneContents();
break;
case "paste":
oRange.deleteContents();
var cloneFragment=this.oFragment.cloneNode(true)
oRange.insertNode(cloneFragment);
oRange.collapse();
break;
}
}
Мой плохой. Это работает только в IE.
Вот еще один способ скопировать текст:
<p>
<a onclick="window.clipboardData.setData('text', document.getElementById('Test').innerText);">Copy</a>
</p>
Я тоже хотел бы поделиться своим решением, оно представляет собой сочетание некоторых ответов.
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"/>' )
Это была единственная вещь, которую я когда-либо получал, изучив различные способы поиска в интернете. Это грязная тема. Множество решений опубликовано по всему миру, и большинство из них НЕ работают. Это сработало для меня:
ПРИМЕЧАНИЕ. Этот код будет работать только в том случае, если он исполняется как прямой синхронный код, похожий на метод onClick. Если вы вызываете асинхронный ответ на ajax или любым другим асинхронным способом, он не будет работать
copyToClipboard(text) {
var copyText = document.createElement("input");
copyText.type = "text";
document.body.appendChild(copyText);
copyText.style = "display: inline; width: 1px;";
copyText.value = text;
copyText.focus();
document.execCommand("SelectAll");
document.execCommand("Copy");
copyText.remove();
}
Я действительно понимаю, что этот код будет показывать компонент шириной 1px на экране в течение миллисекунды, но решил не беспокоиться об этом, что другие могут решить при реальной проблеме.
Чтобы скопировать выделенный текст («Текст для копирования») в буфер обмена, создайте Bookmarklet (закладка браузера, которая выполняет Javsacript) и выполните его (щелкните по нему). Это создаст временную текстовую область.
Код от Github: