Silverstaryu Silverstaryu - 11 months ago 105
Javascript Question

Javascript event listener on a checkbox

I'm trying to hide/show checkboxes based on a button click('send email' or 'cancel'). The button hide show works, but I also added an event listener to the checkboxes to change the button text to 'confirm' if any check box was active. It seems there's a delay in when a checkbox registers as 'checked' and I can't think of or find a better way to check it. Any help would be greatly appreciated!



var checker = document.getElementById("emailer");
var radios=document.querySelectorAll(".radioEmail+label");
for (var i=0; i<radios.length; i++){
radios[i].addEventListener('click',
function(){
var checkingChecks = document.querySelectorAll(".radioEmail:checked").length;
if (checkingChecks>0)
{document.getElementById("emailer").className="confirm";}
else{document.getElementById("emailer").className="cancel"}
}) };


document.getElementById("emailer").addEventListener('click',
function(){
if (checker.getAttribute('class')=='emailer'){
checker.className="cancel";
for(var i = 0;radios.length>i;i++){radios[i].style.display="inline-block"}
}
else if (checker.getAttribute('class')=='cancel'){

for(var i = 0;radios.length>i;i++){radios[i].style.display="none"} checker.className="emailer"; }
});

input[type=checkbox].radioEmail + label{display:none}
.emailer:after{content:"Send Mass Email";}
.confirm:after{content:"confirm"}
.cancel:after{content:"cancel"}
input[type=checkbox] + label{
cursor:pointer;
width : 1em;
font-size : 0.875em;
line-height : 1em;
color : white;
text-align : center;
font-weight : bold;
height : 1em;
margin : 0.25em 0.5em 0.25em 0.25em;
border : 0.0625em solid #000066;
border-radius : 0.25em;
background : white;
vertical-align : bottom;
transition: ease-in-out 0.3s;
-webkit-transition: ease-in-out 0.3s;}
input[type=checkbox].radioEmail + label{display:none}
input[type=checkbox]:checked + label{background:#000066}
input[type=checkbox]:checked + label:before{content: '✓'}
input:hover + label{background:rgba(0,0,102,0.5)}
input[type=checkbox]{
width : 2em;
margin : 0;
padding : 0;
font-size : 1em;
opacity : 0;}

<button id = "emailer" class='emailer' ></button>
<input class="radioEmail" id="option" type="checkbox" name="field" value="option">
<label for="option"></label>

<input class="radioEmail" id="option2" type="checkbox" name="field" value="option">
<label for="option2"></label>





jsfiddle example

Answer Source

Your radios variable contains a collection of the radio labels:

var radios = document.querySelectorAll(".radioEmail+label");

When a label is clicked, the click event is triggered before the input value actually changes.

I would normally recommend putting inputs within their labels. However,you have a lot of input + label CSS that would break, and I don't know what other code you might have that could also break.

A quick solution given your current HTML and CSS would be to check the radio buttons within a setTimeout():

radios[i].addEventListener('click',
  function() {
    setTimeout(function() {
      var checkingChecks = document.querySelectorAll(".radioEmail:checked").length;
      if (checkingChecks > 0) {
        checker.className = "confirm";
      } else {
        checker.className = "cancel";
      }
    });
  }
)

Working Fiddle