Home > Net >  How to properly filter results from a table?
How to properly filter results from a table?

Time:10-21

const myFunction = () => {
  const trs = document.querySelectorAll('#myTable tr:not(.header)')
  const filter = document.querySelector('#myInput').value
  const regex = new RegExp('^'   filter   '$', 'i')
  const isFoundInTds = td => regex.test(td.innerHTML)
  const isFound = childrenArr => childrenArr.some(isFoundInTds)
  const setTrStyleDisplay = ({ style, children }) => {
    style.display = isFound([
      ...children // <-- All columns
    ]) ? '' : 'none' 
  }
  
  trs.forEach(setTrStyleDisplay)
}
<style>
  #myInput {
  background-image: url('https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8iOHV-jsRl0FQ2hVomg1GUjdg4W63HoqXrREEp4m5KNpOVWRAJRxJD_SBXN-l2hlAc7rbL_LNpl145QhEjTUC54EHfJImTH-gKe-a2CtD8XFq9ZBUG4xJekQwHfIvIP4yaU_Zm-QX3HnvawVcXY82APg5QNY6rlcKX2Bx9b3wQ6v_f7zVuOF19Mn4/s1600/149852.png'); /* Add a search icon to input */
  background-position: 10px 12px; /* Position the search icon */
  background-repeat: no-repeat; /* Do not repeat the icon image */
  width: 60%; /* Full-width */
  font-size: 16px; /* Increase font-size */
  padding: 12px 20px 12px 40px; /* Add some padding */
  border: 1px solid #ddd; /* Add a grey border */
  margin-bottom: 12px; /* Add some space below the input */
}

#myTable {
  border-collapse: collapse; /* Collapse borders */
  width: 100%; /* Full-width */
  border: 1px solid #ddd; /* Add a grey border */
  font-size: 18px; /* Increase font-size */
}

#myTable th, #myTable td {
  text-align: left; /* Left-align text */
  padding: 12px; /* Add padding */
}
</style>
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Filter players by name, position, nationality or club...">

<table id="myTable">
<tbody>
  <tr >
