mr.incredible
mr.incredible

Reputation: 4185

jQuery :contains full word

I want to select parent element by it's child text but by full match (two names).

<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")') - doesn't work in this case because it grabs two cards since buggy contains bug too.

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

This also doensn't work.

How to implement full match of text of the child element?

Upvotes: 2

Views: 365

Answers (2)

Pranav C Balan
Pranav C Balan

Reputation: 115222

The text() method returns text content among the collection so it won't check all the .name elements. Although this statement doesn't make any sense $(this).find('.name').text() === "bug" && $(this).find('.name').text() === "fruits" since $(this).find('.name').text() returns the same value and comparing against different string, so it never gets true atmost one of then get true.

To make it work filter out elements separately which satisfies your condition separately and finally get elements which are in common.

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


Or alternate approach is to implement multiple nested filters inside the main filter.

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

Upvotes: 1

CertainPerformance
CertainPerformance

Reputation: 370729

Use .filter, like you're doing, but construct an array of the text content of each element, and then check whether every word you're looking for is included in the array:

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>

Upvotes: 2

Related Questions