javascript - 使用 JS 对带有子项的 HTML 表格进行排序

标签 javascript html sorting html-table

我有下表:

<table border="0" cellspacing="0" cellpadding="0" id="table1">
    <tbody>
        <tr>
            <th onclick="sortTable(0, this); return false;" class="sort-up" order="-1">ColumnA</th>
            <th style="width: 12em;" onclick="sortTable(1, this); return false;" class="sort-none">ColumnB</th>
            <th style="width: 9em;" onclick="sortTable(2, this); return false;" class="sort-none">ColumnC</th>
            <th style="width: 10em;" onclick="sortTable(3, this); return false;" class="sort-none">ColumnD</th>
            <th style="width: 6em;">ColumnE</th>
        </tr>
        <tr id="tr217E9B6C" type="root" level="217E9B6C" depth="0">
            <td class="evenListRow" id="nocenter">
                <div class="tier1">Root A</div>
            </td>
            <td class="evenListRow">1</td>
            <td class="evenListRow">2</td>
            <td class="evenListRow">3</td>
            <td class="evenListRow">4</a>
            </td>
        </tr>
        <tr id="tr217E9B6C-6E781501" type="sub" level="217E9B6C-6E781501" depth="1">
            <td class="oddListRow" id="nocenter">
                <div class="tier2">Sub A</div>
            </td>
            <td class="oddListRow">5</td>
            <td class="oddListRow">6</td>
            <td class="oddListRow">7</td>
            <td class="oddListRow">8</td>
        </tr>
        <tr id="tr217E9B6C-852AB6E5" type="sub" level="217E9B6C-852AB6E5" depth="1">
            <td class="evenListRow" id="nocenter">
                <div class="tier2">Sub B</div>
            </td>
            <td class="evenListRow">9</td>
            <td class="evenListRow">10</td>
            <td class="evenListRow">11</td>
            <td class="evenListRow">12</td>
        </tr>
        <tr id="tr2BE7EAFE" type="root" level="2BE7EAFE" depth="0">
            <td class="evenListRow" id="nocenter">
                <div class="tier1">Root B</div>
            </td>
            <td class="evenListRow">13</td>
            <td class="evenListRow">14</td>
            <td class="evenListRow">15</td>
            <td class="evenListRow">16</td>
        </tr>
        <tr id="tr2BE7EAFE-49A04568" type="sub" level="2BE7EAFE-49A04568" depth="1">
            <td class="oddListRow" id="nocenter">
                <div class="tier2">Sub C</div>
            </td>
            <td class="oddListRow">17</td>
            <td class="oddListRow">18</td>
            <td class="oddListRow">19</td>
            <td class="oddListRow">20</td>
        </tr>
        <tr id="tr2BE7EAFE-DAE218A5" type="sub" level="2BE7EAFE-DAE218A5" depth="1">
            <td class="evenListRow" id="nocenter">
                <div class="tier2">Sub D</div>
            </td>
            <td class="evenListRow">21</td>
            <td class="evenListRow">22</td>
            <td class="evenListRow">23</td>
            <td class="evenListRow">24</td>
        </tr>
        <tr id="tr4FFACE4A" type="root" level="4FFACE4A" depth="0">
            <td class="oddListRow" id="nocenter">
                <div class="tier1">Root C</div>
            </td>
            <td class="oddListRow">25</td>
            <td class="oddListRow">26</td>
            <td class="oddListRow">27</td>
            <td class="oddListRow">28</td>
        </tr>
        <tr id="tr4FFACE4A-B9A443CA" type="sub" level="4FFACE4A-B9A443CA" depth="1">
            <td class="evenListRow" id="nocenter">
                <div class="tier2">Sub E</div>
            </td>
            <td class="evenListRow">29</td>
            <td class="evenListRow">30</td>
            <td class="evenListRow">31</td>
            <td class="evenListRow">32</td>
        </tr>
    </tbody>
</table>

我想对它进行排序,首先按“根”,然后按“子”项,这意味着根 A 将始终在其下方有其子 A、子 B(也已排序,但在其下方)

