texto - pegar portapapeles javascript
¿Cómo copio al portapapeles en JavaScript? (30)
¿Cuál es la mejor manera de copiar texto al portapapeles? (multi-navegador)
Yo he tratado:
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);
}
}
pero en Internet Explorer da un error de sintaxis. En Firefox, dice que unsafeWindow is not defined
.
Un buen truco sin flash: ¿Cómo accede Trello al portapapeles del usuario?
Visión general
Hay 3 API principales del navegador para copiar al portapapeles:
- Async Clipboard API
[navigator.clipboard.writeText]
- Parte centrada en el texto disponible en Chrome 66 (marzo de 2018)
- El acceso es asíncrono y utiliza promesas de JavaScript , que se pueden escribir para que las indicaciones de seguridad del usuario (si se muestran) no interrumpan el JavaScript en la página.
- El texto se puede copiar al portapapeles directamente desde una variable.
- Sólo se admite en páginas servidas a través de HTTPS.
- En Chrome 66, las páginas en pestañas activas pueden escribir en el portapapeles sin una solicitud de permisos.
-
document.execCommand(''copy'')
- La mayoría de los navegadores lo admiten a partir de abril de 2015 (consulte la sección Soporte del navegador a continuación).
- El acceso es sincrónico, es decir, detiene JavaScript en la página hasta que se complete, incluida la visualización y la interacción del usuario con cualquier mensaje de seguridad.
- El texto se lee desde el DOM y se coloca en el portapapeles.
- Durante las pruebas ~ abril de 2015, solo se observó que Internet Explorer mostraba solicitudes de permisos al escribir en el portapapeles.
- Anulando el evento de copia
- Consulte la documentación de la API del Portapapeles sobre Anular el evento de copia .
- Le permite modificar lo que aparece en el portapapeles de cualquier evento de copia, puede incluir otros formatos de datos que no sean texto sin formato.
- No se cubre aquí ya que no responde directamente a la pregunta.
Notas de desarrollo general.
No espere que los comandos relacionados con el portapapeles funcionen mientras prueba el código en la consola. En general, se requiere que la página esté activa (Async Clipboard API) o que requiera la interacción del usuario (por ejemplo, un clic del usuario) para permitir que ( document.execCommand(''copy'')
) acceda al portapapeles, consulte a continuación para obtener más detalles.
Async + Fallback
Debido al nivel de compatibilidad del navegador para la nueva API de Async Clipboard, es probable que desee recurrir al método document.execCommand(''copy'')
para obtener una buena cobertura del navegador.
Aquí hay un ejemplo simple:
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>
Tenga en cuenta que este fragmento de código no funciona bien en la vista previa integrada de . Puede probarlo aquí: https://codepen.io/DeanMarkTaylor/pen/RMRaJX?editors=1011
API async portapapeles
- Anuncio de Chrome 66 (marzo de 2018)
- Referencia de la documentación del borrador de la API de Async Clipboard
Tenga en cuenta que existe la posibilidad de "solicitar permiso" y probar el acceso al portapapeles a través de la API de permisos en Chrome 66.
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 (''copiar'')
El resto de esta publicación incluye los matices y detalles de la API document.execCommand(''copy'')
.
Soporte del navegador
El soporte de JavaScript document.execCommand(''copy'')
ha crecido, vea los enlaces a continuación para obtener actualizaciones del navegador:
- IE10 + (aunque este documento indica que hubo apoyo desde IE5.5 +).
- Google Chrome 43+ (~ Abril 2015)
- Mozilla Firefox 41+ (envío ~ septiembre de 2015)
- Opera 29+ (basado en Chromium 42, ~ abril de 2015)
Ejemplo simple
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>
Ejemplo complejo: copiar al portapapeles sin mostrar la entrada
El ejemplo simple anterior funciona muy bien si hay un área de textarea
o elemento de input
visible en la pantalla.
En algunos casos, es posible que desee copiar texto en el portapapeles sin mostrar un elemento input
/ textarea
. Este es un ejemplo de una forma de solucionar esto (básicamente, insertar elemento, copiar en el portapapeles, eliminar elemento):
Probado con Google Chrome 44, Firefox 42.0a1 e 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>
Notas adicionales
Solo funciona si el usuario realiza una acción.
Todas document.execCommand(''copy'')
llamadas document.execCommand(''copy'')
deben tener lugar como resultado directo de una acción del usuario, por ejemplo, hacer clic en el controlador de eventos. Esta es una medida para evitar entrometerse con el portapapeles de los usuarios cuando no lo esperan.
Consulte la publicación de desarrolladores de Google aquí para obtener más información.
API del portapapeles
Tenga en cuenta que la especificación de borrador de la API del Portapapeles se puede encontrar aquí: https://w3c.github.io/clipboard-apis/
¿Es compatible?
-
document.queryCommandSupported(''copy'')
debe devolvertrue
si el comando "es compatible con el navegador". - y
document.queryCommandEnabled(''copy'')
devuelvetrue
si eldocument.execCommand(''copy'')
tendrá éxito si se llama ahora. Comprobación para garantizar que se haya llamado al comando desde un subproceso iniciado por el usuario y que se cumplan otros requisitos.
Sin embargo, como ejemplo de problemas de compatibilidad del navegador, Google Chrome de ~ abril a ~ octubre de 2015 solo devolvió true
desde document.queryCommandSupported(''copy'')
si se invocó el comando desde un hilo iniciado por el usuario.
Tenga en cuenta los detalles de compatibilidad a continuación.
Detalle de compatibilidad del navegador
Si bien una simple llamada a document.execCommand(''copy'')
envuelta en un bloque try
/ catch
llamado como resultado de un clic del usuario le proporcionará el mayor uso de compatibilidad, tiene algunas condiciones:
Cualquier llamada a document.execCommand
, document.queryCommandSupported
o document.queryCommandEnabled
debe incluirse en un bloque try
/ catch
.
Las diferentes implementaciones de navegador y las versiones de navegador generan diferentes tipos de excepciones cuando se invocan en lugar de devolver false
.
Las diferentes implementaciones de los navegadores aún están en movimiento y la https://w3c.github.io/clipboard-apis/ del https://w3c.github.io/clipboard-apis/ aún está en borrador, así que recuerde hacer sus pruebas.
Aquí está mi opinión sobre esa ...
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;
}
De uno de los proyectos en los que he estado trabajando, un complemento de copia al portapapeles de jQuery que utiliza la biblioteca Zero Clipboard .
Es más fácil de usar que el complemento nativo del Portapapeles de Zero si eres un usuario pesado de jQuery.
El siguiente enfoque funciona en Chrome, Firefox, Internet Explorer y Edge, y en las versiones recientes de Safari (el soporte de Copias se agregó en la versión 10 que se lanzó en octubre de 2016).
- Cree un área de texto y configure su contenido al texto que desea copiar en el portapapeles.
- Agregue el área de texto al DOM.
- Selecciona el texto en el área de texto.
- Llamar document.execCommand ("copia")
- Retire el área de texto del dom.
Nota: no verá el área de texto, ya que se agrega y elimina dentro de la misma invocación sincrónica del código Javascript.
Algunas cosas a tener en cuenta si lo está implementando usted mismo:
- Por razones de seguridad, esto solo se puede realizar desde un controlador de eventos, como hacer clic (al igual que con la apertura de ventanas).
- IE mostrará un diálogo de permisos la primera vez que se actualice el portapapeles.
- IE y Edge se desplazarán cuando el área de texto esté enfocada.
- execCommand () puede lanzar en algunos casos.
- Las líneas nuevas y las pestañas se pueden tragar a menos que uses un área de texto. (La mayoría de los artículos parecen recomendar el uso de un div)
- El área de texto será visible mientras se muestra el cuadro de diálogo de IE, o bien debe ocultarlo o usar la api específica para el portapapeles de IE.
- En IE, los administradores del sistema pueden deshabilitar la API del portapapeles.
La siguiente función debe manejar todos los problemas siguientes de la manera más limpia posible. Por favor, deje un comentario si encuentra algún problema o tiene alguna sugerencia para mejorarlo.
// 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);
}
}
}
He encontrado la siguiente solución:
En clave, el controlador crea una etiqueta "pre". Configuramos el contenido para copiar en esta etiqueta, luego hacemos una selección en esta etiqueta y devolvemos verdadero en el controlador. Esto llama al controlador estándar de Chrome y copia el texto seleccionado.
Y si lo necesita, puede configurar el tiempo de espera para la función de restauración de la selección anterior. Mi implementación en 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. :('');
};
}
Uso:
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;
Al pegar crea textarea y funciona de la misma manera.
PS puede ser que esta solución se pueda utilizar para crear una solución de navegador completo sin flash. Sus obras en FF y Chrome.
La copia automática al portapapeles puede ser peligrosa, por lo que la mayoría de los navegadores (excepto IE) lo hacen muy difícil. Personalmente, utilizo el siguiente simple truco:
function copyToClipboard(text) {
window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
}
Al usuario se le presenta el cuadro de solicitud, donde el texto a copiar ya está seleccionado. Ahora basta con presionar Ctrl + C y Entrar (para cerrar el cuadro), ¡y listo!
Ahora la operación de copia del portapapeles es SEGURA, porque el usuario lo hace manualmente (pero de una manera bastante sencilla). Por supuesto, funciona en todos los navegadores.
<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>
Leer y modificar el portapapeles desde una página web plantea problemas de seguridad y privacidad. Sin embargo, en Internet Explorer, es posible hacerlo. Encontré este fragmento de ejemplo :
<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" />
Recientemente escribí una publicación técnica en el blog sobre este mismo problema (trabajo en Lucidchart y recientemente hicimos una revisión en nuestro portapapeles).
Copiar texto sin formato en el portapapeles es relativamente simple, suponiendo que desee hacerlo durante un evento de copia del sistema (el usuario presiona Ctrl C o usa el menú del navegador).
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();
});
Poner texto en el portapapeles no durante un evento de copia del sistema es mucho más difícil. Parece que algunas de estas otras respuestas hacen referencia a formas de hacerlo a través de Flash, que es la única forma de hacerlo en varios navegadores (según tengo entendido).
Aparte de eso, hay algunas opciones en una base de navegador por navegador.
Este es el más simple en IE, donde puede acceder al objeto clipboardData en cualquier momento desde JavaScript a través de:
window.clipboardData
(Sin embargo, cuando intenta hacer esto fuera de un evento de corte, copia o pegado del sistema, IE solicitará al usuario que otorgue el permiso del portapapeles de la aplicación web).
En Chrome, puede crear una extensión de Chrome que le dará permisos de portapapeles (esto es lo que hacemos para Lucidchart). Luego, para los usuarios con su extensión instalada, solo tendrá que disparar el evento del sistema usted mismo:
document.execCommand(''copy'');
Parece que Firefox tiene algunas opciones que permiten a los usuarios otorgar permisos a ciertos sitios para acceder al portapapeles, pero no he probado ninguno de estos personalmente.
Si desea una solución realmente simple (tarda menos de 5 minutos en integrarse) y se ve bien desde el primer momento, entonces Clippy es una buena alternativa a algunas de las soluciones más complejas.
Fue escrito por un co-fundador de Github. Ejemplo de código de inserción Flash a continuación:
<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>
Recuerde reemplazar #{text}
con el texto que necesita copiar, y #{bgcolor}
con un color.
ZeroClipboard es la mejor solución de navegador cruzado que he encontrado:
<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>
Si necesita soporte no flash para iOS, simplemente agregue una alternativa:
clip.on( ''noflash'', function ( client, args ) {
$("#copy").click(function(){
var txt = $(this).attr(''data-clipboard-text'');
prompt ("Copy link, then click OK.", txt);
});
});
clipboard.js es una pequeña utilidad no flash que permite copiar texto o datos html al portapapeles. Es muy fácil de usar, solo incluye el .js y usa algo como esto:
<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 también está en GitHub
Copiar texto de la entrada HTML al Portapapeles
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>
Nota: el
document.execCommand()
método no es compatible con IE9 y versiones anteriores.
En otros navegadores que no sean IE, debe usar un objeto flash pequeño para manipular el portapapeles, por ejemplo,
Esta es una expansión de la respuesta de @ Chase, con la ventaja de que funcionará para los elementos de IMAGEN y TABLA, no solo DIV en 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'');
}
Geesh, no estoy seguro de por qué nadie señaló esto todavía.
En 2018, amigos, he aquí cómo pueden hacerlo:
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);
}
}
Utilizado en mi código Angular 6+ así:
<button mat-menu-item (click)="copySomething()">
<span>Copy link</span>
</button>
Si paso una cadena, la copia. Si nada, copia la URL de la página.
También se puede hacer más gimnasia para el portapapeles. Ver más información aquí:
https://developers.google.com/web/updates/2018/03/clipboardapi
He encontrado la siguiente solución:
Tengo el texto en una entrada oculta. Como setSelectionRange
no funciona en entradas ocultas, cambié temporalmente el tipo a texto, copié el texto y luego lo oculté nuevamente. Si desea copiar el texto de un elemento, puede pasarlo a la función y guardar su contenido en la variable de destino.
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;
}
He reunido lo que creo que es el mejor.
- Utiliza cssText para evitar excepciones en IE en lugar de estilo directamente.
- Restaura la selección si hubiera una.
- Se configura solo para que el teclado no aparezca en dispositivos móviles.
- Tiene una solución para iOS para que realmente funcione, ya que normalmente bloquea execCommand.
Aquí está:
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://.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;
}
};
})();
He usado clipboard.js
podemos conseguirlo en npm
npm install clipboard --save
y también en Bower
bower install clipboard --save
El uso y los ejemplos se encuentran en https://zenorocha.github.io/clipboard.js/
Por lo que sé, solo funciona en Internet Explorer.
Vea también Herramientas dinámicas - Copiar JavaScript en el Portapapeles , pero requiere que el usuario cambie la configuración primero y aún así no parece funcionar.
<!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>
A partir de Flash 10, solo puede copiar al portapapeles si la acción se origina a partir de la interacción del usuario con un objeto Flash. ( Lea la sección relacionada del anuncio de Adobe Flash 10 )
La solución es excesivamente un objeto flash encima del botón Copiar, o cualquier elemento que inicie la copia. Zero Clipboard es actualmente la mejor biblioteca con esta implementación. Los desarrolladores de Flash con experiencia pueden querer crear su propia biblioteca.
Desde hace poco, Chrome 42+
y Firefox 41+
ahora admite el comando document.execCommand (''copy'') . Así que creé un par de funciones para la capacidad de copia del navegador en el portapapeles utilizando una combinación de la respuesta anterior de Tim Down y la respuesta del desarrollador de 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>
Lo uso con mucho éxito ( sin jquery o cualquier otro framework).
function copyToClp(txt){
txt = document.createTextNode(txt);
document.body.appendChild(txt);
if (document.body.createTextRange) {
var d = document.body.createTextRange();
d.moveToElementText(txt);
d.select();
document.execCommand(''copy'');
} else {
var d = document.createRange();
d.selectNodeContents(txt);
window.getSelection().removeAllRanges();
window.getSelection().addRange(d);
document.execCommand(''copy'');
window.getSelection().removeAllRanges();
}
txt.remove();
}
Advertencia
Las pestañas se convierten en espacios (al menos en cromo).
Los otros métodos copiarán texto plano en el portapapeles. Para copiar HTML (es decir, puede pegar los resultados en un editor WSIWYG), puede hacer lo siguiente SOLO en IE . Esto es fundamentalmente diferente de los otros métodos, ya que el navegador realmente selecciona visiblemente el contenido.
// 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();
Mi error. Esto solo funciona en IE.
Aquí hay otra forma de copiar texto:
<p>
<a onclick="window.clipboardData.setData(''text'', document.getElementById(''Test'').innerText);">Copy</a>
</p>
Muchas respuestas ya pero me gusta agregar una (jQuery). Funciona como un encanto en cualquier navegador, también en dispositivos móviles (es decir, avisos sobre seguridad, pero cuando lo acepta, simplemente funciona bien).
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;
}
En su código:
if( !appCopyToClipBoard( ''Hai there! This is copied to the clipboard.'' ))
{ alert(''Sorry, copy to clipboard failed.''); }
Para copiar un texto seleccionado (''Texto a copiar'') en su portapapeles, cree un Bookmarklet (marcador de navegador que ejecute Javsacript) y ejecútelo (haga clic en él). Se creará un área de texto temporal.
Código de 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'');
Parece que he leído mal la pregunta, pero para referencia, puede extraer un rango del DOM (no para el portapapeles; compatible con todos los navegadores modernos) y combinarlo con los eventos oncopy y onpaste y on beforepaste para obtener el comportamiento del portapapeles. Aquí está el código para lograr esto:
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;
}
}
Tuve el mismo problema al crear una edición de cuadrícula personalizada desde (algo como Excel) y compatibilidad con Excel. Tuve que apoyar la selección de varias celdas, copiar y pegar.
Solución: cree un área de texto donde insertará datos para que el usuario los copie (para mí cuando el usuario esté seleccionando celdas), céntrese (por ejemplo, cuando el usuario presione Ctrl) y seleccione todo el texto.
Entonces, cuando el usuario pulsa Ctrl+ Cobtiene las celdas copiadas, él selecciona. Después de la prueba, solo redimensioné el área de texturas a 1 píxel (no probé si funcionará en la pantalla: ninguna). Funciona bien en todos los navegadores y es transparente para el usuario.
Pegado: podría hacer lo mismo de esta manera (difiere en su objetivo): concentrarse en los eventos de área de texto y de pegado mediante el uso de la pasta (en mi proyecto utilizo las áreas de texto en las celdas para editar)
No puedo pegar un ejemplo (proyecto comercial), pero tienes la idea.
Tuve que copiar el texto de los cuadros sin entrada (texto dentro de cualquier etiqueta div / span) de la página y se me ocurrió el siguiente código. El único truco es tener un campo oculto, pero como tipo TEXTO, no funciona con el tipo oculto.
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;
}
Y en el HTML agrega lo siguiente.
input type = "text" id = "hiddenField" style = "width: 5px; border: 0" /> ...