2

I've been playing with javascript to create a drop down list that shows a div depending on which option is selected.

All the code can be seen here:

http://jsfiddle.net/nmdTy/

var select = document.getElementById('test'),
onChange = function(event) {
    var shown = this.options[this.selectedIndex].value == 1;
    document.getElementById('hidden_div').style.display = shown ? 'block' : 'none';
};

I want to know how do I streamline this code and remove repetition - maybe some kind of loop?

Tomáš Zato
  • 50,171
  • 52
  • 268
  • 778
twigg
  • 3,753
  • 13
  • 54
  • 96

4 Answers4

1

You don't need two event handlers, you can use variables (shown below) to determine which div needs to be displayed or hidden.

var select = document.getElementById('test'), onChange = function(event) {
    var div1 = 'hidden_div';
    var div2 = 'hidden_div2';

    var index1 = this.options[this.selectedIndex].value == 1;
    var index2 = this.options[this.selectedIndex].value == 2;

    if(index1 || index2){
        document.getElementById(div1).style.display = index1 ? 'block' : 'none';
        document.getElementById(div2).style.display = index2 ? 'block' : 'none';
    }
    else{
        document.getElementById(div1).style.display = 'none';
        document.getElementById(div2).style.display = 'none';
    }
};

// attach event handler
if (window.addEventListener) {
    select.addEventListener('change', onChange, false);
} else {
    // of course, IE < 9 needs special treatment
    select.attachEvent('onchange', function() {
        onChange.apply(select, arguments);
    });
}

Working Fiddle

What have you tried
  • 11,018
  • 4
  • 31
  • 45
1

Another code :

var select = document.getElementById('test'),
    nbItems = 2,
    onChange = function (event) {
        var val = this.options[this.selectedIndex].value;

        for (var i = 1; i <= nbItems; i++) {
            document.getElementById('hidden_div' + i).style.display = val == i ? 'block' : 'none';
        }
    };

http://jsfiddle.net/nmdTy/11/

Samuel Caillerie
  • 8,259
  • 1
  • 27
  • 33
  • This is what I would do while solving real-life problem. – Tomáš Zato Apr 17 '13 at 14:34
  • this is very simple yet very elegant at the same time, I really like it and its just the kind of thing I was after. But where would this leave me say if the divs 'hidden_div1/2' had a different names say something like 'some_div' and 'this_other_div'? – twigg Apr 17 '13 at 14:52
  • @twigg you can use an array (like Tomáš Zato has done in his solution) in order to match the divs... See this fiddle : http://jsfiddle.net/nmdTy/17/. – Samuel Caillerie Apr 17 '13 at 15:35
0

I'm not really sure what do you mean by "repetition" but my guess is, that you don't want to type every each of the divs to be hidden/shown.
There could be multiple approaches to such task. The most universal is to have the div id's in a separate array. Then you can hide all but the selected div.

var divs = ["hidden_div1", "special_hidden", "one_more_hidden"];  
var select = document.getElementById('test');
var onchange = function(event) {   //Use var!
    var shown = this.options[this.selectedIndex].value;
    for(var i=0; i<window.divs.length; i++) {   //It would be more effective to save last shown div in a variable, but I've chosen this aproach with loop
        var div = document.getElementById(window.divs[i]);
        if(div!=null) {
          if(i==shown)  
            div.style.display="block";
          else
            div.style.display="none";
        }
    }
};
select.addEventListener("change", onchange);  //Could type the function right here, without using "onchange" variable

In my code, <option> value represents index in the array. Here is jsFiddle.

Tomáš Zato
  • 50,171
  • 52
  • 268
  • 778
0

Delegating a change event in IE<9 is a pain. It is possible, check this question to see how it's done, but it's not what you call elegant.

But your code doesn't delegate the event, so just attaching the handler directly at the onload event should do the trick (and it's X-browser compatible):

document.getElementById('test').onchange = function(e)
{
    e = e || window.event;//the only IE headache
    var shown = this.options[this.selectedIndex].value == 1;
    document.getElementById('hidden_div').style.display = shown ? 'block' : 'none';
    //^^ could keep a reference to this in a closure
};

The full code (with onload and closure reference to hidden div and preventing memory leaks in ie) should look like this:

var winLoad = function(e)
{
    var hiddenDiv = document.getElementById('hidden_div');
    document.getElementById('test').onchange = function(e)
    {
        var shown = !!(this.option[this.selectedIndex].value == 1);//to be safe, coerce to bool
        hiddenDiv.style.display = shown ? 'block' : 'none';
    };
    if (window.addEventListener)
    {
        return window.removeEventListener('load',winLoad,false);
    }
    return window.detachEvent('onload',winLoad);
};
if (window.addEventListener)
{
    window.addEventListener('load',winLoad,false);
}
else
{
    window.attachEvent('onload',winLoad);
}

that should work fine on all major browsers, even IE7 (probably IE6, too)

Community
  • 1
  • 1
Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149