#javascript #jquery
#javascript #jquery
Вопрос:
Я хочу отображать только УНИКАЛЬНЫЕ разделы, содержащие текст, введенный в поле поиска. Мой HTML содержит много повторяющихся данных (в настоящее время очень грубых). Смотрите Пример данных ниже:
<div class="faq_item">
<h3><b>FAQ 1</b></h3> <!-- not unique -->
</div>
<div class="faq_item">
<h3><b>FAQ 1</b></h3> <!-- not unique -->
</div>
<div class="faq_item">
<h3><b>FAQ 2</b></h3>
</div>
Затем я добавляю класс ‘filtersearch’ к каждому элементу, если они содержат текст, сохраненный в переменной ‘searchstring’:
for (var i = 0, len = $(".faq_item").length; i < len; i) {
if($(".faq_item")[i].innerHTML.indexOf(searchstring) !== -1) {
$($(".faq_item")[i]).addClass("filtersearch");
}
}
При этом отображаются только divs, содержащие ‘filtersearch’, однако он не скрывает divs с одинаковым содержимым. Вместо того, чтобы выполнять еще один массивный цикл над каждым div с классом filtersearch, каков наилучший подход для отображения только уникальных divs?
Комментарии:
1. Вы используете
$(".faq_item")
несколько раз. Вы действительно должны сохранить коллекцию в переменной, а затем использовать эту переменную вместо этого.2. И почему вы «извлекаете» узел DOM из коллекции jQuery, чтобы затем обернуть его в другой объект jQuery только для добавления class (
$($(".faq_item")[i]).addClass("filtersearch")
) ?
Ответ №1:
Вместо того, чтобы выполнять еще один массивный цикл над каждым div с классом filtersearch, каков наилучший подход для отображения только уникальных divs?
Вы можете сохранить простой хеш-объект найденного текста, скрыв любой div, который уже был замечен.
Использование ванильного JavaScript:
const faqItems = [...document.querySelectorAll('.faq_item')];
function filterAndRemoveDuplicates(searchstring) {
const foundText = {};
faqItems.forEach(item => {
const text = item.querySelector('h3 > b').innerText;
// hide if a duplicate
if (foundText[text]) {
item.classList.add('hidden');
return;
}
// add 'filtersearch' class on searchstring match
if (text.includes(searchstring)) {
item.classList.add('filtersearch');
}
// update hash
foundText[text] = true;
});
console.log('foundText:', JSON.stringify(foundText));
}
document.querySelector('button').onclick = () => {
filterAndRemoveDuplicates('FAQ 1');
};
.faq_item {
border-bottom: 1px solid black;
}
.filtersearch {
color: dodgerblue;
}
.filtersearch:before {
content: ".filtersearch added:";
}
.hidden {
color: #b0b0b0;
}
.hidden:before {
content: ".hidden added:";
}
<button>Search for "FAQ 1" and Hide Duplicates</button>
<hr>
<div class="faq_item">
<h3><b>FAQ 1</b></h3>
</div>
<div class="faq_item">
<h3><b>FAQ 1</b></h3>
</div>
<div class="faq_item">
<h3><b>FAQ 2</b></h3>
</div>
Ответ №2:
Вы можете использовать :contains
и :first
селектор, чтобы найти первый div, в котором есть содержимое для поиска и скрытия других divs.
Демонстрационный код :
var to_search = "FAQ 1"
var divs = $(".faq_item:contains(" to_search "):first").addClass("found")
$(".faq_item").not(divs).hide()
.found {
color: red
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="faq_item">
<h3><b>FAQ 1</b></h3>
</div>
<div class="faq_item">
<h3><b>FAQ 1</b></h3>
</div>
<div class="faq_item">
<h3><b>FAQ 2</b></h3>
</div>