AJAX Autocomplete Tutorial



7.81 K Views | Rishi Kashyap | 1
Rishi Kashyap
8.66 K
X

AJAX Autocomplete Tutorial


0

After searching long for an autocomplete tutorial I finally gave up as AJAX Autocomplete tutorials were using some framework or they were just too complicated to me. I am specifically avoiding JQuery, scriptaculous, RICO or any other framework just to understand how autocomplete works. This way when I need to alter it later, I would know which line to change.

Though I admit that I am no expert in Javascript or PHP however I do know basics of Javascript. I do not intend to say that the AJAX autocomplete developed is best or perfect in any sense ! With the limited knowledge in Javascript, I am writing this tutorial (following the KISS principle) just to make it clear how the autocomplete works.

The tutorial uses basics of Javascript, DHTML, AJAX calls and javascript functions. I am still uncomfortable with classes, objects,events in javascript. Sure you can use your perfect knowledge and experience to improve it and make it better. Please feel free to reply. Hope this AJAX autocomplete tutorial helps someone.

Rishi Kashyap | | EDIT | REPLY

Rishi Kashyap
8.66 K
X What is Autocomplete ?
0

Autocomplete is used by most of the websites and you may have already used it in Google or Facebook. Google and Facebook use it in their search box. Facebook uses autocomplete even for adding college, company and other profile details. So what is Autocomplete ?

Typeahead was started as a feature by which the textbox in the browser will complete your sentence as you start typing. Later typeahead was modified to be autocomplete and autosuggest. While initially it meant differently today autocomplete, autosuggest and typeahead means almost the same thing. Once you start typing in the text box, it offers you an autocomplete dropdown with suggested lines. Some scripts may pre-fill the textbox with one suggestions and highlight that (typeahead) while others may just give you options for selection.

The autocomplete consists of 3 parts :


  1. 1. Browser or client side.

  2. This is the part where the user interacts and types in the text box. The data fetched from the server is also modified here using Javascript and shown to the user for selecting and avoiding writing the complete line. Most of the action occurs here with the use of javascript.
  3. 2. The AJAX page.

  4. While the user types anything in the text-box, the content is send to the server using AJAX features. AJAX in simple terms means that the content (in this case the typed character) is sent to the server without page reloads/refresh using javascript (asynchronously). Talking in detail about AJAX is beyond the scope of this tutorial. (Sorry !)
  5. 3. The database.

  6. The AJAX page interacts with the database and gets the data to be used on the client side.

Since everything is happening on the same page without any page reload, most of the things have to be done by Javascript. Javascript is a client side language and controls the browser activities. As most of the thing is done in Javascript it hardly matter whether you are using PHP or ASP or JSP as your server language, the program should work well with any server language.

Autocomplete helps both the website developer as well as User. For the user, he needs to type less and can select from the available options. For the developer, it can avoid duplication. Facebook offers you some college name once you type few text in the textbox. You type less and select from the college options. Once you select the college, Facebook knows that its not a new college, but an old one already in the database !What is Autocomplete

Rishi Kashyap | | EDIT | REPLY
Rishi Kashyap
8.66 K
X Autocomplete Basic Idea
0

For an autocomplete, the form generally displays an empty text-box. As the user types something, an options open below the text-box with the suggestion. The options are hidden div or span element which becomes visible once user start to type anything.

For basic understanding let us create the autocomplete HTML with this hidden element visible and rather than sending the data while typing, we will send the detail on click of the button. The Javascript and coding are not clean and we will improve as we will progress with the tutorial. Certain Browser offer their own Autocomplete feature which shows a dropdown of previously entered text. To stop this default nature we are using AUTOCOMPLETE="off".

(A) AUTOCOMPLETE HTML
<form name="autcomplete_form" AUTOCOMPLETE="off" ID="autcomplete_form">
  AutoComplete Text Box: <br/>
  <input type="text" name="autocomplete_value" id="autocomplete_value" style="width:500px;"/>
  <div style="border:1px solid;margin:0;padding:0;width:500px;" id="dropdown">The AJAX Autocomplete data will come here but you will not be able to select it !<br/>
  Write something of 3 characters to search for and press the "AUTOCOMPLETE" button.</div><input type="button" value="AUTOCOMPLETE" onclick="ajax_autocomplete();"/></form>

