UNIT 23 • STAGE 4 OF 7

Live Search

input event, textContent.toLowerCase(), real-time card filtering

UNIT 4 / 7
STEP 1

How Live Search Works

Live search uses the input event: it fires every single time the value inside an input changes. That means it triggers with each keystroke, not just when the user presses Enter.

Inside the event listener, you:

  • Read the current value of the search input
  • Convert it to lowercase with .toLowerCase()
  • Loop through every card
  • Read the card's name and description text with .textContent
  • Convert that to lowercase too
  • Check if it includes the search term using .includes()
  • Show the card if it matches, hide it if not

Why toLowerCase on both sides?

If someone types "cedar" but the card says "Cedar", a direct comparison would fail. Converting both to lowercase first makes the search case-insensitive. Same query, same result regardless of capitalization.

STEP 2

Add the Search Bar CSS

๐Ÿ‘‰ Add to CSS (before #directory): .search-bar {
  margin-bottom: 24px;
  position: relative;
}
.search-bar input {
  width: 100%;
  padding: 14px 20px 14px 48px;
  border: 2px solid #e8e2d8;
  border-radius: 100px;
  font-family: var(--font-body);
  font-size: 1rem;
  color: var(--pine);
  outline: none;
  background: white;
  transition: border-color 0.2s;
}
.search-bar input:focus { border-color: var(--sage); }
.search-icon { position: absolute; left: 18px; top: 50%; transform: translateY(-50%); font-size: 1.125rem; pointer-events: none; }
STEP 3

Add the Search Bar HTML

Above the filter bar, add the search input:

๐Ÿ‘‰ Add above .filter-bar: <div class="search-bar">
  <span class="search-icon">๐Ÿ”</span>
  <input type="text" id="searchInput" placeholder="Search businesses, nations, categories...">
</div>
STEP 4

Add the Search JavaScript

Inside your <script> block, after the filter code, add:

๐Ÿ‘‰ Add to <script> (after filter code): document.getElementById('searchInput').addEventListener('input', function() {
  var query = this.value.toLowerCase().trim();
  cards.forEach(function(card) {
    var text = card.textContent.toLowerCase();
    if (text.includes(query)) {
      card.style.display = '';
    } else {
      card.style.display = 'none';
    }
  });
  if (query === '') {
    cards.forEach(function(card) { card.style.display = ''; });
  }
});

textContent reads all the visible text inside an element, including nested children. So searching "Onamia" finds the Niimi Catering card even though "Onamia" is in the footer, not the business name. The search checks the whole card.

Stage 4 Complete

Live search works. Type anything in the search box and cards filter instantly. Try searching "ojibwe", "cloquet", or "wellness" to see cards appear and disappear in real time.

Next: Stage 5 adds a featured spotlight section above the main grid.

Code Editor
Live Preview