mmu36478
mmu36478

Reputation: 1345

How to select <li> inside <ul>

Assume I have html structure as

ul
  li //this one
    ul
      li
      li
      li
  li //this one

I don't want to get all li's. As I commented I just want to get first segment li's. How can I select them?

document.querySelectorAll("ul > li");

returns all li's.

edit: actually this is just a snippet of the tree.
I can't modify the structure as adding class or id. I'm looking for an answer to get the list of first layer lis

Upvotes: 3

Views: 28202

Answers (7)

nidstang
nidstang

Reputation: 175

You can get the father's direct children. In this case, the "lis":

console.log(document.querySelector("ul").children)
<ul>
    <li>
        <ul>
            <li></li>
            <li></li>
            <li></li>
        </ul>
    </li>
    <li>
        <ul>
            <li></li>
            <li></li>
            <li></li>
        </ul>
    </li>
</ul>

Upvotes: -2

Oghli
Oghli

Reputation: 2340

Try this it should do the trick :

$("ul > li").not("ul li ul li");

Also this should work in your case :

$("ul").first().children("li");

Upvotes: 1

Val
Val

Reputation: 22797

use :scope

console.log(source.querySelectorAll("ul:scope > li"));
<ul id="source">
  <li>
    this
    <ul>
      <li>not this</li>
      <li>not this</li>
      <li>not this</li>
    </ul>
  </li>
  <li>
  this
  </li>
</ul>

Snapshot from Chrome console:

enter image description here

Upvotes: -1

Quentin
Quentin

Reputation: 943142

You need to select all the li items where the grandparent is not another list item.

:not(li) > * > li {}

This will only work if you don't have extra elements in the markup.

For example it would fail with:

<ul>
  <li>
    <div>
      <ul>
        <li>

A slower, but more reliable, approach would be to get all the list items and then filter out ones which had list item ancestors.

var lis = document.getElementsByTagName('li');
var lis_without_li_ancestors = [];
for (var i = 0; i < lis.length; i++) {
  var element = lis[i];
  if (!has_li_ancestor(element)) {
    lis_without_li_ancestors.push(element);
  }
}

console.log(lis_without_li_ancestors);

function has_li_ancestor(element) {
  var parent = element.parentNode;
  if (parent.tagName.toLowerCase() === "body") {
    return false;
  } else if (parent.tagName.toLowerCase() === "li") {
    return true;
  } else {
    return has_li_ancestor(parent);
  }
}
<ul>
  <li>
    <ul>
      <li>...
    </ul>
</ul>

Upvotes: 6

Arg0n
Arg0n

Reputation: 8423

In jQuery you can use this selector ul > li:not('ul > li > ul > li'):

$("ul > li:not('ul > li > ul > li')").css("background", "green");
ul > li {
  background: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
  <li>
    First
    <ul>
      <li>
        Second
        <ul>
          <li>Third</li>
        </ul>
      </li>
      <li>Second</li>
      <li>Second</li>
      <li>Second</li>
    </ul>
  </li>
  <li>First</li>
  <li>First</li>
  <li>First</li>
</ul>

Upvotes: 5

Frederik Hansen
Frederik Hansen

Reputation: 506

You could traverse the first ul's children and look for li's like the following.

function firstLis() {
  var firstUl = document.querySelector('ul');
  var list = [];
  for(var i = 0; i < firstUl.children.length; i++) {
    var element = firstUl.children[i];
    if(element.tagName === 'LI')
      list.push(element);
  }
  return list;
}

Upvotes: 0

Carl Binalla
Carl Binalla

Reputation: 5401

You can add an id to that specific li:

<li id="someID"></li>

then select it using:

var chosenOne = document.getElementById("someID");

Upvotes: 0

Related Questions