So führen Sie eine Echtzeitsuche und -filterung für eine HTML-Tabelle durch


139

Ich habe eine Weile gegoogelt und nach Stapelüberlauf gesucht, aber ich kann dieses Problem einfach nicht umgehen.

Ich habe eine Standard-HTML-Tabelle, die beispielsweise Obst enthält. Wie so:

<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>

Darüber habe ich ein Textfeld, in dem ich die Tabelle als Benutzertyp durchsuchen möchte. Wenn sie Grezum Beispiel tippen, verschwindet die orangefarbene Zeile der Tabelle und der Apfel und die Trauben bleiben zurück. Wenn sie Green Grweitermachen und tippen, sollte die Apple-Reihe verschwinden und nur noch Trauben übrig bleiben. Ich hoffe das ist klar.

Und sollte der Benutzer einige oder alle seiner Abfragen aus dem Textfeld löschen, möchte ich, dass alle Zeilen, die jetzt mit der Abfrage übereinstimmen, wieder angezeigt werden.

Obwohl ich weiß, wie eine Tabellenzeile in jQuery entfernt wird, habe ich keine Ahnung, wie ich die Suche durchführen und Zeilen basierend darauf selektiv entfernen soll. Gibt es eine einfache Lösung dafür? Oder ein Plugin?

Wenn mich jemand in die richtige Richtung weisen könnte, wäre es brillant.

Danke dir.


Antworten:


307

Ich habe diese Beispiele erstellt.

Einfacher Index der Suche

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();
});

Demo : http://jsfiddle.net/7BUmG/2/

Suche nach regulären Ausdrücken

Mit erweiterten Funktionen, die reguläre Ausdrücke verwenden, können Sie Wörter in beliebiger Reihenfolge in der Zeile suchen. Es funktioniert genauso, wenn Sie Folgendes eingeben apple greenoder 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/

Entprellen

Wenn Sie die Tabellenfilterung mit Suche über mehrere Zeilen und Spalten implementieren, ist es sehr wichtig, dass Sie die Leistung und die Suchgeschwindigkeit / -optimierung berücksichtigen. Es ist nicht erforderlich, einfach zu sagen, dass Sie die Suchfunktion nicht bei jedem einzelnen Tastendruck ausführen sollten. Um zu verhindern, dass die Filterung zu oft ausgeführt wird, sollten Sie sie entprellen. Das obige Codebeispiel wird zu:

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

Sie können eine beliebige Entprellungsimplementierung auswählen, beispielsweise aus Lodash _.debounce , oder Sie können etwas sehr Einfaches verwenden, wie ich es in den nächsten Demos verwende (Entprellen von hier ): http://jsfiddle.net/7BUmG/6230/ und http: / /jsfiddle.net/7BUmG/6231/ .


3
Ich bin ziemlich grün mit diesem Zeug, aber wenn ich es in meinen Tisch integrieren möchte, muss ich nur das #tablein das idmeines Tisches ändern ? Müsste es zusätzliche Änderungen geben, um mit <thead>und <tbody>Tags zu arbeiten? Ich habe das Skript und HTML aus dem jsfiddle-Link eingefügt und das geändert #id, aber ich bekomme keine Filterung.
JoshP

10
@JoshP Sctipt funktioniert mit allen Zeilen. Wenn Sie nur diejenigen innerhalb der filtern möchten, <tbody>sollten Sie zu wechseln var $rows = $('#id-of-your-table tbody tr');.
dfsq

2
@JoshP Nein, nichts als jQuery ist erforderlich. Stellen Sie einfach sicher, dass Sie Ihren Code in DOMReady oder nach dem Laden von HTML ausführen.
dfsq

2
Ich würde empfehlen, diesen Ansatz zu verbessern, da er sehr ressourcenintensiv ist. <tr>Fügen Sie alle verfeinerten Zeichenfolgen in ein Array von Objekten mit zwei Feldern ein: einen Verweis auf das DOMElement und die Zeichenfolge. Auf diese Weise keyup()durchsuchen Sie diese Zeichenfolgen (was viel schneller ist) und halten die entsprechenden Zeilen bereit, um bearbeitet zu werden. Dieser erste kostspielige Einrichtungsvorgang sollte dann nur einmal direkt nach dem Laden ausgeführt werden. Alle diese Änderungen sind nur geringfügige Korrekturen. Der eigentliche zentrale Teil bleibt weiterhin wie in dieser Antwort gezeigt. Dieser Ansatz ist auch ohne jQuery möglich und recht einfach zu implementieren.
Pid

2
@confusedMind $('#table tr:not(:first)')Selektor verwenden.
dfsq

10

Ich habe ein JQuery-Plugin dafür. Es verwendet auch jquery-ui. Ein Beispiel finden Sie hier 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
        });

7

Hier ist die beste Lösung für die Suche in einer HTML-Tabelle, während die gesamte Tabelle (alle td, tr in der Tabelle), reines Javascript und so kurz wie möglich abgedeckt werden:

