Sposób wykrywania zawartości pola tekstowego uległ zmianie

417

Chcę wykrywać za każdym razem, gdy zmienia się zawartość pola tekstowego. Mogę użyć metody uzupełniania, ale wykryje także naciśnięcia klawiszy, które nie generują liter, jak na przykład klawisze strzałek. Pomyślałem o dwóch metodach wykonania tego za pomocą zdarzenia keyup:

  1. Sprawdź dokładnie, czy kod ascii naciśniętego klawisza to litera \ backspace \ delete
  2. Użyj zamknięć, aby zapamiętać tekst w polu tekstowym przed naciśnięciem klawisza i sprawdź, czy to się zmieniło.

Oba wyglądają trochę nieporęcznie.

olamundo
źródło
7
Tak, łapanie keyup do tego jest złe. Możesz wklejać pliki bez żadnych naciśnięć klawiszy.
spędzić
2
masz szansę opublikować swoje ostateczne rozwiązanie? Muszę też rozwiązać ten problem :)
Matt Dotson,
1
lub .keyup()wydarzenie ... więcej informacji tutaj: stackoverflow.com/questions/3003879/…
Victor S
1
Zobacz $ („# some-input”). ChangePolling () ; dla opakowania, które sprawdza bieżącą wartość i uruchamia się, .change()jeśli uległa zmianie.
Joel Purra
musisz to sprawdzić też stackoverflow.com/a/23266812/3160597
azerafati,

Odpowiedzi:

714

Zacznij obserwować zdarzenie „wejście” zamiast „zmiana”.

jQuery('#some_text_box').on('input', function() {
    // do your stuff
});

... który jest ładny i czysty, ale można go rozszerzyć na:

jQuery('#some_text_box').on('input propertychange paste', function() {
    // do your stuff
});
Atul Vani
źródło
12
„live” jest przestarzałe. więc skorzystaj z „on” stackoverflow.com/a/15111970/1724777
NavaRajan
21
Jedynym minusem „wejścia” jest to, że nie jest on zgodny z IE <9.
Catfish
5
Dane wejściowe to zdarzenie HTML5, które nie jest obsługiwane we wszystkich przeglądarkach. developer.mozilla.org/en-US/docs/Web/API/window.oninput
commonpike
18
Możesz także objąć większą liczbę baz, używając: .on ('wklej propertychange'), function () {
Graeck
23
Jedynym minusem IE <9 jest to, że nikt go nie używa!
sohaiby,
67

Użyj zdarzenia onchange w HTML / standardowym JavaScript.

W jQuery jest to zdarzenie change () . Na przykład:

$('element').change(function() { // do something } );

EDYTOWAĆ

Po przeczytaniu kilku komentarzy, co z:

$(function() {
    var content = $('#myContent').val();

    $('#myContent').keyup(function() { 
        if ($('#myContent').val() != content) {
            content = $('#myContent').val();
            alert('Content has been changed');
        }
    });
});
Waleed Amjad
źródło
3
Tak, jest to podobne do tego, co zasugerowałem w opcji 2 w moim pytaniu. Wolę zamknięcia, ponieważ użycie globalnego sprawi, że ta funkcja będzie działać tylko dla jednego pola tekstowego. W każdym razie wydaje się, że dziwna jquery nie ma prostszego sposobu na zrobienie tego.
olamundo
1
To jest rzeczywiście dziwne, ale wątpię, aby istniał lepszy sposób. Możesz użyć setInterval, a następnie sprawdzić, czy zawartość została zmieniona co 0,1 sekundy, a następnie coś zrobić. Dotyczy to również past myszy i tak dalej. Ale to nie brzmi zbyt elegancko.
Waleed Amjad
4
Nadal możliwe jest zmienianie treści bez naciskania klawisza, na przykład przez wklejenie myszy. Jeśli ci na tym zależy, teoretycznie możesz również złapać zdarzenia myszy, ale ta konfiguracja jest jeszcze brzydsza. Z drugiej strony, jeśli zechcesz zignorować zmiany sterowane myszą, zrobi to.
Adam Bellaire,
45

Zdarzenie „zmiana” nie działa poprawnie, ale „wejście” jest idealne.

$('#your_textbox').bind('input', function() {
    /* This will be fired every time, when textbox's value changes. */
} );
schwarzkopfb
źródło
7
Działa to idealnie w mojej sytuacji, chociaż .onzaleca się stosowanie od wersji 1.7 (zamiast .bind).
Nick
8
OP nie określił potrzeby zgodności między przeglądarkami. @schwarzkopfb zapewnił rozwiązanie. Nie ma powodu, aby głosować odmownie, ponieważ masz do tego przedstawiciela.
David East
3
@David nie określił także, którą przeglądarkę
ozz
9
@ jmo21 Myślę, że możemy założyć, że tworzenie stron internetowych nie jest specyficzne dla przeglądarki, rozwiązanie powinno być wielofunkcyjne. Norma obsługuje wszystkie przeglądarki.
Chris
3
@Chris „Norma obsługuje wszystkie przeglądarki” - tylko jeśli jesteś sadystą. Nie ma dobrego powodu, aby unikać dobroci HTML5 dla 2% globalnych użytkowników w IE 8/9. caniuse.com/#feat=input-event
Yarin
39

Co powiesz na to:

<jQuery 1.7

$("#input").bind("propertychange change keyup paste input", function(){
    // do stuff;
});

> jQuery 1.7

$("#input").on("propertychange change keyup paste input", function(){
    // do stuff;
});

Działa to w IE8 / IE9, FF, Chrome

Kocia ryba
źródło
1
Problem z tą odpowiedzią polega na tym, że uruchamia się po rozmyciu pola tekstowego, nawet jeśli wartość się nie zmieniła. Sprawcą jest „zmiana”.
Justin
Czy używasz Chrome? Wydaje się, że jest to błąd z chromem i nie jQuery zmiana wydarzenie bugs.jquery.com/ticket/9335
Catfish
działa, ale ma niewielki błąd, jeśli wykonasz console.logwartość pola, które rejestruje dwa razy za każdym razem, gdy wpiszesz znak.
Samuel M.
21

Użyj zamknięć, aby zapamiętać tekst w polu wyboru przed naciśnięciem klawisza i sprawdź, czy to się zmieniło.

Tak. Nie musisz koniecznie używać zamknięć, ale musisz zapamiętać starą wartość i porównać ją z nową.

Jednak! To wciąż nie wychwyci każdej zmiany, ponieważ istnieją sposoby edycji zawartości pola tekstowego, które nie wymagają żadnego naciśnięcia klawisza. Na przykład zaznaczenie zakresu tekstu, a następnie kliknięcie prawym przyciskiem myszy. Lub przeciągając. Lub upuszczenie tekstu z innej aplikacji do pola tekstowego. Lub zmieniając słowo za pomocą sprawdzania pisowni w przeglądarce. Lub...

Więc jeśli musisz wykryć każdą zmianę, musisz ją sondować. Możesz window.setIntervalsprawdzić pole względem jego poprzedniej wartości co (powiedzmy) sekundę. Można również podłączyć onkeyupdo tej samej funkcji, tak aby zmiany, które spowodowane przez znakom odzwierciedlone są szybciej.

Nieporęczny? Tak. Ale tak jest lub po prostu zrób to w zwykły sposób wymiany HTML i nie próbuj natychmiastowej aktualizacji.

Bobin
źródło
1
Obecnie inputwydarzenie HTML5 jest opłacalne i działa w aktualnych wersjach wszystkich głównych przeglądarek.
Tim Down
13
$(document).on('input','#mytxtBox',function () { 
 console.log($('#mytxtBox').val());
});

Możesz użyć zdarzenia „input”, aby wykryć zmianę treści w polu tekstowym. Nie używaj „na żywo”, aby powiązać zdarzenie, ponieważ jest ono przestarzałe w Jquery-1.7, więc skorzystaj z „on”.

NavaRajan
źródło
@NavaRajan Właśnie przetestowałem to ponownie w IE9. naprawdę nie działa na backspace.
Flores,
Nie chcę używać .live, ale mam problem polegający na tym, że jakoś poszedłem „z powrotem do przyszłości” i do projektu mvc3, w którym kierownik zespołu chce trzymać się „po wyjęciu z pudełka”, więc nie tylko EF 4.0, ale jquery 1.5.1 jest używane THUS .on () nie był w 1.5.1, ponieważ został dodany w jquery wersji 1.7 api.jquery.com/on
Tom Stickel
5

Zakładam, że chcesz zrobić coś interaktywnego, gdy zmieni się pole tekstowe (tj. Pobierz niektóre dane przez ajax). Szukałem tej samej funkcjonalności. Wiem, że używanie globalnego rozwiązania nie jest najbardziej niezawodnym ani eleganckim rozwiązaniem, ale właśnie z tym poszedłem. Oto przykład:

var searchValue = $('#Search').val();
$(function () {
    setTimeout(checkSearchChanged, 0.1);
});

function checkSearchChanged() {
    var currentValue = $('#Search').val();
    if ((currentValue) && currentValue != searchValue && currentValue != '') {
        searchValue = $('#Search').val();
        $('#submit').click();
    }
    else {
        setTimeout(checkSearchChanged, 0.1);
    }
}

Jedną kluczową rzeczą do odnotowania tutaj jest to, że używam setTimeout, a nie setInterval, ponieważ nie chcę wysyłać wielu żądań jednocześnie. Zapewnia to, że licznik czasu „zatrzymuje się” po przesłaniu formularza i „uruchamia się” po wypełnieniu żądania. Robię to, wywołując checkSearchChanged, gdy zakończy się moje wywołanie ajax. Oczywiście możesz to rozwinąć, aby sprawdzić minimalną długość itp.

W moim przypadku używam ASP.Net MVC, więc możesz zobaczyć, jak powiązać to z MVC Ajax, a także w następującym poście:

http://geekswithblogs.net/DougLampe/archive/2010/12/21/simple-interactive-search-with-jquery-and-asp.net-mvc.aspx

Doug Lampe
źródło
4

Poleciłbym rzucić okiem na widget autouzupełniania interfejsu użytkownika jQuery. Zajęli się większością spraw, ponieważ ich baza kodu jest bardziej dojrzała niż większość obecnych.

Poniżej znajduje się link do strony demonstracyjnej, dzięki czemu możesz sprawdzić, czy działa. http://jqueryui.com/demos/autocomplete/#default

Największą korzyść uzyskasz, czytając źródło i sprawdzając, jak go rozwiązali. Można go znaleźć tutaj: https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.autocomplete.js .

Zasadniczo robią to wszystko, z czym się wiążą input, keydown, keyup, keypress, focus and blur. Następnie mają specjalną obsługę dla wszelkiego rodzaju kluczy, takich jak page up, page down, up arrow key and down arrow key. Timer jest używany przed uzyskaniem zawartości pola tekstowego. Gdy użytkownik wpisze klawisz, który nie odpowiada poleceniu (klawisz w górę, klawisz w dół itd.), Pojawia się licznik czasu, który eksploruje zawartość po około 300 milisekundach. W kodzie wygląda to tak:

// switch statement in the 
switch( event.keyCode ) {
            //...
            case keyCode.ENTER:
            case keyCode.NUMPAD_ENTER:
                // when menu is open and has focus
                if ( this.menu.active ) {
                    // #6055 - Opera still allows the keypress to occur
                    // which causes forms to submit
                    suppressKeyPress = true;
                    event.preventDefault();
                    this.menu.select( event );
                }
                break;
            default:
                suppressKeyPressRepeat = true;
                // search timeout should be triggered before the input value is changed
                this._searchTimeout( event );
                break;
            }
// ...
// ...
_searchTimeout: function( event ) {
    clearTimeout( this.searching );
    this.searching = this._delay(function() { // * essentially a warpper for a setTimeout call *
        // only search if the value has changed
        if ( this.term !== this._value() ) { // * _value is a wrapper to get the value *
            this.selectedItem = null;
            this.search( null, event );
        }
    }, this.options.delay );
},

Powodem użycia timera jest to, że interfejs użytkownika ma szansę na aktualizację. Gdy JavaScript jest uruchomiony, interfejs użytkownika nie może zostać zaktualizowany, dlatego wywołanie funkcji opóźnienia. Działa to dobrze w innych sytuacjach, takich jak skupienie się na polu tekstowym (używanym przez ten kod).

Możesz więc użyć widgetu lub skopiować kod do własnego widgetu, jeśli nie używasz interfejsu jQuery (lub w moim przypadku opracowujesz niestandardowy widget).

Michael Yagudaev
źródło
2

Chciałbym zapytać, dlaczego próbujesz wykryć, kiedy zawartość pola tekstowego zmieniała się w czasie rzeczywistym ?

Alternatywą byłoby ustawienie timera (przez setIntval?) I porównanie ostatnio zapisanej wartości z bieżącą, a następnie zresetowanie timera. Zapewniłoby to wyłapanie KAŻDEJ zmiany, spowodowanej przez klawisze, mysz, inne urządzenie wejściowe, którego nie wziąłeś pod uwagę, a nawet JavaScript zmieniającą wartość (innej możliwości, o której nikt nie wspominał) z innej części aplikacji.

DVK
źródło
moja sytuacja (która doprowadziła mnie do tego pytania) jest taka, że ​​muszę pokazać przycisk „Aktualizuj koszyk”, gdy ilość w polu tekstowym zostanie zmieniona. użytkownik nie ma pojęcia, że ​​musi stracić koncentrację i w przeciwnym razie może nie zobaczyć przycisku.
Simon_Weaver,
Niestety nie jestem pewien, czy to odpowiada na pytanie „dlaczego nie sprawdzić różnic w harmonogramie”. Wystarczy często sprawdzać (co 1/4 sekundy), a użytkownik nie zauważy żadnej różnicy.
DVK
1

czy rozważasz użycie zdarzenia zmiany ?

$("#myTextBox").change(function() { alert("content changed"); });
Canavar
źródło
5
AFAIK, jest wyzwalany tylko wtedy, gdy utracony jest punkt skupienia elementu. Ktoś, kto zna zamknięcia, prawdopodobnie wie o tym. :)
simon
tak, to się nie stanie - zdarzenie zmiany jest wywoływane tylko wtedy, gdy pole tekstowe traci fokus. Chcę obsłużyć zmianę zaraz po naciśnięciu klawisza.
olamundo
1

Użyj textchange zdarzenia za pomocą niestandardowego podkładki jQuery w celu inputzapewnienia zgodności z różnymi przeglądarkami . http://benalpert.com/2013/06/18/a-near-perfect-oninput-shim-for-ie-8-and-9.html (ostatnio rozwidlony github: https://github.com/pandell /jquery-splendid-textchange/blob/master/jquery.splendid.textchange.js )

Obsługuje wszystkie znaczniki wejściowe, w tym <textarea>content</textarea>, które nie zawsze działają z change keyupitd. (!) Tylko jQueryon("input propertychange") obsługuje <textarea>tagi konsekwentnie, a powyższe jest fałszywe dla wszystkich przeglądarek, które nie rozumieją inputzdarzenia.

<!DOCTYPE html>
<html>
<head>
<script class="jsbin" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="https://raw.githubusercontent.com/pandell/jquery-splendid-textchange/master/jquery.splendid.textchange.js"></script>
<meta charset=utf-8 />
<title>splendid textchange test</title>

<script> // this is all you have to do. using splendid.textchange.js

$('textarea').on("textchange",function(){ 
  yourFunctionHere($(this).val());    });  

</script>
</head>
<body>
  <textarea style="height:3em;width:90%"></textarea>
</body>
</html>

Test JS Bin

To również obsługuje wklejanie, usuwanie i nie powiela wysiłku na keyup.

Jeśli nie używasz podkładki dystansowej, użyj on("input propertychange")zdarzeń jQuery .

// works with most recent browsers (use this if not using src="...splendid.textchange.js")

$('textarea').on("input propertychange",function(){ 
  yourFunctionHere($(this).val());    
});  
Ber
źródło
0

Jest kompletnym przykładem pracy tutaj .

<html>
<title>jQuery Summing</title>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"> </script>
$(document).ready(function() {
$('.calc').on('input', function() {
var t1 = document.getElementById('txt1');
var t2 = document.getElementById('txt2');
var tot=0;
if (parseInt(t1.value))
tot += parseInt(t1.value);
if (parseInt(t2.value))
tot += parseInt(t2.value);
document.getElementById('txt3').value = tot;
});
});
</script>
</head>
<body>
<input type='text' class='calc' id='txt1'>
<input type='text' class='calc' id='txt2'>
<input type='text' id='txt3' readonly>
</body>
</html>
worldofjr
źródło
0

Coś jak to powinno działać, głównie dlatego, focusi focusoutskończy się z dwóch oddzielnych wartości. Używam datatutaj, ponieważ przechowuje wartości w elemencie, ale nie dotyka DOM. Jest to również łatwy sposób na przechowywanie wartości związanej z jego elementem. Równie łatwo można użyć zmiennej o wyższym zasięgu.

var changed = false;

$('textbox').on('focus', function(e) {
    $(this).data('current-val', $(this).text();
});

$('textbox').on('focusout', function(e) {
    if ($(this).data('current-val') != $(this).text())
        changed = true;
    }
    console.log('Changed Result', changed);
}
smcjones
źródło
0

Ten kod wykrywa, gdy zawartość pola tekstowego zostanie zmieniona przez użytkownika i zmodyfikowana przez kod JavaScript.

var $myText = jQuery("#textbox");

$myText.data("value", $myText.val());

setInterval(function() {
    var data = $myText.data("value"),
    val = $myText.val();

    if (data !== val) {
        console.log("changed");
        $myText.data("value", val);
    }
}, 100);
Sandeep Yadav
źródło