我使用了以下仅适用于“子项目”的代码,我无法通过“混合”使其工作,即顶部和子(单独排序)

function sortTable(column, thisrow) {
 var order = thisrow.getAttribute('order');
 if (!order) {
  order = 1;
 }

 var tbl = document.getElementById("table1").tBodies[0];
 if (!tbl) {
  return;
 }

 if (previousSortColumn && previousSortColumn.innerHTML != thisrow.innerHTML) {
  previousSortColumn.setAttribute('class', 'sort-none');
 }
 previousSortColumn = thisrow;

 var store = [];
 /* Build a store object that has every element in the table, we will use this to sort */
 for(var rowpos=1, len=tbl.rows.length; rowpos<len; rowpos++) { // skip row #1 as it is the header
  var row = tbl.rows[rowpos];

  var i_textContent = row.cells[column].textContent;

  while(i_textContent.indexOf(' ') != -1) { // remove spaces
   i_textContent = i_textContent.replace(' ', '');
  }

  var sortnr = i_textContent;
  var type = row.getAttribute('type');
  var level = row.getAttribute('level');
  var depth = row.getAttribute('depth');

  store.push({sortnr: sortnr, row:row, storelength:store.length, type:type, level:level, depth:depth});
 }

 /* We sort first roots then the elements under it */
 store.sort(function(x,y) {
  var xtype = x['type'];
  var ytype = y['type'];

  var result;

  if (xtype == 'root' && ytype == 'root')
  {
   result = x['sortnr'].localeCompare(y['sortnr']);
  } else {
   return 0;
  }

  if (order == 1) {
   return result;
  } else {
   return -1 * result;
  }
 });

 /* We sort the elements under it */
 store.sort(function(x,y) {
  var xtype = x['type'];
  var ytype = y['type'];

  var xlevel = x['level'];
  var ylevel = y['level'];

  if (xlevel.lastIndexOf('-') > 0) {
   xlevel = xlevel.substring(0, xlevel.lastIndexOf('-'));
  }

  if (ylevel.lastIndexOf('-') > 0) {
   ylevel = ylevel.substring(0, ylevel.lastIndexOf('-'));
  }

  if (xlevel != ylevel || xtype == 'root' || ytype == 'root')
  {
   return x['storelength'] - y['storelength']; // return order inside array
  }

  var result = x['sortnr'].localeCompare(y['sortnr']);

  if (order == 1) {
   return result;
  } else {
   return -1 * result;
  }
 });

 for(var i=0; i < store.length; i++) {
  tbl.appendChild(store[i]['row']);
 }
 store = null;
}

更新 1: 在“ColumnB”上单击一次不会影响表格(对我来说这是一个不好的例子),因为信息已经按照正确的顺序排序,但是再次单击应该以相反的顺序对所有内容进行排序

所以两个 Roots 都是相反的,Root C,Root B,Root A,以及它们的子项,Sub D 在 Sub C 之前,...