<th>Rec</th>
<th>Name</th>
<th>Position</th>
<th>Nat</th>
<th>Club</th>
</tr>
<tr>
<td>- - -</td>
<td>Eduardo Camavinga</td>
<td>DM / MC</td>
<td>France</td>
<td>R. Madrid</td>
</tr>
<tr>
<td>- - -</td>
<td>Ansu Fati</td>
<td>AMR / AML / ST</td>
<td>Spain</td>
<td>Barcelona</td>
</tr>
<tr>
<td>- - -</td>
<td>Jude Bellingham</td>
<td>MC</td>
<td>England</td>
<td>Borussia Dortmund</td>
</tr>
<tr>
<td>- - B -</td>
<td>Ernest Poku</td>
<td>AMR / AML / ST</td>
<td>Netherland</td>
<td>AZ</td>
</tr>
<tr>
<td>- - -</td>
<td>Giovanni Reyna</td>
<td>MC / AMC</td>
<td>USA</td>
<td>Borussia Dortmund</td>
</tr>
<tr>
<td>- - -</td>
<td>Enes Sali</td>
<td>AML / AMC</td>
<td>Romania</td>
<td>Farul Constanţa</td>
</tr>
<tr>
<td>- - -</td>
<td>Nico Williams</td>
<td>MC / AMR</td>
<td>Spain</td>
<td>A. Bilbao</td>
</tr>
<tr>
<td>- - -</td>
<td>Takuhiro Nakai</td>
<td>MC</td>
<td>Japan</td>
<td>R. Madrid</td>
</tr>
<tr>
<td>- - -</td>
<td>Julen Jon Guerrero</td>
<td>AMC</td>
<td>Spain</td>
<td>R. Madrid</td>
</tr>
<tr>
<td>- - -</td>
<td>Bruno Iglesias</td>
<td>AMC</td>
<td>Spain</td>
<td>R. Madrid B</td>
</tr>
<tr>
<td>- - -</td>
<td>Yeremy Pino</td>
<td>AMR / AML</td>
<td>Spain</td>
<td>Villarreal</td>
</tr>
<tr>
<td>- - -</td>
<td>Pedri</td>
<td>MC / AMC</td>
<td>Spain</td>
<td>Barcelona</td>
</tr>
<tr>
<td>- - -</td>
<td>Jamal Musiala</td>
<td>AML / AMC</td>
<td>Germany</td>
<td>FC Bayern</td>
</tr>
<tr>
<td>- - -</td>
<td>Dane Scarlett</td>
<td>ST</td>
<td>England</td>
<td>Portsmouth</td>
</tr>
<tr>
<td>- - -</td>
<td>Ilaix Moriba</td>
<td>MC</td>
<td>GUI</td>
<td>Valencia</td>
</tr>
<tr>
<td>- - -</td>
<td>Kaio Jorge</td>
<td>ST</td>
<td>Brasil</td>
<td>Zebre</td>
</tr>
<tr>
<td>- - B- -</td>
<td>Jérémy Doku</td>
<td>AML / ST</td>
<td>Belgium</td>
<td>Rennes</td>
</tr>
<tr>
<td>- - -</td>
<td>Konrad De la Fuente</td>
<td>AMR / AML</td>
<td>USA</td>
<td>Olympiacos</td>
</tr>
<tr>
<td>- - C  -</td>
<td>Tino Livramento</td>
<td>DR</td>
<td>England</td>
<td>Southampton</td>
</tr>
<tr>
<td>- - -</td>
<td>Arthur</td>
<td>AMC</td>
<td>Brasil</td>
<td>FLU</td>
</tr>
<tr>
<td>- - -</td>
<td>Charlie Patino</td>
<td>MC</td>
<td>England</td>
<td>Blackpool</td>
</tr>
<tr>
<td>- - B- -</td>
<td>Gabriel Martinelli</td>
<td>AML / ST</td>
<td>Brasil</td>
<td>Arsenal</td>
</tr>
<tr>
<td>- - -</td>
<td>João Pedro</td>
<td>ST</td>
<td>Brasil</td>
<td>Watford</td>
</tr>
<tr>
<td>- - -</td>
<td>Jevon Simons</td>
<td>AMR / AMC</td>
<td>Netherland</td>
<td>PSV</td>
</tr>
<tr>
<td>- - A -</td>
<td>Bukayo Saka</td>
<td>AMR / AML</td>
<td>England</td>
<td>Arsenal</td>
</tr>
<tr>
<td>- - -</td>
<td>Álex Baena</td>
<td>AML / AMC</td>
<td>Spain</td>
<td>Villarreal</td>
</tr>
<tr>
<td>- - C -</td>
<td>David Kalokoh</td>
<td>AML</td>
<td>Netherland</td>
<td>Ajax</td>
</tr>
<tr>
<td>- - -</td>
<td>Adrián Corral</td>
<td>DC</td>
<td>Spain</td>
<td>A. Madrid B</td>
</tr>
<tr>
<td>- - -</td>
<td>Chaka Traoré</td>
<td>AMR / AML</td>
<td>CIV</td>
<td>Milan</td>
</tr>
<tr>
<td>- - C -</td>
<td>Yunus Musah</td>
<td>M (RC)</td>
<td>USA</td>
<td>Valencia</td>
</tr>
<tr>
<td>- - -</td>
<td>Bryan Okoh</td>
<td>DC</td>
<td>SUI</td>
<td>FC RB Salzburg</td>
</tr>
<tr>
<td>- - -</td>
<td>Ilias Akhomach</td>
<td>AMR / AMC</td>
<td>Spain</td>
<td>Barcelona B</td>
</tr>
<tr>
<td>- - -</td>
<td>Nicolò Rovella</td>
<td>DM / MC</td>
<td>Italy</td>
<td>Monza</td>
</tr>
<tr>
<td>- - -</td>
<td>Florian Wirtz</td>
<td>AMC</td>
<td>Germany</td>
<td>Bayer 04</td>
</tr>
<tr>
<td>- - -</td>
<td>Hugo Félix</td>
<td>MC / AMC</td>
<td>Portugal</td>
<td>Benfica</td>
</tr>
<tr>
<td>- - -</td>
<td>Julian Rijkhoff</td>
<td>ST</td>
<td>Netherland</td>
<td>Borussia Dortmund</td>
</tr>
<tr>
<td>- - -</td>
<td>Tobias Gulliksen</td>
<td>MC, AML</td>
<td>NOR</td>
<td>Strømsgodset</td>
</tr>
<tr>
<td>- - C  -</td>
<td>Michael Olise</td>
<td>AMR</td>
<td>France</td>
<td>Crystal Palace</td>
</tr>
<tr>
<td>- - C- -</td>
<td>Lucien Agoume</td>
<td>DM / MC</td>
<td>France</td>
<td>Troyes</td>
</tr>
<tr>
<td>- - -</td>
<td>Samuele Ricci</td>
<td>DM / MC</td>
<td>Italy</td>
<td>Torino</td>
</tr>
<tr>
<td>- - -</td>
<td>Fábio Silva</td>
<td>ST</td>
<td>Portugal</td>
<td>Anderlecht</td>
</tr>
<tr>
<td>- - -</td>
<td>Endrick</td>
<td>ST</td>
<td>Brasil</td>
<td>SEP</td>
</tr>
<tr>
<td>- - -</td>
<td>Giovani</td>
<td>AMR</td>
<td>Brasil</td>
<td>SEP</td>
</tr>
<tr>
<td>- - C -</td>
<td>Noni Madueke</td>
<td>MC / AMR</td>
<td>England</td>
<td>PSV</td>
</tr>
<tr>
<td>- - -</td>
<td>Gonçalo Esteves</td>
<td>DR</td>
<td>Portugal</td>
<td>Estoril</td>
</tr>
<tr>
<td>- - -</td>
<td>Nicola Zalewski</td>
<td>AML / AMC</td>
<td>POL</td>
<td>Roma</td>
</tr>
<tr>
<td>- - -</td>
<td>Folarin Balogun</td>
<td>ST</td>
<td>England</td>
<td>Reims</td>
</tr>
<tr>
<td>- - -</td>
<td>Reinier</td>
<td>AMC</td>
<td>Brasil</td>
<td>Girona</td>
</tr>
<tr>
<td>- - A- -</td>
<td>Fábio Carvalho</td>
<td>AMC</td>
<td>England</td>
<td>Liverpool</td>
</tr>
<tr>
<td>- - -</td>
<td>Pierre Dwomoh</td>
<td>MC / AMC</td>
<td>Belgium</td>
<td>BRG</td>
</tr>
<tr>
<td>- - -</td>
<td>Joe Gelhardt</td>
<td>ST</td>
<td>England</td>
<td>Leeds</td>
</tr>
<tr>
<td>- - -</td>
<td>Matteo Ruggeri</td>
<td>DL</td>
<td>Italy</td>
<td>Atalanta</td>
</tr>
<tr>
<td>- - -</td>
<td>Ali Akman</td>
<td>ST</td>
<td>TUR</td>
<td>Göztepe</td>
</tr>
<tr>
<td>- - -</td>
<td>Anatolii Trubin</td>
<td>GK</td>
<td>UKR</td>
<td>Shakhtar</td>
</tr>
<tr>
<td>- - -</td>
<td>Devyne Rensch</td>
<td>DC / DR / DM</td>
<td>Netherland</td>
<td>Ajax</td>
</tr>
<tr>
<td>- - -</td>
<td>Ro-Zangelo Daal</td>
<td>AMR / AML</td>
<td>Netherland</td>
<td>AZ</td>
</tr>
<tr>
<td>- - C  -</td>
<td>Luke Thomas</td>
<td>DL</td>
<td>England</td>
<td>Leicester</td>
</tr>
<tr>
<td>- - -</td>
<td>Arsen Zakharyan</td>
<td>AMC</td>
<td>RUS</td>
<td>Dinamo Moscow</td>
</tr>
<tr>
<td>- - -</td>
<td>Alejandro Balde</td>
<td>DL</td>
<td>Spain</td>
<td>Barcelona</td>
</tr>
<tr>
<td>- - C -</td>
<td>Han-Noah Massengo</td>
<td>DM / MC</td>
<td>France</td>
<td>Bristol City</td>
</tr>
<tr>
<td>- - -</td>
<td>Robert Wagner</td>
<td>MC / AMC</td>
<td>Germany</td>
<td>SC Freiburg II</td>
</tr>
<tr>
<td>- - -</td>
<td>Guilherme Santos</td>
<td>MC</td>
<td>Portugal</td>
<td>Sporting CP</td>
</tr>
<tr>
<td>- - -</td>
<td>Rav van den Berg</td>
<td>DC</td>
<td>Netherland</td>
<td>PEC Zwolle</td>
</tr>
<tr>
<td>- - -</td>
<td>Santiago Simón</td>
<td>M (RC)</td>
<td>ARG</td>
<td>River</td>
</tr>
<tr>
<td>- - -</td>
<td>Jahkeele Marshall-Rutty</td>
<td>AMR</td>
<td>CAN</td>
<td>Toronto FC II</td>
</tr>
<tr>
<td>- - -</td>
<td>Cristian Canales</td>
<td>AMR</td>
<td>Spain</td>
<td>Real San Sebastián C</td>
</tr>
<tr>
<td>- - -</td>
<td>Lovro Zvonarek</td>
<td>AMC</td>
<td>Croatia</td>
<td>FC Bayern</td>
</tr>
<tr>
<td>- - C -</td>
<td>Pedro Brazão</td>
<td>AM (RLC)</td>
<td>Portugal</td>
<td>Famalicão</td>
</tr>
<tr>
<td>- - -</td>
<td>Ethan Laidlaw</td>
<td>ST</td>
<td>Scotland</td>
<td>Hibernian</td>
</tr>
<tr>
<td>- - -</td>
<td>Álvaro Carrillo</td>
<td>DC</td>
<td>Spain</td>
<td>R. Madrid B</td>
</tr>
<tr>
<td>- - -</td>
<td>Sergio Dacal</td>
<td>MC / AMR</td>
<td>Spain</td>
<td>S. Gijón B</td>
</tr>
<tr>
<td>- - -</td>
<td>Hugo Siquet</td>
<td>DR</td>
<td>Belgium</td>
<td>SC Freiburg</td>
</tr>
<tr>
<td>- - -</td>
<td>Mateusz Musiałowski</td>
<td>AMR / AML / AMC / ST</td>
<td>POL</td>
<td>Liverpool</td>
</tr>
<tr>
<td>- - -</td>
<td>Piero Hincapié</td>
<td>DC</td>
<td>ECU</td>
<td>Bayer 04</td>
</tr>
<tr>
<td>- - -</td>
<td>Hugo Álvarez</td>
<td>MC</td>
<td>Spain</td>
<td>Vigo B</td>
</tr>
<tr>
<td>- - -</td>
<td>Dário Essugo</td>
<td>DM / MC</td>
<td>Portugal</td>
<td>Sporting CP B</td>
</tr>
<tr>
<td>- - -</td>
<td>Ömer Beyaz</td>
<td>MC / AMC</td>
<td>TUR</td>
<td>Magdeburg</td>
</tr>
<tr>
<td>- - -</td>
<td>Ruslan Neshcheret</td>
<td>GK</td>
<td>UKR</td>
<td>Dynamo Kyiv</td>
</tr>
<tr>
<td>- - -</td>
<td>Sebastiano Esposito</td>
<td>AMC / ST</td>
<td>Italy</td>
<td>Anderlecht</td>
</tr>
<tr>
<td>- - -</td>
<td>Tomás Araújo</td>
<td>DC</td>
<td>Portugal</td>
<td>Gil Vicente</td>
</tr>
<tr>
<td>- - -</td>
<td>Rodrigo Pinheiro</td>
<td>DR</td>
<td>Portugal</td>
<td>FC Porto B</td>
</tr>
<tr>
<td>- - -</td>
<td>Jayden Candelaria</td>
<td>DL</td>
<td>Netherland</td>
<td>Feyenoord</td>
</tr>
<tr>
<td>- - -</td>
<td>José Riasco</td>
<td>ST</td>
<td>VEN</td>
<td>Philadelphia II</td>
</tr>
<tr>
<td>- - -</td>
<td>Mario Vušković</td>
<td>DC</td>
<td>Croatia</td>
<td>Hamburger SV</td>
</tr>
<tr>
<td>- - -</td>
<td>Aster Vranckx</td>
<td>MC</td>
<td>Belgium</td>
<td>Milan</td>
</tr>
<tr>
<td>- - -</td>
<td>Gonçalo Inácio</td>
<td>DC</td>
<td>Portugal</td>
<td>Sporting CP</td>
</tr>
<tr>
<td>- - -</td>
<td>Filip Rønningen Jørgensen</td>
<td>MC</td>
<td>NOR</td>
<td>Odd</td>
</tr>
<tr>
<td>- - -</td>
<td>Nnamdi Collins</td>
<td>DC</td>
<td>Germany</td>
<td>Borussia Dortmund</td>
</tr>
<tr>
<td>- - -</td>
<td>Charlie Setford</td>
<td>GK</td>
<td>England</td>
<td>Ajax</td>
</tr>
<tr>
<td>- - -</td>
<td>Matheus Donelli</td>
<td>GK</td>
<td>Brasil</td>
<td>COR</td>
</tr>
<tr>
<td>- - -</td>
<td>Pablo Ramón</td>
<td>DC</td>
<td>Spain</td>
<td>R. Madrid B</td>
</tr>
<tr>
<td>- - -</td>
<td>Marcos Leonardo</td>
<td>ST</td>
<td>Brasil</td>
<td>SAN</td>
</tr>
<tr>
<td>- - -</td>
<td>Sivert Mannsverk</td>
<td>MC</td>
<td>NOR</td>
<td>Molde</td>
</tr>
<tr>
<td>- - -</td>
<td>Koba Lein</td>
<td>MC</td>
<td>France</td>
<td>Oviedo</td>
</tr>
<tr>
<td>- - -</td>
<td>Nico Serrano</td>
<td>MC / AML</td>
<td>Spain</td>
<td>Mirandés</td>
</tr>
<tr>
<td>- - -</td>
<td>Rayan Aït-Nouri</td>
<td>DL</td>
<td>France</td>
<td>Wolves</td>
</tr>
<tr>
<td>- - -</td>
<td>Daniel Jebbison</td>
<td>ST</td>
<td>England</td>
<td>Sheff Utd</td>
</tr>
<tr>
<td>- - -</td>
<td>Layton Stewart</td>
<td>ST</td>
<td>England</td>
<td>Liverpool</td>
</tr>
<tr>
<td>- - -</td>
<td>Silvano Vos</td>
<td>DM / MC</td>
<td>Netherland</td>
<td>Ajax</td>
</tr>
<tr>
<td>- - -</td>
<td>Lukas Wallner</td>
<td>DC</td>
<td>AUT</td>
<td>FC RB Salzburg</td>
</tr>
<tr>
<td>- - -</td>
<td>Ziad El Sheiwi</td>
<td>DL</td>
<td>AUT</td>
<td>FK Austria Vienna</td>
</tr>
<tr>
<td>- - -</td>
<td>Exequiel Zeballos</td>
<td>AMR / AML</td>
<td>ARG</td>
<td>Boca</td>
</tr>
<tr>
<td>- - -</td>
<td>Luca Podlech</td>
<td>GK</td>
<td>Germany</td>
<td>Schalke 04</td>
</tr>
<tr>
<td>- - -</td>
<td>Gonçalo Ramos</td>
<td>ST</td>
<td>Portugal</td>
<td>Benfica</td>
</tr>
<tr>
<td>- - -</td>
<td>Deivi Barrios</td>
<td>DC</td>
<td>COL</td>
<td>Real Cartagena</td>
</tr>
<tr>
<td>- - -</td>
<td>Jon Karrikaburu</td>
<td>ST</td>
<td>Spain</td>
<td>Real San Sebastián B</td>
</tr>
<tr>
<td>- - -</td>
<td>Rafael Brito</td>
<td>DM</td>
<td>Portugal</td>
<td>MRT</td>
</tr>
<tr>
<td>- - -</td>
<td>Martín Tejón</td>
<td>MC / AMC</td>
<td>Spain</td>
<td>Valencia B</td>
</tr>
<tr>
<td>- - -</td>
<td>Jesús Vázquez</td>
<td>DL</td>
<td>Spain</td>
<td>Valencia B</td>
</tr>
<tr>
<td>- - -</td>
<td>Levi Colwill</td>
<td>DC</td>
<td>England</td>
<td>Brighton</td>
</tr>
<tr>
<td>- - -</td>
<td>Mahmoud Al-Aswad</td>
<td>AMR / AMC</td>
<td>SYR</td>
<td>Al-Karamah</td>
</tr>
<tr>
<td>- - -</td>
<td>Ismaël Gharbi</td>
<td>AMC</td>
<td>France</td>
<td>Paris SG</td>
</tr>
<tr>
<td>- - -</td>
<td>Amadou Diallo</td>
<td>AMR / AML</td>
<td>England</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>- - -</td>
<td>Thierry Small</td>
<td>DL</td>
<td>England</td>
<td>Port Vale</td>
</tr>
<tr>
<td>- - -</td>
<td>Chris Popov</td>
<td>AMR / AML</td>
<td>WAL</td>
<td>Leicester</td>
</tr>
<tr>
<td>- - -</td>
<td>Heorhii Sudakov</td>
<td>AMC</td>
<td>UKR</td>
<td>Shakhtar</td>
</tr>
<tr>
<td>- - -</td>
<td>Luka Sucic</td>
<td>MC</td>
<td>Croatia</td>
<td>FC RB Salzburg</td>
</tr>
<tr>
<td>- - -</td>
<td>Faustino Anjorin</td>
<td>AMC</td>
<td>England</td>
<td>Huddersfield</td>
</tr>
<tr>
<td>- - -</td>
<td>Sandry</td>
<td>MC</td>
<td>Brasil</td>
<td>SAN</td>
</tr>
<tr>
<td>- - -</td>
<td>Matheus Nascimento</td>
<td>ST</td>
<td>Brasil</td>
<td>BOT</td>
</tr>
<tr>
<td>- - -</td>
<td>Álvaro Bastida</td>
<td>MC</td>
<td>Spain</td>
<td>Cádiz B</td>
</tr>
<tr>
<td>- - -</td>
<td>Mateja Milovanović</td>
<td>DC</td>
<td>SRB</td>
<td>Ajax</td>
</tr>
<tr>
<td>- - -</td>
<td>Dimo Krastev</td>
<td>DM / MC</td>
<td>BUL</td>
<td>Fiorentina</td>
</tr>
<tr>
<td>- - -</td>
<td>Sávio</td>
<td>AMR</td>
<td>Brasil</td>
<td>PSV</td>
</tr>
<tr>
<td>- - -</td>
<td>Lucas Cañizares</td>
<td>GK</td>
<td>Spain</td>
<td>R. Madrid B</td>
</tr>
<tr>
<td>- - -</td>
<td>Caleb Okoli</td>
<td>DC</td>
<td>Italy</td>
<td>Atalanta</td>
</tr>
<tr>
<td>- - -</td>
<td>Roko Šimić</td>
<td>ST</td>
<td>Croatia</td>
<td>FC RB Salzburg</td>
</tr>
<tr>
<td>- - -</td>
<td>Facundo González</td>
<td>DC</td>
<td>URU</td>
<td>Valencia B</td>
</tr>
<tr>
<td>- - -</td>
<td>Chem Campbell</td>
<td>AMR / AML</td>
<td>WAL</td>
<td>Wolves</td>
</tr>
<tr>
<td>- - -</td>
<td>Ander Barrenetxea</td>
<td>AMR / AML</td>
<td>Spain</td>
<td>Real San Sebastián</td>
</tr>
<tr>
<td>- - -</td>
<td>Amar Dedic</td>
<td>DL</td>
<td>BIH</td>
<td>FC RB Salzburg</td>
</tr>
<tr>
<td>- - -</td>
<td>Eddie Salcedo</td>
<td>AMC / ST</td>
<td>Italy</td>
<td>Bari</td>
</tr>
<tr>
<td>- - -</td>
<td>Ruslan Litvinov</td>
<td>DM</td>
<td>RUS</td>
<td>Spartak Moscow</td>
</tr>
<tr>
<td>- - -</td>
<td>Luca Netz</td>
<td>DL</td>
<td>Germany</td>
<td>Borussia M'gladbach</td>
</tr>
<tr>
<td>- - -</td>
<td>Rafael Luís</td>
<td>DM / MC</td>
<td>Portugal</td>
<td>Benfica</td>
</tr>
<tr>
<td>- - -</td>
<td>Zito</td>
<td>AMR</td>
<td>ANG</td>
<td>Cagliari</td>
</tr>
<tr>
<td>- - -</td>
<td>Luka Reischl</td>
<td>ST</td>
<td>AUT</td>
<td>FC RB Salzburg</td>
</tr>
<tr>
<td>- - -</td>
<td>André Gomes</td>
<td>GK</td>
<td>Portugal</td>
<td>Benfica</td>
</tr>
<tr>
<td>- - -</td>
<td>Martin Baturina</td>
<td>MC / AMC</td>
<td>Croatia</td>
<td>Dinamo</td>
</tr>
<tr>
<td>- - -</td>
<td>Raúl Moro</td>
<td>AMR / AML</td>
<td>Spain</td>
<td>Ternana</td>
</tr>
</tbody>
</table>

