00robinette
00robinette

Reputation: 557

filtering data using .keypress - no plugins

I am trying to filter data using .keypress. My current approach is to capture the data from .keypress and pass to my filter function. I am successful in returning data that begins with a letter. So if I type A into my field it will return all cats that begin with A. I would like to narrow my search by typing in more letters and have it update each time. Is there a simple solution here? Here is the code

// retrieve data from key press

$("input").keypress(function (e) {
                if (e.which !== 0 && e.charCode !== 0) {
                    var criteria = String.fromCharCode(e.keyCode|e.charCode);
                }
                $.getJSON('cats.json', function(cats) {
                    filterCats(cats, criteria);
                });
            });

// filter function

            function filterCats(cats, criteria){
            $.getJSON('cats.json', function(cats) {
                //var filteredData = cats.filter(function(c){return c.breed.toUpperCase().indexOf(criteria.toUpperCase()) !== -1;});   
                var filteredData = cats.filter(function(c){return c.breed.toUpperCase().indexOf(criteria.toUpperCase()) === 0 ;});    
                renderData(filteredData);
            });
        } 

Upvotes: 0

Views: 899

Answers (2)

Yes Barry
Yes Barry

Reputation: 9846

As others mentioned, keyup is better because it fires after the key is released.

keydown

Fires when the user depresses a key. It repeats while the user keeps the key depressed.

keypress

Fires when an actual character is being inserted in, for instance, a text input. It repeats while the user keeps the key depressed.

keyup

Fires when the user releases a key, after the default action of that key has been performed.

Above from http://www.quirksmode.org/dom/events/keys.html

Also as the other answer states, running your code immediately after every key press could result in a lot of requests sent to the server.

Instead, try throttling it with a timeout.

var timeout, criteria;
$('input').keyup(function(e) {
    clearTimeout(timeout);
    timeout = setTimeout(function() {
        criteria = this.value;
        $.getJSON('cats.json', function(cats) {
            filterCats(cats, criteria);
        });
    }.bind(this), 125);
});

Upvotes: 1

Lajos Arpad
Lajos Arpad

Reputation: 76464

As Andy pointed out in a comment, you need to use the value of the input, since you are currently looking at a single character upon each character entry. As Hossein Shahsahebi pointed out, keyup would be a more accurate event for what you desire to do. Also, do not forget about pasting, which should trigger the same logic.

I would like to add that I believe it is undesirable to do the searching upon each character entry. Imagine someone typing really quickly. You will have a lot of requests sent to the server. I would rather wait for a while before doing the search. When the event is triggered, store the current time in a variable and use setTimeout to wait for a second or so before calling the filterCats function. Whenever the event runs, override that variable to the current moment. When filterCats is executed, check whether the variable's value is old-enough. If not, return without filtering. If so, do the filtering. This will decrease server load due to this feature drastically.

Upvotes: 1

Related Questions