I have left comments for almost every line on Javascript and hence not explaining much about it.

(B) AUTOCOMPLETE JAVASCRIPT
<script type="text/javascript">
function ajax_autocomplete(){
//Get the text from the text-box
var matter=$("autocomplete_value").value;

//Make the AJAX Call
//Send the data to the PHP page "aj_autocomplete-example.php"
//The returned data will be displayed in the div with id "dropdown"
//While the AJAX data is send/received keep the user informed with text "autocompleting.."
callAHAH("aj_autocomplete-example.php?p=1&m="+matter,"dropdown","autocompleting..")
}</script>

The page does not do much. You type few words and rather then the script automatically sending the text you click the "AUTOCOMPLETE" button. The button once clicked gets the text in the text box.

There is no particular CSS necessary now.

The backend for getting Server data from the database is done in PHP. Presently we are returning the blog title of every topic. You can add more security measures and for tutorial purpose I am keeping it simple. The variable "$con" stores the database connection details.

(C) AUTOCOMPLETE PHP
<?php
$con = @mysql_connect($host,$user,$pwd);
$matter=strip_tags(mysql_real_escape_string($_GET["m"]));
$query_t="SELECT Blog_Title FROM Posts WHERE Blog_Title LIKE '%$matter%'";
$result_t= @mysql_query($query_t,$con);
if(mysql_num_rows($result_t)>0)
{while($mydata_t = @mysql_fetch_array ($result_t)){echo stripslashes($mydata_t['Blog_Title']).'<br/>';}}
else {echo '<span class="errors">Nothing Found</span>';}
?>

There is no fixed way for making AJAX calls and your script may vary.

You can see the demo at https://www.jahajee.com/e/ajax-autocomplete/EXAMPLE/Autocomplete Basic Idea

Rishi Kashyap | | EDIT | REPLY
Rishi Kashyap
8.66 K
X Find as you type - 1
0

Now that we have a basic idea how the autocomplete works let us remove the "AUTOCOMPLETE" button and try to find as you type. We will also improve the code so that minimum AJAX calls are made. The tutorial accompanies demo and examples at AJAX AUTOCOMPLETE EXAMPLE

I will jump straight to last part as it will cover almost all previous parts and is an improvement to all previous scripts. You are free to view the source of those web-page for better understanding of the Javascript code. Yet again breaking into 4 parts :

(A) AUTOCOMPLETE HTML
An "onkeyup" event has been attached to the textbox for activating the autocomplete and removal of the "AUTOCOMPLETE" button.
Another input text-box "thetxtid" added to prevent default form submission by clicking enter key. For tutorial is made visible as it will also get the blog_id of the returned blog title, in actual use "thetxtid" should be hidden from the user.
A div with class "bahar" added to align the dropdown div below the textbox.
<form name="autcomplete_form" AUTOCOMPLETE="off" ID="autcomplete_form">
Option ID (will be filled automatically after selection of option): <input type="text" name="thetxtid" id="thetxtid" style="" /><br/>
  AutoComplete Text Box: <br/>
  <input type="text" name="autocomplete_value" id="autocomplete_value" style="width:500px;" onkeyup="ajax_autocomplete(this.value,event);"/>
  <div class="bahar"><div class="hide" id="dropdown"></div></div>
  </form>

(B) AUTOCOMPLETE CSS
"dt" and "marker" are classes with "marker" having additional characteristic of highlighting the background.
"marker" class highlights the selected option by arrow keys.
div:hover highlights the selected option by mouse.
"hide" will hide any element with this class, in our case the "dropdown" element.
"bahar" is a div created with relative positioning. Any element with absolute positioning can be controlled within it.
"show" will make the "dropdown" div visible with absolute positioning and high z-index so that it acts like a dropdown option.

