views:

33

answers:

2

I have the following code which it was provided by Nick in a previous question and it work like a dream.

What I am trying

"I am trying to generate a jquery script to make all tr elements from a table with class top clickeable and when one tr with class top is clicked all tr below with class bt until there is another tr class top will slideToggle."

But I did have to add an extra row in between top and bt class in some tables, and that break the jquery in those tables.

I wonder if there is any modification where I dont need to change the code in the tables and it would still work for all the table on all web pages applied.

<!DOCTYPE html>
<html>
<head>
<script class="jsbin" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"&gt;&lt;/script&gt;
<meta charset=utf-8 />
<title>JS Bin</title>
<!--[if IE]>
  <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"&gt;&lt;/script&gt;
<![endif]-->
  <script type="text/javascript">
  $("tr.top").click(function () {
  $(this).nextUntil('tr:not(.bt)').animate({ opacity: "toggle" });
});

  </script>
</head>
<body>
  <table>
    <tr class="top" style="background-color:red">
      <td>Click here to collapse the next tr with class bt but no other</td>
      <td>top row 1</td>
      <td>top row 1</td>
    </tr>
    <tr class="other">
      <td colspan="3">This is not ment to collapse when the tr at the top is clicked</td>
    </tr>

    <tr class="bt">
      <td>bt row 1</td>
      <td>bt row 1</td>
      <td>bt row 1</td>
    </tr>
    <tr class="bt">
      <td>bt row 1</td>
      <td>bt row 1</td>
      <td>bt row 1</td>
    </tr>
    <tr class="bt">
      <td>bt row 1</td>
      <td>bt row 1</td>
      <td>bt row 1</td>
    </tr>
    <tr class="top" style="background-color:red">
      <td>Click here to collapse the next tr with class bt</td>
      <td>top row 2</td>
      <td>top row 2</td>
    </tr>
    <tr class="bt">
      <td>bt row 2</td>
      <td>bt row 2</td>
      <td>bt row 2</td>
    </tr>
    <tr class="bt">
      <td>bt row 1</td>
      <td>bt row 1</td>
      <td>bt row 1</td>
    </tr>
    <tr class="top" style="background-color:red">
      <td>Click here to collapse the next tr with class bt</td>
      <td>top row 2</td>
      <td>top row 2</td>
    </tr>
    <tr class="bt">
      <td>bt row 2</td>
      <td>bt row 2</td>
      <td>bt row 2</td>
    </tr>
    <tr class="bt">
      <td>bt row 1</td>
      <td>bt row 1</td>
      <td>bt row 1</td>
    </tr>
  </table>
</body>
</html>​​​​​

You can see here EXAMPLE

+1  A: 

Well, it's slightly messy, but I think this should do the job:

$(this).nextAll('.bt:first').prev().nextUntil('tr:not(.bt)').animate({ opacity: "toggle" });

See: http://jsbin.com/ateze5/9

Yi Jiang
@Yi Jiang:Thanks, havent tried yet but +1 for been the first and the example seem to be working.
Cesar Lopez
@Cesar Moved the `first()` into the `nextAll` selector, should be slightly less messy now
Yi Jiang
@Yi Jiang: It works either way. Thanks a lot. :-)
Cesar Lopez
@Yi Jiang:Hi, there is a problem with yours if you put anorther tr.top with another tr.other without tr.bt at the top then when you click in the top one then it will collapse the next. Its my fault for not specifying, but Jack's answer covers that. Thank you a lot anyway.
Cesar Lopez
+1  A: 

Just skip first if it's not a .bt:

$("tr.top").click(function () {
  if (!$(this).next().hasClass('bt'))
    $(this).next().nextUntil('tr:not(.bt)').animate({ opacity: "toggle" });
  else
    $(this).nextUntil('tr:not(.bt)').animate({ opacity: "toggle" });
});

(it works, already tried)

Jack
@Jack: Thanks, I can see it works too, and I like as I can see a different approach to it, thanks too. + 1 :-)
Cesar Lopez