Catch-Paste-Eingabe


210

Ich suche nach einer Möglichkeit, Eingaben zu bereinigen, die ich in den Browser einfüge. Ist dies mit jQuery möglich?

Ich habe es bisher geschafft, Folgendes zu finden:

$(this).live(pasteEventName, function(e) {
 // this is where i would like to sanitize my input
 return false;
}

Leider ist meine Entwicklung aufgrund dieses "kleinen" Problems zum Stillstand gekommen. Ich würde mich wirklich zu einem glücklichen Camper machen, wenn mich jemand in die richtige Richtung weisen könnte.


6
Bitte markieren Sie stackoverflow.com/a/1503425/749232 als Antwort für die Verwendung durch andere Personen, bei denen das gleiche Problem auftritt . Das hat es für mich gelöst.
saji89

2
.live () ist ab jquery 1.9 veraltet, sie empfehlen stattdessen .on ()
Sameer Alibhai

Antworten:


337

OK, bin gerade auf das gleiche Problem gestoßen. Ich bin den langen Weg gegangen

$('input').on('paste', function () {
  var element = this;
  setTimeout(function () {
    var text = $(element).val();
    // do something with text
  }, 100);
});

Nur eine kleine Zeitüberschreitung, bis .val () func gefüllt werden kann.

E. E.


20
Was ist, wenn sich bereits Text im Textbereich befindet und Sie ihn einfügen und nur den eingefügten Text möchten?
Barfoon

39
Funktioniert perfekt, danke. Ein Timeout von 0 funktioniert genauso gut. Die Funktion muss nur auf die nächste Schleife verschoben werden.
Daniel Lewis

4
Ich war gerade in einer ähnlichen Situation. Das Zeitlimit ist vorhanden, da das Einfügeereignis nicht sofort erfolgt, sondern einige Millisekunden dauert, bis der Inhalt der Zwischenablage eingefügt wird.
James

8
@ user563811: Beachten Sie nur, dass das offizielle Mindestzeitlimit in HTML5 4 ms beträgt.
Pimvdb

4
Wie Sharif sagt, setzt 0ms das Ereignis immer noch am Ende des Stapels.
BobRodes

67

Sie können den Wert direkt aus dem Ereignis abrufen . Es ist ein bisschen stumpf, wie man dorthin kommt.

Geben Sie false zurück, wenn Sie nicht möchten, dass es durchlaufen wird.

$(this).on('paste', function(e) {

  var pasteData = e.originalEvent.clipboardData.getData('text')

});

2
Dies ist der
richtige

1
dh 11: window.clipboardData.getData ('text')
Wallstrider

4
Beachten Sie jedoch, dass die Eigenschaft "originalEvent" nur erforderlich ist, wenn Sie das Ereignis mit jQuery behandeln. Sie können dies einfach e.clipboardData.getData('text')in einfachem JavaScript tun .
Asier Paz

Beste Antwort hier! Aber - ich fand es seltsam, dass die Kurzversion von Bindungen nicht mit diesem Fehler funktioniert, dh mit einem Fehler, wenn ich Folgendes versuche: $ (this) .paste (Funktion (e) {...});, gerade obwohl das für Short-Handing .on ('click'), etc ..
funktioniert

Niggle: Dem Code fehlt ein schließender Paren. Anscheinend ist die Änderung zu klein, um sie als Bearbeitung korrigieren zu können.
Joachim Lous

42

Aus Gründen der plattformübergreifenden Kompatibilität sollten Ereignisse oninput und onpropertychange behandelt werden:

$ (something).bind ("input propertychange", function (e) {
    // check for paste as in example above and
    // do something
})

2
Wunderschöne Lösung, die sowohl als Paste- als auch als Keyup-Ereignisfang funktioniert. Hinweis: Dies bewirkt , dass die Event - Funktion aus irgendeinem Grund zweimal schießen , wenn Sie die eingegebenen Inhalte markieren und dann etwas in geben Sie mindestens IE8 (nicht wichtig in vielen Fällen, aber möglicherweise sehr wichtig , in anderen).
Baacke

Nett ! Ich wusste nichts darüber und es passt perfekt zu meinen Bedürfnissen!
Marc Brillault

18

Ich habe es irgendwie mit dem folgenden Code behoben:

$("#editor").live('input paste',function(e){
    if(e.target.id == 'editor') {
        $('<textarea></textarea>').attr('id', 'paste').appendTo('#editMode');
        $("#paste").focus();
        setTimeout($(this).paste, 250);
    }
});

Jetzt muss ich nur noch den Caret-Standort speichern und an diese Position anhängen, dann bin ich fertig ... denke ich :)


