0

I am trying to pre-populate form selections by evaluating a string. I will import a dynamic string later, but wanted to focus on the search function. If the value has a match in the string then write "selected" in the input tag to select it for the viewer. What am I doing wrong?

<script type="text/javascript">
function match_search(search_option) {
var myRegExp = /search_option/;
var string1 = "specialty1,specialty2,specialty3,specialty4";
var match1 = string1.search(myRegExp);

if(match1 != -1)
	document.write("selected"); 
	// End Result in form <option id="specialty2" value="specialty2" selected>specialty2</option>
else
	document.write("");
}
</script>
</head>
<BODY> 

<!-- multi_search -->
<table><tr><td>
<select value name="specialty" size="5" multiple id="specialty">
<!-- <option id="specialty2" value="specialty2" selected>specialty2</option> -->
  <option id="specialty1" value="specialty1" onload="match_search(specialty1)">specialty1</option>
  <option id="specialty2" value="specialty2" onload="match_search(specialty2)">specialty2</option>
  <option id="specialty3" value="specialty3" onload="match_search(specialty3)">specialty3</option>
  <option id="specialty4" value="specialty4" onload="match_search(specialty4)">specialty4</option>
  <option id="specialty5" value="specialty5" onload="match_search(specialty5)">specialty5</option>
  <option id="specialty6" value="specialty6" onload="match_search(specialty6)">specialty6</option>
</select>
</td></tr></table>
3
Contributors
6
Replies
7
Views
6 Years
Discussion Span
Last Post by thatguy2
0

Change the definition of myRegExp to below:

var myRegExp = new RegExp(search_option);

The way you had it you were setting myRegExp to equal the string "search_option" rather than the value that you were passing to the function. I would also set a function onload for the select element rather than each option. Then you would look through each option for the one with the value that matched the string you are evaluating and set the selected option with properties rather than the document.writes, which I don't think would have the results you are looking for anyway (it wipes out the contents of an already loaded page http://javascript.about.com/library/blwrite.htm). Also you would need to fire this in an onload event handler for the body element as onload doesn't work for elements other than: body, frameset, and img.

<script type="text/javascript">
function match_search(search_option) {
  var myRegExp = new RegExp(search_option);
  var string1 = "specialty1,specialty2,specialty3,specialty4";
  var match1 = string1.search(myRegExp);
  var selectEl = document.getElementById("specialty");
 
if(match1 != -1)
	for(var i = 0; i < selectEl.options.length; i++)
        if(selectEl.options[i].value == search_option)
           selectEl.options[i].setAttribute("selected", "selected");
	// End Result in form <option id="specialty2" value="specialty2" selected>specialty2</option>
else
	//do nothing
}

function initSelect()
{
 var someString = "specialty1";
 match_search(someString);
}

window.onload = initSelect;
</script>
</head>
<BODY> 
 
<!-- multi_search -->
<table><tr><td>
<select value name="specialty" size="5" multiple id="specialty">
<!-- <option id="specialty2" value="specialty2" selected>specialty2</option> -->
  <option id="specialty1" value="specialty1" >specialty1</option>
  <option id="specialty2" value="specialty2" >specialty2</option>
  <option id="specialty3" value="specialty3" >specialty3</option>
  <option id="specialty4" value="specialty4" >specialty4</option>
  <option id="specialty5" value="specialty5" >specialty5</option>
  <option id="specialty6" value="specialty6" >specialty6</option>
</select>
</td></tr></table>
1

ThatGuy2,

First, /search_option/ makes a regex from the string "search_option" , not the variable search_option . The // form is only good for hard-coded strings. To dynamically create a regex, you have to use new RegEx() :

var myRegExp = new RegExp(search_option);

Next, options don't have events of their own. I know it's only for testing but you have to use the onchange event of the select node.

<select value name="specialty" size="5" multiple id="specialty" onchange="match_search(this[this.selectedIndex].value)">

And purge out all the onload attributes from the options.

I understand that you really want a function that will force the select menu to a particular option when its value corresponds to a string passed as an argument to the function. If so then try this:

function setSelectMenu(menuID, str) {//we also pass the id of the select menu in question.
	var menu = document.getElementById(menuID);//find the corresponding DOM node.
	if(menu) {//in the DOM node exists ...
		for(var i=0; i<menu.length; i++) {//... then loop through the options.
			if(menu[i].value === str) {//If option's value matches the given string str ...
				menu[i].selected = true;//... then select this option and ...
				break;//... jump out of loop.
			}
		}
	}
}

You can test this with :

onload = function() {//a function that fired after the page has loaded
	setSelectMenu('specialty', 'specialty4');
};

But you also want the constraint that you only set the menu if a certain condition is met - namely that the search string is contained within another string. In that case, its's better to keep the test separate, such that setSelectMenu only gets called if the condition is met:

onload = function() {
	var searchString = "specialty3";
	var constraintString = "specialty1,specialty2,specialty3,specialty4";
	if(constraintString.indexOf(searchString) > -1) { setSelectMenu('specialty', searchString); }
};

Now try changing var searchString = "specialty3"; to var searchString = "specialty5"; and you should see that the menu is not set - the constraint has been applied.

There may be better ways to phrase the constraint but I don't know the background to your project.

Anyways, that should get you started.

Airshow

Edited by Airshow: forgot a code tag

0

I ended up going with the following. It works but I am having one issue with the selections. Why are some selections finding matches that are similar and selecting them and some that are similar are not? How can I fix this?
For Example if I pass the following I get the >Select> result:
Anesthesiology >Selects> Anesthesiology
Anesthesiology_Pain_Management >Selects> Anesthesiology,Anesthesiology_Pain_Management,Pain_Management
Pain_Management >Selects> Pain_Management

JS Code:

