NullVoxPopuli NullVoxPopuli - 5 months ago 28
jQuery Question

How do you propagate a click to child elements if the parent element has preventDefault?

UPDATE:
this doesn't work in the latest version of firefox (15.0.1):
http://jsfiddle.net/DerNalia/NdrNV/5/

clicking the checkbox navigates to google... but it shouldn't :(

it appears that adding e.stopPropagation() doesn't help / doesn't work.




playarea: http://jsfiddle.net/DerNalia/NdrNV/1/

What I'm trying to do:
When I click the checkbox that is next to (but actually is a child element of) the anchor, it should change states, and also change the state of the "other" checkbox.

But because the anchor has e.preventDefault() invoked, the checkbox never gets checked.

Here is my markup

<a href="#">Link Name <input class="home" type="checkbox"/></a>
<br />
Sync'd checkbox: <input class="other" type="checkbox" />​


Here is some the troubled jquery

$(function() {
$("input.home").click(function() {
$("input.other").click();
});

$("a").click(function(e) {
e.preventDefault();
// prevent default so we can do some ajaxy things instead of follow the href
});
})​


So, how do I change the jQuery click action on the anchor tag such that clicks propagate to child elements (but I can still do ajaxy things without the browser following the href of the anchor tag)?

Is there a way to do this without changing the markup? (the way it is now makes semantic sense for my web application)

Answer

It doesn't work because event.preventDefault would cancel the event.

Using e.preventDefault on click on the checkbox which is wrapped inside <a> would not let you change the checkbox state.

A workaround I could think of is to set the checkbox state in a different context so that the e.preventDefault code is ineffective.

DEMO: http://jsfiddle.net/NdrNV/10/

$(function() {
    $("input.home").click(function() {
        $("input.other").click();
    });

    $("a").click(function(e) {
        e.preventDefault();

        var setCheckbox = function() {
            var checkbox = $(e.target)[0];
            checkbox.checked = checkbox.checked?false:true;
        }

        if ($(e.target).is(':checkbox')) {
            setTimeout(setCheckbox, 0);
        }

    });
})

Note: This is a workaround.