วิธีค้นหาและกรองแบบเรียลไทม์บนตาราง HTML


139

ฉันใช้ Googling และค้นหา Stack Overflow มาระยะหนึ่งแล้ว แต่ฉันไม่สามารถแก้ไขปัญหานี้ได้

ฉันมีตาราง 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ตัวอย่างแถว Orange ของตารางจะหายไปจาก Apple และ Grapes หากพวกเขาดำเนินการและพิมพ์Green Grแถว Apple ควรหายไปทิ้งเพียงองุ่น ฉันหวังว่านี่ชัดเจน

และหากผู้ใช้ลบแบบสอบถามบางส่วนหรือทั้งหมดออกจากกล่องข้อความฉันควรให้แถวทั้งหมดที่ตรงกับแบบสอบถามนั้นปรากฏขึ้นอีกครั้ง

ในขณะที่ฉันรู้วิธีลบแถวของตารางใน jQuery ฉันมีความคิดเพียงเล็กน้อยเกี่ยวกับวิธีดำเนินการเกี่ยวกับการค้นหาและลบแถวที่เลือกโดยพิจารณาจากสิ่งนี้ มีวิธีแก้ปัญหาง่ายๆนี้หรือไม่? หรือปลั๊กอิน?

หากใครสามารถชี้ให้ฉันในทิศทางที่ถูกต้องมันจะยอดเยี่ยม

ขอบคุณ.


คำตอบ:


307

ฉันสร้างตัวอย่างเหล่านี้

ค้นหาแบบง่าย ๆ ของดัชนี

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/

debounce

เมื่อคุณใช้การกรองตารางด้วยการค้นหาหลายแถวและคอลัมน์เป็นสิ่งสำคัญมากที่คุณต้องพิจารณาประสิทธิภาพและความเร็วในการค้นหา / การปรับให้เหมาะสม เพียงแค่บอกว่าคุณไม่ควรเรียกใช้ฟังก์ชั่นการค้นหาในการกดแป้นทุกครั้งก็ไม่จำเป็น เพื่อป้องกันการกรองให้ทำงานบ่อยเกินไปคุณควรทำการดีบั๊ก ตัวอย่างโค้ดด้านบนจะกลายเป็น:

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

คุณสามารถเลือกการดำเนินการ debounce ใด ๆ ตัวอย่างเช่นจาก Lodash _.debounceหรือคุณสามารถใช้บางอย่างที่ง่ายเหมือนที่ฉันใช้ในการสาธิตครั้งต่อไป (debounce from here ): 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
pid

2
@confusedMind ใช้$('#table tr:not(:first)')ตัวเลือก
dfsq

10

ฉันมี jquery plugin สำหรับสิ่งนี้ มันใช้ 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 ในตาราง), จาวาสคริปต์แท้และสั้นที่สุด:

<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
หากต้องการป้องกันแถวส่วนหัวของตารางไม่ให้เพิ่ม id ลงในแถวเช่น: <tr id = 'tableHeader'> และเปลี่ยนคำสั่ง else เป็น: if (tr [i] .id! = 'tableHeader') {tr [i ] .style.display = "none";} มันไม่ได้กล่าวถึงในคำถาม แต่ฉันต้องการให้ครอบคลุมเพื่อให้ครอบคลุม
Tarik

แทนที่จะเปรียบเทียบ id โดยใช้! = ฉันขอแนะนำให้เปลี่ยนสุดท้ายเป็น:} อื่นถ้า (! tr [i] .id.match ('^ tableHeader')) {สิ่งนี้ยอมให้มีมากกว่าหนึ่งตารางแต่ละอัน ด้วยส่วนหัวของตัวเอง จำเป็นต้องมีการทำงานมากขึ้นในการกำหนดพารามิเตอร์ฟังก์ชัน 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();
});

การค้นหาที่มั่นคง - ฉันต้องแก้ไขเล็กน้อยเพื่อป้องกันไม่ให้ส่วนหัวและส่วนท้ายของ Table ของฉันหายไปโดยเปลี่ยน: var $rows = $('#WorldPlayersTable tr'); เป็น - var $rows = $('#WorldPlayersTable tbody tr');
Drefetr

2

ฉันพบว่าคำตอบของ dfsq มีประโยชน์อย่างมาก ฉันได้ทำการดัดแปลงเล็กน้อยกับฉัน (และฉันโพสต์ไว้ที่นี่ในกรณีที่มีประโยชน์กับผู้อื่น)

  1. การใช้ classเป็น hooks แทนที่จะเป็นองค์ประกอบตาราง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

คุณสามารถใช้จาวาสคริปต์แบบนี้ได้

<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

ปลั๊กอิน JS ที่สามารถบันทึกข้อมูลได้เป็นอีกคุณสมบัติหนึ่งที่ดีในการค้นหาคุณสมบัติสำหรับตาราง 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


-1

หากคุณสามารถแยก html และ data คุณสามารถใช้ไลบรารีภายนอกเช่น datatables หรือที่ฉันสร้างขึ้น https://github.com/thehitechpanky/js-bootstrap-tables

ห้องสมุดนี้ใช้ฟังก์ชั่นคีย์อัปโหลด tabledata และดูเหมือนว่าจะทำงานเหมือนค้นหา

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.