When I type something into the filter, for example the letter "B", the result shows me <div class="item"
with; Ball, Dinosaur "blue" and Robot.
I would like to know how I can make the filter ignore what is inside <span class="tag"
and only search inside the <p class="name"
, so that the final result is only <divs class="item"
with; Ball and Robot
$("#filter").on("keyup", function () {
var value =$(this).val().toLowerCase();
$("#box .item").filter(function () {
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
});
});
#box {
width: 300px;
}
.item {
display: flex;
align-items: center;
gap: 5px;
border: 1px solid;
}
.name {
text-transform: uppercase;
}
.tag {
background: silver;
padding:2px 4px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<input id="filter" type="text" placeholder="Filter..." autocomplete="off">
<div id="box">
<div class="item">
<img src="" alt="img.jpg">
<p class="name">Radio</p>
<span class="tag">red</span>
</div>
<div class="item">
<img src="" alt="img.jpg">
<p class="name">Ball</p>
<span class="tag">red</span>
</div>
<div class="item">
<img src="" alt="img.jpg">
<p class="name">Dinosaur</p>
<span class="tag">blue</span>
</div>
<div class="item">
<img src="" alt="img.jpg">
<p class="name">Robot</p>
<span class="tag">blue</span>
</div>
</div>
"keydown"
eventname. An Input element should also respond to i.e: copy/paste actions etc, not necessarily coming from a keyboard. Instead, use rather the "input"
event.filter()
if there's nothing to filter. Use jQuery's .each()
insteadthis
's .name
child using $(".name", this)
or $(this).find(".name")
Example:
$("#filter").on("input", function () {
const value = $(this).val().trim().toLowerCase();
$("#box .item").each(function () {
const match = $(".name", this).text().toLowerCase().indexOf(value) > -1;
$(this).toggle(match);
});
});
#box {
width: 300px;
}
.item {
display: flex;
align-items: center;
gap: 5px;
border: 1px solid;
}
.name {
text-transform: uppercase;
}
.tag {
background: silver;
padding:2px 4px;
}
<input id="filter" type="text" placeholder="Filter..." autocomplete="off">
<div id="box">
<div class="item">
<img src="" alt="img.jpg">
<p class="name">Radio</p>
<span class="tag">red</span>
</div>
<div class="item">
<img src="" alt="img.jpg">
<p class="name">Ball</p>
<span class="tag">red</span>
</div>
<div class="item">
<img src="" alt="img.jpg">
<p class="name">Dinosaur</p>
<span class="tag">blue</span>
</div>
<div class="item">
<img src="" alt="img.jpg">
<p class="name">Robot</p>
<span class="tag">blue</span>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
Alternatively, you could inverse the logic in that, you first each #box .name
elements, and then toggle the parent .item
using .closest()
$("#filter").on("input", function () {
const value = $(this).val().trim().toLowerCase();
$("#box .name").each(function () {
const match = $(this).text().toLowerCase().indexOf(value) > -1;
$(this).closest(".item").toggle(match);
});
});
#box {
width: 300px;
}
.item {
display: flex;
align-items: center;
gap: 5px;
border: 1px solid;
}
.name {
text-transform: uppercase;
}
.tag {
background: silver;
padding:2px 4px;
}
.hidden {
display: none;
color: red;
}
<input id="filter" type="text" placeholder="Filter..." autocomplete="off"><br>
<div id="box">
<div class="item">
<img src="" alt="img.jpg">
<p class="name">Radio</p>
<span class="tag">red</span>
</div>
<div class="item">
<img src="" alt="img.jpg">
<p class="name">Ball</p>
<span class="tag">red</span>
</div>
<div class="item">
<img src="" alt="img.jpg">
<p class="name">Dinosaur</p>
<span class="tag">blue</span>
</div>
<div class="item">
<img src="" alt="img.jpg">
<p class="name">Robot</p>
<span class="tag">blue</span>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
Also, why use an entire library (jQuery) for such a simple task?
const lower = (val) => val?.trim().toLowerCase();
function filterItems (val) {
document.querySelectorAll("#box .name").forEach(function(elName) {
const match = lower(elName.textContent).includes(lower(val));
elName.closest(".item").classList.toggle("hidden", !match);
});
}
document.querySelector("#filter").addEventListener("input", function () {
filterItems(this.value);
});
#box {
width: 300px;
}
.item {
display: flex;
align-items: center;
gap: 5px;
border: 1px solid;
}
.name {
text-transform: uppercase;
}
.tag {
background: silver;
padding:2px 4px;
}
.hidden {
display: none;
color: red;
}
<input id="filter" type="text" placeholder="Filter..." autocomplete="off">
<div id="box">
<div class="item">
<img src="" alt="img.jpg">
<p class="name">Radio</p>
<span class="tag">red</span>
</div>
<div class="item">
<img src="" alt="img.jpg">
<p class="name">Ball</p>
<span class="tag">red</span>
</div>
<div class="item">
<img src="" alt="img.jpg">
<p class="name">Dinosaur</p>
<span class="tag">blue</span>
</div>
<div class="item">
<img src="" alt="img.jpg">
<p class="name">Robot</p>
<span class="tag">blue</span>
</div>
</div>