简体   繁体   中英

How to select lowest level ul in nested ul in Javascript/ css

I feel like this is a simple problem and I searched quite a bit but I cannot come up with a good answer.

I have a bunch of nested ULs that I have appended to a div. I want to be able to collapse the UL I click on. The problem is that when you click one UL inside of another UL you are actually clicking both. So if I click the lowest tier to collapse and say something like $(this).css( 'height', '5px') The highest level UL also gets a height of 5px. Hopefully the code will make my question more clear.

<ul class=t0>
  <li class='item'>Top Item 1</li>
  <li class='item'>Top Item 2</li>
  <li class='item'>Top Item 3 is a list</li>
  <ul class=t1>
    <ul class=t2>
      <li class='item'>some <span class='val'>Thing</span></li>
      <li class='item'>something <span class='val'>else</span></li>
    </ul>
    <ul class=t2>
      <li class='item'>method : <span class='val'>GET</span></li>
      <li class='item'>uri : <span class='val'>/status</span></li>
    </ul>
  </ul>
<li class='item'>Top Item 3 is a list</li>
</ul>

So if you click the UL class t2 only that t2 collapses, but if you click on t1 then both the t2s collapse. I know how to change the css and everything I am just having trouble with selecting only the ul clicked. I think I can use .find or .closest I am just not sure exactly how to do it.

Thanks in advance for the help.

$('.t1, .t2').click(function(e){
  e.stopPropagation(); //prevent the event from bubbling up
  $(this).slideUp();
});

This would work - however, your idea/markup/execution is flawed. There is no .t1 to click as it's made up of two .t2 's - Thus, clicking on .t1 is impossible without clicking a .t2

Your HTML is also invalid, as the <ul class='t1'> cannot have another <ul> as its child. You need some <li> 's in there.

You can use event.stopPropagation to prevent the event from going up to higher levels. http://api.jquery.com/event.stopPropagation/

You could delegate and use e.target to determine what was clicked and find it's $.closest() ancestor UL :

Markup (Updated)

<ul class=t0>
    <li class='item'>Top Item 1</li>
    <li class='item'>Top Item 2</li>
    <li class='item'>Top Item 3 is a list
        <ul class=t2>
            <li class='item'>some <span class='val'>Thing</span></li>
            <li class='item'>something <span class='val'>else</span></li>
        </ul>
        <ul class=t2>
            <li class='item'>method : <span class='val'>GET</span></li>
            <li class='item'>uri : <span class='val'>/status</span></li>
        </ul>
    </li>
    <li class='item'>Top Item 3 is a list</li>
</ul>

jQuery

$('.t0').on('click', function click(e) {
    $(e.target).closest('ul').slideUp();
});

http://jsfiddle.net/userdude/ksVUY/

EDIT : Or is this more what you were after? The problem is the <ul><ul> , which is invalid markup, so it depends on what you're doing with that specific part of the markup.

To answer the question (which doesn't seem to be what was actually wanted but others may stumble over the question and be looking for an answer), to find the "lowest" UL you can use getElementsByTagName, which returns a collection in DOM order, and return the last element in the collection (if there is one):

function getLowestUL(el) {
  var uls = el.getElementsByTagName('ul');
  return uls.length? uls[uls.length - 1]  : null;      
}

If the provided element is a UL and you want to return that if it's the lowest UL, then:

function getLowestUL(el) {
  var isUL = el.tagName && el.tagName.toLowerCase() == 'ul';
  var uls = (el.nodeType == 1) && el.getElementsByTagName('ul');
  return (uls && uls.length)? uls[uls.length - 1]  : isUL? el : null;      
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM