Highlight matched text

Viewed 72

I want to implement highlight feature of Notepad++ in HTML, where notepad++ highlights selected words if found in the file. I have been able to mimic a bit only where the highlight happens only on a mouse click in the same div.
I want to change it so the highlight happens in div2 when text is selected in div1 and is found in div2, else div2 is same as div1. Also it should work except any mouse click and with multi words.

notepad++ demo

<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>highlight matching text</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <style>
    .found {
      color: red;
    }
  </style>
  <script>
    function replaceText() {
      $("#div1").find(".found").removeClass("found");
      var searchword = $("#searchtxt").val();
      var custfilter = new RegExp(searchword, "ig");
      var repstr = "<span class='found'>" + searchword + "</span>";
      if (searchword != "") {
        $('#div1').each(function() {
          $(this).html($(this).html().replace(custfilter, repstr));
        })
      }

    }
  </script>
</head>

<body>
  <input type="text" id="searchtxt" placeholder="keyword" />
  <input type="button" value="search" onClick="replaceText();" id="highlightButton" />

  <p id="div1">I'm here but not here. Not here also. But I'm here too.</p>

  <p id="div2"> </p>
</body>

</html>

1 Answers

Try this:

const div1 = document.getElementById("div1"),
      div2 = document.getElementById("div2"),
      isParent = (obj, parent) => !obj || obj === parent ? obj : isParent(obj.parentNode, parent);
/*
isParent is a short version of:

function isParent(obj, parent)
{
  if (!obj || obj === parent)
  {
    return obj;
  }
  else
  {
    return isParent(obj.parentNode, parent);
  }
}

*/


div1.addEventListener("click", e =>
{
  const sel = document.getSelection();
/*
  sel.anchorNode: element the selection started at
  sel.focusNode: element the selection ended at
  we only accept selection of div1 text
  check if both of these elements are children of div1, otherwise exit
*/
  if (!isParent(sel.anchorNode, div1) || !isParent(sel.focusNode, div1))
    return;

  const text = sel.toString() //get selected text
               .trim() //trim trailing white spaces
                //make it html friendly
               .replace(/&/g, "&amp;")
               .replace(/</g, "&lt;")
               .replace(/>/g, "&gt;")
                //make it regex friendly
               .replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');

  if (text === "")
    return;

  div2.innerHTML = div2.innerHTML
                    //remove old highlightings
                    .replace(/<mark>([^<]*)?<\/mark>/g, "$1")
                    // convert selected text into regex,
                    // search and enclose found strings with <mark></mark>
                    .replace(new RegExp("(" + text + ")", "gi"), '<mark>$1</mark>'); //add new highlighting
});
/*
  second paragraph marks
*/
p:first-child + p mark {
  background-color: lightgreen;
}

#div1, #div2
{
  border: 1px solid black;
  padding: 1em;
}

#div2
{
  background-color: #E0E0E0;
  margin-top: -1px;
}
<div id="div1">
  <p>I'm here but not here. Not here also. But I'm here too. &lt;span&gt;blah&lt;/span&gt;</p>
</div>

<div id="div2">
  <p>But I'm here too. <span>blah</span> &lt;span&gt;blah&lt;/span&gt;</p>
  <p>And also here.</p>
  <p>Third paragraph, has "And also here."</p>
</div>

Related