<table border="0" cellspacing="0" cellpadding="0" id="table1">
    <tbody>
        <tr>
            <th onclick="sortTable(0, this); return false;" class="sort-up" order="-1">ColumnA</th>
            <th style="width: 12em;" onclick="sortTable(1, this); return false;" class="sort-none">ColumnB</th>
            <th style="width: 9em;" onclick="sortTable(2, this); return false;" class="sort-none">ColumnC</th>
            <th style="width: 10em;" onclick="sortTable(3, this); return false;" class="sort-none">ColumnD</th>
            <th style="width: 6em;">ColumnE</th>
        </tr>
        <tr id="tr4FFACE4A" type="root" level="4FFACE4A" depth="0">
            <td class="oddListRow" id="nocenter">
                <div class="tier1">Root C</div>
            </td>
            <td class="oddListRow">25</td>
            <td class="oddListRow">26</td>
            <td class="oddListRow">27</td>
            <td class="oddListRow">28</td>
        </tr>
        <tr id="tr4FFACE4A-B9A443CA" type="sub" level="4FFACE4A-B9A443CA" depth="1">
            <td class="evenListRow" id="nocenter">
                <div class="tier2">Sub E</div>
            </td>
            <td class="evenListRow">29</td>
            <td class="evenListRow">30</td>
            <td class="evenListRow">31</td>
            <td class="evenListRow">32</td>
        </tr>
        <tr id="tr2BE7EAFE" type="root" level="2BE7EAFE" depth="0">
            <td class="evenListRow" id="nocenter">
                <div class="tier1">Root B</div>
            </td>
            <td class="evenListRow">13</td>
            <td class="evenListRow">14</td>
            <td class="evenListRow">15</td>
            <td class="evenListRow">16</td>
        </tr>
        <tr id="tr2BE7EAFE-DAE218A5" type="sub" level="2BE7EAFE-DAE218A5" depth="1">
            <td class="evenListRow" id="nocenter">
                <div class="tier2">Sub D</div>
            </td>
            <td class="evenListRow">21</td>
            <td class="evenListRow">22</td>
            <td class="evenListRow">23</td>
            <td class="evenListRow">24</td>
        </tr>
        <tr id="tr2BE7EAFE-49A04568" type="sub" level="2BE7EAFE-49A04568" depth="1">
            <td class="oddListRow" id="nocenter">
                <div class="tier2">Sub C</div>
            </td>
            <td class="oddListRow">17</td>
            <td class="oddListRow">18</td>
            <td class="oddListRow">19</td>
            <td class="oddListRow">20</td>
        </tr>
        <tr id="tr217E9B6C" type="root" level="217E9B6C" depth="0">
            <td class="evenListRow" id="nocenter">
                <div class="tier1">Root A</div>
            </td>
            <td class="evenListRow">1</td>
            <td class="evenListRow">2</td>
            <td class="evenListRow">3</td>
            <td class="evenListRow">4</a>
            </td>
        </tr>
        <tr id="tr217E9B6C-852AB6E5" type="sub" level="217E9B6C-852AB6E5" depth="1">
            <td class="evenListRow" id="nocenter">
                <div class="tier2">Sub B</div>
            </td>
            <td class="evenListRow">9</td>
            <td class="evenListRow">10</td>
            <td class="evenListRow">11</td>
            <td class="evenListRow">12</td>
        </tr>
        <tr id="tr217E9B6C-6E781501" type="sub" level="217E9B6C-6E781501" depth="1">
            <td class="oddListRow" id="nocenter">
                <div class="tier2">Sub A</div>
            </td>
            <td class="oddListRow">5</td>
            <td class="oddListRow">6</td>
            <td class="oddListRow">7</td>
            <td class="oddListRow">8</td>
        </tr>
    </tbody>
</table>

最佳答案

我解决了你的问题。我确实重新组织了代码以使其更具可读性。大部分逻辑是您提供的,我只是添加了一些小部分。顺便说一句,您在 html 中对 id="nocenter"有重复的 id 引用。

这里是 a working jsfiddle of my solution . HTML 正是您提供的那个,有错误,并且在 E 列上没有监听器。This js fiddle version在根 A 上有更多的潜艇。你可以随心所欲地玩它(添加额外的数据)。代码摘要在答案中紧随其后。


更新 - 在评论中获取您的新输入数据,我更新了 jsfiddle 似乎我保留了根,并且它跳出了子集。这是在对潜艇进行排序时更改 1 行的问题。 The new fiddle .

var ASC = 1;
var DESC = -1;
var SORTNR_INDEX = 0;
var LOWER = 1;
var UPPER = 2;
var previousSortColumn ;
var order;

/* The original build store you provided */
var buildStore = function(column,tbl){
    var store = [];
    for (var rowpos = 1, len = tbl.rows.length; rowpos < len; rowpos++) { // skip row #1 as it is the header
        var row = tbl.rows[rowpos];
        var i_textContent = row.cells[column].textContent;
        while (i_textContent.indexOf(' ') != -1) { // remove spaces
            i_textContent = i_textContent.replace(' ', '');
        }
        var sortnr = i_textContent;
        var type = row.getAttribute('type');
        var level = row.getAttribute('level');
        var depth = row.getAttribute('depth');
        store.push({sortnr: sortnr, row: row, storelength: store.length, type: type, level: level, depth: depth});
    }
    return store;
}
// the order convention you offered
var triggerOrder = function(){
    if (order==ASC){
        order = DESC;
    } else if (order==DESC || !order){
        order = ASC;
    }
}

