Wprowadź wklej złap


210

Szukam sposobu na oczyszczenie danych wejściowych wklejonych do przeglądarki, czy jest to możliwe w przypadku jQuery?

Jak dotąd udało mi się to wymyślić:

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

Niestety mój rozwój został wstrzymany z powodu tego „drobnego” problemu. Naprawdę uczyniłbym mnie szczęśliwym obozowiczem, gdyby ktoś mógł skierować mnie w dobrym kierunku.


6
Oznacz stackoverflow.com/a/1503425/749232 jako odpowiedź do użytku innych osób mających ten sam problem. To dla mnie rozwiązało.
saji89,

2
.live () jest przestarzałe od jquery 1.9, zamiast tego zalecamy .on ()
Sameer Alibhai

Odpowiedzi:


337

OK, wpadłem na ten sam problem. Przeszedłem długą drogę

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

Wystarczy mały limit czasu, aż funkcja .val () func może zostać zapełniona.

MI.


20
Co zrobić, jeśli w obszarze tekstowym jest już tekst, który wklejasz, a chcesz po prostu wkleić tekst?
barfoon

39
Działa idealnie, dzięki. Limit czasu równy 0 również działa. Funkcja wymaga tylko odroczenia do następnej pętli.
Daniel Lewis,

4
Właśnie byłem w podobnej sytuacji. Upłynął limit czasu, ponieważ zdarzenie wklejania nie jest natychmiastowe, ale wklejenie zawartości schowka zajmuje kilka milisekund.
James

8
@ user563811: Pamiętaj, że oficjalny minimalny limit czasu wynosi 4 ms w HTML5.
pimvdb

4
Jak mówi sharif, 0ms wciąż umieszcza zdarzenie na dole stosu.
BobRodes,

67

Możesz pobrać wartość bezpośrednio z wydarzenia . To trochę tępe, jak się do tego dostać.

Zwróć false, jeśli nie chcesz, aby to przeszło.

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

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

});

2
To jest droga
DdW

1
tj. 11: window.clipboardData.getData („tekst”)
Wallstrider

4
Należy jednak pamiętać, że potrzeba właściwości „originalEvent” jest potrzebna tylko w przypadku obsługi zdarzenia za pomocą jQuery. Możesz to zrobić e.clipboardData.getData('text')w zwykłym JavaScript.
Asier Paz

Najlepsza odpowiedź tutaj! Ale - okazało się dziwne, że krótka wersja wiązania nie działa z tym, tzn. Błąd, jeśli spróbuję: $ (this) .paste (function (e) {...}) ;, nawet choć działa to na krótką rękę. na („kliknięcie”) itp.
HoldOffHunger

niggle: w kodzie brakuje zamykającego paren. Najwyraźniej zmiana jest zbyt mała, aby pozwolić mi to naprawić jako edycję.
Joachim Lous,

42

W celu zapewnienia zgodności między platformami powinien on obsługiwać zdarzenia wejściowe i zmiany typu:

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

2
Piękne rozwiązanie, które działa zarówno jako przechwytywanie zdarzeń wklejania, jak i tworzenia kluczy. Uwaga: Powoduje to, że funkcja zdarzenia uruchamia się dwa razy z jakiegoś powodu, jeśli podświetlisz zawartość wejściową, a następnie wpiszesz coś w co najmniej IE8 ( nieważne w wielu przypadkach, ale być może bardzo ważne w innych).
baacke

Miły ! Nie wiedziałem o tym i idealnie pasuje do moich potrzeb!
Marc Brillault,

18

Naprawiłem go, używając następującego kodu:

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

Teraz muszę tylko zapisać położenie karetki i dołączyć do tej pozycji, a potem wszystko gotowe ... Myślę, że :)


1
Jak zapisałeś lokalizację karetki?
Petah

@Petah Mógłbyś sprawdzić, na którym elemencie jest skupiony .find(':focus'), a wiedza o tym elemencie określa lokalizację karetki. Zobacz to .
Jacob

Pamiętaj, że „live” jest przestarzałe na korzyść „on”
NBPalomino

inputrobi różnicę :) Zwykle mam to w moich zdarzeniach w polu tekstowym, keyup keydown paste inputale oczywiście zależy od twoich motywów
Pierre

10

Hmm ... Myślę , że możesz użyć, e.clipboardDataaby złapać wklejane dane. Jeśli się nie uda, spójrz tutaj .

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

2
Kiedy uruchamiam to w Safari, dostaję „undefined” :(
Christoffer Winterkvist

1
clipboardData jest sandboxowana w większości przeglądarek (oczywista luka w zabezpieczeniach.)
podperson

2
Tylko Internet Explorer!
Lodewijk

9

Nasłuchuj zdarzenia wklejania i ustaw detektor zdarzenia keyup. Podczas tworzenia klucza przechwyć wartość i usuń moduł nasłuchiwania zdarzeń klucza.

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

6
Jest to bardzo dobre, ale nie działa w przypadku wklejania prawym przyciskiem myszy.
Joseph Ravenwolfe

nie działa również w przypadku wklejania środkowego kliknięcia (X11), działa tylko wtedy, gdy do wklejenia używano klawiatury.
Jasen

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

Będzie dobrze działać.


6

Zbliża się to do tego, czego możesz chcieć.

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() ) );
   }
 });
});

Pamiętaj, że gdy obiekt clipboardData nie zostanie znaleziony (w przeglądarkach innych niż IE), obecnie otrzymujesz pełną wartość elementu + wartość ze schowka.

Prawdopodobnie możesz wykonać dodatkowe kroki, aby różnicować te dwie wartości, przed wejściem i po danych wejściowych, jeśli naprawdę dopiero po tym, jakie dane zostały naprawdę wklejone do elementu.


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

To zadziała dla zdarzenia wklejania myszy.


2
To najlepsze wykorzystanie wszystkich.
Sinan Eldem,

5

Co powiesz na porównanie oryginalnej wartości pola ze zmienioną wartością pola i odjęcie różnicy jako wklejonej wartości? Spowoduje to prawidłowe wychwycenie wklejonego tekstu, nawet jeśli w polu istnieje tekst.

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

Ten kod działa dla mnie albo wklej prawym przyciskiem myszy, albo wklej bezpośrednio kopiuj

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

Po wklejeniu Section 1: Labour Coststaje się 1w polu tekstowym.

Aby zezwolić tylko na wartość zmiennoprzecinkową, używam tego kodu

 //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();

        ...
    }
});

Dalej:


text / html jest niepoprawny, tylko URL i tekst.
Mike

@Mike Skopiowałem fragment kodu bezpośrednio z przywołanej dokumentacji.
davidcondrey

Próbowałem tego przez około dzień. text / html nigdy nie działałby. Skończyło się na dodaniu limitu czasu równego 0 opóźnieniu i byłem w stanie pobrać HTML z div, w którym wklejały się. Gdyby ktoś miał sprawne skrzypce, to by pomogło. Może po prostu źle to robię ...
Mike

3

Zobacz ten przykład: http://www.p2e.dk/diverse/detectPaste.htm

Zasadniczo śledzi każdą zmianę za pomocą zdarzenia oninput, a następnie sprawdza, czy jest to porównanie przez wklejenie. Aha, a w IE jest zdarzenie wklejania. Więc:

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

Czy to niemożliwe, aby uzyskać tekst wklejania, gdy wystąpi zdarzenie?
Christoffer Winterkvist

Cóż, myślę, że będziesz musiał sobie z tym poradzić, na przykład porównać przed i po. To musi być dość łatwe. Ale dlaczego po prostu nie zweryfikujesz ponownie całego wkładu? Powolny?
Ilya Birman

