SitePoint Sponsor

User Tag List

Results 1 to 3 of 3
  1. #1
    SitePoint Member
    Join Date
    Mar 2006
    Posts
    2
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Question Selecting by familial relation instead of ID in JavaScript

    Ok, so it's easy enough to modify element CSS on the fly with getElementById. Problem is, you have to give a unique id to every single element on your page you want to be able to modify. I don't want to have to make over a 100 unique id's for the project I'm working on. I'd rather use DOM familial relationships to determine which element to act upon. I'm sure JS has a solution for me. Can you help me find it?

    Here's my goal. It's a list of projects that my agency is working on. We have lots of projects happening, like maybe 20-30, so the list will need to be expandable/collapsible as seen in the image (this is a screenshot of static XHTML at the moment, no interactivity). In the final product, the + and - bullets will reflect the current status of expandable/retractable elements.



    Here is the html code of the list. All the bullets and formatting are in a separate CSS, and aren't so relevant to my issue.

    HTML Code:
    <ul id="programlist">
    
    <li class="programlistitem" id="p1"><a href="#">Project 1</a>
    <ul>
    <li class="overview"><a href="#">Overview</a></li>
    <p>This is the purpose of the program.</p>
    <li class="news"><a href="#">Latest News</a></li>
    <p>This is what the program did last.</p>
    <li class="contact">Contact Person: John Smith</li>
    <li class="homepage"><a href="...">Project Homepage</a></li>
    </ul>
    </li>
    
    <li class="programlistitem" id="p2"><a href="#">Project 2</a>
    <ul>
    <li class="overview"><a href="#">Overview</a></li>
    <p>This is the purpose of the program.</p>
    <li class="news"><a href="#">Latest News</a></li>
    <p>This is what the program did last.</p>
    <li class="contact">Contact Person: John Smith</li>
    <li class="homepage"><a href="...">Project Homepage</a></li>
    </ul>
    </li>
    
    </ul>
    Now, if someone clicks on, say, the words "Project 1", it says "ok, I need to make my child <ul> visible now, which effectivly expands the contents of the first project, so you can see the 4 items under it. The Overview and Latest News would also function the same way making visible/hidden the <p> tags under themselves, with their content hidden at first, then appearing when you click their links.

    I have created scripts like this before, using display: hidden and display: block to achieve the same effect, but I always had to use a unique ID for EVERY item. I want to take my JS to the next level. Can someone point me to a tutorial that will show me how to select elements more dynamically based upon familial relationships?

    I hope this is clear. Please let me know if you need any more details about what I'm trying to do.

    Thanks in advance for your help!

    chigasakigaijin

  2. #2
    Caveat surfer Buddy Bradley's Avatar
    Join Date
    May 2003
    Location
    Cambridge, UK
    Posts
    2,366
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If you can get hold of a particular element in the DOM, you can create arrays of the nodes beneath it in two ways:

    1. getElementsByTagName
    Code:
    var mydiv = document.getElementById('p1');
    var children = mydiv.getElementsByTagName('ul');
    The array children now contains all UL elements that are descendants of the p1 element.

    2. childNodes
    Code:
    var mydiv = document.getElementById('p1');
    var children = mydiv.childNodes;
    The array children now holds all elements that are direct children of the p1 element. This is really only the UL element, but also note that it may include whitespace in between elements as well - you need to check the nodeType when manipulating them.

  3. #3
    SitePoint Member
    Join Date
    Mar 2006
    Posts
    2
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Cool We're in business!

    Thanks so much for getting me started in the right direction. I found that the items I was looking for were:

    parentElement; and getElementsByTagName();

    here is the final working script for the main project name links.

    Code:
    function toggle(source) 
    {
    	var theParent = source.parentElement;
    	var children = theParent.getElementsByTagName('ul');
    	var target = children[0];
    	//check current visibility and set it to the opposite
    	if ((target.style.display == "none") || (target.style.display == "null"))
    	{
    		target.style.display = "block";
    		//change bullet to minus sign to indicate "collapsible"
    		theParent.style.backgroundImage = "url(/images/projectspage/minus.gif)"; 
    
    	} 
    	else 
    	{
    		target.style.display = "none";
    		//change bullet to plus sign to indicate "expandable"
    		theParent.style.backgroundImage = "url(/images/projectspage/plus.gif)"; 
    	}
    }
    I also made a toggleSub(); function to handle the two sub-list expandable items.

    I call them with the following HTML:
    HTML Code:
    <li class="projectlistitem"><a class="projectname" href="#" onClick="toggle(this);">Web Advisory Committee (WAC)</a>
    The key for me was figuring out what "this" meant. Since it sends in the hierarchical location of where the script was called, I used that as my starting point. Since I use consistent patterns of HTML, I know that I can reliably go, for instance:
    1. Out to the parent
    2. In to the first UL

    and that is what I want to toggle the visibility of. Doing it this way, I did not use a single ID in relation to the JS. The DOM delivered! Smooth, baby.

    Whew, anyway it works, and I'm glad.

    Thanks again!


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
  •