Solved

Javascript trim not working on select box options

Posted on 2006-06-11
9
553 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
 
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
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
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

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

In my daily work (mainly using ASP.net), I need to write a lot of JavaScript code. One of the most repetitive tasks I do are the jQuery Ajax calls. You know: (CODE) I don't know if for you it's the same, but for me is soooo tedious to write the …
This article discusses the difference between strict equality operator and equality operator in JavaScript. The Need: Because JavaScript performs an implicit type conversion when performing comparisons, we have to take this into account when wri…
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…

760 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

20 Experts available now in Live!

Get 1:1 Help Now