// the code you provided
var getLevel = function(obj){
    if (obj && obj.lastIndexOf('-') > 0) {
        return obj.substring(0, obj.lastIndexOf('-'));
    }
    return obj;
}

function sortRoot(a,b){
    var aSort = a[SORTNR_INDEX], bSort = b[SORTNR_INDEX];
    return compareWithOrder(aSort,bSort);
};
var sortSubs = function(x,y){
    var xtype = x['type'];
    var ytype = y['type'];
    if (xtype == 'root'){
        return -1;
    } else if (xtype == ytype) {
        var xSort = x['sortnr'];
        var ySort = y['sortnr'];
        return compareWithOrder(xSort,ySort);
    }
}
var compareWithOrder = function(x,y){
    if (isNaN(parseInt(x))) {
        return order * x.localeCompare(y);
    } else {
        x = parseInt(x);
        y = parseInt(y);
        if (x < y) {
            return -1 * order;
        } else if (x > y) {
            return 1 * order;
        } else {
            return 0;
        }
    }
};
//assumes they are aligned by depth (i.e. will always have a root then subs). if not, an additional sort can be made beforehand
function getGroupsByLevel(store){
    var group = [];
    var groupIndex=0;
    var lower =0, upper, sortNo;
    if (store.length > 0) {
        var x,y;
        for (var i = 0; i < store.length; i++) {
            x = store[i];
            if (store[i+1]){
                y = store[i+1]
            } else{
                y = {};
            }
            var xtype = x['type'];
            var ytype = y['type'];
            if (xtype=='root'){
                sortNo = x['sortnr'];
            }
            var xlevel = getLevel(x['level']);
            var ylevel = getLevel(y['level']);
            if (xlevel != ylevel){
                group[groupIndex] = [sortNo,lower,i];
                lower=i+1;
                groupIndex++;
            }
        }
    }
    return group;
};
function sortTable(column, thisrow) {
    order = thisrow.getAttribute('order');
    triggerOrder();
    thisrow.setAttribute('order',order);

    var tbl = document.getElementById("table1").tBodies[0];
    if (!tbl) return;

    /* Build a store object that has every element in the table, we will use this to sort */
    var store = buildStore(column,tbl);

    var groups = getGroupsByLevel(store);
    groups.sort(sortRoot);
    var newStore=[];
    for (var i=0;i<groups.length;i++){
        var group = groups[i];
        var rootAndSubs = store.slice(group[LOWER],group[UPPER]+1);
        rootAndSubs.sort(sortSubs);
        newStore=newStore.concat(rootAndSubs);
    }
    //update table
    for (var i = 0; i < newStore.length; i++) {
        tbl.appendChild(newStore[i]['row']);
    }
    store = null;
    order = null;
}

基本上是这样的:

  • 设置+触发订单
  • 按照您的预期 build 商店
  • 获取根及其子组
  • 对组进行排序,然后对组中的每个子项进行排序
  • 更新 View

这是我想到的第一个方法。

关于javascript - 使用 JS 对带有子项的 HTML 表格进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32198024/

相关文章:

javascript - 删除导航和横幅之间的空白

javascript - 我无法使用 jquery 隐藏点击事件上的 div

javascript - 使用 jQuery 遍历 XML 获取元素值

javascript - 在选择标签而不是文本中显示值

JavaScript 性能 : Call vs Apply

sorting - 根据值的出现次数对 slice 进行排序

java - 根据整数值对对象进行排序

html - Jquery mobile 在网站中使用时会影响旧的设计和类

javascript - 如何跨域使用window.postMessage?

c - 使用有限的操作尽快对大数字列表(100k)进行排序