Copia negli appunti utilizzando Javascript in iOS

Sto usando questa funzione per copiare un URL negli appunti:

function CopyUrl($this){ var querySelector = $this.next().attr("id"); var emailLink = document.querySelector("#"+querySelector); var range = document.createRange(); range.selectNode(emailLink); window.getSelection().addRange(range); try { // Now that we've selected the anchor text, execute the copy command var successful = document.execCommand('copy', false, null); var msg = successful ? 'successful' : 'unsuccessful'; if(true){ $this.addClass("copied").html("Copied"); } } catch(err) { console.log('Oops, unable to copy'); } // Remove the selections - NOTE: Should use // removeRange(range) when it is supported window.getSelection().removeAllRanges(); } 

Tutto funziona bene sui browser desktop, ma non su dispositivi iOS, in cui la funzione restituisce correttamente, ma i dati non vengono copiati negli appunti. Cosa sta causando questo e come posso risolvere questo problema?

Aggiornare! iOS> = 10

Sembra che con l’aiuto di gamme di selezione e qualche piccolo hack è ansible copiare direttamente negli appunti su iOS (> = 10) Safari. L’ho testato personalmente su iPhone 5C iOS 10.3.3 e iPhone 8 iOS 11.1. Tuttavia, sembrano esserci alcune restrizioni, che sono:

  1. Il testo può essere copiato solo da elementi e .
  2. Se l’elemento che contiene il testo non si trova in un

    , deve essere contenteditable .

  3. L’elemento che contiene il testo non deve essere di readonly (sebbene tu possa provare, questo non è un metodo “ufficiale” documentato ovunque).
  4. Il testo all’interno dell’elemento deve essere compreso nell’intervallo di selezione.

Per coprire tutti e quattro questi “requisiti”, dovrai:

  1. Metti il ​​testo da copiare all’interno di un elemento o .
  2. Salvare i vecchi valori di contenteditable e readonly dell’elemento per poterli ripristinare dopo la copia.
  3. Modifica contenteditable in true e readonly in false .
  4. Crea un intervallo per selezionare l’elemento desiderato e aggiungerlo alla selezione della finestra.
  5. Imposta l’ intervallo di selezione per l’intero elemento.
  6. Ripristina i precedenti valori contenteditable e readonly .
  7. Esegui execCommand('copy') .

Ciò causerà lo spostamento del cursore del dispositivo dell’utente e selezionerà tutto il testo nell’elemento desiderato, quindi eseguirà automaticamente il comando di copia. L’utente vedrà il testo selezionato e verrà mostrato il suggerimento con le opzioni selezionate / copia / incolla.

Ora, questo sembra un po ‘complicato e troppo di una semplice seccatura per emettere un comando di copia, quindi non sono sicuro che questa fosse una scelta progettuale voluta da Apple, ma chissà … nel frattempo, questo funziona attualmente su iOS> = 10 .

Detto questo, è ansible utilizzare polyfill come questo per semplificare questa azione e renderla compatibile con browser diversi (grazie a @Toskan per il collegamento nei commenti).

Esempio di lavoro

Per riassumere, il codice necessario è simile a questo:

 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); // A big number, to cover anything that could be inside the element. el.contentEditable = oldContentEditable; el.readOnly = oldReadOnly; document.execCommand('copy'); } 

Nota che il parametro el per questa funzione deve essere un o .

Vecchia risposta: versioni precedenti di iOS

Su iOS <10 ci sono alcune restrizioni per Safari (che in realtà sono misure di sicurezza) all’API degli Appunti :

  • Spara gli eventi di copy solo su una selezione valida e cut e paste solo in campi modificabili focalizzati.
  • Supporta solo la lettura / scrittura degli appunti OS tramite i tasti di scelta rapida, non tramite document.execCommand() . Si noti che “chiave di shorcut” indica alcuni elementi selezionabili (ad esempio, il menu di azione copia / incolla o la scorciatoia da tastiera iOS personalizzata) o il tasto fisico (ad esempio la tastiera bluetooth collegata).
  • Non supporta il costruttore ClipboardEvent .

Quindi (almeno per ora) non è ansible copiare a livello di codice testo / valore negli appunti su un dispositivo iOS usando Javascript . Solo l’utente può decidere se copiare qualcosa.

È tuttavia ansible selezionare qualcosa a livello di codice , in modo che l’utente debba solo premere il comando “Copia” mostrato nella selezione. Questo può essere ottenuto con lo stesso codice esatto sopra, rimuovendo semplicemente execCommand('copy') , che in effetti non funzionerà.

Ho cercato alcune soluzioni e ne ho trovata una che funziona davvero: http://www.seabreezecomputers.com/tips/copy2clipboard.htm

Fondamentalmente, l’esempio potrebbe essere qualcosa di simile:

 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(); 

Per motivi di sicurezza, iOS Safari consente solo document.execCommand('copy') per il testo all’interno di un contenitore contentEditable .

La soluzione alternativa è rilevare iOS Safari e triggersre rapidamente contentEditable prima di eseguire document.execCommand('copy') .

La seguente funzione dovrebbe funzionare in tutti i browser / dispositivi e accetta un selettore CSS o 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; } 
   

Per favore controlla la mia soluzione.

Funziona su Safari (testato su iPhone 7 e iPad) e su altri browser.

 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/

Spero che ti aiuti.

Saluti.

  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(); });