Dai
Dai

Reputation: 155035

Prevent other event-handlers from being run

My HTML form has this markup:

<fieldset>
    <legend>
        <label> <input type="checkbox" class="warnOnUncheck" /> Include the following data </label>
    </legend>
    <div class="fieldsetContent">
        <!-- and a bunch of <input type="text" /> here. -->
    </div>
 </fieldset>

I have two scripts that are called by DOM-ready:

  1. The first collapses the content of the fieldset when the checkbox is unchecked and shows the
  2. The second, shows a confirm() confirmation message when the checkbox is unchecked. If the user clicks "No" then the checkbox is re-checked.

The problem is that the first event handler is always called, so even if the user clicks "No" the fieldset content is still hidden.

Here's my (abridged) jQuery code (called during the DOM-ready event handler):

$("fieldset.collapseable legend input").change(function(event) {

    var localFieldsetContent = $(this).closest("fieldset").find("div.fieldsetContent");

    var checked = $(this).is(":checked");
    if( checked && localFieldsetContent.is(":visible") ) {
        // if checked and already visible, then skip entirely.
        return;
    }

    localFieldsetContent.slideToggle(200);
);

$("input[type=checkbox].warnOnUncheck").change( function(event) {

    if( !this.checked ) {

        var message = $(this).data("warnMessage");

        var confirmed = confirm( message );
        if( !confirmed ) {

            this.checked = true;
            event.stopImmediatePropagation();
        }
    }

} );

I thought that event.stopImmediatePropagation(); would work, but it doesn't.

How can I prevent the fieldset from being collapsed when confirmed is false?

Upvotes: 1

Views: 200

Answers (3)

LeGEC
LeGEC

Reputation: 51780

Your immediate problem : the first handler is executed before the second one (the one with the confirm) has a chance to call stopImmediatePropagation. Bind your handlers in the reverse order and it should work :

$("input[type=checkbox].warnOnUncheck").change( function(event) {

    if( !this.checked ) {

        var message = $(this).data("warnMessage");

        var confirmed = confirm( message );
        if( !confirmed ) {

            this.checked = true;
            event.stopImmediatePropagation();
        }
    }

} );

$("fieldset.collapseable legend input").change(function(event) {

    var localFieldsetContent = $(this).closest("fieldset").find("div.fieldsetContent");

    var checked = $(this).is(":checked");
    if( checked && localFieldsetContent.is(":visible") ) {
        // if checked and already visible, then skip entirely.
        return;
    }

    localFieldsetContent.slideToggle(200);
);

However, I find it pretty unsafe to split this behaviour over two functions.

I would merge the two handlers into a single one :

$("input[type=checkbox].warnOnUncheck").change( function(event) {
    var confirmed = true;
    if( !this.checked ) {
        var message = $(this).data("warnMessage");

        var confirmed = confirm( message );
        if( !confirmed ) {
            this.checked = true;
        }
    }

    if (confirmed) {
        var localFieldsetContent = $(this).closest("fieldset").find("div.fieldsetContent");
        localFieldsetContent.slideToggle(200);
    }
} );

Here is a jsfiddle


If you can't merge the handlers, you can bind the "collapsing" function to some custom event, and have th "click" event on the checkbox trigger it.

See this updated jsfiddle :

$("input[type=checkbox].warnOnUncheck").change( function(event) {
    var confirmed = true;
    if( !this.checked ) {
        var message = $(this).attr("data-warnMessage");
        confirmed = confirm( message );
        if( !confirmed ) {
            this.checked = true;
        }
    }

        if (confirmed) {
            $(this).trigger("myToggleVisibility");
        }
} );

$("fieldset.collapseable").on("myToggleVisibility", function(event) {
    $(this).find('.fieldsetContent').slideToggle(200);
});

Upvotes: 1

Rohan Kumar
Rohan Kumar

Reputation: 40639

Try this:

$("input[type=checkbox].warnOnUncheck").change( function(event) {    
    if ( event.isImmediatePropagationStopped() ) {
         return false;
    }
    if( !this.checked ) {    
        var message = $(this).data("warnMessage");    
        var confirmed = confirm( message );
        if( !confirmed ) {    
            this.checked = true;
            event.stopImmediatePropagation();
        }
    }    
});

Read http://api.jquery.com/event.isImmediatePropagationStopped/

Upvotes: 0

Devang Rathod
Devang Rathod

Reputation: 6736

use event.preventDefault();

OR

if(!confirmed){
    this.checked = true;
    return false;
}

Upvotes: 0

Related Questions