views:

462

answers:

6

Hi there, I am building a search box (input field) which should make a server call to filter a grid with the text being inserted on it but I need to make this in an smart way, I need to fire the server call only if the user has stopped. Right now I'm trying to implement it, but if someone knows how to do it I'll be very pleased. Anyway, if I do it first I'll post the answer here... Best Regards, Jaime.

+7  A: 
  1. When a key is pressed:
    1. Check if there's an existing timer - stop it if there is one
    2. start a timer.
  2. When the timer expires, call the server method.
    var searchTimeout;
    document.getElementById('searchBox').onkeypress = function () {
        if (searchTimeout != undefined) clearTimeout(searchTimeout);
        searchTimeout = setTimeout(callServerScript, 250);
    };
    function callServerScript() {
        // your code here
    }
nickf
Be sure the timer has a delay of however long you consider 'done typing' so that you dont catch small pauses. Alternatively, use onblur event to see when the user clicks out of the textbox.
Karl
yes, the delay should depend on how intensive the lookup is, how responsive you want it to be, and also: how fast your users normally type. I've used 250ms for a search and it's been fine IMO.
nickf
shouldn't the event be onkeypress, or something like that?
ng.mangine
oh oops - yes. editing now.
nickf
A: 

I don't know much about JavaScript, but you could use a timer (lets say set to 5 seconds) that gets reset on every change event from your input box. If the user stops typing for more than 5 seconds, the timer expires and triggers the submit.

The problem with that approach is that the submit is triggered on every pause, e.g. if the user stops typing to tale a coffee break. You will have to see if this is acceptable to the users.

Treb
+3  A: 

You could use calls to setTimeout that calls your server function (with a maybe 2-3 second delay) on a keypress event. As soon as akey is pressed, cancel the previous setTimeoutcall and create a new one.

Then, 2-3 seconds have elapsed with no keypresses, the server event will be fired.

Andrew Rollings
hehe... you clever devil nickf! You type faster than me too.
Andrew Rollings
muahahah :) You think I got this rep level by *knowing* things? hah!
nickf
Hehe... You could at least upvote me in consolation :D After all, I *did* know it, and my answer *is* helpful.
Andrew Rollings
+1 Pity for @Andrew Rollings
Redbeard 0x0A
A: 

Hi to everyone, thanks for your feedback. I'd implemented this piece of code and it seems that it does the job (using jquery):

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<script src="jquery.js" type="text/javascript"></script>

<script type="text/javascript">
    var interval = 500;
    var filterValue = "";
    $(document).ready(function() {
        $(".txtSearch").bind("keypress", logKeyPress);
    });
    function logKeyPress() {
        var now = new Date().getTime();
        var lastTime = this._keyPressedAt || now;
        this._keyPressedAt = now;
        if (!this._monitoringSearch) {
            this._monitoringSearch = true;
            var input = this;
            window.setTimeout(
                function() {
                    search(input);
                }, 0);
        }
    }
    function search(input) {
        var now = new Date().getTime();
        var lastTime = input._keyPressedAt;
        if ((now - lastTime) > interval) {
            /*console.log(now);
            console.log(lastTime);
            console.log(now - lastTime);*/
            if (input.value != filterValue) {
                filterValue = input.value;
                //console.log("search!");
                alert("search!");
            }
            input._monitoringSearch = false;
        }
        else {
            window.setTimeout(
                function() {
                    search(input);
                }, 0);
        }
    }
</script>

Jaime Febres
Sorry, but I don't think that's a very good way to do it... won't it continuously call search() over and over until the interval is up?
nickf
No, it will stop when the difference between the last time that a key was pressed and the current time > to the *interval* variable (bad name I know). Try it by yourself.
Jaime Febres
+2  A: 

Here is a simple way that will work without jQuery:

<input type="text" id="TxtSearch" onchange="countDown=10;" />

<script type="text/javascript">

var countDown = 0;
function SearchTimerTick()
{
   if(countDown == 1)
   {
      StopTypingCommand();
      countDown = 0;
   }

   if(countDown > 0)
      countDown--;
}

window.setInterval(SearchTimerTick,1000);

</script>
Paul
+1  A: 

You also probably want to check the length of the string on the input box, otherwise risk returning a huge result set!

Redbeard 0x0A
very true point - though that could probably be done server-side. definitely check for an empty string though.
nickf
Thanks for your comment, in the real application an empty box is a valid criteria filter (it means *show me everything*), I'm paging the results so there is no overhead.
Jaime Febres