Solved

javascript quick search of select dropdown is really slow

Posted on 2007-11-14
4
1,011 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
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

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Since pre-biblical times, humans have sought ways to keep secrets, and share the secrets selectively.  This article explores the ways PHP can be used to hide and encrypt information.
This article discusses how to implement server side field validation and display customized error messages to the client.
The viewer will learn how to count occurrences of each item in an array.
The viewer will learn how to create a basic form using some HTML5 and PHP for later processing. Set up your basic HTML file. Open your form tag and set the method and action attributes.: (CODE) Set up your first few inputs one for the name and …

730 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