Использование getElementsByClassName для возврата нескольких элементов

#javascript #html

#javascript #HTML

Вопрос:

Я новичок в JS и следую руководству по списку фильтров W3CSchools, которое отлично работает при использовании getElementById, но, как я понимаю, идентификаторы должны быть уникальными для страницы.

Я изменил getElementsByClassName на getElementsByClassName, но, похоже, это не работает. Я хочу фильтровать результаты только в классе myUL, а не в классе otherUL, который можно найти в somedivclass3.

Я также хотел бы иметь возможность сопоставлять целые или частичные слова в любом порядке, например, «diff» будет соответствовать 3 из 4 li, а «different even» должно соответствовать 1 li.

JS:

 <script>
function myFunction() {
  // Declare variables
  var input, filter, ul, li, a, i, txtValue;
  input = document.getElementById('myInput');
  filter = input.value.toUpperCase();
  ul = document.getElementsByClassName("myUL");
  li = ul.getElementsByTagName('li');

  // Loop through all list items, and hide those who don't match the search query
  for (i = 0; i < li.length; i  ) {
    a = li[i].getElementsByTagName("a")[0];
    txtValue = a.textContent || a.innerText;
    if (txtValue.toUpperCase().indexOf(filter) > -1) {
      li[i].style.display = "";
    } else {
      li[i].style.display = "none";
    }
  }
}
</script>
 

HTML:

 <input type="text" id="myInput" placeholder="Search for names..">
<input type="submit" onclick="myFunction()" value="Go">

    <div class="somedivclass1">
       <ul class="myUL">
          <li>Text here</li>
          <li>Different text here</li>
       </ul>
    </div>

    <div class="somedivclass2">
        <ul class="myUL">
           <li>Even more different text here</li>
           <li>Wildly different text here</li>
        </ul>
    </div>

   <div class="somedivclass3">
        <ul class="otherUL">
           <li>Footer link 1</li>
           <li>Footer link 2</li>
        </ul>
    </div>

 

Я бы хотел, чтобы это работало в соответствии с примером в школах W3C: https://www.w3schools.com/howto/howto_js_filter_lists.asp

Спасибо вам за всю помощь!

Комментарии:

1. У вас есть нулевые элементы с именем класса myInput .

2. @CertainPerformance Извините, я обновил код. Я неправильно обновил не ту часть!

Ответ №1:

Я немного переписал вашу функцию, вы можете найти ее в виде фрагмента.

Первый цикл на ‘ul’ с правильным классом, затем второй цикл на ‘li’ С помощью jquery вы бы сделали это только в одной строке 🙂

 function myFunction() {
  // Declare variables
  var input = document.getElementById('myInput');
  var filter = input.value.toUpperCase();
  //var li = document.getElementsByTagName('li');
  var uls = document.getElementsByClassName("myUL");
  for (var i = 0; i < uls.length; i  ) {
    var ul = uls[i];
    var lis = ul.getElementsByTagName("li");

    for (var j = 0; j < lis.length; j  ) {
      var li = lis[j];
      var txtValue = li.textContent || li.innerText;
      if (filtering(txtValue, filter)) {
        li.style.display = "";
      } else {
        li.style.display = "none";
      }
    }
  }
}

function filtering(text, searchString) {
    const regexStr = '(?=.*'   searchString.split(/,|s/).join(')(?=.*')   ')';
    const searchRegEx = new RegExp(regexStr, 'gi');
    return text.match(searchRegEx) !== null;
} 
 <input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for names..">

<div class="somedivclass">
  <ul class="myUL">
    <li>Text here</li>
    <li>Different text here</li>
  </ul>
</div>

<div class="somedivclass2">
  <ul class="myUL">
    <li>Even more different text here</li>
    <li>Widly different text here</li>
  </ul>
</div> 

Комментарии:

1. Спасибо @Julienrevaultd’A … Это работает, но на странице есть другие теги <li>, и они также отфильтровываются, поэтому я хотел ограничить его одним классом. Это также не позволяет вам изменять порядок слов в поиске, например, «разные», а «четный» не возвращает никаких результатов.

2. Может быть, вы могли бы отредактировать свой пост, потому что я не совсем понимаю, чего вы пытаетесь достичь 🙂

3. @Julienrevaultd’A … Я обновил сам вопрос с более подробной информацией. Спасибо вам за вашу помощь до сих пор!

4. @Julienrevaultd’A… Спасибо, Жюльен. Это определенно работает лучше, чем раньше! Единственная проблема заключается в том, что мне все еще нужно ограничить его «myUL», поскольку он также удаляет панировочные сухари и гиперссылки. Ранее я обновил код, добавив дополнительный div и другой класс UL. Не могли бы вы помочь?

5. @nr85: Проверьте последнюю версию, 1-й цикл на ul, затем цикл на li.. вам также следует взглянуть на jquery, это может помочь упростить код.

Ответ №2:

getElementsByClassName() вернет массив элементов, потому что может быть много элементов с одним и тем же классом. Поэтому вместо этого попробуйте сначала перебрать все ul, а затем li:

 
    for (i = 0; i < ul.length; i  ) 
    {
      li = ul[i].getElementsByTagName('li');

      for(j = 0; j< li.length; j  )  
      {
        a = li[j].getElementsByTagName("a")[0];
        txtValue = a.textContent || a.innerText;

        if (txtValue.toUpperCase().indexOf(filter) > -1) 
        {
          li[j].style.display = "";
        } 
        else 
        {
          li[j].style.display = "none";
        }

      }
    }

 

Комментарии:

1. Извините, я должен был выразиться яснее. Я бы хотел, чтобы он просматривал несколько разделов, которые он не выполняет. Я попробовал ваше предложение, но оно отображается только в первом div.

2. @nr85 вы должны перебирать все элементы, возвращаемые, document.getElementsByClassName("myUL") а не только первый элемент.

3. @ErtanHasani Я попробовал код, который вы предоставили, но, к сожалению, я не смог заставить его работать.

4. @nr85 вы добавили j в var часть в начале?

5. @ErtanHasani Да, я это сделал. Вот что у меня получилось: var input, filter, ul, li, a, i, j, txtValue;