Reputation: 16079
Here is what I have done:
<html><head><script type="text/javascript">
function loaded(){
var selectElems=document.getElementsByName("select");
for(i=0;i<selectElems.length;i++){
var elem=selectElems[i];
elem.onchange=function(){
alert(elem.selectedIndex);
}
}
} </script></head>
<body onload="loaded()">
<select name="select">
<option>0</option>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option> </select>
<select name="select">
<option>0</option>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option></select>
<select name="select">
<option>0</option>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option></select>
</body></html>
I need to get selected index of element with JavaScript. But I had a problem with that. Here is my code: http://jsfiddle.net/aRMpt/139/
Upvotes: 0
Views: 109
Reputation: 92274
The problem is that your elem
always points to the last select
element. The simplest solution is to use this
in the handler instead of the elem variable http://jsfiddle.net/mendesjuan/aRMpt/140/
function loaded(){
var selectElems=document.getElementsByName("select");
for(i=0;i<selectElems.length;i++){
var elem=selectElems[i];
elem.onchange=function(){
// This points to the select element that was changed
alert(this.selectedIndex);
}
}
}
This doesn't really tell you what your problem is though. It's a workaround (though a good one). The reason your code doesn't work is because your closure function onchange
uses the same elem
from the closure. By the time your onchange
is called, elem
points to the last select
element. A way to avoid this is to introduce another closure that freezes the elem for your onchange handler http://jsfiddle.net/mendesjuan/aRMpt/142/
function loaded(){
var selectElems=document.getElementsByName("select");
for(i=0;i<selectElems.length;i++){
var elem=selectElems[i];
// Freeze the elem variable by creating a function that passes
// the elem and creates a separate closure for each handler
elem.onchange= (function(el) {
// This is the function that will actually be the handler
return function(){
// This points to the select element that was changed
alert(el.selectedIndex);
}
}) (elem)
}
Here's another example that may help you understand how the above example works.
// This is a function that returns another function
// Its only reason is so that we don't use the shared closure
// variables from the outer scope, it freezes the el
// variable at the moment its called and so that it's available
// when the handler is called
function createOnChangeHandler(el) {
return function() {
alert(el.selectedIndex);
}
}
function loaded(){
var selectElems=document.getElementsByName("select");
for(i=0;i<selectElems.length;i++){
var elem=selectElems[i];
// If we just use elem here, its value will be what it was assigned last
// in the loop. That is because the handler won't be called until
// this loop has finished. However, by calling another function,
// a new scope is created with the value that we're passing into it
elem.onchange = createOnChangeHandler(elem);
}
This freezing of variables could also be accomplished by using Function.bind, but this only works in newer browsers; however, the above link shows you how to make it work for browsers that don't support it. http://jsfiddle.net/mendesjuan/aRMpt/143/
function loaded(){
var selectElems=document.getElementsByName("select");
for(i=0;i<selectElems.length;i++){
var elem = selectElems[i];
elem.onchange = (function (el) {
alert("Select index: " + el.selectedIndex)
}).bind(null, el);
}
Upvotes: 3