Reputation: 23
I have three buttons and three JS functions that toggle the display of three different divs. How can I simplify/condense my three JS functions into one function that connects each button to its corresponding content?
Example:
HTML Buttons
<button onclick="myFunction1()">Button 1</button>
<button onclick="myFunction2()">Button 2</button>
<button onclick="myFunction3()">Button 3</button>
HTML Content
<div id="ContentOne">This is Content One.</div>
<div id="ContentTwo">This is Content Two.</div>
<div id="ContentThree">This is Content Three.</div>
JavaScript
function myFunction1() {
var x = document.getElementById("ContentOne");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
function myFunction2() {
var x = document.getElementById("ContentTwo");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
function myFunction3() {
var x = document.getElementById("ContentThree");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
Upvotes: 2
Views: 1108
Reputation: 2075
You can use a higher order function.
function generateFunction(elementId) {
return function() {
var x = document.getElementById(elementId);
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
}
var myFunction1 = generateFunction("ContentOne");
var myFunction2 = generateFunction("ContentTwo");
var myFunction3 = generateFunction("ContentThree");
Upvotes: 0
Reputation: 206565
Inline JS is hard to maintain.
I'd use this code with just a line of CSS to hide elements,
and use JS simply to toggle that .hide
class:
const toggleEl = e => document.getElementById(e.target.dataset.tog).classList.toggle("hide");
[...document.querySelectorAll("[data-tog]")].forEach( btn =>
btn.addEventListener("click", toggleEl)
);
.hide { display: none;}
<button data-tog="ContentOne">Button 1</button>
<button data-tog="ContentTwo">Button 2</button>
<button data-tog="ContentThree">Button 3</button>
<div class="hide" id="ContentOne">This is Content One.</div>
<div class="hide" id="ContentTwo">This is Content Two.</div>
<div class="hide" id="ContentThree">This is Content Three.</div>
https://developer.mozilla.org/en-US/docs/Web/API/Element/classList
Here's a ES5 example if you prefer:
function toggleEl() {
var id = this.getAttribute("data-tog");
document.getElementById(id).classList.toggle("hide");
}
var buttons = document.querySelectorAll("[data-tog]");
[].forEach.call(buttons, function( btn ) {
btn.addEventListener("click", toggleEl.bind(btn))
});
.hide { display: none;}
<button data-tog="ContentOne">Button 1</button>
<button data-tog="ContentTwo">Button 2</button>
<button data-tog="ContentThree">Button 3</button>
<div class="hide" id="ContentOne">This is Content One.</div>
<div class="hide" id="ContentTwo">This is Content Two.</div>
<div class="hide" id="ContentThree">This is Content Three.</div>
Upvotes: 2
Reputation: 3455
Add a parameter to the condensed function et violà!
function myFunction(id) {
var x = document.getElementById(id);
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
<button onclick="myFunction('ContentOne')">Button 1</button>
<button onclick="myFunction('ContentTwo')">Button 2</button>
<button onclick="myFunction('ContentThree')">Button 3</button>
<div id="ContentOne">This is Content One.</div>
<div id="ContentTwo">This is Content Two.</div>
<div id="ContentThree">This is Content Three.</div>
The only part that differs within the functions is the ID, so decouple the ID. The function does not need to know which element will be affected of the styling adaptions. So keep the function "dump".
If you are interested in improving your programming style, I suggest you take a look at some anti-pattern. For example, you demonstrated the antipattern of hard coding. It's not as untypical as you think.
Upvotes: 5