1

Can't use jQuery or CSS (only). I have:

function handleDropDown (elementId) {
  document.getElementById('languages').style.display = "block";
}
.flag-icon-wrapper {
  margin-right: 20px;
  padding-top: 5px;
}

.flex {
  display: flex;
}

.flag-icon {
  width: 50px;
}

.is-hidden-initially {
  display: none;
}
<span class="flag-icon-wrapper flex" onClick='handleDropDown()'>
<img class="flag-icon" src="https://i.imgur.com/3DpAxu5.png" />
</span>

<div class="languages is-hidden-initially">
<ul>
<li>Spanish</li>
<li>French</li>
<li>Russian</li>
</ul>
</div>

The idea is that when you click on the American flag, it should reveal a list of other languages (eventually to choose from). Eventually, when you click on another language, I'd like to show the flag that's associated with that language in the flag-icon-wrapper span, but for now, I just want to show or hide the languages div when you click on the flag.

At this point, I'm getting Uncaught TypeError: Cannot read property 'style' of null" - why? I'm getting the element by ID languages to display it as block - so why is that part not working? Thanks

EDIT It's now fixed by changing the class to an ID in the html:

<span class="flag-icon-wrapper flex" onClick='handleDropDown()'>
<img class="flag-icon" src="https://i.imgur.com/3DpAxu5.png" />
</span>

<div id="languages" class="is-hidden-initially">
<ul>
<li>Spanish</li>
<li>French</li>
<li>Russian</li>
</ul>
</div>

But now how can we toggle between showing and hiding the div?

1
  • 2
    Your element doesn't have an id. You've set the class to "languages", not the id. Commented May 14, 2021 at 19:16

5 Answers 5

3

You are trying to access an element by id but haven't specified an id for the element yet.

You could do it like this:

const divHide = document.getElementById("div-hide");

function handleHide(){
    divHide.style.display = "none";
}

function handleShow(){
    divHide.style.display = "block";
}
<div id="div-hide">
Hello
</div>
<button onclick="handleHide()">
click to hide
</button>
<button onclick="handleShow()">
click to show
</button>

Or like this:

const divHide = document.getElementById("div-hide");

const btnHide = document.getElementById("btn-hide");
const btnShow = document.getElementById("btn-show");

btnHide.addEventListener("click" , () => {
    divHide.style.display = "none";
});

btnShow.addEventListener("click" , () => {
    divHide.style.display = "block";
});
<div id="div-hide">
Hello
</div>
<button id="btn-hide">
click to hide
</button>
<button id="btn-show">
click to show
</button>

If you want to add some toggle logic you could do the following:

const divHide = document.getElementById("div-hide");

function handleToggle(){
    divHide.style.display === "none" ? divHide.style.display = "block" : divHide.style.display = "none";
}
<div id="div-hide">
Hello
</div>
<button onclick="handleToggle()">
click to toggle
</button>

Sign up to request clarification or add additional context in comments.

6 Comments

Is there a way to create the logic so that it's hidden initially? The problem is that if you have a 'is-hidden' class, the ID will take precedence, so it's always displaying block initially. We need it to display: none initially.
Thank you for accepting! You can add an initial display:none to the element: <div id="div-hide" style="display:none">Hello</div>
I can't post an answer because it says it is closed, but it looks like you made a typo, try getElementById instead of getElementByID.
Feel free to vote to re-open the question if you want, since I've edited it to be more specific to vanilla JavaScript. Also, here's the most recent version of the Code, which is saying that 'element' is not defined, even though I've defined it as a constant within the ToggleClassMenu() function: jsfiddle.net/3zreyLv2/2 That's as far as I could go.
I asked for a reopen, if it does, I will check it out!
|
1

You want to access using getElementById but your code contains languages as a class, not id. Corrected your code below,

function handleDropDown(elementId) {
  const element = document.getElementById('languages');

  if (element.style.display === "block") {
    element.style.display = "none";
  } else {
    element.style.display = "block";
  }
}
.flag-icon-wrapper {
  margin-right: 20px;
  padding-top: 5px;
}

.flex {
  display: flex;
}

.flag-icon {
  width: 50px;
}

.is-hidden-initially {
  display: none;
}
<span class="flag-icon-wrapper flex" onClick='handleDropDown()'>
<img class="flag-icon" src="https://i.imgur.com/3DpAxu5.png" />
</span>

<div id="languages" class="is-hidden-initially">
  <ul>
    <li>Spanish</li>
    <li>French</li>
    <li>Russian</li>
  </ul>
</div>

5 Comments

