SitePoint Sponsor

User Tag List

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

    looping through table rows

    - I have table rows (TR).

    The special Row:
    - One table row is special, and has the class name: container in first child (TD).
    - The second child in special row, the IMG tag act as click listener.

    The goal:
    - If someone click on special row second child, the IMG tag, I want to hide all row (except the special row) until next container (special row) appear.

    Example: Someone click on IMG tag in line 3:. I want to hide each table row between 5: and 16: (except the special row 2: and 4: )

    Code:
    1: <tbody> 
    2:    <tr id="forum-list-1"> 
    3:       <td colspan="4" class="container"><img src="img.gif" alt="[img]" />Click here</img></div></td> 
    4:    </tr> 
    5:    <tr id="forum-list-3"> 
    6:       <td>forum1</td> 
    7:       <td>0</td> 
    8:       <td>0</td> 
    9:       <td>na</td> 
    10:    </tr> 
    11:   <tr id="forum-list-4"> 
    12:      <td>forum2</td> 
    13:      <td>0</td> 
    14:      <td>0</td> 
    15:      <td>na</td> 
    16:   </tr> 
    17:   
    18:   <tr id="forum-list-2"> 
    19:      <td colspan="4" class="container"><img src="img.gif" alt="[img]" />Click here</img></td> 
    20:   </tr> 
    21:   <tr id="forum-list-5"> 
    22:      <td>forum3</td> 
    23:      <td>0</td> 
    24:      <td>0</td> 
    25:      <td>na</td> 
    26:   </tr> 
    27: </tbody>
    I achieve this using a for loop.

    Code:
    var containerRow = document.getElementById('forum-list-1');
    
    for (var el = containerRow.nextSibling; el; el = el.nextSibling)
    {
    	if (el.nodeType == 1) 
    	{
    		if (el.cells[0].className == "container")
    		{
    			break;
    		}
    				
    		if (!Core.hasClass(el, "hide"))
    		{
                   		Core.addClass(el, "hide");
    		}
    		else
    		{
    			Core.removeClass(el, "hide");
    		}
    	}
    }
    Someone tell me is easier to solve this problem using a "while" loop. Is true ? And BTW, my code is correct or exist a simpler and more beatuiful way to achieve this ?

    Thanks!

  2. #2
    SitePoint Wizard gRoberts's Avatar
    Join Date
    Oct 2004
    Location
    Birtley, UK
    Posts
    2,439
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Loops are the best way to do it.

    Code javascript:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
        <head>
            <title>Untitled Document</title>
            <link rel="stylesheet" type="text/css" media="screen" />
            <style type="text/css"></style>
            <script type="text/javascript">
                function toggle(el) {
                    var tbody = el;
                    var row = el;
                    // get parent row
                    while(row.nodeName != 'TR')
                        row = row.parentNode;
                    // get tbody
                    while(tbody.nodeName != 'TBODY')
                        tbody = tbody.parentNode;
                    var currentRowIndex = 0;
                    for(var i = 0; i < tbody.rows.length; i++) {
                        // find clicked row index
                        if(tbody.rows[i].cells.length == 1 && tbody.rows[i].id == row.id) {
                            currentRowIndex = i;
                            break;
                        }
                    }
                    // go from the clicked row and hide each row until we hit another "special" row
                    for(var i = (currentRowIndex+1); i < tbody.rows.length; i++) {
                        if(tbody.rows[i].cells.length == 1)
                            break;
                        tbody.rows[i].style.display = 'none';
                    }
                }
            </script>
        </head>
        <body>
     
        <table width="100%" cellpadding="0" cellspacing="0">
            <tbody> 
                <tr id="forum-list-1"> 
                    <td colspan="4" class="container"><img src="img.gif" alt="[img]" onclick="toggle(this);"/>Click here</img></div></td> 
                </tr> 
                <tr id="forum-list-3"> 
                    <td>forum1</td> 
                    <td>0</td> 
                    <td>0</td> 
                    <td>na</td> 
                </tr> 
                <tr id="forum-list-4"> 
                    <td>forum2</td> 
                    <td>0</td> 
                    <td>0</td> 
                    <td>na</td> 
                </tr> 
                <tr id="forum-list-2"> 
                    <td colspan="4" class="container"><img src="img.gif" alt="[img]" onclick="toggle(this);" />Click here</img></td> 
                </tr> 
                <tr id="forum-list-5"> 
                    <td>forum3</td> 
                    <td>0</td> 
                    <td>0</td> 
                    <td>na</td> 
                </tr> 
            </tbody>
        </table>
     
        </body>
    </html>


  3. #3
    SitePoint Zealot
    Join Date
    May 2008
    Posts
    156
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    hehe thanks, your code is complicated for me, sorry
    My loop work, but I ask for a simpler way like "while" loop.

  4. #4
    SitePoint Wizard gRoberts's Avatar
    Join Date
    Oct 2004
    Location
    Birtley, UK
    Posts
    2,439
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    lol my fault for not reading the whole post. If your code works then why change it? It's certainly shorter then mine lol


  5. #5
    SitePoint Zealot
    Join Date
    May 2008
    Posts
    156
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok my loop work great:

    Code:
    var containerRow = document.getElementById('forum-list-1');
    
    for (var el = containerRow.nextSibling; el; el = el.nextSibling)
    {
    	if (el.nodeType == 1) 
    	{
    		if (el.cells[0].className == "container")
    		{
    			break;
    		}
    				
    		if (!Core.hasClass(el, "hide"))
    		{
                   		Core.addClass(el, "hide");
    		}
    		else
    		{
    			Core.removeClass(el, "hide");
    		}
    	}
    }
    But I have a question (I promise this is my final question), is possible to check with an IF condition if table rows are really hidden ? after Core.addClass(el, "hide"); executed?

    Please, please help me is very important to solve this problem. Thanks!

  6. #6
    SitePoint Wizard gRoberts's Avatar
    Join Date
    Oct 2004
    Location
    Birtley, UK
    Posts
    2,439
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I wouldn't use a class to hide/show the rows. Instead i'm simply hide/show the rows using the style.display property of the row in question.

    ie

    Code javascript:
    var containerRow = document.getElementById('forum-list-1');
     
    for (var el = containerRow.nextSibling; el; el = el.nextSibling)
    {
        if (el.nodeType == 1) 
        {
            if (el.cells[0].className == "container")
            {
                break;
            }
     
            el.style.display = (el.style.display == '' ? 'none' : '');
        }
    }


  7. #7
    SitePoint Zealot
    Join Date
    May 2008
    Posts
    156
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    This is not what I ask!!! sorry. I need to check if table rows are hidden with IF confidtion. Read my question again.

    BTW, Using the style property not respect the separation for web (is old style). Use HTML for content, CSS for style and JavaScript for behaviour.

  8. #8
    SitePoint Wizard gRoberts's Avatar
    Join Date
    Oct 2004
    Location
    Birtley, UK
    Posts
    2,439
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Not entirely true. The property would not be available if this were the case.

    Because you are setting the display property within your css, it will not update the dom to state its hidden.

    So the answer to your question is no. Unless someone else can show otherwise, the only ways to check if an element is hidden, is to use the visibility or display property.


  9. #9
    SitePoint Zealot
    Join Date
    May 2008
    Posts
    156
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    BTW, I need to run the code once after table rows are hidden. And I need to run a second code once if table rows are visible.

    Your code is located in for loop.

  10. #10
    SitePoint Zealot
    Join Date
    May 2008
    Posts
    156
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I need something like this:

    Code:
    for (var el = containerRow.nextSibling; el; el = el.nextSibling)
    {
                if (el.nodeType == 1)
                {
                    if (el.cells[0].className == "container")
                    {
                        break;
                    }
                   
                    if (!Core.hasClass(el, "hide"))
                    {
                        Core.addClass(el, "hide"); // run this statement on 10 rows.
                        var hiden = true; // run this statement on 10 rows..
                    }
                    else
                    {
                        Core.removeClass(el, "hide"); // run this statement on 10 rows
                    }
                }
    }
    
    if (hiden)
    {
       alert("this code run only once");
    }
    My code work but don't check if table rows are hidden. For example if "Core.addClass(el, "hide");" statement is not executed, I see the alert box.

  11. #11
    SitePoint Wizard
    Join Date
    Nov 2004
    Location
    Nelson BC
    Posts
    2,310
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If someone click on special row second child, the IMG tag, I want to hide all row (except the special row) until next container (special row) appear.
    = behavior, not style

  12. #12
    SitePoint Zealot
    Join Date
    May 2008
    Posts
    156
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    thanks for telling me but really.. someone know a solution ? I work with table rows. I know is harder but I need to find a solution..

  13. #13
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,683
    Mentioned
    99 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by zoliky View Post
    But I have a question (I promise this is my final question), is possible to check with an IF condition if table rows are really hidden ? after Core.addClass(el, "hide"); executed?
    There is the Core.hasClass method, but I suspect that's not really what you're after.

    You can find out the computed style that applies to any element, but that's rather more complex.
    http://www.quirksmode.org/dom/getstyles.html
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  14. #14
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,683
    Mentioned
    99 Post(s)
    Tagged
    4 Thread(s)
    Here is the test code I've been using to improve on things here.
    Notes follow afterwards.

    Code html4strict:
    <html>
    <head>
    <style type="text/css">
    .hide {
    	display: none;
    }
    </style>
    </head>
    <body>
    <table id="myTable">
        <tbody> 
            <tr id="forum-list-1"> 
                <td colspan="4" class="container"><img src="img.gif" alt="[img]" />Click here</img></td> 
            </tr> 
    		<tr id="forum-list-3"> 
    			<td>forum1</td> 
    			<td>0</td> 
    			<td>0</td> 
    			<td>na</td> 
    		</tr> 
    		<tr id="forum-list-4"> 
    			<td>forum2</td> 
    			<td>0</td> 
    			<td>0</td> 
    			<td>na</td> 
    		</tr> 
    		<tr id="forum-list-2"> 
    			<td colspan="4" class="container"><img src="img.gif" alt="[img]" />Click here</img></td> 
    		</tr> 
    		<tr id="forum-list-5"> 
    			<td>forum3</td> 
    			<td>0</td> 
    			<td>0</td> 
    			<td>na</td> 
    		</tr> 
        </tbody>
    </table>
    <script src="core.js"></script>
    <script src="toggle.js">
    </script>
    </body>
    </html>

    Code javascript:
    if (!Node || !Node.ELEMENT_NODE) {
    	var Node = {};
    	Node.ELEMENT_NODE = 1;
    	Node.ATTRIBUTE_NODE = 2;
    	Node.TEXT_NODE = 3;
    	Node.CDATA_SECTION_NODE = 4;
    	Node.ENTITY_REFERENCE_NODE = 5;
    	Node.ENTITY_NODE = 6;
    	Node.PROCESSING_INSTRUCTION_NODE = 7;
    	Node.COMMENT_NODE = 8;
    	Node.DOCUMENT_NODE = 9;
    	Node.DOCUMENT_TYPE_NODE = 10;
    	Node.DOCUMENT_FRAGMENT_NODE = 11;
    	Node.NOTATION_NODE = 12;
    }
    var table = document.getElementById('myTable'),
    	els = table.getElementsByTagName('img'),
    	elsLen = els.length,
    	i;
    for (i = 0; i < elsLen; i += 1) {
    	els[i].onclick = toggle;
    }
    function toggle() {
    	var containerRow = this.parentNode;
    	while (containerRow && containerRow.nodeName !== 'TR') {
    		containerRow = containerRow.parentNode;
    	}
    	var el = containerRow.nextSibling,
    		hidden = false;
    	while (el) {
    		if (el.nodeType == Node.ELEMENT_NODE) {
    			if (el.cells[0].className == "container") {
    				break;
    			}
    			if (!Core.hasClass(el, "hide")) {
               		Core.addClass(el, "hide");
                    hidden = true;
    			} else {
    				Core.removeClass(el, "hide");
    			}
    		}
    		el = el.nextSibling;
    	}
    	if (hidden) {
    	   alert("this code run only once");
    	}
    }

    Instead of checking if the nodeType equals 1, I check if it equals Node.ELEMENT_NODE which makes the code more readable. IE doesn't have the Node object though, so it gets created if it doesn't exist.

    I didn't know how you were attaching the event to the images, so a good standard technique has been used here.

    When things get toggled, instead of taking the first TR, I've instead walked up the DOM tree until one gets found.

    The for loop has been updated to use a while loop instead.

    The alert gets run only when an element has been hidden. Because the class is being set to hide an element, that's all that should be neccessary as far as checking goes.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  15. #15
    SitePoint Zealot
    Join Date
    May 2008
    Posts
    156
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    And what I need to do if I want to run another code (only once) if "hidden" class is removed. I need a separate variable, again ?

  16. #16
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,683
    Mentioned
    99 Post(s)
    Tagged
    4 Thread(s)
    You can use strings instead to store that information.

    Code javascript:
    if (!Core.hasClass(el, "hide")) {
        Core.addClass(el, "hide");
            hidden = 'added';
        } else {
            Core.removeClass(el, "hide");
            hidden = 'removed';
        }
    }
    Code javascript:
    if (hidden === 'added') {
        // something was hidden
    } else if (hidden === 'removed') {
        // something was shown
    }
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  17. #17
    SitePoint Zealot Ken Sharpe's Avatar
    Join Date
    Apr 2008
    Posts
    160
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Have you considered using one of the many javascript frameworks that are designed to handle issues like this with a minimum of fuss and a maximum of browser compatibility?

    Might I suggest JQuery?


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
  •