Bir HTML tablosunda gerçek zamanlı arama ve filtre nasıl yapılır


139

Bir süredir Googling ve Stack Overflow'u aradım, ancak bu sorunu çözemiyorum.

Meyve içeren standart bir HTML tablom var. Şöyle ki:

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

Bunun üstünde, tabloyu kullanıcı türleri olarak aramak istediğim bir metin kutusu var. Onlar yazarsanız Yani, Greörneğin, tablonun Portakal satır Apple ve Grapes bırakarak kaybolanları olacaktır. Eğer devam ettiler ve Green Gryazdılarsa Apple satırı sadece üzüm bırakarak hayal kırıklığına uğratmalı. Umarım açık olmuştur.

Ve kullanıcı, sorgu kutusunun bir kısmını veya tamamını metin kutusundan silerse, şimdi sorguyla eşleşen tüm satırların yeniden görünmesini istemeliyim.

JQuery'de bir tablo satırını nasıl kaldıracağımı bilsem de, arama yapmaya ve satırları buna bağlı olarak seçici bir şekilde kaldırmaya nasıl gideceğimi bilmiyorum. Bunun basit bir çözümü var mı? Veya bir eklenti?

Biri beni doğru yöne yönlendirebilseydi parlak olurdu.

Teşekkür ederim.


Yanıtlar:


307

Bu örnekleri yarattım.

Basit indexOf arama

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/

Düzenli ifade arama

Normal ifadeler kullanan daha gelişmiş işlevsellik, kelimeleri satırdaki herhangi bir sırada aramanıza olanak tanır. apple greenVeya yazarsanız aynı şekilde çalışır 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/

Geri çevrilme

Birden çok satır ve sütun üzerinde arama ile tablo filtrelemesi uyguladığınızda, performans ve arama hızı / optimizasyonunu dikkate almanız çok önemlidir. Basitçe, her tuş vuruşunda arama işlevini çalıştırmamanız gerektiğini söylemek gerekli değildir. Filtrelemenin çok sık çalışmasını önlemek için filtreyi kaldırmanız gerekir. Yukarıdaki kod örneği:

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

Sen Lodash örneğin, herhangi bir filtreleme uygulaması alabilirsiniz _.debounce veya I (dan debounce sonraki demolar kullanmak gibi çok basit bir şey kullanabilirsiniz burada ): http://jsfiddle.net/7BUmG/6230/ ve http: / /jsfiddle.net/7BUmG/6231/ .


3
Bu malzeme ile oldukça yeşil değilim, ama benim tabloya bu dahil etmek istiyorsanız, sadece değiştirmek gerekiyor #tableiçin idbenim tablonun? İle çalışmak için ek değişiklikler olacaksa gerekir <thead>ve <tbody>etiketleri? Ben değiştirerek, jsfiddle link komut dosyası ve html dahil ettik #id, ama hiçbir filtreleme olsun.
JoshP

10
@JoshP Sctipt tüm satırlarla çalışır. Yalnızca içindekileri filtrelemek <tbody>istiyorsanız, olarak değiştirmelisiniz var $rows = $('#id-of-your-table tbody tr');.
dfsq

2
@JoshP Hayır, jQuery'den başka bir şey gerekmez. Kodunuzu DOMReady'de veya HTML yüklendikten sonra çalıştırdığınızdan emin olun.
dfsq

2
Bu yaklaşımı geliştirmenizi tavsiye ederim çünkü oldukça kaynak tüketiyor. Tüm rafine dizeleri iki alana sahip bir nesne dizisine koyun: <tr>DOMElement ve dizeye başvuru . Bu şekilde, keyup()bu dizeleri (çok daha hızlı) ararsınız ve karşılık gelen satırların değiştirilmeye hazır olmasını sağlarsınız. Bu ilk maliyetli kurulum prosedürü, yükleme işleminden hemen sonra gerçekleştirilmelidir. Tüm bu değişiklikler sadece küçük düzeltmelerdir, gerçek orta kısım bu cevapta gösterildiği gibi kalır. Bu yaklaşım da mümkündür ve jQuery olmadan uygulanması oldukça kolaydır.
pid

2
@confusedMind Seçiciyi kullan $('#table tr:not(:first)').
dfsq

10

Bunun için bir jquery eklentisi var. Ayrıca jquery-ui kullanır. Burada bir örnek görebilirsiniz 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
        });

8

Tüm tabloyu ( tablodaki tüm td, tr), saf javascript'i ve olabildiğince kısa sürerken HTML tablosunda arama yapmak için en iyi çözüm :

<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
Tablo başlığı satırının kaybolmasını önlemek için, satıra şu kimliği ekleyin: <tr id = 'tableHeader'> ve diğer son ifadeyi şu şekilde değiştirin: if (tr [i] .id! = 'TableHeader') {tr [i ] .style.display = "none";} Bu soruda bahsedilmiyor ama bunu kapsamlı hale getirmek için bunu kapsamasını istedim.
Tarık

Kimliğini! = Kullanarak karşılaştırmak yerine, sonuncuyu şu şekilde değiştirmenizi öneririm:} else if (! Tr [i] .id.match ('^ tableHeader')) {Bu, her birinin birden fazla tabloya sahip olmasını sağlar kendi başlıkları ile. Tablo kimliğini ileterek searchTable işlevini parametrelendirmek için daha fazla çalışmaya ihtiyaç vardır.
Tom Ekberg

3

@Dfsq çok yardımcı kod için teşekkür ederiz!

Bazı ayarlamalar yaptım ve belki bazıları da onlardan hoşlanıyor. Sıkı bir eşleşme olmadan birden fazla kelime arayabilmenizi sağladım.

Örnek satırlar:

  • Elma ve Armut
  • Elma ve Muz
  • Elmalar ve Portakallar
  • ...

'Ap pe' için arama yapabilir ve ilk satırı tanıyabilir.
'Banana apple' için arama yapabilir ve ikinci satırı tanıyabilir

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

: - Katı arama ben değiştirerek, kaybolan benim Masa'nın başlıklarını & altbilgiler önlemek için hafifçe değiştirmek zorunda var $rows = $('#WorldPlayersTable tr'); için - var $rows = $('#WorldPlayersTable tbody tr');
Drefetr

2

Dfsq'in cevabına yaptığı yorumları çok faydalı buldum. Benim için bazı küçük değişiklikler yaptım (ve başkalarına faydalı olması durumunda burada yayınlıyorum).

  1. classTablo öğeleri yerine kanca olarak kullanmatr
  2. classEbeveyni gösterirken / gizlerken çocuk içindeki metni arama / karşılaştırma
  3. $rowsMetin öğelerini bir dizide yalnızca bir kez depolayarak (ve $rows.lengthzaman hesaplamasından kaçınarak ) daha verimli hale getirme

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

Saf Javascript Çözümü:

İçin çalışır TÜM sütunlar ve büyük harf duyarsız:

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

bunun gibi yerel javascript kullanabilirsiniz

<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

Html ve verileri ayırabiliyorsanız, datatables veya oluşturduğum gibi harici kütüphaneleri kullanabilirsiniz. https://github.com/thehitechpanky/js-bootstrap-tables

Bu kütüphane, tablo verilerini yeniden yüklemek için keyup işlevini kullanır ve bu nedenle arama gibi çalışır.

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);
        });
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.