How to fix my Javascript for checkbox questions/answers with feedback?

Viewed 52

I need help figuring out how to get each checkbox give back a different modal. I figured if it was fine with showing two modals that I could add another one in but it did not work. I want it to give separate feedback for each answer chosen. So for example if Answer A is chosen, then I want Modal1 for feedback. Same for B but Modal 2. Choice C works as being correct already.

<form id="submit1">

    <div id="question1" class="p-body flex-col-left" style="justify-content: flex-start;">
        <label>
            <input type="checkbox" name="input" value="wrongA" class="question1" data-seen=1>
            <span class="lineup">A. Emily should cross through the incorrect information and write in
                the correct information.</span>
        </label>
        <br>
        <label>
            <input type="checkbox" name="input" value="wrongB" class="question1" data-seen=2>
            <span class="lineup">B. Emily does not need to do anything until it is time for her to renew
                her license.</span>
        </label>
        <br>
        <label>
            <input type="checkbox" name="input" value="right" class="question1" data-seen=0>
            <span class="lineup">C. Emily needs to fill out the appropriate paperwork and submit it to
                the TDLR. </span>
        </label>
        <br>

        <br>

    </div>
    <div class="flex-center">
        <button type="submit" id="answer" class="modal-button modal-a">Submit</button>
    </div>
</form>
<script>

    document.getElementById("answer").onclick = validate;

    function validate() {
        var checkboxes = document.getElementsByName("input");
        var checkboxChecked = [];

        for (var i = 0; i < checkboxes.length; i++) {
            if (checkboxes[i].checked && (checkboxes[i].value === "right")) {
                checkboxChecked.push(checkboxes[i]);
            }
        }

        for (var i = 1; i < checkboxes.length; i++) {
            if (checkboxes[i].checked && (checkboxes[i].value === "wrongA")) {
                checkboxWrongA.push(checkboxes[i]);
            }
        }
        for (var i = 2; i < checkboxes.length; i++) {
            if (checkboxes[i].checked && (checkboxes[i].value === "wrongB")) {
                checkboxWrongB.push(checkboxes[i]);
            }
        }

        if (checkboxChecked.length === 1) {
            const modal1 = document.querySelector('#modal1');
            modal1.style.display = 'block'
            window.nextBtn.style.display = "block";
            window.dropdown.style.display = "block";
            window.breadcrumb.style.display = "block";

        } 
        
        if (checkboxWrongA.length === 1) {
            const modal2 = document.querySelector('#modal2');
            modal2.style.display = 'block'
        }

     if (checkboxWrongB.length === 1) {
            const modal3 = document.querySelector('#modal3');
            modal3.style.display = 'block'
        }
    }

</script>
2 Answers

Because you mentioned that your users should only choose 1 option, then a set radio buttons would be the way to go. Then we need to evaluate your JS to work with the radio buttons.

First of make sure that each radio has the same name attribute value. This enables us to use the name to get the value from the input that is checked. Allow the value to represent the chosen option. You could use right or wrongA here, but that doesn't say much about which option is chosen, only it's correctness.

<input type="radio" name="answer" value="A">
<input type="radio" name="answer" value="B">
<input type="radio" name="answer" value="C">

Now on the JavaScript side, we can make things simpler. Since you're using a <form> element, I'd suggest that you listen for a submit event on the form to know when you clicked your validate button.

A submit event happens whenever you have <form> with a <button type="submit"> inside of it and click the button. By default the page would reload. We'll need to stop that from happening by preventing the default behavior of the form. (see event.preventDefault()).

We can extract the data from the form using a FormData object. This object does a lot of work for us, for example, figuring out which of our inputs have been checked. With that object, we can ask for the value of the input by using the name of the input. In this case, I used the name: 'answer'.

Because we now use radio inputs, the value can only be either A, B or C. Based on the answer, look for the appropriate modal and show it.

const form = document.querySelector('#question-form');

form.addEventListener('submit', event => {
  event.preventDefault();

  const formData = new FormData(form);
  const answer = formData.get('answer');
  
  if (answer === 'A') {
    const modal = document.querySelector('#modal1');
    modal.classList.add('show');
  } else if (answer === 'B') {
    const modal = document.querySelector('#modal2');
    modal.classList.add('show');
  } else if (answer === 'C') {
    const modal = document.querySelector('#modal3');
    modal.classList.add('show');
  }
});
.modal {
  display: none;
  position: fixed;
  top: 50%;
  left: 50%;
  translate: -50% -50%;
  background: pink;
  padding: 50px 100px;
}

.modal.show {
  display: block;
}
<form id="question-form">
  <div>
    <label>
      <input type="radio" name="answer" value="A" class="question1" data-seen=1>
      <span class="lineup">A. Emily should cross through the incorrect information and write in the correct information.</span>
    </label>
  </div>
  
  <div>
    <label>
      <input type="radio" name="answer" value="B" class="question1" data-seen=2>
      <span class="lineup">B. Emily does not need to do anything until it is time for her to renew her license.</span>
    </label>
  </div>
  
  <div>
    <label>
      <input type="radio" name="answer" value="C" class="question1" data-seen=0>
      <span class="lineup">C. Emily needs to fill out the appropriate paperwork and submit it to the TDLR.</span>
    </label>
  </div>
  
  <button type="submit" class="modal-button modal-a">Submit</button>
