skip to Main Content

I have a div with a handful of spans, each span containing one word. The user can tap/click a word to select it, but I’m also trying to implement keyboard input.

I’d like to highlight each letter in any matching words as the user types.

For example, let’s say we have these five words:

banana
cat
baby
ball
candy

If the user types "ba" I’d like to highlight the first two letters in "banana" , "baby" , and "ball" (then if they type an ‘n’, it would un-highlight the letters in "baby" and "ball" and would highlight the first three letters of "banana" only)

These words are all dynamically generated from a word list array, so I’m hoping there might be a way to achieve this highlighting without having to wrap every single letter in a span.

Is this possible?

2

Answers


  1. To prevent the addon of span element:

    You may use the linear-gradient css style to highlight specific letter sequence. Please modify the code below to cope with your need since you may need to highlight multiple letters occurrences within a span element.

    /* index.css */
    /* this may be applied if you use <p> other than <span> to wrap your text
    p {
        display: inline-block;
    }
    
    /* update: to ensure each letter has same width */
    span {
        font-family: monospace;
    }
    
    
     <input type="text" id="searchInput" placeholder="Type to highlight">
      <div id="wordContainer">
        <span>banana</span>
        <span>cat</span>
        <span>baby</span>
        <span>ball</span>
        <span>candy</span>
      </div>
    
    <script>
    function highlightWords() {
      const searchInput = document.getElementById("searchInput").value.toLowerCase();
      const spans = document.querySelectorAll("#word-container span");
    
      spans.forEach((span) => {
        const word = span.textContent.toLowerCase();
        const wordLength = word.length;
        const inputLength = searchInput.length;
    
        // Find the start and end index of the search input within the word
        const startIndex = word.indexOf(searchInput);
        const endIndex = startIndex + inputLength;
    
        if (startIndex !== -1 && searchInput.length > 0) {
          const startPercentage = (startIndex / wordLength) * 100;
          const endPercentage = (endIndex / wordLength) * 100;
    
          // Apply the gradient background
          span.style.background = `linear-gradient(
            to right,
            white 0%,
            white ${startPercentage}%,
            yellow ${startPercentage}%,
            yellow ${endPercentage}%,
            white ${endPercentage}%,
            white 100%
          )`;
        } else {
          span.style.background = "none"; // Reset background if no match
        }
      });
    }
    </script>
    
    Login or Signup to reply.
  2. You can get the text and input and then split the text into words using split(), then iterate over that array and check if the value startsWith() whatever string the input is passing during an input eventListener. Placing the logic in a map method you can reformat the searched string and concatenate the leftover part of the word using substring() or splice(). Join the mapped array and then set the elements innerHTML to the newly formatted string with a highlight class.

    See further comments in the code snippet

    // define variables for the elements in HTML
    const par = document.querySelector('#text');
    const input = document.querySelector('#matchText');
    
    // callback passing in the event
    const searchtext = e => {
      // define the input value toLowerCase
      const searchText = e.target.value.toLowerCase();
      // get the text content of the element you wish to search through
      const textCont = par.textContent;
    
      // split the text into words using a whitespace
      const words = textCont.split(' ');
    
      // iterate over the words with map and define word
      const highlightedText = words.map(word => {
    
        // check and see if the word startWith the searchText string
        if (word.toLowerCase().startsWith(searchText) && searchText !== '') {
    
          // return the formatted string of the word 
          // with the letters highlighted using substring
          return `<span class="highlight">${word.substring(0, searchText.length)}</span><span>${word.substring(searchText.length, word.length)}</span>`;
        }
    
        // return the non-matching words in teh original string
        return word;
    
        // create a string with the array values using .join()
      }).join(' ');
    
      // set the innerHTML to the new string containing the highlighted string
      par.innerHTML = highlightedText;
    }
    
    // eventListener using an input event, pass the callback
    input.addEventListener('input', searchtext);
    .highlight {
      background-color: yellow;
    }
    <p id="text">
      <span>Banana</span>
      <span>ball</span>
      <span>ballistic</span>
      <span>cat</span>
      <span>chat</span>
      <span>change</span>
      <span>chap</span>
      <span>character</span>
      <span>color</span>
      <span>people</span>
      <span>peel</span>
      <span>peon</span>
    </p>
    <input type="text" id="matchText" name="matchingText">
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search