0

HTML

<input id="myInput" type="text" onkeyup="ContactsearchFX()" 
       placeholder="Search Titles">
    *</p>
<table id="myTable" style="width: 100%" class="style1">

JAVASCRIPT

window.onload = function() {
   var rows = document.querySelectorAll('tr');

   for (var i = 0; i < rows.length; i++) {
    rows[i].style.display = 'none';
   }
 }

function ContactsearchFX() {
  var input, filter, table, tr, td, i;

   input = document.getElementById("myInput");

  filter = input.value.toUpperCase();
  table = document.getElementById("myTable");
  tr = table.getElementsByTagName("tr");
  for (i = 0; i < tr.length; i++) {
    td = tr[i].getElementsByTagName("td")[0];
    if (td) {
     if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
        tr[i].style.display = "";
     } else {
       tr[i].style.display = "none";

      }
    }
  }

   var rows = document.querySelectorAll('tr');

   if (input.value.length == 0) {
    for (var i = 0; i < rows.length; i++) {
      rows[i].style.display = 'none';
    }
  }
}

Have been trying to implement https://markjs.io/ among other various highlight solutions with no fix or solution. Hope there is enough info to go on. Please do ask if you need more details.

Orbit
  • 97
  • 1
  • 8
  • Possible duplicate of [What does 'synchronized' mean?](https://stackoverflow.com/questions/1085709/what-does-synchronized-mean) – krakig Jul 05 '19 at 19:12
  • So currently you have a table that based on the input displays some of it's rows. And you want to extend this so that the displayed rows have the matching text highlighted right? Also you would like to use a 3rd party library like the one you shared? – kidroca Jul 05 '19 at 23:44
  • Exactly kidroca, only if I could avoid using 3rd party would be even better. – Orbit Jul 06 '19 at 07:54

1 Answers1

0

Setup

Judging by the code you've shared, you're probably not using es6 or a js bundler to setup your project. This means no imports and the library <scrpit>s go inside your index.html

Steps

  1. Verify you are loading the script correctly
  2. Clean up the code
    • separate it to chunks to better understand what's failing
  3. Update the code with the highlight functionality described by the "getting started" of the package

Notes

With the mark.js library it would be best to clean up the mark (.unmark()) before applying it again. because it will add more elements on each change. That's why we keep a single instance of mark per context (context is the table element) instead of creating a new instance inside the highlightChanges function

The snippet below is not the optimal implementation of this functionality but it can serve for a starting point. It was based on the original code

Snippet with added highlight

var input, table, rows, markInstance;

window.onload = function init() {
  input = document.getElementById("myInput");
  table = document.getElementById('myTable');
  rows = table.querySelectorAll('tr');
  markInstance = new Mark(table);

  clear();
}

function ContactsearchFX() {

  clear();

  if (input.value.length == 0) return;

  filterRows(input.value);
  highlightMatches(input.value);
}

function clear() {
  markInstance.unmark();
  
  for (var i = 0; i < rows.length; i++) {
    rows[i].style.display = 'none';
  }
}

function filterRows(text) {
  var part = text.toUpperCase();

  for (i = 0; i < rows.length; i++) {
    var row = rows[i];
    var td = row.getElementsByTagName("td")[0];

    if (td) {
      // part = GI
      // innerHtml = <MARK DATA-MARKJS="TRUE">G</MARK>ITHUB (wont match)
      // innerText = GITHUB (will match)
      var content = td.innerText.toUpperCase();

      if (content.includes(part)) {
        row.style.display = "";
      }
    }
  }
}

function highlightMatches(text) {
   markInstance.mark(text);
}
.input-wrap {
  margin-bottom: 12px;
}

.hints {
  display: none;
  margin-top: 12px;
}

#myInput:invalid~.hints {
  display: block;
}

