Can you help a js noob solve this problem without repeating himself so much?

https://code.sololearn.com/WdGy2v5Tly0F/?ref=app Hey, I have 3 buttons and 3 divs. This is a simple code with inline onclick attribute and 3 functions (that are all the same) showing and hiding the div for each button by manipulating 'display' in the style sheet. I know there has to be better ways to do this. I am reading about eventlisteners and trying to come up with a solution ... can any one recommend a better way while I keep reading? Any help much appreciated! Any ideas for conditionals/loops?

1/13/2018 6:47:58 PM


10 Answers

New Answer


@Jared Bird @visph I'm slowly going through your work and figuring it out, wanted to say 'thank you!!' asap. Very cool! @emmey I am using vanilla js, but thank you.


@visph: thanks also for the freebie on the 2 clicks ... that was my next question! many thanks.


An extremely easy method that emphasises something called modularity or so(am not sure what that name is😄)Please if you don't understand anything in what I wrote let me know..... Anyways for each div element replace its onclick event handler with this function: displayDiv(event) Example: <!--but 1 and div 1--> <button onclick="displayDiv(event)" class="but" id="but1" value="About"/>About</button> <div class="div" id="div1"><p>Here is some text</p> </div> In the js section, just add one single function: function displayDiv(e){ var x = e.target.nextElementSibling; if (x.style.display === "") x.style.display = "block"; else x.style.display = ""; } Explanation:When you click a button, the button passes an event object into the function..... At the js side the function receives the event object and assigns a variable x as a pointer to the next sibling that is an element Then the display property is changed using js For double clicking use @visph's recommendation


I think event attributes are the best way to do it. That's a lot of JavaScript, the best I can do with it is add an alert saying something about the code. I've barely scratched the surface of it!




@Memo: ... but the targeted <div> (to hide/show) is not the same element that the one (<button>) holding the event ^^ You can even use e.target, but you need to explore DOM to get the next (real) sibling element (what should be a little tricky, because in half of browsers, the .nextSibling() method will return text node rather than <div> if there is at least one space-like character (could be a new line char) between us ;P


@visph Am incredibly sorry, I didn't notice that part of the question🙇I have updated my answer accordingly


Simply write same function, but with an argument, such as the <div> id you want to handle: function genericDisplayDiv(targetId) { var x = document.getElementById(targetId); if (x.style.display === "none") { x.style.display = "block"; } else { x.style.display = "none"; } } ... and use it in html as: <button onclick="genericDisplayDiv('div1');" class="but" id="but1" value="About"/>About</button> <div class="div" id="div1"><p>Here is some text</p> </div> <button onclick="genericDisplayDiv('div2');" class="but" id="but2" value="Interests"/>Interests</button> <div class="div" id="div2"><p>Here is some more text</p></div> <button onclick="genericDisplayDiv('div3');" class="but" id="but 3" value="Sololearn"/>Sololearn</button> <div class="div "id="div3"><p>Here is even more text</p></div> However, actually your buttons require 2 clicks the first time to display the related <div>... The reason is the default value hold by the .style.display property is an empty string, even if you declare "display:none" in your css rules, because it read (and write) exclusively the rules in the "style" attribute of html element (<div> in this case). Quick and reommend fix, is to add the attribute: style="display:none;" ... in the <div> tag, or better modify your generic function to test for empty string rather than for "none" value (and assign empty string when you want to 'display:none' the <div> (it will fallback to the css rules if empty string is provided as value in the style attribute): function genericDisplayDiv(targetId) { var x = document.getElementById(targetId); if (x.style.display === "") { x.style.display = "block"; } else { x.style.display = ""; } }


or use like Function displayDiv(num)... Getelephantbyid("div"+num)...


@Memo: still not right ^^ + you should call '.nextSibling()' method (and not '.nextElementSibling()') and append parenthesis pair for that + as I was saying in my last post, the .nextSibling() method would not return the expected value in most of the cases [edit] My bad: .nextElementSibling() is also available and avoid the problem of .nextSibling()... However, I don't know how widely it is supported ;)