Як здійснити пошук і фільтрування в режимі реального часу в таблиці HTML


139

Я деякий час займався Google і шукав переповнення стека, але просто не можу обійти цю проблему.

У мене стандартна таблиця HTML, що містить, скажімо, фрукти. Так:

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

Над цим у мене є текстове поле, в якому я хотів би шукати таблицю як тип користувача. Так, якщо вони вводять, Greнаприклад, помаранчевий рядок таблиці не буде зникати, залишаючи яблуко та виноград. Якщо вони продовжували і набирали, Green Grрядок Apple повинен не зникати, залишаючи лише виноград. Сподіваюся, це зрозуміло.

І якщо користувач видалить частину чи весь запит із текстового поля, мені слід, щоб усі рядки, які зараз відповідають запиту, знову з’явилися.

Хоча я знаю, як видалити рядок таблиці в jQuery, я мало розумію, як слід робити пошук та вибирати рядки вибірково на основі цього. Чи є просте рішення цього? Або плагін?

Якби хто міг би вказати мені в правильному напрямку, це було б геніально.

Дякую.


Відповіді:


307

Я створив ці приклади.

Простий IndexOf пошук

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

Демо : http://jsfiddle.net/7BUmG/2/

Регулярний пошук виразів

Більш вдосконалена функціональність за допомогою регулярних виразів дозволить шукати слова в будь-якому порядку в рядку. Він буде працювати так само, якщо ви введете apple greenабо 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();
});

Демонстрація : http://jsfiddle.net/dfsq/7BUmG/1133/

Дебанку

Коли ви реалізуєте фільтрацію таблиць за допомогою пошуку по декількох рядках і стовпцях, дуже важливо враховувати ефективність та швидкість / оптимізацію пошуку. Просто кажучи, що не слід запускати функцію пошуку на кожному натисканні клавіші, це не обов'язково. Щоб фільтра не запускалося занадто часто, слід його зняти. Наведеним вище прикладом коду стане:

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

Ви можете вибрати будь-яку реалізацію дебюнсу , наприклад, від Lodash _.debounce , або ви можете використовувати щось дуже просте, як я використовую в наступних демонстраціях (дебютування звідси ): http://jsfiddle.net/7BUmG/6230/ та http: / /jsfiddle.net/7BUmG/6231/ .


3
Я досить зелений з цими матеріалами, але якщо я хочу включити це до своєї таблиці, чи потрібно мені просто змінити значення #tableна idмою таблицю? Чи повинні бути додаткові зміни для роботи <thead>та <tbody>тегів? Я включив скрипт та html із посилання jsfiddle, змінивши #id, але я не отримую фільтрації.
JoshP

10
@JoshP Sctipt працює з усіма рядками. Якщо ви хочете відфільтрувати лише ті, хто знаходиться всередині <tbody>вас, слід змінити його var $rows = $('#id-of-your-table tbody tr');.
dfsq

2
@JoshP Ні, нічого, крім jQuery, не потрібно. Просто переконайтеся, що ви запускаєте код у DOMReady або після завантаження HTML.
dfsq

2
Я б рекомендував вдосконалити цей підхід, оскільки це досить витрачає ресурси. Покладіть всі вдосконалені рядки в масив об'єктів з двома полями: посилання на <tr>DOMElement і рядок. Таким чином, keyup()ви шукаєте ті рядки (що швидше) і готові відповідні рядки до маніпулювання. Перша дорога процедура установки повинна бути виконана відразу один раз після завантаження. Усі ці зміни є лише незначними виправленнями, фактична центральна частина все ще залишається такою, як показано у цій відповіді. Цей підхід також можливий і досить простий у впровадженні без jQuery.
під

2
@confusedMind Використовуйте $('#table tr:not(:first)')селектор.
dfsq

10

У мене є плагін jquery для цього. Він також використовує jquery-ui. Приклад ви можете побачити тут 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

Ось найкраще рішення для пошуку всередині таблиці HTML, охоплюючи всю таблицю , (весь td, tr в таблиці), чистий javascript і якомога коротший :

<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
Щоб захистити рядок заголовка таблиці від зникнення, додайте ідентифікатор до рядка на зразок: <tr id = 'tableHeader'> та змініть остаточне твердження на: if (tr [i] .id! = 'TableHeader') {tr [i ] .style.display = "none";} Про це не йдеться у запитанні, але я хотів, щоб він це висвітлив, щоб зробити його всебічним.
Тарік

Замість того, щоб порівнювати ідентифікатор, використовуючи! =, Я ​​пропоную змінити остаточне інше на це:} else if (! Tr [i] .id.match ('^ tableHeader')) {Це дозволяє мати більше однієї таблиці, кожна із власним заголовком. Потрібно більше роботи, щоб параметризувати функцію searchTable, передавши ідентифікатор таблиці.
Том Екберг

3

Дякую @dfsq за дуже корисний код!

Я вніс деякі корективи і, можливо, деякі інші теж їм подобаються. Я гарантував, що ви можете шукати кілька слів, не суворо збігаючись.

Приклад рядків:

  • Яблука та груші
  • Яблука та банани
  • Яблука та апельсини
  • ...

Ви можете шукати "ap pe", і він розпізнає перший рядок.
Ви можете шукати "бананове яблуко", і він розпізнає другий ряд

Демо: 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();
});

Суцільний пошук - мені довелося його трохи змінити, щоб запобігти зникненню заголовків та колонтитулів мого столу, змінивши: var $rows = $('#WorldPlayersTable tr'); на - var $rows = $('#WorldPlayersTable tbody tr');
Drefetr

2

Я вважав відповідь dfsq її коментарями надзвичайно корисною. Я зробив деякі незначні зміни, застосовні до мене (і я розміщую його тут, якщо це корисно для інших).

  1. Використовується classяк гачки, а не елементи таблиціtr
  2. Пошук / порівняння тексту у дитини classпід час показу / приховування батьків
  3. Зробити це більш ефективним, зберігаючи $rowsтекстові елементи в масив лише один раз (і уникаючи $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

Чисте рішення Javascript:

Працює для ВСІХ стовпців і регістру, що не сприймає:

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

ви можете використовувати нативний javascript таким

<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 та дані, ви можете використовувати зовнішні бібліотеки, такі як таблиці даних або створені я. https://github.com/thehitechpanky/js-bootstrap-tables

Ця бібліотека використовує функцію клавіатури, щоб перезавантажити табличні дані, а отже, схоже, вона працює як пошук.

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);
        });
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.