Каков наилучший способ скопировать текст в буфер обмена? (Мульти-браузер)
Я пробовал:
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 получает доступ к буферу пользователя?
Существует 3 основных API браузера для копирования в буфер обмена:
[navigator.clipboard.writeText]
document.execCommand('copy')
Не ожидайте, что команды, связанные с буфером обмена, будут работать, пока вы тестируете код в консоли. Обычно страница должна быть активной (Async Clipboard API) или требует взаимодействия с пользователем (например, щелчок пользователя), чтобы разрешить (document.execCommand('copy')
) доступ к буферу обмена, подробнее см. Ниже.
Из-за уровня поддержки браузером нового 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>
Обратите внимание, что этот фрагмент плохо работает во встроенном предварительном просмотре StackOverflow. Вы можете попробовать его здесь: https://codepen.io/DeanMarkTaylor/pen/RMRaJX?editors=1011.
Обратите внимание, что в 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);
});
Остальная часть этой статьи посвящена нюансам и деталям API document.execCommand('copy')
.
Поддержка 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 и 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 буфера обмена можно найти здесь: 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 буфера обмена все еще находится в стадии разработки, поэтому не забудьте провести тестирование.
var str = "word";
?
Автоматическое копирование в буфер обмена может быть опасным, поэтому большинство браузеров (кроме IE) делают это очень сложным. Лично я использую следующий простой трюк:
function copyToClipboard(text) {
window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
}
Пользователю предоставляется окно с приглашением, в котором уже выбран текст, который нужно скопировать. Теперь достаточно нажать Ctrl + C и Enter (чтобы закрыть окно) - и voila!
Теперь операция копирования буфера обмена SAFE, потому что пользователь делает это вручную (но довольно простым способом). Конечно, работает во всех браузерах.
<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 г.).
Примечание: вы не увидите текстовое поле, поскольку оно добавляется и удаляется в рамках одного и того же синхронного вызова кода Javascript.
Некоторые вещи, о которых следует помнить, если вы сами это реализуете:
Нижеприведенная функция должна обрабатывать все следующие проблемы как можно чище. Пожалуйста, оставьте комментарий, если вы обнаружите какие-либо проблемы или у вас есть предложения по его улучшению.
// 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 - отличная альтернатива некоторым более сложным решениям.
Это было написано одним из основателей Гитуба. Пример Flash embed code ниже:
<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}
с цветом.
zclip
не делает эту работу за меня.
Чтение и изменение буфера обмена с веб-страницы вызывает проблемы безопасности и конфиденциальности. Однако в 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" />
execCommand(\\'copy\\');
объясните, что такое execCommand(\\'copy\\');
делает, если не копировать в буфер обмена для IE? @mrBorna
Я недавно написал технический пост в блоге об этой самой проблеме (я работаю в 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 есть некоторые параметры, которые позволяют пользователям предоставлять разрешения определенным сайтам для доступа к буферу обмена, но я не пробовал ничего из этого лично.
Вот мое занятие на этом...
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;
}
\n
?
\r\n
для перевода строки
clipboard.js - небольшая, не-flash-утилита, которая позволяет копировать текстовые или 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
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>
Если вам нужна поддержка без флэш-памяти для iOS, вы просто добавляете fall-back:
clip.on( 'noflash', function ( client, args ) {
$("#copy").click(function(){
var txt = $(this).attr('data-clipboard-text');
prompt ("Copy link, then click OK.", txt);
});
});
В одном из проектов, над которым я работал, плагин jQuery для копирования в буфер обмена, использующий библиотеку Zero Clipboard.
Он проще в использовании, чем нативный плагин Zero Clipboard, если вы большой пользователь jQuery.
text()
вместо innerHTML()
если хотите ..
Geesh, не знаю, почему никто еще не указал на это.
В 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);
}
}
Используется в моем угловом 6+ коде, например:
<button mat-menu-item (click)="copySomething()">
<span>Copy link</span>
</button>
Если я передам строку, она копирует ее. Если ничего, копирует URL-адрес страницы.
Более гимнастика в буфер обмена может быть выполнена тоже. Подробнее см. Здесь:
https://developers.google.com/web/updates/2018/03/clipboardapi
Я нашел следующее решение:
В ручном манипуляторе создается тэг 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;
При вставке он создает textarea и работает одинаково.
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'). Таким образом, я создал несколько функций для копирования кросс-браузера в буфер обмена с помощью комбинации старого ответа Tim Down и Ответ разработчика 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>
Я использую это очень успешно (без 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).
<!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>
Начиная с Flash 10, вы можете копировать только в буфер обмена, если действие происходит от взаимодействия пользователя с объектом Flash. (Прочтите раздел, посвященный объявлению Adobe Flash 10)
Решением является чрезмерное создание флэш-объекта над кнопкой "Копировать" или какой-либо элемент, инициирующий копию. Zero Clipboard в настоящее время является лучшей библиотекой с этой реализацией. Опытные разработчики Flash могут просто захотеть создать свою собственную библиотеку.
Я нашел следующее решение:
У меня есть текст в скрытом входе. Поскольку 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() { /* Получить текстовое поле */ var copyText = document.getElementById( "myInput" ); /* Выберите текстовое поле */ copyText.select(); /* Скопируйте текст внутри текстового поля */ document.execCommand( "Copy" ); /* Оповещение скопированного текста */ alert ( "Скопированный текст:" + copyText.value); } Код>
<! - Текстовое поле - > < input type = "text" value = "Hello Friend" id = "myInput" > <! - Кнопка, используемая для копирования текста - > < button onclick = "myFunction()" > Копировать текст </button> Код>
Примечание. Метод
document.execCommand()
не поддерживается в IE9 и более ранних версиях.
Я собрал то, что считаю лучшим.
Вот он:
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, вам нужно использовать небольшой флэш-объект для управления буфером обмена, например
Уже много ответов, но мне нравится добавлять один (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.'); }
Я использовал clipboard.js
мы можем получить его на npm
npm install clipboard --save
а также на беседке
bower install clipboard --save
Использование и примеры на https://zenorocha.github.io/clipboard.js/
У меня была такая же проблема с созданием настраиваемого редактирования сетки (например, Excel) и совместимости с Excel. Мне пришлось поддерживать выбор нескольких ячеек, копирование и вставку.
Решение: создайте текстовое поле, в которое вы будете вставлять данные для копирования пользователем (для меня, когда пользователь выбирает ячейки), установите фокус на него (например, когда пользователь нажимает Ctrl) и выбирает весь текст,
Итак, когда пользователь нажал Ctrl + C, он получает скопированные ячейки, которые он выбрал. После тестирования просто изменив размер текстового поля на 1 пиксель (я не тестировал, будет ли он работать на дисплее: none). Он хорошо работает во всех браузерах и прозрачен для пользователя.
Вставка - вы можете сделать то же самое, что и это (отличается от вашей цели) - сосредоточьтесь на событиях textarea и catch paste, используя onpaste (в моем проекте я использую текстовые поля в ячейках для редактирования).
Я не могу вставить пример (коммерческий проект), но у вас есть идея.
Я нашел еще одно приятное решение LMCButton - небольшая анимационная кнопка перекрестного браузера. Одна функция JavaScript и кнопка swf. Простые варианты (подпись, пользовательский JavaScript).
Это расширение ответа @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');
}
Чтобы скопировать выделенный текст ( "Текст для копирования" ) в буфер обмена, создайте закладку закладки (закладку браузера, которая выполняет Javsacript) и запустите ее (щелкните по ней). Это создаст временную текстовую область.
Код из Github:
https://gist.github.com/stefanmaric/2abf96c740191cda3bc7a8b0fc905a7d
(function (text) {
var node = document.createElement('textarea');
var selection = document.getSelection();
node.textContent = text;
document.body.appendChild(node);
selection.removeAllRanges();
node.select();
document.execCommand('copy');
selection.removeAllRanges();
document.body.removeChild(node);
})('Text To Copy');
Это была единственная вещь, с которой я когда-либо работал, после того как я просмотрел различные способы по всему Интернету. Это грязная тема. Многие решения размещены по всему миру, и большинство из них НЕ работают. Это сработало для меня:
ПРИМЕЧАНИЕ. Этот код будет работать только при выполнении как прямой синхронный код с чем-то вроде метода onClick. Если вы вызываете асинхронный ответ на ajax или любым другим способом async, он не будет работать
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 широкий компонент заметно на экране в течение миллисекунды, но решил не беспокоиться об этом, и это то, что другие могут решить, если это реальная проблема.
Я тоже хотел бы поделиться своим решением, это немного комбинация между другими ответами.
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"/>' )
ng-clip
было самым простым решением для AngularJS.
Мой плохой. Это работает только в IE.
Здесь еще один способ скопировать текст:
<p>
<a onclick="window.clipboardData.setData('text', document.getElementById('Test').innerText);">Copy</a>
</p>
Кажется, я неправильно понял вопрос, но для справки вы можете извлечь диапазон 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;
}
}
Мне пришлось скопировать текст без ввода текста (текст в любом теге div/span) со страницы и придумал следующий код. Только трюк состоит в том, чтобы иметь скрытое поле, но как тип TEXT, не работает с типом скрытого.
function copyToClipboard(sID) {
var aField = document.getElementById("hiddenField");
aField.hidden = false;
aField.value = document.getElementById(sID).textContent;
aField.select();
document.execCommand("copy");
alert("Following text has been copied to the clipboard.\n\n" + aField.value);
aField.hidden = true;
}
И в HTML добавьте следующий
input type = "text" id = "hiddenField" style = "width: 5px; border: 0" /" > ...
Похоже, вы взяли код Greasemonkey\JavaScript Copy to Clipboard button или исходный источник этого фрагмента...
Этот код для Greasemonkey, следовательно, небезопасный. И я думаю, синтаксическая ошибка в IE происходит из ключевого слова const
, которое относится к Firefox (замените его на var
).
const
относится не только к Firefox, но и к конкретной версии JavaScript, которую не все браузеры реализуют должным образом.
const
был реализован только в Firefox и не был официальным (насколько я помню). Сегодня, конечно, почти все живые браузеры поддерживают это.
Насколько я знаю, работает только в Internet Explorer.
См. также "Динамические инструменты - копирование JavaScript в буфер обмена" , но для этого требуется, чтобы пользователь сначала изменил конфигурацию, и даже тогда он не кажется, работает.
Я собирался использовать clipboard.js, но на нем нет мобильного решения (пока)... поэтому я написал супер маленькую библиотеку:
https://github.com/ryanpcmcquen/cheval
Это либо скопирует текст (Desktop/Android/Safari 10+), либо, по крайней мере, выберите текст (более старые версии iOS). Минимизация - чуть более 1 КБ. На рабочем столе Safari (нажмите Command + C для копирования. Вам также не нужно писать какой-либо JavaScript для его использования.
Обновление 2015: в настоящее время существует возможность использовать document.execCommand
для работы с буфером обмена.
clipboard.js обеспечивает кросс-браузерный способ работы с буфером обмена (поддержка браузера)
По соображениям безопасности вы не можете этого сделать. Вы должны выбрать flash для копирования буфера обмена. Я предлагаю это; http://zeroclipboard.org/
Используя функцию Javascript, используя try/catch
, вы можете даже улучшить обработку ошибок, делая это следующим образом:
copyToClipboard() {
let el = document.getElementById('Test').innerText
el.focus(); // el.select();
try {
var successful = document.execCommand('copy');
if (successful) {
console.log('Copied Successfully! Do whatever you want next');
} else {
throw ('Unable to copy');
}
} catch (err) {
console.warn('Oops, Something went wrong ', err);
}
}
В дополнение к обновленному ответу Дин Тейлор (июль 2015 г.), я написал метод jQuery, смотрящий его пример.
/**
* Copies the current selected text to the SO clipboard
* This method must be called from an event to work with `execCommand()`
* @param {String} text Text to copy
* @param {Boolean} [fallback] Set to true shows a prompt
* @return Boolean Returns `true` if the text was copied or the user clicked on accept (in prompt), `false` otherwise
*/
var CopyToClipboard = function(text, fallback){
var fb = function () {
$t.remove();
if (fallback !== undefined && fallback) {
var fs = 'Please, copy the following text:';
if (window.prompt(fs, text) !== null) return true;
}
return false;
};
var $t = $('<textarea />');
$t.val(text).css({
width: '100px',
height: '40px'
}).appendTo('body');
$t.select();
try {
if (document.execCommand('copy')) {
$t.remove();
return true;
}
fb();
}
catch (e) {
fb();
}
};
В Chrome вы можете использовать copy('the text or variable etc')
. Хотя это не кросс-браузер (и не работает в фрагменте?), вы можете добавить его в другие кросс-браузерные ответы.
Если вы читаете текст из буфера обмена в расширении Chrome, с разрешенным разрешением "clipboardRead", вы можете использовать ниже код:
function readTextFromClipboardInChromeExtension() {
var ta = $('<textarea/>');
$('body').append(ta);
ta.focus();
document.execCommand('paste');
var text = ta.val();
ta.blur();
ta.remove();
return text;
}
@Jimbo, вот простой буфер обмена на основе ajax/session для одного и того же веб-сайта.
Обратите внимание, что сеанс должен быть включен и действителен, и этот soln. работает на том же сайте. Я протестировал его на Codeigniter, но столкнулся с проблемой session/ajax, но this решил эту проблему. Если вы не хотите играть с сеансами, используйте таблицу DB.
JS/JQuery
<script type="text/javascript">
$(document).ready(function() {
$("#copy_btn_id").click(function(){
$.post("<?php echo base_url();?>ajax/foo_copy/"+$(this).val(), null,
function(data){
//copied successfully
}, "html"
);
});
$("#paste_btn_id").click(function() {
$.post("<?php echo base_url();?>ajax/foo_paste/", null,
function(data) {
$('#paste_btn_id').val(data);
}, "html"
);
});
});
</script>
html
<input type='text' id='copy_btn_id' onclick='this.select();' value='myvalue' />
<input type='text' id='paste_btn_id' value='' />
PHP
<?php
class Ajax extends CI_Controller {
public function foo_copy($val){
$this->session->set_userdata(array('clipboard_val' => $val));
}
public function foo_paste(){
echo $this->session->userdata('clipboard_val');
exit();
}
}
?>
Если скопированная ссылка должна быть вставлена на том же сайте, то простым решением будет
выделите текст перед нажатием простой кнопки копирования html, а затем при нажатии на него текстовый контент сохраняется в сеансе. и там, где он должен быть вставлен, есть кнопка вставки.
** Я знаю, это не стойкое и универсальное решение, а его что-то:)
Использование document.execCommand
сделает всю работу за вас...
Используя это, вы можете вырезать, копировать и вставлять также...
Это одна из простых функций копирования буфера обмена, которая копирует все из входного текста...
function copyInputText() {
var copyText = document.querySelector("#input");
copyText.select();
document.execCommand("copy");
}
document.querySelector("#copy").addEventListener("click", copyInputText);
<input id="input" type="text" />
<button id="copy">Copy</button>
Для получения дополнительной информации посетите здесь
Это единственное, что сработало для меня:
let textarea = document.createElement('textarea');
textarea.setAttribute('type', 'hidden');
textarea.textContent = 'the string you want to copy';
document.body.appendChild(textarea);
textarea.select();
document.execCommand('copy');
Просто добавив мои ответы.
Это лучшее. Так много побед.
var toClipboard = function(text) {
var doc = document;
// Create temp element
var textarea = doc.createElement('textarea');
textarea.style.position = 'absolute';
textarea.style.opacity = '0';
textarea.textContent = text;
doc.body.appendChild(textarea);
textarea.focus();
textarea.setSelectionRange(0, textarea.value.length);
// copy the selection
var success;
try {
success = doc.execCommand("copy");
} catch(e) {
success = false;
}
textarea.remove();
return success;
}
textarea.style.position = 'fixed';
будет лучше
Я скомпилировал несколько функций в простом решении, чтобы охватить все случаи, с быстрым возвратом, если это необходимо.
window.copyToClipboard = function(text) {
// IE specific
if (window.clipboardData && window.clipboardData.setData) {
return clipboardData.setData("Text", text);
}
// all other modern
target = document.createElement("textarea");
target.style.position = "absolute";
target.style.left = "-9999px";
target.style.top = "0";
target.textContent = text;
document.body.appendChild(target);
target.focus();
target.setSelectionRange(0, target.value.length);
// copy the selection of fall back to prompt
try {
document.execCommand("copy");
target.remove();
console.log('Copied to clipboard: "'+text+'"');
} catch(e) {
console.log("Can't copy string on this browser. Try to use Chrome, Firefox or Opera.")
window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
}
}
Протестируйте его здесь https://jsfiddle.net/jv0avz65/
После поиска решения, которое поддерживает Safari и другие браузеры (IE9 +),
Я использую то же, что и Github: ZeroClipboard
http://zeroclipboard.org/index-v1.x.html
HTML
<html>
<body>
<button id="copy-button" data-clipboard-text="Copy Me!" title="Click to copy me.">Copy to Clipboard</button>
<script src="ZeroClipboard.js"></script>
<script src="main.js"></script>
</body>
</html>
JS
var client = new ZeroClipboard(document.getElementById("copy-button"));
client.on("ready", function (readyEvent) {
// alert( "ZeroClipboard SWF is ready!" );
client.on("aftercopy", function (event) {
// `this` === `client`
// `event.target` === the element that was clicked
event.target.style.display = "none";
alert("Copied text to clipboard: " + event.data["text/plain"]);
});
});
Это можно сделать, просто используя комбинацию getElementbyId, Select(), blur() и команды copy.
Заметка
Метод select() выделяет весь текст в элементе или элементе с текстовым полем. Это может не работать на кнопке
использование
let copyText = document.getElementById('input-field');
copyText.select()
document.execCommand("copy");
copyReferal.blur()
document.getElementbyId('help-text').textContent = 'Copied'
Метод blur() удалит некрасиво выделенную часть вместо того, что вы можете показать в красивом сообщении, что ваш контент был успешно скопирован
Вот мое решение
var codeElement = document.getElementsByClassName("testelm") && document.getElementsByClassName("testelm").length ? document.getElementsByClassName("testelm")[0] : "";
if (codeElement != "") {
var e = document.createRange();
e.selectNodeContents(codeElement);
var selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(e);
document.execCommand("Copy");
selection.removeAllRanges();
}
Здесь элегантное решение для Angular 5.x +:
компонент:
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
ElementRef,
EventEmitter,
Input,
OnInit,
Output,
Renderer2,
ViewChild
} from '@angular/core';
@Component({
selector: 'copy-to-clipboard',
templateUrl: './copy-to-clipboard.component.html',
styleUrls: ['./copy-to-clipboard.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class CopyToClipboardComponent implements OnInit {
@ViewChild('input') input: ElementRef;
@Input() size = 'md';
@Input() theme = 'complement';
@Input() content: string;
@Output() copied: EventEmitter<string> = new EventEmitter<string>();
@Output() error: EventEmitter<string> = new EventEmitter<string>();
constructor(private renderer: Renderer2) {}
ngOnInit() {}
copyToClipboard() {
const rootElement = this.renderer.selectRootElement(this.input.nativeElement);
// 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)) {
this.renderer.setAttribute(this.input.nativeElement, 'contentEditable', 'true');
const range = document.createRange();
range.selectNodeContents(this.input.nativeElement);
const sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
rootElement.setSelectionRange(0, 999999);
} else {
rootElement.select();
}
try {
document.execCommand('copy');
this.copied.emit();
} catch (err) {
this.error.emit(err);
}
};
}
Шаблон:
<button class="btn btn-{{size}} btn-{{theme}}" type="button" (click)="copyToClipboard()">
<ng-content></ng-content>
</button>
<input #input class="hidden-input" [ngModel]="content">
Стили:
.hidden-input {
position: fixed;
top: 0;
left: 0;
width: 1px;
height: 1px;
padding: 0;
border: 0;
box-shadow: none;
outline: none;
background: transparent;
}
Я собрал решение, представленное @dean-taylor, вместе с другим кодом select/unselect из другого места в плагин jQuery, доступный на NPM:
https://www.npmjs.com/package/jquery.text-select
npm install --save jquery.text-select
<script>
$(document).ready(function(){
$("#selectMe").selectText(); // Hightlight / select the text
$("#selectMe").selectText(false); // Clear the selection
$("#copyMe").copyText(); // Copy text to clipboard
});
</script>
Более подробную информацию о методах/событиях можно найти на странице реестра НПМ выше.