</form>

<div id="modal1" class="modal">
  Modal 1
</div>

<div id="modal2" class="modal">
  Modal 2
</div>

<div id="modal3" class="modal">
  Modal 3
</div>

In this example checkboxes are replaced by radio buttons since it looks as if there's only one correct answer (and multiple modals are silly). The modals are <dialog> elements. Also, the "answer" button triggers a "submit" event that's registered to the <form>. The event handler check(e) is designed to leverage control by event delegation. In addition, the HTMLFormElement and HTMLFormControlsCollection interfaces were used to reference the <form> and it's form controls (all <input> in the <form>).

Details are commented in example

/**
 * Register the <form> to the "submit" event
 * The event handler check(e) is called when a "submit" event is triggered
 */
document.forms.quiz.onsubmit = check;

/**
 * The event handler passes the Event object by default
 * Prevent the default behavior of <form> during "submit" event
 * Collect all HTMLFormControls into a HTMLCollection
 * If a one form control with [name="chx"] is .checked...
 * ...get the checked radio button's value...
 * ...reference the <dialog> with the class of the same value as the 
 * checked radio button...
 * ...then open that <dialog>
 */
function check(e) {
  e.preventDefault();
  const fc = this.elements;
  if (Array.from(fc.rad).some(c => c.checked)) {
    const answer = fc.rad.value;
    const modal = document.querySelector('.' + answer);
    modal.showModal();
  }
}

/**
 * Collect all .close (buttons) into a NodeList and bind each one to the
 * "click" event.
 * The event handler close(e) is called when the "click" event is triggered.
 */
document.querySelectorAll(".close").forEach(btn => btn.onclick = close);

/**
 * This event handler will close the parent <dialog> of the clicked <button>
 */
function close(e) {
  this.closest('dialog').close();
}
html {
  font: 300 2ch/1.2 'Segoe UI'
}

body {
  min-height: 100vh;
}

body,
form {
  display: flex;
  flex-flow: column nowrap;
  justify-content: center;
  align-items: center;
  margin: 0 20px;
}

form {
  padding: 10px 30px;
}

fieldset {
  width: min(50vw, 500px);
}

legend {
  font-size: 1.25rem;
}

menu {
  margin: 0 20px 10px 0;
}

.list {
  list-style-type: lower-latin;
  margin: 20px 30px 0 -10px;
}

label {
  display: inline-flex;
  align-items: flex-start;
  transform: translate(12px, -17px);
  line-height: 1;
}

button,
input {
  font: inherit;
  cursor: pointer;
}

.right * {
  float: right;
  margin-bottom: 20px;
}
<form id="quiz">
  <fieldset>
    <legend>Quiz</legend>
    <menu class="list">
      <li><label>
        <input name="rad" type="radio" value="A"> Emily should cross through the incorrect information and write in the correct information.
      </label></li>
      <li><label>
        <input name="rad" type="radio" value="B"> Emily does not need to do anything until it is time for her to renew her license.
      </label></li>
      <li><label>
        <input name="rad" type="radio" value="C"> Emily needs to fill out the appropriate paperwork and submit it to the TDLR.
      </label></li>
    </menu>
    <menu class="right">
      <button>Done</button>
    </menu>
  </fieldset>
</form>

<dialog class="A">
  <fieldset>
    <legend>Message A</legend>
    <p>Quote mode. It's called carpe diem Morty. Look it up. Morty! The principal and I have discussed it, a-a-and we're both insecure enough to agree to a three-way! Haha god-damn! </p>
    <menu class="right">
      <input class="close" type="button" value="OK">
    </menu>
  </fieldset>
</dialog>

<dialog class="B">
  <fieldset>
    <legend>Message B</legend>
    <p>Yo! What up my glip glops! Lookin' good! Are you kidding? I'm hoping I can get to both of them, Rick! I mixed in some praying mantis DNA. You know a praying mantis is the exact opposite of a vole, Morty? They mate once and then bluergh cut each other's
      heads off. </p>
    <menu class="right">
      <input class="close" type="button" value="OK">
    </menu>
  </fieldset>
</dialog>

<dialog class="C">
  <fieldset>
    <legend>Message C</legend>
    <p>Get off the high road Summer. We all got pink eye because you wouldn't stop texting on the toilet. Flip the pickle over. Honey, stop raising your father's colesterol so you can take a hot funeral selfie. God? God's turning people into insect monsters
      Beth. I'm the one beating them to death. Thank me. </p>
    <menu class="right">
      <input class="close" type="button" value="OK">
    </menu>
  </fieldset>
</dialog>

Related