<input id='myInput' onkeyup='searchTable()' type='text'>

<table id='myTable'>
   <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>

<script>
function searchTable() {
    var input, filter, found, table, tr, td, i, j;
    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");
        for (j = 0; j < td.length; j++) {
            if (td[j].innerHTML.toUpperCase().indexOf(filter) > -1) {
                found = true;
            }
        }
        if (found) {
            tr[i].style.display = "";
            found = false;
        } else {
            tr[i].style.display = "none";
        }
    }
}
</script>

3
Um die Tabellenkopfzeile vor dem Verschwinden zu schützen, fügen Sie der Zeile eine ID hinzu: <tr id = 'tableHeader'> und ändern Sie die letzte else-Anweisung in: if (tr [i] .id! = 'TableHeader') {tr [i ] .style.display = "none";} Es wird in der Frage nicht erwähnt, aber ich wollte, dass es das abdeckt, um es umfassend zu machen.
Tarik

Anstatt die ID mit! = Zu vergleichen, schlage ich vor, das letzte else in Folgendes zu ändern:} else if (! Tr [i] .id.match ('^ tableHeader')) {Dadurch kann man jeweils mehr als eine Tabelle haben mit ihrem eigenen Header. Weitere Arbeit ist erforderlich, um die searchTable-Funktion durch Übergabe der Tabellen-ID zu parametrisieren.
Tom Ekberg

3

Vielen Dank an @dfsq für den sehr hilfreichen Code!

Ich habe einige Anpassungen vorgenommen und vielleicht auch andere. Ich habe dafür gesorgt, dass Sie nach mehreren Wörtern suchen können, ohne eine strikte Übereinstimmung zu haben.

Beispielzeilen:

  • Äpfel und Birnen
  • Äpfel und Bananen
  • Äpfel und Orangen
  • ...

Sie könnten nach 'ap pe' suchen und es würde die erste Reihe erkennen.
Sie könnten nach 'banana apple' suchen und es würde die zweite Reihe erkennen

Demo: 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();
});

Solide Suche - ich musste es ändern leicht meine Tabelle der Kopf- und Fußzeilen verschwinden, durch den Wechsel zu verhindern: var $rows = $('#WorldPlayersTable tr'); zu - var $rows = $('#WorldPlayersTable tbody tr');
Drefetr

2

Ich fand die Antwort von dfsq in seinen Kommentaren äußerst nützlich. Ich habe einige geringfügige Änderungen an mir vorgenommen (und ich veröffentliche sie hier, falls sie für andere von Nutzen sind).

  1. Verwendung classals Hooks anstelle von Tabellenelemententr
  2. Suchen / Vergleichen von Text innerhalb eines Kindes classbeim Ein- / Ausblenden des Elternteils
  3. Machen Sie es effizienter, indem Sie die $rowsTextelemente nur einmal in einem Array speichern (und Zeitberechnungen vermeiden $rows.length).

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

Reine Javascript-Lösung:

Funktioniert für ALLE Spalten und ohne Berücksichtigung der Groß- und Kleinschreibung:

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";
        }
      } 
    }
  }
}

1

Sie können natives Javascript wie dieses verwenden

<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>



-1

Wenn Sie HTML und Daten trennen können, können Sie externe Bibliotheken wie Datentabellen oder die von mir erstellte verwenden. https://github.com/thehitechpanky/js-bootstrap-tables

Diese Bibliothek verwendet die Keyup-Funktion zum erneuten Laden von Tabellendaten und scheint daher wie eine Suche zu funktionieren.

function _addTableDataRows(paramObjectTDR) {
    let { filterNode, limitNode, bodyNode, countNode, paramObject } = paramObjectTDR;
    let { dataRows, functionArray } = paramObject;
    _clearNode(bodyNode);
    if (typeof dataRows === `string`) {
        bodyNode.insertAdjacentHTML(`beforeend`, dataRows);
    } else {
        let filterTerm;
        if (filterNode) {
            filterTerm = filterNode.value.toLowerCase();
        }
        let serialNumber = 0;
        let limitNumber = 0;
        let rowNode;
        dataRows.forEach(currentRow => {
            if (!filterNode || _filterData(filterTerm, currentRow)) {
                serialNumber++;
                if (!limitNode || limitNode.value === `all` || limitNode.value >= serialNumber) {
                    limitNumber++;
                    rowNode = _getNode(`tr`);
                    bodyNode.appendChild(rowNode);
                    _addData(rowNode, serialNumber, currentRow, `td`);
                }
            }
        });
        _clearNode(countNode);
        countNode.insertAdjacentText(`beforeend`, `Showing 1 to ${limitNumber} of ${serialNumber} entries`);
    }
    if (functionArray) {
        functionArray.forEach(currentObject => {
            let { className, eventName, functionName } = currentObject;
            _attachFunctionToClassNodes(className, eventName, functionName);
        });
    }
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.