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


@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


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!




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 = ""; } }


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


@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 ;)


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