Javascript 使用JS对包含子项的HTML表进行排序

Javascript 使用JS对包含子项的HTML表进行排序,javascript,html,sorting,html-table,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="

我有下表:

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

圆柱
专栏B
柱状
柱状
专栏
根A
1.
2.
3.
4.
亚甲
5.
6.
7.
8.
次级B
9
10
11
12
根B
13
14
15
16
分C
17
18
19
20
副D
21
22
23
24
根C
25
26
27
28
次级E
29
30
31
32
我想对它进行排序,首先按“根”排序,然后按“子”项排序,这意味着根A总是有子A,子B在它下面(也排序,但在它下面)

我使用了下面的代码,它只对“子项”起作用,我无法通过“混合”使其起作用,即top和sub(单独排序)

函数可排序(列,此行){
var order=thisrow.getAttribute('order');
如果(!订单){
顺序=1;
}
var tbl=document.getElementById(“表1”).tBodies[0];
如果(!待定){
返回;
}
if(previousSortColumn&&previousSortColumn.innerHTML!=thisrow.innerHTML){
previousSortColumn.setAttribute('class','sort none');
}
previousSortColumn=此行;
var存储=[];
/*构建一个包含表中所有元素的store对象,我们将使用它进行排序*/
对于(变量rowpos=1,len=tbl.rows.length;rowpos 0){
xlevel=xlevel.substring(0,xlevel.lastIndexOf('-');
}
如果(ylevel.lastIndexOf('-')>0){
ylevel=ylevel.substring(0,ylevel.lastIndexOf('-');
}
如果(xlevel!=ylevel | | xtype=='root'| | ytype=='root')
{
返回x['storelength']-y['storelength'];//返回数组内的顺序
}
var result=x['sortnr'].localeCompare(y['sortnr']);
如果(顺序==1){
返回结果;
}否则{
返回-1*结果;
}
});
对于(变量i=0;i
更新1: 单击“ColumnB”一次不会影响表(我的例子有点不好),因为信息已经按正确的顺序排序,但是再次单击应该按相反的顺序排序

所以两个根都是相反的,根C,根B,根A,还有它们的子项,子项C之前的子项D

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

圆柱
专栏B
柱状
柱状
专栏
根C
25
26
27
28
次级E
29
30
31
32
根B
13
14
15
16
副D
21
22
23
24
分C
17
18
19
20
根A
1.
2.
3.
4.
次级B
9
10
11
12
亚甲
5.
6.
7.
8.

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

这是。HTML正是您提供的HTML,在列E上有错误和all and no listener。在根A上有更多的子项。您可以随意使用它(添加额外数据)。答案中代码的摘要在后面


更新-在注释中获取新的输入数据,我更新了JSFIDLE,似乎我保留了根,它跳出了子集。这是一个改变1行排序潜艇的问题

var-ASC=1;
var DESC=-1;
var-SORTNR_指数=0;
var下限=1;
var上限=2;
var-previousSortColumn;
var顺序;
/*您提供的原始构建存储*/
var buildStore=函数(列,待定){
var存储=[];
对于(var rowpos=1,len=tbl.rows.length;rowpos<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>
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;
}