1
Wie haben Sie den Caret-Standort gespeichert?
Petah

@Petah Sie können überprüfen, auf welches Element der Fokus liegt .find(':focus'), und wissen, dass dieses Element die Caret-Position dafür bestimmt. Sehen Sie das .
Jacob

Denken Sie daran, dass "live" zugunsten von "on"
NBPalomino

inputmacht den Unterschied :) Ich habe diese normalerweise in meinen Textbox-Ereignissen, keyup keydown paste inputaber es hängt natürlich davon ab, was Ihre Motive sind
Pierre

10

Hmm ... Ich denke, Sie können e.clipboardDatadamit die eingefügten Daten abfangen. Wenn es nicht klappt, schauen Sie hier .

$(this).live("paste", function(e) {
    alert(e.clipboardData); // [object Clipboard]
});

2
Wenn ich dies in Safari
starte,

1
clipboardData ist in den meisten Browsern
sandboxed

2
Nur Internet Explorer!
Lodewijk

9

Warten Sie auf das Einfügeereignis und legen Sie einen Listener für Keyup-Ereignisse fest. Erfassen Sie beim Keyup den Wert und entfernen Sie den Listener für das Keyup-Ereignis.

$('.inputTextArea').bind('paste', function (e){
    $(e.target).keyup(getInput);
});
function getInput(e){
    var inputText = $(e.target).val();
    $(e.target).unbind('keyup');
}

6
Dies ist sehr gut, funktioniert jedoch nicht beim Einfügen mit der rechten Maustaste.
Joseph Ravenwolfe

Es funktioniert auch nicht beim Einfügen mit mittlerem Klick (X11). Es funktioniert nur, wenn sie die Tastatur zum Einfügen verwendet haben.
Jasen

7
$("#textboxid").on('input propertychange', function () {
    //perform operation
        });

Es wird gut funktionieren.


6

Dies kommt dem näher, was Sie vielleicht wollen.

function sanitize(s) {
  return s.replace(/\bfoo\b/g, "~"); 
};

$(function() {
 $(":text, textarea").bind("input paste", function(e) {
   try {
     clipboardData.setData("text",
       sanitize(clipboardData.getData("text"))
     );
   } catch (e) {
     $(this).val( sanitize( $(this).val() ) );
   }
 });
});

Beachten Sie, dass Sie derzeit den vollständigen Wert des Elements + den Wert der Zwischenablage erhalten, wenn das Objekt clipboardData nicht gefunden wird (in anderen Browsern als dem Internet Explorer).

Sie können wahrscheinlich einige zusätzliche Schritte ausführen, um die beiden Werte vor einer Eingabe und nach der Eingabe zu unterscheiden, wenn Sie wirklich erst danach sind, welche Daten wirklich in das Element eingefügt wurden.


6
 $('').bind('input propertychange', function() {....});                      

Dies funktioniert für Mauseinfügeereignisse.


2
Dies ist die beste Verwendung von allen.
Sinan Eldem

5

Wie wäre es, wenn Sie den ursprünglichen Wert des Felds mit dem geänderten Wert des Felds vergleichen und die Differenz als eingefügten Wert abziehen? Dadurch wird der eingefügte Text auch dann korrekt erfasst, wenn im Feld bereits Text vorhanden ist.

http://jsfiddle.net/6b7sK/

function text_diff(first, second) {
    var start = 0;
    while (start < first.length && first[start] == second[start]) {
        ++start;
    }
    var end = 0;
    while (first.length - end > start && first[first.length - end - 1] == second[second.length - end - 1]) {
        ++end;
    }
    end = second.length - end;
    return second.substr(start, end - start);
}
$('textarea').bind('paste', function () {
    var self = $(this);
    var orig = self.val();
    setTimeout(function () {
        var pasted = text_diff(orig, $(self).val());
        console.log(pasted);
    });
});

5

Dieser Code funktioniert für mich entweder durch Einfügen mit der rechten Maustaste oder durch direktes Kopieren und Einfügen

   $('.textbox').on('paste input propertychange', function (e) {
        $(this).val( $(this).val().replace(/[^0-9.]/g, '') );
    })

Wenn ich einfüge Section 1: Labour Cost, wird es 1in Textfeld.

Um nur Float-Werte zuzulassen, verwende ich diesen Code

 //only decimal
    $('.textbox').keypress(function(e) {
        if(e.which == 46 && $(this).val().indexOf('.') != -1) {
            e.preventDefault();
        } 
       if (e.which == 8 || e.which == 46) {
            return true;
       } else if ( e.which < 48 || e.which > 57) {
            e.preventDefault();
      }
    });

4
document.addEventListener('paste', function(e){
    if(e.clipboardData.types.indexOf('text/html') > -1){
        processDataFromClipboard(e.clipboardData.getData('text/html'));
        e.preventDefault();

        ...
    }
});

Des Weiteren:


text / html ist ungültig, nur url und text.
Mike

@Mike Ich habe das Snippet direkt aus der referenzierten Dokumentation kopiert.
Davidcondrey

Ich habe es ungefähr einen Tag lang versucht. text / html würde niemals funktionieren. Am Ende fügte ich eine Zeitüberschreitung von 0 Verzögerung hinzu und konnte das HTML aus dem Div holen, in das sie eingefügt wurden. Wenn jemand eine funktionierende Geige hätte, würde das helfen. Vielleicht mache ich es einfach falsch ...
Mike

3

Siehe dieses Beispiel: http://www.p2e.dk/diverse/detectPaste.htm

Es verfolgt im Wesentlichen jede Änderung mit einem Eingabeereignis und prüft dann, ob es sich um eine Einfügung handelt, indem es einen String vergleicht. Oh, und im IE gibt es ein Onpaste-Ereignis. So:

$ (something).bind ("input paste", function (e) {
    // check for paste as in example above and
    // do something
})

Es ist also unmöglich, nur den Einfügetext zu erhalten, wenn das Ereignis eintritt?
Christoffer Winterkvist

Nun, ich denke, Sie müssen sich selbst darum kümmern, indem Sie das Vorher und Nachher vergleichen. Es muss ziemlich einfach sein. Aber warum validieren Sie nicht einfach die gesamte Eingabe? Langsam?
Ilya Birman

Ich dachte nur, dass das möglich wäre, aber ich denke nicht. Im Moment versuche ich eine andere Methode, indem ich sie in einen Textbereich einfüge und sie dann an ihren endgültigen Bestimmungsort übertrage. Ich hoffe das wird funktionieren.
Christoffer Winterkvist

Sie müssen nur das maximal passende Fragment am Anfang von zwei Zeichenfolgen (vorher und nachher) finden. Alles von dort bis zum Längenunterschied ist der eingefügte Text.
Ilya Birman

@IlyaBirman nein, ist es nicht: zB kann der eingefügte Text einen Teil (oder den gesamten Teil) des Originals ersetzen
Jasen

1

Diese Methode verwendet jqueries content (). Unwrap ().

  1. Ermitteln Sie zunächst das Einfügeereignis
  2. Fügen Sie den Tags, die sich bereits in dem Element befinden, in das wir einfügen, eine eindeutige Klasse hinzu.
  3. Durchsuchen Sie nach einer bestimmten Zeitüberschreitung alle Inhalte, die Tags entpacken, die nicht die zuvor festgelegte Klasse haben. Hinweis: Diese Methode entfernt keine selbstschließenden Tags wie in
    einem Beispiel unten.

    //find all children .find('*') and add the class .within .addClass("within") to all tags
    $('#answer_text').find('*').each(function () {
    $(this).addClass("within");
    });
    setTimeout(function() {
    $('#answer_text').find('*').each(function () {
        //if the current child does not have the specified class unwrap its contents
        $(this).not(".within").contents().unwrap();
    });
    }, 0);

