6

I've created a Facebook style ajax search for my site where as you type it will bring up the results in a nice list below your search.

$("#s").keyup(function() {
    var searchbox = $(this).val();
    var dataString = 's='+ searchbox;
    if(searchbox!='') {
        $.ajax({
            type: "POST",
            url: "/livesearch.php",
            data: dataString,
            cache: false,
            success: function(html){
                $("#display").html(html).show();
            }
        });
    } else {return false; }  
});

$("body").click(function() {
        $("#display").hide();
});

The problem with this is it's a little ineffective as the user will type a word for example "football". This will carry out 8 requests to the server. What would be a more effective way to do this? ideally i think it should store the request for 1 second before doing a search rather than instant keyup. but not 100% sure how to do that...

Shadi Almosri
  • 11,678
  • 16
  • 58
  • 80

3 Answers3

10

the method you are referring to is called "Debouncing"

I usually have a "Debounce" function at the bottom of all my scripts

var debounce=function(func, threshold, execAsap) {
    var timeout;
    return function debounced () {
        var obj = this, args = arguments;
        function delayed () {
            if (!execAsap)
                func.apply(obj, args);
            timeout = null; 
        };
        if (timeout)
            clearTimeout(timeout);
        else if (execAsap)
            func.apply(obj, args);
        timeout = setTimeout(delayed, threshold || 100); 
    }; 
};

And then whenever I do anything that will benefit from a debounce I can use it generically

So your code would be re-written as

$("#s").keyup(debounce(function() {
    var searchbox = $(this).val();
    var dataString = 's='+ searchbox;
    if(searchbox!='') {
        $.ajax({
                type: "POST",
                url: "/livesearch.php",
                data: dataString,
                cache: false,
                success: function(html){
                        $("#display").html(html).show();
                }
        });
    } else {return false; }  
}
,350 /*determines the delay in ms*/
,false /*should it execute on first keyup event, 
       or delay the first event until 
       the value in ms specified above*/
));
ekhaled
  • 2,930
  • 20
  • 24
  • of course, you can play around with the delay value to find out what suits you best, for me 350m/s works perfectly.... remember, people type quite fast, and the timeout gets reset to 350ms everytime a letter is typed – ekhaled Oct 14 '09 at 22:24
  • Also, I suggest caching the results, either in JS or w/ HTTP - example: `deboun[500 ms pause]cws[1000 ms pause][backspace][backspace][backspace][500 ms pause]ce`. Without caching, you're sending 2 requests for `deboun`. – Piskvor left the building Nov 04 '09 at 14:22
2

Another option would be to start searching after 2/3 characters. Waiting for 1 second before making every request doesn't look good to me. Also try to send very less data back to server which might also make the request and response faster.

Shoban
  • 22,920
  • 8
  • 63
  • 107
2

You could have a JSON object sitting somewhere and searching that instead of searching the database multiple times. It won't bring too much overhang, as long as it's not a list of 1,000 friends or something.

Garrett
  • 7,830
  • 2
  • 41
  • 42