Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Search and highlight text on page while keeping html structure

Similar questions might have been asked already, but please read the details carefully.

I am using kind of a self-made autocomplete, and now I want to highlight the search term inside the result set. This works so far, but only on plain text. The problem is: I need to keep the html structure, if there is one in the result div. Please see my sample: currently I am loosing the included span's with the class bold. How can I keep them?

Thank you for any advice!

$('#box').keyup(function () {
  const valThis = this.value;
  const length  = this.value.length;

  $('.objType').each(function () {
    const text  = $(this).text();
    const textL = text.toLowerCase();
    const position = textL.indexOf(valThis.toLowerCase());

    if (position !== -1) {
      const matches = text.substring(position, (valThis.length + position));
      const regex = new RegExp(matches, 'ig');
      const highlighted = text.replace(regex, `<mark>${matches}</mark>`);

      $(this).html(highlighted).show();
    } else {
    	$(this).text(text);
      $(this).hide();
    }
  });

});
input[type="text"] { 
    width: 50%;
    margin:10px;
    padding: 5px;
    float:left;
    clear:left;
}
div{
  float:left;
  clear:left;
  margin:10px 10px;
}
.bold {
  font-weight: 700;
}
table td {
  border: solid 1px #ccc;
  padding: 3px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<input placeholder="Filter results" id="box" type="text" />

<div class="objType" id="item1">
  <span class="bold">Accepted</span> Event Relation
  <table>
  <tr>
    <td>Lorem</td>
    <td>ipsum</td>
  </tr>
  </table>
</div>
<div class="objType" id="item2">
  Case <span class="bold">Status</span> Value
  <table>
  <tr>
    <td>Lorem</td>
    <td>ipsum</td>
  </tr>
  </table>
</div>
<div class="objType" id="item3">
  External <span class="bold">Data Source</span>
  <table>
  <tr>
    <td>Lorem</td>
    <td>ipsum</td>
  </tr>
  </table>
</div>
<div class="objType" id="item4">
  Navigation <span class="bold">Link</span> Set
  <table>
  <tr>
    <td>Lorem</td>
    <td>ipsum</td>
  </tr>
  </table>
</div>

PS: a JSFiddle for this in addition might be helpful => https://jsfiddle.net/SchweizerSchoggi/6x3ak5d0/7/

like image 701
JonSnow Avatar asked Dec 04 '19 14:12

JonSnow


People also ask

How do I highlight search results in HTML?

The <mark> HTML element is used to highlight text, so is the perfect element for this use case.

How do you highlight certain text in HTML?

The HTML <mark> tag is used to mark or highlight text that is of special interest or relevance in an HTML document. Browsers traditionally render the text found within the <mark> tag as text with a yellow background color.


2 Answers

Here is a possible base using only native javascript. This behave somewhat like CTRL+F.

This seems to preserve the <td> elements.

The clear function replace the mark elements by a wbr element:

On UTF-8 encoded pages, <wbr> behaves like the U+200B ZERO-WIDTH SPACE code point. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/wbr

function mark(it){
  clearIt()
  if (it.length > 2){
    let c = new RegExp(it, "ig") 
    main.innerHTML = main.innerHTML.replace(c,"<mark>"+it+"</mark>")
  }  
}

function clearIt(){
  let b = new RegExp("mark>", "ig") 
  main.innerHTML = main.innerHTML.replace(b,"wbr>")
}

mark(search.value)
input[type="text"] { 
    width: 50%;
    margin:10px;
    padding: 5px;
    float:left;
    clear:left;
}
div{
  float:left;
  clear:left;
  margin:10px 10px;
}
.bold {
  font-weight: 700;
}
table td {
  border: solid 1px #ccc;
  padding: 3px;
}
<input onfocusout="clearIt()" oninput="mark(this.value)"  value="Lorem" id="search" placeholder="Lorem">
<button onclick="mark(search.value)">SEARCH</button>
<button onclick="clearIt()">CLEAR</button>

<div id="main">
<div class="objType" id="item1">
  <span class="bold">Accepted</span> Event Relation
  <table>
  <tr>
    <td>Lorem</td>
    <td>ipsum</td>
  </tr>
  </table>
</div>
<div class="objType" id="item2">
  Case <span class="bold">Status</span> Value
  <table>
  <tr>
    <td>Lorem</td>
    <td>ipsum</td>
  </tr>
  </table>
</div>
<div class="objType" id="item3">
  External <span class="bold">Data Source</span>
  <table>
  <tr>
    <td>Lorem</td>
    <td>ipsum</td>
  </tr>
  </table>
</div>
<div class="objType" id="item4">
  Navigation <span class="bold">Link</span> Set
  <table>
  <tr>
    <td>Lorem</td>
    <td>ipsum</td>
  </tr>
  </table>
</div>

</div>

By the way the restored/cleared markup isn't the original, to fully restore it, you might need to copy the whole html before marking it up.

like image 162
NVRM Avatar answered Oct 21 '22 05:10

NVRM


Using mark.js plugin

$('#box').on('input', function() {
  const valThis = this.value;

  const options = {
    filter: function(node, term, totalCounter, counter) {
      $(node).parents('.objType').show()
      return true
    }
  };

  $('.objType').unmark({
    done: function() {
      $('.objType')
        .toggle(valThis.length === 0)
        .mark(valThis, options);
    }
  })
});
input[type="text"] {
  width: 50%;
  margin: 10px;
  padding: 5px;
  float: left;
  clear: left;
}

div {
  float: left;
  clear: left;
  margin: 10px 10px;
}

.bold {
  font-weight: 700;
}

table td {
  border: solid 1px #ccc;
  padding: 3px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mark.js/8.11.1/jquery.mark.min.js" integrity="sha256-4HLtjeVgH0eIB3aZ9mLYF6E8oU5chNdjU6p6rrXpl9U=" crossorigin="anonymous"></script>

<input placeholder="Filter results" id="box" type="text" />

<div class="objType" id="item1">
  <span class="bold">Accepted</span> Event Relation
  <table>
    <tr>
      <td>Lorem</td>
      <td>ipsum</td>
    </tr>
  </table>
</div>
<div class="objType" id="item2">
  Case <span class="bold">Status</span> Value
  <table>
    <tr>
      <td>Lorem</td>
      <td>ipsum</td>
    </tr>
  </table>
</div>
<div class="objType" id="item3">
  External <span class="bold">Data Source</span>
  <table>
    <tr>
      <td>Lorem</td>
      <td>ipsum</td>
    </tr>
  </table>
</div>
<div class="objType" id="item4">
  Navigation <span class="bold">Link</span> Set
  <table>
    <tr>
      <td>Lorem</td>
      <td>ipsum</td>
    </tr>
  </table>
</div>
like image 3
User863 Avatar answered Oct 21 '22 03:10

User863