简体   繁体   中英

drop - down menu using JS onclick - what is wrong?

Just learing JS. I have created 3 dropdown menu with different choices and added JS function. HTML and CSS seems to be right. I am concerned about my JS, because it just does not work. Is the even right for that purpose? I am not sure if I use ".this" in the right place.

I would really appreciate any hints!

my JAVASCRIPT:

 document.addEventListener("DOMContentLoaded", function() { console.log("DOM fully loaded and parsed"); var arrow= document.querySelectorAll(".list_arrow"); var panel= document.querySelectorAll(".list_panel"); for (var i= 0; i < arrow.length; i++) { arrow[i].addEventListener('click', function showDiv(event) { if (panel.this.style.display == 'none') { //panel(this.style.display=='none')? panel.this.style.display = 'block'; } else { panel.this.style.display = 'none'; } }); } }); HERE IS MY CSS 
 .form { margin-top:50px; } .drop_down_list { border:1px solid #8de0d2; width: 280px; height:38px; background-color: white; margin-top:22px; padding: 8px 12px; position: relative; } .list_label { font-size: 30px; color: #e2e2e2; font-family: 'ralewaylight', Arial, Tahoma, sans-serif; } .list_arrow { width: 0; height: 0; border-left: 15px solid transparent; border-right: 15px solid transparent; border-top: 15px solid #24baa0; display:block; position: absolute; right: 14px; top: 20px; cursor: pointer; } .list_panel { background-color: white; border: 1px solid #ccc; width: 288px; padding-left: 15px; padding-bottom: 10px; list-style: none; margin: 0; left: 0px; z-index: 2; position: absolute; top: 54px; display:none; } .list_panel li { margin-top:10px; cursor: pointer; color: #585858; } 
  <div class="form"> <div class="drop_down_list"> <span class="list_label">Choose a chair</span> <span class="list_arrow"></span> <ul class="list_panel"> <li>Clair</li> <li>Margarita</li> <li>Selena</li> </ul> </div> </div> <div class="drop_down_list"> <span class="list_label">Choose color</span> <span class="list_arrow"></span> <ul class="list_panel"> <li>red</li> <li>black</li> <li>orange</li> </ul> </div> <div class="drop_down_list"> <span class="list_label">Choose material</span> <span class="list_arrow"></span> <ul class="list_panel"> <li>a</li> <li>b</li> </ul> </div> </div> 

The this keyword refers to the current scope . It is of no use in the state you are using it. What I suggest is to locate the list_panel that is associated with the clicked arrow. There are numerous ways to do that, but you can use the following:

Note that I also added default display-none classes so that they get shown on the first click (this wasn't the case).

 document.addEventListener("DOMContentLoaded", function() { console.log("DOM fully loaded and parsed"); var arrow= document.querySelectorAll(".list_arrow"); for (var i= 0; i < arrow.length; i++) { arrow[i].addEventListener('click', function showDiv(event) { // Find the panel associated with the clicked arrow. var parent = event.target.parentNode, currentPanel = parent.children[2]; if (currentPanel.style.display == 'none') { currentPanel.style.display = 'block'; } else { currentPanel.style.display = 'none'; } }); } });</script> 
 .form { margin-top:50px; } .drop_down_list { border:1px solid #8de0d2; width: 280px; height:38px; background-color: white; margin-top:22px; padding: 8px 12px; position: relative; } .list_label { font-size: 30px; color: #e2e2e2; font-family: 'ralewaylight', Arial, Tahoma, sans-serif; } .list_arrow { width: 0; height: 0; border-left: 15px solid transparent; border-right: 15px solid transparent; border-top: 15px solid #24baa0; display:block; position: absolute; right: 14px; top: 20px; cursor: pointer; } .list_panel { background-color: white; border: 1px solid #ccc; width: 288px; padding-left: 15px; padding-bottom: 10px; list-style: none; margin: 0; left: 0px; z-index: 2; position: absolute; top: 54px; display:none; } .list_panel li { margin-top:10px; cursor: pointer; color: #585858; } 
  <div class="form"> <div class="drop_down_list"> <span class="list_label">Choose a chair</span> <span class="list_arrow"></span> <ul class="list_panel" style='display: none'> <li>Clair</li> <li>Margarita</li> <li>Selena</li> </ul> </div> </div> <div class="drop_down_list"> <span class="list_label">Choose color</span> <span class="list_arrow"></span> <ul class="list_panel" style='display: none'> <li>red</li> <li>black</li> <li>orange</li> </ul> </div> <div class="drop_down_list"> <span class="list_label">Choose material</span> <span class="list_arrow"></span> <ul class="list_panel" style='display: none'> <li>a</li> <li>b</li> </ul> </div> </div> 

You may want to try using jQuery to help you with show() and hide() functions, though it is said that you might not need it :P

I don't understand the declaration of panel .. Thus I cannot go along panel.this . My solution is attached here: http://codepen.io/anon/pen/akXqwA

The main problem is that, during the for-loop, the i will end at the value 3 . When the event is triggered, i will always be 3 , and I cannot access the panel with panel[i] .

So I made a "hack" around it, by getting its nextElementSibling and changing its style.display . Also, I have initialised the value with the HTML ( style="display: none;" ). If you removed that part, the first click on the arrow will not show the items as the style.display value is not "none". There is a way to avoid changing that in HTML: try playing with the line ;)

Check this:

document.addEventListener("DOMContentLoaded", function() {
      console.log("DOM fully loaded and parsed");

      var arrow = document.querySelectorAll(".list_arrow");
      var panel = document.querySelectorAll(".list_panel");

      for (var i = 0; i < arrow.length; i++) {

        arrow[i].addEventListener('click', function showDiv(event) {
          var ulelm = this.parentNode.querySelector("ul");

          if (ulelm.style.display == 'none') { 
            ulelm.style.display = 'block';
          } else {
            ulelm.style.display = 'none';
          }
        });

      }

    });

working example is here .

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