tabla - copy portapapeles javascript
javascript cortar/copiar/pegar al portapapeles: ¿cómo lo resolvió Google? (5)
Sí, esta pregunta se ha hecho una y otra vez: ¿cómo copiar y pegar desde y hacia el portapapeles del sistema con javascript? He encontrado solo soluciones parciales y hacks hasta ahora. La razón por la que se ha preguntado con tanta frecuencia en el pasado es que todavía no existe una solución que funcione. Sin embargo, observé que Google Docs en realidad tiene una solución funcional ahora tanto para eventos de teclado como para botones. Entonces, es posible, pero ¿cómo lo hacen? Artículo de Software Salad, Acceso al portapapeles del sistema con JavaScript - ¿Un Santo Grial? , da una buena visión general del problema (pero tiene algunos años).
En breve:
puede usar los eventos de teclado ctrl + x, ctrl + c, ctrl + v para copiar texto de un área de texto oculta con datos preparados o capturar texto pegado en un campo oculto y luego hacer algo con él
puede utilizar algunos trucos a través de Flash o quizás un applet de Java para copiar algo en el portapapeles del sistema sin necesidad de la aprobación del usuario.
puede utilizar una solución "real" con clipboardData.setData para IE y execCommand para otros navegadores, que depende de la aprobación del usuario.
¿Alguna idea de cómo Google ha abordado el problema del portapapeles?
Como complemento a lo que otros ya han publicado en este hilo, he creado un ejemplo completamente funcional que demuestra el método de acceso directo del teclado (CTRL + C o CMD + C en Mac OS X), así como un método de botón personalizado que activa la acción de copia.
La demostración completa se puede encontrar aquí: http://jsfiddle.net/rve7d/
Encontré la respuesta de Mateusz W muy útil al intentar crear esta demostración, pero no ha considerado el soporte para IE, que se comporta de forma ligeramente diferente y utiliza diferentes tipos de datos como primer parámetro.
if(window.clipboardData) {
// use just ''Text'' or ''Url'' as a first param otherwise strange exception is thrown
window.clipboardData.setData(''Text'', ''Text that will be copied to CB'');
} else if(ev.originalEvent.clipboardData) {
ev.originalEvent.clipboardData.setData(''text/plain'', ''Text that will be copied to CB'');
} else {
alert(''Clipboard Data are not supported in this browser. Sorry.'');
}
PD: Necesitaba esta funcionalidad para nuestro componente personalizado de Vista de hoja de cálculo y en la forma en que analicé el código fuente de las Hojas de cálculo de Google, por lo que mi solución se ajusta principalmente a su solución.
El google utiliza un método muy simple pero genial. Al utilizar Firebug, sabrá que el código html que se carga tiene un área de texto al comienzo del tamaño 1. Lo que hace Google doc es que cuando el usuario selecciona texto y presiona ctrl + c, captura el evento y por alguna técnica obtiene el texto que se selecciona en el contenedor de documentos y establece el valor del área de texto para ese contenido. Que se centra y selecciona el área de texto. Ahora lanza el evento ctrl + c. Pero ahora el texto se selecciona en el área de texto, de modo que cuando el evento se vuelve a publicar, el navegador copia el texto en el área de texto y así obtenemos el texto copiado
Sé que esa pregunta se publicó hace mucho tiempo, pero necesitaba comprobar cómo Google hace eso, así que tal vez a alguien le resulte útil.
En realidad, Google usa también el portapapeles del sistema, pero es un poco complicado. En caso de que cuando use el método abreviado del teclado, pueda capturar / pegar / cortar un evento en, por ejemplo, la ventana:
window.addEventListener(''copy'', function (ev) {
console.log(''copy event'');
// you can set clipboard data here, e.g.
ev.clipboardData.setData(''text/plain'', ''some text pushed to clipboard'');
// you need to prevent default behaviour here, otherwise browser will overwrite your content with currently selected
ev.preventDefault();
});
Ejemplo en vivo para el método abreviado de teclado: http://jsfiddle.net/tyk9U/
Desafortunadamente, esta es solo una solución para el método abreviado de teclado y hay un problema con el menú contextual, porque no puede acceder a los datos del portapapeles sin un evento de copiar / cortar / pegar nativo (de confianza). Pero google hace truco interesante. Existe la API document.execCommand()
que le permite ejecutar comandos para el elemento personalizable y existe el comando ''copiar'' que puede activarlo a través de document.execCommand(''copy'')
. Pero cuando intentas esto en la consola en Chrome, devolverá false
. Pasé un poco de tiempo investigando eso y resultó que tenían la extensión de Chrome instalada, llamada "Google Drive" (ve a chrome: // apps / y puedes verla allí) que permite el acceso al portapapeles para los dominios drive.google. com y docs.google.com. Abra algún documento u hoja de cálculo y escriba en la consola document.execCommand(''copy'')
- devolverá true
. Al desinstalar la extensión, no podrá utilizar las operaciones del portapapeles desde el menú contextual.
Puede crear dicha aplicación por sí mismo con un archivo de manifiesto muy simple (aquí encontrará detalles en https://developer.chrome.com/apps/first_app ):
{
"manifest_version": 2,
"name": "App name",
"description": "App description",
"version": "1.0",
"app": {
"urls": [
"http://your.app.url.here/"
],
"launch": {
"web_url": "http://your.app.url.here/"
}
},
"icons": {
"128": "x-128.png"
},
"permissions": [
"clipboardRead",
"clipboardWrite"
]
}
El campo "permisos" aquí habilita las operaciones del portapapeles.
Ahora, cuando tengas esto habilitado, puedes hacer document.execCommand(''copy'')
y funcionará (devolverá true
). Pero esto no lo es todo: document.execCommand(''copy'')
en el evento de copia de Chrome triggers y puede capturarlo con el mismo código que se usa para capturar los accesos directos del portapapeles. Esto es ahora lo hace Google.
Por supuesto, esta descripción es válida sólo para Chrome.
[ Nota: esta respuesta fue precisa en el momento en que se escribió y respondió correctamente la pregunta del OP. Sin embargo, la tecnología ha evolucionado desde entonces; Si está interesado en admitir copiar y pegar en su aplicación web, consulte las otras respuestas más recientes en esta página. —Ruakh]
Sin embargo, observé que Google Docs en realidad tiene una solución funcional ahora tanto para eventos de teclado como para botones.
No, no lo hace. Realmente no. Para eventos de teclado, Google Docs no hace nada; simplemente no bloquea la función predeterminada de copiar y pegar del navegador; así, los usuarios pueden copiar y pegar libremente sin que Google Docs se interponga en el camino. Para los botones, Google Docs no admite el portapapeles del sistema , sino su propio "portapapeles web" que está completamente dentro de Google Docs. No puede usar los botones de la barra de herramientas para copiar texto para pegarlo en otro programa en su computadora, o para pegar texto que ha sido copiado de otro programa en su computadora.
Para obtener más información sobre esto, consulte "Copiar y pegar en Google Docs" . (Está orientado al usuario en lugar de orientado al desarrollador, pero hace un trabajo decente dejando en claro qué es y qué no es compatible).
<p>COPY : </p>
<p>Email me at <a class="js-emaillink" href="mailto:[email protected]">[email protected]</a></p>
<p><button class="js-emailcopybtn" value="clipboard" >clipboard</button></p>
<textarea rows="10" cols = "12"></textarea>
<p>CUT: </p>
<p><textarea class="js-cuttextarea">Hello I''m some text</textarea></p>
<p><button class="js-textareacutbtn" disable>Cut Textarea</button></p>
<script>
//copy clipboard
var copyEmailBtn = document.querySelector(''.js-emailcopybtn'');
copyEmailBtn.addEventListener(''click'', function(event) {
// Выборка ссылки с электронной почтой
var emailLink = document.querySelector(''.js-emaillink'');
var range = document.createRange();
range.selectNode(emailLink);
window.getSelection().addRange(range);
try {
// Теперь, когда мы выбрали текст ссылки, выполним команду копирования
var successful = document.execCommand(''copy'');
var msg = successful ? ''successful'' : ''unsuccessful'';
console.log(''Copy email command was '' + msg);
} catch(err) {
console.log(''Oops, unable to copy'');
}
// Снятие выделения - ВНИМАНИЕ: вы должны использовать
// removeRange(range) когда это возможно
window.getSelection().removeAllRanges();
});
//cut
var cutTextareaBtn = document.querySelector(''.js-textareacutbtn'');
cutTextareaBtn.addEventListener(''click'', function(event) {
var cutTextarea = document.querySelector(''.js-cuttextarea'');
cutTextarea.select();
try {
var successful = document.execCommand(''cut'');
var msg = successful ? ''successful'' : ''unsuccessful'';
console.log(''Cutting text command was '' + msg);
} catch(err) {
console.log(''Oops, unable to cut'');
}
});
</script>