Solved

Javascript trim not working on select box options

Posted on 2006-06-11
9
563 Views
Last Modified: 2008-02-01
Hi all,

I'm having a bit of a problem trying to resolve this issue.

I have a select box into which options are fed in a tiered structure if one option is the child of another; they are indented by two spaces.

For example:
AAA Option 1
BBB Option 2
  CCC SubOption 1
  DDD SubOption 2
    EEE SubSubOption1

I want to enable type ahead searching that will remove the white space and allow a user to type a 'c' to get to the CCC... option instead of typing '<space><space>c'.

To trim whitespace, I found the following:

String.prototype.trim = function(){
      return this.replace(/^\s*|\s*$/g,'');
}
function trimmer(str){
      return str.replace(/^\s*|\s*$/g,'');
}

When I use the function on a string such as:
 var test =  '   test   ';
 alert("test1:" + test); //prints with spaces
alert("test2:" + test.trim()) //prints trimmed down

Things work fine when I act on a declared string.

The problem arises in the following example.  I am reading all the options from the select box into an array using the following:
allOpts[i] = element.options[i].text.toLowerCase();

When I use the function on a string such as:
 var test = allOpts[3];
 alert("test1:" + test); //prints with spaces
alert("test2:" + test.trim()) //prints with spaces

typeof(allOpts[3]) says that it is of type String, but it does not act the same as a variable stored in a string.

I've also tried:
allOpts[i] = element.options[i].text.toLowerCase().toString().trim();

This doesn't work either.

Any help would be greatly appreciated.

-Rob
0
Comment
Question by:robfurrball
9 Comments
 
LVL 49

Expert Comment

by:Roonaan
ID: 16883426
What if you do:
var test = "" + allOpts[3];
alert("test1:" + test); //prints with spaces
alert("test2:" + test.trim()) //prints with spaces

-r-
0
 
LVL 3

Expert Comment

by:a122178
ID: 16883470
I think the trim in Javascript should be:

trim(test);
0
 
LVL 22

Expert Comment

by:Ivo Stoykov
ID: 16883520
Hello robfurrball,

> allOpts[i] = element.options[i].text.toLowerCase();
here the value is not trimmed= you have to use your trim function here. ie,

allOpts[i] = element.options[i].text.trim().toLowerCase();
OR
allOpts[i] = trimmer(element.options[i].text.).toLowerCase();

both do the same and it doesn't matter which you'll prefer.

then these lines
 alert("test1:" + test); //prints with spaces
alert("test2:" + test.trim()) //prints trimmed down
should show the value timeed.

HTH

I
0
Are your AD admin tools letting you down?

Managing Active Directory can get complicated.  Often, the native tools for managing AD are just not up to the task.  The largest Active Directory installations in the world have relied on one tool to manage their day-to-day administration tasks: Hyena. Start your trial today.

 
LVL 1

Author Comment

by:robfurrball
ID: 16883840
I appreciate all your suggestions so far.

Unfortunately, the same issue still happens.  I was trying to make a test file to copy into the response and I think I made some headway.  The spaces I'm putting in the options are actually '&nbsp;' and that is not caught by the regular expression.  I'm not a regex expert by any means, does anyone know how to add the catch for this set of characters into the formula?

-Rob
0
 
LVL 63

Expert Comment

by:Zvonko
ID: 16883954
Check this:

  allOpts[i] = element.options[i].text.toLowerCase().replace(/&nbsp;/g,"");


0
 
LVL 1

Author Comment

by:robfurrball
ID: 16884524
I don't think that worked either.  Here is a test .html document I've tried this on.

<!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>
</head>
<body>

<script language="JavaScript1.2">
var keyTime, keyStr = '', allOpts, lastElement;
var agt = navigator.userAgent.toLowerCase();
//var is_ie = ((agt.indexOf("msie") != -1) && (agt.indexOf("opera") == -1));
var is_gecko = (agt.indexOf("gecko") != -1);
function populate(srcEvent)
{
  var element = (srcEvent)? ((srcEvent.target)? srcEvent.target : srcEvent.srcElement) : window.event.srcElement;
  if(lastElement != element)
  {
    allOpts = new Array();
    for(var i = 0; i < element.options.length; i++)
      allOpts[i] = element.options[i].text.toLowerCase().replace(/&nbsp;/g,"");
    lastElement = element;

 /////////////////////////////////////////////////////////
 var test = allOpts[3];
 var myArr = new Array();
 myArr[0] = 'test0';
 myArr[1] = '  test01  ';
 myArr[2] = 'test02';

 //test = myArr[1];
// test = '   test   ';
 alert("test1:" + test);
alert("test2:" + test.trim())

///////////////////////////////////////////////////////////

 }

}
function setSelection(srcEvent)
{
  var myEvent = (srcEvent)? srcEvent : window.event;
  var element = (myEvent.target)? myEvent.target : myEvent.srcElement;
  var keyCode = myEvent.keyCode;
  // messy JS keycodes force me to preprocess. Note: I use a US keyboard, other keyboards may vary?
  if((keyCode > 47 && keyCode < 58) || (keyCode > 64 && keyCode < 91 || keyCode == 32)) ; // space or alphanumerical characters, leave them alone
  else if(keyCode > 95 && keyCode < 106) keyCode -= 48; // keypad numbers
  else if(keyCode > 105 && keyCode < 112) keyCode -= 64; // keypad '+', '-', '/', '*', '.'
  else if(keyCode > 187 && keyCode < 192) keyCode -= 144; // '/', '.', ',', '-'
  else if(keyCode > 218 && keyCode < 222) keyCode -= 128; // '\', '[', ']'
  else
  {
    switch(keyCode)
    {
      case 187: keyCode = 61; break; // '='
      case 222: keyCode = 39; break; // '''
      case 192: keyCode = 96; break; // '`'
      case 186: keyCode = 59; break; // ';'
      default: return; // do not process non printable characters (unfortunately backspace cannot be supported because browsers like IE interpret backspace as go back a page in history)
    }
  }
  var currentKey = String.fromCharCode(keyCode).toLowerCase();
  var idx, currentSIdx = element.selectedIndex, useOld = false;
  var newTime = new Date().getTime();
  if(keyTime != null && newTime - keyTime < 500) // do type-ahead if two keys were pressed within 500 milliseconds (0.5 second, one can change this value for customization)
  {
    keyStr += currentKey;
    idx = findIdx();
    if(idx == -1) return; // not found, keep current selection then (leave the incorrect keyStr alone)
  }
  else // unfortunately we seem to have to handle default browser behavior too
  {
    keyStr = currentKey;
    // behavior should be: if next option is available and begins with the same character, select the next option
    // when there is either no more option, or no more option that begins with the same character as the current option,
    // then select the first option that starts with the currentKey
    idx = currentSIdx + 1;
    if(idx >= allOpts.length || allOpts[idx].length == 0 || allOpts[idx].charAt(0) != keyStr)
      idx = findIdx();
  }
  if(idx >= 0) // if keyStr is found in an option, select the option
  {
    element.options[currentSIdx].selected = false;
    // gecko-based browsers have a very strange bug that strikes when user presses
    // the same character multiple times (like 'AAA', 'BBBB'), which could be "fixed"
    // in a strange way too (actually the idx > 0 test is not even necessary!)
    // first make a pattern to check if it's same character multiple times
    var pattern = new RegExp('^' + keyStr.charAt(0) + '+$', "i");
    if(is_gecko && pattern.test(keyStr) && idx > 0) element.options[idx-1].selected = true;
    else element.options[idx].selected = true;
  }
  keyTime = newTime;
}
function findIdx()
{
  // full scan to find the smallest idx that match string keyStr (case-insensitive)
  var len = keyStr.length;
  for(var i = 0; i < allOpts.length; i++)
    if(allOpts[i].length >= len && allOpts[i].trim().substring(0, len) == keyStr)
      return i;
  return -1;
}
String.prototype.trim = function(){
      //return this.replace(/^\s+|\s+$/g|/&nbsp;/g,'');
      return this.replace(/&nbsp;/g,'');
}
function trimmer(str){
      return str.replace(/^\s*|\s*$/g,'');
}
</script>


<select name="tree" onFocus=populate(event) onKeyDown=setSelection(event) onKeyPress="javascript:return false">>
<option value="0">AAA</option>
<option value="1">BBB</option>
<option value="2">&nbsp;&nbsp;CCC</option>
<option value="3">&nbsp;&nbsp;DDD</option>
<option value="4">&nbsp;&nbsp;&nbsp;&nbsp;EEE</option>
</select>

</body>
</html>
0
 
LVL 63

Accepted Solution

by:
Zvonko earned 250 total points
ID: 16884686
Check this:
    for(var i = 0; i < element.options.length; i++)
      allOpts[i] = element.options[i].text.toLowerCase().replace(/\xa0/g,"");


0
 
LVL 1

Author Comment

by:robfurrball
ID: 16891658
That worked, thanks for all your help.  This turned out to be a stranger issue than I thought.
0
 
LVL 63

Expert Comment

by:Zvonko
ID: 16892482
For me too. I expected a blank character. But it is some sort of HTML blank character with the hex value "A0" or decimal 160.

0

Featured Post

PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

Question has a verified solution.

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

Suggested Solutions

When you need to keep track of a simple list of numbers or strings, the Array object is your most direct tool.  As we saw in my earlier EE Article (http://www.experts-exchange.com/A_3488.html), typical array handling might look like this: (CODE) B…
I've been trying to accomplish this for a while and it just struck me yesterday how to accomplish this task. I have done searches all over the internet looking for ways to email pages from my applications and finally I have done it!!! Every single s…
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

825 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