简体   繁体   中英

Sorting Table with Hierarchical Data

I have an odd situation where I have an HTML table with hierarchical data and I need to provide the ability to sort the data, but only the "parent" rows, not the children. In fact, the children should stay attached to the parent, so wherever the parent gets sorted, the children should follow along (but they don't have to be sorted internally). For example:

在此处输入图片说明

When I click on "Rating", it should sort the bolded ratings and the children (the weeds in this example) should just go along for the ride. Is there a magical jquery plugin that will do this for me? :)

EDIT Here is a really stripped-down version of the rendered HTML. I have a certain amount of control over this, but not much (the markup comes from a remote endpoint...).

<table id="grid">
<thead>
    <tr role="row">
        <th>Name</th>
        <th>Rating</th>
        <th>Timing</th>
    </tr>
</thead>
<tbody>
    <tr>
        <td><b>Butyrac 200</b></td>
        <td><b>8</b></td>
        <td>POST</td>
        <td>3</td>
    </tr>
    <tr>
        <td>Common chickweed</td>
        <td>4</td>
        <td></td>
        <td></td>
    </tr>
    <tr>
        <td>Common dandelion</td>
        <td>4</td>
        <td></td>
        <td></td>
    </tr>
    <tr>
        <td><b>Chateau</b></td>
        <td><b>14</b></td>
        <td>PRE</td>
        <td>6</td>
    </tr>
    <tr>
        <td>Common chickweed</td>
        <td>10</td>
        <td></td>
        <td></td>
    </tr>
    <tr>
        <td>Common dandelion</td>
        <td>4</td>
        <td></td>
        <td></td>
    </tr>
</tbody>

If you have any say in the matter, ask to have a bit more structure/definition added to the markup so that you can rely on data rather than presentation to determine how these rows are related.

As is, it looks like you will need to rely on certain elements of the presentation being present. This can be fairly brittle as anyone coming along later and changing the presentation can break your logic very quickly.

Here I've made the assumption that only the top level rows have a <b> marker - you may need to adjust this depending on your exact requirements.

Working Fiddle

No magic here, just a bit of elbow grease:

var $tbody = $('#grid > tbody');
var topRows  = [];
var children = [];
$tbody.find('tr').each(function (idx, ele) {
    var $ele = $(ele);

    if ($ele.find('td:eq(0) > b').length) {
        // It's a parent

        // Make new parent
        var newParent = { ele: $ele, children: [] };
        topRows.push(newParent);

        // Keep track of the children
        children = newParent.children;
    } else {
        // It's a child
        children.push($ele);
    }
});

// Sort the top level array by the value of the rating td
topRows.sort(function(topA, topB) {
    var valA = +topA.ele.find('td:eq(1) > b').text();
    var valB = +topB.ele.find('td:eq(1) > b').text();

    return valA - valB;
});

// Detach it temporarily to avoid live DOM updates
$tbody.detach().empty();

// Add the newly sorted parents back in along with their children
$.each(topRows, function(topIdx, top) {
    $tbody.append(top.ele);
    $.each(top.children, function(childIdx, child) {
        $tbody.append(child);
    });
});

$('#grid').append($tbody);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM