Dan
Dan

Reputation: 11079

DOM/jQuery events propagation differences between input types

As we know, returning false from a DOM event handler will stop the propagation of the event. But I recently discovered that the behavior of different elements varies with respect to this event. For example, consider the following:

<div id="container">
   <input type="checkbox" name="foo" value="1" /> Check me!
   <br />
   <select>
      <option>1</option>
      <option>2</option>
      <option>3</option>
   </select>
   <br />
   <input type="text" size="30" />
</div>

The surrounding container has a click handler that returns false:

$('#container').click(function(e) {
    $('#clicks').append('<span>clicked</span>');
    return false;
});​

Within the div, I can still click on the text box and enter text, and can still click on the dropdown to change its value. But clicking on the checkbox does nothing (actually, that's not quite true - it checks the box, fires the handler, then unchecks it). jsfiddle here: http://jsfiddle.net/4ncaq/

This behavior is consistent across browsers so I assume it's by design. But what exactly is the rule that's at work here? How can I know how other kinds of elements might behave in this type of scenario?

Upvotes: 4

Views: 923

Answers (2)

Bruno Silva
Bruno Silva

Reputation: 3097

When you click an element, the event will continue propagating the event until some handler decides to cancel the propagation. In this case, when you click the checkbox, it will raise the event for the <input> first and then propagate to #container where you are stopping propagation.

If you want to cancel the propagation from input elements such as checkboxes or textareas you should bind to their click event and stop propagation at that point.

Edited

return false also cancels the default action for the original target element. Checkboxes, links, radio buttons are some of the elements where the default click action is cancelable. The default action for the click event in a checkbox toggles the value of the checkbox while there is no default click action for the select which means it does not get cancelled.

I've tried to find a list of default actions without luck but you can check the links at Is there a standard resource for the "default action" of HTML elements?.

Upvotes: 2

Tjkoopa
Tjkoopa

Reputation: 2378

What you are seeing is propagation, events 'bubble' up the DOM, so when you click your checkbox it is actually firing the click event on #container (as well as any events you might have bound to the input or other parent elements).

Using return false like this is ambiguous because it is doing 3 things at once, when you most likely only want it to do one. It prevents the default functionality, halts propagation and stops further execution.

It is better practice to be specific and use the methods from the event object to prevent the default action or stop bubbling.

event.preventDefault() will stop things like loading the href from an anchor click, stopping a checkbox from being checked etc.

event.stopPropagation() will cancel propagation, this is useful for situations like your example - http://jsfiddle.net/4ncaq/1/

The other problem with return false is that it may not be executed, a common mistake I see people make in jQuery is having a click event on an anchor with an $.ajax() request followed by return false to stop the browser from loading the linked page. In this scenario, if there is an error coming from ajax() (not a response error, a jQuery error - usually a misspelt param or something) it will never hit return false; and the browser will load the linked page. Using e.preventDefault() entirely removes this problem.

Upvotes: 4

Related Questions