Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to see which element of menu has been pressed?

I am working on a school project and we have to do a virtual static menu for a restaurant. What I've done until now is this: when I click on a button, a PopUp shows up and it's contained within the div with the class="menu". The thing is, that I stored all the menu items in a JSON file and thus I don't know how many items I'm going to have inside the menu. If you take a look at the code below, you can see that every menu item is contained within the < li > tag. Now, you can also see that the description start off with the display: none; property. What I am trying to do is this: Using Javascript(I don't think it's possible with plain HTML and CSS), how can I set the style of the description to display: block; of that particular item when either the "title" class or the "svg-container" class is called? In either case, when the svg or the title is pressed, the svg MUST rotate 90 degrees and return to 0 degrees when it's clicked again. The problem is that I don't know how to get the reference of the exact item that has been pressed so I can show it's description...

This is a visual representation of what the menu looks like for now:

enter image description here

And this is why I need the description to be set to display: block;

enter image description here

<div class="menu">
        <h2>Our Menu</h2>
        <ul>
            <li>
                <label>
                    <div class="svg-container"> <img class="arrow" src="right-arrow.svg"/></div>
                    <span class="title">Fried Fish With Souce</span>
                    <div class="description" style="display: none;">
                            This is some internal content.This is some internal content.This is some internal content.
                    </div>
                </label>
            </li>
            <li>
                <label>
                    <div class="svg-container"> <img class="arrow" src="right-arrow.svg"/></div>
                    <span class="title">Spaghetti</span>
                    <div class="description" style="display: none;">
                            This is some internal content.This is some internal content.This is some internal content.
                    </div>
                </label>
            </li>
        </ul>
    </div>

I tried my best to explain the problem in a clear way, for any questions or uncertainties I am here to answer. Thanks in advance!

EDIT: Thanks everyone for the quick help, but after implementing your code, there is a slight problem, look what happens when the title is too long to fit inside the menu div:

enter image description here

As you can see, the title moves completely on a new line, but what it should just move the content that doesn't fit(WITHOUT splitting the word, only if there is a space) on the new line.

like image 860
Jasper Howard Avatar asked Oct 27 '22 16:10

Jasper Howard


1 Answers

All you need to do is handle the click at the .menu level and then determine exactly which item within the menu was clicked using [event.target][1]. This approach leverages event bubbling using a technique called "event delegation".

// Set up event listener on the menu
document.querySelector(".menu").addEventListener("click", function(event){
  // The actual item within the menu that was clicked is accessible 
  // through event.target. So, we'll find the nearest ancestor <li> 
  // of that, and then search for the .description element within that
  // and change the style
  event.target.closest("li").querySelector(".description").classList.remove("hidden");

});
.hidden { display:none; }
<div class="menu">
        <h2>Our Menu</h2>
        <ul>
            <li>
                    <div class="svg-container"> 
                      <img class="arrow" src="right-arrow.svg"/>
                      <span class="title">Fried Fish With Souce</span>
                    </div>
                    <div class="description hidden">
                            This is some internal content.This is some internal content.This is some internal content.
                    </div>
            </li>
            <li>
                    <div class="svg-container"> 
                      <img class="arrow" src="right-arrow.svg"/>
                      <span class="title">Spaghetti</span>
                    </div>
                    <div class="description hidden">
                            This is some internal content.This is some internal content.This is some internal content.
                    </div>
            </li>
        </ul>
    </div>

Other:

  • You are not using the label element correctly. It is meant to associate a caption with a form field, not regular HTML elements.

  • If you want the text of the menu item to be next to the arrow, you'll need that span to be inside of the previous div, not outside of it.

  • Avoid inline styles when possible and use CSS classes instead.

  • If you want to be able to toggle the visibility of a clicked item (show/hide/show/hide, etc.), use .classList.toggle instead of classList.remove.

like image 186
Scott Marcus Avatar answered Nov 15 '22 11:11

Scott Marcus