+ 15

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?

13th Jan 2018, 6:47 PM
JMQ
JMQ - avatar
10 Answers
+ 15
@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.
13th Jan 2018, 7:51 PM
JMQ
JMQ - avatar
+ 14
@visph: thanks also for the freebie on the 2 clicks ... that was my next question! many thanks.
13th Jan 2018, 8:05 PM
JMQ
JMQ - avatar
+ 5
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
13th Jan 2018, 7:57 PM
the_code_genin
the_code_genin - avatar
+ 3
@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
13th Jan 2018, 8:01 PM
visph
visph - avatar
+ 2
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!
13th Jan 2018, 6:51 PM
Robyn A
Robyn A - avatar
13th Jan 2018, 7:34 PM
Jared Bird
Jared Bird - avatar
+ 2
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 = ""; } }
13th Jan 2018, 7:43 PM
visph
visph - avatar
+ 2
@visph Am incredibly sorry, I didn't notice that part of the question🙇I have updated my answer accordingly
13th Jan 2018, 8:53 PM
the_code_genin
the_code_genin - avatar
+ 1
@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 ;)
13th Jan 2018, 8:57 PM
visph
visph - avatar
0
or use like Function displayDiv(num)... Getelephantbyid("div"+num)...
13th Jan 2018, 7:49 PM
emmey
emmey - avatar