Stony Stony - 10 days ago 5
Javascript Question

JS uncheck radiobutton makes all uncheckable

I've got a pure CSS accordion and would like to add some functionality for people who have JavaScript enabled. The CSS accordion works with the :checked pseudo-class.

The new functionality:
If an already active button is clicked again, all should collapse. Please no JS libraries like jQuery.

It works the very first time, when clicking the initially uncollapsed item. But then all buttons seem to fulfill

.checked===true
. It is not possible to check an item anymore.


Here is a JSFiddle
and this is the JS (please also look for stupid mistakes - I'm a JS beginner):

function uncheck() {
if(this.checked) {
this.checked = false;
}
}

var elements = document.getElementsByClassName("js-uncheck");
for (var i=0; i<elements.length; i++) {
elements[i].addEventListener("click", uncheck, false);
}


I'm also open for a checkbox variation (already unsuccessfully tested around a bit), as long as only one item is uncollapsed at a time (radiobutton-like).
Here is a Fiddle to play around with checkboxes.

Answer

Basically, the problem is that "click" turns the button to clicked. Then your listener "uncheck" runs, finds that the button is clicked, and then unchecks it. :(

This will get you running and only has the problem of not working on first uncheck if the radio is checked when the page loads. You can overcome that by running some js to uncheck everything on page load, or force check something (and add that my-checked class).

function uncheck() {
  var addit = 1;
  if (this.classList.contains('my-checked')) {
    this.checked = false;
    addit = 0;
  }
  var elements = document.getElementsByClassName("js-uncheck");
  for (var i = 0; i < elements.length; i++) {
    elements[i].classList.remove('my-checked');
  }
  if (addit) {
    this.classList.add('my-checked');
  }
}

var elements = document.getElementsByClassName("js-uncheck");
for (var i = 0; i < elements.length; i++) {
  elements[i].addEventListener("click", uncheck, false);
}
/*   Author:    Michael Raffaele <michael@mraffaele.com>
*    Date:    25th October 2011
*    Info:     http://www.mraffaele.com/blog/2011/10/25/css-accordion-no-javascript/
*/
/* Shared for all accordion types */
.accordion {
  font-family: Arial, Helvetica, sans-serif;
  margin: 0 auto;
  font-size: 14px;
  border: 1px solid #542437;
  border-radius: 10px;
  width: 600px;
  padding: 10px;
  background: #fff;
}

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

.accordion li {
  margin: 0;
  padding: 0;
}

.accordion [type=radio],
.accordion [type=checkbox] {
  display: inline-block;
}

.accordion label {
  display: block;
  font-size: 16px;
  line-height: 16px;
  background: #D95B43;
  border: 1px solid #542437;
  color: #542437;
  text-shadow: 1px 1px 1px rgba(255, 255, 255, 0.3);
  font-weight: 700;
  cursor: pointer;
  text-transform: uppercase;
  -webkit-transition: all .2s ease-out;
  -moz-transition: all .2s ease-out;
}

.accordion ul li label:hover,
.accordion [type=radio]:checked ~ label,
.accordion [type=checkbox]:checked ~ label {
  background: #C02942;
  color: #FFF;
  text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5)
}

.accordion .content {
  padding: 0 10px;
  overflow: hidden;
  border: 1px solid #fff;
  /* Make the border match the background so it fades in nicely */
  -webkit-transition: all .5s ease-out;
  -moz-transition: all .5s ease-out;
}

.accordion p {
  color: #333;
  margin: 0 0 10px;
}

.accordion h3 {
  color: #542437;
  padding: 0;
  margin: 10px 0;
}


/* Vertical */

.vertical ul li {
  overflow: hidden;
  margin: 0 0 1px;
}

.vertical ul li label {
  padding: 10px;
}

.vertical [type=radio]:checked ~ label,
.vertical [type=checkbox]:checked ~ label {
  border-bottom: 0;
}

.vertical ul li label:hover {
  border: 1px solid #542437;
  /* We don't want the border to disappear on hover */
}

.vertical ul li .content {
  height: 0px;
  border-top: 0;
}

.vertical [type=radio]:checked ~ label ~ .content,
.vertical [type=checkbox]:checked ~ label ~ .content {
  height: 100px;
  border: 1px solid #542437;
}
<div class="accordion vertical">
  <ul>
    <li>
      <input type="radio" id="radio-1" name="radio-accordion" class="js-uncheck" checked="checked" />
      <label for="radio-1">Label radio-1</label>
      <div class="content">I'm the content of radio-1 1111111 1111111 1111111 1111111 1111111 1111111 1111111 1111111 1111111 1111111 1111111 1111111 1111111 1111111 1111111</div>
    </li>
    <li>
      <input type="radio" id="radio-2" name="radio-accordion" class="js-uncheck" />
      <label for="radio-2">Label radio-2</label>
      <div class="content">I'm the content of radio-2 2222222 2222222 2222222 2222222 2222222 2222222 2222222 2222222 2222222 2222222 2222222 2222222 2222222 2222222 2222222</div>
    </li>
    <li>
      <input type="radio" id="radio-3" name="radio-accordion" class="js-uncheck" />
      <label for="radio-3">Label radio-3</label>
      <div class="content">I'm the content of radio-3 333333 333333 333333 333333 333333 333333 333333 333333 333333 333333 333333 333333 333333 333333 333333 333333 333333 333333</div>
    </li>
  </ul>
</div>

Comments