0

I have been trying to figure this out and I can't seem to do so on my own. I have a function that works if I hardcode the div's name and use a single button. However, I would like to do this with about 10 different buttons and have them work with the same function instead of copying the function 10 times. Here is the working code:

document.getElementById("genderBtn").addEventListener("click", myFunction);

function myFunction() {
  var x = document.getElementById("gender");
  if (x.style.display === "none") {
    x.style.display = "block";
  } else {
    x.style.display = "none";
  }
}
/* Checkbox Lineup */

fieldset.group {
  margin: 0;
  padding: 0;
  margin-bottom: 1.25em;
  padding: .125em;
}

fieldset.group legend {
  margin: 0;
  padding: 0;
  font-weight: bold;
  margin-left: 20px;
  font-size: 100%;
  color: black;
}

ul.checkbox {
  margin: 0;
  padding: 0;
  margin-left: 20px;
  list-style: none;
}

ul.checkbox li input {
  margin-right: .25em;
}

ul.checkbox li {
  border: 1px transparent solid;
  display: inline-table;
  width: 12em;
}

ul.checkbox li label {
  margin-left: ;
}

ul.checkbox li:hover,
ul.checkbox li.focus {
  background-color: lightyellow;
  border: 1px gray solid;
  width: 12em;
}


/* Radio button lineup */

ul.radio {
  margin: 0;
  padding: 0;
  margin-left: 20px;
  list-style: none;
}

ul.radio li input {
  margin-right: .25em;
}

ul.radio li {
  border: 1px transparent solid;
  display: inline-table;
  width: 12em;
}

ul.radio li label {
  margin-left: ;
}

ul.radio li:hover,
ul.radio li.focus {
  background-color: lightyellow;
  border: 1px gray solid;
  width: 12em;
}

hr {
  display: block;
  height: 1px;
  border: 0;
  border-top: 1px solid #ccc;
  margin: 1em 0;
  padding: 0;
}
<fieldset class="group">
  <legend>
    <h1>Demographics <button type="button" id="genderBtn">Gender</button></h1>
  </legend>

  <ul class="checkbox">
    <li><label for="name">Name: </label><input type="text" name="" id="name" value="" placeholder="default: client" /></li>
    <li><label for="age">Age: </label><input type="text" name="" id="age" value="" /></li><br>
  </ul>
  <hr />
  <div id="gender">
    <b>Biological Sex</b>
    <ul class="checkbox">
      <li><input type="checkbox" name="gender[]" id="gender0" value="female" /><label for="gender0">Female</label></li>
      <li><input type="checkbox" name="gender[]" id="gender1" value="male" /><label for="gender1">Male</label></li><br>
    </ul>
    <hr />
  </div>
  <b>Ethnic/Racial Information</b>
  <ul class="checkbox">
    <li><input type="checkbox" name="race[]" id="race0" value="Caucasian" /><label for="race0">Caucasian</label></li>
    <li><input type="checkbox" name="race[]" id="race1" value="African-American" /><label for="race1">African-American</label></li>
    <li><input type="checkbox" name="race[]" id="race2" value="Hispanic" /><label for="race2">Hispanic</label></li>
    <li><input type="checkbox" name="race[]" id="race3" value="Arabic" /><label for="race3">Arabic</label></li>
    <li><input type="checkbox" name="race[]" id="race4" value="Asian" /><label for="race4">Asian</label></li>
    <li><input type="checkbox" name="race[]" id="race5" value="multi-racial" /><label for="race5">Multi-racial</label></li>
    <li><label for="race6">Other:</label><input type="text" name="" id="race6" value="" /></li>
  </ul>
</fieldset>

Now, when I try to change it to pass the div name as a variable, I can't seem to get it to work.

document.getElementById("someOtherBtn").addEventListener("click", myFunction(someOtherDiv));

function myFunction(theDivName) {
  var x = document.getElementById("theDivName");
  if (x.style.display === "none") {
    x.style.display = "block";
  } else {
    x.style.display = "none";
  }
}

