1

Basically, My subtopics element is hiding, i want subtopics element show once we clicked at Topics element and hide subtopics element again once we clicked at Topics. Just like hide and show elements

I'm trying to use classList with addEventListener when i run code it shows up there is an error which didn't works for me.

I also found out that most of people are using jquery because it's very easy, but for me i want to practice in javascript first.

I'm still looking forward to the situation that works for me. If anyone know how to code with this function please give me some solution thank you very much.

Here is my code please take a look.

var togglemenu = (function () {
    var togSubtopics = document.getElementById("subtopics");

    togSubtopics.addEventListener("click", function () {
        togSubtopics.classList.toggle("show");
    });

    return {
        togglemenu: togglemenu()
    };
})();
body {
    margin: 0;
}

li, a{
    text-decoration: none;
    list-style-type: none;
    text-decoration-line: none;
    color: black;
}

/*main-menu*/
#mainmenu {
    position: relative;
}

#mainmenu ul {
    margin: 0;
    padding: 0;
}

#mainmenu li {
    display: inline-block;
}

#mainmenu a {
    display: block;
    width: 100px;
    padding: 10px;
    border: 1px solid;
    text-align: center;
}

/*subtopics*/
#subtopics {
    position: absolute;
    display: none;
    margin-top: 10px;
    width: 100%;
    left: 0;
}

.show {
    display: block;
}

#subtopics ul {
    margin: 0;
    padding: 0;
}

#subtopics li {
    display: block;
}

#subTopics a {
    text-align: left;
}

/*columns*/
#column1, #column2, #column3 {
    position: relative;
    float: left;
    left: 125px;
    margin: 0px 5px 0px 0px;
}

/*hover underline*/
#mainmenu li:hover {
    text-decoration: underline;
}
<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title></title>
    <link rel="stylesheet" type="text/css" href="index2.css" />
</head>
<body>
    <div id="mainmenu">
        <ul>
            <li><a href="">Logo</a></li>
            <li><a href="">Home</a></li>
            <li><a href="">Topics</a>
                <div id="subtopics">
                    <div id="column1" class="columns">
                        <ul>
                            <li><a href="">example1</a></li>
                            <li><a href="">example2</a></li>
                            <li><a href="">example3</a></li>
                        </ul>
                    </div>
                </div>
            </li>
        </ul>
    </div>

    <script src="index2.js"></script>
</body>
</html>

1 Answers1

2

One possible way to do that: just onclick - toggle that element's class (add or remove class show)

And in CSS add rules that give display: block to .submenu that is under .show

UPD Before show subitems of any item - make sure that you have hidden other opened submenus

(function () {
  var menuElems = document.querySelectorAll("#mainmenu ul > li")

  menuElems.forEach(function(elem){
    elem.addEventListener("click", function(){
      
      //hide all open submenus
      menuElems.forEach(function(e){
        e.classList.remove("show");
      })
      
      //show the one that is clicked right now 
      elem.classList.add("show");
    }, false)
  });
})();
body {
    margin: 0;
}

li, a{
    text-decoration: none;
    list-style-type: none;
    text-decoration-line: none;
    color: black;
}

/*main-menu*/
#mainmenu {
    position: relative;
}

#mainmenu ul {
    margin: 0;
    padding: 0;
}

#mainmenu li {
    display: inline-block;
}

#mainmenu a {
    display: block;
    width: 100px;
    padding: 10px;
    border: 1px solid;
    text-align: center;
}

/*subtopics*/
.subtopics {
    position: absolute;
    display: none;
    margin-top: 10px;
    width: 100%;
    left: 0;
}

.show .subtopics{
    display: block;
}

.subtopics ul {
    margin: 0;
    padding: 0;
}

.subtopics li {
    display: block;
}

.subTopics a {
    text-align: left;
}

/*columns*/
#column1, #column2, #column3 {
    position: relative;
    float: left;
    left: 125px;
    margin: 0px 5px 0px 0px;
}

/*hover underline*/
#mainmenu li:hover {
    text-decoration: underline;
}
<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title></title>
    <link rel="stylesheet" type="text/css" href="index2.css" />
</head>
<body>
    <div id="mainmenu">
        <ul>
            <li><a href="#">Logo</a></li>
            <li><a href="#">Home</a>
              <div class="subtopics">
                <div id="column1" class="columns">
                  <ul>
                    <li><a href="">Home_example1</a></li>
                    <li><a href="">Home_example2</a></li>
                    <li><a href="">Home_example3</a></li>
                  </ul>
                </div>
              </div>
            </li>
            <li><a href="#">Topics</a>
              <div class="subtopics">
                <div id="column1" class="columns">
                  <ul>
                    <li><a href="">Topic_example1</a></li>
                    <li><a href="">Topic_example2</a></li>
                    <li><a href="">Topic_example3</a></li>
                  </ul>
                </div>
              </div>
            </li>
        </ul>
    </div>

    <script src="index2.js"></script>
</body>
</html>

UPD Code that removes show class from menuElems onclick to subtopic

      var subtopicElems = document.querySelectorAll(".subtopics ul > li a")
      subtopicElems.forEach(function(item){
        item.addEventListener("click", function(event){
          menuElems.forEach(function(menuElem){
            menuElem.classList.remove("show")
          })
          event.stopPropagation(); //gotta stop bubbling
        }, false)
      })
about Bubbling and Capturing
Rudolf Manusachi
  • 2,311
  • 2
  • 19
  • 25
  • 1
    I tried your code, once the subtopics is cliked it won't hide. – Saranyuquestion Jun 14 '18 at 04:05
  • @Saranyuquestion well, just similarly add `onclick` event to each `".subtopics li"` where you `.remove("show")` for each `"#mainmenu ul > li"`. Try to do it by yourself. If any problem - let me know ;) – Rudolf Manusachi Jun 14 '18 at 21:21
  • Can you more clarify for me why are you using forEach loop stead of using for loop? Are there any advantages ? And why are you using getElementById in stead of querySelectorAll("#mainmenu ul > li") ? – Saranyuquestion Jun 15 '18 at 05:02
  • @Saranyuquestion about [for loop vs forEach](https://stackoverflow.com/a/23614460/2542172) `querySelectorAll` allows us to use more complex selectors (like in this case we need `li` items descended straight from `#mainmenu ul`..) [all modern browsers support it](https://caniuse.com/#feat=queryselector) – Rudolf Manusachi Jun 17 '18 at 01:17
  • @Saranyuquestion actually due to subtopics are inside mainmenu's link - click on sublink triggers event of it parent (adds class show to parent). In order to prevent that we have to [stop bubbling](https://javascript.info/bubbling-and-capturing) I have updated answer, added code for that into the spoiler – Rudolf Manusachi Jun 17 '18 at 02:01