diff --git a/.datatables-commit-sync b/.datatables-commit-sync index a3e344d8..1e99f71e 100644 --- a/.datatables-commit-sync +++ b/.datatables-commit-sync @@ -1 +1 @@ -848be40591690163c03003346ee3748aec1b0006 +19a4f46a4f58fd7d24197f3ab6b550a4fd29dcae diff --git a/examples/server_side/row_details.html b/examples/server_side/row_details.html index 5862febe..9a2b0957 100644 --- a/examples/server_side/row_details.html +++ b/examples/server_side/row_details.html @@ -36,7 +36,7 @@ $(document).ready(function() { var dt = $('#example').DataTable( { "processing": true, "serverSide": true, - "ajax": "scripts/objects.php", + "ajax": "scripts/ids-objects.php", "columns": [ { "class": "details-control", @@ -52,19 +52,38 @@ $(document).ready(function() { "order": [[1, 'asc']] } ); - $('#example tbody').on('click', 'tr td:first-child', function () { + // Array to track the ids of the details displayed rows + var detailRows = []; + + $('#example tbody').on( 'click', 'tr td:first-child', function () { var tr = $(this).parents('tr'); var row = dt.row( tr ); + var idx = $.inArray( tr.attr('id'), detailRows ); if ( row.child.isShown() ) { tr.removeClass( 'details' ); row.child.hide(); + + // Remove from the 'open' array + detailRows.splice( idx, 1 ); } else { tr.addClass( 'details' ); row.child( format( row.data() ) ).show(); + + // Add to the 'open' array + if ( idx === -1 ) { + detailRows.push( tr.attr('id') ); + } } } ); + + // On each draw, loop over the `detailRows` array and show any child rows + dt.on( 'draw', function () { + $.each( detailRows, function ( i, id ) { + $('#'+id+' td:first-child').trigger( 'click' ); + } ); + } ); } ); @@ -97,6 +116,12 @@ $(document).ready(function() { information to show. Note that the format details function has access to the full data source object for the row, including information that is not actually shown in the table (the salary parameter for example).

+ +

Furthermore, this example shows a small difference from the client-side row details example in that to have rows automatically reopen + when the table is redrawn, we need to track a unique identifier for each row - in this case the row + id. This is required because in server-side processing mode rows are automatically + destroyed and recreated on each draw.

@@ -142,7 +167,7 @@ $(document).ready(function() { var dt = $('#example').DataTable( { "processing": true, "serverSide": true, - "ajax": "scripts/objects.php", + "ajax": "scripts/ids-objects.php", "columns": [ { "class": "details-control", @@ -158,19 +183,38 @@ $(document).ready(function() { "order": [[1, 'asc']] } ); - $('#example tbody').on('click', 'tr td:first-child', function () { + // Array to track the ids of the details displayed rows + var detailRows = []; + + $('#example tbody').on( 'click', 'tr td:first-child', function () { var tr = $(this).parents('tr'); var row = dt.row( tr ); + var idx = $.inArray( tr.attr('id'), detailRows ); if ( row.child.isShown() ) { tr.removeClass( 'details' ); row.child.hide(); + + // Remove from the 'open' array + detailRows.splice( idx, 1 ); } else { tr.addClass( 'details' ); row.child( format( row.data() ) ).show(); + + // Add to the 'open' array + if ( idx === -1 ) { + detailRows.push( tr.attr('id') ); + } } } ); + + // On each draw, loop over the `detailRows` array and show any child rows + dt.on( 'draw', function () { + $.each( detailRows, function ( i, id ) { + $('#'+id+' td:first-child').trigger( 'click' ); + } ); + } ); } );

In addition to the above code, the following Javascript library files are loaded for use in this diff --git a/examples/server_side/scripts/ids-arrays.php b/examples/server_side/scripts/ids-arrays.php index 093a8f13..68091e31 100644 --- a/examples/server_side/scripts/ids-arrays.php +++ b/examples/server_side/scripts/ids-arrays.php @@ -29,7 +29,16 @@ $primaryKey = 'id'; // parameter represents the DataTables column identifier. In this case simple // indexes + the primary key column for the id $columns = array( - array( 'db' => 'id', 'dt' => 'DT_RowId' ), + array( + 'db' => 'id', + 'dt' => 'DT_RowId', + 'formatter' => function( $d, $row ) { + // Technically a DOM id cannot start with an integer, so we prefix + // a string. This can also be useful if you have multiple tables + // to ensure that the id is unique with a different prefix + return 'row_'.$d; + } + ), array( 'db' => 'first_name', 'dt' => 0 ), array( 'db' => 'last_name', 'dt' => 1 ), array( 'db' => 'position', 'dt' => 2 ), diff --git a/examples/server_side/scripts/ids-objects.php b/examples/server_side/scripts/ids-objects.php index a8820dc0..feccbf87 100644 --- a/examples/server_side/scripts/ids-objects.php +++ b/examples/server_side/scripts/ids-objects.php @@ -29,7 +29,16 @@ $primaryKey = 'id'; // parameter represents the DataTables column identifier - in this case object // parameter names $columns = array( - array( 'db' => 'id', 'dt' => 'DT_RowId' ), + array( + 'db' => 'id', + 'dt' => 'DT_RowId', + 'formatter' => function( $d, $row ) { + // Technically a DOM id cannot start with an integer, so we prefix + // a string. This can also be useful if you have multiple tables + // to ensure that the id is unique with a different prefix + return 'row_'.$d; + } + ), array( 'db' => 'first_name', 'dt' => 'first_name' ), array( 'db' => 'last_name', 'dt' => 'last_name' ), array( 'db' => 'position', 'dt' => 'position' ), diff --git a/media/js/jquery.dataTables.js b/media/js/jquery.dataTables.js index 3698b435..079bcae0 100644 --- a/media/js/jquery.dataTables.js +++ b/media/js/jquery.dataTables.js @@ -6596,6 +6596,16 @@ }, + eq: function ( idx ) + { + var ctx = this.context; + + return ctx.length > idx ? + new _Api( ctx[idx], this[idx] ) : + null; + }, + + filter: function ( fn ) { var a = []; @@ -7413,11 +7423,19 @@ order = opts.order, // applied, current, index (original - compatibility with 1.9) page = opts.page; // all, current - // Current page implies that order=current and fitler=applied, since it is - // fairly senseless otherwise, regardless of what order and search actually - // are - if ( page == 'current' ) - { + if ( _fnDataSource( settings ) == 'ssp' ) { + // In server-side processing mode, most options are irrelevant since + // rows not shown don't exist and the index order is the applied order + // Removed is a special case - for consistency just return an empty + // array + return search === 'removed' ? + [] : + _range( 0, displayMaster.length ); + } + else if ( page == 'current' ) { + // Current page implies that order=current and fitler=applied, since it is + // fairly senseless otherwise, regardless of what order and search actually + // are for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i 0 ) { // On each draw, insert the required elements into the document - table.on('draw'+namespace, function () { - table.find('tbody tr').each( function () { - // Look up the row index for each row and append open row - var rowIdx = _fnNodeToDataIndex( settings, this ); - var row = settings.aoData[ rowIdx ]; + api.on( drawEvent, function () { + api.rows( {page:'current'} ).eq(0).each( function (idx) { + // Internal data grab + var row = settings.aoData[ idx ]; if ( row._detailsShow ) { - row._details.insertAfter( this ); + row._details.insertAfter( row.nTr ); } } ); } ); // Column visibility change - update the colspan - table.on( 'column-visibility'+namespace, function ( e, settings, idx, vis ) { + api.on( colvisEvent, function ( e, settings, idx, vis ) { // Update the colspan for the details rows (note, only if it already has // a colspan) var row, visible = _fnVisbleColumns( settings );