admin管理员组

文章数量:1314558

Intended behaviour

I have a checkbox inside of a div element. I want both the box and the div to be clickable.

  • When the checkbox is clicked by the user, a class is added to the div to change its background colour. This class is then removed if the checkbox is clicked again.
  • When the div itself is clicked, the class with the background colour is added or removed as appropriate and the checkbox is ticked or unticked too

Currently, I have most of this working using plain javascript:

function boxPress(markNumber) {
  var checkbox = "mark" + markNumber;
  var element = document.getElementById(checkbox);
  var markbox = "markbox" + markNumber;
  if (element.getAttribute("checked") == null) {
    element.setAttribute("checked", "checked");
    document.getElementById(markbox).classList.add('checked');
  } else {
    element.removeAttribute("checked");
    document.getElementById(markbox).classList.remove('checked');
  }
}
.mark {
  margin-bottom: 5px;
  margin-top: 5px;
  background-color: #FFFFFF;
  border-width: 2px;
  border-radius: 0px 5px 5px 0px;
  border-left-style: solid;
  border-left-width: 10px;
  border-color: lime;
  overflow: auto;
  padding: 2%;
  transition: background-color 0.5s linear 0s;
  cursor: pointer;
}

.checked {
  background-color: #66ff66;
}

.mark:hover {
  background-color: #fffcaf;
}

.checked:hover {
  background-color: #b3ffb3;
}

.flex-container {
  display: -webkit-flex;
  display: flex;
  align-items: center;
  margin: 0px;
  padding: 0px;
}

.flex-mark {
  width: 85%;
  margin: 0px;
}

.flex-tick {
  width: 15%;
  margin: 0px;
  text-align: center;
}

.flex-tick input {
  width: 40px;
  height: 40px;
}
<div class="mark col-12 col-m-6" id="markbox0" onclick="boxPress(0)">
  <div class="flex-container">
    <div class="flex-mark">
      <p>Candidate introduces themself by first name, surname and role</p>
    </div>
    <div class="flex-tick"><input type="checkbox" id="mark0"></div>
  </div>
</div>

Intended behaviour

I have a checkbox inside of a div element. I want both the box and the div to be clickable.

  • When the checkbox is clicked by the user, a class is added to the div to change its background colour. This class is then removed if the checkbox is clicked again.
  • When the div itself is clicked, the class with the background colour is added or removed as appropriate and the checkbox is ticked or unticked too

Currently, I have most of this working using plain javascript:

function boxPress(markNumber) {
  var checkbox = "mark" + markNumber;
  var element = document.getElementById(checkbox);
  var markbox = "markbox" + markNumber;
  if (element.getAttribute("checked") == null) {
    element.setAttribute("checked", "checked");
    document.getElementById(markbox).classList.add('checked');
  } else {
    element.removeAttribute("checked");
    document.getElementById(markbox).classList.remove('checked');
  }
}
.mark {
  margin-bottom: 5px;
  margin-top: 5px;
  background-color: #FFFFFF;
  border-width: 2px;
  border-radius: 0px 5px 5px 0px;
  border-left-style: solid;
  border-left-width: 10px;
  border-color: lime;
  overflow: auto;
  padding: 2%;
  transition: background-color 0.5s linear 0s;
  cursor: pointer;
}

.checked {
  background-color: #66ff66;
}

.mark:hover {
  background-color: #fffcaf;
}

.checked:hover {
  background-color: #b3ffb3;
}

.flex-container {
  display: -webkit-flex;
  display: flex;
  align-items: center;
  margin: 0px;
  padding: 0px;
}

.flex-mark {
  width: 85%;
  margin: 0px;
}

.flex-tick {
  width: 15%;
  margin: 0px;
  text-align: center;
}

.flex-tick input {
  width: 40px;
  height: 40px;
}
<div class="mark col-12 col-m-6" id="markbox0" onclick="boxPress(0)">
  <div class="flex-container">
    <div class="flex-mark">
      <p>Candidate introduces themself by first name, surname and role</p>
    </div>
    <div class="flex-tick"><input type="checkbox" id="mark0"></div>
  </div>
</div>

This works perfectly, apart from where the user first interacts with the checkbox, then later with the div element.

Steps to reproduce the problem in the above snippet:

  1. Click the div. The background changes and the checkbox is ticked.
  2. Click the div again. The changes are reversed as expected.
  3. Click the checkbox. The background change is applied.
  4. Click the checkbox again. The change is reversed as expected.
  5. Now click the div again. The background changes happen but the checkbox remains unticked

Even more interestingly, the HTML of the checkbox reads:

<input type="checkbox" id="mark0" checked="true">

Yet the browser doesn't render the box as checked.

Why is this happening, and why is it only a problem when the div click es after the box click? It happens in both Chrome and Edge.

Share Improve this question edited Apr 27, 2017 at 17:21 Rory asked Apr 27, 2017 at 17:11 RoryRory 2,5161 gold badge29 silver badges43 bronze badges 8
  • I cannot reproduce the issue in Chrome, it works as expected after 15 cliks – VMAtm Commented Apr 27, 2017 at 17:15
  • 1 Because the value of the checked attribute should not be true, it should be checked or not present. See the standard. – Heretic Monkey Commented Apr 27, 2017 at 17:15
  • did you try calling checkbox's click() ? – user5328504 Commented Apr 27, 2017 at 17:16
  • Or you could just set the checked property to true or false like element.checked = true;. See the dupe: stackoverflow./q/18862149/215552 – Heretic Monkey Commented Apr 27, 2017 at 17:18
  • Possible duplicate of How to uncheck a checkbox in pure JavaScript? – Heretic Monkey Commented Apr 27, 2017 at 17:18
 |  Show 3 more ments

1 Answer 1

Reset to default 9

There is a difference between the attribute checked and the checked state of a checkbox. Fixed code below.

Explanation:

Because the checked attribute can be set in the markup to "pre-check" the checkbox the DOM has to have a checked state for the checkbox or it would be impossible to "un-check" it. A checkbox that could not be un-checked wouldn't be very useful.

When you set the attribute for the first time (with javascript) it checks the box just like if you had put it in the HTML but the DOM ignores the attribute after that because it needs to rely on the checked state as explained above.

function boxPress(markNumber) {
  var checkbox = "mark" + markNumber;
  var element = document.getElementById(checkbox);
  var markbox = "markbox" + markNumber;
  if (element.getAttribute("checked") == null) {
    element.setAttribute("checked", "true");
    element.checked = true;
    document.getElementById(markbox).classList.add('checked');
  } else {
    element.removeAttribute("checked");
    element.checked = false;
    document.getElementById(markbox).classList.remove('checked');
  }
}
.mark {
  margin-bottom: 5px;
  margin-top: 5px;
  background-color: #FFFFFF;
  border-width: 2px;
  border-radius: 0px 5px 5px 0px;
  border-left-style: solid;
  border-left-width: 10px;
  border-color: lime;
  overflow: auto;
  padding: 2%;
  transition: background-color 0.5s linear 0s;
  cursor: pointer;
}

.checked {
  background-color: #66ff66;
}

.mark:hover {
  background-color: #fffcaf;
}

.checked:hover {
  background-color: #b3ffb3;
}

.flex-container {
  display: -webkit-flex;
  display: flex;
  align-items: center;
  margin: 0px;
  padding: 0px;
}

.flex-mark {
  width: 85%;
  margin: 0px;
}

.flex-tick {
  width: 15%;
  margin: 0px;
  text-align: center;
}

.flex-tick input {
  width: 40px;
  height: 40px;
}
<div class="mark col-12 col-m-6" id="markbox0" onclick="boxPress(0)">
  <div class="flex-container">
    <div class="flex-mark">
      <p>Candidate introduces themself by first name, surname and role</p>
    </div>
    <div class="flex-tick"><input type="checkbox" id="mark0"></div>
  </div>
</div>

本文标签: htmlWhy can I not change the 39checked39 status of a checkbox in JavascriptStack Overflow