Can someone please let me know what I'm doing wrong?

Robert
  • 130
  • 1
  • 1
  • 9
  • On this line `var x = document.getElementById("theDivName");` there is a mistake. `theDivName` should not be wrapped in double quotes. –  Feb 02 '20 at 00:58
  • Note: the `
    ` and `` tags do not use and do not need a closing slash and never have in HTML.
    – Rob Feb 02 '20 at 01:03

4 Answers4

2

Not tested:

document.getElementById("someOtherBtn").addEventListener("click", function() {
   myFunction("someOtherDiv");
});

function myFunction(theDivName) {
  var x = document.getElementById(theDivName);
  if (x.style.display === "none") {
    x.style.display = "block";
  } else {
    x.style.display = "none";
  }
}

OR

myClickFunction("someOtherDiv");
myClickFunction("someOtherDiv2");
myClickFunction("someOtherDiv3");

function myClickFunction(theDivName) {
     var x = document.getElementById(theDivName);
     x.addEventListener("click", function() {
        myFunction(x);
     });
}
function myFunction(theDivElement) {
  var x = theDivElement;
  if (x.style.display === "none") {
    x.style.display = "block";
  } else {
    x.style.display = "none";
  }
}
Emiel Zuurbier
  • 19,095
  • 3
  • 17
  • 32
db1975
  • 775
  • 3
  • 9
  • Thank you so much! The first option works! I don't really understand the second one and how that would work with buttons in a form. I'm not a professional programmer (obviously) nor trying to be one. I'm just a psychologist trying to automate parts of my job. – Robert Feb 02 '20 at 01:25
0

On this line: var x = document.getElementById("theDivName"); You wrapped theDivName in double quotes, which is why you can't find the element. Leave the double quotes out.

After this little change, the line should look like this:

var x = document.getElementById(theDivName);

0

