tags:

views:

25

answers:

2

I have a series of content and header divs to display some data. In addition each header has a checkbox.

<div id="content-1">
    <div class="head"><input type="checkbox" name="check-1"/> Header</div>
    <div class="content">Content</div>
</div>
<div id="content-2">...</div>
<div id="content-3">...</div>

I use to following jQuery to show/hide a content div by clicking on the respective header div.

$(".head").toggle(
    function(){ $(this).nextAll().slideDown('200'); },
    function(){ $(this).nextAll().slideUp('200'); }
);

The problem is that clicking the checkbox shows/hides the content div and the checkbox can not be checked/unchecked. I want the content toggle to only occur when clicking the head div, and for the checkbox to function as normal.

Any help greatly appreciated.

A: 

The problem you're experiencing is due to the fact you have two click events for only one handler. Your two events are: clicking the head-div and clicking a checkbox WITHIN that head-div. As you have only specified one handler, bot events will be delegated to that one (as your checkboxes are contained by the head-div) and thus will toggle both.

You need to add a handler, which will act more specifcly. With a selector like this:

$(".head :checkbox").click(function(event){
$(this).attr('checked','checked');
});

EDIT: not tested, but I think this should do the trick.

Anzeo
A: 

You can check if $(event.target).is('.head') in order to do the toggle.

$('.head').toggle(
    function(e){ $(e.target).is('.head') &&
                     $(this).nextAll().slideDown('200') },
    function(e){ $(e.target).is('.head') &&
                     $(this).nextAll().slideUp('200') }
)

A cleaner option would be to check if event.target and this are different and then stop the event propagation. Otherwise, do the sliding.

$('.head').toggle(
    function(e){ e.target !== this ? e.stopPropagation()
                                   : $(this).nextAll().slideDown(200) },
    function(e){ e.target !== this ? e.stopPropagation()
                                   : $(this).nextAll().slideUp(200) }
)

I've not tested it, thoughit seems to me a reasonable solution.

UPDATE:

In fact, toggle calls preventDefault, so the solution should be something in this lines:

$('.head').bind('click', function(e){
    e.target !== this
        ? e.stopPropagation()
        : $(this).nextAll().slideToggle(200)
});
xPheRe
Thank you. Both solutions exclude the checkbox from the toggle function. However, the checkbox no longer functions correctly.
Craig552uk
If I remember correctly, $.toggle does a call to preventDefault, so this is preventing the checkbox for being check. I'd suggest to move to bind('click') and use slideToggle instead.
xPheRe