Reputation: 4185
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
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
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 include
d 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