Checkbox button doesn't work when you click quickly multiple times

I have a jsfiddle here: http://jsfiddle.net/zAFND/616

Now if you open the script in IE (I am using IE9) and firefox, if you double click on the checkbox button, it will enable it but not disable it. But if you open it in opera, safari and chrome, it works great if you double click or quickly press the button.

My question is how to allow quick clicks to work properly in firefox and IE9?

code:

HTML:

<div id="ck-button"><label>
<input type="checkbox" name="options[]" id="optionA" value="A" /><span>A</span></label>
</div>

      

CSS

#ck-button {
    margin:8px;
    background-color:#EFEFEF;
    border:1px solid #D0D0D0;
    overflow:auto;
    float:left;
    position: relative;
}

#ck-button label {
    float:left;
    width:4.0em;
    cursor:pointer;
}

#ck-button label span {
    text-align:center;
    padding:3px 0px;
    display:block;
}

#ck-button label input {
    position:absolute;
    top:-20px;
}

#ck-button input:checked + span {
    background-color:green;
    color:white;
}

      

Jquery / JavasScript:

 $(document).ready(function(){
            $("body").css("-webkit-user-select","none");
            $("body").css("-moz-user-select","none");
            $("body").css("-ms-user-select","none");
            $("body").css("-o-user-select","none");
            $("body").css("user-select","none");
    });

      

+3


source to share


2 answers


This is a bug in Firefox. See Bug 608180 - double / quick click on a checkbox label does not work as expected

IE has historical reasons (but fixed in later versions), a listenable event model that skips events twice, mousedown

and click

. See bug 263 - Beware of DoubleClick in IE .

I created a plugin that fixes some bugs in jQuery UI button widgets and also working on Firefox bug recently, it shouldn't be hard to adapt it to your non jQuery UI buttons.

Extracted the important part and adapted it for nested checkboxes inside label

s:

(function () {
    var mdtarg, //last label mousedown target
        mdchecked, //checked property when mousedown fired
        fixedLabelSelector = '.fixedLabelCheckbox'; //edit as you see fit
    $(document).on('mousedown', fixedLabelSelector, function (e) {
        //only left clicks will toggle the label
        if (e.which !== 1) return;
        mdtarg = this;
        mdchecked = this.control ? this.control.checked : $(this).find('input')[0].checked;
        //reset mdtarg after mouseup finishes bubbling; prevents bugs with
        //incorrect mousedown-mouseup sequences e.g.
        //down IN label, up OUT, down OUT, up IN
        $(document).one('mouseup', function () {
            mdtarg = null;
        });
    }).on('mouseup', fixedLabelSelector, function (e) {
        if (e.which !== 1) return;
        if (mdtarg === this) {
            var ch = this.control || $(this).find('input')[0];
            //the click event is supposed to fire after the mouseup so
            //we wait until mouseup and click finish bubbling and check if it
            //had the desired effect
            setTimeout(function () {
                if (mdchecked === ch.checked) {
                    //else patch it manually
                    ch.checked = !ch.checked;
                    $(ch).change();
                }
            }, 0);
        }
    });
}());

      

Fiddle tested in Firefox.

You must add a class fixedLabelCheckbox

to all labels containing checkboxes that you want to fix with the code above.

It will work no matter where you put the script, and also sets dynamically added checkboxes if the label has an appropriate delegated class / selector.



Please note that if you are using other libraries this may not trigger jQuery related change handlers.

If you don't want to add additional classes to your markup, you can use this version (more code and less performance):

(function ($) {
    function getControl(lbl) { //fallback for non-HTML5 browsers if necessary
        return lbl.control || (lbl.htmlFor ? $('input[id="'+lbl.htmlFor+'"]')[0] : $(lbl).find('input')[0]);
    }
    var mdtarg, //last label mousedown target
        mdchecked; //checked property when mousedown fired
    $(document).on('mousedown', 'label', function (e) {
        //only left clicks will toggle the label
        if (e.which !== 1) return;
        var ch = getControl(this);
        if (!ch || ch.type !== 'checkbox') return;
        mdtarg = this;
        mdchecked = ch.checked;
        //reset mdtarg after mouseup finishes bubbling; prevents bugs with
        //incorrect mousedown-mouseup sequences e.g.
        //down IN label, up OUT, down OUT, up IN
        $(document).one('mouseup', function () {
            mdtarg = null;
        });
    }).on('mouseup', 'label', function (e) {
        if (e.which !== 1) return;
        if (mdtarg === this) {
            var ch = getControl(this);
            //the click event is supposed to fire after the mouseup so
            //we wait until mouseup and click finish bubbling and check if it
            //had the desired effect
            setTimeout(function () {
                if (mdchecked === ch.checked) {
                    //else patch it manually
                    ch.checked = !ch.checked;
                    $(ch).change();
                }
            }, 0);
        }
    });
}(jQuery));

      

Fiddle

As you can see from the above code, this version should work with both the label attribute for

and nested inputs inside the label, without adding any additional markup.


About disabling selection: you can put user-select

in CSS as mentioned in your question, or if browsers that don't support user-select

also apply, apply this answer on all shortcuts you want to disable.

+3


source


You can add browser detection and then if IE or Firefox add an ondblclick

event
via JS to invert the checkbox.

You can't just install it unconditionally, as some browsers (Safari, Chrome) only transmit two click

and dblclick

, while others (IE, Firefox) only transmit one click

and one dblclick

. In the first case, two events click

will invert the field twice. In the latter case, only one event is triggered click

and, therefore, the field is only inverted once; To reduce this, you need to do dblclick

invert the field so that two clicks will invert it an even number of times.



Hope this helps!

0


source







All Articles