views:

107

answers:

4

I have the following markup. I would like to add class_A to <p class="subitem-text"> (that holds the radio button and the label) when user clicks on the <input> or <label>.

If user clicks some other radio-button/label in the same group, I would like to add class_A to this radio-button's parent paragraph and remove class_A from any other paragraph that hold radio-buttons/labels in that group. Effectively, in each <li>, only one <p class="subitem-text"> should have class_A added to it.

Is there a jQuery plug-in that does this? Or is there a simple trick that can do this?

<ul>
<li>
    <div class="myitem-wrapper" id="10"> 
        <div class="myitem clearfix">
            <span class="number">1</span>
            <div class="item-text">Some text here </div>
        </div>
        <p class="subitem-text">
            <input type="radio" name="10" value="15" id="99">
            <label for="99">First subitem </label>
        </p>
        <p class="subitem-text">
            <input type="radio" name="10" value="77" id="21">
            <label for="21">Second subitem</label>
        </p>

    </div>
</li>

<li>
    <div class="myitem-wrapper" id="11"> 
        <div class="myitem clearfix">
            <span class="number">2</span>
            <div class="item-text">Some other text here ... </div>
        </div>
        <p class="subitem-text">
            <input type="radio" name="11" value="32" id="201">
            <label for="201">First subitem ... </label>
        </p>
        <p class="subitem-text">
            <input type="radio" name="11" value="68" id="205">
            <label for="205">Second subitem ...</label>
        </p>

        <p class="subitem-text">
            <input type="radio" name="11" value="160" id="206">
            <label for="206">Third subitem ...</label>
        </p>
    </div>
</li>
</ul>   
A: 

Like this:

$(':radio').click(function() {
    $(this).closest('ul').find('.subitem-text').removeClass('active');

    $(this).closest('.subitem-text').addClass('active');
});
SLaks
use `DIV` instead of `UL` `$(this).closest('div').find('.subitem-text')`
aSeptik
+1  A: 

You can do something like this:

  // find all the radio inputs inside a subitem-text
  $('.subitem-text input[type=radio]').bind('change', function() {
    // find our parent LI
    var $li = $(this).closest('li'); 
    // remove any "class_A" 
    $li.find('.class_A').removeClass('class_A');
    // find the subitem with the checked input and add "class_A"
    $li.find('.subitem-text:has(input[checked])').addClass('class_A');
  });

jsbin preview/demo

gnarf
Binds to every single radio in the document..? Kinda crappy..
danp
@danp - Seriously? -1 over a `$('input[type=radio]')` ?
gnarf
i hate downvoters! grrr! so +1 ;-)
aSeptik
Tell that to whichever joker decided to downvote my answer. Wasnt you?
danp
And, I'll stick to my guns, binding to every radio in the document really isn't a good idea.. ;)
danp
first of all i have never downvoted exept to the same person that have downvoted me cause he is kidding with me, second no one have said that you have downvoted! 3th and not least i will upvote to everyone that have received a downvote for nothing real important cause i'm batman! is a good answer for you!?
aSeptik
@danp - I down-voted your answer that didn't actually answer the question. Your (now deleted) answer did not handle xraminx's specification of only adding the class to one `p.subitem-text` per `li` - it only added the class to one `p.subitem-text` in the whole document. Not that I really care about having a down-vote, it just bugs me to see someone down-vote for retribution as opposed to the quality of the post. Binding to all radios in the document is not a "crappy" thing - although, using a more specific class based selector would be quicker, the HTML the OP provided didn't have that.
gnarf
This is what I ended up using:$('p.subitem-text').bind('change', function() { $(this).parent().find('p.subitem-text').removeClass('class_A'); $(this).parent().find('p.subitem-text:has(input[checked])').addClass('class_A');});
xraminx
@xraminix - you could tack `.filter(':has(input[checked])').addClass('class_A');` onto the first `find().removeClass()` and do it all in one chain :)
gnarf
@danp - My point is that the location of the event bind isn't that important, its the functionality of the event handler - searching within the parent `li` only - remove `class_A` - and add to the `.subitem-text` that has the checked input that the OP was curious how to write.
gnarf
@gnarf: super! :)
xraminx
humm, binding to 'change' did not work in IE so I am binding back to 'click'.
xraminx
@xraminx - Thats one of the reasons I prefer to bind `change` events to actual `input`s. You could still limit the selector by using `$('p.subitem-text input[type=radio]')`
gnarf
+2  A: 

DEMO: http://jsbin.com/ebaye3

since you are putting all inside P you can use it!

$(function($) {
    $('.subitem-text').click(function() {
        $(this).parent().find('.subitem-text').removeClass('class_A');
        if ( $(this).children(':radio').is(':checked') ) // for sake! ;-)
        $(this).addClass('class_A');
    });
   //you can also write it like this:

  $('.subitem-text :radio').click(function() {
    $(this).parent().parent().children().removeClass('class_A');
    if ( $(this).is(':checked') )
    $(this).parent().addClass('class_A');
   });

});
aSeptik
+1 for the clean technique - still doesn't take into account if the radio is actually checked or not, although I'm not sure if that matters to the OP..
gnarf
yes a little more check is not bad idea! i have just thinked that he is using label + radio so when it click on a label the radio will be checked too! so since it is on the <p> i'm assuming that if one click on te <p> is for check it! ;-)))
aSeptik
Will this allow the grouping behaviour the questioner was after?
danp
how your next questioner is structured? in anycase by just adding the id to group selector like #11 .subitem-text the problem is solved!
aSeptik
Thank you. I ended up using a mix of your answer and gnarf's. I did that extra check to make sure that the radio button is selected. find('.subitem-text:has(input[checked])').addClass('class_A'); Without that check, sometimes class_A would be assigned to unchecked radio buttons! I don't know who should get the points for the answer now! ;)
xraminx
Don't forget you can change a radio with tab and spacebar, not just clicks :)
gnarf
@gnarf: Yeah, you are right. I also changed "click" binding to "change" as per your answer.
xraminx
you can vote the person you want! important thing is that you have learned something as i'm learning each time i'm asking question here! ;-)
aSeptik
FYI - `$(this).addClass(...) is working with the input element not the p element.
istruble
@istruble: i think your firebug is not working well! ;-P
aSeptik
@aSeptik - You are right, it is working on the p element. The bouncing up from and then back down to the target `p` element + gnarf's bind to the input threw me off. You can rewrite your 2nd example `$(this).is(':checked').parent()\n.addClass(...)\n.siblings('.submit-item').removeClass(...);`
istruble
A: 

There is no set way to do this since it is dependent on the html in your document. The simplest way to do this is to bind to each of your radio input elements but you can also use event delegation and bind to the div.myitem-wrapper, li, parent ul or event body tag.

Just binding click handlers to each of the input elements we are interested in:

$("div.myitem-wrapper input[type=radio]").bind('change', function (event) {
    $(event.target).is(':checked').closest('p')
        .addClass('class_A')
        .siblings('p.subitem-text').removeClass('class_A');
});

Same thing but using event delegation to reduce the number of handlers to one. This can really speed things up if you find that you are binding to a large number of elements.

$("#id_of_the_parent_UL").bind('change', function (event) {
    var $target = $(event.target);
    if ($target.is('input[type=radio]:checked')) {
        $target.closest('p')
            .addClass('class_A')
            .siblings('p.subitem-text').removeClass('class_A');
    }
});

Note that it is perfectly valid to say $(this) instead of $(event.target) but it will give different results if and when you start moving to event delegation. An added advantage is that it will be easier for you or the next guy to understand the code in in two months if you go with event.target.

istruble