Solved

javascript quick search of select dropdown is really slow

Posted on 2007-11-14
4
1,001 Views
Last Modified: 2013-12-13
I am currently using this code to show a dropdown box of all the clients in my database. Currently around 2500.  This box loads instantly on its own.]


            <select name="client_id">
              <?

$check_name = $user_fullname;            


            $query = 'SELECT c1.client_name AS c1_client_name, c2.client_name AS c2_client_name, c1.client_surname AS c1_client_surname, c2.client_surname AS c2_client_surname, c1.client_id AS client_id, c1.client_rel_id AS c1_client_rel_id'
. ' FROM client c1'
. ' LEFT JOIN client c2 ON c1.client_rel_id = c2.client_id'
. ' WHERE (c1.client_archive = "0" AND c1.client_rel_id = "") OR (c1.client_archive = 0 AND c1.client_sex = "Male" AND c2.client_sex = "Female") OR (c1.client_archive = "0" AND c1.client_sex = c2.client_sex AND c1.client_id < c2.client_id)'
. ' ORDER BY c1.client_surname, c1.client_name';



$results = mysql_query($query);

while ($row = mysql_fetch_assoc($results)) {

if ($row['c1_client_rel_id'] == '') {
    echo '<option value="' . $row['client_id'] . '">';
    echo $row['c1_client_surname'] . ', ' . $row['c1_client_name'];
    echo "</option>\n";
      } else {
      echo '<option value="' . $row['client_id'] . '">';
    echo $row['c1_client_surname'] . ', ' . $row['c1_client_name'];
    echo ' and ';
    echo $row['c2_client_surname'] . ', ' . $row['c2_client_name'];
    echo "</option>\n";
      }
}
?><option value=" " selected="selected"> </option>
  </select>





However, i want to add a quick search box so as you type in letters the dropdown box becomes smaller and smaller with relevant entries.  I have used javascript successfully to do this however it is VERY SLOW. depending on the speed of the pc using the page it can take anywhere between 8-15 seconds to load this page. Baring in mind without the javascript it loads instantly with all 2500 entries in the dropdown.

Please can anyone suggest how i can speed up the javascript or an alternative which is much quicker? Possibly ajax?

Here is the javascript i include in this page:

      include "key_clients.html";


--------------------
key_clients.html
--------------------


<head>
<SCRIPT LANGUAGE="JavaScript">
<!-- Original:  Anand Raman (anand_raman@poboxes.com) -->
<!-- Web Site:  http://www.angelfire.com/ar/diduknow -->

<!-- This script and many more are available free online at -->
<!-- The JavaScript Source!! http://javascript.internet.com -->

<!-- Begin
function SelObj(formname,selname,textname,str) {
this.formname = formname;
this.selname = selname;
this.textname = textname;
this.select_str = str || '';
this.selectArr = new Array();
this.initialize = initialize;
this.bldInitial = bldInitial;
this.bldUpdate = bldUpdate;
}

function initialize() {
if (this.select_str =='') {
for(var i=0;i<document.forms[this.formname][this.selname].options.length;i++) {
this.selectArr[i] = document.forms[this.formname][this.selname].options[i];
this.select_str += document.forms[this.formname][this.selname].options[i].value+":"+
document.forms[this.formname][this.selname].options[i].text+"|";
   }
}
else {
var tempArr = this.select_str.split('|');
for(var i=0;i<tempArr.length;i++) {
var prop = tempArr[i].split(':');
this.selectArr[i] = new Option(prop[1],prop[0]);
   }
}
return;
}
function bldInitial() {
this.initialize();
for(var i=0;i<this.selectArr.length;i++)
document.forms[this.formname][this.selname].options[i] = this.selectArr[i];
document.forms[this.formname][this.selname].options.length = this.selectArr.length;
return;
}

function bldUpdate() {
var str = document.forms[this.formname][this.textname].value.replace('^\\s*','');
if(str == '') {this.bldInitial();return;}
this.initialize();
var j = 0;
pattern1 = new RegExp("^"+str,"i");
for(var i=0;i<this.selectArr.length;i++)
if(pattern1.test(this.selectArr[i].text))
document.forms[this.formname][this.selname].options[j++] = this.selectArr[i];
document.forms[this.formname][this.selname].options.length = j;
if(j==1){
document.forms[this.formname][this.selname].options[0].selected = true;
//document.forms[this.formname][this.textname].value = document.forms[this.formname][this.selname].options[0].text;
   }
}
function setUp() {
obj1 = new SelObj('form2','client_id','client_id_entry');
// menuform is the name of the form you use
// itemlist is the name of the select pulldown menu you use
// entry is the name of text box you use for typing in
obj1.bldInitial();
}
//  End -->
</script>
</head>









And i also add a small text box infront of the dropdown box which i pasted at the top:

  <input type="text" name="client_id_entry" size="20" onKeyUp="javascript:obj1.bldUpdate();">



Any help would be greatly appreciated as this page takes waaaay too long to load.
AR
0
Comment
Question by:drews1f
4 Comments
 
LVL 18

Accepted Solution

