Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fire an event on input.checked=true/false _without_ jQuery

Consider the following code (http://jsfiddle.net/FW36F/1/):

<input type="checkbox" onchange="alert(this.checked)">
<button onclick="document.getElementsByTagName('input')[0].checked=!document.getElementsByTagName('input')[0].checked;">toggle</button>

If you click the checkbox, you get an alert telling you if it's checked or not. Great. However, if you click the toggle button, the checkbox changes it's checked state but the onchange event is NOT fired.

Essentially, the onchange for a checkbox only fires if the user actually clicks the checkbox, not if the checkbox is changed via JavaScript. This is be true in IE, FF, and Chrome. It appears that this behavior is to specification also.

However, I really need some kind of event to fire if, for any reason, the checkbox's checked state changes. Is this possible?

Oh yeah, and jQuery is not allowed. And please no setTimeout/setInterval based solutions either...

Update: Also, I should make it clear that the code above is for illustration only. In the real code, we need to ensure the state of the checkbox is checked or unchecked -- not just toggle it. Perhaps this would be better code to illustrate that:

<input type="checkbox" onchange="alert(this.checked)">
<button onclick="document.getElementsByTagName('input')[0].checked=true;">check</button> 
<button onclick="document.getElementsByTagName('input')[0].checked=false;">un check</button>

Moreover, there may be code in other areas we don't fully control, which might do a simple .checked=true/false -- we'd like to make sure we see that also.

like image 339
jwl Avatar asked May 17 '12 14:05

jwl


1 Answers

The existing answers work just fine, even with your update. Just be smart about it and don't call click if you don't need to. Also, please don't use inline JS. That was OK 10 years ago.

<input type="checkbox" onchange="alert(this.checked)">
<button id='check'>check</button> 
<button id='uncheck'>uncheck</button>

document.getElementById('check').onclick = function() {
   if (!this.checked) {
      this.click();
   }
}

If you need to be modified when a script changes the value, in Firefox, you can use https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/watch

Example here http://jsfiddle.net/PPuZ8/

// In FF $ is a shortcut for document.getElementById
// It doesn't fire when set from the UI, you have to use a regular handler for that
$('cb').watch("checked", function(){
   console.log('Checked state changed from script', arguments);
   return true;
});

For IE you can use onpropertychange http://msdn.microsoft.com/en-us/library/ie/ms536956(v=vs.85).aspx (Thanks to jivings for the reminder)

Example: http://jsfiddle.net/PPuZ8/1/

document.getElementById('cb').onpropertychange = function() {    
    if (event.propertyName == 'checked') {
       console.log('Checked state changed onproperty change');    
    }
};

For other browsers, you have to poll using setInterval/setTimeout

like image 169
Juan Mendes Avatar answered Sep 28 '22 06:09

Juan Mendes