Problem, please help

Okay, so I’m a bit stuck.

I have a search form… which drops down and the results are displayed in real time below the form.

If you type too quickly, the results display EVERY entry from the database… not the word in the search box.

If you type slower, it returns the right results, I am stumped on how to fix it.

$(document).ready(function() {
  	$('#results a').click(function(){
	  		$('#results').show();
 	});

	$('#searchval').focus(function() {
		if($datareturn.length == 0) {
  	  		$('#results').css('display', 'none');
  	  	} else {
  	  		$('#results').css('display', 'block');
 	  	}
  	});
	  	
 	$('#searchval').blur(function() {
 		setTimeout(function() {
 			$('#results').hide();
 		}, 400);
	});
	
 	$('#searchval').click(function() {
 		 $('#searchval').attr('value', '');
	});
		
	$('#search').keyup(function() {
		// get the value from the search box
		var $datareturn = $('#searchval').val();	

		// send the data to the script 
		$.get("inc/searchAjax.php", { s: $datareturn }, function(data){
			// process data thats received
			if(data=="error123error") {
				$('#results').css('display', 'none');
			} else {
				$('#search-box').html(data);
				$('#results').fadeIn('slow');
			}
		});
		
	});
});

Search form can be located at the top of http://www.freemoviedb.com/

jS can be located here: http://www.freemoviedb.com/js/freemoviedb.js

Thanks for any help :blush:

What browser are you using when this happens?

edit - i have a very good idea of why this is probably happening. But, I personally can’t reproduce it.

All browsers, if you type too fast for example “Avatar”, type it fast and it will flicker and then show all movie names.

Also, I have this error:

Webpage error details

User Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Tablet PC 2.0)
Timestamp: Sun, 21 Mar 2010 15:21:08 UTC


Message: '$datareturn' is undefined
Line: 7
Char: 3
Code: 0
URI: http://www.freemoviedb.com/js/freemoviedb.js


Message: '$datareturn' is undefined
Line: 7
Char: 3
Code: 0
URI: http://www.freemoviedb.com/js/freemoviedb.js

Any help to fix this would be appreciated.

Why does that variable name start with a dollar sign? Since the $ has special meaning to jQuery I don’t think you should be using that.

I’ve removed the $, I am still new to Javascript & jQuery, although I’ve just bought the novice to ninja book - it hasn’t arrived yet.

Do you know where I can find help for what I need to fix?

Basically I just want it to the results doesn’t stuff up, and I want it to stop blinking.

Ok, I got it to do it.

You have a race condition.
You have multiple ajax requests in progress at the same time. New requests get started before previous requests complete. Here’s the problem.

Lets say The user is searching for “the grave”. Since you use the keyup event, you pretty much send a request for each successive letter combo in that string.

When a request for "the " gets sent, there’s going be a lot of results. It might take lets say 300ms for your server to produce the list because it’s large.
The next request which happens say 50ms later, for “the g” will produce a much smaller list of results. Your server can find and produce this small list much faster, lets say 100ms.

So, if you do the addition, the fast request for “the g” will be received back by the browser before the slow request for "the ". So, the list for “the g” does display, only for a split second until the larger slower request for "the " finally makes it back, which then gets displayed.

Basically, the order in which the ajax requests complete isn’t dependant on the order they were sent. Your code assumes it is, and this is why it’s having the problem.

You need to manage this. You could abort the other ajax requests before sending a new one. There’s other much more advanced techniques that will maximize responsiveness but make sure the ui reflects something intuitive to the user(google’s autocomplete is pretty nice if you want to look).

There’s some jquery plugins to help though. AjaxQueue and AjaxManager plugins exist. There’s also an Autocomplete plugin as well that probably handles this for you(I’ve never used it).

btw- You might also consider some other modifications.

Right now, it looks like if I search for “t” i get a list of every movie in your db that has a t in the movie title. As your site grows, this list could get very large.

If you really desire this functionality(showing everything), then you don’t even need to any more ajax requests after the first letter is known. You could simply filter the list you got back from the server as the user enters more characters. Of course, if the user enters a new search string, and first letter is no longer a “t”, then a new request needs to be sent.

This could be made to be extremely fast from the user perspective, because you could just pregenerate the lists on your server, optionally just storing them as static files that you periodically update. You just need one list for every unique character in the db.

But, the size of the lists could get pretty big.

I’ve just updated the search, check it out and let me know if it looks okay.

http://www.freemoviedb.com

Another question, I want to add a “close” or “x” icon on the list of results that drops down, as some people will probably not think to click out of the div, how do I go about doing this?

It doesn’t look like you even tried to solve race condition at all.

Funny, seeing as I’m using the Autocomplete jquery plugin you told me to.

Maybe they have errors too?

I don’t see the plugin.

(I’m assuming that you are using JQuery UI 1.8 Autocomplete).

It’s not that they have “errors” per se, but they also entirely fail to handle race-conditions (a significant oversight, IMHO). It’s something you have to manage yourself. I’ve managed to implement it (just a few minutes ago), but my implementation is rough at best.

My “fix” involves implementing a new plugin which is uses ui.autocomplete as the base. However you can probably get away with a handling this in a custom callback function. In a nutshell, you need to keep a handle to the XMLHttpRequest instance returned by jQuery’s ajax request methods. Before a new one is sent out you need to call .abort() on the old one.

here is useful information on aborting a jQuery ajax request that might help:

http://stackoverflow.com/questions/446594/kill-ajax-requests-using-javascript-using-jquery

Sorry my answer is so abstract, my implementation is just too rough to pass on right now.

Edit: Okay, bad assumption on my part… I don’t see the plugin implementation either. maybe you mis-interpreted the suggested plugin as the built-in $.get() method. In any case, the concept on fixing is the same. Hopefully my original post will be of use to other people researching this.