I'm trying to make a table filter which would return specific results. For example, in my table, I have a column 'Position'which has results like DC / DR, or AMR / AML / AMC etc. And with my current code, the filer excludes these results and only shows DC, or AMR players in this position.

<script>
const myFunction = () => {
  const trs = document.querySelectorAll('#myTable tr:not(.header)')
  const filter = document.querySelector('#myInput').value
  const regex = new RegExp('^'   filter   '$', 'i')
  const isFoundInTds = td => regex.test(td.innerHTML)
  const isFound = childrenArr => childrenArr.some(isFoundInTds)
  const setTrStyleDisplay = ({ style, children }) => {
    style.display = isFound([
      ...children // <-- All columns
    ]) ? '' : 'none' 
  }
  
  trs.forEach(setTrStyleDisplay)
}
</script>

Is it possible to include results that have DC / DR as a position when I write DR in the search filter?

I've tried removing '^' and/or '$' from new RegExp, but it's not giving the results I want.

Also, I want to make the filter so that it doesn't show results if the letters are inside of a sentence.

CodePudding user response:

The first thing you'll need to do is escape whatever the user types, since certain characters are special to regular expressions, as discussed here. I'll use the function from bobince's answer.

You'll also want to show all rows when there's no filter, to handle the case where the user clears the filter. You can either special case that up-front and just set all rows to display = "none", or use a regex like /.*/ that matches anything.

