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.

Christoffer Winterkvist
źródło
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.

Evgeni Dimov
źródło
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')

});
Charles Haro
źródło
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
})
Xue Liangliang
źródło
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 :)

Christoffer Winterkvist
źródło
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]
});
moff
źródło
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');
}
Eric
źródło
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ć.

Rajat Jain
źródło
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.

Pan Lucky
źródło
6
 $('').bind('input propertychange', function() {....});                      

To zadziała dla zdarzenia wklejania myszy.

Abhiram
źródło
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);
    });
});
Alo Sarv
źródło
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();
      }
    });
RN Kushwaha
źródło
4
document.addEventListener('paste', function(e){
    if(e.clipboardData.types.indexOf('text/html') > -1){
        processDataFromClipboard(e.clipboardData.getData('text/html'));
        e.preventDefault();

        ...
    }
});

Dalej:

Davidcondrey
źródło
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
})
Ilya Birman
źródło
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);
Shadrack B. Orina
źródło
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.


źródło
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");
    }
}
Alex kucharz
źródło
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;
}
lordcheeto
źródło