JQuery: содержит полное слово - PullRequest
1 голос
/ 04 апреля 2019

Я хочу выбрать родительский элемент по его дочернему тексту, но по полному совпадению (два имени).

<div class="card">
   <div class="name">buggy</div>
   <div class="name">fruits</div>
</div>
<div class="card"> <!-- select only this one card -->
   <div class="name">bug</div>
   <div class="name">fruits</div>
</div>

$('.card:contains("bug"):contains("fruits")') - в этом случае не работает, поскольку он захватывает две карты, начиная с buggy содержит bug тоже.

$('.card').filter(function() {
    return $(this).find('.name').text() === "bug" && $(this).find('.name').text() === "fruits";
});

Это также не работает.

Как реализовать полное совпадение текста дочернего элемента?

Ответы [ 2 ]

2 голосов
/ 04 апреля 2019

Используйте .filter, как вы делаете, но создайте массив текстового содержимого каждого элемента, а затем проверьте, является ли каждое слово, которое вы ищете, include d в массиве:

const $filteredCards = $('.card').filter(function() {
  const nameTexts = $(this)
    .children()
    .map(function() { return $(this).text() })
    .get();
  return nameTexts.includes('bug') && nameTexts.includes('fruits')
});

$filteredCards.css('background-color', 'yellow');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="card">
   <div class="name">buggy</div>
   <div class="name">fruits</div>
</div>
<div class="card"> <!-- select only this one card -->
   <div class="name">bug</div>
   <div class="name">fruits</div>
</div>
1 голос
/ 04 апреля 2019

Метод text() возвращает текстовое содержимое коллекции, поэтому он не проверяет все элементы .name. Хотя это утверждение не имеет никакого смысла $(this).find('.name').text() === "bug" && $(this).find('.name').text() === "fruits", так как $(this).find('.name').text() возвращает одно и то же значение и сравнивает его с другой строкой, поэтому оно никогда не становится истинным, по крайней мере, один из них становится истинным.

Чтобы заставить его работать, отфильтруйте элементы по отдельности, которые удовлетворяют вашему условию, и, наконец, получите общие элементы.

// filter out elements which contains 'bug'
$('.card .name').filter(function() {
    return $(this).text() === "bug";
  })
  // get its parent
  .closest('.card')
  // filter elements in both
  .filter(
    // filter out elements which contains 'fruits'
    $('.card .name').filter(function() {
      return $(this).text() === "fruits";
    })
    // get its parent
    .closest('.card')
  );

let $ele = $('.card .name').filter(function() {
  return $(this).text() === "bug";
}).closest('.card').filter($('.card .name').filter(function() {
  return $(this).text() === "fruits";
}).closest('.card'));

$ele.addClass('test')
.test {
  color: red
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="card">
  <div class="name">buggy</div>
  <div class="name">fruits</div>
</div>
<div class="card">
  <!-- select only this one card -->
  <div class="name">bug</div>
  <div class="name">fruits</div>
</div>

Или альтернативный подход заключается в реализации нескольких вложенных фильтров внутри основного фильтра.

// iterate over the car divs
$('.card').filter(function() {
  // iterate over the strings to check each of them
  return ['fruits', 'bug'].every(str => $('.name', this).filter(function() { // get .name inside and filter based on match and check length of filtered
    return $(this).text() === str;
  }).length);
});

let $ele = $('.card').filter(function() {
  return ['fruits', 'bug'].every(str => $('.name', this).filter(function() {
    return $(this).text() === str;
  }).length);
});


$ele.addClass('test')
.test {
  color: red
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="card">
  <div class="name">buggy</div>
  <div class="name">fruits</div>
</div>
<div class="card">
  <!-- select only this one card -->
  <div class="name">bug</div>
  <div class="name">fruits</div>
</div>
...