Каков наилучший способ скрыть все divs с одинаковым классом и содержимым в js / jquery?

#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>