javascriptautocompletesearchbarbold

How to bold matched letters when typing in search box using javascript?


How can I type within a search box and have the letters I type turn bold from suggested words? For example, I type "he" in search bar and it looks like this as I type: help. Also, if I type in "lp" the text should appear: help.

I have some code written already and I just want to add this functionality to it, but not sure how to do this. Thank you.

  // List toggle (search bar)
  const searchBar = document.querySelector('#search-bar');
  const searchList = document.querySelector('#search-list');

  searchBar.addEventListener('click', () => {
    searchList.style.display = "block";
  });

  const updateListState = e => {
    const targetId = e.target.id;
    if (targetId !== 'search-bar' && targetId !== 'search-list' && targetId !== 'search-bar-filler' && targetId !== 'search-bar-container' && targetId !== 'search-item-names' && targetId !== 'search-submit' && targetId !== 'search-submit-container') {
      searchList.style.display = "none";
    }
  }
  document.addEventListener('mousemove', updateListState);

  // Letter search (search bar)
  function search_items() {
    let input = document.getElementById('search-bar').value
    input = input.toLowerCase();

    let x = document.getElementsByClassName('search-item-names');

    for (i = 0; i < x.length; i++) {
      if (!x[i].innerHTML.toLowerCase().includes(input)) {
        x[i].style.display = "none";
      }
      else {
        x[i].style.display = "list-item";
      }
    }
  }
  #filler {
    position: absolute;
    background-color: red;
    width: 20px;
    height: 20px;
  }

  #search-list {
    margin-top: 20px;
    width: 150px;
    height: 150px;
    display: none;
  }
  <div id="search-bar-container">
    <input id="search-bar" type="text" name="search" onkeyup="search_items()" placeholder="Search items..">
    <div id="search-bar-filler"></div>
    <div id='search-list'>
      <div id="search-item-names" class="search-item-names">Automotive Degreaser</div>
      <div id="search-item-names" class="search-item-names">Beats by Dre</div>
      <div id="search-item-names" class="search-item-names">JBL Partybox</div>
      <div id="search-item-names" class="search-item-names">Makeup</div>
      <div id="search-item-names" class="search-item-names">Mr Potato Head</div>
      <div id="search-item-names" class="search-item-names">Olympus Camera</div>
      <div id="search-item-names" class="search-item-names">Pillow</div>
      <div id="search-item-names" class="search-item-names">RC Race Car</div>
      <div id="search-item-names" class="search-item-names">Simon Rabbit</div>
      <div id="search-item-names" class="search-item-names">Truth Hoodie</div>
    </div>
  </div>


Solution

  • How about dynamically creating a regular expression based on the user's input and using it to parse and format the matching parts of the suggestions:

    const searchBar = document.querySelector('#search-bar');
    const searchList = document.querySelector('#search-list');
    
    searchBar.addEventListener('click', () => {
        searchList.style.display = "block";
    });
    
    const updateListState = e => {
        const targetId = e.target.id;
        if (targetId !== 'search-bar' && targetId !== 'search-list' && targetId !== 'search-bar-filler' && targetId !== 'search-bar-container' && targetId !== 'search-item-names' && targetId !== 'search-submit' && targetId !== 'search-submit-container') {
            searchList.style.display = "none";
        }
    }
    document.addEventListener('mousemove', updateListState);
    
    function search_items() {
        let input = document.getElementById('search-bar').value;
        input = input.toLowerCase();
        let x = document.getElementsByClassName('search-item-names');
        const regex = new RegExp(input, 'gi');
        for (let i = 0; i < x.length; i++) {
            let originalText = x[i].getAttribute('data-original-text');
            if (!originalText) {
                originalText = x[i].textContent;
                x[i].setAttribute('data-original-text', originalText);
            }
            if (!originalText.toLowerCase().includes(input)) {
                x[i].style.display = "none";
            } else {
                x[i].style.display = "list-item";
                const formattedText = originalText.replace(regex, match => `<b>${match}</b>`);
                x[i].innerHTML = formattedText;
            }
        }
    }
    
    document.getElementById('search-bar').addEventListener('input', function () {
        if (this.value === '') {
            search_items();
        }
    });
    #filler {
        position: absolute;
        background-color: red;
        width: 20px;
        height: 20px;
    }
    
    #search-list {
        margin-top: 20px;
        width: 150px;
        height: 150px;
        display: none;
    }
    <div id="search-bar-container">
        <input id="search-bar" type="text" name="search" onkeyup="search_items()" placeholder="Search items..">
        <div id="search-bar-filler"></div>
        <div id='search-list'>
            <div id="search-item-names" class="search-item-names">Automotive Degreaser</div>
            <div id="search-item-names" class="search-item-names">Beats by Dre</div>
            <div id="search-item-names" class="search-item-names">JBL Partybox</div>
            <div id="search-item-names" class="search-item-names">Makeup</div>
            <div id="search-item-names" class="search-item-names">Mr Potato Head</div>
            <div id="search-item-names" class="search-item-names">Olympus Camera</div>
            <div id="search-item-names" class="search-item-names">Pillow</div>
            <div id="search-item-names" class="search-item-names">RC Race Car</div>
            <div id="search-item-names" class="search-item-names">Simon Rabbit</div>
            <div id="search-item-names" class="search-item-names">Truth Hoodie</div>
        </div>
    </div>