Pomyślałem, że to możliwe, ale chyba nie. W tej chwili próbuję innej metody, wklejając ją do obszaru tekstowego, a następnie przenosząc do ostatecznego miejsca docelowego. Mam nadzieję, że to zadziała.
Christoffer Winterkvist

Musisz tylko znaleźć maksymalny pasujący fragment na początku dwóch ciągów (przed i po). Wszystko stamtąd i aż do różnicy długości jest wklejonym tekstem.
Ilya Birman

@IlyaBirman nie to nie jest: np. Wklejony tekst może zastępować część (lub całość) oryginału
Jasen

1

Ta metoda wykorzystuje zawartość jqueries content (). Uncrap ().

  1. Najpierw wykryj zdarzenie wklejania
  2. Dodaj unikalną klasę do tagów, które są już w elemencie, do którego wklejamy.
  3. Po określonym limicie czasu przejrzyj wszystkie tagi rozpakowywania zawartości, które nie mają ustawionej wcześniej klasy. Uwaga: ta metoda nie usuwa tagów samozamykających się, jak
    na przykład poniżej.

    //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);

Zdecydowanie najlepsza, najkrótsza i mówiąca jak dotąd odpowiedź !!! Dziękuję bardzo,
sprawiłeś

0

Okazało się to dość iluzoryczne. Wartość danych wejściowych nie jest aktualizowana przed wykonaniem kodu wewnątrz funkcji zdarzenia wklejania. Próbowałem wywoływać inne zdarzenia z funkcji wklejania zdarzenia, ale wartość wejściowa nadal nie jest aktualizowana z wklejonym tekstem wewnątrz funkcji jakichkolwiek zdarzeń. To są wszystkie zdarzenia oprócz keyup. Jeśli wywołujesz keyup z funkcji wklejania zdarzenia, możesz zdezynfekować wklejony tekst z funkcji zdarzenia blokowania. tak jak ...

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

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

Jest tutaj jedno zastrzeżenie. W przeglądarce Firefox, jeśli zresetujesz tekst wejściowy przy każdym zestawieniu klawiszy, jeśli tekst jest dłuższy niż widoczny obszar dozwolony przez szerokość wejściową, to zresetowanie wartości przy każdym zestawieniu klawiszy przerywa działanie przeglądarki, która automatycznie przewija tekst do pozycji daszka na koniec tekstu. Zamiast tego tekst przewija się z powrotem na początek, pozostawiając niewidoczny kursor.


onpaste jest wywoływany przed wklejeniem zawartości. Potrzebne jest opóźnienie co najmniej 4 ms, aby utworzyć własną funkcję pasty, aby zmyć wyniki pasty.
DragonLord,

-1

Skrypt do usuwania znaków specjalnych ze wszystkich pól za pomocą klasy portlet-form-input-field:

// 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
Czy możesz dodać opis odpowiedniej dezynfekcji i dlaczego może ona pomóc w rozwiązaniu problemu z plakatem? Samo podanie bloku kodu tak naprawdę nie pomaga OP (lub przyszłym użytkownikom) zrozumieć, jak rozwiązać problem - po prostu zachęca do kopiowania / wklejania źle zrozumianego kodu.
Troy Alford,

-2

Jest tutaj jedno zastrzeżenie. W przeglądarce Firefox, jeśli zresetujesz tekst wejściowy przy każdym zestawieniu klawiszy, jeśli tekst jest dłuższy niż widoczny obszar dozwolony przez szerokość wejściową, to zresetowanie wartości przy każdym zestawieniu klawiszy przerywa działanie przeglądarki, która automatycznie przewija tekst do pozycji daszka na koniec tekstu. Zamiast tego tekst przewija się z powrotem na początek, pozostawiając niewidoczny kursor.

function scroll(elementToBeScrolled) 
{
     //this will reset the scroll to the bottom of the viewable area. 
     elementToBeScrolled.topscroll = elementToBeScrolled.scrollheight;
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.