Sam Slater
Sam Slater

Reputation: 13

jQuery Parent Child Element Click Event

My HTML looks something like this (unfortunately it cannot change because it is being rendered with the CMS I am using):

<li>
<input id="cb1" type="checkbox">
<label for="cb1">
<div>Some Other Content</div>
<div class="pledge">Click to Pledge</div>
</label>
</li>

The jQuery.

$("div.pledge").click(function() {

  var checkboxlabel = $(this).parent("label");

  $("input[for=checkboxlabel]").attr('checked', !$checkbox.attr('checked'));

});

Using this code will toggle the checkbox if I click anywhere inside the label. What I need is for the action to only take place when I click the <div class="pledge"> element. I suspect that .stopPropagation(); will help me here but I have not been able to get it to work properly.

Here is another shot that seems to be accomplishing the same think:

$("div.pledge").click(function() {

  $("input[for=' + this.parent("label").attr("id") + ']").attr('checked', !$checkbox.attr('checked'));

});

Upvotes: 1

Views: 3884

Answers (5)

nnnnnn
nnnnnn

Reputation: 150010

Reading between the lines, it seems to me that the following will achieve your desired result without any JS:

<li>
<input id="cb1" type="checkbox">
<div>
<div>Some Other Content</div>
<label for="cb1">Click to Pledge</label>
</div>
</li>

http://jsfiddle.net/nnnnnn/VqmBb/

This displays "Some Other Content" and "Click to Pledge" next to the checkbox, but as you can see with my demo only the "Click to Pledge" part checks/unchecks the box when clicked.

I've swapped your label and the "pledge" div around, and made use of the label's for attribute to associate it with the checkbox so that it will automatically check/uncheck it. (Though now the outer div doesn't actually do anything and could be removed unless you need it for styling.)

Regarding your JS, the following line has some problems:

$("input[for=checkboxlabel]").attr('checked', !$checkbox.attr('checked'));

First, your selector "input[for=checkboxlabel]" seems to be trying to use the checkboxlabel variable declared on the line before, but what you've actually done is just include a string that happens to include the text "checkboxlabel". So that won't select any elements in your html because you have no "input" element with a "for" attribute equal to the string "checkboxlabel". Also you've got a variable $checkbox that isn't defined anywhere.

UPDATE: OK, the following should work for your updated html (it worked for me). The problem with your existing JS code, apart from the fact that you are trying to use a variable, $checkbox, that isn't declared, is that you are trying to bind your click handler to the "pledge" div which means you haven't done anything to handle clicks on other parts of the label. Given that you specifically want to stop clicks on other parts of the label I'd suggest that you attach the .click() handler to the label - clicks on the label's children will bubble up to the label's click handler, so then you can test whether the element that was clicked was the one with class "pledge". If not return false to cancel the default behaviour for a label click, but if it is the "pledge" element do nothing and let the default happen:

$("div.pledge").parent("label").click(function(e) {
    if (!$(e.target).hasClass("pledge"))
        return false;
});

(Note I'm selecting the parent of "div.pledge" rather than just saying $("label").click() so that this processing doesn't get attached to all labels.)

If you don't like that I think mgibsonbr's answer is a nice alternative.

Upvotes: 4

mgibsonbr
mgibsonbr

Reputation: 22007

If I understood correctly, when you say "you can't change the HTML", you mean only the HTML that is generated by the server, right? But can you change it in the client side, using JavaScript?

jQuery(document).ready(function($) {
    $('label[for="cb1"]').removeAttr("for");
    $("div.pledge").click(function() {
        $(this).parent().prev().attr("checked", function(index,oldValue) {
            return !oldValue;
        });
    });
});

This way the label won't have a for anymore, and the div click is handled manually.

Upvotes: 1

ShankarSangoli
ShankarSangoli

Reputation: 69905

Move checkbox inside the label element. You don't need any js and even id or for attribute is not required for input and label element. Try this.

<label>
    <input type="checkbox" />
    <div>Some Other Content</div>
    <div class="pledge">Click to Pledge</div>
</label>

Demo

Upvotes: 0

elclanrs
elclanrs

Reputation: 94101

Your code, both HTML and JavaScript are invalid.
<label> is an inline element which can't have block elements inside such as <div>.
Then, your JS code is missing some ; (I see you added them). Also, this makes no sense:

$("input[for=checkboxlabel]").attr('checked', !$checkbox.attr('checked'))

This should work. Notice the new html tags and the proper jQuery code:

html:

<li>
    <label>Something that describes this checkbox</label>
    <input id="check" type="checkbox">
    <p>Some Other Content</p>
    <a href="#" id="pledge">Click to Pledge</a>
</li>

jQ:

$('#pledge').click(function()}{ $('#check').prop('checked', true); });

Upvotes: 0

akhaku
akhaku

Reputation: 1157

You're not going about this the right way - you need to specify the 'for' attribute in your label and set it to the id of the checkbox you're assigning it to like so:

<label for="checkbox_id">Label-text</label>
<input type="checkbox" id="checkbox_id" />

This will check/uncheck the checkbox when you click the label. All the points made by @elclanrs above hold too, the html and js are invalid.

Upvotes: 0

Related Questions