Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filter elements by search values - multiple words

Tags:

jquery

filter

I have a list made of DIV's and an INPUT search box:

<input id="search" type="text">

<div>Caramel Apples</div>
<div>Strawberry Lemonade</div>
<div>Pineapple Cake</div>
<div>Apple Pie</div>
<div>Cherry Ice Cream</div>

While typing in the search box, I want to do a live update to show only those rows that match ALL the search keywords, even if they are partials. If I type "app ca", I should get "Caramel Apples" and "Pineapple Cake".

I have not been able to make the standard jQuery Attribute Contains Selector [name*="value"] work for more than one "value". Multiple Attribute Selector doesn't seem to work either, probably because I am operating on just one attribute, not multiple.

As an added bonus, I also need it to be case-insensitive.

I found a similar question HERE, but it only does an OR filter on the keywords, not an AND. Nor is it dynamic, e.g. keywords being typed in. It may be a good start, but I don't know how to modify it to apply to my situation.

like image 672
jfriend Avatar asked Dec 18 '25 14:12

jfriend


1 Answers

  • Trim the input value and split by multiple spaces to get an Array
  • Compare the search Array with each element text string (both as lowercase) using String.prototype.includes() in combination with Array.prototype.some() - or Array.prototype.every() if you need that kind of search.
  • Use a Utility class like u-none {display: none}
  • Toggle that utility class using Element.classList.toggle() or jQuery's .toggleClass() Method

Filter items by multiple search words

For multiple words, you'll have to split by space and treat each part as a valid search query:

const EL_input = document.querySelector("#search");
const ELS_items = document.querySelectorAll("div");

const filterItems = (text) => {
  const words = text.trim().toLowerCase().split(/ +/);
  console.log(words);
  ELS_items.forEach(EL => {
    const cont = EL.textContent.trim().toLowerCase();
    const hasWord = words.some((w) => cont.includes(w));
    EL.classList.toggle("u-none", !hasWord);
  });
}

EL_input.addEventListener("input", () => {
  filterItems(EL_input.value);
});
/* Utility classes */

.u-none {
  display: none;
}
<input id=search type=text autocomplete=off>

<div>Caramel Apples</div>
<div>Strawberry Lemonade</div>
<div>Pineapple Cake</div>
<div>Apple Pie</div>
<div>Cherry Ice Cream</div>

Filter items by single search word

  • Compare the search string with each element text string (both as lowercase) using String.prototype.includes()

const EL_input = document.querySelector("#search");
const ELS_items = document.querySelectorAll("div");
// BE MORE SPECIFIC WITH YOUR SELECTORS! Use a class instead of "div"

const filterItems = (text) => {
  text = text.trim().toLowerCase();
  ELS_items.forEach(EL => {
    const cont = EL.textContent.trim().toLowerCase();
    const hasText = cont.includes(text);
    EL.classList.toggle("u-none", !hasText);
  });
}

EL_input.addEventListener("input", () => {
  filterItems(EL_input.value);
});
/* Utility classes */

.u-none {
  display: none;
}
<input id="search" type="text" autocomplete=off>

<div>Caramel Apples</div>
<div>Strawberry Lemonade</div>
<div>Pineapple Cake</div>
<div>Apple Pie</div>
<div>Cherry Ice Cream</div>

Using jQuery is quite similar, with the only difference of loading a relatively big library unnecessarily (at this date (2021.)), but the code is quite the same:

jQuery - Filter items by multiple search words

const $input = $("#search");
const $items = $("div");
// BE MORE SPECIFIC WITH YOUR SELECTORS! Use a class instead of "div"

function filterItems(text) {
  const words = text.trim().toLowerCase().replace(/ +/g, " ").split(" ");
  $items.each(function() {
    const cont = $.trim($(this).text().toLowerCase());
    const hasText = words.some((w) => cont.includes(w));
    $(this).toggleClass("u-none", !hasText);
  });
}

$input.on("input", function() {
  filterItems($(this).val());
});
/* Utility classes */

.u-none {
  display: none;
}
<input id="search" type="text" autocomplete=off>

<div>Caramel Apples</div>
<div>Strawberry Lemonade</div>
<div>Pineapple Cake</div>
<div>Apple Pie</div>
<div>Cherry Ice Cream</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

jQuery - Filter items by single search word

const $input = $("#search");
const $items = $("div");
// BE MORE SPECIFIC WITH YOUR SELECTORS! Use a class instead of "div"

function filterItems(text) {
  text = text.trim().toLowerCase();
  $items.each(function() {
    const cont = $.trim($(this).text().toLowerCase());
    const hasText = cont.includes(text);
    $(this).toggleClass("u-none", !hasText);
  });
}

$input.on("input", function() {
  filterItems($(this).val());
});
/* Utility classes */

.u-none {
  display: none;
}
<input id="search" type="text" autocomplete=off>

<div>Caramel Apples</div>
<div>Strawberry Lemonade</div>
<div>Pineapple Cake</div>
<div>Apple Pie</div>
<div>Cherry Ice Cream</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
like image 180
Roko C. Buljan Avatar answered Dec 20 '25 08:12

Roko C. Buljan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!