简体   繁体   中英

Showing/Hiding Divs with Javascript on click

I'm trying to show/hide tabs on click using just Javascript but I'm getting errors ("Uncaught TypeError: Cannot set property 'className' of undefined tabs.(anonymous function).onclick"). Can someone give me an idea of what the issue might be?

<style>
    a { text-decoration: none; }
    li { list-style: none; }
    li.selected { font-weight: bold; } 
    .panels div { display: none; }
    .panels .selected { display: block; }
</style>

<div id="tabs" class="tabs">
    <ul>
        <li class="selected"><a href="javascript:;">One</a></li>
        <li class=""><a href="javascript:;">Two</a></li>
        <li class=""><a href="javascript:;">Three</a></li>
    </ul>
</div>

<div id="panels" class="panels">
    <div class="selected">This is panel one.</div>
    <div class="">This is panel two.</div>
    <div class="">This is panel three.</div>
</div>

<script>
    var tabs = document.getElementById("tabs").getElementsByTagName("li");
    var panels = document.getElementById("panels").getElementsByTagName("div");
    for (var i = 0; i < tabs.length; i++) {
        new function(i) {
            tabs[i].onclick = function() {
                tabs[i].className = panels[i].className = "selected";
                for (var i = 0; i < panels.length; i++) {
                tabs[i].className = panels[i].className = "";
                }
            }
        }(i);
    }
</script>

Your inner for loop has an i variable that conflict with the outter variable for loop with the same name.

You should also remove selected class from all elements before setting the clicked element 'selected'.

Try:

<script>
    var tabs = document.getElementById("tabs").getElementsByTagName("li");
    var panels = document.getElementById("panels").getElementsByTagName("div");
    for (var i = 0; i < tabs.length; i++) {
        new function(i) {
            tabs[i].onclick = function() {
                for (var j = 0; j < panels.length; j++) {
                    tabs[j].className = panels[j].className = "";
                }
                tabs[i].className = panels[i].className = "selected";
            }
        }(i);
    }
</script>

Below here will work, as you are expecting. Two issues I found for accessing HTML Element inside for loop, you need to use .item() as its HTMLCollection you are getting instead of an array. Also your inner for loop needs to use different looping index, with one additional if condition to leave clicked one as shown and rest hidden.

<style>
    a { text-decoration: none; }
    li { list-style: none; }
    li.selected { font-weight: bold; } 
    .panels div { display: none; }
    .panels .selected { display: block; }
</style>

<div id="tabs" class="tabs">
    <ul>
        <li class="selected"><a href="javascript:;">One</a></li>
        <li class=""><a href="javascript:;">Two</a></li>
        <li class=""><a href="javascript:;">Three</a></li>
    </ul>
</div>

<div id="panels" class="panels">
    <div class="selected">This is panel one.</div>
    <div class="">This is panel two.</div>
    <div class="">This is panel three.</div>
</div>

<script>
    var tabs = document.getElementById("tabs").getElementsByTagName("li");
    var panels = document.getElementById("panels").getElementsByTagName("div");
    for (var i = 0; i < tabs.length; i++) {
        new function(i) {
            tabs[i].onclick = function() {
                tabs.item(i).className = panels.item(i).className = "selected";
                for (var j = 0; j < panels.length; j++) {
                    if(i!=j){
                        tabs.item(j).className = panels.item(j).className = "";
                    }
                }
            }
        }(i);
    }
</script>

You've got a couple of problems:

  • Multiple i variables
  • new function(i) {...} isn't the best syntax. I've used a closure below
  • multiple assignments per line isn't good

I've given your <li> elements values so that we can tell which li element has been clicked

  var tabs = document.getElementById("tabs").getElementsByTagName("li"); var panels = document.getElementById("panels").getElementsByTagName("div"); for (var i = 0; i < panels.length; i++) { (function(i) { tabs[i].onclick = function() { var j; var panelIndex; // remove styles from other tabs for (j = 0; j < tabs.length; j++) { tabs[j].className = ""; } // apply style to the current tab: 'this' this.className = "selected"; // hide other panels for (j = 0; j < panels.length; j++) { panels[j].className = ""; } // show the selected panel panelIndex = +this.value; // convert value to number panels[panelIndex-1].className="selected"; // arrays are 0-indexed, so subtract 1 } })(i); } 
 a { text-decoration: none; } li { list-style: none; } li.selected { font-weight: bold; } .panels div { display: none; } .panels .selected { display: block; } 
 <div id="tabs" class="tabs"> <ul> <li value="1" class="selected"><a href="javascript:;">One</a></li> <li value="2" class=""><a href="javascript:;">Two</a></li> <li value="3" class=""><a href="javascript:;">Three</a></li> </ul> </div> <div id="panels" class="panels"> <div class="selected">This is panel one.</div> <div class="">This is panel two.</div> <div class="">This is panel three.</div> </div> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM