AJAX Autocomplete Tutorial




4.16 K Views | Rishi Kashyap | 1 FOLLOW
    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 | 7 years ago | EDIT | REPLY


      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 | 7 years ago | EDIT | REPLY
        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 | 7 years ago | EDIT | REPLY
          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 | 7 years ago | EDIT | REPLY
            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 | 7 years ago | EDIT | REPLY
              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 | 7 years ago | EDIT | REPLY

                tags  JAVASCRIPT JAVASCRIPT AJAX PHP TUTORIAL