Is it possible to include results that have DC / DR as a position when I write DR in the search filter?

Yes, but that's at odds with your comment that you're looking for an exact match, since those fields have other text in them.

You could use a "whole word" match instead of an exact match by using a "word boundary" assertion (\b) on either side of what the user types:

// Since we're using a string literal, we have to escape the backslash so it's
// actually a backslash in the string `RegExp` sees
const regex = !filter ? /.*/ : new RegExp("\\b"   escapeRegex(filter)   "\\b", "i");

Here's that plus a couple of other tweaks:

const myFunction = () => {
    const trs = document.querySelectorAll("#myTable tr:not(.header)");
    const filter = document.querySelector("#myInput").value.trim(); // *** Added `.trim()`
    // Don't filter if the filter is blank (`/.*/` matches anything)
    const regex = !filter
        ? /.*/
        : new RegExp("\\b"   escapeRegex(filter)   "\\b", "i");
    // Made this singular since it only checks a single td
    // and make it look in just the text, not the HTML markup
    const isFoundInTd = (td) => regex.test(td.textContent);
    const isFound = (childrenArr) => childrenArr.some(isFoundInTd);
    const setTrStyleDisplay = ({ style, children }) => {
        style.display = isFound([
            ...children, // <-- All columns
        ])
            ? ""
            : "none";
    };

    trs.forEach(setTrStyleDisplay);
};

