SitePoint Sponsor

User Tag List

Results 1 to 10 of 10
  1. #1
    SitePoint Zealot
    Join Date
    May 2008
    Posts
    156
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    DOM traversing with jQuery

    I have a HTML table (drupal forum):

    Code HTML4Strict:
    <table id="forum-0" class="accordion">
    <thead>
      <tr>
         <th>Forum</th>
         <th>Topics</th>
         <th>Posts</th>
         <th>Last Post</th>
      </tr>
    </thead>
    <tbody>
         <tr id="forum-list-1" class="odd">
              <td colspan="4" class="container"><div class="show_hide"></div></td>
         </tr>
         <tr id="forum-list-3" class="even">
              <td>........</td>
              <td>........</td>
              <td>........</td>
              <td>........</td>
         </tr>
    ..
    ..
    </tbody>

    The forum illustrated: http://img61.imageshack.us/img61/7029/drufcw3.jpg

    My JavaScript code put a click listener on show_hide class (the class is located in forum container) :

    Code JavaScript:
    $(document).ready(function()
    {
    	var Accordion =
    	{
    		clickListener: function(e)
    		{
    			e.preventDefault();
    		}
    	};
     
    	$('.show_hide').click(Accordion.clickListener);
    });

    I want to obtain all elements in TBODY, except the container. So, I need this elements with jQuery:

    Code HTML4Strict:
    <tr id="forum-list-3" class="even">
         <td>........</td>
         <td>........</td>
         <td>........</td>
         <td>........</td>
    </tr>

    I need to collapse/expand the code, and I think is not a good idea to include the container.

    Which is the best way to obtain all elements inside TBODY, except forum container row using jQuery?

    Thank you very much!

  2. #2
    SitePoint Enthusiast
    Join Date
    Feb 2008
    Posts
    62
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Are the id attributes of tbody and the tr elements dynamic or can you know them ahead of time?

    Here's a way without know the IDs.

    Code:
    $('tbody tr:eq(1)')
    You could also use
    Code:
    $('#forum-0 tbody tr:eq(1)')
    if you know forum-0 will be the ID or just
    Code:
    $('#forum-list-3')
    if you know the ID of the tr element you want before hand.

    The best bet of the examples I've given, if you don't know the IDs ahead of time is to give the tbody an ID and do this
    Code:
    $('#tbody-id-here tr:eq(1)')
    That will select the second tr element under the tbody element with the ID that you choose.

  3. #3
    SitePoint Zealot
    Join Date
    May 2008
    Posts
    156
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    LogicFlux thanks for you reply I explain the problem more carefully.

    1. I have an HTML table:

    Code JavaScript:
    1: <tbody>  
    2:    <tr>  
    3:       <td colspan="4" class="container"><div class="show_hide">Second text</div></td>  
    4:    </tr>  
    5:    <tr>  
    6:       <td>forum1</td>  
    7:       <td>0</td>  
    8:       <td>0</td>  
    9:       <td>na</td>  
    10:    </tr>  
    11:    <tr>  
    12:       <td>forum2</td>  
    13:       <td>0</td>  
    14:       <td>0</td>  
    15:       <td>na</td>  
    16:    </tr>  
    17:   
    18:    <tr>  
    19:       <td colspan="4" class="container"><div class="show_hide">Second</div></td>  
    20:    </tr>  
    21:    <tr>  
    22:       <td>forum3</td>  
    23:       <td>0</td>  
    24:       <td>0</td>  
    25:       <td>na</td>  
    26:    </tr>  
    27: </tbody>

    The table illustrated: http://img61.imageshack.us/img61/7029/drufcw3.jpg

    2. The first "Second text" link need to select all table row (TR) in first container (except the container row).
    For example: I click on "second text" (line number: 3:) and I want to get all TR between (line number: 5:) and (line number: 16:) without 2: and 4:

    And yes, "#forum-list-3" is a dynamic element, but if need I try to add a new class or something to any element.

    Can you help me a bit ? Thanks !

  4. #4
    SitePoint Enthusiast
    Join Date
    Feb 2008
    Posts
    62
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I think I understand now.



    Code HTML4Strict:
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <HTML>
     <HEAD>
      <TITLE> </TITLE>
     
      <script type="text/javascript" src="jquery-1.2.6.min.js"></script>
     
      <script type="text/javascript">
     
     
        $(document).ready(function(){
     
          $('.show_hide').each( function () { 
     
     
            $(this).click( function () { 
     
              var clickContainerNotFound = true;
     
              $(this).parents('tr').nextAll().each(function () { 
     
     
                // This checks to see if we've gone too far
                $(this).children().children().each(function () {
     
                  //alert($(this).attr('id'));
     
                  if ($(this).attr('class') == 'show_hide')
                    clickContainerNotFound = false;
                });
     
                if (!clickContainerNotFound)
                {
                  return false;
                }
     
                // End gone too far check
     
     
                $(this).toggle();
     
              });
     
            });
     
          });
     
     
        }); 
     
     
     
     
      </script>
     </HEAD>
     
     <BODY>
      <table id="forum-0" class="accordion">
    <thead>
      <tr>
         <th>Forum</th>
         <th>Topics</th>
         <th>Posts</th>
         <th>Last Post</th>
      </tr>
    </thead>
     
    <!-- <tbody>
         <tr id="forum-list-1" class="odd">
              <td colspan="4" id='showhideparent' class="container"><div class="show_hide">show_hide</div></td>
         </tr>
         <tr id="forum-list-3" class="even">
              <td>........</td>
              <td>........</td>
              <td>........</td>
              <td>........</td>
         </tr>
         <tr id="forum-list-4" class="even">
              <td>........</td>
              <td>........</td>
              <td>........</td>
              <td>........</td>
         </tr>
    </tbody> -->
     
     
     
     <tbody> 
        <tr id='tr-1'> 
           <td colspan="4" id='showhideparent' class="container"><div class="show_hide">Second text</div></td> 
        </tr> 
        <tr id='tr-2'> 
           <td>forum1</td> 
           <td>0</td> 
           <td>0</td> 
           <td>na</td> 
        </tr> 
        <tr id='tr-3'> 
           <td>forum2</td> 
           <td>0</td> 
           <td>0</td> 
           <td>na</td> 
        </tr> 
     
        <tr id='tr-4'> 
           <td colspan="4"  id='showhideparent' class="container"><div class="show_hide">Second</div></td> 
        </tr> 
        <tr id='tr-5'> 
           <td>forum3</td> 
           <td>0</td> 
           <td>0</td> 
           <td>na</td> 
        </tr> 
     </tbody>
     
     
     </BODY>
    </HTML>

    I put the IDs in some of the elements to test it so I could alert them to see which elements I was grabbing. The code doesn't rely on the elements have any IDs.
    Last edited by LogicFlux; May 31, 2008 at 23:44.

  5. #5
    SitePoint Zealot
    Join Date
    May 2008
    Posts
    156
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    thanks for your kind help I try your code soon.
    Because I want to collapse/expand each table row (except the container row) is not a good idea to put each table row in one separate row?

    An example:

    Code HTML4Strict:
    1: <tbody> 
    2:    <tr> 
    3:       <td colspan="4" class="container"><div class="show_hide">Second text</div></td> 
    4:    </tr>
    5:    <tr> <!-- the new row - I want to hide this row with CSS-->
    6:       <tr> 
    7:          <td>forum1</td> 
    8:          <td>0</td> 
    9:          <td>0</td> 
    10:          <td>na</td> 
    11:      </tr> 
    12:      <tr> 
    13:         <td>forum2</td> 
    14:         <td>0</td> 
    15:         <td>0</td> 
    16:         <td>na</td> 
    17:      </tr> 
    18:   </tr> <!-- new row end -->

    The "Sitepoint - simply javascript" book use something similar in accordion (non-jQuery) example but use DIV's. For me is not possible to use DIV, because I work with table.

    I wait your opinion. Thanks!

  6. #6
    SitePoint Enthusiast
    Join Date
    Feb 2008
    Posts
    62
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It's better to use divs as containers. That way you can show/hide an entire container holding many elements all at once. And if you wanted to animate the show/hide actions I think you'd pretty much have to use divs and not individual table rows.
    I didn't know how much control you have over the generation of the html so I just created code to work with the table rows.
    The code I posted is not that optimized. It does pretty much work on every click and then it shows/hides elements one at a time. This may be noticeable on a really slow computers but I'm not sure. It would be better to cache the info of the elements instead of doing all the work of traversing them on every click. But I don't know how slow a computer would need to be to notice the difference. I'm on a computer with middle of the road specs and it seems to work fine for me.

    Here's a more condensed version.

    Code JavaScript:
        $(document).ready(function(){
     
          $('.show_hide').each( function(){ 
     
            $(this).click(function(){ 
     
              var clickContainerNotFound = true;
     
              $(this).parents('tr').nextAll().each(function(){ 
     
                $(this).children().children('.show_hide').each(function(){ clickContainerNotFound = false;});
     
                if (!clickContainerNotFound){ return false; }
     
                $(this).toggle();
              });
            });
          });
        });

  7. #7
    SitePoint Zealot
    Join Date
    May 2008
    Posts
    156
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    can you help me with an example how to put the container in div? thanks!

  8. #8
    SitePoint Enthusiast
    Join Date
    Feb 2008
    Posts
    62
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

  9. #9
    SitePoint Zealot
    Join Date
    May 2008
    Posts
    156
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks, I write a code without jQuery (I do the same thing with Core library from sitepoint - simply javascript book). Someone tell me, is possible to animate the table rows, without DIV's. The accordion work great, now! I try to animate each table row, to increase - decrease the height gradually.

  10. #10
    SitePoint Zealot
    Join Date
    May 2008
    Posts
    156
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Your code work good:

    Code:
    $(document).ready(function(){
         
          $('.show_hide').each( function(){
     
            $(this).click(function(){
     
              var clickContainerNotFound = true;
     
              $(this).parents('tr').nextAll().each(function(){
     
                $(this).children().children('.show_hide').each(function(){ clickContainerNotFound = false;});
               
                if (!clickContainerNotFound){ return false; }
               
                $(this).toggle();
              });
            });
          });
        });
    I want to affect the selected container row. This is the forum structure:
    Code:
    + Container 1 row
       [] Forum1 row
       [] Forum2 row
    + Container 2 row
       [] Forum3 row
    If "Container 1 row" is selected and all child node (Forum1 row, Forum2 row) are collapsed I want to change a picture in Container 1 row (a little arrow).
    I want to do the same thing with expanded child nodes. I need a toogle or something similar...

    I try this for testing but not work:

    Code:
    $(document).ready(function(){
         
          $('.show_hide').each( function(){
     
            $(this).click(function(){
     
              var clickContainerNotFound = true;
     
              $(this).parents('tr').nextAll().each(function(){
     
                $(this).children().children('.show_hide').each(function(){ clickContainerNotFound = false;});
               
                if (!clickContainerNotFound){ return false; }
               
                $(this).toggle();
              });
    
              $(this).toggle(function(){
                  alert('first click on container 1');  
                  //change image
              }, function() {
                  alert('second click on container 2');
                  //change image again
              });
            });
          });
        });
    btw, I need to do this only if rows are collapsed or expanded. I think my code not check this. Can you help me a bit please to solve this issue ? Thanks!


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •