使用jquery / javascript基于单元格值对表行进行分组

时间:2015-08-12 10:35:04

标签: javascript jquery html css

我一直在努力解决这个问题。我非常感谢你能解决这个问题的任何帮助。我有一张如下表:

ID              Name            Study
1111            Angela          XRAY
2222            Bena            Ultrasound
3333            Luis            CT Scan
1111            Angela          Ultrasound
3333            Luis            XRAY
3333            Luis            LASER

我希望将它们分组为:

ID              Name            Study
GROUP BY id(1111) 2 hits  "+"
2222            Bena            Ultrasound
GROUP BY id(3333) 3 hits "+"

如果" +"单击然后它将展开:

 ID              Name            Study
GROUP BY id(1111) 2 hits  "-"
1111            Angela          XRAY  
1111            Angela          Ultrasound
2222            Bena            Ultrasound
GROUP BY id(3333) 3 hits  "-"
3333            Luis            CT Scan
3333            Luis            Ultrasound
3333            Luis            LASER

我在stackoverflow(http://jsfiddle.net/FNvsQ/1/)上找到了一个演示,但我唯一的问题是我想在动态标题下包含所有具有相同id的行,如

按ID(1111)分组,然后是展开/折叠图标(+/-)

var table = $('table')[0];
var rowGroups = {};
//loop through the rows excluding the first row (the header row)
while(table.rows.length > 0){
    var row = table.rows[0];
    var id = $(row.cells[0]).text();
    if(!rowGroups[id]) rowGroups[id] = [];
    if(rowGroups[id].length > 0){
        row.className = 'subrow';
        $(row).slideUp();
    }
    rowGroups[id].push(row);
    table.deleteRow(0);
}
//loop through the row groups to build the new table content
for(var id in rowGroups){
    var group = rowGroups[id];
    for(var j = 0; j < group.length; j++){
        var row = group[j];
        if(group.length > 1 && j == 0) {
            //add + button
            var lastCell = row.cells[row.cells.length - 1];           
            $("<span class='collapsed'>").appendTo(lastCell).click(plusClick);                                         
        }
        table.tBodies[0].appendChild(row);        
    }
}
//function handling button click
function plusClick(e){
    var collapsed = $(this).hasClass('collapsed');
    var fontSize = collapsed ? 14 : 0;
    $(this).closest('tr').nextUntil(':not(.subrow)').slideToggle(400)
           .css('font-size', fontSize);
    $(this).toggleClass('collapsed');        
}

2 个答案:

答案 0 :(得分:3)

以下是我自己的问题的答案。

首先将id添加到表和行中,然后对JS进行一些小改动:

&#13;
&#13;
var table = $('table')[0];
var rowGroups = {};

//loop through the rows excluding the first row (the header row)
while (table.rows.length > 1) {
  var row = table.rows[1];
  var id = $(row.cells[0]).text();

  if (!rowGroups[id]) rowGroups[id] = [];

  if (rowGroups[id].length > 0) {
    row.className = 'subrow';
    $(row).slideUp();
  }
  rowGroups[id].push(row);
  table.deleteRow(1);
}

//loop through the row groups to build the new table content
for (var id in rowGroups) {
  var group = rowGroups[id];

  for (var j = 0; j < group.length; j++) {
    var row = group[j];
    var notSubrow = false;

    if (group.length > 1 && j == 0) {
      //add + button
      var lastCell = row.cells[row.cells.length - 1];
      var rowId = row.id;
      var tableId = table.id;
      notSubrow = true;
      //$("<span class='collapsed'>").appendTo(lastCell).click(plusClick);                                         
    }
    table.tBodies[0].appendChild(row);

    if (notSubrow) {
      $('#' + tableId).find('#' + rowId).attr('class', 'subrow');
      $('#' + tableId).find('#' + rowId).before("<tr class='subrowHeader' style='background:#E6E6FA;border-bottom:1px solid #708AA0 !important'><td colspan='3'>&nbsp;group by&nbsp" + $(row.cells[0]).text() + "&nbsp;(" + group.length + ")" + "<span class='collapsed' onclick='plusClick(this)' style='float:left;display:inline'></td></tr>");
      $('#' + tableId).find('#' + rowId).hide();
    }
  }
}
//function handling button click
function plusClick(e) {
  var collapsed = $(e).hasClass('collapsed');
  var fontSize = collapsed ? 14 : 0;
  $(e).closest('tr').nextUntil(':not(.subrow)').slideToggle('fast').css('font-size', fontSize);
  $(e).toggleClass('collapsed');
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="table1">
  <tr id="tr1">
    <th>Parent ID</th>
    <th>Parent Name</th>
    <th>Study</th>
  </tr>
  <tr id="tr2">
    <td>1111</td>
    <td>Angela</td>
    <td>XRAY</td>
  </tr>
  <tr id="tr3">
    <td>2222</td>
    <td>Bena</td>
    <td>Untrasound</td>
  </tr>
  <tr id="tr4">
    <td>3333</td>
    <td>Luis</td>
    <td>CT Scan</td>
  </tr>
  <tr id="tr5">
    <td>1111</td>
    <td>Angela</td>
    <td>Untrasound</td>
  </tr>
  <tr id="tr6">
    <td>3333</td>
    <td>Luis</td>
    <td>LCD</td>
  </tr>
  <tr id="tr7">
    <td>3333</td>
    <td>Luis</td>
    <td>LASER</td>
  </tr>
</table>
&#13;
&#13;
&#13;

*为了测试将代码复制并粘贴到http://jsfiddle.net/FNvsQ/1/&amp; 在框架和&amp;扩展面板,将onLoad设置为No wrap-in body。

答案 1 :(得分:1)

作为比较,这里是一个POJS函数,在相同数量的代码中功能相同。但是不使用大型外部库。

它使用相同的算法收集第一个单元格中具有相同值的所有行,然后修改表格以插入标题行并对数据行进行分组。

// Group table rows by first cell value. Assume first row is header row
function groupByFirst(table) {

  // Add expand/collapse button
  function addButton(cell) {
    var button = cell.appendChild(document.createElement('button'));
    button.className = 'toggleButton';
    button.textContent = '+';
    button.addEventListener('click', toggleHidden, false);
    return button;
  }

  // Expand/collapse all rows below this one until next header reached
  function toggleHidden(evt) {
    var row = this.parentNode.parentNode.nextSibling;
    
    while (row && !row.classList.contains('groupHeader')) {
      row.classList.toggle('hiddenRow');
      row = row.nextSibling;
    }
  }
  
  // Use tBody to avoid Safari bug (appends rows to table outside tbody)
  var tbody = table.tBodies[0];

  // Get rows as an array, exclude first row
  var rows = Array.from(tbody.rows).slice(1);
  
  // Group rows in object using first cell value
  var groups = rows.reduce(function(groups, row) {
    var val = row.cells[0].textContent;
    
    if (!groups[val]) groups[val] = [];
    
    groups[val].push(row);
    return groups;
  }, Object.create(null));
  
  // Put rows in table with extra header row for each group
  Object.keys(groups).forEach(function(value, i) {

    // Add header row
    var row = tbody.insertRow();
    row.className = 'groupHeader';
    var cell = row.appendChild(document.createElement('td'));
    cell.colSpan = groups[value][0].cells.length;
    cell.appendChild(
      document.createTextNode(
        'Grouped by ' + table.rows[0].cells[0].textContent +
        ' (' + value + ') ' + groups[value].length + ' hits'
      )
    );
    var button = addButton(cell);

    // Put the group's rows in tbody after header
    groups[value].forEach(function(row){tbody.appendChild(row)});
    
    // Call listener to collapse group
    button.click();
  });
}

window.onload = function(){
  groupByFirst(document.getElementById('table1'));
}
table {
  border-collapse: collapse;
  border-left: 1px solid #bbbbbb;
  border-top: 1px solid #bbbbbb;
}
th, td {
  border-right: 1px solid #bbbbbb;
  border-bottom: 1px solid #bbbbbb;
}
.toggleButton {
  float: right;
}
.hiddenRow {
  display: none;
}
<table id="table1">
  <tr id="tr1">
    <th>Parent ID</th>
    <th>Parent Name</th>
    <th>Study</th>
  </tr>
  <tr id="tr2">
    <td>1111</td>
    <td>Angela</td>
    <td>XRAY</td>
  </tr>
  <tr id="tr3">
    <td>2222</td>
    <td>Bena</td>
    <td>Ultrasound</td>
  </tr>
  <tr id="tr4">
    <td>3333</td>
    <td>Luis</td>
    <td>CT Scan</td>
  </tr>
  <tr id="tr5">
    <td>1111</td>
    <td>Angela</td>
    <td>Ultrasound</td>
  </tr>
  <tr id="tr6">
    <td>3333</td>
    <td>Luis</td>
    <td>LCD</td>
  </tr>
  <tr id="tr7">
    <td>3333</td>
    <td>Luis</td>
    <td>LASER</td>
  </tr>
</table>