by:
Morcalavin earned 250 total points
ID: 20281376
I don't have php on my system, so I'll have to demonstrate using an xml document instead.  Basically, names.xml would be replaced by a php script that returns xml data, based on the url you provide it.  So the url could be "mydatabaselookup.php?name=" + text.value

Run the test scripts below to get an idea of what I'm talking about.


index.html
--------------
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
      <title>Test</title>
      <script type="text/javascript" src="ajax.js"></script>
     <script type="text/javascript">
     /*<![CDATA[*/
             function getData(text)
            {
                  var ajax = new Ajax(
                        'names.xml',
                        {
                              method: 'GET',
                              onSuccess: fillData,
                              onFailure: function(){alert('An error occurred')}
                        })
            }
            
            function fillData(xml)
            {
                  document.getElementById('select').options.length = 0;
                  var allNames = xml.responseXML.getElementsByTagName('name');
                  for(var i = 0; i < allNames.length; i++)
                  {
                        var option = new Option(allNames[i].getAttribute('value'), allNames[i].getAttribute('value'));
                        document.getElementById('select').options[i] = option;
                  }
            }
     /*]]>*/
     </script>
</head>
<body>
<div>
<input type="text" id="text" onkeyup="getData(this)"/><br/>
<select id="select">
<option value="Bob">Bob</option>
<option value="Dave">Dave</option>
<option value="Steve">Steve</option>
<option value="Tim">Tim</option>
<option value="Bill">Bill</option>
<option value="Charlie">Charlie</option>
</select>
</div>
</body>
</html>


ajax.js
-------------
/*extern ActiveXObject, XMLHttpRequest, window */

function Ajax(url, options)
{
      var xmlhttp = false;
      var reqObj =
      [
            function() {return new XMLHttpRequest();},
            function() {return new ActiveXObject("Msxml2.XMLHTTP");},
            function() {return new ActiveXObject("Microsoft.XMLHTTP");},
            function() {return window.createRequest();}
      ];
      for(var i = 0; i < reqObj.length; i++)
      {
            try
            {
                  xmlhttp = reqObj[i]();
                  break;
            }
            catch(err)
            {
                  xmlhttp = false;
            }
      }
      reqObj = null;
      
      try
      {
            var parameters = null;
            xmlhttp.open(options.method, url, true);
            if(options.method == 'POST')
            {
                  parameters = '';
                  for(i=0; i < options.form.length; i++)
                  {
                        parameters = parameters + options.form[i].name + "=" + encodeURI(options.form[i].value) + "&";
                        xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
                        xmlhttp.setRequestHeader("Content-length", parameters.length);
                        xmlhttp.setRequestHeader("Connection", "close");      
                  }
            }
            xmlhttp.onreadystatechange = function()
            {
                  if(xmlhttp.readyState == 4)
                  {
                        if(xmlhttp.status == 200)
                        {
                              options.onSuccess(xmlhttp);
                        }
                        else
                        {
                              if(options.onFailure)
                              {
                                    options.onFailure(xmlhttp);
                              }
                        }
                  }
            };
            xmlhttp.send(parameters);      
      }
      catch(error)
      {
            if(options.onError)
            {
                  options.onError(error);
            }
      }
}


names.xml
---------------
<?xml version="1.0"?>
<names>
<name value="Tom" />
<name value="Wilson" />
</names>
0
 
LVL 2

Assisted Solution

by:DavidBlackledge
DavidBlackledge earned 250 total points
ID: 20306646
Regarding your original Javascript solution's problem, the problem is with your initialize() function.

That gets called with every onkeyup event... the first time it iterates through the entire list to build a bar and semicolon delimited list of the values (this could have been done by building the same string in your PHP code that is building the Option tags and just outputting that already-built string instead of making JavaScript do it).
But the real problem is: EVERY subsequent call then breaks that string down into an array of arrays, and populates selectArr with new Options based on the values in the array of arrays.
It doesn't just populate selectArr once, but it re-populates it with every keystroke.  That code should probably have been within the original "if" statement rather than in that if's "else" statement.

Finally, that step could have been elminated by the PHP as well... ignore the above string building by PHP... build the actual Javascript to create the array of options using the PHP.
Output lines like:
'this.selectArr[i] = new Option(" . $row['client_id'] . "," . $row['c1_client_surname'] . ', ' . $row['c1_client_name'] . ");'
(that's just pseudo-PHP.. I don't know PHP really)
Then throw out all references to "this.initialize()"
Then your page should load almost as instantly as it did before (it will just have generated 2500 more lines of javascript if the user looked at the source of the HTML page)).

That array is never modified, so it's just static and can be created by the PHP with no problem.  Anytime you can shift the calculations to the server side (mainly for static things like this array) the better it will run on the browser.

0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

Suggested Solutions

This article will give core knowledge of JavaScript and will head in to your first JavaScript program. I am Durvesh Naik and I am here to deal with this series of JavaScript. I will teach you JavaScript in part wise , as its quite boring to read big…
JavaScript can be used in a browser to change parts of a webpage dynamically. It begins with the following pattern: If condition W is true, do thing X to target Y after event Z. Below are some tips and tricks to help you get started with JavaScript …
The viewer will learn how to dynamically set the form action using jQuery.
The viewer will learn how to count occurrences of each item in an array.

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now