.Click () anatomy or single issue history

    Good day, comrades.

    Faced one problem in jQuery and now I want to find out: is everything as always (the fool himself and goodbye to the remnants of karma) or is it such a feature of jQuery?

    Suppose there is the following HTML:



    * This source code was highlighted with Source Code Highlighter.


    The operation scheme is extremely simple: the #chb checkbox controls the activity of the #txt text field (when checked -! Disabled and vice versa), and the #dis checkbox disables (disabled = "disabled") the #chb checkbox and switches its state.

    Here is a sample code:
    $("#chb").click(function() {
        $("#txt").attr("disabled", ! this.checked);
    });

    $("#dis").click(function() {
        if ( $("#chb").attr("checked") )
        {
            $("#chb").click();
        }

        $("#chb").attr("disabled", this.checked);
    });

    * This source code was highlighted with Source Code Highlighter.


    It would seem nothing unusual?

    By clicking on #chb, the text field will turn on / off as it should. But clicking on #dis, we get only disabling #chb. But what about #txt? After all, the execution of $ ("# chb"). Click () should guarantee that it will also be disabled. (If not, correct me, please, and give a link to an explanatory article. Thank you.)

    As the test showed, there is some inconsistency in the sequence of actions.

    When clicking on the checkbox with the mouse:
    1) switch checked;
    2) execute click-hung handlers.

    When programmatically calling click ():
    1) execute handlers hung on a click;
    2) switch checked.

    (you can check by hanging on click alert)

    That is, the same(it would seem) the operation causes different sequences of actions.

    Now it’s clear why #txt isn’t turned off: at the moment the handler is running (checking whether the control checkbox is checked?), The checkbox is still checked.

    So what to do?



    Since we know what is happening, then we can solve the problem.

    Everything would be just great if somewhere not only the current state of the element (checked) was stored, but also the state change (+1 - checked changed from false to true, -1 - from true to false). Unfortunately, as far as I know, jQuery does not follow this.

    A bit of equipment to understand what follows. When you click on an element, three events are sequentially generated:
    1) mousedown
    2) mouseup
    3) click Click
    is responsible for switching the state of the checkbox. And since it does not behave the way we want, we will turn it off completely and will use mouseup.

    This is how I see the solution:
    $("#chb").click(function(e) {
        // отключаем стандартную обработку клика, сами справимся
        e.preventDefault();
    });

    $("#dis").click(function() {
        if ( $("#chb").attr("checked") )
        {
            $("#chb").mouseup();
        }

        $("#chb").attr("disabled", this.checked);
    });

    $("#chb").mouseup(function() {
        // имитация клика — переключение
        this.checked = ! this.checked;

        $("#txt").attr("disabled", ! this.checked);
    });

    * This source code was highlighted with Source Code Highlighter.


    Thus, from mouseup we made click with predictable behavior.

    I apologize for the writing style, it’s hard to read, but I don’t know how to write differently. I hope someday this is useful to someone.

    And in the comments I will be glad to explain such an unusual phenomenon, criticism and simpler solutions (if they are required at all). Thanks for attention.

    upd: Yeah's Habraiser suggested a triggerHandler function that can call event-hung handlers without triggering standard behavior. Then you can make it easier by changing a couple of lines in the initial version:

    $("#dis").click(function() {
      if ( $("#chb").attr("checked") )
      {
        // сделаем поведение однообразным: сначала снимем галочку, а затем вызовем обработчики
        $("#chb").attr("checked", false);
        $("#chb").triggerHandler('click');
      }

      $("#chb").attr("disabled", this.checked);
    });

    * This source code was highlighted with Source Code Highlighter.

    And no mouseup. But the question remains of the reasons for this behavior.


    Also popular now: