¿Cómo puede una aplicación web detectar un evento de pegado y recuperar los datos que se pegarán?
Me gustaría eliminar el contenido HTML antes de que el texto se pegue en un editor de texto enriquecido.
Limpiar el texto después de pegarlo funciona, pero el problema es que se pierde todo el formato anterior. Por ejemplo, puedo escribir una oración en el editor y ponerla en negrita, pero cuando pego un texto nuevo, todo el formato se pierde. Quiero limpiar solo el texto que se pega y dejar intacto cualquier formato anterior.
Idealmente, la solución debería funcionar en todos los navegadores modernos (por ejemplo, MSIE, Gecko, Chrome y Safari).
Tenga en cuenta que MSIE tiene clipboardData.getData()
, pero no pude encontrar una funcionalidad similar para otros navegadores.
event.clipboardData.getData('Text')
funcionó para mí.document.addEventListener('paste'...
funcionó para mí, pero causó conflictos si un usuario deseaba poder pegar en otra parte de la página. Luego lo intentémyCanvasElement.addEventListener('paste'...
, pero eso no funcionó. Finalmente me di cuenta de quemyCanvasElement.parentElement.addEventListener('paste'...
funcionó.Respuestas:
La situación ha cambiado desde que escribí esta respuesta: ahora que Firefox ha agregado soporte en la versión 22, todos los principales navegadores ahora admiten acceder a los datos del portapapeles en un evento de pegado. Vea la respuesta de Nico Burns para un ejemplo.
En el pasado, esto no era posible en general en un navegador cruzado. Lo ideal sería poder obtener el contenido pegado a través del
paste
evento, lo cual es posible en navegadores recientes pero no en algunos navegadores antiguos (en particular, Firefox <22).Cuando necesite admitir navegadores antiguos, lo que puede hacer es bastante complicado y un truco que funcionará en los navegadores Firefox 2+, IE 5.5+ y WebKit como Safari o Chrome. Las versiones recientes de TinyMCE y CKEditor utilizan esta técnica:
designMode
apague y llamefocus()
al área de texto, moviendo así el cursor y redirigiendo efectivamente la pastadesignMode
vuelva a encenderlo , restaure la selección del usuario y pegue el texto.Tenga en cuenta que esto solo funcionará para pegar eventos de teclado y no para pegar desde el contexto o editar menús. Para cuando se active el evento de pegado, es demasiado tarde para redirigir el cursor al área de texto (al menos en algunos navegadores).
En el improbable caso de que necesite admitir Firefox 2, tenga en cuenta que deberá colocar el área de texto en el documento principal en lugar del documento del iframe del editor WYSIWYG en ese navegador.
fuente
designMode
es una propiedad booleana dedocument
y hace que toda la página sea editable cuandotrue
. Los editores WYSIWYG usualmente usan un iframe condesignMode
on como el panel editable. Guardar y restaurar la selección del usuario se realiza de una manera en IE y otra en otros navegadores, al igual que pegar el contenido en el editor. Necesita obtener unTextRange
en IE y otroRange
en otros navegadores.paste
evento, pero generalmente es demasiado tarde para redirigir la pasta a otro elemento, por lo que este truco no funcionará. El respaldo en la mayoría de los editores es mostrar un diálogo para que el usuario lo pegue.paste
evento, sin embargo, le permitirá borrar el contenido del elemento (y guardarlo en una variable para que pueda restaurarlo más adelante). Si este contenedor es unadiv
(probablemente trabaja para unaiframe
también) a continuación, a continuación, puede desplazarse por el contenido pegado utilizando métodos DOM normales, o conseguir como una cadena usandoinnerHTML
. A continuación, puede restaurar el contenido anterior deldiv
e insertar el contenido que desee. Ah, y tienes que usar el mismo truco de temporizador que el anterior. Me sorprende que TinyMCE no haga esto ...Solución n. ° 1 (solo texto sin formato y requiere Firefox 22+)
Funciona para IE6 +, FF 22+, Chrome, Safari, Edge (solo probado en IE9 +, pero debería funcionar para versiones inferiores)
Si necesita soporte para pegar HTML o Firefox <= 22, consulte la Solución # 2.
HTML
JavaScript
JSFiddle: https://jsfiddle.net/swL8ftLs/12/
Tenga en cuenta que esta solución utiliza el parámetro 'Texto' para la
getData
función, que no es estándar. Sin embargo, funciona en todos los navegadores al momento de escribir.Solución n. ° 2 (HTML y funciona para Firefox <= 22)
Probado en IE6 +, FF 3.5+, Chrome, Safari, Edge
HTML
JavaScript
JSFiddle: https://jsfiddle.net/nicoburns/wrqmuabo/23/
Explicación
El
onpaste
evento deldiv
tiene lahandlePaste
función adjunta y pasó un único argumento: elevent
objeto para el evento de pegar. De particular interés para nosotros es laclipboardData
propiedad de este evento que permite el acceso al portapapeles en navegadores que no sean. En IE, el equivalente eswindow.clipboardData
, aunque tiene una API ligeramente diferente.Vea la sección de recursos a continuación.
La
handlepaste
función:Esta función tiene dos ramas.
La primera verifica la existencia de
event.clipboardData
y verifica si sutypes
propiedad contiene 'text / html' (types
puede ser unaDOMStringList
que se verifica usando elcontains
método o una cadena que se verifica con elindexOf
método). Si se cumplen todas estas condiciones, entonces procedemos como en la solución # 1, excepto con 'text / html' en lugar de 'text / plain'. Actualmente funciona en Chrome y Firefox 22+.Si este método no es compatible (todos los demás navegadores), entonces
DocumentFragment
waitForPastedData
funciónLa
waitforpastedata
función:Esta función primero sondea los datos pegados (una vez cada 20 ms), lo cual es necesario porque no aparece de inmediato. Cuando aparecieron los datos:
La
processpaste
función:Hace cosas arbitrarias con los datos pegados. En este caso, solo alertamos los datos, puede hacer lo que quiera. Probablemente desee ejecutar los datos pegados a través de algún tipo de proceso de desinfección de datos.
Guardar y restaurar la posición del cursor
En una situación real, es probable que desee guardar la selección antes y restaurarla después ( establezca la posición del cursor en contentEditable <div> ). Luego, podría insertar los datos pegados en la posición en la que se encontraba el cursor cuando el usuario inició la acción de pegar.
Recursos:
Gracias a Tim Down por sugerir el uso de un DocumentFragment, y sobretodo por detectar un error en Firefox debido al uso de DOMStringList en lugar de una cadena para clipboardData.types
fuente
DocumentFragment
lugar de usarloinnerHTML
por varias razones: primero, mantiene los controladores de eventos existentes; segundo, guardar y restaurarinnerHTML
no garantiza la creación de una copia idéntica del DOM anterior; En tercer lugar, puede guardar la selección como algo enRange
lugar de tener que cambiar el orden agregando elementos de marcador o calculando compensaciones de texto (que es lo que tendría que hacer si lo usarainnerHTML
).DocumentFragment
una molestia extraer en IE? Es lo mismo que en otros navegadores, a menos que use un Range yextractContents()
para hacerlo, lo que no es más conciso que la alternativa en cualquier caso. He implementado un ejemplo de su técnica, usando Rangy para mantener las cosas agradables y uniformes en los navegadores: jsfiddle.net/bQeWC/4 .waitforpastedata
text/html
utilizando la API del Portapapeles W3C. En el pasado, tal intento arrojaría una excepción. Por lo tanto, ya no se necesita esta solución / hack para Edge.Versión simple:
Utilizando
clipboardData
Demostración: http://jsbin.com/nozifexasu/edit?js,output
Edge, Firefox, Chrome, Safari, Opera probado.
⚠ Document.execCommand () está obsoleto ahora.
Nota: Recuerde verificar la entrada / salida en el lado del servidor también (como las etiquetas de tira PHP )
fuente
window.clipboardData.getData('Text');
e.preventDefault(); if (e.clipboardData) { content = (e.originalEvent || e).clipboardData.getData('text/plain'); document.execCommand('insertText', false, content); } else if (window.clipboardData) { content = window.clipboardData.getData('Text'); document.selection.createRange().pasteHTML(content); }
Demo en vivo
Probado en Chrome / FF / IE11
Hay una molestia de Chrome / IE que es que estos navegadores agregan
<div>
elementos para cada nueva línea. Hay un post sobre esto aquí y se puede fijar mediante el establecimiento de la contenteditable elemento a serdisplay:inline-block
Seleccione un HTML resaltado y péguelo aquí:
fuente
He escrito una pequeña prueba de concepto para la propuesta de Tim Downs aquí con el área de texto fuera de la pantalla. Y aquí va el código:
Simplemente copie y pegue todo el código en un archivo html e intente pegar (usando ctrl-v) texto del portapapeles en cualquier parte del documento.
Lo probé en IE9 y nuevas versiones de Firefox, Chrome y Opera. Funciona bastante bien También es bueno que uno pueda usar cualquier combinación de teclas que prefiera para activar esta funcionalidad. Por supuesto, no olvide incluir las fuentes jQuery.
Siéntase libre de usar este código y si tiene algunas mejoras o problemas, publíquelos nuevamente. También tenga en cuenta que no soy desarrollador de Javascript, por lo que es posible que me haya perdido algo (=> haga su propio testign).
fuente
Basado en l2aelba anwser. Esto fue probado en FF, Safari, Chrome, IE (8,9,10 y 11)
fuente
Este no usa ningún setTimeout ().
He usado este excelente artículo para lograr compatibilidad con varios navegadores.
Este código se amplía con el controlador de selección antes de pegar: demo
fuente
Para limpiar el texto pegado y reemplazar el texto seleccionado actualmente con el texto pegado, el asunto es bastante trivial:
JS:
fuente
Esto debería funcionar en todos los navegadores que admitan el evento onpaste y el observador de mutaciones.
Esta solución va más allá de obtener solo el texto, en realidad le permite editar el contenido pegado antes de pegarlo en un elemento.
Funciona mediante el uso de eventos onpaste contenteditable (compatible con todos los principales navegadores) en observadores de mutación (compatible con Chrome, Firefox e IE11 +)
paso 1
Crear un elemento HTML con contenteditable
paso 2
En su código Javascript agregue el siguiente evento
Necesitamos vincular pasteCallBack, ya que el observador de mutaciones se llamará asincrónicamente.
paso 3
Agregue la siguiente función a su código
Lo que hace el código:
Ejemplo
Mostrar fragmento de código
Muchas gracias a Tim Down. Vea esta publicación para la respuesta:
Obtenga el contenido pegado en el documento en el evento pegar
fuente
La solución que funciona para mí es agregar un detector de eventos para pegar el evento si está pegando en una entrada de texto. Dado que el evento pegar ocurre antes de que el texto en los cambios de entrada, dentro de mi controlador de pegar, creo una función diferida dentro de la cual verifico los cambios en mi cuadro de entrada que ocurrieron en pegar:
fuente
Esto fue demasiado largo para un comentario sobre la respuesta de Nico, que creo que ya no funciona en Firefox (según los comentarios), y no funcionó para mí en Safari tal como está.
En primer lugar, ahora parece que puede leer directamente desde el portapapeles. En lugar de código como:
utilizar:
porque Firefox tiene un
types
campoDOMStringList
que no se implementatest
.Siguiente Firefox no permitirá pegar a menos que el foco esté en un
contenteditable=true
campo.Finalmente, Firefox no permitirá pegar de manera confiable a menos que el foco esté en una
textarea
(o quizás entrada) que no solo seacontenteditable=true
sino también:display:none
visibility:hidden
Estaba tratando de ocultar el campo de texto para poder pegar el trabajo sobre un emulador JS VNC (es decir, iba a un cliente remoto y en realidad no había
textarea
etc. para pegar). Descubrí que tratar de ocultar el campo de texto en el cuadro anterior daba síntomas en los que funcionaba a veces, pero generalmente fallaba en la segunda pegada (o cuando el campo se borró para evitar pegar los mismos datos dos veces) ya que el campo perdió el foco y no se recuperó correctamente a pesar de esofocus()
. La solución que se me ocurrió fue ponerloz-order: -1000
, hacerlodisplay:none
, hacerlo como 1px por 1px, y establecer todos los colores en transparentes. YuckEn Safari, se aplica la segunda parte de lo anterior, es decir, necesita tener uno
textarea
que no lo esdisplay:none
.fuente
Lo primero que viene a la mente es el pastehandler del cierre de google lib http://closure-library.googlecode.com/svn/trunk/closure/goog/demos/pastehandler.html
fuente
Solución simple:
fuente
Esto funcionó para mí:
fuente
fuente
Puedes hacer esto de esta manera:
use este complemento jQuery para eventos de pre y post pegado:
Ahora puedes usar este plugin ;:
Explicación
Primero establezca un uid para todos los elementos existentes como atributo de datos.
Luego compare todos los nodos POST PASTE event. Entonces, al comparar, puede identificar el recién insertado porque tendrá un uid, luego simplemente elimine el atributo style / class / id de los elementos recién creados, para que pueda mantener su formato anterior.
fuente
fuente
Simplemente deje que el navegador pegue como de costumbre en su contenido editable div y luego, después de pegar, intercambie cualquier elemento span utilizado para estilos de texto personalizados con el texto mismo. Esto parece funcionar bien en Internet Explorer y en los otros navegadores que probé ...
Esta solución supone que está ejecutando jQuery y que no desea formatear el texto en ninguno de sus divs editables de contenido .
El lado positivo es que es súper simple.
fuente
span
etiquetar? Me imagino que la pregunta era sobre todas las etiquetas.Esta solución es reemplazar la etiqueta html, es simple y de navegador cruzado; compruebe este jsfiddle: http://jsfiddle.net/tomwan/cbp1u2cx/1/ , código central:
aviso: debe hacer un trabajo sobre el filtro xss en la parte posterior porque esta solución no puede filtrar cadenas como '<< >>'
fuente
Este es un código existente publicado anteriormente, pero lo he actualizado para IE, el error fue cuando se seleccionó el texto existente y pegado no eliminará el contenido seleccionado. Esto ha sido arreglado por el siguiente código
Ver el código completo a continuación
fuente