2014 年 10 月 2 日星期四

滑動子資料列

顯示與表格中特定記錄相關資訊的能力,可以大大簡化最終用戶的表格主要顯示,同時仍然允許在詳細視圖中訪問任意複雜的資料。為此,DataTables 內建支援顯示附加到表格中父資料列的子資料列,透過其 row().child() API 方法集。

有一個範例 顯示如何使用這些方法在子資料列中顯示資訊,但一個常見的要求是透過使用一點 jQuery 動畫滑動打開子資料列,為子資料列的顯示添加更多樣式。

這篇文章探討了我們如何輕鬆實現該效果,最終結果如下表所示。

名稱 職位 辦公室 薪資
名稱 職位 辦公室 薪資

起點

我們的起點將是標準 DataTables 子資料列範例。讓我們快速總結一下它是如何運作的,方法是考慮以下程式碼

$('#example tbody').on('click', 'td.details-control', function () {
    var tr = $(this).closest('tr');
    var row = table.row( tr );

    if ( row.child.isShown() ) {
        // This row is already open - close it
        row.child.hide();
        tr.removeClass('shown');
    }
    else {
        // Open this row
        row.child( format(row.data()) ).show();
        tr.addClass('shown');
    }
} );
  • 第 1 行:將 click 事件監聽器附加到表格中具有 details-control 類別的儲存格(使用 columns.className 初始化選項設定)。
  • 第 2 行:使用 jQuery 來取得此列的 tr 節點的參考。
  • 第 3 行:使用 tr 元素,我們使用 DataTables API 來取得該資料列的 API 物件,然後該物件可用於子資料列操作。
  • 第 5 行:使用 row().child.isShown() 檢查子資料列是否顯示。
  • 第 6-8 行:如果目前可見,則使用 row().child.hide() 隱藏它。
  • 第 11-13 行:如果不可見,則使用 row().child.show() 顯示它,並使用一個格式化函數來呈現來自該列的資料(使用 row().data())。

您會看到此處使用的 format() 方法只是演示可以做什麼,並且它可以根據您自己的需求傳回顯示所需的任何 HTML,無論它有多複雜。事實上,如果需要,它可以向伺服器發出 Ajax 呼叫以取得額外資訊。

添加動畫

要添加動畫,首先要考慮的是動畫表格資料列的高度可能相當複雜,因此我們將完全跳過它,方法是將要在子資料列中顯示的資料封閉在 div 元素中,該元素可以使用 jQuery 的 $().slideDown()$().slideUp() 方法輕鬆製作動畫。

在上面的範例中,format() 函數將傳回一個 HTML 字串,例如

<div class="slider">
    ... Data to be shown ...
</div>

在我們的 CSS 中,我們添加

div.slider {
    display: none;
}

這可確保元素在首次添加到文檔時會被隱藏,以便 jQuery 可以為其顯示製作動畫。

顯示

現在,我們只需要使用 $().slideDown() 來動畫元素,因此請修改子資料列的顯示方式,方法是新增一行程式碼,如下所示

// Open this row
row.child( format(row.data()) ).show();
tr.addClass('shown');

$('div.slider', row.child()).slideDown();

請注意使用 row().child() 來取得子資料列節點的參考,以便我們可以選擇要製作動畫的元素。

隱藏

在關閉時動畫子資料列的變更同樣簡單 - 我們使用 $().slideUp() 及其提供在動畫完成時執行的回呼的能力(在我們要使用 row().child.hide() 來完全移除子資料列,而不是在動畫之前或期間移除)。

// This row is already open - close it
$('div.slider', row.child()).slideUp( function () {
    row.child.hide();
    tr.removeClass('shown');
} );

更流暢的動畫

當使用預設的 DataTables 樣式表和許多其他樣式選項時,表格中的儲存格會有邊距。此邊距不是 jQuery 在 div 元素上執行的動畫的一部分,因此我們希望將其從子資料列中移除,而不是在顯示子資料列時立即出現。這可以使用附加到子資料列容器儲存格的類別名稱來完成,該類別名稱可以使用 row().child() 方法的可選第二個參數來分配

// Open this row
row.child( format(row.data()), 'no-padding' ).show();

新增一個額外的 CSS 規則

table.dataTable tbody td.no-padding {
    padding: 0;
}

這就是在 DataTales 中為子資料列新增滑動動畫的全部內容!

完整程式碼

此範例使用的完整程式碼如下所示。

Javascript

/* Formatting function for row details - modify as you need */
function format ( d ) {
    // `d` is the original data object for the row
    return '<div class="slider">'+
        '<table cellpadding="5" cellspacing="0" border="0" style="padding-left:50px;">'+
            '<tr>'+
                '<td>Full name:</td>'+
                '<td>'+d.name+'</td>'+
            '</tr>'+
            '<tr>'+
                '<td>Extension number:</td>'+
                '<td>'+d.extn+'</td>'+
            '</tr>'+
            '<tr>'+
                '<td>Extra info:</td>'+
                '<td>And any further details here (images etc)...</td>'+
            '</tr>'+
        '</table>'+
    '</div>';
}

$(document).ready(function() {
    var table = $('#example').DataTable( {
        "ajax": "/examples/ajax/data/objects.txt",
        "columns": [
            {
                "class":          'details-control',
                "orderable":      false,
                "data":           null,
                "defaultContent": ''
            },
            { "data": "name" },
            { "data": "position" },
            { "data": "office" },
            { "data": "salary" }
        ],
        "order": [[1, 'asc']]
    } );
    
    // Add event listener for opening and closing details
    $('#example tbody').on('click', 'td.details-control', function () {
        var tr = $(this).closest('tr');
        var row = table.row( tr );

        if ( row.child.isShown() ) {
            // This row is already open - close it
            $('div.slider', row.child()).slideUp( function () {
                row.child.hide();
                tr.removeClass('shown');
            } );
        }
        else {
            // Open this row
            row.child( format(row.data()), 'no-padding' ).show();
            tr.addClass('shown');

            $('div.slider', row.child()).slideDown();
        }
    } );
} );

CSS

td.details-control {
    background: url('/examples/resources/details_open.png') no-repeat center center;
    cursor: pointer;
}

tr.shown td.details-control {
    background: url('/examples/resources/details_close.png') no-repeat center center;
}

div.slider {
    display: none;
}

table.dataTable tbody td.no-padding {
    padding: 0;
}