Comment une application Web peut-elle détecter un événement de collage et récupérer les données à coller?
Je souhaite supprimer le contenu HTML avant de coller le texte dans un éditeur de texte enrichi.
Le nettoyage du texte après avoir été collé par la suite fonctionne, mais le problème est que tout le formatage précédent est perdu. Par exemple, je peux écrire une phrase dans l'éditeur et la mettre en gras, mais lorsque je colle un nouveau texte, tout le formatage est perdu. Je souhaite nettoyer uniquement le texte collé et laisser intacte toute mise en forme précédente.
Idéalement, la solution devrait fonctionner sur tous les navigateurs modernes (par exemple, MSIE, Gecko, Chrome et Safari).
Notez que MSIE l'a fait clipboardData.getData()
, mais je n'ai pas pu trouver de fonctionnalités similaires pour d'autres navigateurs.
event.clipboardData.getData('Text')
travaillé pour moi.document.addEventListener('paste'...
a fonctionné pour moi mais a provoqué des conflits si un utilisateur voulait pouvoir coller ailleurs sur la page. Ensuite, j'ai essayémyCanvasElement.addEventListener('paste'...
, mais cela n'a pas fonctionné. Finalement, j'ai compris que celamyCanvasElement.parentElement.addEventListener('paste'...
fonctionnait.Réponses:
La situation a changé depuis la rédaction de cette réponse: maintenant que Firefox a ajouté la prise en charge dans la version 22, tous les principaux navigateurs prennent désormais en charge l'accès aux données du presse-papiers dans un événement de collage. Voir la réponse de Nico Burns pour un exemple.
Dans le passé, cela n'était généralement pas possible de manière croisée. L'idéal serait de pouvoir récupérer le contenu collé via l'
paste
événement, ce qui est possible dans les navigateurs récents mais pas dans certains navigateurs plus anciens (notamment Firefox <22).Lorsque vous devez prendre en charge des navigateurs plus anciens, ce que vous pouvez faire est très impliqué et un peu un hack qui fonctionnera dans les navigateurs Firefox 2+, IE 5.5+ et WebKit tels que Safari ou Chrome. Les versions récentes de TinyMCE et CKEditor utilisent cette technique:
designMode
désactivez-le et appelezfocus()
la zone de texte, déplaçant ainsi le curseur et redirigeant efficacement la pâtedesignMode
, restaure la sélection de l'utilisateur et colle le texte.Notez que cela ne fonctionnera que pour les événements de collage au clavier et non les pâtes du menu contextuel ou d'édition. Au moment où l'événement coller se déclenche, il est trop tard pour rediriger le curseur dans la zone de texte (dans certains navigateurs, au moins).
Dans le cas peu probable où vous devez prendre en charge Firefox 2, notez que vous devrez placer la zone de texte dans le document parent plutôt que le document iframe de l'éditeur WYSIWYG dans ce navigateur.
la source
designMode
est une propriété booléenne dedocument
et rend la page entière modifiable quandtrue
. Les éditeurs WYSIWYG utilisent généralement une iframe avecdesignMode
on comme volet modifiable. L'enregistrement et la restauration de la sélection des utilisateurs se font d'une manière dans IE et d'une autre dans d'autres navigateurs, tout comme le collage du contenu dans l'éditeur. Vous devez obtenir unTextRange
dans IE et unRange
dans d'autres navigateurs.paste
événement mais il est généralement trop tard pour rediriger la pâte vers un autre élément, donc ce hack ne fonctionnera pas. La solution de rechange dans la plupart des éditeurs consiste à afficher une boîte de dialogue dans laquelle l'utilisateur peut coller.paste
événement, mais cela vous permettra d'effacer le contenu de l'élément (et de l'enregistrer dans une variable afin de pouvoir le restaurer plus tard). Si ce conteneur est undiv
(il fonctionne probablement pour uniframe
aussi), vous pouvez alors parcourir le contenu collé à l'aide des méthodes dom normales, ou le récupérer sous forme de chaîneinnerHTML
. Vous pouvez ensuite restaurer le contenu précédent de ladiv
et insérer le contenu que vous souhaitez. Oh, et vous devez utiliser le même hack de minuterie que ci-dessus. Je suis surpris que TinyMCE ne fasse pas ça ...Solution n ° 1 (texte brut uniquement et nécessite Firefox 22+)
Fonctionne pour IE6 +, FF 22+, Chrome, Safari, Edge (testé uniquement dans IE9 +, mais devrait fonctionner pour les versions inférieures)
Si vous avez besoin de support pour coller du HTML ou Firefox <= 22, consultez la solution n ° 2.
HTML
Javascript
JSFiddle: https://jsfiddle.net/swL8ftLs/12/
Notez que cette solution utilise le paramètre 'Text' pour la
getData
fonction, qui n'est pas standard. Cependant, cela fonctionne dans tous les navigateurs au moment de la rédaction.Solution # 2 (HTML et fonctionne pour Firefox <= 22)
Testé dans IE6 +, FF 3.5+, Chrome, Safari, Edge
HTML
Javascript
JSFiddle: https://jsfiddle.net/nicoburns/wrqmuabo/23/
Explication
L'
onpaste
événement dudiv
a lahandlePaste
fonction qui lui est attachée et a passé un seul argument: l'event
objet de l'événement coller. Un intérêt particulier pour nous est laclipboardData
propriété de cet événement qui permet d'accéder au presse-papiers dans des navigateurs non-ie. Dans IE, l'équivalent estwindow.clipboardData
, bien que celui-ci ait une API légèrement différente.Voir la section des ressources ci-dessous.
La
handlepaste
fonction:Cette fonction a deux branches.
Le premier vérifie l'existence
event.clipboardData
et vérifie si satypes
propriété contient 'text / html' (types
peut être soit unDOMStringList
qui est vérifié en utilisant lacontains
méthode, soit une chaîne qui est vérifiée en utilisant laindexOf
méthode). Si toutes ces conditions sont remplies, nous procédons comme dans la solution n ° 1, sauf avec 'text / html' au lieu de 'text / plain'. Cela fonctionne actuellement dans Chrome et Firefox 22+.Si cette méthode n'est pas prise en charge (tous les autres navigateurs), nous
DocumentFragment
waitForPastedData
fonctionLa
waitforpastedata
fonction:Cette fonction interroge d'abord les données collées (une fois toutes les 20 ms), ce qui est nécessaire car elles n'apparaissent pas immédiatement. Lorsque les données sont apparues, elles:
La
processpaste
fonction:Fait des choses arbitraires avec les données collées. Dans ce cas, nous alertons simplement les données, vous pouvez faire ce que vous voulez. Vous souhaiterez probablement exécuter les données collées via une sorte de processus de nettoyage des données.
Sauvegarde et restauration de la position du curseur
Dans une situation réelle, vous voudrez probablement enregistrer la sélection avant et la restaurer après ( définir la position du curseur sur contentEditable <div> ). Vous pouvez ensuite insérer les données collées à la position où se trouvait le curseur lorsque l'utilisateur a lancé l'action de collage.
Ressources:
Merci à Tim Down d'avoir suggéré l'utilisation d'un DocumentFragment et abligh pour avoir détecté une erreur dans Firefox due à l'utilisation de DOMStringList au lieu d'une chaîne pour clipboardData.types
la source
DocumentFragment
plutôt que de l'utiliserinnerHTML
pour plusieurs raisons: d'abord, vous conservez tous les gestionnaires d'événements existants; deuxièmement, l'enregistrement et la restaurationinnerHTML
ne sont pas garantis pour créer une copie identique du DOM précédent; troisièmement, vous pouvez ensuite enregistrer la sélection en tant queRange
plutôt que d'avoir à vous déplacer avec l'ajout d'éléments de marqueur ou le calcul des décalages de texte (ce que vous auriez à faire si vous l'utilisiezinnerHTML
).DocumentFragment
une douleur dans IE? C'est la même chose que dans les autres navigateurs, sauf si vous utilisez une plage etextractContents()
pour le faire, ce qui n'est pas plus concis que l'alternative dans tous les cas. J'ai implémenté un exemple de votre technique, en utilisant Rangy pour garder les choses agréables et uniformes sur tous les navigateurs: jsfiddle.net/bQeWC/4 .waitforpastedata
fonctiontext/html
à l'aide de l'API W3C Clipboard. Dans le passé, une telle tentative jetterait une exception. Donc, on n'a plus besoin de cette solution de contournement / hack pour Edge.Version simple:
En utilisant
clipboardData
Démo: http://jsbin.com/nozifexasu/edit?js,output
Testé sur Edge, Firefox, Chrome, Safari, Opera.
⚠ Document.execCommand () est désormais obsolète .
Remarque: n'oubliez pas de vérifier les entrées / sorties côté serveur également (comme les strip-tags PHP )
la source
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); }
Démo en direct
Testé sur Chrome / FF / IE11
Il y a une gêne pour Chrome / IE, c'est que ces navigateurs ajoutent un
<div>
élément pour chaque nouvelle ligne. Il y a un article à ce sujet ici et il peut être corrigé en définissant l' élément contenteditable surdisplay:inline-block
Sélectionnez du HTML en surbrillance et collez-le ici:
la source
J'ai écrit une petite preuve de concept pour la proposition de Tim Downs ici avec une zone de texte hors écran. Et voici le code:
Copiez et collez tout le code dans un fichier html et essayez de coller (à l'aide de ctrl-v) du texte du presse-papiers n'importe où sur le document.
Je l'ai testé dans IE9 et dans les nouvelles versions de Firefox, Chrome et Opera. Fonctionne assez bien. Il est également bon que l'on puisse utiliser la combinaison de touches qu'il préfère pour améliorer cette fonctionnalité. Bien sûr, n'oubliez pas d'inclure les sources jQuery.
N'hésitez pas à utiliser ce code et si vous venez avec des améliorations ou des problèmes, merci de les poster. Notez également que je ne suis pas un développeur Javascript, donc j'ai peut-être raté quelque chose (=> faites votre propre testign).
la source
Basé sur la réponse l2aelba. Cela a été testé sur FF, Safari, Chrome, IE (8,9,10 et 11)
la source
Celui-ci n'utilise aucun setTimeout ().
J'ai utilisé cet excellent article pour obtenir une prise en charge multi-navigateurs.
Ce code est étendu avec la poignée de sélection avant de coller: démo
la source
Pour nettoyer le texte collé et remplacer le texte actuellement sélectionné par le texte collé, la question est assez banale:
JS:
la source
Cela devrait fonctionner sur tous les navigateurs qui prennent en charge l'événement onpaste et l'observateur de mutation.
Cette solution va au-delà de l'obtention du texte uniquement, elle vous permet en fait de modifier le contenu collé avant qu'il ne soit collé dans un élément.
Il fonctionne en utilisant un événement onpaste modifiable (pris en charge par tous les principaux navigateurs) et des observateurs de mutation (pris en charge par Chrome, Firefox et IE11 +)
étape 1
Créer un élément HTML avec contenteditable
étape 2
Dans votre code Javascript, ajoutez l'événement suivant
Nous devons lier pasteCallBack, car l'observateur de mutation sera appelé de manière asynchrone.
étape 3
Ajoutez la fonction suivante à votre code
Ce que fait le code:
Exemple
Afficher l'extrait de code
Un grand merci à Tim Down Voir cet article pour la réponse:
Récupérer le contenu collé sur le document lors de l'événement de collage
la source
La solution qui fonctionne pour moi consiste à ajouter un écouteur d'événements pour coller un événement si vous le collez dans une entrée de texte. Étant donné que l'événement paste se produit avant que le texte dans les modifications d'entrée, dans mon gestionnaire on paste, je crée une fonction différée à l'intérieur de laquelle je vérifie les changements dans ma zone de saisie qui se sont produits lors du collage:
la source
C'était trop long pour un commentaire sur la réponse de Nico, qui ne fonctionne plus sur Firefox (selon les commentaires), et n'a pas fonctionné pour moi sur Safari tel quel.
Premièrement, vous semblez maintenant pouvoir lire directement depuis le presse-papiers. Plutôt que de coder comme:
utilisation:
parce que Firefox a un
types
champ qui n'estDOMStringList
pas implémentétest
.Firefox suivant n'autorisera pas le collage sauf si le focus est dans un
contenteditable=true
champ.Enfin, Firefox n'autorisera pas le collage de manière fiable à moins que le focus soit dans un
textarea
(ou peut-être une entrée) qui n'est pas seulementcontenteditable=true
mais aussi:display:none
visibility:hidden
J'essayais de masquer le champ de texte pour que je puisse faire fonctionner le collage sur un émulateur JS VNC (c'est-à-dire qu'il allait vers un client distant et qu'il n'y avait pas réellement
textarea
etc.) dans lequel coller. J'ai trouvé que le fait d'essayer de masquer le champ de texte ci-dessus donnait des symptômes où cela fonctionnait parfois, mais échouait généralement sur le deuxième collage (ou lorsque le champ était effacé pour éviter de coller deux fois les mêmes données) car le champ perdait le focus et ne revenait pas correctement malgré celafocus()
. La solution que j'ai trouvée était de le mettrez-order: -1000
, de le fairedisplay:none
, de le faire en 1px par 1px et de définir toutes les couleurs sur transparent. Beurk.Sur Safari, la deuxième partie de ce qui précède s'applique, c'est-à-dire que vous devez en avoir un
textarea
qui ne l'est pasdisplay:none
.la source
Le premier qui me vient à l'esprit est le gestionnaire de pâte de la fermeture de Google lib http://closure-library.googlecode.com/svn/trunk/closure/goog/demos/pastehandler.html
la source
Solution simple:
la source
Cela a fonctionné pour moi:
la source
la source
Vous pouvez le faire de cette manière:
utilisez ce plugin jQuery pour les événements avant et après collage:
Vous pouvez maintenant utiliser ce plugin ;:
Explication
Définissez d'abord un uid pour tous les éléments existants comme attribut de données.
Comparez ensuite tous les nœuds de l'événement POST PASTE. Ainsi, en comparant, vous pouvez identifier celui qui vient d'être inséré, car il aura un uid, puis supprimez simplement l'attribut style / classe / id des éléments nouvellement créés, afin de conserver votre ancienne mise en forme.
la source
la source
Laissez simplement le navigateur coller comme d'habitude dans son div modifiable de contenu, puis après le collage, échangez tous les éléments de portée utilisés pour les styles de texte personnalisés avec le texte lui-même. Cela semble fonctionner correctement dans Internet Explorer et les autres navigateurs que j'ai essayés ...
Cette solution suppose que vous exécutez jQuery et que vous ne souhaitez pas la mise en forme du texte dans aucun de vos divs modifiables de contenu .
Le côté positif est que c'est super simple.
la source
span
tag? J'imagine que la question concernait toutes les balises.Cette solution consiste à remplacer la balise html, c'est simple et multi-navigateur; vérifiez ce jsfiddle: http://jsfiddle.net/tomwan/cbp1u2cx/1/ , code principal:
remarque: vous devriez faire un peu de travail sur le filtre xss à l'arrière car cette solution ne peut pas filtrer les chaînes comme '<< >>'
la source
Il s'agit d'un code existant publié ci-dessus, mais je l'ai mis à jour pour IE, le bogue était lorsque le texte existant est sélectionné et collé ne supprimera pas le contenu sélectionné. Cela a été corrigé par le code ci-dessous
Voir le code complet ci-dessous
la source