web-dev-qa-db-fra.com

Comment effectuer une recherche et un filtre en temps réel sur un tableau HTML

Je fais des recherches sur Google et je cherche des informations sur Stack Overflow, mais je ne parviens pas à résoudre ce problème.

J'ai un tableau HTML standard, contenant, par exemple, des fruits. Ainsi:

<table>
   <tr>
      <td>Apple</td>
      <td>Green</td>
   </tr>
   <tr>
      <td>Grapes</td>
      <td>Green</td>
   </tr>
   <tr>
      <td>Orange</td>
      <td>Orange</td>
   </tr>
</table>

Au-dessus de cela, j'ai une zone de texte dans laquelle j'aimerais effectuer une recherche dans la table en tant qu'utilisateur. Ainsi, s'ils tapent Gre par exemple, la rangée orange de la table disparaîtrait, laissant Apple et Grapes. S'ils ont continué et ont tapé Green Gr, la rangée Apple devrait disparaître, ne laissant que des raisins. J'espère que cela est clair.

Et, si l'utilisateur supprime une partie ou la totalité de sa requête de la zone de texte, je souhaite que toutes les lignes qui correspondent maintenant à la requête réapparaissent.

Bien que je sache comment supprimer une ligne de tableau dans jQuery, je ne sais pas trop comment procéder pour effectuer la recherche et supprimer les lignes de manière sélective en fonction de cela. Y a-t-il une solution simple à cela? Ou un plugin?

Si quelqu'un pouvait me diriger dans la bonne direction, ce serait génial.

Je vous remercie.

121
samiles

J'ai créé ces exemples.

Simple indexOf search

var $rows = $('#table tr');
$('#search').keyup(function() {
    var val = $.trim($(this).val()).replace(/ +/g, ' ').toLowerCase();

    $rows.show().filter(function() {
        var text = $(this).text().replace(/\s+/g, ' ').toLowerCase();
        return !~text.indexOf(val);
    }).hide();
});

Démo: http://jsfiddle.net/7BUmG/2/

Recherche par expression régulière

Des fonctionnalités plus avancées utilisant des expressions régulières vous permettront de rechercher des mots dans n'importe quel ordre de la ligne. Cela fonctionnera de la même manière si vous tapez Apple green ou green Apple:

var $rows = $('#table tr');
$('#search').keyup(function() {

    var val = '^(?=.*\\b' + $.trim($(this).val()).split(/\s+/).join('\\b)(?=.*\\b') + ').*$',
        reg = RegExp(val, 'i'),
        text;

    $rows.show().filter(function() {
        text = $(this).text().replace(/\s+/g, ' ');
        return !reg.test(text);
    }).hide();
});

Demo: http://jsfiddle.net/dfsq/7BUmG/1133/

Debounce

Lorsque vous implémentez le filtrage de table avec une recherche sur plusieurs lignes et colonnes, il est très important que vous preniez en compte les performances et la vitesse/optimisation de la recherche. Dire simplement que vous ne devez pas lancer la fonction de recherche sur chaque frappe, ce n’est pas nécessaire. Pour éviter que le filtrage ne soit exécuté trop souvent, vous devez le supprimer. L'exemple de code ci-dessus deviendra:

$('#search').keyup(debounce(function() {
    var val = $.trim($(this).val()).replace(/ +/g, ' ').toLowerCase();
    // etc...
}, 300));

Vous pouvez choisir n'importe quelle implémentation de debounce, par exemple chez Lodash _.debounce , ou vous pouvez utiliser quelque chose de très simple, comme dans les démos suivants (debounce from here ): http: // jsfiddle net/7BUmG/6230/ et http://jsfiddle.net/7BUmG/6231/ .

282
dfsq

j'ai un plugin JQuery pour cela. Il utilise aussi jquery-ui. Vous pouvez voir un exemple ici http://jsfiddle.net/tugrulorhan/fd8KB/1/

$("#searchContainer").gridSearch({
            primaryAction: "search",
            scrollDuration: 0,
            searchBarAtBottom: false,
            customScrollHeight: -35,
            visible: {
                before: true,
                next: true,
                filter: true,
                unfilter: true
            },
            textVisible: {
                before: true,
                next: true,
                filter: true,
                unfilter: true
            },
            minCount: 2
        });