const myFunction = () => {
    const trs = document.querySelectorAll("#myTable tr:not(.header)");
    const filter = document.querySelector("#myInput").value.trim(); // *** Added `.trim()`
    // Don't filter if the filter is blank (`/.*/` matches anything)
    const regex = !filter
        ? /.*/
        : new RegExp("\\b"   escapeRegex(filter)   "\\b", "i");
    // Made this singular since it only checks a single td
    // and make it look in just the text, not the HTML markup
    const isFoundInTd = (td) => regex.test(td.textContent);
    const isFound = (childrenArr) => childrenArr.some(isFoundInTd);
    const setTrStyleDisplay = ({ style, children }) => {
        style.display = isFound([
            ...children, // <-- All columns
        ])
            ? ""
            : "none";
    };

    trs.forEach(setTrStyleDisplay);
};

function escapeRegex(string) {
    return string.replace(/[-\/\\^$* ?.()|[\]{}]/g, "\\$&");
}
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Filter players by name, position, nationality or club...">

<table id="myTable">
<tbody>
<tr >
<th>Rec</th>
<th>Name</th>
<th>Position</th>
<th>Nat</th>
<th>Club</th>
</tr>
<tr>
<td>- - -</td>
<td>Eduardo Camavinga</td>
<td>DM / MC</td>
<td>France</td>
<td>R. Madrid</td>
</tr>
<tr>
<td>- - -</td>
<td>Ansu Fati</td>
<td>AMR / AML / ST</td>
<td>Spain</td>
<td>Barcelona</td>
</tr>
<tr>
<td>- - -</td>
<td>Jude Bellingham</td>
<td>MC</td>
<td>England</td>
<td>Borussia Dortmund</td>
</tr>
</tbody>
</table>

It does mean that typing "ansu" will show the row for "Ansu Fati" (your original code would have required the entire name). If you don't want to do that, you could have two regular expressions: One for all the other fields and one for the position field.

An alternative approach keeps using the anchors, but splits the position field on those / characters (after stripping whitespace) and tests each position separately. To do that, I've added to the position cells so we know which ones to treat specially:

const myFunction = () => {
    const trs = document.querySelectorAll("#myTable tr:not(.header)");
    const filter = document.querySelector("#myInput").value.trim(); // Added `.trim()`
    // Don't filter if the filter is blank (`/.*/` matches anything)
    const regex = !filter
        ? /.*/
        : new RegExp("^"   escapeRegex(filter)   "$", "i");
    // Made this singular since it only checks a single td
    // and make it look in just the text, not the HTML markup
    const isFoundInTd = (td) => {
        const text = td.textContent;
        if (td.classList.contains("position")) {
            return text
                .replace(/ /g, "")
                .split("/")
                .some((position) => regex.test(position));
        }
        return regex.test(text);
    };
    const isFound = (childrenArr) => childrenArr.some(isFoundInTd);
    const setTrStyleDisplay = ({ style, children }) => {
        style.display = isFound([
            ...children, // <-- All columns
        ])
            ? ""
            : "none";
    };

    trs.forEach(setTrStyleDisplay);
};