mark {
    background: orange;
    font-weight: bold;
    color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/mark.js/8.11.1/mark.js"></script>

<div class="input-wrap">
  <label>
    Search Titles: 
    <input id="myInput" type="text" required 
           onkeyup="ContactsearchFX()" 
           placeholder="Search Titles" />

    <span class="hints">
      Hints: type "git", "bit", "forge" ...
    </span>
  </label>
</div>

<table id="myTable" style="width: 100%" class="style1">
  <tr>
    <th>Title</th>
    <th>Description</th>
  </tr>
  <tr>
    <td>Github</td>
    <td>Is the HUB</td>
  </tr>
  <tr>
    <td>Gitlab</td>
    <td>Have nice CI</td>
  </tr>
  <tr>
    <td>Bitbucket</td>
    <td>Has Jira integration (Duh)</td>
  </tr>
  <tr>
    <td>SourceForge</td>
    <td>Open source projects live here. It is said</td>
  </tr>
</table>

And a more appropriate version for production

Quick look through the examples and the API for the options parameter of the mark() function review that we can substitute most of the logic with the hooks from the options

The input event handler is debounceed (function from from lodash _.debounce) this way the filtering will start when the user stops typing (for more than 250ms)

Content is again .unmark()ed at the start - the different part is that we use the options parameter with a done callback to continue with highlightMatches when unmark finishes

The options parameter have an each prop which is a callback for each element that matches. Using this callback we can search for it's parent that we know must be a row, and we add a class show so the row can become visible.

There's also a noMatch prop which will be called (back) if the texts matches nothing so we can show some hint to maybe try a different text

The options parameter hold other useful props that can configure the matching like, wildcards, case sensitive matching and so on...

var input, table, rows, noMatches, markInstance;

window.onload = function init() {
  input = document.getElementById('myInput');
  noMatches = document.getElementById('noMatches');
  table = document.getElementById('myTable');
  rows = table.querySelectorAll('tr');
  markInstance = new Mark(table);

  input.addEventListener('keyup', _.debounce(ContactsearchFX, 250));
}

function ContactsearchFX() {

  resetContent();

  markInstance.unmark({
    done: highlightMatches
  });

}

function resetContent() {
 noMatches.textContent = '';

  rows.forEach(function(row) {
    row.classList.remove('show');
  });
}

function highlightMatches() {
  markInstance.mark(input.value, {
    each: showParantRow,
    noMatch: onNoMatches,
  })
}

function showParantRow(element) {
  var row = element.closest('tr');
  row.classList.add('show');
}

function onNoMatches(text) {
  noMatches.textContent = 'No records match: "' + text + '"';
};
.input-wrap {
  margin-bottom: 12px;
}


#myInput:invalid~.hints {
  display: block;
}

#noMatches:empty, #noMatches:empty + .hints {
  display: none;
}

.filterTable tr {
  display: none;
}

.filterTable .show {
  display: table-row;
}

mark {
  background: orange;
  font-weight: bold;
  color: black;
}
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.11/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mark.js/8.11.1/mark.min.js"></script>

<div class="input-wrap">
  <label>
    Search Titles: 
    <input id="myInput" type="text" required
           placeholder="Search Titles" />
  </label>
</div>

<div class="hintsWrap">
  <p id="noMatches"></p>
  <p class="hints">
    Hints: type "git", "bit", "forge" ...
  </p>
</div>


<table id="myTable" style="width: 100%" class="filterTable">
  <tr>
    <td>Github</td>
    <td>Is the HUB</td>
  </tr>
  <tr>
    <td>Gitlab</td>
    <td>Have nice CI</td>
  </tr>
  <tr>
    <td>Bitbucket</td>
    <td>Has Jira integration (Duh)</td>
  </tr>
  <tr>
    <td>SourceForge</td>
    <td>Open source projects live here. It is said</td>
  </tr>
</table>
kidroca
  • 3,480
  • 2
  • 27
  • 44
  • Thanks Kidroca, well explained – Orbit Jul 08 '19 at 13:23
  • Thanks again Kidroca. My data tables are tables are nested in *TABLES* table data tags. So your code snippet fits, only mark.js is working though no results are displayed. Not sure why this is. Is there a simple solution? – Orbit Jul 17 '19 at 21:53