2

I have a Textbox with the id text ("#text") with has an autocomplete like that:

$("#text").autocomplete(data);

this works fine. Now i want three things:

a) If the user clicks on a autocomplete option -> search for that

b) If the user types something and an autocomplete action is shown but he clicks somewhere else -> search for that string he typed

c) If the user types something that has to autocomplete and clicks somewhere else (change event) -> search for that string he typed

Sounds easy to me but i cant get it to work. At the Moment i have something like that:

$("#text").result(function(e) {
    $("#text").trigger("change");
});
$("#text").change(function(e){
    $(".x").load(...);  
});

If i dont use that trigger, than a) does not work at all, if i type "a" and click on an autocomplete option, "#text" contains "a" in the change function. So the change fires before the value is changed. My thought is that this would be no problem as then shortly after that the result fires the trigger again now with the right value, but that does not happen.

Like this it sometimes works but not all the time. I tried lots and lots of stuff and some worked better and some worse but nothing was correct all the time. How do i do this the right way?

user229044
  • 232,980
  • 40
  • 330
  • 338
Flo
  • 1,660
  • 4
  • 21
  • 34

1 Answers1

2

I've never worked with the autocomplete that you're using, but here's a tool you should include in your JavaScript problem-solving toolbox.

When an event fires immediately before another event and you need to wait for the second event to complete before processing the first, use setTimeout(...). There are times where it looks like a delay is required, but more often than not, you just need a few nested calls to setTimeout(..., 0)

function onIdle(fn, loops) {
  loops = loops == null ? 1 : loops;
  if (loops > 0) {
    setTimeout(function() { onIdle(fn, loops - 1); }, 0);
  } else {
    fn();
  }
}

With the above code, you could do something like this in your onChange handler:

onIdle(function() { ... }, 5);

That would call setTimeout consecutively, 5 times. On the fifth time (after which the other event should have completed), you can process the change and use the new value.

aefxx
  • 24,835
  • 6
  • 45
  • 55
John Fisher
  • 22,355
  • 2
  • 39
  • 64
  • makes sense, but i tried it and it seems (just like before) to work sometimes and sometimes not. – Flo Feb 15 '11 at 16:11
  • It seems to work alot better if i set the loops higher. On a short manual test it seems to run pretty good with 15. I will have to test more, but thanks :) – Flo Feb 15 '11 at 16:19
  • -1 So, bassically you are suggesting to run that function 5 times in a row (each approximately fired after 4 to 10ms). The same could have been achieved - ahem - by `setTimeout(fn, 50);`. – aefxx Sep 29 '12 at 16:41
  • @aefxx: You are quite wrong. Your suggestion does not allow the function to execute after other messages have been placed in the timeout queue. This method allows you to push execution of the function to the end of the queue - including after messages that have not yet been posted. – John Fisher Sep 29 '12 at 17:14
  • 1
    @JohnFisher You have my apologies. It's true that your approach would allow the function in question to run AFTER any other timeout set up in the meantime. – aefxx Sep 30 '12 at 10:54