const myFunction = () => {
    const trs = document.querySelectorAll("#myTable tr:not(.header)");
    const filter = document.querySelector("#myInput").value.trim(); // Added `.trim()`
    // Don't filter if the filter is blank (`/.*/` matches anything)
    const regex = !filter
        ? /.*/
        : new RegExp("^"   escapeRegex(filter)   "$", "i");
    // Made this singular since it only checks a single td
    // and make it look in just the text, not the HTML markup
    const isFoundInTd = (td) => {
        const text = td.textContent;
        if (td.classList.contains("position")) {
            return text
                .replace(/ /g, "")
                .split("/")
                .some((position) => regex.test(position));
        }
        return regex.test(text);
    };
    const isFound = (childrenArr) => childrenArr.some(isFoundInTd);
    const setTrStyleDisplay = ({ style, children }) => {
        style.display = isFound([
            ...children, // <-- All columns
        ])
            ? ""
            : "none";
    };

    trs.forEach(setTrStyleDisplay);
};

function escapeRegex(string) {
    return string.replace(/[-\/\\^$* ?.()|[\]{}]/g, "\\$&");
}
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Filter players by name, position, nationality or club...">

<table id="myTable">
<tbody>
<tr >
<th>Rec</th>
<th>Name</th>
<th>Position</th>
<th>Nat</th>
<th>Club</th>
</tr>
<tr>
<td>- - -</td>
<td>Eduardo Camavinga</td>
<td >DM / MC</td>
<td>France</td>
<td>R. Madrid</td>
</tr>
<tr>
<td>- - -</td>
<td>Ansu Fati</td>
<td >AMR / AML / ST</td>
<td>Spain</td>
<td>Barcelona</td>
</tr>
<tr>
<td>- - -</td>
<td>Jude Bellingham</td>
<td >MC</td>
<td>England</td>
<td>Borussia Dortmund</td>
</tr>
</tbody>
</table>

That way, "ansu" doesn't match "Ansu Fati" but "DM" matches "DM / MC".

  • Related