?
Solved

Javascript trim not working on select box options

Posted on 2006-06-11
9
Medium Priority
?
580 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
[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
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
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
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 1000 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

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

This article shows how to create and access 2-dimensional arrays in JavaScript.  It includes a tutorial in case you are just trying to "get your head wrapped around" the concept and we'll also look at some useful tips for more advanced programmers. …
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 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…
Suggested Courses

777 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