Skip to content

onchange and onreset handlers not updating css properties on reset

I have a form (which I am incidentally generating in PHP from a database) that is using CSS to replace checkboxes. When a checkbox is checked, the containing <li> should have an outline added, and when unchecked, the outline should be removed. Using onchange events works to change these at a click, but the outlines remain when the form is reset. I added onreset events, to try to force the removal, but that doesn’t seem to change anything.

I’ve recreated this behavior in the snippet. (I have not hidden the checkboxes, as the snippet system apparently does not duplicate the normal browser behavior of clicking on the <label> to set or clear the checkbox. [EDIT: This was my mistake; I set the wrong for on the labels, and now that behavior works. The rest stands.])

How do I make this work? I could have a function that manually sets each outline in a reset function, but, as I said, the checkboxes are created from a database, so I’d have to write the PHP to write the js function, which seems like the wrong way to go.

function doCheckboxes(clicked_id) {
  if (document.getElementById(clicked_id).checked) {
    document.getElementById(clicked_id).parentNode.style.outline = "2px solid black";
  } else {
    document.getElementById(clicked_id).parentNode.style.outline = "0 none black";
  }
}

function clearCheckboxes(clicked_id) {
  document.getElementById(clicked_id).parentNode.style.outline = "0 none black";
}
li {
  display: inline-block;
  margin: 10px;
  text-align: center;
  font-weight: 600;
}

.imageholder {
  display: block;
  height: 60px;
  width: 60px;
  background-repeat: no-repeat;
  background-clip: content-box;
  background-size: cover;
  margin: auto;
}

.has-thing1 .imageholder {
  background-image: url(path/to/image.png);
}

.has-thing2 .imageholder {
  background-image: url(path/to/image.png);
}

.has-thing3 .imageholder {
  background-image: url(path/to/image.png);
}
<form action="." method="get">
  <fieldset class="subcategory">
    <ul>
      <li class="has-x has-thing1">
        <input type="checkbox" onChange="doCheckboxes(this.id)" onReset="clearCheckboxes(this.id)" id="x_thing1" name="has[]" value="thing1">
        <label for="x_thing1">
        <div class="imageholder">&nbsp;</div>
        Thing1
      </label>
      </li>
      <li class="has-x has-thing2">
        <input type="checkbox" onChange="doCheckboxes(this.id)" onReset="clearCheckboxes(this.id)" id="x_thing2" name="has[]" value="thing2">
        <label for="x_thing2">
        <div class="imageholder">&nbsp;</div>
        Thing2
      </label>
      </li>
      <li class="has-x has-thing3">
        <input type="checkbox" onChange="doCheckboxes(this.id)" onReset="clearCheckboxes(this.id)" id="x_thing3" name="has[]" value="thing3">
        <label for="x_thing3">
        <div class="imageholder">&nbsp;</div>
        Thing3
      </label>
      </li>
    </ul>
  </fieldset>
  <div>
    <button type="submit">Submit</button></div>
  <button type="reset">Clear Selection</button>
</form>

Answer

Create function clearAllCheckboxes

  function clearAllCheckboxes(evt) {
    const formEl = evt.closest('form')
    const allCheckbox = formEl.querySelectorAll('[type=checkbox]')
    allCheckbox.forEach(checkbox => {
      checkbox.parentNode.style.outline = "0 none black"
    })
  }

Add an onClick handler to the button “Clear Selection”

<button type="reset" onClick="clearAllCheckboxes(this)">Clear Selection</button>