javascriptjqueryjquery-callback

This Click Function is Executing Even with Proper Callbacks


I can't for the life of me figure why these functions are executing. I understand the proper syntax for binding a function is as follows.

$('#idOfThing').bind('click', foofunc);
function foofunc() { ///do things }

However, something is going on with my code. Either one of these binds/unbinds work, or the other ones don't. I have tried every combination I can think of.

$(window).on("load", function () {
         $('#divContactSticky').addClass("bottomDiv");
         $('#divContactSticky').bind('click', FillScreen);

         });

        var FillScreen = function() {
            $('#divContactSticky').unbind("click", FillScreen);
            $('#divContactSticky').css('height', '90vh');
        };

        function CancelForm() {
                $('#divContactSticky').css('height', '77px');
                $('#divContactSticky').bind('click', function () {
                    FillScreen();
                });
        }

The point of this is to have a div fixed to the bottom of the window. When the user clicks on that div. The ViewPort will fill with the div. Inside this div is a Cancel button. It is html and CancelForm() will execute on click. Obviously once the div is clicked, I have to unbind the function, or FillScreen will execute with every form input click etc.

I have tried making the CancelForm() bind function the same as the load callback type. I have tried everything. I have made FillScreen = to an anonymous function. I've tried almost every combination of return types I can think of. Where am I going wrong?

Edit:

CancelForm has received a makeover, and the issue persists. CancelForm as following executes FillScreen immediately.

function CancelForm() {
            $('#divContactSticky').css('height', '77px');
            $('#divContactSticky').bind('click', FillScreen);

    }

**Edit 2: **

@Radicate had partially the correct answer. There is a major difference between bind and on/off. The code below is what finally worked.

$(document).ready(function () {
    $('.cancelb').click(function () {
        CancelForm();
    });
    $('#divContactSticky').click(FillScreen);
}
$(window).on("load", function () {
         $('#divContactSticky').addClass("bottomDiv");
         $('#divContactSticky').on('click', FillScreen);

         });

        var FillScreen = function() {
            $('#divContactSticky').off("click", FillScreen);
            $('#divContactSticky').css('height', '90vh');
        };

        function CancelForm() {
                $('#divContactSticky').css('height', '77px');
                $('#divContactSticky').on('click', FillScreen);
                    event.stopPropagation()
                });
        }

Solution

  • What you're experiencing is event propagation as the cancel button is inside the div.

    DOM events have two stages, capture and propagation - what we're dealing with in most cases (as it's mostly the default) is the propagation stage, in which the event travels up the DOM tree.

    So basically what we'll do is cancel the event when it triggers on the cancel button, before it is triggered on the div as well which would again resize our div to 90vh.

    In jQuery we'll do it with event.stopPropagation()

    Read about it here: https://api.jquery.com/event.stoppropagation/

    And if you want to learn more about the way events pass, I recommend you read this: https://www.kirupa.com/html5/event_capturing_bubbling_javascript.htm

    Another thing that was wrong with your code, as mentioned by @SLaks is the use of unbind - in which you tried to unbind an anonymous function instead of unbinding it just the way you bound it - so you'd just increment the amount of listeners on your div that would all trigger together.

    Anyhow, using unbind here is unnecessary as we want the listeners on both elements, we'll just cancel the event when needed.

    Enough talk, here's a working example:

    $(window).on("load", function() {
      $('#divContactSticky').addClass("bottomDiv");
      $('#divContactSticky').bind('click', FillScreen);
      $("button.cancel").click(function(){
    		CancelForm();
    		event.stopPropagation();
    	});
    
    });
    
    var FillScreen = function() {
      $('#divContactSticky').css('height', '90vh');
    };
    
    function CancelForm() {
      $('#divContactSticky').css('height', '77px');
    }
    .bottomDiv {
      color:red;
    }
    #divContactSticky{
      border:1px solid blue;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div id="divContactSticky">
      divContactSticky
      <button class="cancel">
      Cancel
      </button>
    </div>