HTML 테이블에서 실시간 검색 및 필터링을 수행하는 방법


139

인터넷 검색을하고 잠시 동안 스택 오버플로를 검색했지만이 문제를 해결할 수는 없습니다.

과일을 포함하는 표준 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사과 줄을 계속 타자 하면 포도 만 남기고 사라져야한다. 이것이 분명하기를 바랍니다.

그리고 사용자가 텍스트 상자에서 쿼리의 일부 또는 전부를 삭제하면 쿼리와 일치하는 모든 행이 다시 나타나도록해야합니다.

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

debounce 구현을 Lodash _.debounce 에서 선택하거나 다음 데모에서 사용하는 것과 같은 매우 간단한 것을 사용할 수 있습니다 ( 여기 에서 debounce ) : http://jsfiddle.net/7BUmG/6230/http : / /jsfiddle.net/7BUmG/6231/ .


3
나는이 물건 꽤 녹색,하지만 난 내 테이블에이 통합하려는 경우, 그냥를 변경해야합니까 #table받는 id내 테이블? 와 작업에 대한 추가 변경이있을 필요가 <thead><tbody>태그? jsfiddle 링크에서 스크립트와 html을 포함 시켜서을 변경 #id했지만 필터링하지 않습니다.
JoshP

10
@JoshP Sctipt는 모든 행에서 작동합니다. 내부의 필터 만 필터링 <tbody>하려면로 변경해야합니다 var $rows = $('#id-of-your-table tbody tr');.
dfsq

2
@JoshP 아니요, jQuery 만 있으면됩니다. DOMReady에서 또는 HTML이로드 된 후에 코드를 실행하십시오.
dfsq 2016 년

2
이 방법은 리소스를 많이 소비하므로이 방법을 향상시키는 것이 좋습니다. 다듬어 진 모든 문자열을 <tr>DOMElement에 대한 참조 와 문자열 이라는 두 개의 필드가있는 객체 배열에 넣습니다 . 이 방법으로 keyup()문자열을 검색하고 (더 빠른) 해당 행을 조작 할 준비가되었습니다. 그 첫 번째 비용이 많이 드는 설정 절차는로드 직후에 한 번만 실행되어야합니다. 이러한 모든 변경 사항은 사소한 수정일 뿐이며 실제 중심 부분은 여전히이 답변에 표시된대로 유지됩니다. 이 방법도 가능하며 jQuery없이 구현하기가 매우 쉽습니다.
pid

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

다음은 모든 테이블 , ( 테이블의 모든 td, tr), 순수한 자바 스크립트 및 가능한 한 짧은 시간 을 다루면서 HTML 테이블 내부를 검색하는 가장 좋은 솔루션입니다 .

<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'>와 같이 행에 id를 추가하고 마지막 else 문을 다음과 같이 변경하십시오. if (tr [i] .id! = 'tableHeader') {tr [i ] .style.display = "none";} 질문에 언급되지 않았지만 포괄적으로 만들기 위해 다루고 싶었습니다.
Tarik

! =를 사용하여 id를 비교하는 대신 final을 다음과 같이 변경하는 것이 좋습니다.} else if (! tr [i] .id.match ( '^ tableHeader')) {이렇게하면 각각 하나 이상의 테이블을 가질 수 있습니다 자신의 헤더와 함께. 테이블 ID를 전달하여 searchTable 함수를 매개 변수화하려면 더 많은 작업이 필요합니다.
Tom Ekberg

3

매우 유용한 코드에 대해 @dfsq에게 감사합니다!

나는 약간의 조정을했고 어쩌면 다른 사람들도 좋아했습니다. 엄격한 일치없이 여러 단어를 검색 할 수 있습니다.

행 예 :

  • 사과 배
  • 사과와 바나나
  • 사과와 오렌지
  • ...

'ap pe'를 검색하면 첫 번째 행을 인식
할 수 있습니다. 'banana apple'을 검색하면 두 번째 행을 인식 할 수 있습니다.

데모 : 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

순수한 자바 스크립트 솔루션 :

작동 모든 열 및 대소 문자를 구별 :

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

이 같은 네이티브 자바 스크립트를 사용할 수 있습니다

<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과 데이터를 분리 할 수 ​​있으면 datatables 또는 내가 만든 것과 같은 외부 라이브러리를 사용할 수 있습니다. 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);
        });
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.