All the highlighting, showing and hiding of dropdown box is done by changing the class name of elements by using Javascript
<style type="text/css">
.dt,.marker{margin:1px;padding:1px;}
#dropdown div:hover{font-weight:bold;background:#DFEBFD;}
.marker{font-weight:bold;background:#DFEBFD;}
.hide{display:none;}
.bahar{position:relative;margin:0;padding:0;}
.show{display:block;border:1px solid;margin:0;padding:0;width:500px;position:absolute;background:#fff;z-index:10;height:200px;overflow:auto;}
</style>

(C) AUTOCOMPLETE PHP
As told before, most action in autocomplete is primarily because of Javascript and only the data fetched and returned by server requires server side programming. This server side programming can be in any language PHP, ASP, JSP etc. In my case I am using PHP as shown below.

While the data returned by Server can also be pre formatted like I was doing in previous AJAX AUTOCOMPLETE EXAMPLE. This approach is not advisable as we need to get the raw data for local caching and searching and filtering on the client side (read browser). Hence pre formatting will ad another complexity.
I am sending each blog id and title separated by string "---". Each such data is again separated by "***". Hence we can separate the data easily using Javascript.
If there is no result in the database then the server returns '<span class="errors">Nothing Found</span>'.
<?php
$con = @mysql_connect($host,$user,$pwd);
$matter=strip_tags(mysql_real_escape_string($_GET["m"]));
$query_t="SELECT blog_id,Blog_Title FROM database.Posts WHERE Blog_Title LIKE '%$matter%' LIMIT 0,100";
$result_t= @mysql_query($query_t,$connection);
if(mysql_num_rows($result_t)>0)
{while($mydata_t = @mysql_fetch_array ($result_t))
{$res[]="$mydata_t[blog_id]---".stripslashes($mydata_t[Blog_Title]);}
echo join('***',$res);}
else {echo '<span class="errors">Nothing Found</span>';}
?>

Rishi Kashyap | | EDIT | REPLY
Rishi Kashyap
8.66 K
X Find as you type - 2
0

The tutorial accompanies demo and examples at AJAX AUTOCOMPLETE EXAMPLE

Autocomplete Javascript for finding as you type has comments which should be self explanatory.

Rather than making AJAX Calls on every key press what we are doing is we are getting a large number of data. So for "Wh" we will get all the blog title which have "what", "why", "which", "where" etc. So on further key press we search first locally refining our results. Once no results are found locally we again make an AJAX Call and again get large results. The process continues like this till 4 AJAX Calls. If even after that we do not find any matches locally or at server then we assume that there is no data with such typed text. This caching and restricting AJAX calls to autocomplete will restrict large usage of your website bandwidth and better results with more text being send between each AJAX calls and hence better results.
<script type="text/javascript">
//Declare some global variables
//"recarray" is an array which will hold all the data returned from server by AJAX call
var recarray = new Array();
//"chosen" will store the highlighted option position by the arrow key
var chosen="";
//"opt_no" stores the highlighted options number by the arrow key
var opt_no= new Array();
//"searching" is a boolean which will tell whether an AJAX call is already in progress
var searching;
//"nothing" is a boolean checking if server has anything to return as data
var nothing = false;
//"before" will hold the previous value entered in the textbox e.g. the value less the last character
var before ="";
//"no_time" will hold the number of AJAX calls made.
var no_time =0;

function shownothing(x){
//If there is no matched data locally or from server then show the below divs
 $("dropdown").innerHTML='<span id="showid_-1" class="hide">' x '</span><span id="valid_-1" class="hide">-1</span><div

class="dt" id="opt_-1" onclick=setvalue("-1"); onmouseover="removed();">' x '</div>';
 }

//"allok" is a function used in the AJAX call and is used once the AJAX call is completed
//Using this function you can decide what to do with the returned data from the AJAX Call
//The function forms the 4th optional part of the AJAX calls.
function allok(to_show,to_modify){
 //to_show holds the AJAX returned data
//to_modify holds the text entered in the text-box
the_value=to_modify;
//If the server has nothing to show
if(to_show =='<span class="errors">Nothing Found</span>')
{
  //set "nothing" to true
  nothing=true;
  //Increase the count of "no_time"
  no_time  ;
  //activate the "shownothing" function
  shownothing(the_value);
if (no_time > 3){nothing=false;}
}
else{
//Received data to be formatted - split the data into array where the string has "***"
recarray = to_show.split("***");
//Call the "listing" function with the typed text
listing(the_value);
}
//Set the searching to false indicating AJAX call ended
searching = false;
}

//This function will remove the highlighted option selected by the arrow key
function removehighlight(theClass){
 //Get all the elements with tag "div" in the element "dropdown"
 allHTMLTags=$("dropdown").getElementsByTagName("div");
 //Of the got tags change the class name to "dt" whose previous class name was as defined
 for(i=0;i<allHTMLTags.length;i  ){if(allHTMLTags[i].className==theClass){allHTMLTags[i].className="dt";}}
 }

function aj_call(the_str,thevalue){
 //Make the AJAX Call
//Send the data to the PHP page "aj_autocomplete-example.php"
//The returned data will be displayed in the div with id "dropdown"
//While the AJAX data is send/received keep the user informed with text "autocompleting.."
//4th parameter "thevalue" if set will use the function "allok" once data is received after AJAX call as defined before
callAHAH("aj_autocomplete-example.php?" the_str,"dropdown","autocompleting..",thevalue);
//Set the searching to true indicating AJAX call in progress
searching = true;
}
//This function gets activated at every keyup.
function ajax_autocomplete(thevalue,e){
//Do not show the dropdown if less than 3 digits also reset every variable and do nothing
 if(thevalue.length < 3){recarray =new Array();dontshow("dropdown");before ="";searching=false;nothing=true;no_time=0;return false;}
 
//detect which key was pressed
var action = e.which;
//detect which key was pressed for IE
if (action == undefined){action = e.keyCode;}

//If Backspace was pressed, check the value with the "listing" function
 if (action == 8){listing(thevalue);return false;}

//If delete was pressed, check the value with the "listing" function
 if (action == 46){listing(thevalue);return false;}
 
//If arrow down was pressed then highlight the option
 if(action == 40){highlight(1);return false;}

//If arrow up was pressed then highlight the option
 if(action == 38){highlight(-1);return false;}

//If enter was pressed
if(action == 13){
//if option was highlighted and pressed enter
if(chosen !==-1)
{
//if option was highlighted and pressed enter
if(chosen !==-1)
{
//Fill the text-box with the value
  $("autocomplete_value").value = $("showid_"+opt_no[chosen]).innerHTML;
  //Fill the text-box with the ID
  $("thetxtid").value = $("valid_"+opt_no[chosen]).innerHTML;
  //hide the autocomplete dropdown div
  dontshow("dropdown");
  //Also change the highlighted option to default with no highlight
  chosen = -1;
  //no need to go ahead
return false;
}
}

//If it is not a character key then do nothing
if (action < 32 || (action >= 33 && action <= 46) || (action >= 112 && action <= 123)){return false;}
//else make the ajax call
else {
//If the searching is not set it indicates no AJAX Call in progress
//If the previous value is not one less then the present value
//If nothing is found either after matching locally or after the AJAX call
if(!searching && (thevalue.indexOf(before) != 0 || nothing))
{
 //Change the "dropdown" class to "show" and unhide the same
$("dropdown").className="show";
//Get string detail to send by AJAX call
var t_str="p=6&m=" thevalue ;
//Make the AJAX call by the function "aj_call"
aj_call(t_str,thevalue);
}
else {
//else use the listing function with the text in the textbox  
 listing(thevalue);
  }
//Set "before" to the typed text value in the textbox
before=thevalue;
//If any previous selection done from the options then reset that
if($("thetxtid").value!==""){$("thetxtid").value="";}
}
}

//"matcheddata" will return all the AJAX returned data which matches the typed text in the textbox
function matcheddata(thestr){
//Using regular expression we assign the pattern to find e.g. "thestr". i will ignore the caps
regExp = new RegExp(thestr,"i");
var final=new Array();
//"recarray" is the received array found in the "allok" function after completion of AJAX call
//for each array data we need to split the value and the Id
  for(i=0;i<recarray.length;i  )
  {
    //Split again at "---" to separate ID and value - "recdata[0]" stores the ID and "recdata[1]" stores the value string
    recdata=recarray[i].split("---");
    //If "thestr" matches in the received AJAX returned value string
    if(recdata[1].match(regExp)){
    //return index of the first match between the regular expression and value string
   var begin = recdata[1].search(regExp);
    //return a substring of the value string that starts at "begin" and ends at the specified length
    var matched = recdata[1].substring(begin,begin+thestr.length);
   //return the new string that results after all matches of regex within and enclose with <b> and <u>
  milgaya= recdata[1].replace(regExp,"<u><b>"+matched+"</b></u>");
   //format the string with additional div containing value and Id and store it in an array "final"
   final[i]='<span id="showid_' i '" class="hide">' recdata[1] '</span><span id="valid_' i '" class="hide">' recdata[0] '</span><div class="dt" id="opt_' i '" onclick=setvalue("' i '"); onmouseover="rhigh();">' milgaya;
}
  }
  //return the "final" array
  return final;
}
//"listing" function checks locally if the input text matches strings from "recarray" array of AJAX call
function listing(theText){
   //reset "chosen" to default value
   chosen = -1;
   //find number of matches found with the input text and the AJAX data returned
   foundmatch = matcheddata(theText);   
  if(foundmatch.length > 0)
  {
   //if there are matches found, join them with the closing div and make it as a string
   var stringshow=foundmatch.join("</div>");
   //show the string thus made in the "dropdown" div
   $("dropdown").innerHTML=stringshow;
   //Since we have found something locally, "nothing" to be set "false"
   nothing = false;
   }
  else{
   //no matches found so "nothing" to be set "true"
   nothing=true;
   //However if more than 3 AJAX calls made then "nothing" to be set "false" to prevent more AJAX Calls
   if (no_time > 3){nothing=false;}
   //activate the "shownothing" function
   shownothing(theText);}
}

//"highlight" function highlights the options when selected by the arrow keys
function highlight(x){
//Get all the elements with tag "div" in the element "dropdown"
allHTMLTags=$("dropdown").getElementsByTagName("div");
 //Of the got tags get the id number of the options and store them in "opt_no" array at highlighted position
 for(i=0;i  //Get the position of the highlighted option
now=parseInt(chosen) parseInt(x);
//Get the total number of options returned after matching the text with the AJAX returned array "recarray"
var num=allHTMLTags.length;num--;
//While pressing arrow up key if the position reaches to end then default to 1st selection
if(now<=0){now=0;}
//While pressing arrow down key if the position reaches to end then default to last selection
if(now>num){now=num;}
//Also change the "chosen" value
chosen=now;
//remove any previous highlight of the option
removehighlight("marker");
//Highlight the option at the chosen position
$("opt_"+opt_no[now]).className="marker";
}

//This function activates when cursor is over any dropdown option
function rhigh(){
 //When cursor is hovered over any option remove any previous highlighted option by arrow keys
 removehighlight("marker");
 //Also change the highlighted option to default with no highlight
 chosen = -1;
 }

//Hide any element by changing the class "hide". The CSS class "hide" has display:none and will not be shown
function dontshow(theid){$(theid).className="hide";}

//Select the highlighted text
function setvalue(num){
 //Fill the text-box with the value
 $("autocomplete_value").value = $("showid_" num).innerHTML;
 //Fill the text-box with the ID
 $("thetxtid").value = $("valid_" num).innerHTML;
 //hide the autocomplete dropdown div
 dontshow("dropdown");
 //Also change the highlighted option to default with no highlight
 chosen = -1;}
</script>

Rishi Kashyap | | EDIT | REPLY
Rishi Kashyap
8.66 K
X AJAX Autocomplete Final Words
0

Is it the best AJAX autocomplete ?
Of course not ! There is large scope of improvement. It could be modified for more than one text box. OOPS and event binding too can be done of which I am ignorant now. I have tested it in latest version of Internet Explorer, Chrome and Firefox browser. Browser compatibility needs to be improved.

AJAX Calls too can be made using any framework. I avoid such framework simply because of the file size, same reason why I do not use Jquery for autocomplete. You are in more control when you know what and where to change as per your requirement.

One word of caution is that my AJAX script had a line which forms the base of this scriptfunction $(id){return document.getElementById(id)}This function simply returns the element with the specified Id. This is used in almost all framework and is the soul of DHTML. So if you are getting JS error "ReferenceError: $ is not defined" then it means you need to add the said code to your javascript files.

Your reply and suggestions are welcome.

Rishi Kashyap | | EDIT | REPLY

tags  JAVASCRIPT JAVASCRIPT AJAX PHP TUTORIAL

SUBSCRIBE TO RISHI'S BLOGS