+ 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?
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.
+ 14
@visph:
thanks also for the freebie on the 2 clicks ... that was my next question! many thanks.
+ 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
+ 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
+ 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!
+ 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 = "";
}
}
+ 2
@visph Am incredibly sorry, I didn't notice that part of the questionđI have updated my answer accordingly
+ 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 ;)
0
or use like Function displayDiv(num)...
Getelephantbyid("div"+num)...