tags:

views:

96

answers:

5

Hey guys, I'd like to create a toggle event for 2 different TD's in my table row. the event should show / hide the next table row.

<table>
<tr>
<td>1</td> <td>2</td> <td>3</td> <td>4</td> <td>5</td> <td class="clickable1">6</td> <td class="clickable2">7</td>
</tr>
<tr><td>this row should be toggled between show/hide once one of the clickable TDs were clicked</td></tr>
</table>

here's the code i tried to apply but it has applied each one of the classes the event:

$('.clickable1,.clickable2').toggle(function() {
            $(this).parent()
               .next('tr')
               .show();
        }, function() {
        $(this).parent()
               .next('tr')
               .hide();
        });

One more thing: i'm applying on each TR a css hover psuedo class. how can i make the two TRs to be highlighted (like hover effect on two of them) ?

Thanks in advanced!

:-Dan

UPDATE: thanks for all the answers guys! here's what i've found to be working perfectly so far:

$('.clickable1,.clickable2').click(function() {
                   $(this).parent()
                          .next('tr')
                          .toggle();
});

it seems that the TR remembers it's previous state by the toggle command! good stuff !

+1  A: 

Rather than use a toggle handler, just toggle visibility based on button click. Use toggleClass to switch the "hover" class in and out.

$('.clickable1,.clickable2').click(function() {
     var parent = $(this).parent();
     parent.toggleClass('hovered');

     var next = parent.next('tr');
     next.toggle().toggleClass('hovered');
});
tvanfosson
This is a great solution given the assumption that the show/hide was the only functionality required for the toggle.
patrick dw
A: 

Check this jsFiddle out that demos both requested behaviors. Note that I changed the classes clickable1 and clickable2 to just clickable since I didn't see any reason in your example to have two classes. That can be changed back with minor tweaks if you want. The code is also included below in case jsFiddle dies:

HTML:

<table id="table">
<tr>
<td>1</td> <td>2</td> <td>3</td> <td>4</td> <td>5</td> <td class="clickable">6</td> <td class="clickable">7</td>
</tr>
<tr class="toggleVis"><td colspan="7">this row should be toggled between show/hide once one of the clickable TDs were clicked</td></tr>
</table>​

CSS:

.clickable{cursor:pointer;}
.hide{display:none;}
.hover{font-weight:bold;border:solid 1px blue;background-color:yellow;}​

jQuery:

$(".clickable").click(function() {
    $(".toggleVis").toggleClass("hide");
});
$('tr', "#table").hover(
    function() {
        $(this).toggleClass("hover");
    },
    function() {
        $(this).toggleClass("hover");
    });
Bradley Mountford
@Bradley - Respectfully, this doesn't quite work. First, remember that the OP may have reasons for the two different classes beyond the event handling. Second, your click handler will toggle *all* elements with the class `.toggleVis`, while OP just wants to toggle the next row (pretty safe assumption that he has several row pairs). Third, for the row hilighting on hover, OP wants to hilight each row with its pair (the one that would be hidden on the click event).
patrick dw
+1  A: 

If you really only want one event, one option would be to place the handler on the parent container, and rely on the automatic bubbling to trigger it.

You could normally use jQuery's delegate() function, but I don't think it supports the toggle event.

$('tr:has([class^=clickable])').toggle(function(e) {

        // Verify that the target had a clickable class
    if($(e.target).closest('[class^=clickable]').length ) {

            // No need to call .parent() since the handler is now on the <tr>
        $(this).next('tr').show();
    }
},
function(e) {

        // Verify that the target had a clickable class
    if($(e.target).closest('[class^=clickable]').length ) {

            // No need to call .parent() since the handler is now on the <tr>
        $(this).next('tr').hide();
    }
});

Alternatively, you could just have one fire the other.

$('.clickable1').toggle(function() {
        $(this).parent()
           .next('tr')
           .show();
    }, function() {
    $(this).parent()
           .next('tr')
           .hide();
    });

$('.clickable2').click(function() {
    $(this).prev().click();     // Fires the click event for its previous sibling
});

EDIT:

For the hover, this would be one approach.

$('tr:has([class^=clickable]):even').hover(
  function() {
      $(this).addClass('hilite')
      .next().addClass('hilite');
  },
  function() {
      $(this).removeClass('hilite')
      .next().removeClass('hilite');

});
patrick dw
A: 

Why couldn't you just do this?

$('.clickable1,.clickable2').click(function(e){
    var nTR=$(e.target).parent().next('tr');
    if (nTR.css("display")!="none") nTR.hide();
    else nTR.show();
});​​​​​​

Also, you might want to take a look at this answer.

As for the psuedo-class on the TRs, you're going to have to use another event handler for that, since it's a custom behavior. Luckily, that's pretty easy:

$("tr").hover(function(){
  $(this).next('tr').andSelf()
     .css("backgroundColor","#F00");},
  function(){$(this).next('tr').andSelf()
     .css("backgroundColor","#FFF");
});
Trafalmadorian
A: 

thanks for all the answers guys! here's what i've found to be working perfectly so far:

$('.clickable1,.clickable2').click(function() {
                       $(this).parent()
                              .next('tr')
                              .toggle();
});
danfromisrael