Wie kann eine Webanwendung ein Einfügeereignis erkennen und die einzufügenden Daten abrufen?
Ich möchte HTML-Inhalte entfernen, bevor der Text in einen Rich-Text-Editor eingefügt wird.
Das Bereinigen des Texts nach dem Einfügen funktioniert, aber das Problem ist, dass alle vorherigen Formatierungen verloren gehen. Zum Beispiel kann ich einen Satz in den Editor schreiben und fett machen, aber wenn ich neuen Text einfüge, geht die gesamte Formatierung verloren. Ich möchte nur den eingefügten Text bereinigen und alle vorherigen Formatierungen unberührt lassen.
Idealerweise sollte die Lösung in allen modernen Browsern (z. B. MSIE, Gecko, Chrome und Safari) funktionieren.
Beachten Sie, dass MSIE hat clipboardData.getData()
, aber ich konnte keine ähnliche Funktionalität für andere Browser finden.
event.clipboardData.getData('Text')
hat für mich gearbeitet.document.addEventListener('paste'...
hat für mich funktioniert, aber Konflikte verursacht, wenn ein Benutzer in der Lage sein wollte, an anderer Stelle auf der Seite einzufügen. Dann habe ich es versuchtmyCanvasElement.addEventListener('paste'...
, aber das hat nicht funktioniert. Schließlich fand ich heraus, dass esmyCanvasElement.parentElement.addEventListener('paste'...
funktioniert.Antworten:
Die Situation hat sich seit dem Schreiben dieser Antwort geändert: Nachdem Firefox in Version 22 Unterstützung hinzugefügt hat, unterstützen alle gängigen Browser den Zugriff auf die Zwischenablagedaten in einem Einfügeereignis. Siehe Nico Burns Antwort für ein Beispiel.
In der Vergangenheit war dies im Allgemeinen nicht browserübergreifend möglich. Ideal wäre es, den eingefügten Inhalt über das
paste
Ereignis abrufen zu können. Dies ist in neueren Browsern möglich , in einigen älteren Browsern jedoch nicht (insbesondere in Firefox <22).Wenn Sie ältere Browser unterstützen müssen, ist das, was Sie tun können, ziemlich kompliziert und ein bisschen wie ein Hack, der in Firefox 2+ -, IE 5.5+ - und WebKit-Browsern wie Safari oder Chrome funktioniert. Neuere Versionen von TinyMCE und CKEditor verwenden diese Technik:
designMode
und rufen Sie ihnfocus()
auf. Dadurch wird das Caret verschoben und die Paste effektiv umgeleitetdesignMode
, die Benutzerauswahl wiederherstellt und den Text einfügt.Beachten Sie, dass dies nur für Tastatureinfügeereignisse funktioniert und nicht für Einfügungen aus dem Kontext oder zum Bearbeiten von Menüs. Zum Zeitpunkt des Auslösens des Einfügeereignisses ist es zu spät, das Caret in den Textbereich umzuleiten (zumindest in einigen Browsern).
Beachten Sie für den unwahrscheinlichen Fall, dass Sie Firefox 2 unterstützen müssen, dass Sie den Textbereich im übergeordneten Dokument und nicht im Dokument des WYSIWYG-Editors iframe in diesem Browser platzieren müssen.
quelle
designMode
ist eine boolesche Eigenschaft vondocument
und macht die gesamte Seite bearbeitbar, wenntrue
. WYSIWYG-Editoren verwenden normalerweise einen Iframe mitdesignMode
on als bearbeitbaren Bereich. Das Speichern und Wiederherstellen der Benutzerauswahl erfolgt auf eine Weise im IE und auf andere Weise in anderen Browsern, ebenso wie das Einfügen des Inhalts in den Editor. Sie müssen eineTextRange
in IE und eineRange
in anderen Browsern erhalten.paste
Ereignisses erkennen, aber bis dahin ist es im Allgemeinen zu spät, um die Paste in ein anderes Element umzuleiten, sodass dieser Hack nicht funktioniert. Der Fallback in den meisten Editoren besteht darin, ein Dialogfeld anzuzeigen, in das der Benutzer einfügen kann.paste
Ereignis nicht auf ein anderes Element verschieben. Sie können jedoch den Inhalt des Elements löschen (und in einer Variablen speichern, damit Sie es später wiederherstellen können). Wenn es sich bei diesem Container um einen handeltdiv
(wahrscheinlich funktioniert er auch für eineniframe
), können Sie den eingefügten Inhalt mit normalen dom-Methoden durchlaufen oder ihn als Zeichenfolge abrufeninnerHTML
. Sie können dann den vorherigen Inhalt von wiederherstellendiv
und den gewünschten Inhalt einfügen. Oh, und Sie müssen den gleichen Timer-Hack wie oben verwenden. Ich bin überrascht, dass TinyMCE dies nicht tut ...Lösung Nr. 1 (Nur einfacher Text und erfordert Firefox 22+)
Funktioniert für IE6 +, FF 22+, Chrome, Safari, Edge (Nur in IE9 + getestet, sollte aber für niedrigere Versionen funktionieren)
Wenn Sie Unterstützung zum Einfügen von HTML oder Firefox <= 22 benötigen, lesen Sie Lösung 2.
HTML
JavaScript
JSFiddle: https://jsfiddle.net/swL8ftLs/12/
Beachten Sie, dass diese Lösung den Parameter 'Text' für die
getData
Funktion verwendet, der nicht dem Standard entspricht. Es funktioniert jedoch zum Zeitpunkt des Schreibens in allen Browsern.Lösung 2 (HTML und funktioniert für Firefox <= 22)
Getestet in IE6 +, FF 3.5+, Chrome, Safari, Edge
HTML
JavaScript
JSFiddle: https://jsfiddle.net/nicoburns/wrqmuabo/23/
Erläuterung
Dem
onpaste
Ereignis vondiv
ist diehandlePaste
Funktion zugeordnet, und es wurde ein einziges Argument übergeben: dasevent
Objekt für das Einfügeereignis. Von besonderem Interesse für uns ist dieclipboardData
Eigenschaft dieses Ereignisses, die den Zugriff auf die Zwischenablage in nicht-dh Browsern ermöglicht. Im IE ist das Äquivalentwindow.clipboardData
, obwohl dies eine etwas andere API hat.Siehe Abschnitt Ressourcen unten.
Die
handlepaste
Funktion:Diese Funktion hat zwei Zweige.
Der erste prüft auf das Vorhandensein von
event.clipboardData
und prüft, ob seinetypes
Eigenschaft 'text / html' enthält (types
entweder eine,DOMStringList
die mit dercontains
Methode überprüft wird, oder eine Zeichenfolge, die mit derindexOf
Methode überprüft wird). Wenn alle diese Bedingungen erfüllt sind, fahren wir wie in Lösung 1 fort, außer mit 'text / html' anstelle von 'text / plain'. Dies funktioniert derzeit in Chrome und Firefox 22+.Wenn diese Methode nicht unterstützt wird (alle anderen Browser), dann wir
DocumentFragment
waitForPastedData
Funktion aufDie
waitforpastedata
Funktion:Diese Funktion fragt zuerst nach den eingefügten Daten (einmal pro 20 ms), was erforderlich ist, da sie nicht sofort angezeigt werden. Wenn die Daten erschienen sind:
Die
processpaste
Funktion:Macht willkürliche Dinge mit den eingefügten Daten. In diesem Fall alarmieren wir nur die Daten, Sie können tun, was Sie wollen. Möglicherweise möchten Sie die eingefügten Daten durch einen Datenbereinigungsprozess ausführen.
Speichern und Wiederherstellen der Cursorposition
In einer realen Situation möchten Sie wahrscheinlich die Auswahl vorher speichern und danach wiederherstellen ( Cursorposition auf contentEditable <div> setzen ). Sie können die eingefügten Daten dann an der Position einfügen, an der sich der Cursor befand, als der Benutzer die Einfügemaßnahme initiierte.
Ressourcen:
Vielen Dank an Tim Down für den Vorschlag, ein DocumentFragment zu verwenden, und für das Abfangen eines Fehlers in Firefox aufgrund der Verwendung von DOMStringList anstelle einer Zeichenfolge für clipboardData.types
quelle
DocumentFragment
anstatt ihninnerHTML
aus mehreren Gründen zu verwenden: Erstens behalten Sie alle vorhandenen Ereignishandler bei; Zweitens wird beim Speichern und WiederherstelleninnerHTML
nicht garantiert, dass eine identische Kopie des vorherigen DOM erstellt wird.Range
Drittens können Sie die Auswahl dann als speichern , anstatt sich mit dem Hinzufügen von Markierungselementen oder dem Berechnen von Textversätzen herumschlagen zu müssen (was Sie tun müssten, wenn Sie es verwenden würdeninnerHTML
).DocumentFragment
einem Schmerz im IE? Es ist dasselbe wie in anderen Browsern, es sei denn, Sie verwenden einen Bereich undextractContents()
tun dies, was auf keinen Fall prägnanter als die Alternative ist. Ich habe ein Beispiel für Ihre Technik implementiert und Rangy verwendet, um die Dinge in allen Browsern schön und einheitlich zu halten: jsfiddle.net/bQeWC/4 .waitforpastedata
Funktiontext/html
mithilfe der W3C-Zwischenablage-API. In der Vergangenheit würde ein solcher Versuch eine Ausnahme auslösen. Man braucht diese Problemumgehung / diesen Hack für Edge also nicht mehr.Einfache Version:
Verwenden von
clipboardData
Demo: http://jsbin.com/nozifexasu/edit?js,output
Edge, Firefox, Chrome, Safari, Opera getestet.
⚠ Document.execCommand () ist jetzt veraltet .
Hinweis: Denken Sie daran, die Eingabe / Ausgabe auch serverseitig zu überprüfen (wie PHP-Strip-Tags ).
quelle
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); }
Live-Demo
Getestet auf Chrome / FF / IE11
Es gibt einen Chrome / IE-Ärger, der darin besteht, dass diese Browser
<div>
für jede neue Zeile ein Element hinzufügen . Es gibt einen Beitrag über das hier und es kann durch Setzen des fixiert werden contenteditable Element zu seindisplay:inline-block
Wählen Sie hervorgehobenes HTML aus und fügen Sie es hier ein:
quelle
Ich habe hier einen kleinen Proof of Concept für den Vorschlag von Tim Downs mit Textbereich außerhalb des Bildschirms geschrieben. Und hier geht der Code:
Kopieren Sie einfach den gesamten Code und fügen Sie ihn in eine HTML-Datei ein. Versuchen Sie dann, (mit Strg-V) Text aus der Zwischenablage an einer beliebigen Stelle im Dokument einzufügen.
Ich habe es in IE9 und neuen Versionen von Firefox, Chrome und Opera getestet. Funktioniert ganz gut. Es ist auch gut, dass man jede Tastenkombination verwenden kann, die er bevorzugt, um diese Funktionalität zu nutzen. Vergessen Sie natürlich nicht, jQuery-Quellen einzuschließen.
Fühlen Sie sich frei, diesen Code zu verwenden. Wenn Sie Verbesserungen oder Probleme haben, senden Sie diese bitte zurück. Beachten Sie auch, dass ich kein Javascript-Entwickler bin, sodass ich möglicherweise etwas verpasst habe (=> mache dein eigenes Testign).
quelle
Basierend auf l2aelba Antwort. Dies wurde auf FF, Safari, Chrome, IE (8,9,10 und 11) getestet.
quelle
Dieser verwendet kein setTimeout ().
Ich habe diesen großartigen Artikel verwendet, um Cross-Browser-Unterstützung zu erreichen.
Dieser Code wird vor dem Einfügen: Demo um das Auswahlhandle erweitert
quelle
Um den eingefügten Text zu bereinigen und den aktuell ausgewählten Text durch den eingefügten Text zu ersetzen, ist die Sache ziemlich trivial:
JS:
quelle
Dies sollte in allen Browsern funktionieren, die das Ereignis onpaste und den Mutationsbeobachter unterstützen.
Diese Lösung geht weit über das Abrufen nur des Texts hinaus. Sie ermöglicht es Ihnen, den eingefügten Inhalt zu bearbeiten, bevor er in ein Element eingefügt wird.
Es funktioniert mit inhaltsbearbeitbaren Onpaste-Ereignissen (von allen gängigen Browsern unterstützt) und Mutationsbeobachtern (unterstützt von Chrome, Firefox und IE11 +).
Schritt 1
Erstellen Sie ein HTML-Element mit contenteditable
Schritt 2
Fügen Sie in Ihrem Javascript-Code das folgende Ereignis hinzu
Wir müssen pasteCallBack binden, da der Mutationsbeobachter asynchron aufgerufen wird.
Schritt 3
Fügen Sie Ihrem Code die folgende Funktion hinzu
Was der Code macht:
Beispiel
Code-Snippet anzeigen
Vielen Dank an Tim Down In diesem Beitrag finden Sie die Antwort:
Ruft den eingefügten Inhalt beim Einfügen in ein Dokument ab
quelle
Die für mich geeignete Lösung besteht darin, einen Ereignis-Listener zum Einfügen eines Ereignisses hinzuzufügen, wenn Sie eine Texteingabe einfügen. Da das Einfügeereignis auftritt, bevor sich Text in der Eingabe ändert, erstelle ich in meinem Handler zum Einfügen eine verzögerte Funktion, in der ich nach Änderungen in meinem Eingabefeld suche, die beim Einfügen aufgetreten sind:
quelle
Dies war zu lang für einen Kommentar zu Nicos Antwort, von der ich glaube, dass sie in Firefox nicht mehr funktioniert (gemäß den Kommentaren), und in Safari nicht so wie sie ist.
Erstens scheinen Sie jetzt in der Lage zu sein, direkt aus der Zwischenablage zu lesen. Anstatt Code wie:
verwenden:
weil Firefox ein
types
Feld hat, dasDOMStringList
nicht implementiert isttest
.Next Firefox lässt das Einfügen nur zu, wenn der Fokus in einem
contenteditable=true
Feld liegt.Schließlich erlaubt Firefox das zuverlässige Einfügen nur, wenn der Fokus auf einer
textarea
(oder vielleicht einer Eingabe) liegt, die nicht nur,contenteditable=true
sondern auch:display:none
visibility:hidden
Ich habe versucht, das Textfeld auszublenden, damit das Einfügen über einen JS VNC-Emulator funktioniert (dh es wurde an einen Remoteclient gesendet und es gab kein
textarea
usw. zum Einfügen). Ich habe festgestellt, dass der Versuch, das Textfeld oben auszublenden, Symptome hervorrief, bei denen es manchmal funktionierte, aber normalerweise beim zweiten Einfügen fehlschlug (oder wenn das Feld gelöscht wurde, um zu verhindern, dass dieselben Daten zweimal eingefügt wurden), da das Feld den Fokus verlor und nicht richtig wiederhergestellt wurde es trotzfocus()
. Die Lösung, die ich mir ausgedacht habe, war, es auf 1px mal 1px zu setzenz-order: -1000
, zu machendisplay:none
und alle Farben auf transparent zu setzen. Yuck.Auf Safari gilt der zweite Teil der oben genannten Punkte, dh Sie benötigen einen,
textarea
der nicht vorhanden istdisplay:none
.quelle
Als erstes fällt mir der Pastehandler von Googles Closure Lib http://closure-library.googlecode.com/svn/trunk/closure/goog/demos/pastehandler.html ein
quelle
Einfache Lösung:
quelle
Das hat bei mir funktioniert:
quelle
quelle
Sie können dies folgendermaßen tun:
Verwenden Sie dieses jQuery-Plugin für Ereignisse vor und nach dem Einfügen:
Jetzt können Sie dieses Plugin verwenden;:
Erklärung
Legen Sie zunächst eine UID für alle vorhandenen Elemente als Datenattribut fest.
Vergleichen Sie dann das POST PASTE-Ereignis aller Knoten. Durch Vergleichen können Sie also die neu eingefügte identifizieren, da sie eine UID haben. Entfernen Sie dann einfach das Attribut style / class / id aus den neu erstellten Elementen, damit Sie Ihre ältere Formatierung beibehalten können.
quelle
quelle
Lassen Sie den Browser einfach wie gewohnt in seinem inhaltsbearbeitbaren Div einfügen und tauschen Sie nach dem Einfügen alle für benutzerdefinierte Textstile verwendeten Span-Elemente mit dem Text selbst aus. Dies scheint im Internet Explorer und den anderen Browsern, die ich ausprobiert habe, in Ordnung zu sein ...
Diese Lösung setzt voraus, dass Sie jQuery ausführen und keine Textformatierung in einem Ihrer inhaltsbearbeitbaren Divs wünschen .
Das Plus ist, dass es super einfach ist.
quelle
span
taggen? Ich würde mir vorstellen, dass die Frage alle Tags betraf.Diese Lösung ersetzt das HTML-Tag. Sie ist einfach und browserübergreifend. Überprüfen Sie diese jsfiddle: http://jsfiddle.net/tomwan/cbp1u2cx/1/ , Kerncode :
Hinweis: Sie sollten einige Arbeiten zum xss-Filter auf der Rückseite durchführen, da diese Lösung keine Zeichenfolgen wie '<< >>' filtern kann.
quelle
Dies ist ein vorhandener Code, der oben veröffentlicht wurde, aber ich habe ihn für IE aktualisiert. Der Fehler war, dass beim Auswählen und Einfügen des vorhandenen Texts der ausgewählte Inhalt nicht gelöscht wird. Dies wurde durch den folgenden Code behoben
Siehe vollständigen Code unten
quelle