function MultiSelect() {
	this.constructor.apply(this, arguments);
}

MultiSelect.prototype = {
	select: null,
	values: null,
	constructor: function(values) {
		this.values = String(values);
	},
	
	init: function(select) {
		this.select = select;
		this.autoSelect();
		select = null;
	},
	
	autoSelect: function() {
		for (var i = 0, length = this.select.options.length; i < length; i++) {
			this.select.options[i].selected = this.match(this.select.options[i].value);
		}
	},
	
	match: function(value) {
		return (this.values.indexOf(value) > -1);
	}
	
};

onload = function() {
  var specialty = new MultiSelect(["Anesthesiology_Pain_Management"]);
  specialty.init(document.getElementById("specialty"));
};
// alternate
// var specialty = new MultiSelect(["Anesthesiology", "Orthopaedic_Surgery"]);

Form code:

<select value name="specialty" size="6" multiple class="textbox_full" id="specialty">                    
  <option value="Anesthesiology" id="Anesthesiology">Anesthesiology</option>
  <option value="Anesthesiology_Pain_Management" id="Anesthesiology_Pain_Management">Anesthesiology Pain Management</option>
  <option value="Oral_Maxillofacial_Surgery" id="Oral_Maxillofacial_Surgery">Oral Maxillofacial Surgery</option>
  <option value="Orthopaedic_Surgery" id="Orthopaedic_Surgery">Orthopaedic Surgery</option>
  <option value="Orthopaedics_Adult_Reconstructive" id="Orthopaedics_Adult_Reconstructive">Orthopaedics/Adult Reconstructive</option>
  <option value="Pain_Management" id="Pain_Management">Pain Management</option> 
</select>
0

I can't immediately see why you get that behaviour and I'm not going to try to debug it because that's a lot of javascript and an over-complex pattern for something really simple.

Sticking with your general concept, it would make more sense to reverse the logic in onload to give the following:

onload = function() {
	var specialty = new MultiSelect(document.getElementById("specialty"));
	specialty.autoSelect(["Anesthesiology_Pain_Management"]);
//	alternate
//	specialty.autoSelect(["Anesthesiology", "Orthopaedic_Surgery"]);
};

And here's the code to make that call pattern work :

//First add php-like "inarray" method to Array :
Array.prototype.inarray = function(x) {
	for (var i=0; i<this.length; i++) { if(this[i] == x) { return true; } }
	return false;
};
//Now a simple MultiSelect constructor :
function MultiSelect(menu) {
	this.autoSelect = function(valuesArray) {
		for (var i = 0, length = menu.options.length; i < length; i++) {
			menu.options[i].selected = valuesArray.inarray(menu.options[i].value);
		}
	};
}

Airshow

1

I would try a form of regex matching rather than the index of. I think Anesthesiology and Anesthesiology_Pain_Management would both pass .indexOf if you search for Anesthesiology as well as Pain_Management and Anesthesiology_Pain_Management if you search for Pain_Management.

match: function(value) {
   var myRegExp = new RegExp(value);
		return myRegExp.test(this.values.toString());
}

Edited by scrappedcola: n/a

0

Thank very much Airshow and scrappedcola for you valued input on this! A combination of your code has worked successfully. I appreciate your help.
Final code used:

<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">

<script type="text/javascript">

MultiSelect.prototype = {
	select: null,
	values: null,
	constructor: function(values) {
		this.values = String(values);
	},
	
	init: function(select) {
		this.select = select;
		this.autoSelect();
		select = null;
	},
	
	autoSelect: function() {
		for (var i = 0, length = this.select.options.length; i < length; i++) {
			this.select.options[i].selected = this.match(this.select.options[i].value);
		}
	},
	
match: function(value) {
   var myRegExp = new RegExp(value);
		return myRegExp.test(this.values.toString());
}
	
};

//First add php-like "inarray" method to Array :
Array.prototype.inarray = function(x) {
	for (var i=0; i<this.length; i++) { if(this[i] == x) { return true; } }
	return false;
};
//Now a simple MultiSelect constructor :
function MultiSelect(menu) {
	this.autoSelect = function(valuesArray) {
		for (var i = 0, length = menu.options.length; i < length; i++) {
			menu.options[i].selected = valuesArray.inarray(menu.options[i].value);
		}
	};
}
onload = function() {
	var specialty = new MultiSelect(document.getElementById("specialty"));
	specialty.autoSelect(["Anesthesiology_Pain_Management"]);
//	alternate "Anesthesiology_Pain_Management"
//	specialty.autoSelect(["Anesthesiology", "Orthopaedic_Surgery"]);
};
</script>
</head>
<body bgcolor="#FFFFFF">
            <table cellspacing="0" cellpadding="5" width="558" border="0">
	          <tr>
	            <td align="left" valign="top">           
                 <form id="signup" name="signup" action="" method="post">Specialty:<br>
             
                
<select value name="specialty" size="6" multiple class="textbox_full" id="specialty">                    
  <option value="Anesthesiology" id="Anesthesiology">Anesthesiology</option>
  <option value="Anesthesiology_Pain_Management" id="Anesthesiology_Pain_Management">Anesthesiology Pain Management</option>
  <option value="Oral_Maxillofacial_Surgery" id="Oral_Maxillofacial_Surgery">Oral Maxillofacial Surgery</option>
  <option value="Orthopaedic_Surgery" id="Orthopaedic_Surgery">Orthopaedic Surgery</option>
  <option value="Orthopaedics_Adult_Reconstructive" id="Orthopaedics_Adult_Reconstructive">Orthopaedics/Adult Reconstructive</option>
  <option value="Pain_Management" id="Pain_Management">Pain Management</option> 
</select>

                  </form>
</td>

              </tr>
            </table>
</body>
</html>
This question has already been answered. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.