Perfect - thank you. So now, the question is - how can we hide it again when it gets clicked a second time. I'll want to know the best way to toggle between showing and hiding the languages div.
Use its current display to determine how to display it. document.getElementById('languages').style.display = (document.getElementById('languages').style.display == "block") ? "none" : "block";
@HappyHands31 updated my answer for show/hide logic.
Actually, the problem with this is that it only shows and hides once. It should show and hide as many times as the flag is clicked...
@HappyHands31 yes you were right, updated my logic, now it will work on every click. Thanks
0
<span class="flag-icon-wrapper flex" onclick="handleDropDown()">
        <img class="flag-icon" src="https://i.imgur.com/3DpAxu5.png" />
        </span>
        
        <div class="languages is-hidden-initially" id="languages">
        <ul>
        <li>Spanish</li>
        <li>French</li>
        <li>Russian</li>
        </ul>
        </div>

js

function handleDropDown() {
    var x = document.getElementById("languages");
    if (x.style.display === "none") {
        x.style.display = "block";
    } else {
        x.style.display = "none";
    }
}

Hope It will work.

Comments

0

You can simply add a toggle to the classList: element.classList.toggle("is-hidden-initially");

function handleDropDown(elementId) {
  const element = document.getElementById('languages');
  element.classList.toggle("is-hidden-initially");
}
.flag-icon-wrapper {
  margin-right: 20px;
  padding-top: 5px;
}

.flex {
  display: flex;
}

.flag-icon {
  width: 50px;
}

.is-hidden-initially {
  display: none;
}
<span class="flag-icon-wrapper flex" onClick='handleDropDown()'>
<img class="flag-icon" src="https://i.imgur.com/3DpAxu5.png" />
</span>

<div id="languages" class="is-hidden-initially">
  <ul>
    <li>Spanish</li>
    <li>French</li>
    <li>Russian</li>
  </ul>
</div>

Comments

0

I believe I see what you are attempting. I would be a bit more deliberate, not proliferate with unique id's and I would use a data attribute set to both toggle and set visibility using CSS.

I added a second flag just to illustrate the same code works for both using the data attributes set. Note I pass this from the element but you could also use an event handler instead of embedding that call in the element, keeping the code separate from the markup. (2nd example)

function handleDropDown(me) {
  // get and use the selector from the data attribute
  let toggles = ["hidden", "showem"];
  let tarsel = me.dataset.clickTarget;
  let tar = document.querySelector(tarsel);
  tar.dataset.hideme = tar.dataset.hideme == toggles[0] ? toggles[1] : toggles[0];
}
.flag-icon-wrapper {
  margin-right: 20px;
  padding-top: 5px;
}

.flex {
  display: flex;
}

.flag-icon {
  width: 50px;
}

[data-hideme="hidden"] {
  display: none;
}

[data-hideme="showem"] {
  border: solid lime 1px;
  ;
}
<span class="flag-icon-wrapper flex" onClick='handleDropDown(this)' data-click-target=".mytarget.languages">
<img class="flag-icon" src="https://i.imgur.com/3DpAxu5.png" />
</span>
<span class="flag-icon-wrapper flex" onClick='handleDropDown(this)' data-click-target=".newtarget.languages">
<img class="flag-icon" src="https://i.imgur.com/3DpAxu5.png" />
</span>
<div class="newtarget languages" data-hideme="hidden">
  <ul>
    <li>Spanish</li>
    <li>French</li>
    <li>Russian</li>
  </ul>
</div>
<div class="mytarget languages" data-hideme="hidden">
  <ul>
    <li>Beer</li>
    <li>Wine</li>
    <li>Cheese</li>
  </ul>
</div>

2nd example using an event handler from code instantiation rather than in markup

let wappers = document.querySelectorAll(".flag-icon-wrapper");
wappers.forEach(el => el.addEventListener("click", function(event) {
  // get and use the selector from the data attribute
  let toggles = ["hidden", "showem"];
  let tarsel = this.dataset.clickTarget;
  let tar = document.querySelector(tarsel);
  tar.dataset.hideme = tar.dataset.hideme == toggles[0] ? toggles[1] : toggles[0];
}));
.flag-icon-wrapper {
  margin-right: 20px;
  padding-top: 5px;
}

.flex {
  display: flex;
}

.flag-icon {
  width: 50px;
}

[data-hideme="hidden"] {
  display: none;
}

[data-hideme="showem"] {
  border: solid lime 1px;
  ;
}
<span class="flag-icon-wrapper flex" data-click-target=".mytarget.languages">
<img class="flag-icon" src="https://i.imgur.com/3DpAxu5.png" />
</span>
<span class="flag-icon-wrapper flex" data-click-target=".newtarget.languages">
<img class="flag-icon" src="https://i.imgur.com/3DpAxu5.png" />
</span>
<div class="newtarget languages" data-hideme="hidden">
  <ul>
    <li>Spanish</li>
    <li>French</li>
    <li>Russian</li>
  </ul>
</div>
<div class="mytarget languages" data-hideme="hidden">
  <ul>
    <li>Beer</li>
    <li>Wine</li>
    <li>Cheese</li>
  </ul>
</div>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.