#javascript
#javascript
Вопрос:
Я совершенно новичок в javascript, так что извините мою тупость.
Я хочу, чтобы три разных списка были отфильтрованы в соответствии с тем, что введено внутри текстового поля. Моя функция сортирует только первый список, и только тогда, когда я «получаю элемент по идентификатору», а не по классу.
Моя идея состояла в том, чтобы распределить элементы по классам и, следовательно, отфильтровать все три списка, но это не совсем так работает. Что я могу сделать?
Javascript:
<script>
function filterList() {
var input, filter, ul, li, a, i, txtValue;
input = document.getElementById('searchCombo');
filter = input.value.toUpperCase();
ul = document.getElementsByClassName("drugList");
li = ul.getElementsByTagName('li');
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="searchCombo" onkeyup="filterList()" placeholder="Search for names..">
<ul ID="list1" class="drugList">
<li><a href="#">List 1 element 1</a></li>
<li><a href="#">List 1 element 2</a></li>
<li><a href="#">List 1 element 3</a></li>
</ul>
<ul ID="list2" class="drugList">
<li><a href="#">List 2 element 1</a></li>
<li><a href="#">List 2 element 2</a></li>
<li><a href="#">List 2 element 3</a></li>
</ul>
<ul ID="list3" class="drugList">
<li><a href="#">List 3 element 1</a></li>
<li><a href="#">List 3 element 2</a></li>
<li><a href="#">List 3 element 3</a></li>
</ul>
Комментарии:
1. Вам нужно перебирать
ul
и обрабатывать их по отдельности.2. Или вы могли
querySelectorAll('.drugList li')
бы обработать все lis одновременно
Ответ №1:
Я рекомендую вам использовать Element.querySelectorAll(), для фильтрации элементов li внутри класса drugList. Затем выполните итерацию по элементам:
const nothingFound = document.querySelector('.nothingFound');
nothingFound.style.display="none";
const searchCombo = document.getElementById('searchCombo');
searchCombo.addEventListener("keyup", (e)=> {
const {value} = e.target;
const liElements=Array.from(document.querySelectorAll(".drugList li"));
let count = 0;
liElements.forEach(li => {
li.style.display = "none"
if(li.textContent.toLowerCase().includes(value.toLowerCase())) {
li.style.display = "";
count;
}
});
nothingFound.style.display = count > 0 ? "none": "";
});
<input type="text" id="searchCombo" placeholder="Search for names..">
<ul ID="list1" class="drugList">
<li><a href="#">List 1 element 1</a></li>
<li><a href="#">List 1 element 2</a></li>
<li><a href="#">List 1 element 3</a></li>
</ul>
<ul ID="list2" class="drugList">
<li><a href="#">List 2 element 1</a></li>
<li><a href="#">List 2 element 2</a></li>
<li><a href="#">List 2 element 3</a></li>
</ul>
<ul ID="list3" class="drugList">
<li><a href="#">List 3 element 1</a></li>
<li><a href="#">List 3 element 2</a></li>
<li><a href="#">List 3 element 3</a></li>
</ul>
<span class="nothingFound">Nothing found in this category</span>
Также вам следует рассмотреть возможность использования css-класса вместо element.style.display.
Комментарии:
1. Большое вам спасибо за вашу помощь, она отлично работает! Есть ли какой-либо способ добавить «Ничего не найдено в этой категории», если входные данные не соответствуют ни одному элементу li в ul? И можно ли добавить невидимые дополнительные ключевые слова к каждому ли?
Ответ №2:
Я не уверен, что этот ответ имеет такое большое значение, он заимствован из ответа @lissettdm, и я в основном написал его, чтобы посмотреть, что я напишу. Я разместил здесь на случай, если это кого-то заинтересует.
const select_all = (selector, selectee = document) =>
Array.from(selectee.querySelectorAll(selector));
const hide_item = item => item.style.display = 'none';
const show_item = item => item.style.display = '';
const item_text = item => item.textContent.toLowerCase() ' ' item.dataset.keywords;
const compare = text => item => item_text(item).includes(text);
const has_class = class_name => item => item.className.includes(class_name);
const not_has_class = class_name => item => !has_class(class_name)(item);
const both = (pred_a, pred_b) => item => pred_a(item) amp;amp; pred_b(item);
const filter_list = text => list => {
const lis = select_all("li", list);
let to_show = lis.filter(both( not_has_class('none'), compare(text) ));
if(to_show.length === 0)
to_show = lis.filter(has_class('none'));
lis.forEach(hide_item);
to_show.forEach(show_item);
};
const filter = (event) =>
select_all(".drugList").forEach(
filter_list((event?.target?.value || '').toLowerCase())
);
document.getElementById('searchCombo').addEventListener("keyup", filter);
filter();
<input type="text" id="searchCombo" placeholder="Search for names..">
<ul ID="list1" class="drugList">
<li data-keywords="additional keywords"><a href="#">List 1 element 1</a></li>
<li data-keywords="bob fred"><a href="#">List 1 element 2</a></li>
<li data-keywords="jane neela"><a href="#">List 1 element 3</a></li>
<li class="none">Nothing found in this category</li>
</ul>
<ul ID="list2" class="drugList">
<li><a href="#">List 2 element 1</a></li>
<li><a href="#">List 2 element 2</a></li>
<li><a href="#">List 2 element 3</a></li>
<li class="none">Nothing found in this category</li>
</ul>
<ul ID="list3" class="drugList">
<li><a href="#">List 3 element 1</a></li>
<li><a href="#">List 3 element 2</a></li>
<li><a href="#">List 3 element 3</a></li>
<li class="none">Nothing found in this category</li>
</ul>
Комментарии:
1. Это именно то, что я искал! Большое вам спасибо! Что касается моего второго вопроса с невидимыми дополнительными ключевыми словами, которые можно искать, я просто ввожу ключевые слова с размером шрифта = 0. <li> Список 1 элемент 1 <font style=»font-size: 0px;»> дополнительные ключевые слова для поиска здесь </font></li> Может быть, естьболее элегантное решение, но оно работает.
2. @suverenia, мое предложение было бы включено в редактирование. (Хотя я не совсем понимаю, что каждый подход может сделать для SEO и тому подобного.)