Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 6 of 6
  1. #1
    New Coder
    Join Date
    Jan 2004
    Location
    USA
    Posts
    11
    Thanks
    0
    Thanked 0 Times in 0 Posts

    hierarchical selection

    hi!

    here's the situation:

    an outline format list of files that the user can pick to download. each file has a checkbox. i want the user to be able to select all the files in a sublevel by clicking the checkbox for that level.

    visualize:
    (x shall be checkbox)
    Code:
    x top level
        x sub level
            x bottom level
            x bottom level
        x sub level
            x bottom level
            x bottom level
    clicking the top level would select everything. clicking a sub level would select the files underneath that level. clicking a bottom level would only select that file.

    also, i'd like it to work backwards too. if a user deselects a file on the bottom level, the sublevel directly above that should uncheck.

    is this even possible with javascript? have i bitten off more than i can chew? if so, suggestions for a more elegant way to approach this would be appreciated.

    thanks in advance!

    attached is a bare beginning...
    Attached Files Attached Files

  • #2
    Regular Coder
    Join Date
    Aug 2002
    Location
    São Paulo, Brazil
    Posts
    367
    Thanks
    0
    Thanked 0 Times in 0 Posts
    A recursive function should solve it:

    PHP Code:
    <html>
    <
    head>
    <
    meta http-equiv="content-type" content="text/html;charset=ISO-8859-1">
    <
    script>
    function 
    check(f,isChild) {

        
    /* Returns an array with children inputs */
        
    function getChildren(f) {
            var 
    childContainer=f.nextSibling;
            while (
    childContainer && childContainer.tagName!="BLOCKQUOTE") {
                
    childContainer=childContainer.nextSibling;
            }
            if (
    childContainer) {
                return 
    childContainer.getElementsByTagName("INPUT");
            } else {
                return [];
            }
        }

        
    /* Checks / unchecks all parents */
        
    function checkParent(f,checked) {
            var 
    p=f.parentNode.previousSibling;
            while (
    && p.tagName!="INPUT") {
                
    p=p.previousSibling;
            }
            if (
    p) {
                var 
    fields=getChildren(p);
                for (var 
    0fields.lengthi++) {
                    if (!
    fields].checked) {
                        
    checked=false;
                    }
                }
                
    p.checked=checked;
                
    checkParent(p,checked);
            }
        }

        var 
    checked=f.checked;

        
    /* Check / uncheck all children */
        
    var fields=getChildren(f);
        for (var 
    0fields.lengthi++) {
            
    fields].checked checked;
            
    check(fields],true);
        }

        
    /* Verify the state of the parents to calling node */
        
    if (typeof isChild=="undefined") {
            
    checkParent(f,checked);
        }
    }
    </script>
    <title>Test JS</title>

    </head>
    <body>

    <form name="form">
        <input type="checkbox" onclick="check(this);" />top level<br />
        <blockquote>
            <input type="checkbox" onclick="check(this);" />sublevel<br />
            <blockquote>
                <input type="checkbox" onclick="check(this);" />bottom level<br />
                <input type="checkbox" onclick="check(this);" />bottom level
            </blockquote>
            <input type="checkbox" onclick="check(this);" />sublevel<br />
            <blockquote>
                <input type="checkbox" onclick="check(this);" />bottom level<br />
                <input type="checkbox" onclick="check(this);" />bottom level
            </blockquote>
        </blockquote>
    </form>
    </body>
    </html> 
    The first step is to loop down through the hierarchy and check/uncheck the children. This is done by identifying the the container, which is a sibling to the <input> (in this case <blockquote>), and getting all inputs from this container, using the getChildren() function.

    The second step is to check whether the parent(s) should be checked. This is done by calling another recursive function - checkParent() - to loop up through the hierarchy.
    /Daniel

  • #3
    New Coder
    Join Date
    Jan 2004
    Location
    USA
    Posts
    11
    Thanks
    0
    Thanked 0 Times in 0 Posts
    ah! that's beautiful! that's the first javascript i've seen that actually uses the strengths of the language. (i say that like i know what i'm talking about. in reality, that's first thing i'd ever seen about "children" and so on... )

    anyway, i have one question: what if i don't use blockquotes? in my actual application, i'm using <div> tags to format my list. each div has a unique name. like this:

    Code:
    <div class="section">
    	<input type="checkbox" id="firstsection"> Section One</input>
    </div>
    <div class="subsection">
    	<input type="checkbox" id="firstsubsection"> Subsection One</input>
    </div>
    <div class="file">
    	<input type="checkbox"> File One</input>
    </div>
    <div class="file">
    	<input type="checkbox"> File Two</input>
    </div>
    <div class="subsection">
    	<input type="checkbox" id="secondsubsection"> Subsection Two</input>
    </div>
    <div class="file">
    	<input type="checkbox"> File One</input>
    </div>
    <div class="file">
    	<input type="checkbox"> File Two</input>
    </div>
    <div class="section">
    	<input type="checkbox" id="secondsection"> Section Two</input>
    </div>
    would that even be possible with the code you've provided? if not, i may have to rethink my formatting... keep in mind, this is dynamically generated, however.

    thanks again!

  • #4
    Regular Coder
    Join Date
    Aug 2002
    Location
    São Paulo, Brazil
    Posts
    367
    Thanks
    0
    Thanked 0 Times in 0 Posts
    If you rearrange your HTML a little, to better describe the parent-child relation, it should work:
    Code:
    <div class="section">
        <input type="checkbox" id="firstsection" onclick="check(this);"> Section One
        <div class="subsection">
            <input type="checkbox" id="firstsubsection" onclick="check(this);"> Subsection One
            <div class="file">
                <input type="checkbox" onclick="check(this);"> File One
                <input type="checkbox" onclick="check(this);"> File Two
            </div>
            <input type="checkbox" id="secondsubsection" onclick="check(this);"> Subsection Two
            <div class="file">
                <input type="checkbox" onclick="check(this);"> File One
                <input type="checkbox" onclick="check(this);"> File Two
            </div>
        </div>
    </div>
    <div class="section">
        <input type="checkbox" id="secondsection" onclick="check(this);"> Section Two
    </div>
    You also need to change this line
    Code:
    while (childContainer && childContainer.tagName!="BLOCKQUOTE") {
    to this:
    Code:
    while (childContainer && childContainer.tagName!="DIV") {
    If you don't want to change the HTML, you need to modify the getChildren-function to return the children in a different way. A good DOM reference can help you to do that.
    Last edited by Danne; 01-05-2004 at 11:14 PM.
    /Daniel

  • #5
    New Coder
    Join Date
    Jan 2004
    Location
    USA
    Posts
    11
    Thanks
    0
    Thanked 0 Times in 0 Posts
    thanks! that's actually exactly what i ended up doing. the added bonus is that my html is a lot cleaner now.

    thanks for your time and effort!

  • #6
    Regular Coder
    Join Date
    Aug 2002
    Location
    São Paulo, Brazil
    Posts
    367
    Thanks
    0
    Thanked 0 Times in 0 Posts
    You're welcome...
    /Daniel


  •  

    Posting Permissions

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