Question

Imagine something like this.

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Testing event bubbling</title>
    <script src="js/jquery/jquery-2.0.0.js"></script>
    <script>
        $(document).on('click', 'div', function(e) {
            e.preventDefault();
            console.log('Clicked');
            return true;
        });
        $(document).on('submit', 'form', function(e) {
            e.preventDefault();
            console.log('Submitted');
        });

    </script>
</head>
<body>
<form>
    <div><div><div>
        Click this.
        <input type="submit">
    </div></div></div>
</form>

</body>
</html>

Now when you click on the submit button, the click event is captured and propagated down to all the DIVs and you see 'Clicked' three times. Whats peculiar to me, is that this seems to skip over the form submit event. If I remove the Click binding, the submit event gets triggered correctly. Is there a way around without manually triggering submit() on the form? I know I can make the click event more specific so it doesn't apply to the submit button, but... I have a weird usecase.

What am I getting wrong here? If one event is triggered, does that mean all other events of lower priority are ignored?

Was it helpful?

Solution

e.preventDefault() is used to prevent the default action of some controls. For example, if you click a link, it will try to load its href, if you click a submit button, it will try to submit the form. So, preventDefault is used to prevent those actions.

If you don't want the submit to "interrupt", in other words, if you want to submit the form, remove the preventDefault from your click event.

Now, second point, the click event is propagated 3 times. You have something like:

<div>
    Div 1
    <div>
        Div 2
    </div>
</div>

And you are binding the onclick method to every <div> on the page. So, 3 divs, 3 onclicks. If all divs are overlapped then when you click the inner one, you are clicking it's parent div too, and so on. You can use stopPropagation() if you don't want the event to propagate to deeper divs (think of it as "layers" one over each other).

OTHER TIPS

You can use event.stopPropagation() to stop the event bubbling to other elements. There's no need to call e.preventDefault() on click here - it stops the default action being executed and that's not what you're after.

You can check whether the click happend in an input field

$(document).on('click', 'div', function(e) {
    if(!$(e.target).is('input')){
        e.preventDefault();
    }  
    console.log('Clicked');
    return true;
});
$(document).on('submit', 'form', function(e) {
    e.preventDefault();
    console.log('Submitted');
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top