0

Here is a part of my HTML which is enough to see the problem, and JavaScript code where i don't know how to bold every letter/word when user's input is matched to my title or body. I am using JSON API holder to fetch the /posts when user input some text. If someone can finish my boldSearchedWord() functions, thanks a lot!

HTML:

<div class="wrap-container">
 <div class="search-bar">
   <i class="fas fa-search"></i>
    <input type="text" placeholder="Please, start entering the text to search" class="search">
    <div class="items"></div>
 </div>
</div>

JavaScript:

// Ataching event listener
let myInput = document.querySelector('.search');
//setup before functions
let typingTimer;
let doneTypingInterval = 500;
let searchElement = document.querySelector('.items');
let sorryItemElement = '<div class="sorry-wrapper"><i class="fas fa-truck-loading"></i><a href="#" class="sorry-msg">Sorry, we couldn\'t find anything :(</a><div>';
let loadingItemElement = '<div class="loading"><i class="fas fa-spinner"></i> Loading...</div>';
// keyup event would be better, but it doesn't recognize backspace because backspace it's not printable key
myInput.addEventListener('keydown', () => {
    clearTimeout(typingTimer);
    if (myInput.value) {
        typingTimer = setTimeout(searchBodyTitle, doneTypingInterval);
    }
});


async function searchBodyTitle() {
    const query = myInput.value;
    // early return
    if (query === '') {
        clearItems();
        return;
    }

    try {
        startLoading();
        const result = await fetch(`https://jsonplaceholder.typicode.com/posts?q=${query}`);
        const data = await result.json();
        const posts = data.map(post => {
            return {
                title: post.title,
                body: post.body
            }
        });
        finishLoading();
        if (posts.length === 0) {
            searchElement.innerHTML += sorryItemElement;
        } else {
            posts.forEach(post => {
                let slicedTitle = post.title.slice(0, 30);
                let slicedBody = `${post.body.slice(0, 50)} ...`;
                newElement(slicedTitle, slicedBody);
            });
        }
        return data;
    } catch (error) {
        finishLoading();
        console.log(error);
    }
}

function clearItems() {
    searchElement.innerHTML = '';
}

function newElement(title, body) {
    let newElement = `<a href="#" class="item-options"><span class="dropdown-title">${title}</span><span class="dropdown-body">${body}</span></a>`;
    searchElement.innerHTML += newElement;
}

function startLoading() {
    clearItems();
    searchElement.innerHTML += loadingItemElement;
}

function finishLoading() {
    clearItems();
}

function boldSearchedWord() {
    let titles = document.querySelectorAll('.dropdown-title');
   
}
Pavle Ilic
  • 25
  • 6

1 Answers1

0

You could use the code below.

It performs a replacement with a <b> in the matched value. There is a demo in the end.

function escapeRegex(string) {
    return string.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}

function boldSearchedWord(text, search) {
  const escapedSearch = escapeRegex(search);

  // \\b: find just the words STARTING with the searched value 
  // g: find all words and not just the first one
  // m: find in multiple lines
  // i: ignore case sensitive
  const regexpExpression = new RegExp('\\b('+ escapedSearch + ')\\b', 'gmi');
  
  let additionalIndexValue = 0;
  let newText = text;

  while ((match = regexpExpression.exec(text)) !== null) {
    const boldMatch = '<b>'+ match[0] +'</b>';
    const matchStart = match.index + additionalIndexValue;
    const matchEnd = regexpExpression.lastIndex + additionalIndexValue;
    
    newText = newText.substr(0, matchStart) + boldMatch + newText.substr(matchEnd);
    
    // After each match, a '<b></b>' HTML element is added surround the searched string in the text
    // Then we need to add the additional value to the index for a correct replacement
    additionalIndexValue += 7; 
  }
  
  return newText;
}

Credits:

  1. Is there a RegExp.escape function in JavaScript?
  2. Replace substring in string with range in JavaScript

Demo: https://jsfiddle.net/7rmfqxt0/

Zavarock
  • 341
  • 3
  • 7