calvin2011
calvin2011

Reputation: 387

How to display all nested list elements according to input text search?

I'm creating a web application that returns an NBA player's name and jersey number when a user searches for a player (and the match is found).

I can return the name that has been searched, but I cannot return the jersey number.

I've tried setting style.display = true, which works for the name node, but I can't get this to work on the jersey node.

Here's how my HTML has been created with DOM manipulation from a JSON:

function searchPlayer() {
  let input, filter, ul, li, playerName, i;
  input = document.getElementById("search-bar");
  filter = input.value.toUpperCase();
  li = document.getElementById("player-list").getElementsByTagName("li");

  Object.keys(li).forEach(function(name) {
    playerName = li[name].innerHTML;

    if (playerName.toUpperCase().indexOf(filter) > -1) {
      li[name].style.display = true;
    } else {
      li[name].style.display = "none";
    }
  })
}
<div id="player-list-section">
  <ul id="player-list">
    <li id="player">
      <li id="full-name">Alex Abrines</li>
      <li id="jersey">Jersey: 8</li>
    </li>
    <li id="player">
      <li id="full-name">Quincy Acy</li>
      <li id="jersey">Jersey: 13</li>
    </li>
  </ul>
</div>

<input id="search-bar" />
<button onclick="searchPlayer()">Search</button>

I know I can access the child node of player using e.g. li[name].childNode[1] (which returns the jersey li), but I can't call anything on this, such as .innerHTML or .style.display.

How can I return both the name and the jersey?

Upvotes: 1

Views: 462

Answers (1)

Zakaria Acharki
Zakaria Acharki

Reputation: 67525

You need to use list-item instead of true if you want to show the list items after hidding them using display:none and use .closest(".player") to toggle the display of the parent instead:

if (playerName.toUpperCase().indexOf(filter) > -1) {
  li[name].closest(".player").display = 'block';
} else {
  li[name].closest(".player").display = "none";
}

NOTE 1: You need to validate your structure li can't be a parent of another li, check my updated HTML format.

NOTE 2: You need also to replace the duplicate id by common classes since the identifier must be unique in the same document.

function searchPlayer() {
  let input, filter, ul, li, playerName, i;
  input = document.getElementById("search-bar");
  filter = input.value.toUpperCase();
  li = document.querySelectorAll("#player-list .full-name");

  Object.keys(li).forEach(function(name) {
    playerName = li[name].innerHTML;

    if (playerName.toUpperCase().indexOf(filter) > -1) {
      li[name].closest(".player").style.display = 'list-item';
    } else {
      li[name].closest(".player").style.display = "none";
    }
  })
}
<input id="search-bar" oninput='searchPlayer()'>

<div id="player-list-section">
  <ul id="player-list">
    <li class="player">
      <ul>
        <li class="full-name">Alex Abrines</li>
        <li class="jersey">Jersey: 8</li>
      </ul>
    </li>
    <li class="player">
      <ul>
        <li class="full-name">Quincy Acy</li>
        <li class="jersey">Jersey: 13</li>
      </ul>
    </li>
  </ul>
</div>

Upvotes: 1

Related Questions