sirve que para funciona descargar javascript ios copy mobile-safari clipboard

que - Copiar al portapapeles usando Javascript en iOS



javascript no funciona en ipad (11)

Estoy usando esta función para copiar una URL en el portapapeles:

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

Todo funciona bien en los navegadores de escritorio, pero no en dispositivos iOS, donde mi función regresa con éxito, pero los datos no se copian en el portapapeles. ¿Qué está causando esto y cómo podría resolver este problema?


¡Actualizar! iOS> = 10

Parece que con la ayuda de rangos de selección y algún pequeño truco, es posible copiar directamente al portapapeles en iOS (> = 10) Safari. Personalmente probé esto en iPhone 5C iOS 10.3.3 y iPhone 8 iOS 11.1. Sin embargo, parece haber algunas restricciones, que son:

  1. El texto solo se puede copiar de los elementos <input> y <textarea> .
  2. Si el elemento que contiene el texto no está dentro de un <form> , entonces debe estar contenteditable .
  3. El elemento que contiene el texto no debe ser de readonly (aunque puede intentarlo, este no es un método "oficial" documentado en ninguna parte).
  4. El texto dentro del elemento debe estar en el rango de selección.

Para cubrir estos cuatro "requisitos", deberá:

  1. Coloque el texto a copiar dentro de un elemento <input> o <textarea> .
  2. Guarde los valores antiguos de contenteditable y readonly del elemento para poder restaurarlos después de la copia.
  3. Cambie contenteditable a true y readonly a false .
  4. Cree un range para seleccionar el elemento deseado y agréguelo a la selección de la ventana.
  5. Establezca el rango de selección para todo el elemento.
  6. Restaurar los valores anteriores de readonly y de readonly .
  7. Ejecute execCommand(''copy'') .

Esto hará que el dispositivo del usuario se mueva y seleccione todo el texto en el elemento que desee, y luego emita automáticamente el comando copiar. El usuario verá el texto seleccionado y se mostrará la información sobre herramientas con las opciones seleccionar / copiar / pegar.

Ahora, esto parece un poco complicado y demasiado complicado para simplemente emitir un comando de copia, por lo que no estoy seguro de que Apple haya elegido esta opción de diseño, pero quién sabe ... mientras tanto, esto actualmente funciona en iOS> = 10 .

Dicho esto, los polyfills como este podrían usarse para simplificar esta acción y hacer que sea compatible con @Toskan navegadores (gracias @Toskan por el enlace en los comentarios).

Ejemplo de trabajo

Para resumir, el código que necesitará se ve así:

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

Tenga en cuenta que el parámetro el para esta función debe ser un <input> o un <textarea> .

Respuesta anterior: versiones anteriores de iOS

En iOS <10 hay algunas restricciones para Safari (que en realidad son medidas de seguridad) para la API del Portapapeles :

  • Dispara eventos de copy solo en una selección válida y cut y paste solo en campos editables enfocados.
  • Solo admite la lectura / escritura del portapapeles del sistema operativo a través de teclas de acceso directo, no a través de document.execCommand() . Tenga en cuenta que "tecla de acceso directo" significa que se puede hacer clic (por ejemplo, menú de acción copiar / pegar o atajo de teclado iOS personalizado) o tecla física (por ejemplo, teclado bluetooth conectado).
  • No es compatible con el constructor ClipboardEvent .

Entonces (al menos a partir de ahora) no es posible copiar programáticamente algún texto / valor en el portapapeles en un dispositivo iOS usando Javascript . Solo el usuario puede decidir si copiar algo.

Sin embargo, es posible seleccionar algo mediante programación , de modo que el usuario solo tenga que presionar la información sobre herramientas "Copiar" que se muestra en la selección. Esto se puede lograr con el mismo código que el anterior, simplemente eliminando el execCommand(''copy'') , que de hecho no funcionará.


Esta es mi implementación de navegador cruzado

Puede probarlo ejecutando el fragmento a continuación

Ejemplo:

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>

NOTA: ¡No funciona cuando el usuario no lo inicia, como los tiempos de espera o cualquier evento asíncrono!

Debe provenir de un evento confiable como el llamado desde un evento de click en un botón


Este me funcionó para un elemento de entrada de solo lectura.

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


Esto es lo que funcionó para mí. El código se prueba en todos los navegadores más recientes y funciona.

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

La idea es crear un área de texto falso, agregarlo a DOM, establecer contentEditable & readOnly como verdadero. Cree un rango para seleccionar el elemento deseado y agréguelo a la selección de la ventana. Establezca el rango de selección para todo el elemento. Y luego ejecute execCommand (''copia''). Puede observar un gran número (999999) dentro del método setSelectionRange (). Bueno, es para cubrir cualquier cosa que pueda estar dentro del elemento. Lea más sobre el rango de MDN Docs: range

Prueba de funcionamiento (funciona en la siguiente combinación de dispositivo / navegador)

iPhone (iOS> = 10) - Safari, Chrome

Android: Chrome, FF

Mac: Chrome, FF, Safari

Windows: Chrome, IE, FF

No he mencionado versiones específicamente porque probé las últimas versiones disponibles para mí al momento de escribir esta publicación. Aquí hay una escritura detallada de lo mismo: https://josephkhan.me/javascript-copy-clipboard-safari/


He buscado algunas soluciones y he encontrado una que realmente funciona: http://www.seabreezecomputers.com/tips/copy2clipboard.htm

Básicamente, el ejemplo podría ser algo como:

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


Mi función para ios y otros navegadores que copian al portapapeles después de probar en ios: 5c, 6,7

copyText = input => { const isIOSDevice = navigator.userAgent.match(/ipad|iphone/i); if (isIOSDevice) { input.setSelectionRange(0, input.value.length); } else { input.select(); } document.execCommand(''copy''); };

respuesta anterior sobre contenteditable = verdadero. Creo que solo pertenece a divs. Y para <textarea> no es aplicable.

La variable isIOS se puede verificar como

const isIOS = navigator.userAgent.match(/ipad|ipod|iphone/i);


Mi solución fue creada combinando otras respuestas de esta página.

A diferencia de las otras respuestas, no requiere que ya tenga un elemento en la página. Creará su propio área de texto y luego limpiará el desorden.

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


Por favor revisa mi solución.

Funciona en Safari (probado en iPhone 7 y iPad) y en otros navegadores.

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/

Espero que te ayude.

Saludos.


bueno, aquí está el refactor de mecanografía de arriba en caso de que alguien esté interesado (escrito como módulo ES6):

/** * 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 } };


Problema: iOS Safari solo permite document.execCommand(''copy'') para texto dentro de un contentEditable contenido contentEditable .

Solución: detecte iOS Safari y cambie rápidamente contentEditable antes de ejecutar document.execCommand(''copy'') .

La siguiente función funciona en todos los navegadores. Llame con un selector de CSS o elemento HTMLE :

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>


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