Auf jeden Fall die beste, kürzeste und selbstsprachigste Antwort, die jemals gesehen wurde !!! Vielen Dank, Sie haben meinen Tag gemacht;)
Webprogrammierer

0

Dies erwies sich als ziemlich illusorisch. Der Wert der Eingabe wird vor der Ausführung des Codes innerhalb der Einfügeereignisfunktion nicht aktualisiert. Ich habe versucht, andere Ereignisse aus der Funktion zum Einfügen von Ereignissen heraus aufzurufen, aber der Eingabewert wird immer noch nicht mit dem eingefügten Text innerhalb der Funktion von Ereignissen aktualisiert. Das sind alle Ereignisse außer Keyup. Wenn Sie keyup aus der Funktion zum Einfügen von Ereignissen aufrufen, können Sie den eingefügten Text aus der Funktion keyup event bereinigen. wie so ...

$(':input').live
(
    'input paste',
    function(e)
    {
        $(this).keyup();
    }
);

$(':input').live
(
    'keyup',
    function(e)
    {
        // sanitize pasted text here
    }
);

Hier gibt es eine Einschränkung. Wenn Sie in Firefox den Eingabetext bei jedem Keyup zurücksetzen, wenn der Text länger als der durch die Eingabebreite zulässige sichtbare Bereich ist, wird durch das Zurücksetzen des Werts bei jedem Keyup die Browserfunktionalität unterbrochen, mit der der Text automatisch zur Caret-Position am gescrollt wird Ende des Textes. Stattdessen scrollt der Text zurück zum Anfang und lässt das Caret außer Sicht.


onpaste wird aufgerufen, bevor der Inhalt eingefügt wird. Sie benötigen eine zeitliche Verzögerung von mindestens 4 ms, um Ihre eigene Afterpaste-Funktion zu erstellen und die Ergebnisse der Paste zu waschen.
DragonLord

-1

Skript zum Entfernen von Sonderzeichen aus allen Feldern mit dem Klassenportlet-Formular-Eingabefeld:

// Remove special chars from input field on paste
jQuery('.portlet-form-input-field').bind('paste', function(e) {
    var textInput = jQuery(this);
    setTimeout(function() {
        textInput.val(replaceSingleEndOfLineCharactersInString(textInput.val()));
    }, 200);
});

function replaceSingleEndOfLineCharactersInString(value) {
    <%
        // deal with end-of-line characters (\n or \r\n) that will affect string length calculation,
        // also remove all non-printable control characters that can cause XML validation errors
    %>
    if (value != "") {
        value = value.replace(/(\x00|\x01|\x02|\x03|\x04|\x05|\x06|\x07|\x08|\x0B|\x0C|\x0E|\x0F|\x10|\x11|\x12|\x13|\x14|\x15|\x16|\x17|\x18|\x19|\x1A|\x1B|\x1C|\x1D|\x1E|\x1F|\x7F)/gm,'');
        return value = value.replace(/(\r\n|\n|\r)/gm,'##').replace(/(\#\#)/gm,"\r\n");
    }
}

2
Könnten Sie bitte eine Beschreibung der relevanten Desinfektion hinzufügen und warum dies zur Lösung des Posterproblems beitragen kann? Das einfache Bereitstellen eines Codeblocks hilft dem OP (oder zukünftigen Suchenden) nicht wirklich zu verstehen, wie das Problem gelöst werden kann - es fördert lediglich das Kopieren / Einfügen von missverstandenem Code.
Troy Alford

-2

Hier gibt es eine Einschränkung. Wenn Sie in Firefox den Eingabetext bei jedem Keyup zurücksetzen, wenn der Text länger als der durch die Eingabebreite zulässige sichtbare Bereich ist, wird durch das Zurücksetzen des Werts bei jedem Keyup die Browserfunktionalität unterbrochen, mit der der Text automatisch zur Caret-Position am gescrollt wird Ende des Textes. Stattdessen scrollt der Text zurück zum Anfang und lässt das Caret außer Sicht.

function scroll(elementToBeScrolled) 
{
     //this will reset the scroll to the bottom of the viewable area. 
     elementToBeScrolled.topscroll = elementToBeScrolled.scrollheight;
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.