views:

118

answers:

5

I want to imitate Google suggest with the following code, which means:

step 1: When user types in search box, the query string will be processed by a server php file and query suggestion string is returned(using Ajax object).

step 2:When user clicks on a query suggestion, it will fill into the search box (autocomplete).

Step 1 is achieved while step 2 is not. I think the problem lies in the .click() method (I use .live() later, but it's still not working). My intention is to use .live() or .click() binding a onclick event to the dynamically created <li> element. Any idea?

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;

<script src="jquery-1.4.2.js">
</script>

<style>
#search,#suggest,ul,li{margin: 0; padding:0; width: 200px;}
ul{ list-style-type: none;}
.border{border: solid red 1px; }
</style>

<p>My first language is:</p>
<input type="text" width="200px" id="search" onkeyup="main(this.value)" value="" />
<ul id="suggest"></ul>

<script type="text/javascript">
$(function main(str)
{  //binding any forthcoming li element click event to a function
$('li').live('click', function(){ $("#search").val(array[i]);});
  //setup Ajax object 
  var request=new XMLHttpRequest();
  request.open("GET","language.php?q="+str,true)
  //core function
  request.onreadystatechange=function()
    {    
  if ( request.readyState==4 && request.status==200)
       {  if (str=="") {$('li').remove(); $('ul').removeClass('border');return;}
      $('li').remove();
      reply=request.responseText.split(",");
         for (i=0;i<reply.length;i++)
         {
          //create HTML element of <li>
         $('#suggest').append($('<li>',{id: 'li'+i, html: reply[i]}));
         //style ul
         $('ul').addClass('border');
              }       
      }
    }
  request.send(); 
})
</script>

PHP:

<?php
$q=$_GET[q];

$a[]='english';
$a[]='chinese';
$a[]='japanese';
$a[]='eeeeee';

//lookup all hints from array if length of q>0
if (strlen($q) > 0)
{
  $hint="";
  for($i=0; $i<count($a); $i++)
  {
    if (strtolower($q)==strtolower(substr($a[$i],0,strlen($q))))
    {
      if ($hint=="")
      {
        $hint=$a[$i];
      }
      else
      {
        $hint=$hint." , ".$a[$i];
      }
    }
  }
}

// Set output to "no suggestion" if no hint were found
// or to the correct values
if ($hint == "")
{
  $response="no suggestion";
}
else
{
  $response=$hint;
}

//output the response
echo $response;
?>
+3  A: 

You're looking for jQuery Autocomplete.

Gert G
Thanks, I m looking into it. But i still want to know what goes wrong in my code.
phil
See also [the one in the jQuery UI project](http://jqueryui.com/demos/autocomplete/)
Nathan
A: 

If you want your application to work correctly, you should also consider to cache the response, in case of backspace for instance.

Rob
+2  A: 

You're correct about which line is the problem. You're missing the # to search by ID.

$('li'+i).click(function(){ $("#search").html(array[i]);});

should be

$('#li'+i).click(function(){ $("#search").html(array[i]);});

There are much cleaner ways to do this, however, that don't require a re-query of the document to attach this handler. I concur fully with the suggestion to use a plugin.

x1a4
Thanks for pointing this out.
phil
+1  A: 

Hi, I went through your code and there are few issues in it. 1) If you want to bind click event on dynamically created elements then you should use .live('click', function(){}) event binder. This jQuery function will bind click event on the selector which will be created later on in the code dynamically so li elements that are coming from the server will automatically be binded to the click event if you write live() event on document ready function. Read docs.

Here is the sample code

<script>
$(function(){
$("#suggest li").live('click', function(){
$("#search").val($(this).text()); // li inner html contains text that needs to put into search box
    alert($(this).text());  // or  alert(array[i]); in your code 
   //c what is the out put of above code. better if you change name of an array
});
});
</script>

Also text input elements values are fetch using .val() function instead of .html function in your code $("#search").html(array[i]);

regards Ayaz Alavi

Ayaz Alavi
I modified the script like you said. But it's still not working.1) change ('li'+i) to ('#li'+i)2) change .html() to .val()3) change .click to .live('click',function...) There must be other bugs in the script. Is it have something to do with closure? problem regarding nested function?
phil
dude you need to write live click function only on document on load function for once not for every time you do ajax. If you do it once then every li that will be inserted into #suggest ul later on will automatically be binded with click events. also when you click on an li then alert value of array[i] to see what is the value of array[i] you are inserting into input(c my edited code above) . It is better if you change name of array to something else because it is also a keyword used by Javascript.
Ayaz Alavi
also see ajax response through firebug to see if server is responsindg correctly. Also your function hierarchy is fine. I dont think there is any thing wrong with function calls but make sure keyup event is being fired through alert or through console.log(str) statement.
Ayaz Alavi
I place '$'(shorthand for document.ready) before function main(). and move move .live outside of ajax. Still it's not working. I modified the script in the original post, you may like to copy and run it on your machine. I never used firebug but i know it's good stuff and will check it out. Also, what's console.log(str) statement?
phil
+2  A: 

Also, you might want to wait for the user to be idle. This prevents too many round-trips. This would mean writing something like:

$("input").keyUp(function(e) {
  clearTimeout(updater);
  updater = setTimeout(whenReady, 200);
}

function whenReady() {
  // update the search box here...
}
Tim
Good thoughts. But I am still working on getting the script up and running. I am putting the performance issue on a later date.
phil