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 10 of 10
  1. #1
    New to the CF scene
    Join Date
    Aug 2007
    Posts
    4
    Thanks
    1
    Thanked 0 Times in 0 Posts

    Add Class to Parent of Nested Lists

    I'm trying to add a class name to list items that contain lists, excluding the root list. I don't think it's that hard to do, but I can't for the life of me figure out how to do it. Here's the concept:
    Code:
    <ul> << should not get class
      <li>
        <ul>
          <li> << this and any li below it that contain lists need a class indicating they contain children
            <ul>
              <li></li>
              <li></li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>
    Not knowing any better, my preference is for an approach that uses getElementsByTagName. I just don't know how to select the right elements. Is there a "best practice" method for doing this?

    Any help would be MUCH appreciated.

  • #2
    Senior Coder
    Join Date
    Sep 2005
    Posts
    1,791
    Thanks
    5
    Thanked 36 Times in 35 Posts
    this is an ideal case for one of the many js libraries that give you css selector support, using prototype.js (http://prototypejs.org) you would do:
    Code:
    $$('ul li ul').each(function(list) {
      list.up('li').addClassName('has_children');
    });
    jQuery, yui, dojo and mootools all (I think) have similar functionality

    [edit] misread, minor correction

    [edit]some explanation:
    the $$() function takes a 'css selector' and returns an array of matching elements- in this case we use 'ul li ul' which (starting from the right) means 'all ul-elements that are inside an li-element which in turn are inside a ul-element'.

    The each() method on arrays takes a function as its argument, and applies it to 'each' element of the array. The function receives as an argument each item from the array, in turn.

    prototype.js gives us the 'up()' method on elements, which (in this case) returns the first 'ancestor' (parent, or parent's parent and so on) that matches the given tag (it's a little less brittle than 'parentNode', and is automagically extended by prototype- using parentNode directly in IE won't work).

    We then call the addClassName() method (again, a prototype.js thing) that should be fairly self explanatory.
    Last edited by GJay; 08-31-2007 at 09:47 PM.
    My thoughts on some things: http://codemeetsmusic.com
    And my scrapbook of cool things: http://gjones.tumblr.com

  • Users who have thanked GJay for this post:

    kavaXtreme (08-31-2007)

  • #3
    New to the CF scene
    Join Date
    Aug 2007
    Posts
    4
    Thanks
    1
    Thanked 0 Times in 0 Posts
    I had thought about looking into a Mootools or JQuery solution, but it's just for a simple menu, so those seem like overkill and I'd like to avoid the extra load time/bandwidth.

    Is there a simple way to do this using regular JS?

  • #4
    Regular Coder
    Join Date
    Feb 2005
    Posts
    679
    Thanks
    0
    Thanked 16 Times in 15 Posts
    For your example:
    Code:
    <ul> << should not get class
      <li>
        <ul>
          <li> << this and any li below it that contain lists need a class indicating they contain children
            <ul>
              <li></li>
              <li></li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>
    A loop would do
    Code:
    <script type="text/javascript">
    mylist = document.getElementsByTagName('li');
    for (var i = 1;i < mylist.length; i++) {
     mylist[i].className = 'myclass';
    }
    </script>

  • #5
    New to the CF scene
    Join Date
    Aug 2007
    Posts
    4
    Thanks
    1
    Thanked 0 Times in 0 Posts
    Wouldn't that just add a class to all li tags? I'm looking for a solution that would only add a class to list elements that contain lists, excluding the parent/root list.

  • #6
    Smokes a Lot
    Join Date
    Jul 2003
    Location
    CA, USA
    Posts
    1,594
    Thanks
    5
    Thanked 20 Times in 20 Posts
    Code:
    <script type="text/javascript">
    mylist = document.getElementsByTagName('li');
    for (var i = 0;i < mylist.length; i++) {
     kidLists=mylist[i].getElementsByTagName('li');
     for(var j=0;j<kidLists.length;j++){
     	kidLists[j].className="myclass";
     }
    }
    </script>
    I think that'll work, didn't test.
    Last edited by Basscyst; 08-31-2007 at 11:40 PM.
    Helping to build a bigger box. - Adam Matthews

  • #7
    Regular Coder
    Join Date
    Feb 2005
    Posts
    679
    Thanks
    0
    Thanked 16 Times in 15 Posts
    Quote Originally Posted by kavaXtreme View Post
    Wouldn't that just add a class to all li tags? I'm looking for a solution that would only add a class to list elements that contain lists, excluding the parent/root list.
    For your posted example, since the loop starts on the second li element, the output of the loop would be
    Code:
    <ul> << should not get class
      <li>
        <ul>
          <li class="myclass"> << this and any li below it that contain lists need a class indicating they contain children
            <ul>
              <li class="myclass"></li>
              <li class="myclass"></li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>

  • #8
    Smokes a Lot
    Join Date
    Jul 2003
    Location
    CA, USA
    Posts
    1,594
    Thanks
    5
    Thanked 20 Times in 20 Posts
    I'm sure he has more than just that list on his page. What if there are other li elements on the page. All that does is skip the first li, which could cause undesired results.
    Helping to build a bigger box. - Adam Matthews

  • #9
    New to the CF scene
    Join Date
    Aug 2007
    Posts
    4
    Thanks
    1
    Thanked 0 Times in 0 Posts
    Hmm. Still can't get it to work. (Sorry, I don't have a public link.)

    @Basscyst
    I gave that code a shot, but it just seems to add the class to all LI elements except the root's.

    To explain the reason I need this class: I want to put a little arrow in the menu to indicate which menu items contain sub-items. Make sense?

  • #10
    Regular Coder
    Join Date
    Feb 2005
    Posts
    679
    Thanks
    0
    Thanked 16 Times in 15 Posts
    Set a class for each ul group you wish to add the li class to:
    Code:
    <ul class="menu"> << should not get class
      <li>
        <ul>
          <li> << this and any li below it that contain lists need a class indicating they contain children
            <ul>
              <li></li>
              <li></li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>
    
    
    <script type="text/javascript">
    var myULs = document.getElementsByTagName('ul');
    for (var i = 0;i < myULs.length; i++) {
       if (myULs[i].className === 'menu') {
           var subULs = myULs[i].getElementsByTagName('ul');
                    for (j = 0;j < subULs.length-1;j++) {
                     subULs[j].getElementsByTagName('li')[0].className = 'myclass';
                    }
       }
    }
    </script>
    Last edited by rwedge; 09-01-2007 at 05:50 AM. Reason: script


  •  

    Posting Permissions

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