Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IE does not fire 'Change' event on indeterminate checkbox when you click on it

i have a tri-state checkbox and i need the change event to be fired when the user clicks on it but the IE won't fire it when the checkbox's state is on "INDETERMINATE" (browser bug maybe?).
As work around for IE i could trigger the change event programmatically but this doesn't work for my case because i need to know if the event was fired because the user actually clicked on it.

Fiddle here / Test on IE and Chrome

<label for="cb">
  <input id="cb" type="checkbox" />
   click me
</label>

var checkbox = document.getElementById("cb");
checkbox.indeterminate = true;
$('#cb').change(function(){alert('Change Event')});

I have read this article https://github.com/jquery/jquery/issues/1698 and How to deal with browser differences with indeterminate checkbox but i could find a specific resolution for my case.

Any ideas how to fix this?

Thank you in advance.

like image 509
Jero Franzani Avatar asked Nov 04 '15 13:11

Jero Franzani


1 Answers

Checkbox inputs can only have two states: checked or unchecked. The indeterminate state is visual only and it masks the real state of the checkbox.

The first time you click on a checkbox that has its indeterminate set to true will simply change it to false and the checkbox will show its real state. For that reason, the change from "indeterminate" to either "checked" or "unchecked" is not a change in the real state and it does not trigger the onchange event.

Interestingly, the only browser that implements this behaviour correctly is IE. You can test this in IE and other browsers:

document.getElementById("cb1").indeterminate = true;
document.getElementById("cb2").indeterminate = true;
<label for="cb1"><input id="cb1" type="checkbox" checked="checked" />I'm actually checked</label>
<label for="cb2"><input id="cb2" type="checkbox" />I'm actually unchecked</label>

In IE, the first click will reveal the real state of the checkbox. In Chrome, it will change the real state to the other real state.

Although IE implementation is the correct one technically, the implementation of the other browsers is the more practical one. For most applications, the visual "indeterminate" state needs to be considered as a real state just like the "checked" and "unchecked" which means that the change from any of those 3 states to another one should trigger the onchange event.

How to solve this? Well, the most obvious answer can be to register a one-time click event for IE only, like the one suggested by https://github.com/jquery/jquery/issues/1698.

// As other browsers already fire the change event,
// only bind the listener for IE.
if ( window.navigator.userAgent.indexOf('Trident') >= 0 ) {
    $(function(){
        // Pointer events in IE10, IE11 can be handled as mousedown.
        $(document).on('mousedown', 'input', function(){
            // Only fire the change event if the input is indeterminate.
            if ( this.indeterminate ) {
                $(this).trigger('change');
            }
        });
    });
}

However, the more generic approach given by A. Wolff is probably a better approach as it is always better to avoid browser-specific code whenever possible:

var checkbox = document.getElementById("cb");
checkbox.indeterminate = true;
$('#cb').one('click', function () {
    if (!this.checked) {
        this.checked = true;
        var evt = document.createEvent("HTMLEvents");
    evt.initEvent("change", false, true);
    this.dispatchEvent(evt);
    }
}).change(function (e) {
    console.log(e);
    alert(e.originalEvent)
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label for="cb">
    <input id="cb" type="checkbox" />click me
</label>
like image 71
Racil Hilan Avatar answered Oct 20 '22 06:10

Racil Hilan