Forum Moderators: open

Message Too Old, No Replies

Search Form Help

Using jQuery and AJAX

         

ridingforlife

3:09 am on Dec 11, 2010 (gmt 0)

10+ Year Member



Hi everyone,

I've got a search form on a website I'm working on, that allows users to search for movie titles. The search form works great with PHP, but I wanted to enhance it with jQuery and AJAX. I'm relatively new to jQuery and AJAX, just started working with it.

When typing in a movie title, the list of movies is dynamically populated below the search and gets smaller with more specificity. However, the problem is shortly after. It seems like the search does a re-search, even after finding a match.

I can type in Bruce Almighty and it will find the match, but then on its own, search for the letter B and give me results containing the letter B - which is a long list of titles. I have the PHP spitting back out what the user has searched for, so I can see that it at first searches for Bruce Almighty, but then all of a sudden is searching for B even if I have the full title in the search form.

This behaviour isn't very consistent, but it's enough to be a bit of a problem.

Does anyone have an idea why this is occurring? I am using the shorthand AJAX .post() function if that helps.

Thanks!

Ps. Sorry if this is in the wrong forum, but this seems like an AJAX thing, not a PHP thing.

Fotiman

5:33 am on Dec 11, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Can you provide some of your AJAX code? Does it use setTimeout to delay the search at all?

Fotiman

5:33 am on Dec 11, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Can you provide some of your AJAX code? Does it use setTimeout to delay the search at all?

ridingforlife

5:43 am on Dec 11, 2010 (gmt 0)

10+ Year Member



Here is the AJAX:


function findTitles(value) {
$.post("php/searchingtitles_ajax.php", {searchtitle:value}, function(data) {
// If the search input is empty
if( $('#searchmovies').attr("value") == "") {
// Display nothing in the #searchResults div
$('#searchResults').html("");
// Otherwise, display the data results in the #searchResults div
} else {
$('#searchResults').html(data);
}
});
}


The function findTitles is called by onkeyup in the search input. There is no setTimeout. For me, it almost seems like it can't keep up. If I type slower it's okay. But if I type normally, it'll keep up but then cut off and only match part of the title, or the first letter, even if it had matched fine at first.

Fotiman

5:11 pm on Dec 11, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Ah, ok. AJAX calls are asynchronous, so you can't guarantee that the results are going to come back in the same order that they were sent out in. Ideally what you should do is add a slight delay before sending a request so that you only send a request after some slight delay instead of after every key press. For example, onkeyup you might do something like this:

findTitlesID = -1;
function () {
clearTimeout(findTitlesID);
findTitlesID = setTimeout(findTitles, 500);
}

Note, that is more of pseudo code example as I'm not showing the logic for passing the value. But essentially what that does is for every onkeyup event, it will clear the timeout for any previous onkeyup event that hasn't triggered a search yet. So if the user is typing faster than 1 key every 500ms, then a search won't execute until the user takes longer than 500ms after a keyup. In addition, instead of passing the value to findTitles, you could have findTitles pull the value from the input box (just to ensure it's the current value and not some value as it appeared 500ms ago).

Does that make sense? Note, I just picked 500 arbitrarily. You might need to play with that to find a delay that meets your needs.

ridingforlife

1:33 am on Dec 12, 2010 (gmt 0)

10+ Year Member



I think that makes sense. Thanks Fotiman, I'll try it out and give an update after I've played with it.

ridingforlife

4:51 am on Dec 12, 2010 (gmt 0)

10+ Year Member



Hi Fotiman,

I guess I'm not understanding this as well as I thought. Are you able to explain this a bit further?

Fotiman

3:39 am on Dec 13, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Sure. When the user is typing you don't actually want to perform the search on each key up because they might be typing quickly. So instead, you want to do something like this:

1. onkeyup schedule an AJAX search to happen after a short delay
2. if there was a previously scheduled search, cancel it

In actuality, we want to perform those steps in reverse order, but it's easier to understand in this order. When the presses a button, we'll clear any previously scheduled AJAX call that has not yet happened (the clearTimeout). Then we'll schedule an AJAX call to happen in a short delay. So if the user types "example" quickly, we won't perform the search as each letter is typed, but only after some short delay. For example, suppose the user types "exa" and then pauses... we'll do the search at that point.

Does that make sense? Is there anything in particular that I could clarify better?

ridingforlife

6:12 am on Dec 14, 2010 (gmt 0)

10+ Year Member



The explanation in plain English makes sense, yes. But I guess the code is what is tripping me up. I'm not sure how to incorporate it in properly while still passing the value.

Fotiman

2:21 pm on Dec 14, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Rather than passing the value, why not just pull it from the text field?

If you want to pass the value, you'll need to do something along the lines of this:

setTimeout(function(){findTitles(value)},500);

ridingforlife

11:06 pm on Dec 14, 2010 (gmt 0)

10+ Year Member



Thanks Fotiman! I changed it as you said to pull the value from the text field, and the delay works great. :)

Fotiman

3:05 am on Dec 15, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Glad to help. :)