On this line: if (x.style.display === "none") { equal expression was used incorrectly.

Must be: if (x.style.display == "none") {

  • I tried that change and it didn't do anything differently. Also, without passing the variable, it worked with ===. – Robert Feb 02 '20 at 01:19
0

Make your JavaScript dynamic. Use the attributes HTML has to offer to tell JavaScript what elements to select or what kind of function it should fire.

The <button> element has the value attribute, which could tell something about, for example: which <div> to hide or show.

Since you want multiple buttons, and presumably the same buttons occur multiple times on screen, I'd suggest that you lose the id attribute on the buttons.

Use Event Delegation, which is a fancy term for listening on one element for, lets say a 'click' event, to listen to all of it's children. So however how many buttons you have, if you click anywhere in the element, the event is being listened to.

So listen to a top element which holds all your buttons. I've added a <form> element to wrap all the buttons and inputs. Listen for a 'click' event. Whenever the click is made, check if the clicked element was a button with, maybe a certain class to identify it. If it is, call your function and use the data on the button to select the proper action.

Now your toggle can turn on every element just by giving it the id of the element you want to toggle.

And you could do this too for all your checkboxes, if you might need it later.

Also, try to avoid writing your variables as x, or a and b for example. You might want to know what that x means whenever you later review your code. Call the beast by its name. Tell us what it is.

The <legend> element can only have a textnode as child, meaning no other elements besides just plain text. Otherwise your HTML would be invalid. It would still work, but it's not how you should do it.

The <b> tag is old and deprecated. If it's a title, use <h1> until <h6>.

Same goes for the <hr> tag. A horizontal rule is considered more as styling than markup, so let CSS handle that. It's good at it.

const form = document.querySelector('form');

function myFunction(target) {
  const id = target.value;
  const section = document.getElementById(id);
  if (section.style.display === "none") {
    section.style.display = "block";
  } else {
    section.style.display = "none";
  }
}

function onFormClick(event) {
  const target = event.target.closest('button.toggle');
  if (target !== null) {
    myFunction(target);
  }
}

form.addEventListener('click', onFormClick);
/* Checkbox Lineup */

*,
*::before,
*::after {
  box-sizing: border-box;
}

h2 {
  font-size: 20px;
}

fieldset.group {
  margin: 0;
  padding: 0;
  margin-bottom: 1.25em;
  padding: 1.25em;
}

fieldset.group > * {
  border-bottom: 1px solid #ccc;
  padding: 20px;
}

fieldset.group > *:last-child {
  border-bottom: 0;
}

fieldset.group legend {
  margin: 0;
  padding: 0;
  font-weight: bold;
  margin-left: 20px;
  font-size: 100%;
  color: black;
  border-bottom: 0;
}

ul.checkbox {
  padding: 0;
  margin: 0;
  list-style: none;
}

ul.checkbox li input {
  margin-right: .25em;
}

ul.checkbox li {
  border: 1px transparent solid;
  display: inline-table;
  width: 12em;
}

ul.checkbox li label {
  margin-left: ;
}

ul.checkbox li:hover,
ul.checkbox li.focus {
  background-color: lightyellow;
  border: 1px gray solid;
  width: 12em;
}


/* Radio button lineup */

ul.radio {
  margin: 0;
  padding: 0;
  margin-left: 20px;
  list-style: none;
}

ul.radio li input {
  margin-right: .25em;
}

ul.radio li {
  border: 1px transparent solid;
  display: inline-table;
  width: 12em;
}

ul.radio li label {
  margin-left: ;
}

ul.radio li:hover,
ul.radio li.focus {
  background-color: lightyellow;
  border: 1px gray solid;
  width: 12em;
}

hr {
  display: block;
  height: 1px;
  border: 0;
  border-top: 1px solid #ccc;
  margin: 1em 0;
  padding: 0;
}

.buttons {
  display: flex;
  flex-wrap: wrap;
  margin: 0 -2px;
  list-style: none;
  padding: 0 20px;
}

.buttons .toggle {
  margin: 0 2px 4px;
}
<form class="form">
  <fieldset class="group">
    <legend>Demographics</legend>

    <ul class="buttons">
      <li><button type="button" class="toggle" name="gender-button" value="gender">Gender</button></li>
      <li><button type="button" class="toggle" name="race-button" value="race">Race</button></li>
    </ul>

    <div id="credentials">
      <ul class="checkbox">
        <li><label for="name">Name: </label><input type="text" name="" id="name" value="" placeholder="default: client" /></li>
        <li><label for="age">Age: </label><input type="text" name="" id="age" value="" /></li><br>
      </ul>
    </div>

    <div id="gender">
      <h2>Biological Sex</h2>
      <ul class="checkbox">
        <li><input type="checkbox" name="gender[]" id="gender0" value="female" /><label for="gender0">Female</label></li>
        <li><input type="checkbox" name="gender[]" id="gender1" value="male" /><label for="gender1">Male</label></li><br>
      </ul>
    </div>

    <div id="race">
      <h2>Ethnic/Racial Information</h2>
      <ul class="checkbox">
        <li><input type="checkbox" name="race[]" id="race0" value="Caucasian" /><label for="race0">Caucasian</label></li>
        <li><input type="checkbox" name="race[]" id="race1" value="African-American" /><label for="race1">African-American</label></li>
        <li><input type="checkbox" name="race[]" id="race2" value="Hispanic" /><label for="race2">Hispanic</label></li>
        <li><input type="checkbox" name="race[]" id="race3" value="Arabic" /><label for="race3">Arabic</label></li>
        <li><input type="checkbox" name="race[]" id="race4" value="Asian" /><label for="race4">Asian</label></li>
        <li><input type="checkbox" name="race[]" id="race5" value="multi-racial" /><label for="race5">Multi-racial</label></li>
        <li><label for="race6">Other:</label><input type="text" name="" id="race6" value="" /></li>
      </ul>
    </div>

  </fieldset>
</form>
Emiel Zuurbier
  • 19,095
  • 3
  • 17
  • 32