10
Yorgo

Merci @dfsq pour le code très utile!

J'ai fait quelques ajustements et peut-être que d'autres les aiment aussi. Je me suis assuré que vous pouvez rechercher plusieurs mots, sans correspondance stricte.

Exemple de lignes:

  • Pommes et poires
  • Pommes et bananes
  • Pommes et oranges
  • ...

Vous pouvez rechercher 'ap pe' et reconnaître la première ligne
Vous pouvez rechercher 'banana Apple' et reconnaître la deuxième ligne

Démo:http://jsfiddle.net/JeroenSormani/xhpkfwgd/1/

var $rows = $('#table tr');
$('#search').keyup(function() {
  var val = $.trim($(this).val()).replace(/ +/g, ' ').toLowerCase().split(' ');

  $rows.hide().filter(function() {
    var text = $(this).text().replace(/\s+/g, ' ').toLowerCase();
    var matchesSearch = true;
    $(val).each(function(index, value) {
      matchesSearch = (!matchesSearch) ? false : ~text.indexOf(value);
    });
    return matchesSearch;
  }).show();
});
3
Sormano

J'ai trouvé la réponse de dfsq très utile dans ses commentaires. J'ai apporté quelques modifications mineures applicables à moi (et je l'affiche ici, au cas où cela pourrait être utile à d'autres).

  1. Utilisation de class comme crochets au lieu d'éléments de table tr
  2. Rechercher/comparer du texte dans un enfant class lors de l'affichage/du masquage du parent
  3. Le rendre plus efficace en stockant les éléments de texte $rows dans un tableau une seule fois (et en évitant le calcul $rows.length fois)

var $rows = $('.wrapper');
var rowsTextArray = [];

var i = 0;
$.each($rows, function() {
  rowsTextArray[i] = $(this).find('.fruit').text().replace(/\s+/g, ' ').toLowerCase();
  i++;
});

$('#search').keyup(function() {
  var val = $.trim($(this).val()).replace(/ +/g, ' ').toLowerCase();
  $rows.show().filter(function(index) {
    return (rowsTextArray[index].indexOf(val) === -1);
  }).hide();
});
span {
  margin-right: 0.2em;
}
<input type="text" id="search" placeholder="type to search" />

<div class="wrapper"><span class="number">one</span><span class="fruit">Apple</span></div>
<div class="wrapper"><span class="number">two</span><span class="fruit">banana</span></div>
<div class="wrapper"><span class="number">three</span><span class="fruit">cherry</span></div>
<div class="wrapper"><span class="number">four</span><span class="fruit">date</span></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

2
Kaya Toast

vous pouvez utiliser un javascript natif comme celui-ci 

<script>
function myFunction() {
  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";
      }
    }       
  }
}
</script>

0
Omar Maher

Datatable JS plugin est également un bon substitut pour permettre la recherche de la table HTML

var table = $('#example').DataTable();

// #myInput is a <input type="text"> element
$('#myInput').on( 'keyup', function () {
    table.search( this.value ).draw();
} );

https://datatables.net/examples/basic_init/zero_configuration.html

0
Aditya

Solution Javascript pure:

Fonctionne pour TOUTES les colonnes et insensible à la casse:

function search_table(){
  // Declare variables 
  var input, filter, table, tr, td, i;
  input = document.getElementById("search_field_input");
  filter = input.value.toUpperCase();
  table = document.getElementById("table_id");
  tr = table.getElementsByTagName("tr");

  // Loop through all table rows, and hide those who don't match the search query
  for (i = 0; i < tr.length; i++) {
    td = tr[i].getElementsByTagName("td") ; 
    for(j=0 ; j<td.length ; j++)
    {
      let tdata = td[j] ;
      if (tdata) {
        if (tdata.innerHTML.toUpperCase().indexOf(filter) > -1) {
          tr[i].style.display = "";
          break ; 
        } else {
          tr[i].style.display = "none";
        }
      } 
    }
  }
}
0
Natesh bhat