javascripthtmlcsstags

Why does my function not show the correct format with HTML tags when highlighting matches?


I am trying to create a match strings highlighting matches in the following code. But, somehow, the results or output does not appear in the format I am setting in the div results (UL/LIs). Actually, I'would appreciate your advice to tackle this issue.

element.innerHTML = highlightedText;  //if I comment this line, then the text works but, without format

function wrapMatchesInSpan(element, searchTerm) {
  var text = element.textContent;
  var regex = new RegExp(searchTerm, 'gi');
  var matches = text.match(regex);
  if (matches && matches.length > 0) {
    var highlightedText = text.replace(regex, function(match) {
      return '<span class="highlight">' + match + '</span>';
    });
    element.innerHTML = highlightedText; //if I comment this line, then the text works but, without format
  }
}

function search() {
  var searchTerm = document.getElementById("searchInput").value.toLowerCase();
  var listItems = document.getElementById("searchResults").getElementsByTagName("li");
  var teamItems = document.getElementById("searchTeams").getElementsByTagName("li");
  var resultsDiv = document.getElementById("results");

  for (var i = 0; i < listItems.length; i++) {
    var listItem = listItems[i];
    var text = listItem.textContent.toLowerCase();

    if (text.includes(searchTerm)) {
      listItem.innerHTML = listItem.innerHTML.replace(new RegExp(searchTerm, 'gi'), function(match) {
        return '<span class="highlight">' + match + '</span>';
      });
      listItem.style.display = "list-item";
    } else {
      listItem.innerHTML = ''; // Clear the content
      listItem.style.display = "none";
    }
  }

  var hideAllTeams = true;
  for (var j = 0; j < teamItems.length; j++) {
    var teamItem = teamItems[j];
    var teamText = teamItem.textContent.toLowerCase();

    if (teamText.includes(searchTerm)) {
      teamItem.style.display = "list-item";
      hideAllTeams = false;
    } else {
      teamItem.style.display = "none";
    }
  }

  if (searchTerm === "") {
    resultsDiv.style.display = "none";
  } else {
    resultsDiv.style.display = "block";
  }

  if (hideAllTeams) {
    teamsDiv.style.display = "none";
  } else {
    teamsDiv.style.display = "block";
  }
}
* {
  box-sizing: border-box;
}

#results {
  display: none;
  margin-top: 10px;
}

#searchResults {
  background-color: #f6f6f6;
  margin-top: -2px;
  width: 430px;
  height: 200px;
  border: 1px solid #ddd;
}

#searchInput {
  background-image: url('/css/searchicon.png');
  background-position: 10px 12px;
  background-repeat: no-repeat;
  width: 425px;
  font-size: 14px;
  padding: 12px 20px 12px 40px;
  border: 1px solid #ddd;
  margin-bottom: 12px;
}

#searchTeams {
  list-style-type: none;
  width: 425px;
  font-size: 16px;
  border: 1px solid #ddd;
}

#searchTeams li a {
  color: 1px solid #ddd;
  margin-top: -2px;
  /* Prevent double borders */
  background-color: #f6f6f6;
  background-position: 10px 12px;
  font-weight: bold;
  padding: 12px;
  text-decoration: none;
  font-size: 19px;
  color: black;
  display: block
}

#teams {
  color: 1px solid #ddd;
  margin-top: -2px;
  /* Prevent double borders */
  padding: 12px;
  text-decoration: none;
}

#searchTeams li a:hover:not(.header) {
  background-color: #aeadca;
  width: 100%;
  padding-left: 35px;
  color: blue;
}

ul.scroll {
  background-color: #f6f6f6;
  width: 600px;
  height: 500px;
  overflow-x: hidden;
  overflow-y: auto;
  text-align: left;
  padding: 20px;
}

.highlight {
  background-color: yellow;
}
<!DOCTYPE html>
<html>

<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>NACC-Teams-Locator</title>
</head>

<body>
  <div id="teams">
    <h2>ACC Teams:</h2>
    <input type="text" id="searchInput" placeholder="Search for teams / keywords / services..." oninput="search()">
    <ul class="scroll" id="searchTeams">
      <li style="display: list-item;"><a href="#">WMAA</a></li>
      <li style="display: list-item;"><a href="#">MobileInf</a></li>
      <li style="display: list-item;"><a href="#">MSM</a></li>
      <li style="display: list-item;"><a href="#">SECAPPS</a></li>
      <li style="display: list-item;"><a href="#">SECAPPS</a></li>
    </ul>
    <div id="results">
      <h3>Services supported by team:</h3>
      <ul id="searchResults" class="scroll">
        <li style="display: none;">
          <h3>MobileInf:</h3><br> -APIs<br> -Layer 7<br> -Gloo<br> -Gateways<br> -API portal</li>
        <li style="display: none;">
          <h3>Midrange Servers Management (MSM):</h3> -Servers<br> -Filesystem usage<br> -Patching<br> -Root<br> -API portal</li>
        <li style="display: none;">
          <h3>SECAPPS:</h3> -Okta<br> -Passwordsafe<br> -OIG<br> -Forgerock<br> -Evidian <br> -Cyberark<br> -go/password</li>
        <li style="display: none;">
          <h3>Hadoop:</h3> -Hive<br> -Cloudera<br> -Hue/Ambari<br> -Yarn/HDFS<br> -Hadoop Data Movement</b>
        </li>
      </ul>
    </div>
  </div>
  <p>
    //<img src="" />
  </p>
</body>

</html>


Solution

  • As already mentioned in the comments, the innerHTML gets changed every time when search() is invoked. From the second call on, the search characters cannot be found because there exists <span></span> tags. However, you can circumvent this problem by deleting the corresponding parts from innerHTML each time when search() is called.

      for (var i = 0; i < listItems.length; i++) {
        var listItem = listItems[i];
        var text = listItem.textContent.toLowerCase();
    
        listItem.innerHTML = listItem.innerHTML.replaceAll('<span class="highlight">', '') 
        listItem.innerHTML = listItem.innerHTML.replaceAll('</span>', '') 
    
        ...
    

    enter image description here