Aktualisieren! iOS> = 10
Sieht so aus, als ob es mit Hilfe von Auswahlbereichen und ein wenig Hack möglich ist, auf iOS (> = 10) Safari direkt in die Zwischenablage zu kopieren. Ich persönlich habe dies auf iPhone 5C iOS 10.3.3 und iPhone 8 iOS 11.1 getestet. Es scheint jedoch einige Einschränkungen zu geben:
- Text kann nur von
<input>
und <textarea>
Elementen kopiert werden.
- Wenn sich das Element, das den Text enthält, nicht in a befindet
<form>
, muss es sein contenteditable
.
- Das Element, das den Text enthält, darf nicht sein
readonly
(obwohl Sie es versuchen können, ist dies keine "offizielle" Methode, die irgendwo dokumentiert ist).
- Der Text innerhalb des Elements muss sich im Auswahlbereich befinden.
Um alle vier dieser "Anforderungen" abzudecken, müssen Sie:
- Fügen Sie den zu kopierenden Text in ein
<input>
oder <textarea>
-Element ein.
- Speichern Sie die alten Werte von
contenteditable
und readonly
des Elements, um sie nach dem Kopieren wiederherstellen zu können.
- Wechseln Sie
contenteditable
zu true
und readonly
zu false
.
- Erstellen Sie einen Bereich , um das gewünschte Element auszuwählen, und fügen Sie es der Fensterauswahl hinzu.
- Stellen Sie den Auswahlbereich für das gesamte Element ein.
- Stellen Sie die vorherigen
contenteditable
und readonly
Werte wieder her.
- Ausführen
execCommand('copy')
.
Dadurch wird das Caret des Geräts des Benutzers verschoben und der gesamte Text in dem gewünschten Element ausgewählt. Anschließend wird automatisch der Kopierbefehl ausgegeben. Der Benutzer sieht den ausgewählten Text und der Tooltip mit den Optionen Auswählen / Kopieren / Einfügen wird angezeigt.
Das sieht ein bisschen kompliziert und zu umständlich aus, um nur einen Kopierbefehl auszugeben. Ich bin mir also nicht sicher, ob dies eine beabsichtigte Designentscheidung von Apple war, aber wer weiß ... in der Zwischenzeit funktioniert dies derzeit unter iOS> = 10 .
Vor diesem Hintergrund könnten Polyfills wie diese verwendet werden, um diese Aktion zu vereinfachen und browserübergreifend kompatibel zu machen (danke @Toskan für den Link in den Kommentaren).
Arbeitsbeispiel
Zusammenfassend sieht der Code, den Sie benötigen, folgendermaßen aus:
function iosCopyToClipboard(el) {
var oldContentEditable = el.contentEditable,
oldReadOnly = el.readOnly,
range = document.createRange();
el.contentEditable = true;
el.readOnly = false;
range.selectNodeContents(el);
var s = window.getSelection();
s.removeAllRanges();
s.addRange(range);
el.setSelectionRange(0, 999999);
el.contentEditable = oldContentEditable;
el.readOnly = oldReadOnly;
document.execCommand('copy');
}
Beachten Sie, dass der el
Parameter für diese Funktion ein <input>
oder ein sein muss <textarea>
.
Alte Antwort: frühere iOS-Versionen
Unter iOS <10 gibt es einige Einschränkungen für Safari (die eigentlich Sicherheitsmaßnahmen sind) für die Zwischenablage-API :
- Es löst
copy
Ereignisse nur für eine gültige Auswahl cut
und paste
nur in fokussierten bearbeitbaren Feldern aus.
- Es unterstützt nur das Lesen / Schreiben der OS-Zwischenablage über Tastenkombinationen, nicht über
document.execCommand()
. Beachten Sie, dass "Shorcut-Taste" eine anklickbare (z. B. Aktionsmenü zum Kopieren / Einfügen oder benutzerdefinierte iOS-Tastaturkürzel) oder physische Taste (z. B. verbundene Bluetooth-Tastatur) bedeutet.
- Der
ClipboardEvent
Konstruktor wird nicht unterstützt .
Daher ist es (zumindest ab sofort) nicht möglich, Text / Wert in der Zwischenablage auf einem iOS-Gerät mithilfe von Javascript programmgesteuert zu kopieren . Nur der Benutzer kann entscheiden, ob er etwas kopiert.
Es ist jedoch möglich, etwas programmgesteuert auszuwählen , so dass der Benutzer nur den in der Auswahl angezeigten Tooltip "Kopieren" drücken muss. Dies kann mit genau dem gleichen Code wie oben erreicht werden, indem nur der entfernt wird execCommand('copy')
, was in der Tat nicht funktionieren wird.
Ich habe nach einigen Lösungen gesucht und eine gefunden, die tatsächlich funktioniert: http://www.seabreezecomputers.com/tips/copy2clipboard.htm
Grundsätzlich könnte ein Beispiel so etwas sein wie:
var $input = $(' some input/textarea '); $input.val(result); if (navigator.userAgent.match(/ipad|ipod|iphone/i)) { var el = $input.get(0); var editable = el.contentEditable; var readOnly = el.readOnly; el.contentEditable = 'true'; el.readOnly = 'false'; var range = document.createRange(); range.selectNodeContents(el); var sel = window.getSelection(); sel.removeAllRanges(); sel.addRange(range); el.setSelectionRange(0, 999999); el.contentEditable = editable; el.readOnly = readOnly; } else { $input.select(); } document.execCommand('copy'); $input.blur();
quelle
Dies ist meine browserübergreifende Implementierung
Sie können es testen, indem Sie das folgende Snippet ausführen
Beispiel:
copyToClipboard("Hello World");
/** * Copy a string to clipboard * @param {String} string The string to be copied to clipboard * @return {Boolean} returns a boolean correspondent to the success of the copy operation. */ function copyToClipboard(string) { let textarea; let result; try { textarea = document.createElement('textarea'); textarea.setAttribute('readonly', true); textarea.setAttribute('contenteditable', true); textarea.style.position = 'fixed'; // prevent scroll from jumping to the bottom when focus is set. textarea.value = string; document.body.appendChild(textarea); textarea.focus(); textarea.select(); const range = document.createRange(); range.selectNodeContents(textarea); const sel = window.getSelection(); sel.removeAllRanges(); sel.addRange(range); textarea.setSelectionRange(0, textarea.value.length); result = document.execCommand('copy'); } catch (err) { console.error(err); result = null; } finally { document.body.removeChild(textarea); } // manual copy fallback using prompt if (!result) { const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0; const copyHotkey = isMac ? '⌘C' : 'CTRL+C'; result = prompt(`Press ${copyHotkey}`, string); // eslint-disable-line no-alert if (!result) { return false; } } return true; }
Demo: <button onclick="copyToClipboard('It works!\nYou can upvote my answer now :)') ? this.innerText='Copied!': this.innerText='Sorry :(' ">Click here</button> <p> <textarea placeholder="(Testing area) Paste here..." cols="80" rows="4"></textarea> </p>
quelle
textarea.focus();
aus der vorgeschlagenen Lösung - ansonsten wird unabhängig von der Einstellung nach unten gescrollttextarea.style.position = 'fixed';
Problem: iOS Safari lässt nur
document.execCommand('copy')
Text in einemcontentEditable
Container zu.Lösung: Erkennen Sie iOS Safari und schalten Sie
contentEditable
vor der Ausführung schnell umdocument.execCommand('copy')
.Die folgende Funktion funktioniert in allen Browsern. Aufruf mit einem CSS Selector oder HTMLElement :
function copyToClipboard(el) { // resolve the element el = (typeof el === 'string') ? document.querySelector(el) : el; // handle iOS as a special case if (navigator.userAgent.match(/ipad|ipod|iphone/i)) { // save current contentEditable/readOnly status var editable = el.contentEditable; var readOnly = el.readOnly; // convert to editable with readonly to stop iOS keyboard opening el.contentEditable = true; el.readOnly = true; // create a selectable range var range = document.createRange(); range.selectNodeContents(el); // select the range var selection = window.getSelection(); selection.removeAllRanges(); selection.addRange(range); el.setSelectionRange(0, 999999); // restore contentEditable/readOnly to original state el.contentEditable = editable; el.readOnly = readOnly; } else { el.select(); } // execute copy command document.execCommand('copy'); }
input { font-size: 14px; font-family: tahoma; } button { font-size: 14px; font-family: tahoma; }
<input class="important-message" type="text" value="Hello World" /> <button onclick="copyToClipboard('.important-message')">Copy</button>
quelle
readOnly
. Hoffe das hilft anderen!Bitte überprüfen Sie meine Lösung.
Es funktioniert auf Safari (getestet auf iPhone 7 und iPad) und in anderen Browsern.
window.Clipboard = (function(window, document, navigator) { var textArea, copy; function isOS() { return navigator.userAgent.match(/ipad|iphone/i); } function createTextArea(text) { textArea = document.createElement('textArea'); textArea.value = text; document.body.appendChild(textArea); } function selectText() { var range, selection; if (isOS()) { range = document.createRange(); range.selectNodeContents(textArea); selection = window.getSelection(); selection.removeAllRanges(); selection.addRange(range); textArea.setSelectionRange(0, 999999); } else { textArea.select(); } } function copyToClipboard() { document.execCommand('copy'); document.body.removeChild(textArea); } copy = function(text) { createTextArea(text); selectText(); copyToClipboard(); }; return { copy: copy }; })(window, document, navigator); // How to use Clipboard.copy('text to be copied');
https://gist.github.com/rproenca/64781c6a1329b48a455b645d361a9aa3 https://fiddle.jshell.net/k9ejqmqt/1/
Hoffe das hilft dir.
Grüße.
quelle
Meine Lösung wurde erstellt, indem andere Antworten von dieser Seite kombiniert wurden.
Im Gegensatz zu den anderen Antworten ist es nicht erforderlich, dass Sie bereits ein Element auf der Seite haben. Es wird ein eigenes Textfeld erstellt und anschließend das Chaos beseitigt.
function copyToClipboard(str) { var el = document.createElement('textarea'); el.value = str; el.setAttribute('readonly', ''); el.style = {position: 'absolute', left: '-9999px'}; document.body.appendChild(el); if (navigator.userAgent.match(/ipad|ipod|iphone/i)) { // save current contentEditable/readOnly status var editable = el.contentEditable; var readOnly = el.readOnly; // convert to editable with readonly to stop iOS keyboard opening el.contentEditable = true; el.readOnly = true; // create a selectable range var range = document.createRange(); range.selectNodeContents(el); // select the range var selection = window.getSelection(); selection.removeAllRanges(); selection.addRange(range); el.setSelectionRange(0, 999999); // restore contentEditable/readOnly to original state el.contentEditable = editable; el.readOnly = readOnly; } else { el.select(); } document.execCommand('copy'); document.body.removeChild(el); }
quelle
Schön, hier ist der Typoskript-Refactor von oben, falls jemand interessiert ist (geschrieben als ES6-Modul):
type EditableInput = HTMLTextAreaElement | HTMLInputElement; const selectText = (editableEl: EditableInput, selectionStart: number, selectionEnd: number) => { const isIOS = navigator.userAgent.match(/ipad|ipod|iphone/i); if (isIOS) { const range = document.createRange(); range.selectNodeContents(editableEl); const selection = window.getSelection(); // current text selection selection.removeAllRanges(); selection.addRange(range); editableEl.setSelectionRange(selectionStart, selectionEnd); } else { editableEl.select(); } }; const copyToClipboard = (value: string): void => { const el = document.createElement('textarea'); // temporary element el.value = value; el.style.position = 'absolute'; el.style.left = '-9999px'; el.readOnly = true; // avoid iOs keyboard opening el.contentEditable = 'true'; document.body.appendChild(el); selectText(el, 0, value.length); document.execCommand('copy'); document.body.removeChild(el); }; export { copyToClipboard };
quelle
Das hat bei mir funktioniert. Der Code wird in allen aktuellen Browsern getestet und funktioniert.
function copyToClipboard(textToCopy) { var textArea; function isOS() { //can use a better detection logic here return navigator.userAgent.match(/ipad|iphone/i); } function createTextArea(text) { textArea = document.createElement('textArea'); textArea.readOnly = true; textArea.contentEditable = true; textArea.value = text; document.body.appendChild(textArea); } function selectText() { var range, selection; if (isOS()) { range = document.createRange(); range.selectNodeContents(textArea); selection = window.getSelection(); selection.removeAllRanges(); selection.addRange(range); textArea.setSelectionRange(0, 999999); } else { textArea.select(); } } function copyTo() { document.execCommand('copy'); document.body.removeChild(textArea); } createTextArea(textToCopy); selectText(); copyTo(); }
Die Idee ist, einen gefälschten Textbereich zu erstellen, ihn zu DOM hinzuzufügen, contentEditable & readOnly als true festzulegen. Erstellen Sie einen Bereich, um das gewünschte Element auszuwählen, und fügen Sie es der Fensterauswahl hinzu. Stellen Sie den Auswahlbereich für das gesamte Element ein. Führen Sie dann execCommand ('copy') aus. Möglicherweise stellen Sie eine große Zahl (999999) in der setSelectionRange () -Methode fest. Nun, es soll alles abdecken, was sich innerhalb des Elements befinden könnte. Weitere Informationen zum Bereich finden Sie in den MDN-Dokumenten: https://developer.mozilla.org/en-US/docs/Web/API/Range
Testlauf (funktioniert in der folgenden Geräte- / Browserkombination)
iPhone (iOS> = 10) - Safari, Chrome
Android - Chrome, FF
Mac - Chrome, FF, Safari
Windows - Chrome, IE, FF
Ich habe Versionen nicht speziell erwähnt, da ich die neuesten Versionen getestet habe, die mir zum Zeitpunkt des Schreibens dieses Beitrags zur Verfügung standen. Hier ist eine detaillierte Beschreibung derselben: https://josephkhan.me/javascript-copy-clipboard-safari/
quelle
iOS 13.4 und neuer
Ab Version 13.4 unterstützt iOS Safari die moderne asynchrone Zwischenablage-API:
Wie bei allem in JavaScript ist die neuere API etwa 1000-mal besser, aber Sie benötigen immer noch einen groben Fallback-Code, da einige Ihrer Benutzer einige Jahre lang auf alten Versionen arbeiten werden.
So verwenden Sie die neue API für die Zwischenablage mit dem Code in der ursprünglichen Frage:
function CopyUrl($this){ var querySelector = $this.next().attr("id"); var emailLink = document.querySelector("#"+querySelector); if (navigator.clipboard) { var myText = emailLink.textContent; navigator.clipboard.writeText(myText).then(function() { // Do something to indicate the copy succeeded }).catch(function() { // Do something to indicate the copy failed }); } else { // Here's where you put the fallback code for older browsers. } }
quelle
Dieser arbeitete für mich für ein schreibgeschütztes Eingabeelement.
copyText = input => { const isIOSDevice = navigator.userAgent.match(/ipad|iphone/i); if (isIOSDevice) { input.setSelectionRange(0, input.value.length); } else { input.select(); } document.execCommand('copy'); };
quelle
input.setSelectionRange(0, input.value.length)
kurz danach ausführen,input.select
da es nicht weh tutMeine Funktion für iOS und andere Browser, die nach dem Testen auf iOS in die Zwischenablage kopiert wurden: 5c, 6,7
/** * Copies to Clipboard value * @param {String} valueForClipboard value to be copied * @param {Boolean} isIOS is current browser is Ios (Mobile Safari) * @return {boolean} shows if copy has been successful */ const copyToClipboard = (valueForClipboard, isIOS) => { const textArea = document.createElement('textarea'); textArea.value = valueForClipboard; textArea.style.position = 'absolute'; textArea.style.left = '-9999px'; // to make it invisible and out of the reach textArea.setAttribute('readonly', ''); // without it, the native keyboard will pop up (so we show it is only for reading) document.body.appendChild(textArea); if (isIOS) { const range = document.createRange(); range.selectNodeContents(textArea); const selection = window.getSelection(); selection.removeAllRanges(); // remove previously selected ranges selection.addRange(range); textArea.setSelectionRange(0, valueForClipboard.length); // this line makes the selection in iOS } else { textArea.select(); // this line is for all other browsers except ios } try { return document.execCommand('copy'); // if copy is successful, function returns true } catch (e) { return false; // return false to show that copy unsuccessful } finally { document.body.removeChild(textArea); // delete textarea from DOM } };
obige Antwort zu contenteditable = true. Ich denke, gehört nur zu divs. Und für
<textarea>
ist nicht anwendbar.Die isIOS-Variable kann als überprüft werden
const isIOS = navigator.userAgent.match(/ipad|ipod|iphone/i);
quelle
Die Zwischenablage-API wurde in Safari 13.1 hinzugefügt. Siehe hier https://webkit.org/blog/10247/new-webkit-features-in-safari-13-1/
Es ist jetzt so einfach wie
navigator.clipboard.writeText("Text to copy")
quelle
Dies verbessert die Antwort von Marco, indem der Text als Variable übergeben werden kann. Dies funktioniert auf ios> 10. Dies funktioniert nicht unter Windows.
function CopyToClipboardIOS(TheText) { var el=document.createElement('input'); el.setAttribute('style','position:absolute;top:-9999px'); el.value=TheText; document.body.appendChild(el); var range = document.createRange(); el.contentEditable=true; el.readOnly = false; range.selectNodeContents(el); var s=window.getSelection(); s.removeAllRanges(); s.addRange(range); el.setSelectionRange(0, 999999); document.execCommand('copy'); el.remove(); }
quelle
<input id="copyIos" type="hidden" value=""> var clipboard = new Clipboard('.copyUrl'); //兼容ios复制 $('.copyUrl').on('click',function() { var $input = $('#copyIos'); $input.val(share_url); if (navigator.userAgent.match(/ipad|ipod|iphone/i)) { clipboard.on('success', function(e) { e.clearSelection(); $.sDialog({ skin: "red", content: 'copy success!', okBtn: false, cancelBtn: false, lock: true }); console.log('copy success!'); }); } else { $input.select(); } //document.execCommand('copy'); $input.blur(); });
quelle